ToB企服应用市场:ToB评测及商务社交产业平台

标题: 德克萨斯大学奥斯汀分校自然语言处理硕士课程汉化版(第四周) - 语言建模 [打印本页]

作者: 立山    时间: 2024-6-9 15:38
标题: 德克萨斯大学奥斯汀分校自然语言处理硕士课程汉化版(第四周) - 语言建模
语言建模

  
1. 统计语言模子

统计语言模子旨在量化自然语言文本中序列的概率分布,即计算一个词序列(如一个句子或文档)出现的大概性。这类模子基于统计方法,使用大量文本数据学习语言的统计规律,进而推测未知文本的概率,大概为给定的文本序列生成最大概的后续词汇。
统计语言模子的核心思想是将语言视为一个随机过程,每一个词的选择都受到其上下文的影响。模子通常定义为一个概率函数,比如假设一个句子由                                   T                              T                  T个单词顺序组成:
                                         W                            =                                       w                               T                                      :                            =                            (                                       w                               1                                      ,                                       w                               2                                      ,                            ⋯                             ,                                       w                               T                                      )                                  W = w^{T} := (w_{1}, w_{2}, \cdots, w_{T})                     W=wT:=(w1​,w2​,⋯,wT​)
那么该句子的连合概率如下:
                                         p                            (                                       w                               T                                      )                            =                            p                            (                                       w                               1                                      )                            ⋅                            p                            (                                       w                               2                                      ∣                                       w                               1                                      )                            ⋅                            p                            (                                       w                               3                                      ∣                                       w                               1                               2                                      )                            ⋯                            p                            (                                       w                               T                                      ∣                                       x                               1                                           T                                  −                                  1                                                 )                                  p(w^{T}) = p(w_{1}) \cdot p(w_{2}|w_{1}) \cdot p(w_{3}|w_{1}^{2}) \cdots p(w_{T}|x_{1}^{T-1})                     p(wT)=p(w1​)⋅p(w2​∣w1​)⋅p(w3​∣w12​)⋯p(wT​∣x1T−1​)
其中,模子参数为:
                                         p                            (                                       w                               1                                      )                            ,                            p                            (                                       w                               2                                      ∣                                       w                               1                                      )                            ,                            p                            (                                       w                               3                                      ∣                                       w                               1                               2                                      )                            ,                            ⋯                             ,                            p                            (                                       w                               T                                      ∣                                       w                               1                                           T                                  −                                  1                                                 )                                  p(w_{1}), p(w_{2}|w_{1}) , p(w_{3}|w_{1}^{2}), \cdots, p(w_{T}|w_{1}^{T-1})                     p(w1​),p(w2​∣w1​),p(w3​∣w12​),⋯,p(wT​∣w1T−1​)
根据贝叶斯公式可得:
                                         p                            (                                       w                               k                                      ∣                                       w                               1                                           k                                  −                                  1                                                 )                            =                                                   p                                  (                                               w                                     1                                     k                                              )                                                      p                                  (                                               w                                     1                                                   k                                        −                                        1                                                           )                                                       p(w_{k}|w_{1}^{k-1}) = \frac{p(w_{1}^{k})}{p(w_{1}^{k-1})}                     p(wk​∣w1k−1​)=p(w1k−1​)p(w1k​)​
根据大数定理可得:
                                         p                            (                                       w                               k                                      ∣                                       w                               1                                           k                                  −                                  1                                                 )                            ≈                                                   c                                  o                                  u                                  n                                  t                                  (                                               w                                     1                                     k                                              )                                                      c                                  o                                  u                                  n                                  t                                  (                                               w                                     1                                                   k                                        −                                        1                                                           )                                                       p(w_{k}|w_{1}^{k-1}) \approx \frac{count(w_{1}^{k})}{count(w_{1}^{k-1})}                     p(wk​∣w1k−1​)≈count(w1k−1​)count(w1k​)​
其中count体现统计词串在语料中的出现次数,当k比较大时,上述计算比较耗时。
2. N-gram 语言建模

