python - NLTK: corpus-nivel bleu vs nivel de oración BLEU puntuación
machine-learning nlp (2)
He importado nltk en python para calcular BLEU Score en Ubuntu. Entiendo cómo funciona el puntaje BLEU a nivel de oración, pero no entiendo cómo funciona el puntaje BLEU a nivel de corpus.
A continuación está mi código para la puntuación BLEU a nivel del corpus:
import nltk
hypothesis = [''This'', ''is'', ''cat'']
reference = [''This'', ''is'', ''a'', ''cat'']
BLEUscore = nltk.translate.bleu_score.corpus_bleu([reference], [hypothesis], weights = [1])
print(BLEUscore)
Por alguna razón, la puntuación de bleu es 0 para el código anterior. Esperaba una puntuación BLEU de nivel corpus de al menos 0.5.
Aquí está mi código para el puntaje BLEU a nivel de oración
import nltk
hypothesis = [''This'', ''is'', ''cat'']
reference = [''This'', ''is'', ''a'', ''cat'']
BLEUscore = nltk.translate.bleu_score.sentence_bleu([reference], hypothesis, weights = [1])
print(BLEUscore)
Aquí el puntaje BLEU a nivel de oración es 0,71, lo que espero, teniendo en cuenta la brevedad de la pena y la palabra faltante "a". Sin embargo, no entiendo cómo funciona el puntaje BLEU a nivel de corpus.
Cualquier ayuda sería apreciada.
Vamos a ver:
>>> help(nltk.translate.bleu_score.corpus_bleu)
Help on function corpus_bleu in module nltk.translate.bleu_score:
corpus_bleu(list_of_references, hypotheses, weights=(0.25, 0.25, 0.25, 0.25), smoothing_function=None)
Calculate a single corpus-level BLEU score (aka. system-level BLEU) for all
the hypotheses and their respective references.
Instead of averaging the sentence level BLEU scores (i.e. marco-average
precision), the original BLEU metric (Papineni et al. 2002) accounts for
the micro-average precision (i.e. summing the numerators and denominators
for each hypothesis-reference(s) pairs before the division).
...
Estás en una mejor posición que yo para entender la descripción del algoritmo, así que no intentaré "explicarte". Si el docstring no aclara lo suficiente, eche un vistazo a la fuente en sí. O encuentralo localmente
>>> nltk.translate.bleu_score.__file__
''.../lib/python3.4/site-packages/nltk/translate/bleu_score.py''
TL; DR :
>>> import nltk
>>> hypothesis = [''This'', ''is'', ''cat'']
>>> reference = [''This'', ''is'', ''a'', ''cat'']
>>> references = [reference] # list of references for 1 sentence.
>>> list_of_references = [references] # list of references for all sentences in corpus.
>>> list_of_hypotheses = [hypothesis] # list of hypotheses that corresponds to list of references.
>>> nltk.translate.bleu_score.corpus_bleu(list_of_references, list_of_hypotheses)
0.6025286104785453
>>> nltk.translate.bleu_score.sentence_bleu(references, hypothesis)
0.6025286104785453
(Nota: debe extraer la última versión de NLTK en la sucursal de develop
para obtener una versión estable de la implementación del puntaje BLEU)
En Long :
En realidad, si solo hay una referencia y una hipótesis en todo su corpus, tanto corpus_bleu()
como sentence_bleu()
deberían devolver el mismo valor que se muestra en el ejemplo anterior.
En el código, vemos que sentence_bleu
es en realidad un tipo de pato de corpus_bleu
:
def sentence_bleu(references, hypothesis, weights=(0.25, 0.25, 0.25, 0.25),
smoothing_function=None):
return corpus_bleu([references], [hypothesis], weights, smoothing_function)
Y si miramos los parámetros para sentence_bleu
:
def sentence_bleu(references, hypothesis, weights=(0.25, 0.25, 0.25, 0.25),
smoothing_function=None):
""""
:param references: reference sentences
:type references: list(list(str))
:param hypothesis: a hypothesis sentence
:type hypothesis: list(str)
:param weights: weights for unigrams, bigrams, trigrams and so on
:type weights: list(float)
:return: The sentence-level BLEU score.
:rtype: float
"""
La entrada para las referencias de sentence_bleu
es una list(list(str))
.
Entonces, si tienes una cadena de frases, por ejemplo, "This is a cat"
, debes tokenizarla para obtener una lista de cadenas, ["This", "is", "a", "cat"]
y dado que permite referencias múltiples, tiene que ser una lista de lista de cadenas, por ejemplo, si tiene una segunda referencia, "Esto es un felino", su entrada a sentence_bleu()
sería:
references = [ ["This", "is", "a", "cat"], ["This", "is", "a", "feline"] ]
hypothesis = ["This", "is", "cat"]
sentence_bleu(references, hypothesis)
Cuando se trata del parámetro corpus_bleu()
list_of_references, es básicamente una lista de lo que tome el sentence_bleu()
como referencias :
def corpus_bleu(list_of_references, hypotheses, weights=(0.25, 0.25, 0.25, 0.25),
smoothing_function=None):
"""
:param references: a corpus of lists of reference sentences, w.r.t. hypotheses
:type references: list(list(list(str)))
:param hypotheses: a list of hypothesis sentences
:type hypotheses: list(list(str))
:param weights: weights for unigrams, bigrams, trigrams and so on
:type weights: list(float)
:return: The corpus-level BLEU score.
:rtype: float
"""
Aparte de ver el más doctest dentro de nltk/translate/bleu_score.py
, también puedes echar un vistazo a unittest en nltk/test/unit/translate/test_bleu_score.py
para ver cómo usar cada uno de los componentes dentro de bleu_score.py
.
Por cierto, dado que sentence_bleu
se importa como bleu
en ( nltk.translate.__init__.py
] ( https://github.com/nltk/nltk/blob/develop/nltk/translate/ init .py # L21 ), utilizando
from nltk.translate import bleu
sería lo mismo que:
from nltk.translate.bleu_score import sentence_bleu
y en código:
>>> from nltk.translate import bleu
>>> from nltk.translate.bleu_score import sentence_bleu
>>> from nltk.translate.bleu_score import corpus_bleu
>>> bleu == sentence_bleu
True
>>> bleu == corpus_bleu
False