2016-10-27 3 views
0

Мне нужно нормализовать все слова в огромных корпусах. Любые идеи по оптимизации этого кода? Это слишком медленно ...Normalize all words in document

texts = [ [ list(morph.normalize(word.upper()))[0] for word in document.split() ] 
      for document in documents ] 

documents список строк, где каждая строка представляет собой текст одиночной книги.

morph.normalize работает только для верхнего регистра, поэтому я применяю .upper() ко всем словам. Более того, он возвращает набор с одним элементом, который является нормированным словом (строка)

+2

Не уверен, что вы подразумеваете под «нормализацией слов», но, возможно, [memoization] (https://stackoverflow.com/questions/1988804/what-is-memoization-and-how-can-i-use-it- in-python) может ускорить его. – neuhaus

+0

Поскольку morph не является частью стандартной библиотеки (а не так широко известной как, например, NumPy), сообщите, какую библиотеку вы используете. – MKesper

+2

'list() [0]' кажется для меня дополнительным усилием - 'morph.normalize (word.upper()). Pop()' должен выполнять ту же работу. –

ответ

1

Первой и очевидной вещью, которую я бы сделал, было бы кэширование нормализованных слов в локальном dict, чтобы избежать вызова morph.normalize() более одного раза для данного слова.

Вторая оптимизация заключается в методах псевдонимов для локальных переменных - это позволяет избежать сквозного вызова атрибута look + function invcriptor + instodeiation объекта метода на каждом этапе цикла.

Тогда, поскольку это «огромный» корпус, вы, вероятно, хотите избежать создания полного списка списков сразу, что может съесть весь ваш баран, заставить ваш компьютер начать заменять (что гарантировано, чтобы сделать его улитки медленнее) и наконец, сбой памяти. Я не знаю, что вы должны делать с этим списком списков и каким огромным каждый документ, но в качестве примера я использую результат для каждого документа и записываю его в stdout - что действительно должно быть сделано, зависит от контекста и конкретного использование случай.

NB: непроверенный код, очевидно, но, по крайней мере, это поможет вам начать

def iterdocs(documents, morph): 
    # keep trac of already normalized words 
    # beware this dict might get too big if you 
    # have lot of different words. Depending on 
    # your corpus, you may want to either use a LRU 
    # cache instead and/or use a per-document cache 
    # and/or any other appropriate caching strategy... 
    cache = {} 

    # aliasing methods as local variables 
    # is faster for tight loops 
    normalize = morph.normalize 

    def norm(word): 
     upw = word.upper() 
     if upw in cache: 
      return cache[upw] 
     nw = cache[upw] = normalize(upw).pop() 
     return nw 

    for doc in documents: 
     words = [norm(word) for word in document.split() if word] 
     yield words 

for text in iterdocs(docs, morph): 
    # if you need all the texts for further use 
    # at least write them to disk or other persistence 
    # mean and re-read them when needed. 
    # Here I just write them to sys.stdout as an example 
    print(text) 

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

Наконец, как только вы убедитесь, что ваш код не доходит до большого объема памяти для одного документа, следующая очевидная оптимизация - это параллелизация - запуск процесса на доступное ядро ​​и разделение корпуса между процессами (каждый из которых записывает результаты данное место). Тогда вам просто нужно подвести итоги, если вам нужны все сразу ...

О, и да: если этого еще недостаточно, вы можете распространять работу с какой-либо картой уменьшения каркаса - ваша проблема выглядит как идеально подходит для уменьшения карты.