N-gram模子是一种统计语言模子,用于推测给定文本中下一个词(或字符)的概率。该模子基于一个简化的假设:一个词(或字符)的出现概率只依赖于它前面的N-1个词(或字符),也就是n-1阶的马尔科夫假设。这里的N代表了模子考虑的上下文窗口大小,因此模子被称为N-gram。
                                                                                           p                                        (                                                       w                                           k                                                      ∣                                                       w                                           1                                                           k                                              −                                              1                                                                     )                                                                                                                       ≈                                        p                                        (                                                       w                                           k                                                      ∣                                                       w                                                           k                                              −                                              n                                              +                                              1                                                                          k                                              −                                              1                                                                     )                                                                                                                                                                                               ≈                                                                       count                                              (                                                               w                                                                   k                                                    −                                                    n                                                    +                                                    1                                                                  k                                                              )                                                                          count                                              (                                                               w                                                                   k                                                    −                                                    n                                                    +                                                    1                                                                                    k                                                    −                                                    1                                                                               )                                                                                                             \begin{aligned} p(w_{k}|w_{1}^{k-1}) &\approx p(w_{k}|w_{k-n+1}^{k-1}) \\ &\approx \frac{\text{count}(w_{k-n+1}^{k})}{\text{count}(w_{k-n+1}^{k-1})} \end{aligned}                     p(wk​∣w1k−1​)​≈p(wk​∣wk−n+1k−1​)≈count(wk−n+1k−1​)count(wk−n+1k​)​​
N-gram模子中的概率通常通过从大型文本语料库中计算词序列的频次来估计。具体来说,使用最大似然估计(Maximum Likelihood Estimation, MLE)计算每个N-gram的概率,这些概率可以通过简单地统计每个N-gram在语料库中出现的频次来估计。
该模子基于这样一种假设,第N个词的出现只与前面N-1个词相干,而与别的任何词都不相干,整句的概率就是各个词出现概率的乘积。这些概率可以通过直接从语料中统计N个词同时出现的次数得到,然后可以使用这些概率来计算给定上下文情况下下一个词或字符的概率。常用的是二元(Bi-gram)建模和三元(Tri-gram)建模。
比方,在一个句子"ChatGPT is a powerful language model"中,如果我们使用2-gram,那么句子可以被分成以下2-gram序列:[“ChatGPT is”, “is a”, “a powerful”, “powerful language”, “language model”]。假设我们有一个充足大的文本语料库,其中包罗很多句子。我们可以使用2-gram语言模子来计算给定一个词的前提下,下一个词出现的概率。如果我们想要推测句子中的下一个词,我们可以使用前面的一个词作为上下文,并计算每个大概的下一个词的概率。比方,在句子"ChatGPT is a"中,我们可以计算出给定上下文"ChatGPT is"下一个词"powerful"的概率。通过统计语料库中"ChatGPT is"背面是"powerful"的次数,并将其除以"ChatGPT is"出现的次数,我们可以得到这个概率。
2.1. N-gram 语言模子中的平滑处理

在统计语言模子中,平滑操纵是至关重要的一个步骤,主要目的是办理以下几个关键题目:
常见的平滑技术包括但不限于:
平滑不仅是统计语言模子构建中的一个必要步骤,也是提拔模子实用性和准确性的重要本领。
以2-gram为例,最大似然估计如下:
                                         p                            (                                       w                               i                                      ∣                                       w                                           i                                  −                                  1                                                 )                            =                                                   c                                  (                                               w                                                   i                                        −                                        1                                                                        w                                     i                                              )                                                      c                                  (                                               w                                                   i                                        −                                        1                                                           )                                                       p(w_i|w_{i-1}) = \frac{c(w_{i-1} w_i)}{c(w_{i-1})}                     p(wi​∣wi−1​)=c(wi−1​)c(wi−1​wi​)​
以上其实就是简单的计数,然后我们就要在这里去做平滑,其实就是减少分母为0的出现。拉普拉斯平滑如下:
                                                    p                               add                                      (                                       w                               i                                      ∣                                       w                                           i                                  −                                  1                                                 )                            =                                                   c                                  (                                               w                                                   i                                        −                                        1                                                                        w                                     i                                              )                                  +                                  δ                                                      c                                  (                                               w                                                   i                                        −                                        1                                                           )                                  +                                  δ                                  ∣                                  V                                  ∣                                                       p_{\text{add}}(w_i|w_{i-1}) = \frac{c(w_{i-1} w_i) + \delta}{c(w_{i-1}) + \delta |V|}                     padd​(wi​∣wi−1​)=c(wi−1​)+δ∣V∣c(wi−1​wi​)+δ​
