Преобразование плотного матричного кода в разреженный матричный код - PullRequest
0 голосов
/ 30 мая 2018

Я пытаюсь преобразовать этот код, чтобы использовать скудные разреженные матрицы, поскольку реальная матрица очень большая, но у меня проблемы с ней.Пожалуйста, кто-нибудь может помочь?

import numpy as np
G = np.array([[0., 50., 50., 0.],
              [10., 0., 10., 0.],
              [0., 0., 0., 10.],
              [2., 0., 2., 0.]])
s = G.sum(axis=0)
m = np.minimum(G, 1).transpose()
sm = s * m
sm_rnorm = (sm / sm.sum(axis=0))
smm = sm * sm_rnorm
G += smm.transpose()
print(G)

Я попробовал следующее:

import numpy as np
from scipy.sparse import csc_matrix
G = np.array([[0.,50.,50.,0.],
              [10.,0.,10.,0.],
              [0.,0.,0.,10.],
              [2.,0.,2.,0.]])
G = csc_matrix(G, dtype=np.float)
s = csc_matrix(G.sum(axis=0))
m = csc_matrix.minimum(G, 1).transpose()
sm = s * m
sm_rnorm = (sm / csc_matrix(sm.sum(axis=0)))
smm = sm * sm_rnorm
G += smm.transpose()
print(G)

... но получите ValueError: dimension mismatch

1 Ответ

0 голосов
/ 30 мая 2018

Я запустил ваш плотный код,

In [224]: G = np.array([[0., 50., 50., 0.],
     ...:               [10., 0., 10., 0.],
     ...:               [0., 0., 0., 10.],
     ...:               [2., 0., 2., 0.]])
     ...: s = G.sum(axis=0)
     ...: m = np.minimum(G, 1).transpose()
     ...: sm = s * m
     ...: sm_rnorm = (sm / sm.sum(axis=0))
     ...: smm = sm * sm_rnorm
     ...:               
In [225]: s
Out[225]: array([12., 50., 62., 10.])
In [226]: m
Out[226]: 
array([[0., 1., 0., 1.],
       [1., 0., 0., 0.],
       [1., 1., 0., 1.],
       [0., 0., 1., 0.]])
In [227]: sm
Out[227]: 
array([[ 0., 50.,  0., 10.],
       [12.,  0.,  0.,  0.],
       [12., 50.,  0., 10.],
       [ 0.,  0., 62.,  0.]])

, а затем запустил разреженную версию:

In [192]: from scipy import sparse
In [228]: Gm = sparse.csr_matrix(G)
In [229]: Gm
Out[229]: 
<4x4 sparse matrix of type '<class 'numpy.float64'>'
    with 7 stored elements in Compressed Sparse Row format>
In [230]: s_m = Gm.sum(axis=0)
In [231]: s_m
Out[231]: matrix([[12., 50., 62., 10.]])
In [233]: m_m = Gm.minimum(1).T
In [234]: m_m.A
Out[234]: 
array([[0., 1., 0., 1.],
       [1., 0., 0., 0.],
       [1., 1., 0., 1.],
       [0., 0., 1., 0.]])

Упс:

In [236]: s_m * m_m
Out[236]: matrix([[112.,  74.,  10.,  74.]])

* если матрицаумножение для np.matrix и разреженной матрицы

In [237]: s.dot(m)
Out[237]: array([112.,  74.,  10.,  74.])

умножение элементов с разреженной матрицей:

In [242]: sm_m = m_m.multiply(s_m)
In [243]: sm_m.A
Out[243]: 
array([[ 0., 50.,  0., 10.],
       [12.,  0.,  0.,  0.],
       [12., 50.,  0., 10.],
       [ 0.,  0., 62.,  0.]])

теперь для соответствия sm_rnorm:

In [244]: sm_m.sum(axis=0)
Out[244]: matrix([[ 24., 100.,  62.,  20.]])
In [250]: sm_m / sm_m.sum(axis=0)
Out[250]: 
matrix([[0. , 0.5, 0. , 0.5],
        [0.5, 0. , 0. , 0. ],
        [0.5, 0.5, 0. , 0.5],
        [0. , 0. , 1. , 0. ]])

sparse/dense работает поэлементно, но у sparse/sparse есть проблемы:

In [252]: sm_m / sparse.csr_matrix(sm_m.sum(axis=0))
----> 1 sm_m / sparse.csr_matrix(sm_m.sum(axis=0))
--> 576         return self._divide(other, true_divide=True)
    568             if true_divide and np.can_cast(self.dtype, np.float_):
ValueError: inconsistent shapes

Я думаю, что это проблема деления матрицы, но я бы покопался дальше, чтобы быть уверенным.

sm_m.multiply(1 / sm_m.sum(axis=0)) даетразреженная матрица с правильными значениями, но медленнее (по крайней мере, для этого примера).

smm_m = sm_m.multiply( sm_m / sm_m.sum(axis=0)) соответствует smmGm += smm_m работает.Разреженный += не вызывает ошибки эффективности, поскольку не меняет разреженности.

Поэтому ключевой вопрос заключается в том, чтобы умножение матриц и умножение элементов было прямым (и соответствующие деления).

w / sklearn

sklearn.utils.sparsefuncs имеет несколько разреженных утилит

Вышеприведенный sm_m массив coo (не знаю почему):

In [366]: sm_m
Out[366]: 
<4x4 sparse matrix of type '<class 'numpy.float64'>'
    with 7 stored elements in COOrdinate format>
In [367]: sm_m.A
Out[367]: 
array([[ 0., 50.,  0., 10.],
       [12.,  0.,  0.,  0.],
       [12., 50.,  0., 10.],
       [ 0.,  0., 62.,  0.]])

преобразовать его в csr:

In [368]: sm_m1 = sm_m.tocsr()
In [369]: sm_m1
Out[369]: 
<4x4 sparse matrix of type '<class 'numpy.float64'>'
    with 7 stored elements in Compressed Sparse Row format>

получить массив масштабирования столбцов:

In [370]: x = sm_m1.sum(axis=0)
In [371]: x
Out[371]: matrix([[ 24., 100.,  62.,  20.]])
In [372]: x = 1/x.A1      # .A1 makes a 1d array from np.matrix

применить масштабирование на месте:

In [373]: sklearn.utils.sparsefuncs.inplace_csr_column_scale(sm_m1,x)
In [374]: sm_m1.A
Out[374]: 
array([[0. , 0.5, 0. , 0.5],
       [0.5, 0. , 0. , 0. ],
       [0.5, 0.5, 0. , 0.5],
       [0. , 0. , 1. , 0. ]])

Это на месте column_scale просто:

def inplace_csr_column_scale(X, scale):
    # ....
    X.data *= scale.take(X.indices, mode='clip')

Шаг m_m.multiply(s_m) также можно выполнить следующим образом:

In [380]: m1_m = m_m.tocsr()
In [381]: sklearn.utils.sparsefuncs.inplace_csr_column_scale(m1_m,s_m.A1)
In [382]: m1_m.A
Out[382]: 
array([[ 0., 50.,  0., 10.],
       [12.,  0.,  0.,  0.],
       [12., 50.,  0., 10.],
       [ 0.,  0., 62.,  0.]])

Я подозреваю, что код можно очистить, удалив транспонирование и т. Д.

Является ли G изначально квадратным?Мне нравится использовать неквадратные массивы, чтобы лучше отслеживать формы, транспонирование и размерные суммы.Я попытался расширить G до (5,4) и столкнулся с проблемой на шаге s*m.

...