Как использовать spacy для распознавания именных объектов в файле CSV - PullRequest
0 голосов
/ 10 марта 2020

Я пробовал так много вещей, чтобы сделать распознавание имен объектов в столбце в моем CSV-файле, я попытался ne_chunk, но я не могу получить результат моего ne_chunk в столбцах, как это

ID  STORY                                       PERSON  NE   NP  NN VB  GE
1   Washington, a police officer James...        1      0    0   0   0   1

Вместо этого после использования этого кода

news=pd.read_csv("news.csv")

news['tokenize'] = news.apply(lambda row: nltk.word_tokenize(row['STORY']), axis=1)


news['pos_tags'] = news.apply(lambda row: nltk.pos_tag(row['tokenize']), axis=1)

news['entityrecog']=news.apply(lambda row: nltk.ne_chunk(row['pos_tags']), axis=1)

tag_count_df = pd.DataFrame(news['entityrecognition'].map(lambda x: Counter(tag[1] for tag in x)).to_list())

news=pd.concat([news, tag_count_df], axis=1).fillna(0).drop(['entityrecognition'], axis=1)

news.to_csv("news.csv")

я получил эту ошибку

IndexError : list index out of range

Итак, мне интересно, смогу ли я сделать это с помощью spaCy, что является еще одной вещью, о которой я понятия не имею. Кто-нибудь может помочь?

1 Ответ

0 голосов
/ 10 марта 2020

Кажется, что вы неправильно проверяете чанки, поэтому вы получаете ошибку ключа. Я догадываюсь немного о том, что вы хотите сделать, но это создает новые столбцы для каждого типа NER, возвращаемого NLTK. Было бы немного чище предопределить и обнулять каждый столбец типа NER (так как это дает вам NaN, если NER не существует).

def extract_ner_count(tagged):
    entities = {}
    chunks = nltk.ne_chunk(tagged)
    for chunk in chunks:
        if type(chunk) is nltk.Tree:
          #if you don't need the entities, just add the label directly rather than this.
          t = ''.join(c[0] for c in chunk.leaves())
          entities[t] = chunk.label()
    return Counter(entities.values())

news=pd.read_csv("news.csv")
news['tokenize'] = news.apply(lambda row: nltk.word_tokenize(row['STORY']), axis=1)
news['pos_tags'] = news.apply(lambda row: nltk.pos_tag(row['tokenize']), axis=1)
news['entityrecognition']=news.apply(lambda row: extract_ner_count(row['pos_tags']), axis=1)
news = pd.concat([news, pd.DataFrame(list(news["entityrecognition"]))], axis=1)

print(news.head())

Если все, что вам нужно, это количество, то следующее является более производительным и не имеет NaN:

tagger = nltk.PerceptronTagger()
chunker = nltk.data.load(nltk.chunk._MULTICLASS_NE_CHUNKER)
NE_Types = {'GPE', 'ORGANIZATION', 'LOCATION', 'GSP', 'O', 'FACILITY', 'PERSON'}

def extract_ner_count(text):
    c = Counter()
    chunks = chunker.parse(tagger.tag(nltk.word_tokenize(text,preserve_line=True)))
    for chunk in chunks:
        if type(chunk) is nltk.Tree:
            c.update([chunk.label()])
    return c

news=pd.read_csv("news.csv")
for NE_Type in NE_Types:
    news[NE_Type] = 0
news.update(list(news["STORY"].apply(extract_ner_count)))

print(news.head())
...