Как создать набор обучающих данных с нуля для пользовательской модели тегов standfordNLP/Stanza NER с несколькими классами в формате BIOES/BILOU?
Я использую NLP для специального приложения и хочу обучить свою собственную модель тегов NER в StanfordNLP, в настоящее время известном как Stanza.
Модель по умолчанию ограничена очень общими тегами, такими как LOC, PER, MISC, COUNTRY, TIME и т. Д.
Мои пользовательские теги более конкретны, например. Еда, Спорт, Программное обеспечение, Бренд. Как я могу узнать о форматировании данных, которые я удалил из Интернета или из файлов PDF в формате BIOES/BILOU?https://en.wikipedia.org/wiki/Inside%E2%80%93outside%E2%80%93beginning_(tagging)
Обязательно ли мне помечать их вручную? или напишите сценарий для генерации данных в формате, показанном ниже:
Alex S-PER
is O
playing O
basketball I-SPORT
with O
Marty B-PER
. O
Rick E-PER
likes O
to O
eat O
Pizza I-FOOD
in O
Los B-LOC
Angeles E-LOC
Если да, то какие инструменты и библиотеки я могу использовать в Python?
Заранее спасибо.
1 ответ
Вы можете написать фрагмент кода для выполнения этой задачи.
Вот решение, которое я сделал.
from flashtext import KeywordProcessor
import stanza
nlp = stanza.Pipeline(lang='en', processors='tokenize,ner,pos')
# Tag tokens with standard NLP BIO tags
def bio_tagger(entity, start_char, end_char, tag):
bio_tagged = {"tag":None, "end_char":None, "start_char":None}
ne_tagged = entity.split()
if len(ne_tagged) == 1:
bio_tagged["start_char"] = start_char
bio_tagged["end_char"] = start_char + len(ne_tagged[0])
bio_tagged["tag"] = "B-"+tag
elif len(ne_tagged) == 2:
bio_tagged["start_char"] = start_char
bio_tagged["end_char"] = start_char + len(ne_tagged[0])
bio_tagged["tag"] = "B-"+tag
bio_tagged["start_char"] = end_char - len(ne_tagged[-1])
bio_tagged["end_char"] = end_char
bio_tagged["tag"] = "E-"+tag
elif len(ne_tagged) >= 3:
bio_tagged["start_char"] = start_char
bio_tagged["end_char"] = start_char + len(ne_tagged[0])
bio_tagged["tag"] = "B-"+tag
bio_tagged["start_char"] = end_char - len(ne_tagged[-1])
bio_tagged["end_char"] = end_char
bio_tagged["tag"] = "E-"+tag
cursor = start_char + len(ne_tagged[0]) + 2
for tok in ne_tagged[1:-1]:
bio_tagged["start_char"] = cursor
bio_tagged["end_char"] = cursor + len(tok)
bio_tagged["tag"] = "I-"+tag
cursor = cursor + len(tok) + 2
return bio_tagged
def bio_corpus_builder(text, tags2dict):
#tags2dict {'SPORT':['football','basektball'],
# 'FOOD':['banana','orange']}
corpus = []
document = []
for tag, tag_values in tags2dict.items():
keyword_processor = KeywordProcessor()
keyword_processor.add_keywords_from_list(tag_values)
for sent in get_sentences(text):
word_tag_tagger = []
each_token = {"text": None, "upos":None, "xpos":None,"tag":None, "end_char":None, "start_char":None}
entities_found = keyword_processor.extract_keywords(sent, span_info=True)
if entities_found:
# construct custom tag
for word_tag in entities_found:
word_tag_tagger.append(bio_tagger(word_tag[0], word_tag[1], word_tag[2], tag))
# read original tag
doc = nlp(sent)
sentence = doc.sentences[0]
print(word_tag_tagger)
each_sent = []
for token in sentence.tokens:
each_token["text"] = token.text
each_token["tag"] = token.ner
each_token["end_char"] = token.end_char
each_token["start_char"] = token.start_char
each_token["upos"] = token.to_dict()[0]["upos"]
each_token["xpos"] = token.to_dict()[0]["xpos"]
each_sent.append(dict(each_token))
#update tagging
for tok in each_sent:
for word2tags in word_tag_tagger:
if (int(tok["start_char"]) == int(word2tags["start_char"])) and (int(tok["end_char"]) == int(word2tags["end_char"])):
tok["tag"] = word2tags['tag']
document.append(each_sent)
del keyword_processor
return document
# if "__name__"=="__main__":
tags2dict ={'SPORT':['football','basektball'],'FOOD':['banana','orange']}
text = "Barack Obama was born in Hawaii. He love basektball."
bio_corpus_builder(text, tags2dict)
#output
# [[{'text': 'He',
# 'upos': 'PRON',
# 'xpos': 'PRP',
# 'tag': 'O',
# 'end_char': 2,
# 'start_char': 0},
# {'text': 'love',
# 'upos': 'VERB',
# 'xpos': 'VBP',
# 'tag': 'O',
# 'end_char': 7,
# 'start_char': 3},
# {'text': 'basektball',
# 'upos': 'NOUN',
# 'xpos': 'NN',
# 'tag': 'B-SPORT',
# 'end_char': 18,
# 'start_char': 8},
# {'text': '.',
# 'upos': 'PUNCT',
# 'xpos': '.',
# 'tag': 'O',
# 'end_char': 19,
# 'start_char': 18}]]