一般地,                                   δ                              \delta                  δ取1,                                   ∣                         V                         ∣                              |V|                  ∣V∣体现词典库的大小。

基于二元模子的简单示例,包括数据预处理、构建模子、平滑处理以及基于模子举行推测。
  1. import collections
  2. class BigramLanguageModel:
  3.     def __init__(self, sentences: list):
  4.         """
  5.         初始化Bigram模型
  6.         :param sentences: 训练语料,类型为字符串列表
  7.         """
  8.         self.sentences = sentences
  9.         self.word_counts = collections.Counter()
  10.         self.bigram_counts = collections.defaultdict(int)
  11.         self.unique_words = set()
  12.         
  13.         # 预处理数据:分词并合并所有句子
  14.         words = ' '.join(sentences).split()
  15.         for w1, w2 in zip(words[:-1], words[1:]):
  16.             self.word_counts[w1] += 1
  17.             self.word_counts[w2] += 1
  18.             self.bigram_counts[(w1, w2)] += 1
  19.             self.unique_words.update([w1, w2])
  20.    
  21.     def laplace_smooth(self, delta: float = 1.0):
  22.         """
  23.         拉普拉斯平滑
  24.         :param delta: 平滑因子,默认为1.0
  25.         """
  26.         V = len(self.unique_words)  # 词汇表大小
  27.         self.model = {}
  28.         for w1 in self.unique_words:
  29.             total_count_w1 = self.word_counts[w1] + delta*V
  30.             self.model[w1] = {}
  31.             for w2 in self.unique_words:
  32.                 count_w1w2 = self.bigram_counts.get((w1, w2), 0) + delta
  33.                 self.model[w1][w2] = count_w1w2 / total_count_w1
  34.                
  35.     def generate_text(self, start_word: str, length: int = 10) -> str:
  36.         """
  37.         生成文本
  38.         :param start_word: 文本起始词
  39.         :param length: 生成文本的长度
  40.         :return: 生成的文本字符串
  41.         """
  42.         if start_word not in self.model:
  43.             raise ValueError(f"Start word '{start_word}' not found in the model.")
  44.         sentence = [start_word]
  45.         current_word = start_word
  46.         
  47.         for _ in range(length):
  48.             next_word_probs = self.model[current_word]
  49.             next_word = max(next_word_probs, key=next_word_probs.get)
  50.             sentence.append(next_word)
  51.             current_word = next_word
  52.             
  53.         return ' '.join(sentence)
  54. # 示例使用
  55. corpus = [
  56.     "ChatGPT is a powerful language model for multi task",
  57.     "ChatGPT is a powerful language model",
  58.     "ChatGPT can generate human-like text",
  59.     "ChatGPT is trained using deep learning",
  60. ]
  61. model = BigramLanguageModel(corpus)
  62. model.laplace_smooth()
  63. generated_text = model.generate_text('ChatGPT', 5)
  64. print(generated_text)  # ChatGPT is a powerful language model
复制代码
3. 语言模子评估

