Я запустил ваш плотный код,
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))
соответствует smm
.И Gm += 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
.