Построение пользовательского распознавания именованных сущностей с помощью Spacy, используя случайный текст в качестве образца - PullRequest
0 голосов
/ 07 августа 2020

Мой вопрос на самом деле длиннее этого. Однако я разделяю вопрос на две части, поскольку он действительно длинный.

Я пытаюсь создать пользовательское распознавание именованных сущностей (NER) с помощью Spacy для продуктов. Я составил список слов, связанных с едой, и выполнил инструкции в разделе «Простой стиль обучения» на сайте Spacy https://spacy.io/usage/training#ner

Первый вопрос Чтобы создать TRAIN_DATA , то, что я сделал, было прочитано во всем "состоянии объединения" из этого набора данных kaggle https://www.kaggle.com/rtatman/state-of-the-union-corpus-1989-2017; токенизировал их в предложения, а затем просто случайно добавил в ключевые слова в случайное предложение из состояния объединения адреса. Затем я нашел его позицию в тексте и поместил в формат, описанный в документации Spacy. Могу я это сделать?

Вот мой код. Второй вопрос касается тестирования нового NER. Он поднимает первую сущность, но затем останавливается. Это улучшается, когда я предлагаю токенизировать текст, но проблема заключается в моем непонимании алгоритма Spacy. Я хотел бы задать это отдельным вопросом, так как этот вопрос уже слишком длинный:

import random
import pandas as pd
import os
import re
import nltk
from nltk.tokenize import PunktSentenceTokenizer
from random import randrange
import spacy
from spacy.util import minibatch, compounding
import warnings
from nltk.stem import WordNetLemmatizer


lemmatizer = WordNetLemmatizer()

food = pd.DataFrame(data = {"Description":["carrot","garlic", "beef", "pork"])  ## My actual dataset is in an excel file, and is much longer


food = food[["Description"]]
food["Description"] = food["Description"].apply(lambda x: x.lower())
food["Description"] = food["Description"].apply(lambda x: lemmatizer.lemmatize(x))

food.drop_duplicates(subset = ["Description"], inplace=True)
food["Description"] = food["Description"].apply(lambda x: x.strip())


os.chdir(r"C:\Users\Kah\AppData\Roaming\nltk_data\corpora\state_union")  ##Where I have saved the state of the union speeches

random_text = ""

for directory, folder,files in os.walk(r"C:\Users\Kah\AppData\Roaming\nltk_data\corpora\state_union"):
    for file in files:
        if "txt" in file:
            with open(file,  mode = "r") as text:
                data = text.read()
                data = re.sub(r'[^\x00-\x7f]',r'', data)
                data = re.sub("\n",r" ", data)
                random_text = random_text + " " + data.lower()


sent_tokenizer = PunktSentenceTokenizer()

random_sent = sent_tokenizer.tokenize(random_text)


df = pd.DataFrame({"Sent": random_sent})

df["Word"] = df["Sent"].apply(lambda x: nltk.word_tokenize(x))

##Return empty spaces in random text

df["Empty spaces"] = df["Sent"].apply(lambda x: [idx for idx, item in enumerate(x.lower()) if " " in item])

df["str blank"] = df["Empty spaces"].astype(str)
df = df.loc[df["str blank"] != "[]",:].copy(deep=True)


###Steps
##Pick a random sentence in df, pick a random empty space, insert target text (chemical or food), return start and end position
##This yields
#(Sentence, dict("entities":[(beg str, end str, ENTITY_NAME)]})
##Identify the shape of the random text so a computer can randomly pick a sentence
##Use randrange to randomly pick a sentence, add the word randomly in the sentence, then prepare the tag for training

df_shape = df.shape[0]

def tagger(series, df, label):

train = []

for x in series:

    try:
        randline = randrange(df_shape)-1
        rand_sent  = df["Sent"][randline]
        rand_space = df["Empty spaces"][randline][randrange(len(df["Empty spaces"][randline]))]
        rand_sent = f"{rand_sent[:rand_space]} {x}{rand_sent[rand_space:]}"
        start_index = rand_sent.find(x)
        end_index= start_index + len(x)
        word_tag ={"entities":[(start_index, end_index, label)]}
        tag = (rand_sent, word_tag)
        print(f"{x} completed")

        train.append(tag)
    except:
        pass

return train


food = pd.concat([food]*10)
train_food = tagger(food["Description"], df, "FOOD")
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...