神经网络语言模型(前馈神经网络语言模型)


本文一共回答了六个问题,这六个问题可以分为两个部分:

  1. 神经网络基本原理
  2. 神经网络+语言模型 = 神经网络语言模型

第一部分:

  • 一、什么是神经网络?
  • 二、神经网络的基本结构是什么?
  • 三、神经网络为什么能解决问题?
  • 四、卷积神经网络跟经典的神经网络有什么差异?

第二部分:

  • 五、神经网络怎么在语言模型层面进行应用?
  • 六、为什么会想到用神经网络来构件语言模型?

什么是神经网络?

神经网络是一种模拟人脑神经元连接结构的机器学习模型。

如果之前听过什么输入层、隐藏层、输出层,那这些概念就是来自神经网络。
如果没听过,那就简单理解神经网络就是用一堆矩阵来模拟某一个连续函数,我们可能不知道这个函数是长什么样的,但是我们猜有这么一个函数F(X),当我们给定输入X,F(X)有一个输出G,G就是神经网络根据输入预测的输出。

神经网络的基本结构是什么?

神经网络的结构包括:

  • 层数(几层隐藏层)
  • 每层的神经元数目
  • 相邻层之间神经元相连的权重
  • 每层使用的激活函数

输入层

接受原始数据(如图像像素、音频、文本向量)

所谓的输入层,就是将输入数据用离散的数据表示,为什么需要离散,因为现实世界是连续的,有些概念是抽象的,例如文字的“你”、“我”,我们告诉计算机说输入一个“你”、“我”,实际上也是将“你”、“我”变成一堆010101010…,我理解这就是离散的过程,也就是输入层的作用:将现实中的数据以向量/矩阵等计算机可以进行运算的格式进行表示。

隐藏层

通过加权和+激活函数提取特征

隐藏层很"简单",就是外界数据通过输入层之后,变成了一堆计算机可以运算的数据,隐藏层对数据刷刷一堆操作,最后输出到输出层。

输出层

输出预测结果

输出层可以简单理解为函数的输出值,只不过输出值可以用输出层的节点来组合表示。最简单的是如果F(X)的结果只可能是0~9十个数,那么输出层的节点个数就可以设为10。
基本神经网络示意图

神经网络为什么能解决问题?

通用近似定理

依据理论为“通用近似定理”,经典论述为:

一个具有足够数量隐藏单元、非线性激活函数 的前馈神经网络,可以以任意精度逼近定义在紧致空间上的任意连续函数。
换句话说,只要网络足够大,它就能学会从输入到输出的任意连续映射。

所以有时候我们会听到类似“算的不够准?再加节点!再加一层!”的说法。

一些思考】我个人理解这个过程有点像多项式拟合一个连续函数,我只要把多项式的项数加的够多,总能拟合出来的,不够准确?那就再加一项!

为什么需要权重和偏置?为什么需要激活函数?

首先是权重和偏置,他们两是线性的,是根据上一层的数据简单的线性组合。例如输入是In0、In1、In2,想要知道他们对P0结果的贡献,
r e s 0 = I n 0 ∗ W 00 + I n 1 ∗ W 10 + I n 2 ∗ W 20 + B 0 res0 = In0 * W00 + In1 * W10 + In2 * W20 + B0 res0=In0W00+In1W10+In2W20+B0

这里使用res0代表他不是最终值,而只是一个中间值,Wxx代表权重,B0代表偏置,这里只是想要表达一个大概的计算流程

可以看出来,都是线性组合,如果只有权重和偏置,没有激活函数,神经网络是一个线性变换堆叠(即矩阵乘法),只能拟合线性关系。为了求得可以拟合的更多结果,需要加入激活函数
加入非线性激活函数(如 ReLU、Sigmoid、Tanh)后,网络就可以表达更复杂、非线性的函数
激活函数有很多种,这里随便放一张图来表示激活函数的样式
A c t F u n c ( r e s 0 ) 【 A c t F u n c 代表激活函数】 ActFunc(res0) 【ActFunc代表激活函数】 ActFunc(res0)ActFunc代表激活函数】
激活函数

