Нормализация sparse.csc_matrix по диагонали
У меня есть scipy.sparse.csc_matrix с dtype = np.int32. Я хочу эффективно разделить каждый столбец (или строку, в зависимости от того, что быстрее для csc_matrix) матрицы на диагональный элемент в этом столбце. Итак, mnew[:,i] = m[:,i]/m[i,i] . Обратите внимание, что мне нужно преобразовать мою матрицу в np.double (так как mnew элементов будет в [0,1]), и так как матрица массивна и очень редка, мне интересно, смогу ли я сделать это как-нибудь эффективно / нет для цикла / никогда идти плотным путем.
Лучший,
Илья
1 ответ
Сделайте разреженную матрицу:
In [379]: M = sparse.random(5,5,.2, format='csr')
In [380]: M
Out[380]:
<5x5 sparse matrix of type '<class 'numpy.float64'>'
with 5 stored elements in Compressed Sparse Row format>
In [381]: M.diagonal()
Out[381]: array([ 0., 0., 0., 0., 0.])
слишком много нулей в диагонали - давайте добавим ненулевую диагональ:
In [382]: D=sparse.dia_matrix((np.random.rand(5),0),shape=(5,5))
In [383]: D
Out[383]:
<5x5 sparse matrix of type '<class 'numpy.float64'>'
with 5 stored elements (1 diagonals) in DIAgonal format>
In [384]: M1 = M+D
In [385]: M1
Out[385]:
<5x5 sparse matrix of type '<class 'numpy.float64'>'
with 10 stored elements in Compressed Sparse Row format>
In [387]: M1.A
Out[387]:
array([[ 0.35786668, 0.81754484, 0. , 0. , 0. ],
[ 0. , 0.41928992, 0. , 0.01371273, 0. ],
[ 0. , 0. , 0.4685924 , 0. , 0.35724102],
[ 0. , 0. , 0.77591294, 0.95008721, 0.16917791],
[ 0. , 0. , 0. , 0. , 0.16659141]])
Теперь тривиально разделить каждый столбец по диагонали (это матрица "продукт")
In [388]: M1/M1.diagonal()
Out[388]:
matrix([[ 1. , 1.94983185, 0. , 0. , 0. ],
[ 0. , 1. , 0. , 0.01443313, 0. ],
[ 0. , 0. , 1. , 0. , 2.1444144 ],
[ 0. , 0. , 1.65583764, 1. , 1.01552603],
[ 0. , 0. , 0. , 0. , 1. ]])
Или разделить строки - (умножить на вектор столбца)
In [391]: M1/M1.diagonal()[:,None]
ой, они плотные; давайте сделаем диагональ разреженной
In [408]: md = sparse.csr_matrix(1/M1.diagonal()) # do the inverse here
In [409]: md
Out[409]:
<1x5 sparse matrix of type '<class 'numpy.float64'>'
with 5 stored elements in Compressed Sparse Row format>
In [410]: M.multiply(md)
Out[410]:
<5x5 sparse matrix of type '<class 'numpy.float64'>'
with 5 stored elements in Compressed Sparse Row format>
In [411]: M.multiply(md).A
Out[411]:
array([[ 0. , 1.94983185, 0. , 0. , 0. ],
[ 0. , 0. , 0. , 0.01443313, 0. ],
[ 0. , 0. , 0. , 0. , 2.1444144 ],
[ 0. , 0. , 1.65583764, 0. , 1.01552603],
[ 0. , 0. , 0. , 0. , 0. ]])
md.multiply(M)
для версии столбца.
Деление разреженной матрицы - аналогично, за исключением того, что вместо диагонали используется сумма строк. Немного больше касается потенциальной проблемы "деление на ноль".