一、人工智能和新科技革命
2017年围棋界发生了一件比較重要事,Master(Alphago)以60连胜横扫天下,击败各路世界冠军。人工智能以气势如虹的姿态出现在我们人类的面前。围棋以前一度被称为“人类智慧的堡垒”,现在。这座堡垒也随之成为过去。从2016年三月份AlphaGo击败李世石開始,AI全面进入我们大众的视野,对于它的讨论变得更为火热起来。整个业界普遍觉得,它非常可能带来下一次科技革命,而且,在未来可预见的10多年里,深刻得改变我们的生活。
事实上。AI除了能够做我们熟知的人脸、语音等识别之外,它能够做蛮多有趣的事情。
比如,让AI学习大量古诗之后写古诗,而且能够写出质量很不错的古诗。
又或者。将两部设计造型不同的汽车进行融合,形成全新一种设计风格的新汽车造型。
还有,之前大家在朋友圈里可能看过的,将相片转换成相应的艺术风格的画作。
当前。人工智能已经在图像、语音等多个领域的技术上,取得了全面的突破。与此同一时候,另外一个问题随之而来。假设这一轮的AI浪潮真的将会掀起新的科技革命。那么在可预见的未来。我们整个互联网都将发生翻天覆地的变化。深刻影响我们的生活。
那么作为project师的我,又应该以何种态度和方式应对这场时代洪流的冲击呢?
在回答这个问题之前。我们先一起看看上一轮由计算机信息技术引领的科技革命中,过去30多年中国程序猿的角色变化:
通过上图能够简总结:编程技术在不断地发展而且走向普及。从最開始掌握在科学家和专家学者手中的技能,逐渐发展为一门大众技能。换而言之,我们公司内非常多资深的project师,假设带着今天对编程和计算机的理解和理念回到1980年,那么他无疑就是那个时代的计算机专家。
假设这一轮AI浪潮真的会带来新的一轮科技革命,那么我们相信,它也会遵循类似的发展轨迹,逐步发展和走向普及。假设基于这个理解,也许。我们能够通过积极学习,争取成为第一代AIproject师。
二、深度学习技术
这一轮AI的技术突破。主要源于深度学习技术。而关于AI和深度学习的发展历史我们这里不反复讲述。可自行查阅。我用了一个多月的业务时间,去了解和学习了深度学习技术,在这里。我尝试以一名project师的视角,以尽量easy让大家理解的方式一起探讨下深度学习的原理,虽然。受限于我个人的技术水平和掌握程度,未必全然准确。
1. 人的智能和神经元
人类智能最重要的部分是大脑。大脑尽管复杂,它的组成单元却是相对简单的。大脑皮层以及整个神经系统,是由神经元细胞组成的。而一个神经元细胞。由树突和轴突组成。它们分别代表输入和输出。
连在细胞膜上的分叉结构叫树突,是输入。那根长长的“尾巴”叫轴突,是输出。神经元输出的有电信号和化学信号,最基本的是沿着轴突细胞膜表面传播的一个电脉冲。
忽略掉各种细节,神经元。就是一个积累了足够的输入,就产生一次输出(兴奋)的相对简单的装置。
树突和轴突都有大量的分支,轴突的末端通常连接到其它细胞的树突上,连接点上是一个叫“突触”的结构。一个神经元的输出通过突触传递给成千上万个下游的神经元。神经元能够调整突触的结合强度。而且,有的突触是促进下游细胞的兴奋,有的是则是抑制。
一个神经元有成千上万个上游神经元,积累它们的输入。产生输出。
人脑有1000亿个神经元。1000万亿个突触。它们组成人脑中庞大的神经网络,终于产生的结果即是人的智能。
2. 人工神经元和神经网络
一个神经元的结构相对来说是比較简单的。于是。科学家们就思考,我们的AI能否够从中获得借鉴?神经元接受激励,输出一个响应的方式,同计算机中的输入输出很类似,看起来简直就是量身定做的,刚好能够用一个函数来模拟。
通过借鉴和參考神经元的机制。科学家们模拟出了人工神经元和人工神经网络。
当然,通过上述这个抽象的描写叙述和图。比較难让大家理解它的机制和原理。我们以“房屋价格測算”作为样例,一起来看看:
一套房子的价格,会受到非常多因素的影响。比如地段、朝向、房龄、面积、银行利率等等,这些因素假设细分,可能会有几十个。一般在深度学习模型里,这些影响结果的因素我们称之为特征。我们先假设一种极端的场景。比如影响价格的特征仅仅有一种,就是房子面积。
于是我们收集一批相关的数据,比如,50平米50万、93平米95万等一系列样本数据。假设将这些样本数据放到而为坐标里看,则例如以下图:
然后,正如我们前面所说的。我们尝试用一个“函数”去拟合这个输入(面积x)和输出(价格y),简而言之,我们就是要通过一条直线或者曲线将这些点“拟合”起来。
如果情况也比較极端,这些点刚好能够用一条“直线”拟合(真实情况通常不会是直线),例如以下图:
那么我们的函数是一个一次元方程f(x) = ax +b,当然,假设是曲线的话,我们得到的将是多次元方程。我们获得这个f(x) = ax +b的函数之后,接下来就能够做房价“预測”,比如。我们能够计算一个我们从未看见的面积案例81.5平方米。它到底是多少钱?
这个新的样本案例,能够通过直线找到相应的点(黄色的点),如图下:
粗略的理解,上面就是AI的概括性的运作方式。
这一切似乎显得过于简单了?当然不会,由于,我们前面提到,影响房价事实上远不止一个特征。而是有几十个。这样问题就比較复杂了。接下来,这里则要继续介绍深度学习模型的训练方式。
这部分内容相对复杂一点,我尽量以业务project师的视角来做一个粗略而简单的阐述。
3. 深度学习模型的训练方式
当有好几十个特征共同影响价格的时候,自然就会涉及权重分配的问题。比如有一些对房价是主要正权重的,比如地段、面积等,也有一些是负权重的,比如房龄等。
(1)初始化权重计算
那么。第一个步事实上是给这些特征加一个权重值,可是。最開始我们根本不知道这些权重值是多少?怎么办呢?无论那么多了,先给它们随机赋值吧。随机赋值,终于计算出来的估算房价肯定是不准确的。比如,它可能将价值100万的房子。计算成了10万。
(2)损失函数
由于如今模型的估值和实际估值差距比較大。于是,我们须要引入一个评估“不准确”程度的衡量角色,也就是损失(loss)函数。它是衡量模型估算值和真实值差距的标准。损失函数越小,则模型的估算值和真实值的察觉越小,而我们的根本目的,就是减少这个损失函数。
让刚刚的房子特征的模型估算值,逼近100万的估算结果。
(3)模型调整
通过梯度下降和反向传播,计算出朝着降低损失函数的方向调整权重參数。
举一个不恰当的比喻,我们给面积添加一些权重,然后给房子朝向降低一些权重(实际计算方式,并不是针对单个个例特征的调整),然后损失函数就变小了。
(4)循环迭代
调整了模型的权重之后。就能够又又一次取一批新的样本数据。反复前面的步骤,经过几十万次甚至很多其它的训练次数。终于估算模型的估算值逼近了真实值结果。这个模型的则是我们要的“函数”。
为了让大家更easy理解和直观,採用的样例比較粗略,而且讲述深度学习模型的训练过程,中间省略了比較多的细节。
讲完了原理,那么我们就開始讲讲怎样学习和搭建demo。
三、深度学习环境搭建
在2个月前(2016年11月)。人工智能对我来说,仅仅是一个高大上的概念。
可是,经过一个多月的业余时间的认真学习,我发现还是可以学到一些东西,而且跑一些demo和应用出来的。
1. 学习的提前准备
(1)部分数学内容的复习,高中数学、概率、线性代数等部分内容。(累计花费了10个小时,,挑了关键的点看了下。事实上还是不太够。仅仅能让自己看公式的时候,相对没有那么懵)
(2)Python基础语法学习。(花费了3个小时左右。我曾经从未写过Python,由于后面Google的TensorFlow框架的使用是基于Python的)
(3)Google的TensorFlow深度学习开源框架。(花费了10多个小时去看)
数学基础好或者前期先不关注原理的同学,数学部分不看也能够開始做,全凭个人选择。
2. Google的TensorFlow开源深度学习框架
深度学习框架,我们可以粗略的理解为是一个“数学函数”集合和AI训练学习的执行框架。通过它,我们可以更好的将AI的模型执行和维护起来。
深度学习的框架有各种各样的版本号(、、等等),我仅仅接触了Google的TensorFlow。因此。后面的内容都是基于TensorFlow展开的,它的具体介绍这里不展开讲述。建议直接进入官网查看。
很令人庆幸的是TensorFlow比較早就有中文社区了。虽然里面的内容有一点老。搭建好开发环境方面有一些坑,可是已经属于为数不多的中文文档了,大家且看且珍惜。
TensorFlow的中文社区:
TensorFlow的英文社区:
3. TensorFlow环境搭建
环境搭建本身并不复杂,主要解决相关的依赖。可是,基础库的依赖能够带来非常多问题。因此,建议尽量一步到位,会简单非常多。
(1)操作系统
我搭建好开发环境使用的机器是腾讯云上的机器,软件环境例如以下:
操作系统:CentOS 7.2 64位(GCC 4.8.5)
由于这个框架依赖于python2.7和glibc 2.17。
比較旧的版本号的CentOS一般都是python2.6以及版本号比較低的glibc,会产生比較的多基础库依赖问题。并且。glibc作为Linux的底层库,牵一发动全身,直接对它升级是比較复杂,非常可能会带来很多其它的环境异常问题。
(2)软件环境
我眼下安装的Python版本号是python-2.7.5。建议能够採用yum install python的方式安装相关的原来软件。然后,再安装 python内的组件包管理器pip。安装好pip之后。接下来的其它软件的安装就相对照较简单了。
比如安装TensorFlow,可通过例如以下一句命令完毕(它会自己主动帮忙解决一些库依赖问题):
pip install -U tensorflow
这里须要特别注意的是,不要依照TensorFlow的中文社区的指引去安装。由于它会安装一个非常老的版本号(0.5.0),用这个版本号跑非常多demo都会遇到问题的。而实际上,眼下通过上述提供的命令安装。是tensorflow (1.0.0)的版本号了。
Python(2.7.5)下的其它须要安装的关键组件:
tensorflow (0.12.1)。深度学习的核心框架
image (1.5.5),图像处理相关。部分样例会用到
PIL (1.1.7),图像处理相关。部分样例会用到
除此之后,当然还有另外的一些依赖组件,通过pip list命令能够查看我们安装的python组件:
appdirs (1.4.0)backports.ssl-match-hostname (3.4.0.2)chardet (2.2.1)configobj (4.7.2)decorator (3.4.0)Django (1.10.4)funcsigs (1.0.2)image (1.5.5)iniparse (0.4)kitchen (1.1.1)langtable (0.0.31)mock (2.0.0)numpy (1.12.0)packaging (16.8)pbr (1.10.0)perf (0.1)PIL (1.1.7)Pillow (3.4.2)pip (9.0.1)protobuf (3.2.0)pycurl (7.19.0)pygobject (3.14.0)pygpgme (0.3)pyliblzma (0.5.3)pyparsing (2.1.10)python-augeas (0.5.0)python-dmidecode (3.10.13)pyudev (0.15)pyxattr (0.5.1)setuptools (34.2.0)six (1.10.0)slip (0.4.0)slip.dbus (0.4.0)tensorflow (1.0.0)urlgrabber (3.10)wheel (0.29.0)yum-langpacks (0.4.2)yum-metadata-parser (1.1.4)
依照上述提供的来搭建系统,能够规避不少的环境问题。
搭建好开发环境的过程中。我遇到不少问题。比如:在跑官方的样例时的某个报,AttributeError: ‘module’ object has no attribute ‘gfile’,就是由于安装的TensorFlow的版本号比較老,缺少gfile模块导致的。并且。还有各种各样的。
更具体的安装说明:
(3)TensorFlow环境測试执行
測试是否成功安装,能够採用官方的提供的一个短小的样例,demo生成了一些三维数据, 然后用一个平面拟合它们(官网的样例採用的初始化变量的函数是initialize_all_variables,该函数在新版本号里已经被废弃了):
#!/usr/bin/python#coding=utf-8importtensorflowastfimportnumpyasnp# 使用 NumPy 生成假数据(phony data), 总共 100 个点.x_data=np.float32(np.random.rand(2,100))# 随机输入y_data=np.dot([0.100,0.200],x_data)+0.300# 构造一个线性模型#b=tf.Variable(tf.zeros([1]))W=tf.Variable(tf.random_uniform([1,2],-1.0,1.0))y=tf.matmul(W,x_data)+b# 最小化方差loss=tf.reduce_mean(tf.square(y-y_data))optimizer=tf.train.GradientDescentOptimizer(0.5)train=optimizer.minimize(loss)# 初始化变量,旧函数(initialize_all_variables)已经被废弃,替换为新函数init=tf.global_variables_initializer()# 启动图 (graph)sess=tf.Session()sess.run(init)# 拟合平面forstepinxrange(0,201): sess.run(train) ifstep%20==0: printstep,sess.run(W),sess.run(b)# 得到最佳拟合结果 W: [[0.100 0.200]], b: [0.300]
执行的结果类似例如以下:
经过200次的训练,模型的參数逐渐逼近最佳拟合的结果(W: [[0.100 0.200]], b: [0.300]),另外,我们也能够从代码的“风格”中,了解到框架样本训练的基本执行方式。尽管,官方的教程兴许会涉及越来越多更复杂的样例,但从总体上看,也是类似的模式。
步骤划分:
- 准备数据:获得有标签的样本数据(带标签的训练数据称为有监督学习);
- 设置模型:先构建好须要使用的训练模型,可供选择的机器学习方法事实上也挺多的。换而言之就是一堆数学函数的集合。
- 损失函数和优化方式:衡量模型计算结果和真实标签值的差距;
- 真实训练运算:训练之前构造好的模型。让程序通过循环训练和学习,获得终于我们须要的结果“參数”。
- 验证结果:採用之前模型没有训练过的測试集数据,去验证模型的准确率。
当中。TensorFlow为了基于python实现高效的数学计算。一般会使用到一些基础的函数库,比如Numpy(採用外部底层语言实现)。可是,从外部计算切回到python也是存在开销的,尤其是在几万几十万次的训练过程。因此。Tensorflow不单独地执行单一的函数计算,而是先用图描写叙述一系列可交互的计算操作流程,然后所有一次性提交到外部执行(在其它机器学习的库里。也是类似的实现)。所以,上述流程图中。蓝色部分都仅仅是设置了“计算操作流程”。而绿色部分開始才是真正的提交数据给究竟层库进行实际运算,并且,每次训练通常是批量执行一批数据的。
四、经典入门demo:识别手写数字(MNIST)
常规的编程入门有“Hello world”程序,而深度学习的入门程序则是MNIST,一个识别28*28像素的图片中的手写数字的程序。
MNIST的数据和官网:
深度学习的内容。其背后会涉及比較多的数学原理。作为一个刚開始学习的人,受限于我个人的数学和技术水平。或许并不足以准确讲述相关的数学原理,因此。本文会很多其它的关注“应用层面”,不正确背后的数学原理进行展开,感谢谅解。
1. 载入数据
程序运行的第一步当然是载入数据,依据我们之前获得的数据集主要包含两部分:60000的训练数据集(mnist.train)和10000的測试数据集(mnist.test)。里面每一行。是一个28*28=784的数组。数组的本质就是将28*28像素的图片。转化成相应的像素点阵。
比如手写字1的图片转换出来的相应矩阵表演示样例如以下:
之前我们常常听说,图片方面的深度学习须要大量的计算能力,甚至须要採用昂贵、专业的GPU(Nvidia的GPU),从上述转化的案例我们就已经能够获得一些答案了。
一张784像素的图片,对学习模型来说。就有784个特征,而我们实际的相片和图片动辄几十万、百万级别,则相应的基础特征数也是这个数量级。基于这样数量级的数组进行大规模运算,没有强大的计算能力支持,确实寸步难行。当然。这个入门的MNIST的demo还是能够比較高速的跑完。
Demo中的关键代码(读取而且载入数据到数组对象中。方便后面使用):
2. 构建模型
MNIST的每一张图片都表示一个数字,从0到9。而模型终于期望获得的是:给定一张图片。获得代表每一个数字的概率。比方说,模型可能猜測一张数字9的图片代表数字9的概率是80%可是推断它是8的概率是5%(由于8和9都有上半部分的小圆),然后给予它代表其它数字的概率更小的值。
MNIST的入门样例,採用的是softmax回归(softmax regression),softmax模型能够用来给不同的对象分配概率。
为了得到一张给定图片属于某个特定数字类的证据(evidence),我们对图片的784个特征(点阵里的各个像素值)进行加权求和。假设某个特征(像素值)具有非常强的证据说明这张图片不属于该类,那么对应的权重值为负数,相反假设某个特征(像素值)拥有有利的证据支持这张图片属于这个类,那么权重值是正数。
类似前面提到的房价估算样例,对每个像素点作出了一个权重分配。
如果我们获得一张图片,须要计算它是8的概率,转化成数学公式则例如以下:
公式中的i代表须要预測的数字(8), 代表预測数字为8的情况下,784个特征的不同权重值。代表8的偏置量(bias),X则是该图片784个特征的值。
通过上述计算。我们则能够获得证明该图片是8的证据(evidence)的总和,softmax函数能够把这些证据转换成概率 y。(softmax的数学原理,辛苦各位查询相关资料哈)
将前面的过程概括成一张图(来自官方)则例如以下:
不同的特征x和相应不同数字的权重进行相乘和求和,则获得在各个数字的分布概率。取概率最大的值,则觉得是我们的图片预測结果。
将上述过程写成一个等式,则例如以下:
该等式在矩阵乘法里能够很easy地表示,则等价为:
不展开里面的详细数值,则能够简化为:
假设我们对线性代数中矩阵相关内容有适当学习。事实上,就会明确矩阵表达在一些问题上,更易于理解。
假设对矩阵内容不太记得了,也没有关系。后面我会附加上线性代数的视频。
尽管前面讲述了这么多,事实上关键代码就四行:
上述代码都是类似变量占位符,先设置好模型计算方式。在真实训练流程中。须要批量读取源数据,不断给它们填充数据,模型计算才会真实跑起来。tf.zeros则表示,先给它们统一赋值为0占位。X数据是从数据文件里读取的。而w、b是在训练过程中不断变化和更新的,y则是基于前面的数据进行计算得到。
3. 损失函数和优化设置
为了训练我们的模型,我们首先须要定义一个指标来衡量这个模型是好还是坏。这个指标称为成本(cost)或损失(loss),然后尽量最小化这个指标。简单的说,就是我们须要最小化loss的值,loss的值越小。则我们的模型越逼近标签的真实结果。
Demo中使用的损失函数是“交叉熵”(cross-entropy),它的公式例如以下:
y 是我们预測的概率分布, y’ 是实际的分布(我们输入的),交叉熵是用来衡量我们的预測结果的不准确性。TensorFlow拥有一张描写叙述各个计算单元的图。也就是整个模型的计算流程,它能够自己主动地使用。来确定我们的权重等变量是怎样影响我们想要最小化的那个loss值的。
然后,TensorFlow会用我们设定好的优化算法来不断改动变量以减少loss值。
当中,demo採用梯度下降算法(gradient descent algorithm)以0.01的学习速率最小化交叉熵。
梯度下降算法是一个简单的学习过程。TensorFlow仅仅需将每一个变量一点点地往使loss值不断减少的方向更新。
相应的关键代码例如以下:
备注内容:
交叉熵:
反向传播:
在代码中会看见one-hot vector的概念和变量名,事实上这个是个很easy的东西。就是设置一个10个元素的数组,当中仅仅有一个是1,其它都是0。以此表示数字的标签结果。
比如表示数字3的标签值:
[0,0,0,1,0,0,0,0,0,0]
4. 训练运算和模型精确度測试
通过前面的实现。我们已经设置好了整个模型的计算“流程图”。它们都成为TensorFlow框架的一部分。于是,我们就能够启动我们的训练程序。以下的代码的含义是。循环训练我们的模型500次,每次批量取50个训练样本。
其训练过程,事实上就是TensorFlow框架的启动训练过程,在这个过程中,python批量地将数据交给底层库进行处理。
我在官方的demo里追加了两行代码,每隔50次则额外计算一次当前模型的识别准确率。
它并不是必要的代码,只用于方便观察整个模型的识别准确率逐步变化的过程。
当然。里面涉及的accuracy(预測准确率)等变量,须要在前面的地方定义占位:
当我们训练完成,则到了验证我们的模型准确率的时候,和前面同样:
我的demo跑出来的结果例如以下(softmax回归的样例执行速度还是比較快的),当前的准确率是0.9252:
5. 实时查看參数的数值的方法
刚開始跑官方的demo的时候。我们总想将相关变量的值打印出来看看,是如何一种格式和状态。
从demo的代码中,我们能够看见非常多的Tensor变量对象,而实际上这些变量对象都是无法直接输出查看,粗略地理解,有些仅仅是占位符,直接输出的话。会获得类似例如以下的一个对象:
Tensor("Equal:0", shape=(?,), dtype=bool)既然它是占位符,那么我们就必须喂一些数据给它。它才干将真实内容展示出来。
因此,正确的方法是。在打印时通常须要加上当前的输入数据给它。
比如。查看y的概率数据:
print(sess.run(y,feed_dict={x:batch_xs,y_:batch_ys}))部分非占位符的变量还能够这样输出来:
print(W.eval())总的来说。92%的识别准确率是比較令人失望,因此,官方的MNIST事实上也有多种模型的不同版本号。当中比較适合图片处理的CNN(卷积神经网络)的版本号,能够获得99%以上的准确率。当然。它的运行耗时也是比較长的。
(备注:cnn_mnist.py就是卷积神经网络版本号的,后面有附带微云网盘的下载url)
前馈神经网络(feed-forward neural network)版本号的MNIST。可达到97%:
分享在微云上的数据和源代码:
(备注:国外站点下载都比較慢,我这份下载相对会快一些,在环境已经搭建完成的情况下,运行里面的run.py就可以)
五、和业务场景结合的demo:预測用户是否是超级会员身份
依据前面的内容,我们对上述基于softmax仅仅是三层(输入、处理、输出)的神经网络模型已经比較熟悉。那么。这个模型能否够应用到我们详细的业务场景中,当中的难度大吗?为了验证这一点。我拿了一些现网的数据来做了这个试验。
1. 数据准备
我将一个现网的电影票活动的用户參与数据,包含点击过哪些button、手机平台、IP地址、參与时间等信息抓取了出来。
事实上这些数据其中是隐含了用户的身份信息的。比如,某些礼包的必须是超级会员身份才干领取,假设这个button用户点击领取成功,则能够证明该用户的身份肯定是超级会员身份。
当然,我仅仅是将这些不知道相不相关的数据特征直观的整理出来,作为我们的样本数据,然后相应的标签为超级会员身份。
用于训练的样本数据格式例如以下:
第一列是QQ号码,仅仅做认知标识的,第二列表示是否超级会员身份,作为训练的标签值,后面的就是IP地址,平台标志位以及參与活动的參与记录(0是未成功參与,1表示成功參与)。则获得一个拥有11个特征的数组(经过一些转化和映射,将特别大的数变小):
[0.9166666666666666,0.4392156862745098,0.984313725490196,0.7411764705882353,0.2196078431372549,1.0,0.0,0.0,0.0,0.0,1.0]相应的是否是超级数据格式例如以下。作为监督学习的标签:
超级会员:[0, 1]
非超级会员:[1, 0]
这里须要专门解释下。在实际应用中须要做数据转换的原因。一方面。将这些数据做一个映射转化。有助于简化数据模型。还有一方面。是为了规避NaN的问题,当数值过大。在一些数学指数和除法的浮点数运算中,有可能得到一个无穷大的数值,或者其它溢出的情形。在Python里会变为NaN类型,这个类型会破坏掉兴许所有计算结果,导致计算异常。
比例如以下图,就是特征数值过大。在训练过程中,导致中间某些參数累计越来越大,终于导致产生NaN值,兴许的计算结果所有被破坏掉:
而导致NaN的原因在复杂的数学计算里,会产生无穷大或者无穷小。比如,在我们的这个demo中,产生NaN的原因,主要是由于softmax的计算导致。
Runtime Warning: divide by zero encountered in log刚開始做实际的业务应用,就发现常常跑出极奇怪异的结果(遇到NaN问题,我发现程序也能继续走下去),几经排查才发现是NAN值问题,是很令人沮丧的。
当然,经过细致分析问题。发现也并不是没有排查的方式。由于,NaN值是个奇特的类型。能够採用下述编码方式NaN != NaN来检測自己的训练过程中,是否出现的NaN。
关键程序代码例如以下:
我採用上述方法,非常顺利地找到自己的深度学习程序,在学习到哪一批数据时产生的NaN。因此。非常多原始数据我们都会做一个除以某个值,让数值变小的操作。比如官方的MNIST也是这样做的,将256的像素颜色的数值统一除以255,让它们都变成一个小于1的浮点数。
MNIST在处理原始图片像素特征数据时。也对特征数据进行了变小处理:
处理NaN问题更专业的方法,就是对输入数据进行归一化处理(min-max标准化或Z-score标准化方法),将值控制在一个可控的范围内。NaN值问题曾一度深深地困扰着我,特别放到这里。避免入门的同学踩坑。
2. 运行结果
我准备的训练集(6700)和測试集(1000)数据并不多,只是。超级会员身份的预測准确率终于能够达到87%。尽管。预測准确率是不高,这个可能和我的训练集数据比較少有关系。只是,整个模型也没有花费多少时间,从整理数据、编码、训练到终于跑出结果,仅仅用了2个晚上的时间。
下图是两个实际的測试样例,比如。该模型预測第一个QQ用户有82%的概率是非超级会员用户,17.9%的概率为超级会员用户(该预測是准确的)。
通过上面的这个样例,我们会发觉事实上对于某些比較简单的场景下应用,我们是能够比較easy就实现的。
六、其它模型
1. CIFAR-10识别图片分类的demo(官方)
CIFAR-10数据集的分类是机器学习中一个公开的基准測试问题,它任务是对一组32x32RGB的图像进行分类,这些图像涵盖了10个类别:飞机, 汽车, 鸟。 猫。 鹿。 狗。 青蛙。 马, 船和卡车。
这也是官方的重要demo之中的一个。
更具体的介绍内容:
该样例运行的过程比較长。须要耐心等待。
我在机器上的运行过程和结果:
cifar10_train.py用于训练:
cifar10_eval.py用于检验结果:
识别率不高是由于该官方模型的识别率本来就不高:
另外,官方的样例我首次在1月5日跑的时候,还是有一些小问题的,无法跑起来(最新的官方可能已经修正),建议能够直接使用我放到微云上的版本号(代码里面的log和读取文件的路径,须要调整一下)。
源代码下载:
微云盘里,不含训练集和測试集的图片数据,可是。程序假设检測到这些图片不存在,会自行下载:
2. 是否大于5岁的測试demo
为了检验softma回归模型是否可以学习到一些我自己设定好的规则。我做了一个小demo来測试。我通过随机数生成的方式构造了一系列的数据,让前面的softmax回归模型去学习,终于看看模型是否能通过训练集的学习,终于100%预測这个样本数据是否大于5岁。
模型和数据本身都比較简单,构造的数据的方式:
我随机构造一个仅仅有2个特征纬度的样本数据,[year, 1],当中year随机取值0-10。数字1是放进去作为干扰。
假设year大于5岁。则标签设置为:[0, 0, 1];
否则,标签设置为:[0, 1, 0]。
生成了6000条假训练集去训练该模型。终于它能做到100%成功预測准确:
微云下载(源代码下载):
3. 基于RNN的古诗学习
最开头的AI写古诗,很令人感到惊艳,那个demo是美国的一个研究者做出来的。可以依据主题生成不能的古诗,并且古诗的质量还比較高。于是。我也尝试在自己的机器上也跑一个可以写古诗的模型。后来我找到的是一个基于RNN的模型。RNN。是很经常使用的深度学习模型之中的一个。
我基于一个外部的demo,进行一些调整后跑起一个可以学习古诗和写古诗的比較简单的程序。
我的程序默认配置是读取三万首诗(做了一些过滤。将格式有误的或者非五言、七言的过滤掉),运行写诗(让它写了十首):
画枕江天月似霜,竹房春雪夜中春。今人已向陵边寺,夜客闲行入画舟。
云上古来烟雪晚,月寒溪水夜无穷。何因便是鲈根侣。又是离觞酒到年。
酒渴清秋未可还,年华偏见酒壶钱。无因不自全为叟。自觉平阳似我同。
棋中春草下春城。更被霜衣独入门。若教未开应要老,无妨归梦不离身。青苔白首无山药,落雪飞来夜夜长。何时未过无惆怅,满溪红土绿荷寒。
不辞宫树与仙郎,曾与青春得断魂。为向前溪犹绕药,可因心苦雪时春。不须爱尽春来老,自有文师说了何。不必便从归上信。也为言在此花来。
初时一点锦莲红。曾对仙舆在上河。万卷有时人未见,五金终处更难过。山横海渚人来起,天柳萧森旧殿寒。
唯见长州知己所,更从平地作风光。
去事相来别恨情。年边未是我家贫。花声未觉春多病。白雪无多到日寒。三亩有愁多不定,数千终去故心忙。莫将何用知兄用,犹待青林又不迷。 子有心才非病拙。一杯曾有白流愁。三朝独到南山晚,白鹤争生未见山。
多在玉壶人爱静。仅仅能安稳更堪怜。仅仅惭旧笔同才力,犹恐长心是主机。
尘末高台入碧霄。故王门户尽知无。黄华仅仅拟相依锁。三落青花亦有时。不见一家相似恨。白衣无限梦长安。 莫惜花声酒醒杯,未央山冷一枝香。花垂未入东窗晓,雨冷山寒白鹤飞。长是玉山心寂漫,何曾便在旧楼间。时闻此夕来还坐,笑作青苔寄旧游。
夹江城暖望潾山,山水清深独倚楼。白云半向三山客,万顷东楼日满林。白日夜声多远浪。绿花犹向梦来迟。明年不觉长相见,欲别寒泉又夜流。
该模型比較简单。写诗的水平不如最前面我介绍的美国研究者demo,可是,所採用的基本方法应该是类似的,仅仅是他做的更为复杂。
另外,这是一个通用模型。能够学习不同的内容(古诗、现代诗、宋词或者英文诗等),就能够生成相应的结果。
七、深度学习的入门学习体会
1. 人工智能和深度学习技术并不神奇,更像是一个新型的工具,通过喂数据给它。然后,它能发现这些数据背后的规律。并为我们所用。
2. 数学基础比較重要,这样有助于理解模型背后的数学原理。只是,从纯应用角度来说。并不一定须要全然掌握数学,也能够提前開始做一些尝试和学习。
3. 我深深地感到计算资源很缺乏。每次调整程序的參数或训练数据后,跑完一次训练集常常要许多个小时。部分场景不跑多一些训练集数据,看不出区别,比如写诗的案例。个人感觉,这个是制约AI发展的重要问题,它直接让程序的“调试”效率很低下。
4. 中文文档比較少。英文文档也不多,开源社区一直在高速更新。文档的内容过时也比較快。因此。入门学习时遇到的问题会比較多,而且缺乏成型的文档。
八、小结
我们不知道人工智能的时代是否真的会来临,也不知道它将要走向何方,可是。毫无疑问,它是一种全新的技术思维模式。更好的探索和学习这样的新技术。然后在业务应用场景寻求结合点。终于达到帮助我们的业务获得更好的成果。一直以来,就是我们project师的不懈追求。还有一方面。对发展有重大推动作用的新技术。一般会高速的发展而且走向普及。就如同我们的编程一样。因此,人人都能够做深度学习应用。并不是仅仅是一句噱头。
參考文档:
部分数学相关的内容:
高中和大学数学部分内容
线性代数视频: