key words:simple neuron ; multilayer;feedforward;non-linear;
(artificial)neural network
inspired by the biological neural networls in brains
生物细胞处理信息后,从轴突中输出若干个信号
受神经网络和生物神经元的启发,设计出由计算机能够计算的人工神经元:接受n个数作为输入,然后产生一个数的输出,它由参数w和b以及激活函数f来构成
a neuron is a computational unit with n inputs and 1 output and parameters w,b
n inputs(w)各权重 +bias(b)偏置权重=output
对于多个output:此时b成为一个向量,w为一个矩阵
然后依次叠加每一层,进行前向计算,最终得output
Q:一个神经元在输出结果之前,会经过一个非线形的激活函数,那么这个激活函数时干什么用的呢?
假设神经网络中它并没有激活函数,即,它每一层进行的操作只对上一层进行输出,应用一个线性变换。假设有2层,分别进行得到h1和h2:
h1=w1x+b1 ; h2=w2h1+b2 ---》h2 =w2w1x+w2b1+b2
此时发现,这两个神经网络层其实可以表示为一层,此时他的权重矩阵是w2乘w1,偏置是w2b1+b2。
如果神经网络只存在这样的线形变换的话,那么多层神经网络其实可以被转化成当成的神经网络,即多层神经网络和单层神经网络他的表达是一致的,因此我们需要引入非线形激活函数,防止多层坍塌成单层,并且可以增加他的表达能力,来拟合更复杂的函数。
常见非线形函数:
将一个从负无穷到正无穷之间的数,转化为0~1的数、-1~1的数
对于正数输入依然为原来的正数,对于负数输入转化为0
通过添加多个若干的隐层,我们可以提高表达能力
Q:怎样得到我们想要的输出结果呢?
我们需要添加网络的最后一层,即输出层:output layer
(1)对于回归问题:linear output线性层输出层(如:训练这个神经网络去预测一个具体的连续的一个值)
(2)解决二分类的问题:sigmoid输出层,先得到一个线性值,在此基础上,运用sigmoid激活函数,把其输出压到0~1之间(如:表示这个模型预测当前输入属于某一个类的概率y,和属于另一个类的概率1-y)
(3)解决多分类问题:softmax输出层,即,分类者的这个类别的数量大于2的情况(如:解决一个3分类问题,就让它设置3个输出)首先,我们对最后一个隐层去应用一个普通的一个线性层,得到输出z,我们就可以把最后这个隐层去通过线性变化,先变换成我们想要的一个维度,即类别数量。之后我们对z中的每一个元素去计算这个z的e的z次方,把其转化为e的多少次方,就可以把每一个维度的z的这个值,无论他是真的还是负的,都把它映射成一个正的值,再把这些正的值去除以他们的和,这样输出层每一个维度的值加起来的和就会为1(保证为正值,其加起来为1),得到的是不同类别的一个概率分布,因此我们可以从输出层去判断,我们的输出属于某一个类别的概率。
summary:
单个神经元,构成一层的神经网络
然后堆叠这些层,可以得到多层的神经网络
其中每个神经元的非线性激活函数,可以用于让神经网络来表达更复杂的内容
最终为了得到想要的输出形式,我们去应用对应的输出层
objective; gradients; backpropogation;
想要训练一个神经网络,我们需要先去设定一个训练目标,依据目标对此进行调整
假如:
情况一:
我们有若干条训练数据,其中的某个输入为某个电脑的一些属性,比如他的一些配置之类的,然后我们希望是,模型能够预测出电脑的价格y。这个问题为回归问题,即希望我们的神经网络去根据输入数据来拟合一个具体的值。
在这个情况下,我们可以以降低所谓的均方差来作为我们的训练目标,具体为:对于每一条的训练数据我们计算真实价格的yi和模型预测的价格F(xi)之间的一个差的平方,显然,这个值越小,说明我们的神经网络学习的越准确,因此我们的目标是最小化这个值,这个均方差称为损失函数loss
我们训练神经网络的目标就是去减小所谓的损失函数的值
情况二:
文本分类任务:输入数据可能是一段文本,我们希望模型去预测一个例如:情感标签这样的东西,它可以是正面、负面或者中性,这些情感标签就可以用比如说y=123来表示,这个时候我们通常希望以最小化的交叉熵cross-entropy为我们的训练目标,此时的交叉熵cross-entropy就为我们的损失函数loss
交叉熵cross-entropy是衡量模型正确分类的负log的一个概率。如这里正确的标签是训练中提供的标签yi,那么我们拿到这个模型去预测出这条数据xi他是属于这个yi这个类别的情感的概率,然后去负log来计算出这条数据的交叉熵
交叉熵是如何计算的?
左侧是模型,经过softmax输出层计算出结果,得到一个概率分布,分别是3个类别的概率,我们在训练集中具有一个标签y来表示这段文本正确的类别,如果第一个类别正确,则他的损失值loss为0.74,依次计算,损失值越小,则说明我们的模型它预测的也就越准确
为了达到我们的训练目标,通常我们是希望最小化某一个损失函数
Q:我们如何去最小化一个损失函数呢?
在神经网络中我们通常会采用:梯度下降法。我们希望把整个这个优化步骤拆分成若干个步骤,然后每一步我们去缩小这个损失函数一点儿
那么,我们要怎么去调整参数,才能够在每一步去缩小这个损失函数呢?
方式:首先要求损失函数对于这个模型参数的梯度,它代表了这个参数进行单位大小的改动,损失函数它变化最快的一个方向,我们顺着这个方向向前走一步,去应用一个对模型参数的一个小的变化,我们就可以去降低一点点损失的函数,这就好比我们去爬一座山,我们去选择最陡峭的一步去迈出脚,这样可以可能让我们爬的快一点。由于我们要对损失函数去降低,因此我们爬的方向其实是这个梯度的一个反方向,因此前面添加一个负号。
我们沿着这个方向走一小步到底有多大?是有里面的阿尔法参数来决定的,可以被称作learning rate或者叫学习率。
这就是通过梯度下降进行学习的一个基本思想
为计算梯度下降,我们需要求到损失函数对于每个参数的梯度
关于梯度计算:
给出一个f,有n个输入,最后有一个标量的输出,这可以对应到我们在计算神经网络中计算损失函数的那一步,在那一步我们的输入可能是有模型的这个输出以及真实的标签,然后最后得到的是我们的损失函数,它通常是一个标量值,我们可以对写参数求梯度,最终得到一个大小为输入大小的这么一个向量,向量中的每一个维度是对于输入中对应维度的一个偏导数
另一种情况:n个输入,m个输出,m个具有n个输入单个输出的函数,即m个神经元构成的一层神经网络,我们让这个m个输出对于n个输入去求微分,得到的就是一个mxn大小的jacobian矩阵。
jacobian矩阵:第i行第j列:第i个输出对第j个输入的偏导数。它每一行对应的就是一个输出函数,它对于所有n个输入的梯度的向量,与上面单个的情况是一样的。
求微分中会用到的链式法则:
推广到多输入和多输出的情况也适用(加粗的为向量,,大写的为矩阵)
实际的深度学习场景中,我们运用的是反向传播的算法
其中介绍反向传播算法之前需要了解计算图
计算图可以让我们把神经网络的计算公式画成一个图,图的原节点代表这个网络的输入,内部节点表示计算操作,有向边祈祷一个传递计算出来的值的作用,可以把值写到有向边里,按照这个边进行计算就可以。
方向传播算法,计算某点的,从后向前,
依次计算:上游梯度——本地梯度—(链式法则)—》下游梯度,直到计算出最开始的那个参数的输出
eg:先对其进行前向传播,再计算本地梯度,后向传播,再用链式法则,对其求下游梯度
注意:y有两条边
前向传播得到最终的值
反向传播,运用链式法则得到结果对各参数的梯度
求出梯度之后,就可以用梯度下降法来训练我们的神经网络
一个神经网络的列子:word2vec词向量,它利用非常简单的神经网络进行训练可以得到词向量,即这个词的低维的一个表示
word2vec能得到什么样的效果?取得什么样的词向量?
word2vec得到的词向量可以反映语言的一些规律,(学到这些词汇比较丰富的语义内涵,从而捕捉到语言上的一些规律):
例如:queen和woman平行
其中queen的向量减去king再加上man就等于woman,就可以认为其存在平行关系
queen--》king 与woman---〉man 这两个向量是平行的
word2vec用非常简单的神经网络就实现了这点,它有两类模型:
word2vec使用滑动窗口,来构造我们的训练数据
一个滑动窗口,是在一段文本中连续出现了几个单词,然后这些单词构成了一个窗口,在这样的一个窗口里,最中间的那个词就叫做target目标词,其他词被称作context上下文的词
模型一CBOW用context预测target。模型二skip-gram用target去预测context
滑动窗口事例如下:窗口大小设置为5,蓝色为target,白色为context
需要注意的是:但窗口滑动到这个句子的某一端时,比如第一个在句子的最左端,那么这个窗口,通常它就是不完整的,目标词在最左边,它的更左边就没有其他的context词了
一、从CBOW这个模型开始介绍word2vec的网络结构
CBOW是context去预测target,但滑动窗口为5时:对于never too late to learn
会用never too to learn去预测late这个目标词
注意:这里面有个bag-of-word的假设,即,不考虑context的词的次序,随便调用两个context词的位置,其模型在这个情况下,他要执行这个预测任务是完全相同的,对于模型的输入也是完全一样的
输入词的多少由滑动窗口的大小来决定
never和late这两个词,分别表示为one-hot向量,这个one-hot向量就是其他元素都是0,一个元素为1,这个元素就是词表中所表示这个词的所代表的维度
我们在一个词向量矩阵中找到never和late这两个词分别对应的词向量,即这次要训练的两个词向量,我们将这两个词向量average,即把他们加起来做平均,这样可以得到一个向量,这个向量的大小仍为这个词向量的维度
为了让这个模型去预测出too这个词,我们考虑把这个问题设计成一个n分类问题(softmax),这里的n表示的是词表的大小,即我们希望对所有的词做一个分类,每一个词去代表它的一个类别,所以我们必须对我们网络的输出层进行设计,让它具备有词表大小这么多个维度,并且进行一个softmax,这样的话我们就可以得到一个概率分布。所以我们在dot product处就是要进行一个线性变换,把词向量大小维度的向量去转化为词表大小,然后在上面用一个softmax层,得到一个词表大小的概率分布的向量,它的每一个维度加起来的值是1。
在这个例子里,它得到预测too的概率是0.4
二、对于skip-gram这个结构
它与CBOW正相反,是从target词去预测context词
对于一个神经网络来说,让它预测出多个输出其实是不太容易的,所以我们把这个问题去分解,分别让它学会去输出每一个context
输入一个词target,找到它对应的词向量,转换成词表大小,然后再去softmax,让它预测context这个词
以上两个模型中,我们都默认了要对整个词表进行softmax,然后最后再使用cross entropy loss来进行训练,
这样会产生一个问题:实际上这个vocabulary词表的大小它可能会非常的大,比如说上万,这样一来,我们进行全部的softmax之后,再进行反向传播和梯度下降,那么这个计算量就会非常大,所以我们需要想一些办法来提高计算的效率
为了计算效率的提高,我们需要对计算过程去进行取舍,具体来说,我们可以用两种方法来提高计算的效率,一种方法为:负采样;另一种方法为:做分层softmax
(1)负采样:
我们不把整个文档or词表去作为一个softmax,只采样一小部分作为所谓的负例
Q:我们如何进行负例的采样?
对于word2vec,他是按照这个词的频率,来进行负例的采样,词频越高,它被采样的概率越大
可对其做调整,如下,对其做了一个3/4的次方,这里的3/4就是一个经验值,这样可以让这些低频词被采的概率稍微提高一些,防止他们总是不被采到
这里用skip-gram这个结构来说明负采例的一个情况:
在整个词表大小做一个softmax,然后最后这个概率分布里面,包含这个词表里面的每一个词
那么我们在这里面应用负采例采样的技巧,在做softmax之前,我们只采用4个不是要我们预测的context的词,即4个和never不一样的词,然后我们把它们在这一步的这个数拿出来,和所谓的正例,即never,他们5个数进行一个softmax,最后形成的概率分布也为模型在这5个词里面进行预测的一个概率分布,这相当于,其他词压根就没有参与这个计算过程,这样我们的计算量就可以降低到一个非常低的一个程度,使得word2vec这个的训练是变得可能的
比如:我们在最后一步矩阵的映射中,从词向量维度映射到词表维度,它通过一个300x10000的这么一个矩阵实现,也就是说,假设我们词量维度是100,词表维度是10000,那么我们原本要对这10000个词进行softmax,然后再反向传播的时候,我们要对一整个300x10000的这么一个矩阵去进行一个梯度的计算,其计算量非常大,进行参数更新的时候也会有很大的计算量,
那么我们使用负列采样之后,假设我们只采4个负例,俺么我们最终softmax的时候只有5个值,那么我们在最后反向传播的时候,只对300x5折么一个子矩阵去求梯度,因此计算量非常小,它自由0.05%
事实证明,这种方法可以有效地训练得到我们想要的词向量的
此外,word2vec还有一些其他的训练技巧:
1、sub-sampling:
这个方法是为了平衡常见词和罕见词,
罕见词出现的概率比较低,它可能会包含比较丰富的语义信息
常见词出现的概率比较高,它涵盖的意义可能不太丰富,比如:的,额
所以这个方法就是,在训练过程中,去去掉一些词,依照以下公式
一个词出现的频次越高,它在训练中被去掉的概率也就越大,t是一个可以调整的参数
2、soft sliding window非固定的滑动窗口
之前讲的word2vec是固定窗口,窗口内所有的context的词它都处于一个平等的地位
实际上,我们会认为,这个离target词更近的context词,它可能会比一个更远的context词更加的相关,因此我们在word2vec的实践过程中,运用的是一个不固定大小的滑动窗口
这个窗口通过采样得到:设定一个滑动窗口的最大值smax,然后在生成训练数据的时候从1到smax之间去采样一个值,让这个值作为这一次训练的滑动窗口大小,通过这个变化的大小,我们离target词更近的词,它会有更大的机率会被采样成context词来进行训练