【一些思考】我对权重、偏置和激活函数的理解就是:线性+非线性=非线性
通过激活函数引入非线性,使得神经网络可以表达非线性的函数,因为生活中需要用到神经网络来解决的问题基本都是非线性的。
而神经网络不同层之间节点的权重连接,以及在节点上的偏置,其实就是加入了更多排列组合后引入了更多的可能变化,通过引入变化来使得神经网络更能描述复杂的事物。

权重是如何确定的?

一个神经网络想要算得准,那就需要进行调整,但是对于神经网络来说,网络结构一旦确定下来,可以调整的空间就局限在权重偏置了。

为什么不调整节点数量激活函数?也有,这样相当于重新确定一个神经网络算法,我们从控制变量法的思想出发,先考虑权重偏置的改变。

下边为了方便说明,我就统一用权重来表示权重+偏置

既然要确定权重的值,那么就需要考虑一个问题:
我为什么要选择这个值作为权重具体的参数值,而不是那个值?

也就是需要一个评价标准来评价权重的选择,这个标准就是:
最小化损失函数输出,即网络预测值和真实值之间的误差。
说人话就是,我选择这一批权重值能猜的准。

借用3blue1brown的比喻:
想象一个“有很多旋钮的机器”,你要不断调整这些旋钮(即权重),直到输出结果最接近你想要的答案。

下边有两种选择权重的方法:

1. 穷举

对应的权重是要调高,还是要调低,最简单的办法就是穷举!
毕竟只要给足够长的时间,一只猴子也能在打字机上打出一本《哈姆雷特》(狗头)。

不过这种方法用的比较少,因为在参数比较多的情况下,我们很难说运气好刚好找到一组合适的参数,加上人类的生命目前还是有限的,我们比较期望能够有一个方法来指导我们进行,尽快找到合适的权重。

2. 反向传播

反向传播是一种使用链式法则(Chain Rule)计算误差梯度的方法。

主要步骤:

假定神经网络很简单:
【输入x】—w1(权重)----【隐藏层】----w2(权重)—【输出】

  1. 前向传播
    • 将输入数据通过神经网络,得到预测输出。

这个正向的过程可以是:

  1. x*w1 = z1,作为隐藏层的中间结果
  2. σ ( z 1 ) = a 1 \sigma(z1) = a1 σ(z1)=a1,表示进行激活
  3. a1 * w2 = z2,作为输出层的中间结果
  4. σ ( z 2 ) = a 2 \sigma(z2) = a2 σ(z2)=a2,a2表示激活后输出层的最终结果,也被称为预测值 y pred y_{\text{pred}} ypred
  1. 计算损失
    • 使用损失函数 L ( y true , y pred ) L(y_{\text{true}}, y_{\text{pred}}) L(ytrue,ypred) 评估预测的好坏。
  2. 反向传播计算梯度
    • 对每一层的参数求偏导(链式法则)。

L是a2的函数,a2是z2的函数,z2是a1的函数,a1是z1的函数,z1是w1的函数,但是只要每一层都有表达式关系,我们就可以通过链式法则求得偏导数:
∂ L / ∂ w 1 = ∂ L / ∂ a 2 ⋅ ∂ a 2 / ∂ z 2 ⋅ ∂ z 2 / ∂ a 1 ⋅ ∂ a 1 / ∂ z 1 ⋅ ∂ z 1 / ∂ w 1 ∂L/∂w1 = ∂L/∂a2 ⋅ ∂a2/∂z2 ⋅ ∂z2/∂a1 ⋅ ∂a1/∂z1 ⋅ ∂z1/∂w1 L/w1=L/a2a2/z2z2/a1a1/z1z1/w1

  1. 参数更新
    • 使用梯度下降等优化器来更新参数。
能使用梯度来优化参数的原因
  1. 误差L跟神经网络中可以调节的权重W有关,L可以表示为W和输入X的函数
  2. 因此 ∂ L ∂ W \frac{∂L}{∂W} WL就能得到L对参数W的梯度,按照梯度的定义,梯度是函数值增长最快的方向,因此梯度的反方向,就是误差L降低最快的方向
  3. 函数是复杂的,我们得到的方向只是在当前这个局部点的最快下降方向,因此为了避免“走过头”,我们还需要选择“步长” : η \eta η η \eta η同时也被称为“学习率”。
  4. 最终更新后的权重就是: W n e w = W o l d − ∂ L ∂ W ∗ η W_{new} = W_{old} - \frac{∂L}{∂W} * \eta Wnew=WoldWLη

