У меня есть двумерный массив (фактически матрица сходства), по которому мне нужно вычислить среднее по блокам. Например, со следующей матрицей:
sima = np.array([[1,0.8,0.7,0.3,0.1,0.5],
[0.8,1,0.1,0.5,0.2,0.5],
[0.7,0.1,1,0.1,0.3,0.9],
[0.3,0.5,0.1,1,0.8,0.5],
[0.1,0.2,0.3,0.8,1,0.5],
[0.5,0.5,0.9,0.5,0.5,1]])
И метки вектора:
labels = np.array([1,1,1,2,2,3])
Это означает, что первые три строки матрицы (а также столбцы столбцов, поскольку матрица подобия симметрична) соответствуют кластеру 1
, следующие 2 соответствуют кластеру 2
, а последние соответствуют кластер 3
.
Мне нужно вычислить среднее количество блоков в sima
, соответствующее меткам в labels
. Дает следующий вывод:
0.69 0.25 0.63
0.25 0.90 0.50
0.63 0.50 1.00
Пока у меня есть рабочее решение, использующее двойную петлю для меток и замаскированных массивов:
labels_matrix = np.tile(np.array(labels), (len(labels), 1))
output = pd.DataFrame(np.zeros(shape = (3,3)))
for i in range(3):
for j in range(3):
mask = (labels_matrix != j+1) | (labels_matrix.T != i+1)
output.loc[i,j] = np.mean(np.mean(np.ma.array(sima, mask = mask)))
Этот код выдает правильный вывод, но моя фактическая матрица 50kx50k, и этот код требует вечных вычислений. Как я мог сделать это быстрее?
Примечание: мне нужен другой порядок величины скорости, поэтому я ожидаю, что использования трюков, таких как симметрия матрицы подобия, будет недостаточно.