准确率作为语言模子的评估指标没有太多意义,语言是开放的序列推测题目,给定前面的文本,下一个词的大概性是非常多的,因此准确率值会非常低。
作为替换,应该在模子保留数据(held-out data)上,计算其对应的似然性(取平均值以消除长度影响)来评估语言模子。对数似然(log likelihood,LL)计算如下:
                                         LL                            (                            W                            )                            =                                       1                               n                                                 ∑                                           i                                  =                                  1                                          n                                      log                            ⁡                            P                            (                                       w                               i                                      ∣                                       w                               1                                      ,                            ⋯                             ,                                       w                                           i                                  −                                  1                                                 )                                  \text{LL}(W) = \frac{1}{n} \sum_{i=1}^n \log P(w_i|w_1, \cdots, w_{i-1})                     LL(W)=n1​i=1∑n​logP(wi​∣w1​,⋯,wi−1​)
   保留数据:指在练习语言模子时,专门保留一部门数据不到场练习,用作评估模子性能的数据集。这确保了评估数据独立于练习数据,可以或许真实反映模子在新数据上的泛化本事。
  困惑度(Perplexity,PPL)是评价语言模子质量的一个重要指标,可以或许更好地体现语言模子对句子流通性、语义连贯性的建模本事。困惑度是指数情势的平均负对数似然,计算如下:
                                         PPL                            (                            W                            )                            =                            exp                            ⁡                            (                            NLL                            (                            W                            )                            )                            =                            exp                            ⁡                            (                            −                            LL                            (                            W                            )                            )                                  \text{PPL}(W) = \exp (\text{NLL}(W) ) = \exp (- \text{LL}(W) )                     PPL(W)=exp(NLL(W))=exp(−LL(W))
   对数似然:给定语料库数据,对数似然衡量模子为这些数据赋予的概率的对数值。对数似然越高,模子对数据的建模本事越强。
  负对数似然:由于对数似然值通常是个负值,取负号得到正值更利于分析比较。
  平均负对数似然:将负对数似然值加总后除以数据长度(如词数),得到平均负对数似然。这样可以消除数据长度的影响,更公平地比较差别模子。
  指数情势:将平均负对数似然值做指数运算,得到Perplexity值。由于似然自己很小,对数似然为负值,做指数能使结果值落在较合理的范围。
  困惑度本质上反映了模子对数据的平均怀疑程度。值越低,说明模子对数据的建模质量越高、不确定性越小。通常良好模子的困惑度值在10-100之间,值越接近1越好。
4. 神经语言模子

神经语言模子(Neural Language Model, NLM)是一种使用神经网络来建模和生成自然语言序列的模子。相比传统的统计语言模子(如n-gram模子),神经语言模子具有以下几个主要特点:
常见神经语言模子有基于RNN、LSTM、Transformer等差别网络架构,并广泛应用于语言建模、呆板翻译、对话系统等自然语言处理任务中。神经语言模子弥补了传统模子的不足,极大地推进了语言模子的发展,但也面临练习资源需求大、解释性较差等新的挑战。
5. 循环神经网络

前馈神经网络(Feedforward NNs)无法处理可变长度的输入,特性向量中的每个位置都有固定的语义。使用传统前馈神经网络作为语言模子时的主要缺陷和范围性如下:
为了办理这个题目,出现了诸如循环神经网络(RNN)、长短期影象网络(LSTM)等可以或许更好地处理序列输入的神经网络架构。
5.1. Vanilla RNN

循环神经网络是一种可以接受变长输入和产生变长输出的网络架构类型,这与尺度的前馈神经网络形成对比。我们也可以考虑变长的输入,比如视频帧序列,并盼望在该视频的每一帧上都做出决策。

对于循环神经网络,我们可以在每个时间步应用递推公式来处理向量序列:
                                                    h                               t                                      =                                       f                               W                                      (                                       h                                           t                                  −                                  1                                                 ,                                       x                               t                                      )                                  h_t = f_W(h_{t-1}, x_t)                     ht​=fW​(ht−1​,xt​)
