【NLG】(一)文本生成评价指标——BLEU原理及代码示例

关于指标:

评价算法的效果,给模型效果进行量化,这样可以跟有同样功能的模型比较好坏。所以指标在定义的时候,也跟模型的解决的问题有关系。比如分类模型,评估模型效果时,会看其准招率;推荐模型会看auc、NDCG等指标,每个指标有自己的优缺点,想使用该指标,也得接受它不足的地方。

当然,你也可以自己定义指标的计算方式i,至于业界是否认,那就不好说了。

自然语言生成(Natural Language Generation,NLG),经常使用的无监督自评估方法如下(这里只展示一部分):

  1. bleu:比较真实评论和生成评论里的n-gram的重合程度
  2. meteor:考虑了基于整个语料库上的准确率和召回率而得出测度
  3. entropy:生成评论所包含的信息量
  4. kl_divergence:生成评论与真实评论两个分布之间的不同
  5. diversity:评价生成评论用词的多样性
  6. rouge:

1.BLEU原理

Bleu 全称为 Bilingual Evaluation Understudy(双语评估研究),意为双语评估替换,是衡量一个有多个正确输出结果的模型的精确度的评估指标。比较候选译文和参考译文里的 n-gram 的重合程度。多用于翻译质量评估。

可以说是所有评价指标的鼻祖,它的核心思想是比较候选译文和参考译文里的 n-gram 的重合程度,重合程度越高就认为译文质量越高。unigram用于衡量单词翻译的准确性,高阶n-gram用于衡量句子翻译的流畅性。 实践中,通常是取N=1~4,然后对进行加权平均。

BLEU 需要计算译文 1-gram,2-gram,...,N-gram 的精确率,一般 N 设置为 4 即可,公式中的 Pn 指 n-gram 的精确率。

其中,Wn 指 n-gram 的权重,一般设为均匀权重,即对于任意 n 都有 Wn = 1/N。BP 是惩罚因子,如果译文的长度小于最短的参考译文,则 BP 小于 1。lc机器翻译的长度,lr最短的参考译文的长度。

BLEU 的 1-gram 精确率表示译文忠于原文的程度,而其他 n-gram 表示翻译的流畅程度。不过BLEU对词重复和短句有着非常不好的表现,所以改进的BLEU分别使用改进的多元精度(n-gram precision) 和短句惩罚因子进行了优化。

BLEU评分的范围是从0到1。很少有翻译得分为1,除非它们与参考翻译完全相同。

考虑评估建议的响应和实际响应之间的字重叠量的度量.

2.优缺点

优点

  • 它的易于计算且速度快,特别是与人工翻译模型的输出对比,结果比较接近人类评分;
  • 它应用范围广泛,这可以让你很轻松将模型与相同任务的基准作对比。

缺点

  • 它不考虑语义,句子结构,不考虑语言表达(语法)上的准确性;
  • 不能很好地处理形态丰富的语句(BLEU原文建议大家配备4条翻译参考译文),测评精度会受常用词的干扰;
  • BLEU 指标偏向于较短的翻译结果(brevity penalty 没有想象中那么强),短译句的测评精度有时会较高;
  • 没有考虑同义词或相似表达的情况,可能会导致合理翻译被否定;

BLEU本身就不追求百分之百的准确性,也不可能做到百分之百,它的目标只是给出一个快且不差的自动评估解决方案。

3.如何算BLEU

查找了一些参考代码,最后采用了一个最简单的计算方法。

一 安装nltk

pip install nltk

二 计算BLEU

手动计算的例子:

待续

数据形式:

这里的输入数据,要求按字分开。每个字作为一个字符串,一句话组成一个元素为str的list,作为输入数据。

代码demo:

通过weights参数来控制n-gram的值。

from nltk.translate.bleu_score import corpus_bleu, sentence_bleu
from nltk.translate.bleu_score import SmoothingFunction
smooth = SmoothingFunction()  # 定义平滑函数对象
labels = ['我', '是', '谁']
predicts = ['我', '是', '猫']
corpus_score_2 = corpus_bleu(labels, predicts, weights=(0.5, 0.5, 0, 0), smoothing_function=smooth.method1)
corpus_score_4 = corpus_bleu(labels, predicts, smoothing_function=smooth.method1)