一些思考】 反向传播为什么叫反向传播?因为他是通过向前传播计算之后,欸,发现算出来的值跟真实值(这里的真实值指的是训练材料给的值)有误差,就通过这个误差,把误差当成一个输入,反着来更新权重。
问题是我要怎么用这个误差,让误差来指导我更新参数,使得下一次算的时候能更贴近真实值?
就想到了L可以表示为w的函数,那么我通过求梯度,梯度的反向是函数值降低最快的方向,通过叠加梯度和步长,更新权重w,来力求让L趋于0。

这样通过反复迭代,也就能得到一个比较好的权重参数了。

卷积神经网络跟经典的神经网络有什么差异?

卷积神经网络采用了“滑动窗口”和参数共用的概念,专业点的话为

使用一个小窗口(卷积核)在图像上滑动,对局部区域执行加权求和(即卷积运算),并使用相同的权重(权重共享)。

挖个坑,后续再用一个独立的章节单独说明。

神经网络怎么在语言模型层面进行应用?

本质上,神经网络语言模型和N-Gram一样,都是预测下一个词的概率,因为神经网络是用来拟合函数的,这句话也可以表述为:

用神经网络拟合一个“下一个词的概率函数”

输入层的不同

神经网络的输入层接受的是数字,有些的场景下可以直接提供离散的数值,例如图像/音频等,可以直接用像素点的值或者频率。
但是神经网络能接受的其实是离散的数字,所以需要将输入的词转化为向量,便于后续操作,这一步称之为嵌入

如何将词拼接成语句作为输入?

通过嵌入我们只能获取单个词的词向量,但是作为神经网络语言模型的输入,当个词肯定是不够的,起码一定量的词组成的语句才能很好的预测下一个词,毕竟“我打你”和“你打我”是不一样的,虽然他们组成的词是一样的。
参照 N-Gram 的建模方式,为了将语句中的顺序信息传入神经网络语言模型,前馈神经网络语言模型(Feedforward Neural Network Language Model) 对输入层的处理采用了嵌入+向量拼接的方式:

每个词先通过词嵌入层(Embedding Layer)转化为嵌入向量,例如:

“我” → v_我 = [0.2, 0.1, -0.3, 0.7]

“打” → v_打 = [-0.1, 0.3, 0.8, 0.2]

然后将这些向量按词语顺序拼接成一个大向量:

[v_我 ; v_打] = [0.2, 0.1, -0.3, 0.7, -0.1, 0.3, 0.8, 0.2]

这个拼接后的向量作为输入层的输入传入神经网络。因此,必须先确定上下文窗口大小 N(例如使用 N-1 个词预测下一个词),才能确定输入层的维度,即 N-1 个词 × 每个词的嵌入维度。

不过,这种方式也存在缺陷:

  1. 输入的上下文长度是固定的,不能适应变长句子;
  2. 难以建模长距离依赖;
  3. 对于超出窗口的上下文信息无法捕捉。
    可以发现这些限制和N-Gram是很像的,因为前馈神经网络语言模型输入层的节点数量跟N-Gram依据前N-1个词预测下一个词的N-1数量是成比例的。(假设是依靠前两个词预测下一个词,嵌入向量的长度是4,前馈神经网络语言模型输入层的节点数量就是4*2 = 8)
    这些限制正是后续引入循环神经网络(RNN)和 Transformer 架构的动因。

如何确定词要转化的向量值是多少?

  1. 第一步:生成随机的向量值
  2. 第二步:正向传播
  3. 第三步:计算损失函数
  4. 第四步:反向传播更新参数
    不过在反向传播更新参数的时候,神经网络一般不会更新到入参,因为入参本来就是确定的。
    但是!“嵌入”流程一开始生成的向量值是随机的,所以他也是可以进行更新的!

