Com o CoreNLPParser.tag()
atual, a "retocagem" do Stanford CoreNLP é inesperada:
>>> from nltk.parse.corenlp import CoreNLPParser
>>> ner_tagger = CoreNLPParser(url='http://localhost:9000', tagtype='ner')
>>> sent = ['my', 'phone', 'number', 'is', '1111', '1111', '1111']
>>> ner_tagger.tag(sent)
[('my', 'O'),
('phone', 'O'),
('number', 'O'),
('is', 'O'),
('1111\xa01111\xa01111', 'NUMBER')]
O comportamento esperado deve ser:
>>> from nltk.parse.corenlp import CoreNLPParser
>>> ner_tagger = CoreNLPParser(url='http://localhost:9000', tagtype='ner')
>>> sent = ['my', 'phone', 'number', 'is', '1111', '1111', '1111']
>>> ner_tagger.tag(sent)
[('my', 'O'), ('phone', 'O'), ('number', 'O'), ('is', 'O'), ('1111', 'DATE'), ('1111', 'DATE'), ('1111', 'DATE')]
A solução proposta é permitir a sobrecarga de properties
argumentos para .tag()
e .tag_sents()
, ou seja, em https://github.com/nltk/nltk/blob/develop/nltk/parse/ corenlp.py # L348 e por padrão use properties = {'tokenize.whitespace':'true'}
porque estamos concatenando os tokens por espaços em tag_sents()
.
def tag_sents(self, sentences, properties=None):
"""
Tag multiple sentences.
Takes multiple sentences as a list where each sentence is a list of
tokens.
:param sentences: Input sentences to tag
:type sentences: list(list(str))
:rtype: list(list(tuple(str, str))
"""
# Converting list(list(str)) -> list(str)
sentences = (' '.join(words) for words in sentences)
if properties == None:
properties = {'tokenize.whitespace':'true'}
return [sentences[0] for sentences in self.raw_tag_sents(sentences, properties)]
def tag(self, sentence, properties=None):
"""
Tag a list of tokens.
:rtype: list(tuple(str, str))
>>> parser = CoreNLPParser(url='http://localhost:9000', tagtype='ner')
>>> tokens = 'Rami Eid is studying at Stony Brook University in NY'.split()
>>> parser.tag(tokens)
[('Rami', 'PERSON'), ('Eid', 'PERSON'), ('is', 'O'), ('studying', 'O'), ('at', 'O'), ('Stony', 'ORGANIZATION'),
('Brook', 'ORGANIZATION'), ('University', 'ORGANIZATION'), ('in', 'O'), ('NY', 'O')]
>>> parser = CoreNLPParser(url='http://localhost:9000', tagtype='pos')
>>> tokens = "What is the airspeed of an unladen swallow ?".split()
>>> parser.tag(tokens)
[('What', 'WP'), ('is', 'VBZ'), ('the', 'DT'),
('airspeed', 'NN'), ('of', 'IN'), ('an', 'DT'),
('unladen', 'JJ'), ('swallow', 'VB'), ('?', '.')]
"""
return self.tag_sents([sentence], properties)[0]
def raw_tag_sents(self, sentences, properties=None):
"""
Tag multiple sentences.
Takes multiple sentences as a list where each sentence is a string.
:param sentences: Input sentences to tag
:type sentences: list(str)
:rtype: list(list(list(tuple(str, str)))
"""
default_properties = {'ssplit.isOneSentence': 'true',
'annotators': 'tokenize,ssplit,' }
default_properties.update(properties or {})
# Supports only 'pos' or 'ner' tags.
assert self.tagtype in ['pos', 'ner']
default_properties['annotators'] += self.tagtype
for sentence in sentences:
tagged_data = self.api_call(sentence, properties=default_properties)
yield [[(token['word'], token[self.tagtype]) for token in tagged_sentence['tokens']]
for tagged_sentence in tagged_data['sentences']]
Isso deve reforçar a lista de tokens de string inseridos pelos usuários.
Se permitirmos que .tag()
sobrecarregue as propriedades antes de raw_tag_sents
, isso também permitirá aos usuários lidar facilmente com casos como # 1876
Parece bom.
Apenas alguns pequenos comentários. Deve ser if properties is None
, não if properties == None
. assert self.tagtype in ['pos', 'ner']
deve ser assert self.tagtype in ['pos', 'ner'], "CoreNLP tagger supports only 'pos' or 'ner' tags."
.
Eu realmente não gosto da ideia de juntar e dividir strings, talvez pudesse haver uma maneira de passar uma lista de palavras para CoreNLP como uma frase em vez de uma string simples.
Olá, gostaria de considerar este meu primeiro problema.
É ótimo que você esteja interessado no assunto. Se você tiver alguma dúvida, pergunte aqui.
Comentários muito úteis
Parece bom.
Apenas alguns pequenos comentários. Deve ser
if properties is None
, nãoif properties == None
.assert self.tagtype in ['pos', 'ner']
deve serassert self.tagtype in ['pos', 'ner'], "CoreNLP tagger supports only 'pos' or 'ner' tags."
.Eu realmente não gosto da ideia de juntar e dividir strings, talvez pudesse haver uma maneira de passar uma lista de palavras para CoreNLP como uma frase em vez de uma string simples.