源码逻辑:

待续

 

参考:

1.评估指标的代码:https://github.com/Maluuba/nlg-eval

2.BLEU:https://zhuanlan.zhihu.com/p/100942429

  • 6
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
当然可以,以下是一个简单的基于RNN的自然语言生成模型的代码实现。 首先,我们需要准备训练数据。这里我们使用一个简单的数据集,其中每个样本都是一个句子,如下所示: ``` I am happy. She is sad. He is angry. ``` 接下来,我们需要将这些句子转换为计算机能够理解的向量表示。为此,我们可以使用词袋模型,将每个单词表示为一个独热向量,然后将整个句子表示为所有单词向量的平均值。代码如下: ```python import numpy as np def create_dataset(sentences): # Create word-to-index dictionary word_to_idx = {} for sentence in sentences: for word in sentence.split(): if word not in word_to_idx: word_to_idx[word] = len(word_to_idx) # Create dataset dataset = [] for sentence in sentences: sentence_vec = np.zeros(len(word_to_idx)) for word in sentence.split(): sentence_vec[word_to_idx[word]] = 1 dataset.append(sentence_vec) return dataset, word_to_idx sentences = ["I am happy.", "She is sad.", "He is angry."] dataset, word_to_idx = create_dataset(sentences) ``` 接下来,我们可以构建我们的RNN模型。这里我们使用一个简单的单层LSTM网络。 ```python import torch import torch.nn as nn class RNN(nn.Module): def __init__(self, input_size, hidden_size, output_size): super(RNN, self).__init__() self.hidden_size = hidden_size self.lstm = nn.LSTM(input_size, hidden_size) self.fc = nn.Linear(hidden_size, output_size) def forward(self, input): h0 = torch.zeros(1, 1, self.hidden_size) c0 = torch.zeros(1, 1, self.hidden_size) output, _ = self.lstm(input.view(len(input), 1, -1), (h0, c0)) output = self.fc(output.view(len(input), -1)) return output[-1] ``` 现在我们可以开始训练我们的模型。由于我们的目标是生成一个句子,所以我们将网络的输出解释为每个单词的概率分布,然后使用softmax函数将其转换为概率。代码如下: ```python import torch.optim as optim # Build model input_size = len(word_to_idx) hidden_size = 128 output_size = len(word_to_idx) rnn = RNN(input_size, hidden_size, output_size) # Train model criterion = nn.CrossEntropyLoss() optimizer = optim.SGD(rnn.parameters(), lr=0.1) for epoch in range(1000): for sentence in dataset: rnn.zero_grad() input = torch.tensor(sentence[:-1], dtype=torch.float32) target = torch.tensor(sentence[1:], dtype=torch.long) output = rnn(input) loss = criterion(output, target) loss.backward() optimizer.step() if epoch % 100 == 0: print("Epoch {0}, Loss {1}".format(epoch, loss.item())) ``` 最后,我们可以使用训练好的模型生成新的句子。为此,我们从一个随机单词开始,然后多次调用模型来预测下一个单词,直到我们达到了句子的最大长度。代码如下: ```python max_length = 10 def generate_sentence(rnn, word_to_idx): # Choose random starting word idx_to_word = {i: w for w, i in word_to_idx.items()} input = torch.zeros(len(word_to_idx)) start_idx = np.random.randint(len(word_to_idx)) input[start_idx] = 1 # Generate sentence sentence = [idx_to_word[start_idx]] for i in range(max_length): output = rnn(input) output_dist = nn.functional.softmax(output, dim=0) idx = torch.argmax(output_dist).item() input.zero_() input[idx] = 1 sentence.append(idx_to_word[idx]) if idx == word_to_idx["."]: break return " ".join(sentence) for i in range(5): print(generate_sentence(rnn, word_to_idx)) ``` 这就是一个简单的基于RNN的自然语言生成模型的代码实现。当然,这只是一个基础模型,还有很多改进的空间。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值