Commit 6b465c50 by xiaotong

wording (lm search)

parent 84bb2ea8
...@@ -816,18 +816,18 @@ c_{\textrm{KN}}(\cdot) = \left\{\begin{array}{ll} ...@@ -816,18 +816,18 @@ c_{\textrm{KN}}(\cdot) = \left\{\begin{array}{ll}
\subsection{搜索问题的建模} \subsection{搜索问题的建模}
\parinterval 基于语言模型的序列生成问题可以被定义为:在无数任意排列的单词序列中找到概率最高的序列。这里单词序列$w = w_1 w_2 \ldots w_m$的语言模型得分$\funp{P}(w)$度量了这个序列的合理性和流畅性。因此在序列生成任务中,基于语言模型的搜索问题可以被描述为: \parinterval 基于语言模型的序列生成问题可以被定义为:在无数任意排列的单词序列中找到概率最高的序列。这里单词序列$w = w_1 w_2 \ldots w_m$的语言模型得分$\funp{P}(w)$度量了这个序列的合理性和流畅性。在序列生成任务中,基于语言模型的搜索问题可以被描述为:
\begin{eqnarray} \begin{eqnarray}
w^{'} = \argmax_{w \in \chi}\funp{P}(w) \hat{w} = \argmax_{w \in \chi}\funp{P}(w)
\label{eq:2-40} \label{eq:2-40}
\end{eqnarray} \end{eqnarray}
\parinterval 这里$\arg$即argument,$\argmax_{w \in \chi}\funp{P}(w)$表示想要找到使语言模型得分$\funp{P}(w)$达到最大的单词序列$w$$\chi$是搜索问题的解空间 \footnote[1]{解空间,是一个算法执行后,所得到的所有解构成的集合。},它是所有可能的单词序列$w$的集合。$w^{'}$可以被看做该搜索问题中的“最优解”,即“出现概率最大的单词序列” \noindent 这里$\arg$即argument(参数),$\argmax_x f(x)$表示返回使$f(x)$达到最大的$x$$\argmax_{w \in \chi}\funp{P}(w)$表示找到使语言模型得分$\funp{P}(w)$达到最大的单词序列$w$$\chi$ 是搜索问题的解空间,它是所有可能的单词序列$w$的集合。$\hat{w}$可以被看做该搜索问题中的“最优解”,即概率最大的单词序列
\parinterval 在序列生成任务中,最简单的策略就是对词表中的词汇进行任意组合,通过这种枚举的方式得到全部可能的序列。但是,很多时候并没有预先指定生成序列的长度。比如,机器翻译中目标语序列的长度是无法预先知道的。那么怎样判断一个序列何时完成了生成过程呢?回顾人类书写文字的过程可以发现,句子的生成首先从一片空白开始,然后从左到右逐词生成,除了第一个单词,所有单词的生成都依赖于前面已经生成的单词。为了方便计算机实现,通常定义单词序列从一个特殊的符号<sos>后开始生成。同样地,一个单词序列的结束也用一个特殊的符号<eos>来表示。 \parinterval 在序列生成任务中,最简单的策略就是对词表中的词汇进行任意组合,通过这种枚举的方式得到全部可能的序列。但是,很多时候并生成序列的长度是无法预先知道的。比如,机器翻译中目标语序列的长度是任意的。那么怎样判断一个序列何时完成了生成过程呢?这里借用人类书写中文和英文的过程:句子的生成首先从一片空白开始,然后从左到右逐词生成,除了第一个单词,所有单词的生成都依赖于前面已经生成的单词。为了方便计算机实现,通常定义单词序列从一个特殊的符号<sos>后开始生成。同样地,一个单词序列的结束也用一个特殊的符号<eos>来表示。
\parinterval 对于一个序列$<$sos$>$\ \ I\ \ agree\ \ $<$eos$>$,图\ref{fig:2-13}展示语言模型视角该序列的生成过程。该过程通过在序列的末尾不断附加词表中的单词来逐渐扩展序列,直到这段序列结束。这种生成单词序列的过程被称作{\small\bfnew{自左向右生成}}\index{自左向右生成}(Left-To-Right Generation)\index{Left-To-Right Generation} \parinterval 对于一个序列$<$sos$>$\ \ I\ \ agree\ \ $<$eos$>$,图\ref{fig:2-13}展示语言模型视角下该序列的生成过程。该过程通过在序列的末尾不断附加词表中的单词来逐渐扩展序列,直到这段序列结束。这种生成单词序列的过程被称作{\small\bfnew{自左向右生成}}\index{自左向右生成}(Left-To-Right Generation)\index{Left-To-Right Generation}。注意,这种序列生成策略与$n$-gram的思想天然契合,因为$n$-gram语言模型中,每个词的生成概率依赖前面(左侧)若干词,因此$n$-gram语言模型也是一种自左向右的计算模型
%---------------------------------------------- %----------------------------------------------
\begin{figure}[htp] \begin{figure}[htp]
...@@ -838,7 +838,10 @@ w^{'} = \argmax_{w \in \chi}\funp{P}(w) ...@@ -838,7 +838,10 @@ w^{'} = \argmax_{w \in \chi}\funp{P}(w)
\end{figure} \end{figure}
%------------------------------------------- %-------------------------------------------
\parinterval 在这种序列生成方式的基础上,实现对候选序列的搜索过程通常有两种方法\ \dash\ 深度优先遍历和宽度优先遍历\upcite{DBLP:books/mg/CormenLR89}。在深度优先遍历中,每次从词表中可重复地选择一个单词,然后从左至右地生成序列,直到<eos>被选择,此时一个完整的单词序列被生成出来。然后从<eos>回退到上一个单词,选择之前词表中未被选择到的候选单词代替<eos>,并继续挑选下一个单词直到<eos>被选到,如果上一个单词的所有可能都被枚举过,那么回退到上上一个单词继续枚举,直到回退到<sos>,这时候枚举结束。在宽度优先遍历中,每次不是只选择一个单词而是枚举所有单词。一个简单的例子是一个只有两个单词\{a, b\}的词表,从<sos>开始枚举所有单词,可以生成: \parinterval 在这种序列生成方式的基础上,实现搜索通常有两种方法\ \dash\ 深度优先遍历和宽度优先遍历\upcite{DBLP:books/mg/CormenLR89}。在深度优先遍历中,每次从词表中可重复地选择一个单词,然后从左至右地生成序列,直到<eos>被选择,此时一个完整的单词序列被生成出来。然后从<eos>回退到上一个单词,选择之前词表中未被选择到的候选单词代替<eos>,并继续挑选下一个单词直到<eos>被选到,如果上一个单词的所有可能都被枚举过,那么回退到上上一个单词继续枚举,直到回退到<sos>,这时候枚举结束。在宽度优先遍历中,每次不是只选择一个单词,而是枚举所有单词。
有一个一个简单的例子。假设词表只含两个单词\{a, b\},从<sos>开始枚举所有单词,有三种可能:
\begin{eqnarray} \begin{eqnarray}
\text{\{<sos> a, <sos> b, <sos> <eos>\}} \nonumber \text{\{<sos> a, <sos> b, <sos> <eos>\}} \nonumber
\end{eqnarray} \end{eqnarray}
...@@ -865,16 +868,19 @@ w^{'} = \argmax_{w \in \chi}\funp{P}(w) ...@@ -865,16 +868,19 @@ w^{'} = \argmax_{w \in \chi}\funp{P}(w)
\end{itemize} \end{itemize}
\parinterval 当任务对单词序列长度没有限制时,上述两种方法枚举出的单词序列也是无穷无尽的。因此这两种枚举策略并不具备完备性而且会导致枚举过程无法停止。由于日常生活中通常不会见到特别长的句子,因此可以通过限制单词序列的最大长度来避免这个问题。一旦单词序列的最大长度被确定,以上两种枚举策略就可以在一定时间内枚举出所有可能的单词序列,因而一定可以找到最优的单词序列,即具备最优性。 \parinterval 当任务对单词序列长度没有限制时,上述两种方法枚举出的单词序列也是无穷无尽的。因此这两种枚举策略并不具备完备性而且会导致枚举过程无法停止。由于日常生活中通常不会见到特别长的句子,因此可以通过限制单词序列的最大长度来避免这个问题。一旦单词序列的最大长度被确定,以上两种枚举策略就可以在一定时间内枚举出所有可能的单词序列,因而一定可以找到最优的单词序列,即具备最优性。
\parinterval 此时上述生成策略虽然可以满足完备性和最优性,但其仍然算不上是优秀的生成策略,因为这两种算法在时间复杂度和空间复杂度上的表现很差,如表\ref{tab:2-3}所示。其中$|V|$为词表大小,$m$ 为序列长度值得注意的是,在之前的遍历过程中,除了在序列开头一定会挑选<sos>之外,其他位置每次可挑选的单词并不只有词表中的单词,还有结束符号<eos>,因此实际上生成过程中每个位置的单词候选数量为$|V|+1$
\vspace{0.5em} \vspace{0.5em}
%------------------------------------------------------ %------------------------------------------------------
\begin{table}[htp]{ \begin{table}[htp]{
\begin{center} \begin{center}
\caption{枚举的两种实现方式比较} \caption{枚举的两种实现方式比较}
{ {
\begin{tabular}{c|c|c|c|c} \begin{tabular}{c|c|c}
\rule{0pt}{10pt} & 完备性 & 最优性 & 时间复杂度 & 空间复杂度\\ \hline \rule{0pt}{10pt} & 时间复杂度 & 空间复杂度\\ \hline
\rule{0pt}{10pt} 深度优先 & $\surd^{\ast}$ & $\surd^{\ast}$ & $\textrm{O}({(|V|+1)}^{m-1})$ & $\textrm{O}(m)$ \\ \rule{0pt}{10pt} 深度优先 & $\textrm{O}({(|V|+1)}^{m-1})$ & $\textrm{O}(m)$ \\
\rule{0pt}{10pt} 宽度优先 & $\surd$ & $\surd^{\ast}$ & $\textrm{O}({(|V|+1)}^{m-1}$) & $\textrm{O}({(|V|+1)}^{m})$ \\ \rule{0pt}{10pt} 宽度优先 & $\textrm{O}({(|V|+1)}^{m-1}$) & $\textrm{O}({(|V|+1)}^{m})$ \\
\end{tabular} \end{tabular}
\label{tab:2-3} \label{tab:2-3}
} }
...@@ -882,9 +888,7 @@ w^{'} = \argmax_{w \in \chi}\funp{P}(w) ...@@ -882,9 +888,7 @@ w^{'} = \argmax_{w \in \chi}\funp{P}(w)
}\end{table} }\end{table}
%------------------------------------------------------ %------------------------------------------------------
\parinterval 此时上述生成策略虽然可以满足完备性和最优性,但其仍然算不上是优秀的生成策略,因为这两种算法在时间复杂度和空间复杂度上的表现很差,如表\ref{tab:2-3}所示。其中$|V|$为词表大小,$m$为序列长度,$\ast$表示“当且仅当在单词序列的最大长度被确定”。值得注意的是,在之前的遍历过程中,除了在序列开头一定会挑选<sos>之外,其他位置每次可挑选的单词并不只有词表中的单词,还有结束符号<eos>,因此实际上生成过程中每个位置的单词候选数量为$|V|+1$ \parinterval 那么是否有比枚举策略更高效的方法呢?答案是肯定的。一种直观的方法是将搜索的过程表示成树型结构,称为解空间树。它包含了搜索过程中可生成的全部序列。该树的根节点恒为$<$sos$>$,代表序列均从$<$sos$>$ 开始。该树结构中非叶子节点的兄弟节点有$|V|$个,由词表和结束符号$<$eos$>$构成。从图\ref{fig:2-14}可以看到,对于一个最大长度为4的序列的搜索过程,生成某个单词序列的过程实际上就是访问解空间树中从根节点<sos> 开始一直到叶子节点<eos>结束的某条路径,而这条的路径上节点按顺序组成了一段独特的单词序列。此时对所有可能单词序列的枚举就变成了对解空间树的遍历。并且枚举的过程与语言模型打分的过程也是一致的,每枚举一个词$i$也就是在上图选择$w_i$一列的一个节点,语言模型就可以为当前的树节点$w_i$给出一个分值,即$\funp{P}(w_i | w_1 w_2 \ldots w_{i-1})$。对于$n$-gram语言模型,这个分值$\funp{P}(w_i | w_1 w_2 \ldots w_{i-1})=\funp{P}(w_i | w_{i-n+1} \ldots w_{i-1})$
\parinterval 那么是否有比枚举策略更高效的方法呢?答案是肯定的。从图\ref{fig:2-14}可以看到,对于一个最大长度为4的序列的搜索过程,生成某个单词序列的过程实际上就是访问解空间树\footnote[2]{解空间树是搜索路径的树型表示,它包含了搜索过程中可生成的全部序列。该树的根节点恒为$<$sos$>$,代表序列均从$<$sos$>$开始。该树结构中非叶子节点的兄弟节点有$|V|$个,由词表和结束符号$<$eos$>$构成。}中从根节点<sos>开始一直到叶子节点<eos>结束的某条路径,而这条的路径上节点按顺序组成了一段独特的单词序列。此时对所有可能单词序列的枚举就变成了对解空间树的遍历。并且枚举的过程与语言模型打分的过程也是一致的,每枚举一个词$i$也就是在上图选择$w_i$一列的一个节点,语言模型就可以为当前的树节点$w_i$给出一个分值,即$\funp{P}(w_i | w_1 w_2 \ldots w_{i-1})$
%---------------------------------------------- %----------------------------------------------
\begin{figure}[htp] \begin{figure}[htp]
...@@ -895,11 +899,11 @@ w^{'} = \argmax_{w \in \chi}\funp{P}(w) ...@@ -895,11 +899,11 @@ w^{'} = \argmax_{w \in \chi}\funp{P}(w)
\end{figure} \end{figure}
%------------------------------------------- %-------------------------------------------
\parinterval 从这个角度来看,可以很自然地引入语言模型打分来对枚举的解空间树的遍历进行增广:在解空间树中引入节点的权重\ \dash\ 将当前节点$i$的得分重设为语言模型打分$\log \funp{P}(w_i | w_1 w_2 \ldots w_{i-1})$,其中$w_1 w_2 \ldots w_{i-1}$是该节点的全部祖先。与先前不同的是,由于在使用语言模型打分时,词的概率通常小于1,因此句子很长时概率会非常小,容易造成浮点误差,所以这里使用概率的对数形式$\log \funp{P}(w_i | w_1 w_2 \ldots w_{i-1})$代替$\funp{P}(w_i | w_1 w_2 \ldots w_{i-1})$。此时对于图中一条包含<eos>的完整序列来说,它的最终得分为$\log \funp{P}(w_1 w_2 \ldots w_m) = \sum_{i=1}^{m}\log \funp{P}(w_i | w_1 w_2 \ldots w_{i-1})$。如图\ref{fig:2-15}所示,可知红线所示单词序列“<sos>\ I\ agree\ <eos>”的得分为: \parinterval 从这个角度来看,在树的遍历中,可以很自然地引入语言模型打分:在解空间树中引入节点的权重\ \dash\ 将当前节点$i$的得分重设为语言模型打分$\log \funp{P}(w_i | w_1 w_2 \ldots w_{i-1})$,其中$w_1 w_2 \ldots w_{i-1}$是该节点的全部祖先。与先前不同的是,由于在使用语言模型打分时,词的概率通常小于1,因此句子很长时概率会非常小,容易造成浮点误差,所以这里使用概率的对数形式$\log \funp{P}(w_i | w_1 w_2 \ldots w_{i-1})$代替$\funp{P}(w_i | w_1 w_2 \ldots w_{i-1})$。此时对于图中一条包含<eos>的完整序列来说,它的最终得分为$\log \funp{P}(w_1 w_2 \ldots w_m) = \sum_{i=1}^{m}\log \funp{P}(w_i | w_1 w_2 \ldots w_{i-1})$。如图\ref{fig:2-15}所示,可知红线所示单词序列“<sos>\ I\ agree\ <eos>”的得分为:
\begin{eqnarray} \begin{eqnarray}
&&\textrm{score(<sos>\ I\ agree\ <eos>)} \nonumber \\ &&\textrm{score(<sos>\ I\ agree\ <eos>)} \nonumber \\
& = & \log \funp{P}(\textrm{I} | \textrm{<sos>}) + \log \funp{P}(\textrm{agree} | \textrm{<sos>\ I}) + \log \funp{P}(\textrm{<sos>}| \textrm{<sos>\ I\ agree}) \nonumber \\ & = & \log \funp{P}(\textrm{<sos>}) + \log \funp{P}(\textrm{I} | \textrm{<sos>}) + \log \funp{P}(\textrm{agree} | \textrm{<sos>\ I}) + \log \funp{P}(\textrm{<sos>}| \textrm{<sos>\ I\ agree}) \nonumber \\
& = & -0.5-0.2-0.8 \nonumber \\ & = & 0-0.5-0.2-0.8 \nonumber \\
& = & -1.5 & = & -1.5
\label{eq:2-41} \label{eq:2-41}
\end{eqnarray} \end{eqnarray}
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论