对于简单的 Vanilla 循环神经网络来说,计算公式如下:
                                                                                           h                                        t                                                                                                                       =                                        tanh                                        ⁡                                        (                                                       W                                                           h                                              h                                                                                    h                                                           t                                              −                                              1                                                                     +                                                       W                                                           x                                              h                                                                                    x                                           t                                                      +                                                       b                                           h                                                      )                                                                                                                            y                                        t                                                                                                                       =                                                       W                                                           h                                              y                                                                                    h                                           t                                                      +                                                       b                                           y                                                                                              \begin{aligned} h_t &= \tanh (W_{hh} h_{t-1} + W_{xh} x_t + b_h) \\ y_t &= W_{hy} h_t + b_y \end{aligned}                     ht​yt​​=tanh(Whh​ht−1​+Wxh​xt​+bh​)=Why​ht​+by​​

  1. import numpy as np
  2. np.random.seed(0)
  3. class RecurrentNetwork(object):
  4.     """When we say W_hh, it means a weight matrix that accepts a hidden state and produce a new hidden state.
  5.     Similarly, W_xh represents a weight matrix that accepts an input vector and produce a new hidden state. This
  6.     notation can get messy as we get more variables later on with LSTM and I simplify the notation a little bit in
  7.     LSTM notes.
  8.     """
  9.     def __init__(self):
  10.         self.hidden_state = np.zeros((3, 3))
  11.         self.W_hh = np.random.randn(3, 3)
  12.         self.W_xh = np.random.randn(3, 3)
  13.         self.W_hy = np.random.randn(3, 3)
  14.         self.Bh = np.random.randn(3,)
  15.         self.By = np.random.rand(3,)
  16.     def forward_prop(self, x):
  17.         # The order of which you do dot product is entirely up to you. The gradient updates will take care itself
  18.         # as long as the matrix dimension matches up.
  19.         self.hidden_state = np.tanh(np.dot(self.hidden_state, self.W_hh) + np.dot(x, self.W_xh) + self.Bh)
  20.         return self.W_hy.dot(self.hidden_state) + self.By
  21.    
  22.    
  23. input_vector = np.ones((3, 3))
  24. rnn = RecurrentNetwork()
  25. # Notice that same input, but leads to different ouptut at every single time step.
  26. print(rnn.forward_prop(input_vector))
  27. print(rnn.forward_prop(input_vector))
  28. print(rnn.forward_prop(input_vector))
复制代码
5.2. LSTM

虽然 Vanilla RNN 在处理序列数据方面具有一定的本事,但它在长期依赖性建模方面存在一些挑战。长短期影象网络(Long Short Term Memory, LSTM )是一种特殊类型的 RNN,通过引入细胞状态(cell state)和门控机制来办理长期依赖性题目。以下是 LSTM 相对于 Vanilla RNN 的一些优点和特点:
LSTM 相对于 Vanilla RNN 具有更强的影象和建模本事,可以或许更好地处理长期依赖性和序列任务。它通过引入细胞状态和门控机制,办理了 Vanilla RNN 在处理长序列时出现的梯度消散和梯度爆炸题目。

LSTM 计算过程如下:
                                                                                           f                                        t                                                                                                                       =                                        σ                                        (                                                       W                                                           h                                              f                                                                                    h                                                           t                                              −                                              1                                                                     +                                                       W                                                           x                                              f                                                                     x                                        +                                                       b                                           f                                                      )                                                                                                                            i                                        t                                                                                                                       =                                        σ                                        (                                                       W                                                           h                                              i                                                                                    h                                                           t                                              −                                              1                                                                     +                                                       W                                                           x                                              i                                                                     x                                        +                                                       b                                           i                                                      )                                                                                                                            o                                        t                                                                                                                       =                                        σ                                        (                                                       W                                                           h                                              o                                                                                    h                                                           t                                              −                                              1                                                                     +                                                       W                                                           x                                              o                                                                     x                                        +                                                       b                                           o                                                      )                                                                                                                            c                                        t                                                                                                                       =                                                       f                                           t                                                      ⊙                                                       c                                                           t                                              1                                                                     +                                                       i                                           t                                                      ⊙                                        tanh                                        ⁡                                        (                                                       W                                                           g                                              x                                                                     x                                        +                                                       W                                                           g                                              h                                                                                    h                                                           t                                              −                                              1                                                                     +                                                       b                                           g                                                      )                                                                                                                            h                                        t                                                                                                                       =                                                       o                                           t                                                      ⊙                                        tanh                                        ⁡                                        (                                                       c                                           t                                                      )                                                                                \begin{aligned} f_t &= \sigma(W_{hf} h_{t-1} + W_{xf} x + b_f) \\ i_t &= \sigma(W_{hi} h_{t-1} + W_{xi} x + b_i) \\ o_t &= \sigma(W_{ho} h_{t-1} + W_{xo} x + b_o) \\ c_t &= f_t \odot c_{t_1} + i_t \odot \tanh(W_{gx} x + W_{gh} h_{t-1} + b_g) \\ h_t &= o_t \odot \tanh(c_t) \end{aligned}                     ft​it​ot​ct​ht​​=σ(Whf​ht−1​+Wxf​x+bf​)=σ(Whi​ht−1​+Wxi​x+bi​)=σ(Who​ht−1​+Wxo​x+bo​)=ft​⊙ct1​​+it​⊙tanh(Wgx​x+Wgh​ht−1​+bg​)=ot​⊙tanh(ct​)​
