Как ускорить время при вычислении сходства косинусов с использованием вложенных циклов в python

Я пытаюсь вычислить косинусное сходство между всеми значениями.

Время расчета 1000*20000 стоило мне более 10 минут.

Код:

from gensim import matutils
# array_A contains 1,000 TF-IDF values
# array_B contains 20,000 TF-IDF values 
for x in array_A:
   for y in array_B:
      matutils.cossim(x,y)

Необходимо использовать пакет gensim для получения значения tf-idf и расчета сходства.

Может ли кто-нибудь дать мне несколько советов и указаний, чтобы ускорить время?


person huang06    schedule 18.09.2017    source источник
comment
Можно ли избавиться от одного из циклов for? Cython ускоряет работу?   -  person Mateen Ulhaq    schedule 18.09.2017


Ответы (3)


используйте memoize, а также, возможно, используйте кортежи (это может быть быстрее) для массивов:

def memoize(f):
    memo = {}

    def helper(a, b):
        if (b, a) in memo: return memo[b, a]
        elif (a, b) in memo: return memo[a, b]
        else:
            memo[(a, b)] = f(a, b)
            return memo[a, b]

    return helper


@memoize
def myfunc(a, b):
    matutils.cossim(x,y)

ИЗМЕНИТЬ также после использования приведенного выше кода, возможно, добавьте это на тот случай, если вы делаете что-то еще с данными

cossim_responses = [myfunc(a, b) for a in array_A for b in array_B]
# you could also do (myfunc(a, b) for a in array_A for b in array_B)
person Eli    schedule 18.09.2017
comment
Результат показывает, что TypeError: unhashable type: 'list' - person huang06; 18.09.2017
comment
Какой код? Я обновил его так, что теперь он говорит a, b вместо a, a - person Eli; 18.09.2017

Вы можете посмотреть исходный код matutils.cossim() от gensim:

https://github.com/RaRe-Technologies/gensim/blob/2e58a1c899af05ee6a39a1dd1c49dd6641501a9c/gensim/matutils.py#L436

Вы увидите, что он немного поработал над своими двумя (разреженными массивами) аргументами, чтобы переместить их ненулевые измерения во временные словари, а затем вычислить их длину, что повторяется каждый раз, когда один и тот же вектор предоставляется в ваших циклах.

Вы можете получить разумное ускорение, выполнив эти шаги для каждого вектора только один раз и запомнив эти слова и длины для повторного использования при каждом последнем попарном вычислении. (То есть запоминание промежуточных значений, а не только окончательных значений.)

person gojomo    schedule 18.09.2017

Вы можете использовать Nmslib или Faiss для операций векторного поиска

person mustfkeskin    schedule 24.10.2019