【问题标题】:Replace specific values in a matrix using Python使用 Python 替换矩阵中的特定值
【发布时间】:2014-11-29 15:08:33
【问题描述】:

我有一个 m x n 矩阵,其中每一行是一个样本,每一列是一个类。每行包含每个类的 soft-max 概率。我想用 1 替换每行中的最大值,用 0 替换其他行中的最大值。如何在 Python 中有效地做到这一点?

【问题讨论】:

    标签: python numpy machine-learning classification sparse-matrix


    【解决方案1】:

    这种使用基本 numpy 和列表​​推导的方法有效,但性能最低。我把这个答案留在这里,因为它可能有点指导意义。首先我们创建一个 numpy 矩阵:

    matrix = np.matrix(np.random.randn(2,2))
    

    matrix 是,例如:

    matrix([[-0.84558168,  0.08836042],
            [-0.01963479,  0.35331933]])
    

    如果元素为最大值,则将 1 映射到新矩阵,否则为 0:

    newmatrix = np.matrix([[1 if i == row.max() else 0 for i in row] 
                                                       for row in np.array(matrix)])
    

    newmatrix 现在是:

    matrix([[0, 1],
            [0, 1]])
    

    【讨论】:

    • @Matrix 我试图想出一个更好的方法。 Jaime 目前已经击败了我,但我正在寻找一种性能更好的替代方案,如果/当我解决它时,我会透露。
    【解决方案2】:

    一些虚构的数据:

    >>> a = np.random.rand(5, 5)
    >>> a
    array([[ 0.06922196,  0.66444783,  0.2582146 ,  0.03886282,  0.75403153],
           [ 0.74530361,  0.36357237,  0.3689877 ,  0.71927017,  0.55944165],
           [ 0.84674582,  0.2834574 ,  0.11472191,  0.29572721,  0.03846353],
           [ 0.10322931,  0.90932896,  0.03913152,  0.50660894,  0.45083403],
           [ 0.55196367,  0.92418942,  0.38171512,  0.01016748,  0.04845774]])
    

    一行:

    >>> (a == a.max(axis=1)[:, None]).astype(int)
    array([[0, 0, 0, 0, 1],
           [1, 0, 0, 0, 0],
           [1, 0, 0, 0, 0],
           [0, 1, 0, 0, 0],
           [0, 1, 0, 0, 0]])
    

    一种更有效(也更详细)的方法:

    >>> b = np.zeros_like(a, dtype=int)
    >>> b[np.arange(a.shape[0]), np.argmax(a, axis=1)] = 1
    >>> b
    array([[0, 0, 0, 0, 1],
           [1, 0, 0, 0, 0],
           [1, 0, 0, 0, 0],
           [0, 1, 0, 0, 0],
           [0, 1, 0, 0, 0]])
    

    【讨论】:

    • 很好的答案!谢谢:)
    • 好答案,加一。
    【解决方案3】:

    我认为您的特定问题的最佳答案是使用矩阵类型对象。

    考虑到大多数矩阵都填充了零,就以内存友好的方式存储大量这些大尺寸矩阵而言,稀疏矩阵应该是性能最高的。这应该优于直接使用 numpy 数组,尤其是对于两个维度上的非常大的矩阵,如果不是就计算速度而言,就内存而言。

    import numpy as np
    import scipy       #older versions may require `import scipy.sparse`
    
    matrix = np.matrix(np.random.randn(10, 5))
    maxes = matrix.argmax(axis=1).A1           
                          # was .A[:,0], slightly faster, but .A1 seems more readable
    n_rows = len(matrix)  # could do matrix.shape[0], but that's slower
    data = np.ones(n_rows)
    row = np.arange(n_rows)
    sparse_matrix = scipy.sparse.coo_matrix((data, (row, maxes)), 
                                            shape=matrix.shape, 
                                            dtype=np.int8)
    

    相对于常规矩阵对象,这个 sparse_matrix 对象应该是非常轻量级的,因为它会不必要地跟踪其中的每个零。将其具体化为普通矩阵:

    sparse_matrix.todense()
    

    返回:

    matrix([[0, 0, 0, 0, 1],
            [0, 0, 1, 0, 0],
            [0, 0, 1, 0, 0],
            [0, 0, 0, 0, 1],
            [1, 0, 0, 0, 0],
            [0, 0, 1, 0, 0],
            [0, 0, 0, 1, 0],
            [0, 1, 0, 0, 0],
            [1, 0, 0, 0, 0],
            [0, 0, 0, 1, 0]], dtype=int8)
    

    我们可以和matrix比较:

    matrix([[ 1.41049496,  0.24737968, -0.70849012,  0.24794031,  1.9231408 ],
            [-0.08323096, -0.32134873,  2.14154425, -1.30430663,  0.64934781],
            [ 0.56249379,  0.07851507,  0.63024234, -0.38683508, -1.75887624],
            [-0.41063182,  0.15657594,  0.11175805,  0.37646245,  1.58261556],
            [ 1.10421356, -0.26151637,  0.64442885, -1.23544526, -0.91119517],
            [ 0.51384883,  1.5901419 ,  1.92496778, -1.23541699,  1.00231508],
            [-2.42759787, -0.23592018, -0.33534536,  0.17577329, -1.14793293],
            [-0.06051458,  1.24004714,  1.23588228, -0.11727146, -0.02627196],
            [ 1.66071534, -0.07734444,  1.40305686, -1.02098911, -1.10752638],
            [ 0.12466003, -1.60874191,  1.81127175,  2.26257234, -1.26008476]])
    

    【讨论】:

    • 在内存使用方面真的很棒!非常感谢:-)
    • @Matrix 感谢这个好问题,我真的从回答中得到了很多。坚持下去。
    【解决方案4】:
    Y = np.random.rand(10,10)
    X=np.zeros ((5,5))
    y_insert=2
    x_insert=3
    offset = (1,2)
    for index_x, row in enumerate(X):
      for index_y, e in enumerate(row):
        Y[index_x + offset[0]][index_y + offset[1]] = e
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-28
      • 1970-01-01
      • 2022-09-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多