其中,                                             f                            t                                       f_t                  ft​体现遗忘门,控制影象的遗忘程度;                                             i                            t                                       i_t                  it​体现输入门,控制信息写入状态单元的程度;                                             o                            t                                       o_t                  ot​体现输出门,控制状态单元的暴露程度;                                             c                            t                                       c_t                  ct​体现状态单元,负责内部影象;                                             h                            t                                       h_t                  ht​体现隐藏单元,负责对外暴露信息。

  1. import numpy as np
  2. np.random.seed(0)
  3. class LSTMNetwork(object):
  4.     def __init__(self):
  5.         self.hidden_state = np.zeros((3, 3))
  6.         self.cell_state = np.zeros((3, 3))
  7.         self.W_hh = np.random.randn(3, 3)
  8.         self.W_xh = np.random.randn(3, 3)
  9.         self.W_ch = np.random.randn(3, 3)
  10.         self.W_fh = np.random.randn(3, 3)
  11.         self.W_ih = np.random.randn(3, 3)
  12.         self.W_oh = np.random.randn(3, 3)
  13.         self.W_hy = np.random.randn(3, 3)
  14.         self.Bh = np.random.randn(3,)
  15.         self.By = np.random.randn(3,)
  16.     def forward_prop(self, x):
  17.         # Input gate
  18.         i = sigmoid(np.dot(x, self.W_xh) + np.dot(self.hidden_state, self.W_hh) + np.dot(self.cell_state, self.W_ch))
  19.         # Forget gate
  20.         f = sigmoid(np.dot(x, self.W_xh) + np.dot(self.hidden_state, self.W_hh) + np.dot(self.cell_state, self.W_fh))
  21.         # Output gate
  22.         o = sigmoid(np.dot(x, self.W_xh) + np.dot(self.hidden_state, self.W_hh) + np.dot(self.cell_state, self.W_oh))
  23.         # New cell state
  24.         c_new = np.tanh(np.dot(x, self.W_xh) + np.dot(self.hidden_state, self.W_hh))
  25.         self.cell_state = f * self.cell_state + i * c_new
  26.         self.hidden_state = o * np.tanh(self.cell_state)
  27.         return np.dot(self.hidden_state, self.W_hy) + self.By
  28. def sigmoid(x):
  29.     return 1 / (1 + np.exp(-x))
  30. input_vector = np.ones((3, 3))
  31. lstm = LSTMNetwork()
  32. # Notice that the same input will lead to different outputs at each time step.
  33. print(lstm.forward_prop(input_vector))
  34. print(lstm.forward_prop(input_vector))
  35. print(lstm.forward_prop(input_vector))
复制代码

LSTM 可以一定程度上缓解梯度消散题目,但对于非常长的序列或复杂的任务,仍然存在一定的限制。除了梯度消散题目,LSTM 在处理序列时也存在性能上的限制。由于它们是渐渐处理序列的,无法充实使用并行计算的上风。对于长度为 n 的序列,LSTM 需要执行 O(n) 的非并行操纵来举行编码,导致速率较慢。
为了降服这些限制,提出了 Transformer 模子作为办理方案。Transformer 可以扩展到处理数千个单词的序列,并且可以或许并行计算。它引入了自留意力机制和位置编码,使得模子可以或许同时关注序列中差别位置的信息,并且可以或许以高效的方式对输入举行编码。这使得 Transformer 在处理长序列和大规模数据时具有上风,并且在呆板翻译和自然语言处理等范畴取得了显著的乐成。

Understanding LSTM Networks
Vanilla Recurrent Neural Network
LSTM Recurrent Neural Network

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4