Matrix 在Julia中,如何对稀疏矩阵进行列规格化?

Matrix 在Julia中,如何对稀疏矩阵进行列规格化?,matrix,normalization,sparse-matrix,julia,Matrix,Normalization,Sparse Matrix,Julia,如果我已经使用稀疏(I,j,k)构造函数构造了一个稀疏矩阵,那么如何规范化矩阵的列(使每列总和为1)?在创建矩阵之前,我无法有效地规范化条目,因此非常感谢您的帮助。谢谢 最简单的方法是将广播除以各列之和: julia> A = sprand(4,5,.5) A./sum(A,1) 4x5 Array{Float64,2}: 0.0 0.0989976 0.0 0.0 0.0795486 0.420754 0.458653

如果我已经使用稀疏(I,j,k)构造函数构造了一个稀疏矩阵,那么如何规范化矩阵的列(使每列总和为1)?在创建矩阵之前,我无法有效地规范化条目,因此非常感谢您的帮助。谢谢

最简单的方法是将广播除以各列之和:

julia> A = sprand(4,5,.5)
       A./sum(A,1)
4x5 Array{Float64,2}:
 0.0        0.0989976  0.0        0.0       0.0795486
 0.420754   0.458653   0.0986313  0.0       0.0
 0.0785525  0.442349   0.0        0.856136  0.920451
 0.500693   0.0        0.901369   0.143864  0.0
…但它看起来还没有针对稀疏矩阵进行优化,并返回到完整矩阵。因此,通过一个简单的循环在列上进行迭代可以实现以下目的:

julia> for (col,s) in enumerate(sum(A,1))
         s == 0 && continue # What does a "normalized" column with a sum of zero look like?
         A[:,col] = A[:,col]/s
       end
       A
4x5 sparse matrix with 12 Float64 entries:
    [2, 1]  =  0.420754
    [3, 1]  =  0.0785525
    [4, 1]  =  0.500693
    [1, 2]  =  0.0989976
    [2, 2]  =  0.458653
    [3, 2]  =  0.442349
    [2, 3]  =  0.0986313
    [4, 3]  =  0.901369
    [3, 4]  =  0.856136
    [4, 4]  =  0.143864
    [1, 5]  =  0.0795486
    [3, 5]  =  0.920451

julia> sum(A,1)
1x5 Array{Float64,2}:
 1.0  1.0  1.0  1.0  1.0
这完全在稀疏矩阵中工作,并在适当的位置完成(尽管它仍在为每个列切片分配新的稀疏矩阵)。

给定一个矩阵a(不管它是否稀疏),通过任何维度进行规格化

 A ./ sum(A,1) or  A ./ sum(A,2)
为了证明它是有效的:

A = sprand(10,10,0.3)   
println(sum(A,1))
println(A ./ sum(A,1))
唯一的警告

A[1,:] = 0
println(A ./ sum(A,1))
如您所见,列1现在只包含NaN,因为我们除以零。最后我们得到的是一个矩阵,而不是稀疏矩阵

另一方面,你可以很快为你的问题找到一个有效的专门解决方案

function normalize_columns(A :: SparseMatrixCSC)
          sums = sum(A,1)
          I,J,V = findnz(A)
          for idx in 1:length(V)
            V[idx] /= sums[J[idx]]
          end
          sparse(I,J,V)
end

@马特B在我打字的时候给出了一个非常相似的答案:)

记住朱莉娅的稀疏矩阵是压缩列形式。因此,您可以直接访问数据:

for col = 1 : size(A, 2)
  i = A.colptr[col]
  k = A.colptr[col+1] - 1
  n = i <= k ? norm(A.nzval[i:k]) : 0.0  # or whatever you like
  n > 0.0 && (A.nzval[i:k] ./= n)
end
列=1的
:大小(A,2)
i=A.colptr[col]
k=A.colptr[col+1]-1
n=i 0.0&(A.nzval[i:k]./=n)
结束

以下是您想要的: A=南坡(4,5,0.5) B=A/稀疏(和(A,1))

问题是sum(A,1)给出了一个1x5的密集数组,因此通过./operator与稀疏矩阵A结合得到了密集数组。所以你需要强制它是稀疏类型。或者你可以打字
稀疏(A./sum(A,1))。

为了将来的参考,在你的答案后面给出一些解释是一件好事。在这种情况下,我不明白ei、ej、ev是用来做什么的——它们应该是bi.bj.bv吗?
# get the column sums of A
S = vec(sum(A,1))

# get the nonzero entries in A. ei is row index, ej is col index, ev is the value in A
ei,ej,ev = findnz(A)

# get the number or rows and columns in A
m,n = size(A)

# create a new normalized matrix. For each nonzero index (ei,ej), its new value will be
# the old value divided by the sum of that column, which can be obtained by S[ej]
A_normalized = sparse(ei,ej,ev./S[ej],m,n)