评估语言模型性能的最佳方法是将其嵌入到一个具体应用中,并测量该应用性能的提升程度。 这种端到端的评估称为外在评估(extrinsic evaluation)。 外在评估是唯一能够确定语言模型(或任何组件)的某项改进是否真正有助于当前任务的方法。 因此,在评估作为语音识别或机器翻译等任务组成部分的n元语法(n-gram)语言模型时,可以通过分别使用两个候选语言模型运行语音识别器或机器翻译系统两次,比较哪种模型产生的转录更准确,从而进行评估。
然而,端到端地运行大型自然语言处理系统往往成本高昂。因此,我们需要一种能够快速评估语言模型潜在改进的指标。 内在评估(intrinsic evaluation)是一种不依赖具体应用、直接衡量模型质量的方法。 在下一节中,我们将介绍一种标准的内在评估指标——困惑度(perplexity),它被广泛用于衡量语言模型的性能,无论是简单的n元语法语言模型,还是第9章中更复杂的神经网络大语言模型。
评估任何机器学习模型,至少需要三个不同的数据集:训练集(training set)、开发集(development set,也称为验证集 validation set)和测试集(test set)。
训练集用于学习模型的参数。对于简单的n元语法语言模型来说,训练集就是从中统计n元组频率的语料库,随后将这些频率归一化为概率值,构建语言模型。
测试集则是一组与训练集完全不重叠的独立数据,用于评估模型的表现。我们需要一个独立的测试集来无偏估计训练出的模型在面对未知数据时的泛化能力。如果一个机器学习模型完美地拟合了训练数据,但在其他任何数据上表现都很差,那么它在实际应用中将毫无用处。因此,通过模型在这些“未见过”的测试集或测试语料上的表现来衡量n元语法模型的质量。
我们应该如何选择训练集和测试集呢?测试集应能反映我们希望使用该模型的语言场景。如果打算将语言模型用于化学讲座的语音识别,那么测试集就应该是化学讲座的文本;如果打算将其用于中译英的酒店预订请求翻译系统,那么测试集就应该是酒店预订请求的文本;如果希望语言模型具备通用性,那么测试集就应涵盖多种类型的文本。在这种情况下,可以从不同来源收集大量文本,然后将其划分为训练集和测试集。划分时要格外小心;如果构建的是一个通用模型,就不希望测试集仅包含来自单一文档或某一位作者的文本,因为这不能很好地衡量模型的泛化能力。
因此,如果手头有一个语料库,并希望比较两个不同n元语法模型的表现,可以将数据划分为训练集和测试集,并在训练集上训练两个模型的参数。然后,可以比较这两个训练好的模型在测试集上的拟合程度。
但“拟合测试集”到底意味着什么呢?标准答案很简单:哪个语言模型给测试集分配了更高的概率,就意味着它对测试集的预测更准确,因此是更好的模型。给定两个概率模型,更优的模型就是那个能够更好预测测试数据细节的模型,因此它会给测试数据分配更高的概率。
由于估指标是基于测试集概率的,因此非常重要的一点是:不能将测试集中的句子泄露到训练集中。假设我们试图计算某个特定“测试”句子的概率,如果这个测试句子包含在训练语料中,那么当它出现在测试集中时,我们会错误地给它分配一个虚高的概率。我们将这种情况称为在测试集上训练。在测试集上训练会引入偏差,使所有概率看起来都偏高,并会导致下面将要介绍的基于概率的评估指标——困惑度(perplexity)出现严重偏差。
即使没有在测试集上进行训练,如果多次对语言模型在测试集上进行测试(每次在模型修改之后),也可能会无意中根据测试集的特点对模型进行调优,因为我们可能会注意到哪些修改使模型表现更好。因此,只应在模型完全准备就绪之后,对测试集进行一次或极少数几次测试。
正因如此,通常还会引入第三个数据集,称为开发集(development test set)或简称验证集(devset)。在最终阶段之前,所有的模型调优和测试都使用这个开发集。只有当确信模型已经调优完毕后,才在测试集上进行一次最终测试,以评估模型的真实表现。
那么,该如何将数据划分为训练集、开发集和测试集呢?我们希望测试集尽可能大,因为一个过小的测试集可能会偶然不具备代表性。但同时,也希望拥有尽可能多的训练数据。最低限度上,希望选择一个足够大的测试集,以便能够有足够强的统计能力,检测出两个候选模型之间是否存在统计显著的差异。此外,开发集必须与测试集来自相同的文本类型,因为它的目标就是用来预测模型在测试集上的表现。