Я пытаюсь лемматизировать регистры чата в фрейме данных, используя spacy. Мой код:
nlp = spacy.load("es_core_news_sm")
df["text_lemma"] = df["text"].apply(lambda row: " ".join([w.lemma_ for w in nlp(row)]))
У меня около 600 000 строк, и выполнение приложения занимает более двух часов. Есть ли более быстрый пакет/способ лемматизации? (Мне нужно решение, которое работает для испанского)
Я только пытался использовать пакет spacy
Пожалуйста, ознакомьтесь с часто задаваемыми вопросами о скорости spaCy — использование nlp.pipe
, как упоминалось в других ответах, является одним из важных шагов. Если все, что вам нужно, это лемматизатор, вам следует отключить неиспользуемые компоненты, такие как синтаксический анализатор и NER. github.com/explosion/spaCy/discussions/8402
Замедление скорости обработки связано с многочисленными вызовами конвейера spaCy через nlp()
. Более быстрый способ обработки больших текстов — вместо этого обрабатывать их как поток с помощью команды nlp.pipe()
. Когда я протестировал это на 5000 строк фиктивного текста, он предложил увеличение скорости примерно в 3,874 раза (~ 9,759 с против ~ 2,519 с) по сравнению с исходным методом. При необходимости есть способы улучшить это, см. этот контрольный список для оптимизации spaCy, которую я сделал.
# Assume dataframe (df) already contains column "text" with text
# Load spaCy pipeline
nlp = spacy.load("es_core_news_sm")
# Process large text as a stream via `nlp.pipe()` and iterate over the results, extracting lemmas
lemma_text_list = []
for doc in nlp.pipe(df["text"]):
lemma_text_list.append(" ".join(token.lemma_ for token in doc))
df["text_lemma"] = lemma_text_list
import spacy
import pandas as pd
import time
# Random Spanish sentences
rand_es_sentences = [
"Tus drafts influirán en la puntuación de las cartas según tu número de puntos DCI.",
"Información facilitada por la División de Conferencias de la OMI en los cuestionarios enviados por la DCI.",
"Oleg me ha dicho que tenías que decirme algo.",
"Era como tú, muy buena con los ordenadores.",
"Mas David tomó la fortaleza de Sion, que es la ciudad de David."]
# Duplicate sentences specified number of times
es_text = [sent for i in range(1000) for sent in rand_es_sentences]
# Create data-frame
df = pd.DataFrame({"text": es_text})
# Load spaCy pipeline
nlp = spacy.load("es_core_news_sm")
# Original method (very slow due to multiple calls to `nlp()`)
t0 = time.time()
df["text_lemma_1"] = df["text"].apply(lambda row: " ".join([w.lemma_ for w in nlp(row)]))
t1 = time.time()
print("Total time: {}".format(t1-t0)) # ~9.759 seconds on 5000 rows
# Faster method processing rows as stream via `nlp.pipe()`
t0 = time.time()
lemma_text_list = []
for doc in nlp.pipe(df["text"]):
lemma_text_list.append(" ".join(token.lemma_ for token in doc))
df["text_lemma_2"] = lemma_text_list
t1 = time.time()
print("Total time: {}".format(t1-t0)) # ~2.519 seconds on 5000 rows
Вызов list
не очень хорош, потому что вы материализуете всю трубу. Просто используйте объект генератора.
@erip Согласен, я обновил код и ценю ваш вклад. Отмечу, что документация spaCy использует оба, и могут быть случаи, когда кому-то требуется функциональность, предлагаемая списком, вместо прямой работы с объектом-генератором. Также не было никаких заметных изменений во времени обработки по сравнению с моим кратким тестированием.
Спасибо! Эти решения очень помогли
Используйте
nlp.pipe
, API для массовых аннотаций.