首页 > 解决方案 > 如何构建一个numpy矩阵(从头开始,以前不存在)在for循环中添加计算列

问题描述

这是学校的一项任务(矩阵每一列的并行归一化),除了您可能会看到的其他问题之外,我发现很难找到像 list = [] 这样简单的东西,您可以在其中 list.append() 整个列表一个循环,没有预定义尺寸。这是我到目前为止所讨论的最后一行的内容。预先感谢您的任何帮助!

from multiprocessing import Pool
import numpy as np

def fct_norm(col):
    mn = col.min()
    mx = col.max()
    col_norm = np.zeros((6, 1))
    for i in range(6):
        col_norm[i, 0] = (col[i] - mn) / (mx - mn)
    return col_norm

if __name__ == "__main__":
    pool = Pool()
    arr = np.random.uniform(0, 100, size=(6, 3))
maybe predefine arr_norm here?
    for i in range(2):
        print("i = ", i)
        col = arr[:, i]
        result = pool.map(fct_norm, [col])
        norm_arr = HOW_TO_ADD_EACH_RESULT_COLUMN_TO_A_NEW_ARRAY?

标签: pythonnumpymultiprocessing

解决方案


您需要连接多个列的函数是np.hstack. 但是,一个很大的问题是 pool.map在原始代码中没有以正确的方式使用。

正如所写,列没有并行执行,因为每次调用pool.map都只获得一个列。这个想法是同时传递一个带有多个值的迭代器——在这种情况下,多个列到pool.map.

由于numpy循环遍历行而不是列,因此必须转置矩阵(使用(...).T运算符。此外,在pool完成后,关闭它是一个很好的措施。自动处理此问题的一种方法是使用上下文(即with Pool() as pool:构造,然后它将自动关闭。

这一切加在一起给出了以下解决方案:

from multiprocessing import Pool
import numpy as np


def fct_norm(col):
    mn = col.min()
    mx = col.max()
    col_norm = np.zeros((6, 1))
    for i in range(6):
        col_norm[i, 0] = (col[i] - mn) / (mx - mn)
    return col_norm


if __name__ == "__main__":
    arr = np.random.uniform(0, 100, size=(6, 3))

    with Pool() as pool:
        norm_arr = np.hstack(pool.map(fct_norm, arr.T))

    # Here norm_arr is available for further operations.

因此,整个操作可以在两行中执行。


推荐阅读