scikit Learn LatentDirichletAllocation зависает после многопроцессорных и URL-запросов

Как правило, мой код Python выполняет следующие три шага.

  1. запустить multiprocess, чтобы очистить результаты поиска от поисковой системы
  2. очищать текст с каждого URL-адреса в списке (без многопроцессорности), используя библиотеку запросов python
  3. запустить метод fit_partial объекта класса LDA из библиотеки обучения scikit

Программа работает нормально, когда я вырезал всего 50–80 URL-адресов, но когда URL-адресов много, программа зависает на шаге 3 после завершения метода fit_partial от трех до восьми и печати журналов.

[Parallel(n_jobs=4)]: Done   4 out of   4 | elapsed:    0.1s finished
[Parallel(n_jobs=4)]: Done   4 out of   4 | elapsed:    0.1s finished
[Parallel(n_jobs=4)]: Done   4 out of   4 | elapsed:    0.1s finished
[Parallel(n_jobs=4)]: Done   4 out of   4 | elapsed:    0.1s finished

Если я проверю использование процессора процесса, все процессы python имеют нулевое использование процессора.

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

Итак, я провел две симуляции. В первой симуляции я пропускаю только шаг 2. Во второй симуляции пропускаю только шаг 1. В каждой симуляции я загружал сохраненный результат шага 1 и шага 2 вместо выполнения фактического шага.

Первая симуляция прошла нормально, но вторая зависла.

Из чего следует вывод, что шаг 2 вызывает зависание шага 3. Ниже приведен код для шага 2. Все результаты добавляются в объект словаря, который использует URL-адреса в качестве ключей.

def parse_information(url):

print(url)

try:
    response = requests.get(url, verify=False)
except:
    raise Exception("requests exception")

obj_bs = BeautifulSoup(response.text, "html.parser")

meta_refresh = obj_bs.find("meta", {"http-equiv": "refresh"})

if meta_refresh is not None:
    refresh_url = meta_refresh["content"].lower().rsplit("url=")[1]
    rup = urlparse(refresh_url)
    if rup.netloc == "":
        up = urlparse(url)
        return parse_information(up.scheme + "://" + up.netloc + refresh_url)
    return parse_information(refresh_url)

meta_charset = obj_bs.find(lambda tag: tag.name == 'meta' and 'charset' in tag.attrs)
http_equivs = obj_bs.findAll(lambda tag: tag.name == 'meta' and 'http-equiv' in tag.attrs)

if meta_charset is not None:
    response.encoding = meta_charset["charset"]
elif len(http_equivs) > 0:
    content_charset = ""
    for http_equiv in http_equivs:
        if http_equiv["http-equiv"].lower() == "content-type":
            content_charset = http_equiv["content"]
            break
    if content_charset != "":
        parse_charset = content_charset.split("charset=")
        if len(parse_charset) > 1:
            response.encoding = parse_charset[1]
    else:
        response.encoding = "shift_jis"
else:
    response.encoding = "shift_jis"
obj_bs = BeautifulSoup(response.text, "html.parser")

info_dict = dict(title="", h1="", keywords="", description="", h2="")

tag_title = obj_bs.find("title")
info_dict["title"] = tag_title.text if tag_title is not None else ""

tag_h1 = obj_bs.find("h1")
info_dict["h1"] = tag_h1.text if tag_h1 is not None else ""

tags_h2 = obj_bs.findAll("h2")
info_dict["h2"] = "|".join([tag_h2.text.strip("\t\r\n ") for tag_h2 in tags_h2]) if len(tags_h2) > 0 else ""

metas = obj_bs.findAll(lambda tag: tag.name == 'meta' and 'name' in tag.attrs)

for meta in metas:
    if meta["name"] == "keywords":
        info_dict["keywords"] = meta.get("content", "")
    elif meta["name"] == "description":
        info_dict["description"] = meta.get("content", "")

htot = html2text.HTML2Text()
htot.ignore_links = True
htot.images_to_alt = True
htot.ignore_emphasis = True

pure_text = htot.handle(response.text).lower()

noun_dict = japanese_noun_dict(pure_text)

if len(noun_dict) == 0:
    num_nouns = 0
else:
    num_nouns = reduce(lambda a, b: a + b, noun_dict.values())

return {"info": info_dict, "noun": {"num": num_nouns, "freq": noun_dict}}

Ниже приведен код для шага 3. g_result_lda.model — это объект класса LatentDirichletAllocation, изучаемый программой scikit. corpus_data — это матрица слов документа, созданная из текстов URL.

g_result_lda = TextLDA(documents=corpus_data, n_topics=n_topic)

len_corpus = len(g_result_lda.corpus_data)

# g_result_lda.model.fit(g_result_lda.corpus_data)

start_index = 0

while start_index < len_corpus:

    end_index = start_index + 20 if start_index + 20 < len_corpus else len_corpus
    g_result_lda.model.partial_fit(g_result_lda.corpus_data[start_index:end_index])
    start_index = start_index +20

Кто-нибудь знает, в чем причина проблемы? Есть ли у библиотеки scikit-learn конфликт с библиотекой запросов?

Я изучаю Python на OSX


person Donguk Lim    schedule 22.01.2016    source источник


Ответы (1)


Я только что решил проблему, создав RPC-сервер с RabbitMQ. Я использовал библиотеку Pika для использования RabbitMQ и создал сервер с BlockingConnection. Сервер работает исключительно в одном потоке и процессе, ожидая одного запроса, а когда он получает запрос, он выполняет анализ LDA с множественной обработкой и возвращает результат.

person Donguk Lim    schedule 25.04.2016