Проблема
Я пытаюсь вычислить косинусное сходство между двумя массивами, но есть небольшое изменение в базовой формуле. А именно, я забочусь только о компонентах, которые перекрываются с «ссылочным» массивом. Например, если бы мы вычислили косинусное сходство между следующими двумя массивами:
A = [1 0 1] B = [1 1 0]
[0 1 1] [0 1 1]
Допустим, B
является эталонным массивом. Затем A
изменяется относительно каждой строки в B, чтобы включить только те компоненты, которые перекрываются с этой строкой. Например, первая строка в B
равна [1 1 0]
, поэтому вычисление подобия выполняется с модифицированной матрицей A:
[1 0 0]
[0 1 0]
Чтобы вычислить следующие сходства с помощью [0 1 1]
, измененное значение A
становится:
[0 0 1]
[0 1 1]
Мой вопрос: есть ли способ внедрить эту модификацию без существенного снижения производительности (по сравнению со встроенными опциями сходства косинусов, такими как sklearn.metrics.pairwise.cosine_similarity
)? Я понимаю, что ничто не будет таким же быстрым, как стандартное вычисление сходства косинусов, но сейчас мои попытки ввести это изменение привели к замедлению почти в 100 раз, поэтому любое улучшение этого было бы большим.
Попытки
На самом деле я не знаю ни одного способа сделать это, кроме как проходить строку за строкой через массив ссылок, маскировать другой массив в соответствии с текущей строкой, а затем выполнять косинус-подобие матрицы-вектора. Примерно так:
def modified_cosine_sim(arr1, arr2):
# arr2 is reference array
final_arr = []
for row in arr2:
masked_arr1 = arr1 * np.where(row > 0, 1, 0)
final_arr.append(cosine_similarity(masked_arr1, row))
return final_arr
Хотя это довольно неэффективно. Я проверил, есть ли какой-нибудь умный способ изменить код sklearn cosine_similarity
для достижения цели, но этот код основан на нормализации обоих массивов до того, как вычисления продолжатся, и я не могу этого сделать - arr1
эффективно изменяется на протяжении всего вычисления, в зависимости от строки в arr2
, которая в настоящее время используется для вычисления сходств.
Мне приходится многократно запускать это вычисление на несколько больших массивах, поэтому любые советы по оптимизации будут высоко оценены. Или, если это вычисление соответствует какой-то уже оптимизированной встроенной функции, с которой я не знаком, это было бы еще лучше. Спасибо!