【一些思考】输入层的入参也是损失函数参数的一部分,因此也是能计算随时函数L与输入层参数x的偏导数,进行通过梯度进行更新。只是通常神经网络的输入都是确定的,总不能更新确定的东西吧(狗头)。但是神经网络语言模型不一样!可以认为确定的是“词”,但是“词”到神经网络中间的一层“嵌入”,也可以认为是一个函数变换的过程,因此也是能够进行更新的,更新“词”到对应“嵌入向量值”的过程,就相当于更新神经网络权重的过程。
这里有一个比较好的比喻:“嵌入向量”是”“词”在高维空间中的坐标点,因为我们一开始不知道这个坐标在哪,只能随便猜,但是通过反向转播,我们让这个坐标更加的准确。

嵌入矩阵

嵌入矩阵的概念是从嵌入向量引入的,在做神经网络语言模型的时候,首先需要确认词汇表的大小,也就是我需要认识多少个“词”,这样我可以给每一个词一个单独的嵌入向量,也可以在输出的时候,给出每一个词的概率,而这都需要知道“词汇表的大小”。
嵌入矩阵说白了就是一个向量的向量,
e m b e d d i n g ( w i ) = E [ i ] embedding(w_i) = E[i] embedding(wi)=E[i]
其中 E E E是嵌入矩阵, i i i是词汇表中第 i i i个词, E [ i ] E[i] E[i]也就是词汇表中第 i i i个词的嵌入向量。

输出层的不同

正如一开始所言,神经网络语言模型希望得到的结果是预测下一个词是什么, 如何表示这个结果呢?我们可以将输出层的大小设置为词汇表的大小,这样才能输出所有词的概率。

softmax

因为输出层的结果不一定是0~1之间的值,所以需要有一个办法将结果转化为概率。
softmax ( z i ) = e z i ∑ j = 1 K e z j \text{softmax}(z_i) = \frac{e^{z_i}}{\sum_{j=1}^{K} e^{z_j}} softmax(zi)=j=1Kezjezi
其中, z i , z j z_i,z_j zi,zj代表输出第i, j个的值。
反向传播就可以通过这个概率来计算。

【一些思考】可以将softmax计算出概率的过程看作在输出层节点上的“激活函数”,虽然不太像哈,激活函数只需要这个节点的信息,但是softmax需要所有节点的信息参与计算。

所以,通过神经网络搭建语言模型的过程中,神经网络语言模型多了嵌入计算词向量的过程和softmax计算概率的过程,而计算词向量的过程是一个可以学习的过程,词向量或者说嵌入向量更像是词在高位空间的一个映射,因此这种映射关系是可以学习的;而softmax计算出的概率,又可以跟训练材料的实际输出进行对比,计算损失函数,从而通过反向传播来更新神经网络模型的参数。

为什么会想到用神经网络来构件语言模型?

使用神经网络搭建语言模型的核心动机在于:我们认为语言可以被表示为一种连续的分布式表示,而神经网络恰好擅长拟合这类复杂的函数关系。

换句话说,我们希望构建一个预测函数,能够根据已有的上下文来预测下一个词。这个函数本质上是非线性、高维、难以显式表达的,但神经网络正好能够在数据驱动下自动学习到这种“看不见摸不着”的映射。

用ai的话来总结,就是

  1. 语言的本质可以用连续空间来建模
    各个词之间不是孤立的,是有联系的。通过词嵌入(Word Embedding),我们将词映射到一个连续的高维向量空间,从而可以使用向量运算表达语义关系;
    例如:king - man + woman ≈ queen 这样的类比关系。
  2. 语言可以被看作是“序列”的建模问题
    也就是下一词的出现和前面的上下文息息相关
  3. 神经网络具有强大的表示与泛化能力
    能构建“预测函数”,这个比N-Gram强多了,N-Gram只能计算已经出现过的组合,但是神经网络语言模型训练好之后就算是没出现过的组合,也能够进行预测,因为他不是通过简单的概率计算来做的。

一些思考】我们使用神经网络搭建语言模型,是因为我们认为语言可以嵌入到一个连续空间中,并通过可学习的函数来预测词的分布。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值