Сходство косинусного косинуса и сходство косинусного косинуса - PullRequest
1 голос
/ 29 апреля 2020

Я заметил, что и scipy, и sklearn имеют функции косинусного сходства / косинусного расстояния. Я хотел проверить скорость для каждого из пар векторов:

setup1 = "import numpy as np; arrs1 = [np.random.rand(400) for _ in range(60)];arrs2 = [np.random.rand(400) for _ in range(60)]"
setup2 = "import numpy as np; arrs1 = [np.random.rand(400) for _ in range(60)];arrs2 = [np.random.rand(400) for _ in range(60)]"

import1 = "from sklearn.metrics.pairwise import cosine_similarity"
stmt1 = "[float(cosine_similarity(arr1.reshape(1,-1), arr2.reshape(1,-1))) for arr1, arr2 in zip(arrs1, arrs2)]"

import2 = "from scipy.spatial.distance import cosine"
stmt2 = "[float(1 - cosine(arr1, arr2)) for arr1, arr2 in zip(arrs1, arrs2)]"

import timeit
print("sklearn: ", timeit.timeit(stmt1, setup=import1 + ";" + setup1, number=1000))
print("scipy:   ", timeit.timeit(stmt2, setup=import2 + ";" + setup2, number=1000))
sklearn:  11.072769448000145
scipy:    1.9755544730005568

sklearn работает почти в 10 раз медленнее, чем scipy (даже если вы удалите изменение формы массива для примера sklearn и генерировать данные, которые уже в правильной форме). Я не могу себе представить, почему один значительно медленнее другого?

1 Ответ

1 голос
/ 29 апреля 2020

Как уже упоминалось в разделе комментариев, я не думаю, что сравнение справедливо в основном потому, что sklearn.metrics.pairwise.cosine_similarity предназначен для сравнения попарного расстояния / подобия выборок в заданных входных 2-мерных массивах. С другой стороны, scipy.spatial.distance.cosine предназначен для вычисления косинусного расстояния двух 1-D массивов.

Возможно, более справедливое сравнение - использовать scipy.spatial.distance.cdist против sklearn.metrics.pairwise.cosine_similarity, где оба вычисляют попарно расстояние образцы в заданных массивах. Однако, к моему удивлению, это показывает, что реализация sklearn намного быстрее, чем реализация scipy (которой у меня сейчас нет объяснения!). Вот эксперимент:

import numpy as np
from sklearn.metrics.pairwise import cosine_similarity
from scipy.spatial.distance import cdist

x = np.random.rand(1000,1000)
y = np.random.rand(1000,1000)

def sklearn_cosine():
    return cosine_similarity(x, y)

def scipy_cosine():
    return 1. - cdist(x, y, 'cosine')

# Make sure their result is the same.
assert np.allclose(sklearn_cosine(), scipy_cosine())

И вот результат синхронизации:

%timeit sklearn_cosine()
10 loops, best of 3: 74 ms per loop

%timeit scipy_cosine()
1 loop, best of 3: 752 ms per loop
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...