人人都能够做深度学习应用:入门篇
一、人工智能和新科技革命
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的模型执行和维护起来。
深度学习的框架有各种各样的版本号(Caffe、Torch、Theano等等),我仅仅接触了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模块导致的。并且。还有各种各样的。
更具体的安装说明:
https://www.tensorflow.org/install/install_linux
(3)TensorFlow环境測试执行
測试是否成功安装,能够採用官方的提供的一个短小的样例,demo生成了一些三维数据, 然后用一个平面拟合它们(官网的样例採用的初始化变量的函数是initialize_all_variables,该函数在新版本号里已经被废弃了):
#!/usr/bin/python #coding=utf-8 importtensorflowastf importnumpyasnp # 使用 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的数据和官网:
MNIST handwritten digit database, Yann LeCun, Corinna Cortes and Chris Burges
深度学习的内容。其背后会涉及比較多的数学原理。作为一个刚開始学习的人,受限于我个人的数学和技术水平。或许并不足以准确讲述相关的数学原理,因此。本文会很多其它的关注“应用层面”,不正确背后的数学原理进行展开,感谢谅解。
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拥有一张描写叙述各个计算单元的图。也就是整个模型的计算流程,它能够自己主动地使用反向传播算法(backpropagation algorithm)。来确定我们的权重等变量是怎样影响我们想要最小化的那个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循环神经网络(Recurrent Neural Networks)。是很经常使用的深度学习模型之中的一个。
我基于一个外部的demo,进行一些调整后跑起一个可以学习古诗和写古诗的比較简单的程序。
我的程序默认配置是读取三万首诗(做了一些过滤。将格式有误的或者非五言、七言的过滤掉),运行写诗(让它写了十首):
画枕江天月似霜,竹房春雪夜中春。今人已向陵边寺,夜客闲行入画舟。
云上古来烟雪晚,月寒溪水夜无穷。何因便是鲈根侣。又是离觞酒到年。
酒渴清秋未可还,年华偏见酒壶钱。无因不自全为叟。自觉平阳似我同。
棋中春草下春城。更被霜衣独入门。若教未开应要老,无妨归梦不离身。青苔白首无山药,落雪飞来夜夜长。何时未过无惆怅,满溪红土绿荷寒。
不辞宫树与仙郎,曾与青春得断魂。为向前溪犹绕药,可因心苦雪时春。不须爱尽春来老,自有文师说了何。不必便从归上信。也为言在此花来。
初时一点锦莲红。曾对仙舆在上河。万卷有时人未见,五金终处更难过。山横海渚人来起,天柳萧森旧殿寒。
唯见长州知己所,更从平地作风光。
去事相来别恨情。年边未是我家贫。花声未觉春多病。白雪无多到日寒。三亩有愁多不定,数千终去故心忙。莫将何用知兄用,犹待青林又不迷。
子有心才非病拙。一杯曾有白流愁。三朝独到南山晚,白鹤争生未见山。
多在玉壶人爱静。仅仅能安稳更堪怜。仅仅惭旧笔同才力,犹恐长心是主机。
尘末高台入碧霄。故王门户尽知无。黄华仅仅拟相依锁。三落青花亦有时。不见一家相似恨。白衣无限梦长安。
莫惜花声酒醒杯,未央山冷一枝香。花垂未入东窗晓,雨冷山寒白鹤飞。长是玉山心寂漫,何曾便在旧楼间。时闻此夕来还坐,笑作青苔寄旧游。
夹江城暖望潾山,山水清深独倚楼。白云半向三山客,万顷东楼日满林。白日夜声多远浪。绿花犹向梦来迟。明年不觉长相见,欲别寒泉又夜流。
该模型比較简单。写诗的水平不如最前面我介绍的美国研究者demo,可是,所採用的基本方法应该是类似的,仅仅是他做的更为复杂。
另外,这是一个通用模型。能够学习不同的内容(古诗、现代诗、宋词或者英文诗等),就能够生成相应的结果。
七、深度学习的入门学习体会
1. 人工智能和深度学习技术并不神奇,更像是一个新型的工具,通过喂数据给它。然后,它能发现这些数据背后的规律。并为我们所用。
2. 数学基础比較重要,这样有助于理解模型背后的数学原理。只是,从纯应用角度来说。并不一定须要全然掌握数学,也能够提前開始做一些尝试和学习。
3. 我深深地感到计算资源很缺乏。每次调整程序的參数或训练数据后,跑完一次训练集常常要许多个小时。部分场景不跑多一些训练集数据,看不出区别,比如写诗的案例。个人感觉,这个是制约AI发展的重要问题,它直接让程序的“调试”效率很低下。
4. 中文文档比較少。英文文档也不多,开源社区一直在高速更新。文档的内容过时也比較快。因此。入门学习时遇到的问题会比較多,而且缺乏成型的文档。
八、小结
我们不知道人工智能的时代是否真的会来临,也不知道它将要走向何方,可是。毫无疑问,它是一种全新的技术思维模式。更好的探索和学习这样的新技术。然后在业务应用场景寻求结合点。终于达到帮助我们的业务获得更好的成果。一直以来,就是我们project师的不懈追求。还有一方面。对发展有重大推动作用的新技术。一般会高速的发展而且走向普及。就如同我们的编程一样。因此,人人都能够做深度学习应用。并不是仅仅是一句噱头。
參考文档:
部分数学相关的内容:
高中和大学数学部分内容
线性代数视频:
posted on 2017-08-09 13:38 gavanwanggw 阅读(1360) 评论(0) 编辑 收藏 举报