Общая память для нескольких объектов только для чтения с многопроцессорным пулом - PullRequest
0 голосов
/ 24 января 2019

Я создаю векторы документов с обученной моделью FastText на моем компьютере.Насколько мне известно, FastText Gensim не имеет возможности создавать векторы документов (более известные как векторы абзацев [PV]).Поэтому я рассчитал их вручную, взяв среднее значение суммы слов, имеющихся в документе.Эта задача сама по себе не займет много времени.

Если я хочу добавить несколько других числовых функций к вычисленному PV, создание 5 миллионов документов займет около 30 минут.Я думал, что этот процесс можно улучшить, разделив работу на несколько ядер на моем компьютере с помощью многопроцессорной библиотеки Python, которая работает сейчас, но только в определенной степени.

Было несколько проблем, которые мне пришлось решитьпрежде чем добраться до этой стадии.Поскольку я использую блокнот Jupyter для выполнения кода, мне пришлось поместить несколько методов в отдельный скрипт Python, чтобы иметь возможность использовать многозадачность в блокноте Jupyter.Этот код доступен в блокноте Jupyter.Он импортирует модуль "m_helpers", который имеет методы для создания векторов документов:

import multiprocessing
import m_helpers

# Define number of workers.
num_processes = 3

if __name__ == "__main__":
    # This pool spawns several processes to built the
    # document vectors with the FastText model
    with multiprocessing.Pool(processes = num_processes, 
                              initializer = m_helpers.init_vars, 
                              initargs = (fasttext_model, vars_df)) as pool:
        results = pool.map(m_helpers.create_docvecs,
                           data_df.itertuples(name = False), 
                           chunksize = 512)
        output = [x for x in results]

    # Print length of output to see whether everything was processed
    print("Length of output (document vectors): {0}".format(len(output)))

m_helpers.py:

fasttext_model = None
vars_df = None

def init_vars(model, df):
    global fasttext_model
    fasttext_model = model
    global vars_df
    vars_df = df

def create_docvecs(data):
    word_vectors = [fasttext_model.wv[word] for word in data[-1].str.split()]
    document_vector = sum(word_vectors) / len(word_vectors)
    feature_vector = vars_df.loc[data[0], :].values
    # Further code to combine both vectors
    return document_vector

У меня есть компьютер с 6 ядрами / 12 потоков.Однако я могу заставить этот код работать только для 3 ядер.Использование большего количества ядер всегда приводит к ошибке, вызванной использованием всей памяти (ОЗУ).Я думаю, что это вызвано всеми этими копиями объектов для каждого процесса.

Теперь, похоже, существуют способы создания общей памяти для доступа всех процессов.Существует кадр данных, который я перебираю для доступа к текстовым данным.Метод, который вызывается для всех процессов, использует другой фрейм данных и модель быстрого текста.Все эти объекты доступны только для чтения, чтобы создать PV и добавить значения из другого кадра данных.Я мог бы объединить текстовый фрейм данных и особенность фрейма данных раньше.Тем не менее, мне все равно нужно было бы поделиться хотя бы объектом fasttext_model.Вопрос в том, как это сделать?Это вообще возможно?Я прочитал несколько вопросов, касающихся этой проблемы, на stackoverflow, но я не мог многое сделать из этого.Может мне нужно использовать что-то отличное от пула?

...