MinMax Scale Sparse Matrix исключая нулевые элементы

1

У меня есть матрица, которая содержит числа между [0, 5]. Матрица очень разреженная, большинство элементов равно нулю. Я хочу применить масштабирование min-max к каждой строке отдельно, чтобы все элементы находились между [-1, 1]. Однако я хочу учитывать только ненулевые элементы. Например, рассмотрим следующую матрицу:

[[0.5 3.  0.  2.  0. ]
 [0.  4.  5.  0.  0. ]
 [3.  0.  0.  2.5 4. ]]

После преобразования он будет выглядеть так: (Как видите, 0 элементов нетронутыми)

[[-1.          1.          0.          0.2         0.        ]
 [ 0.         -1.          1.          0.          0.        ]
 [-0.33333333  0.          0.         -1.          1.        ]]

Я могу сделать это на обычных массивах numpy со следующим кодом:

max_arr = A.max(axis=1)
min_arr = np.where(A == 0, A.max(), A).min(axis=1)
row_idx, col_idx = A.nonzero()
A_scaled = np.zeros_like(A)
for row, col in zip(row_idx, col_idx):
    element = A[row, col]
    A_scaled[row, col] = 2 * ((element - min_arr[row]) / (max_arr[row] - min_arr[row])) - 1

Здесь есть пара вопросов. Во-первых, он медленный (из-за цикла for может быть?). Другое дело, что моя матрица разрежена, поэтому я хочу использовать разреженный формат csr_matrix. Этот код не работает, если матрица A является csr_matrix. Он дает ошибку в строке 2, говорящей ValueError: setting an array element with a sequence.

Как я могу достичь этого быстро и эффективно? Я посмотрел на sklearn.preprocessing.MinMaxScaler но он не поддерживает масштабирование, исключая нули.

  • 0
    @Divakar, да. Извините за поздний ответ, я не мог найти время, чтобы попробовать ваш код до сих пор. Это работает как шарм, и это определенно намного быстрее. Благодарю.
Теги:
numpy
scipy

1 ответ

1
Лучший ответ

Здесь один векторный метод для матриц csr_matrix -

def scale_sparse_matrix_rows(s, lowval=0, highval=1):
    d = s.data

    lens = s.getnnz(axis=1)
    idx = np.r_[0,lens[:-1].cumsum()]

    maxs = np.maximum.reduceat(d, idx)
    mins = np.minimum.reduceat(d, idx)

    minsr = np.repeat(mins, lens)
    maxsr = np.repeat(maxs, lens)

    D = highval - lowval
    scaled_01_vals = (d - minsr)/(maxsr - minsr)
    d[:] = scaled_01_vals*D + lowval

Пример прогона -

1) Ввод установки csr_matrix:

In [153]: a
Out[153]: 
array([[0.5, 3. , 0. , 2. , 0. ],
       [0. , 4. , 5. , 0. , 0. ],
       [3. , 0. , 0. , 2.5, 4. ]])

In [154]: from scipy.sparse import csr_matrix

In [155]: s = csr_matrix(a)

2) Запустите предложенный метод и проверьте результаты:

In [156]: scale_sparse_matrix_rows(s, lowval=-1, highval=1)

In [157]: s.toarray()
Out[157]: 
array([[-1.        ,  1.        ,  0.        ,  0.2       ,  0.        ],
       [ 0.        , -1.        ,  1.        ,  0.        ,  0.        ],
       [-0.33333333,  0.        ,  0.        , -1.        ,  1.        ]])

Ещё вопросы

Сообщество Overcoder
Наверх
Меню