神经网络算法初探(上)

Posted 美利大鲨鱼

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了神经网络算法初探(上)相关的知识,希望对你有一定的参考价值。

众所周知,这两年大火特火的深度学习算法事实上是基于上个世纪就已提出的神经网络模型。

背景分享

1943年,心理学家W·Mcculloch和数理逻辑学家W·Pitts在分析、总结神经元基本特性的基础上首先提出神经元的数学模型。此模型沿用至今,并且直接影响着这一领域研究的进展。因而,他们两人可称为人工神经网络研究的先驱。

1986年,Rumelhart、Hinton和Williams提出了多层前馈神经网络的学习算法,即BP算法。它从证明的角度推导算法的正确性,使学习算法有理论依据。从学习算法角度上看,是一个很大的进步。使得神经网络这一模型可以真正的开始落地实用。

但限于当年的硬件水平,当神经网络层次多,输入数据量大时,计算速度就成了一个难以逾越的瓶颈。直到近10年以来,随着硬件条件的突飞猛进,以及2006年Hinton的革命性的DBNs(Deep Belief Networks)的提出,才使得神经网络这一方向可以真正开始工业应用。

到目前为止,在图像/语音/文本处理/推荐算法等领域,深度学习的算法在准确性上基本打败了所有传统机器学习算法。尤其是最近Google提出并开源的BERT(https://github.com/google-research/bert)模型在NLP领域几乎可以说是一骑绝尘,并在很多评测集中超越了人类的准确率。

引证解释

那么本篇文章追本溯源,先讨论一下究竟什么是神经网络。

在机器学习领域(时髦的说法叫AI,但事实上,目前被广泛称为AI的这些学习算法是和智能不搭边的,更多的是为了贩卖炒作概念,事实上只能算一种统计模拟,所以还是叫机器学习吧),当想知道一个问题的答案时,必定有一系列已知信息,我们期望有一个model,把这一系列已知信息输入进去,这个model就能告诉我们问题的答案是什么。

所以问题可以简单划分为如下四步:

1. 如何把已知信息转化为model可以读懂的东西?

2. model如何定义?

3. model如何生成?

4. 如何评判model输出答案的准确性?

那下面我们来做详细的介绍

1. 如何把已知信息转化为model可以读懂的东西?

这一步可以说是决定后续的一个总方向,在不同的应用领域,在这一步都做了大量工作,也是后续model训练的一个基础。一般来说,都是需要把这一系列已知信息用一个数学向量来表示。

如下举两个例子

Example 1. 在金融领域,如何把一个自然人用一个向量表示?

我们日常在做贷款申请时,不论是消费贷款还是信用卡办理申请,银行总会要求我们填写一大堆的个人资料,比如户籍信息,收入水平,个人名下有无房产,婚姻状态,等等等等。将这些信息转化为向量有一个最简单的办法,就是one-hot 编码,例如一个人的婚姻状态只可能是 已婚/未婚/离异 三种,则用3位向量来表示一个人的婚姻状态,(1,0,0)表示已婚,(0,1,0)表示未婚,(0,0,1)表示离异,然后把这个人对应资料都如此编码后,再进行一个简单的拼接,就能得到一个非常长的向量来表征这个人了。当然,这个方法也存在很多问题,举个例子,比如支付宝掌握了某个人的一系列历史消费记录,明确知到这个人之前都在哪些商铺有过消费记录,那么如何把这个信息编入向量当中?总不可能把所有的商铺组成一个向量,消费记录里有哪个就在哪一位上置1,那向量就太长了。所以针对消费记录这一信息,又需要做大量的建模工作。比如这个人去高消费场所的消费比例?比如消费地点总是聚集在某个地区还是散落在全国各地?等等等其他方法做一些更复杂的处理分析,并最终把建模结果拼接到表征这个人的向量里。

Example 2. 在自然语言处理领域,如何把一段文本用一个向量来表示?

最早的时候,这个问题是用词袋模型(bag of words)来处理的,很好理解,装词的袋子。例如,“我喜欢周杰伦唱歌”,“他喜欢蔡依林唱歌”,这两句话用词袋模型表示就分别是: (1,0,1,1,0,1) (0,1,1,0,1,1) 每一位分别表示(我,他,喜欢,周杰伦,蔡依林,唱歌). 当然在真实工业应用当中,这个向量长度可能是几万到几十万,因为日常词库会很大,不可能像上例中只有6个词,表征每段文本的向量里一般都会包含大量的0,因为一段文本用到的词肯定只占词库里所有词的一小部分。 这个方法有很大的弊端,比如表征文本的向量非常稀疏(包含了大量的0,这对后续model计算非常不利),而词的顺序也对文本语义实际上有重要影响,这个表征方法也不能体现。         

所以目前工业界更多的是用词向量(word2vec)模型来表征文本。预先根据大量的文本,训练出每个词对应的一个向量,训练的结果是语义相近的词,其对应向量之间的余弦值也越接近1(即对应向量之间夹角越靠近0度)。更多信息参考:《Distributed representations of words and phrases and their compositionality》

2. model如何定义?

由于本篇主要介绍的是神经网络算法,这里重点说一下这个算法的模型定义。 所谓神经网络,顾名思义,这个算法实际上是模拟神经元的信息传递方法。

Figure 1

如Figure 1,就是一个非常简单的四层神经网络,最左侧的LayerL1表示输入向量,最右侧的输出向量L4表示模型对问题的预测结果。如果对应到金融业务里,最左侧可能表示一个来借款的用户,最右侧的向量里的两个值,一个表示这个人后续会违约的概率,一个表示这个人接下来的还款周期中会提前结清的概率。对应到文本处理领域,可能最左侧表示了一篇文章,最右侧的两个值,表示了这段文本是否包含色情信息的概率,如果是电商里的客户评论文本,可能需要判定是负面评论的概率。 L1,L2,L3三层最下侧的元素表示偏移量,具体作用后续会讲到。

如Figure 1 所示,除了L1层是输入向量,后面的每一层中的每个向量值(也可以叫神经元)都依赖于前一层的每一个向量值来做计算得到(这个最简单的例子里,每层的每一个神经元都依赖于前一层所有的神经元,即图中用箭头所示的关联。这种模型也叫全连接模型,现如今的深度学习工业应用时,因为计算量的原因,都不会采用这一形式了,而是有选择的连接某些元素,来减少运算量)。

对于Figure1中的每个未知的神经元如何计算,如下图Figure2所示


神经网络算法初探(上)

Figure 2

那么如何计算呢?这就依赖于激活函数的选择,此函数的input是一个向量,output是一个double值,常用的激活函数这里介绍两个

Figure 3(a)


Figure 3(b)

其中exp(-z)是指数函数,tanh(z)是双曲正切函数,z=w1x1+w2x2+w3*x3+b,b即figure1中所说的偏移量,可以发现,如果没有b,当input向量为0时,不论激活函数中的参数向量(即向量[w1,w2,w3])如何变动,z始终为0,这通常是不符合事实的。

Figure3(a)是激活函数里最常用的一种,也叫sigmoid函数,可以看出此函数的值域在0~1之间,事实上,这个单一“神经元”的输入-输出映射关系其实就是一个逻辑回归(逻辑回归参考:https://tech.meituan.com/intro_to_logistic_regression.html

如上,在Figure1这个简单的模型里,就是要最终确定7个激活函数里的参数向量的取值。这样,一旦新来一个向量(可能是一个借款用户,也可能是一篇文章),就可以通过这些激活函数,一层一层计算得到L2,L3,L4里每一个神经元的取值(即图中7个未知的圆圈)。计算出L4层的两个神经元的取值后,也就得到了最终的预测结果。

          上述步骤代码片段如下:

 
   
   
 
  1. public double[] predict(double[] x) {

  2.        for (int i = 0; i < x.length; i++) {

  3.            _temp_A[0][i] = x[i];

  4.        }

  5.        predictForwardPass();

  6.        return Arrays.copyOf(_temp_A[layerNum - 1], activationLayerNum[activationLayerNum.length - 1]);

  7.    }


  8.    private void predictForwardPass() {

  9.        for (int l = 1; l < layerNum; l++) {

  10.            for (int i = 0; i < activationLayerNum[l]; i++) {

  11.                _temp_Z[l][i] = innerProduct(_temp_A[l - 1], _W[l - 1][i]) + _B[l - 1];

  12.                _temp_A[l][i] = sigmoid(_temp_Z[l][i]);

  13.            }

  14.        }

  15.    }


  16.    private static double innerProduct(double[] a, double[] b) {

  17.        double sum = 0.0;

  18.        for (int i = 0; i < a.length; i++) {

  19.            sum += (a[i] * b[i]);

  20.        }

  21.        return sum;

  22.    }


  23.    private static double sigmoid(double z) {

  24.        return 1.0 / (1.0 + Math.exp(-z));

  25.    }

那么这7个激活函数里的参数如何确定呢,也就到了模型求解的核心部分,我们会在下篇里给出详细解答。

神经网络算法初探(下)

3. model如何生成?

4. 如何评判model输出答案的准确性?

以上是关于神经网络算法初探(上)的主要内容,如果未能解决你的问题,请参考以下文章

简单神经网络初探

有人可以解释啥是 SVN 平分算法吗?理论上和通过代码片段[重复]

强连通分量算法·$tarjan$初探

算法CDQ分治初探

初探12306售票算法-java代码实践

如何标记从卷积神经网络的分割算法生成的图像片段?