Hello Ines, Thank you for your message (and sorry I didn't respond sooner - I hadn't seen your message until just now)!
I think I understand! Knowing that those indices refer to token spans rather than character spans was key. So thank you for clarifying 
With that in mind, I believe there is a mistake in @honnibal's original code. Matt said the confidence scores are supposed to be the sums of each entity score across all beams divided by the total confidence score across all beams. His code, as originally written, says:
text = content
doc = nlp.make_doc(text)
(beams, somethingelse) = nlp.entity.beam_parse([doc], beam_width=16, beam_density=0.0001)
for score, ents in nlp.entity.moves.get_beam_parses(beams[0]):
print (score, ents)
entity_scores = defaultdict(float) #Move this line...
for start, end, label in ents:
entity_scores[(start, end, label)] += score
print ('entity_scores', entity_scores)
but this overwrites the summation calculation within each beam parse loop. Instead, I think he meant to write:
text = content
doc = nlp.make_doc(text)
(beams, somethingelse) = nlp.entity.beam_parse([doc], beam_width=16, beam_density=0.0001)
entity_scores = defaultdict(float) #This line is moved above the for loop
for score, ents in nlp.entity.moves.get_beam_parses(beams[0]):
print (score, ents)
for start, end, label in ents:
entity_scores[(start, end, label)] += score
print ('entity_scores', entity_scores)
This way, the score summation can be applied across all like entities across all beam parses.
I think the essence of the question "How can I see spacy's confidence scores" is so we can judge whether to ignore or accept a recognized entity. To that end, below I am including the code to do exactly that - rejecting any entity with less than 90% confidence:
from collections import defaultdict
import spacy
nlp = spacy.load('en_core_web_sm')
examples = [
"Trump says he's answered Mueller's Russia inquiry questions \u2013 live",
"Alexander Zverev reaches ATP Finals semis then reminds Lendl who is boss",
"Britain's worst landlord to take nine years to pay off string of fines",
"Tom Watson: people's vote more likely given weakness of May's position",
]
def filter_low_confidence_entities(entities, cutoff = 0.8):
return {key: value for key, value in entities.items() if value > cutoff}
for text in examples:
doc = nlp.make_doc(text)
beams = nlp.entity.beam_parse([doc], beam_width=16, beam_density=0.0001)
entity_scores = defaultdict(float)
total_score = 0
print(text)
for score, ents in nlp.entity.moves.get_beam_parses(beams[0]):
total_score += score
for start, end, label in ents:
entity_scores[(start, end, label)] += score
normalized_beam_score = {dict_key: dict_value/total_score for dict_key, dict_value in entity_scores.items()}
high_confidence_entities = filter_low_confidence_entities(normalized_beam_score, 0.9)
high_confidence_entity_texts = {key: doc[int(key[0]): int(key[1])] for key, value in high_confidence_entities.items()}
print(' All entities with their normalized beam score:', normalized_beam_score)
print(' Entities with over 90% confidence:', high_confidence_entities)
print(' Text of entities with over 90% confidence:', high_confidence_entity_texts)
print()
This generates the output:
Trump says he's answered Mueller's Russia inquiry questions – live
All entities with their normalized beam score: {(0, 1, 'PERSON'): 0.8310895450340546, (5, 6, 'PERSON'): 0.544892847991814, (7, 8, 'GPE'): 0.9995667492150351, (5, 6, 'GPE'): 0.17364807605704594, (5, 6, 'ORG'): 0.1348159179697731, (0, 1, 'ORG'): 0.14118210418236288, (0, 1, 'WORK_OF_ART'): 0.021270195958141717, (5, 6, 'PRODUCT'): 0.010583714212205777, (5, 7, 'ORG'): 0.0020761379197505566, (7, 8, 'NORP'): 0.00043325078496490415}
Entities with over 90% confidence: {(7, 8, 'GPE'): 0.9995667492150351}
Text of entities with over 90% confidence: {(7, 8, 'GPE'): Russia}
Alexander Zverev reaches ATP Finals semis then reminds Lendl who is boss
All entities with their normalized beam score: {(0, 2, 'PERSON'): 1.0, (8, 9, 'PERSON'): 0.8126843355674371, (8, 9, 'GPE'): 0.16098034886646048, (8, 9, 'ORG'): 0.009975386613193055, (8, 9, 'EVENT'): 0.0033844388023142186, (8, 9, 'LOC'): 0.0031300464486402756, (8, 9, 'DATE'): 0.0022775503479185756, (8, 9, 'WORK_OF_ART'): 0.0007166247409828817, (8, 9, 'TIME'): 0.0005546103020750846, (3, 4, 'ORG'): 0.0007808016968760548, (8, 9, 'ORDINAL'): 0.00020208240500204164, (8, 9, 'NORP'): 0.0001284758944144186, (8, 9, 'CARDINAL'): 9.48442763928523e-05}
Entities with over 90% confidence: {(0, 2, 'PERSON'): 1.0}
Text of entities with over 90% confidence: {(0, 2, 'PERSON'): Alexander Zverev}
Britain's worst landlord to take nine years to pay off string of fines
All entities with their normalized beam score: {(0, 1, 'GPE'): 1.0, (6, 8, 'DATE'): 1.0}
Entities with over 90% confidence: {(0, 1, 'GPE'): 1.0, (6, 8, 'DATE'): 1.0}
Text of entities with over 90% confidence: {(0, 1, 'GPE'): Britain, (6, 8, 'DATE'): nine years}
Tom Watson: people's vote more likely given weakness of May's position
All entities with their normalized beam score: {(0, 2, 'PERSON'): 1.0, (11, 12, 'DATE'): 0.9304278463190857, (11, 12, 'PERSON'): 0.011462009957275915, (11, 12, 'ORG'): 0.010313748202097068, (11, 12, 'EVENT'): 0.0069746922642973065, (11, 12, 'WORK_OF_ART'): 0.004421763927953416, (11, 12, 'GPE'): 0.0014732389994051099, (11, 12, 'TIME'): 0.00095577752865234, (11, 12, 'FAC'): 0.0004951325925289379, (11, 12, 'LAW'): 0.00020647127193283314}
Entities with over 90% confidence: {(0, 2, 'PERSON'): 1.0, (11, 12, 'DATE'): 0.9304278463190857}
Text of entities with over 90% confidence: {(0, 2, 'PERSON'): Tom Watson, (11, 12, 'DATE'): May}
Interestingly this eliminates a lot of Entity candidates. And there's even one false positive in here where May
was recognized as a date rather than part of a person's name (I believe Theresa "May"). Do you / your team have any suggestions for:
- eliminating/reducing these false positives?
- boosting the confidence of other recognized entities?
- can you recommend a strategy for when or if to accept different entity candidates at different confidence thresholds?
Please let me know if something looks off but otherwise thanks again for your help! And for the amazing libraries your team makes!! 