一、简介

  TensorFlow时谷歌于2015年11月宣布在Github上开源的第二代分布式机器学习系统,目前仍处于快速开发迭代中,有大量的新功能新特性在陆续研发中;

  TensorFlow既是一个实现机器学习算法的接口,同时也是执行机器学习算法的框架。它的前端支持Python、C++、Go、Java等多种开发语言,后端使用C++、CUDA等编写,其实现的算法可以在很多不同的系统上进行移植,虽然TensorFlow主要用来执行的是深度学习算法,但其也可以用来实现很多其他算法,诸如线性回归、逻辑回归、随机森林等,目前,TensorFlow依然成为最流行的深度学习框架;

  TensorFlow的特点是它使用数据流式图来进行计算流程的规划,其内部的计算都可以表示为一个有向图(directed graph),或称计算图(computation graph),其中每一个运算操作(operation)将作为一个节点(node),而节点之间的连接称为边(edge),通过这个规划好的计算图,很清楚的描述了数据的计算流程,它也负责维护和更新状态,用户可以对计算图的分支进行条件控制或循环操作。用户可以使用Python、C++、Go、Java等几种语言设计这个数据计算的有向图。计算图的每一个结点都可以有任意多个输入和任意多个输出,每一个节点描述了一种运算操作,节点相当于运算操作的实例化(instance)。

  而对于tensorflow完成实际学习任务时的工作机制的介绍,下面以一个广为人知的分类任务为引;

二、MNIST手写数字识别

  作为机器学习中hello world级别的案例,MNIST是一个非常简单的计算机视觉数据集,它由数万张28X28像素的手写数字图片组成,这些图片只包含灰度值信息,而我们的训练任务是实现对这些数字进行分类至0-9一共10类,tensorflow和sklearn一样自带了这个数据集,并且已经分成55000个训练集样本,10000个测试集样本,以及5000个验证集样本,每个样本有28X28=784个维度特征作为自变量,即已经将图片展开成一行(本篇只是对tensorflow进行一个基本的初探,关于结构化数据的处理之后的博文会介绍),以及一个数字做为因变量,即其真实代表的数字,我们载入这个数据集中训练集、验证集与测试集,并对因变量进行one hot处理,即用一个10维的向量来代替原来的因变量,譬如,真实数字为0,则它one hot编码后的结果为[1,0,0,0,0,0,0,0,0,0],即除了它真实数值所在的位置,其他位置全为0;并且我们随意挑选绘制其中的一个样本:

import matplotlib.pyplot as plt
from tensorflow.examples.tutorials.mnist import input_data '''载入MNIST数据集,并进行one hot处理'''
mnist = input_data.read_data_sets('MNIST_data',one_hot=True) '''抽出训练集中的一行出来并reshape为28X28的形式'''
test = mnist.train.images[666,:].reshape([28,28]) '''绘制格点图'''
plt.matshow(test)

运行结果:

我们一眼就能看出这是个5,接下来我们利用tensorflow训练模型来实现机器对其的分类,这里因为是初探tensorflow的演示,故不选择进阶的复杂模型,而是采用softmax regression算法,这是一个经典的处理多分类问题的算法,softmax函数会对每一种类别输出的概率进行估算,然后选取其中最大的那个作为正式输出,是神经网络中多分类模型的基础,其基础的解释如下,更细致的解析将会在下一篇博文中介绍:

Softmax Regression:

  对我们前面提到的one hot的结果,即转换后的10个特征,用i代表第i个类,j代表一个样本的第i个自变量特征即第i个像素点,bias表示数据集本身的倾向,类似先验分布,有如下式子:

接着,经过前面的加权加偏移的输入过程,就到了softmax的部分,对于前面传入的每一个feature,先经过:

即对每一个位置的输入特征进行指数化(将非正数正数化)再进行标准化(使得所有输出相加等于1,即对每个特征输入指数化后的结果施加一个伸缩系数),再于是得到每个特征位置输出的概率值:

将上述的过程转化为矩阵乘法形式(这里指的是单个样本的计算过程)即为:

理清楚上面这个过程,下面就来利用tensorflow搭建一系列部件来实现softmax regression,因为Python本身运算效率不高,因此为了加速运算,tensorflow在利用Python语句搭建好计算图结构后,运行时将计算部分利用C++放在CPU中或利用CUDA运行在GPU上,我们首先载入tf库,并创建一个新的InteractiveSession作为默认的session,之后的运算在不更改session的情况都在该session中运行:

import tensorflow as tf

'''注册默认的session,之后的运算都会在这个session中进行'''
sess = tf.InteractiveSession()

接着我们创建一个placeholder对象作为自变量的入口,这是tensorflow中用于输入数据的部件,其中的第一个参数指定的传入数据的精度类型,第二个列表形式的参数指定了该数据入口允许的数据集形状(行数、列数),行设置为None表示输入的样本数没有限制,但输入数据的特征维数一定是784个:

'''创建placeholder用来定义数据的入口部件,其中第一个参数设置数据类型,第二个参数控制输入数据的shape,None表示样本数不限,784列表示特征维度限制为784维'''
x = tf.placeholder(tf.float32, [None, 784])

接下来要为模型中逐轮调整的参数创建容器,tensorflow中的variable对象就是专门为模型的参数设置的容器部件,不同于存储数据的tensor一经使用便马上消失,variable在模型的训练过程中是一直存在的,并且模型训练完成后还可以被导出,它们在每一轮迭代中被更新,这里我们将weights和biases全部初始化为0,因为这里的演示比较简单,真实的训练任务中往往会利用少量数据进行预训练以确定一个较好的weights和biases起点,按照我们之前推导的公式,则W的形状为784X10,biases的形状为1X10:

'''为权重和bias设置持久化的variable,这里权重为784乘10,10是输出层的尺寸'''
W = tf.Variable(tf.zeros([784,10])) b = tf.Variable(tf.zeros([10]))

初始化所有参数后,下面要进行的就是对softmax函数计算部分部件的初始化,我们使用tensorflow.nn中的softmax()组件,tensorflow.nn用于存放各种神经网络组件,我们在softmax求解器中按照前面的计算公式部署我们前面所有参数及变量,tf.matmul()表示tf中的矩阵乘法:

'''定义输出层softmax求解部件'''
y = tf.nn.softmax(tf.matmul(x, W) + b)

所有计算图中forward的部分基本完成,下面要为BP算法来设置一个loss function,考虑这样一个例子:

对于某个样本的真实值y和某轮算法的输出值y’(这里均指one hot后的形式):

可以看出,算法的估计值并没有完美达到真实值y,因此基于均方误差的思想,构造loss function如下:

则我们的训练目标即BP算法优化的方向是一轮一轮地削减这个loss function,因此我们将训练样本真实的标签也设置一个入口部件,并在loss function中进行计算,对应的代码如下:

'''将均方误差作为loss function来描述模型的分类精度'''

'''定义均方误差求解的计算入口部件,y_代表真实类别'''
y_ = tf.placeholder(tf.float32, [None, 10]) '''根据均方误差的计算公式定义计算部件'''
loss_function = tf.reduce_mean((y_ - y)**2)

现在我们有了模型,有了loss function,接下来需要的就是根据梯度进行求解的优化器了,这里我们选择比价简单的标准梯度下降算法,tf.train中集成了很多优化器,这里我们选择梯度下降法对应的tf.train.GradientDescentOptimizer:

'''定义优化器组件,这里采用标准的梯度下降法作为优化算法'''
train_step = tf.train.GradientDescentOptimizer(0.5).minimize(loss_function)

至此,我们所有的训练计算图部分都已经搭建好,下面需要激活所有计算图,并进行迭代,我们对全局参数初始化器tf.global_variables_initializer()使用run()方法,:

'''使用全局参数初始化器并进行run'''
tf.global_variables_initializer().run()

这样我们的计算图就搭建好了,下面通过循环迭代进行前面定义的train_step,设定最大迭代次数,以及要feed给模型的各项输入即可,这里我们为了收敛更快且以更大的可能跳出局部最优,每一轮迭代从总的训练集中抽出100个样本进行训练,这就相当于随机梯度下降,我们使用next_batch()来实现这个抽样的过程,并对train_step施加run方法,传入参数为字典指定的自变量与因变量,具体代码如下:

'''迭代执行训练操作'''
for i in range(10000):
batch_xs, batch_ys = mnist.train.next_batch(100)
train_step.run({x:batch_xs, y_:batch_ys})

这样经过些许等待,我们就可以得到10000次迭代后的模型,下面利用测试集对其准确率进行考察,还是像以前一样,先搭建涉及到的计算图,再feed数据,这里的eval()和Session.run()的效用是等价的,就是激活计算图:

'''判断预测值与真实值是否相等并保存到bool型变量中'''
correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1)) '''统计正确率,这里tf.cast用来将bool型变量转化为float32,再求平均值,即正确率'''
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32)) print(accuracy.eval({x:mnist.test.images, y_:mnist.test.labels}))

运行结果:

但不要觉得0.93了挺不错的,实际上早在上个世纪90年代就已经利用LeNet5实现了在MNIST数据集上99%的正确率,因为我们本文只是简单初体验一下tensorflow,并没有对MNIST的图片结构信息有什么利用;

  我们将上述过程概括一下,主要有以下几个核心步骤:

  1、初始化session,定义算法中,在神经网络里是forward的计算部分计算图部件;

  2、定义loss function、优化器以及优化器优化loss的计算图部件;

  3、激活所有部件,并在循环中自定义数据的feed方式进行训练;

  4、在测试集上利用训练好的模型来计算各种评价指标;

三、现状

  自从2006年Hinton等人提出了逐层预训练来初始化权重的方法,以及利用多层RBM(受限玻尔兹曼机,Restricted Boltzmann Machine,一种基于分布的神经网络)堆叠成了DBN(深度信念网络,Deep Belief Network)神经网络后,人们又对神经网络赋予了极大的期待,大量新结构的神经网络也应孕而生,神经网络的最大价值在于对特征的自动提取和抽象,免去了人工做特征工程的繁琐,可以自动找出复杂且有效的高阶特征,这一点类似人的学习过程,对知识的理解从浅入深,神经网络的隐层越多,能够提取到的特征就更抽象;

  当下,深度学习在复杂机器学习问题上的碾压性优势已经确定,只要有足够多数据,设计完善的神经网络都可以取得比其他算法更好的效果,其实本篇中的模型可以算是一个没有隐层的神经网络,而在之后的文章中,我将就一些流行的更加复杂的神经网络进行介绍,敬请期待。

(数据科学学习手札35)tensorflow初体验的更多相关文章

  1. (数据科学学习手札40)tensorflow实现LSTM时间序列预测

    一.简介 上一篇中我们较为详细地铺垫了关于RNN及其变种LSTM的一些基本知识,也提到了LSTM在时间序列预测上优越的性能,本篇就将对如何利用tensorflow,在实际时间序列预测任务中搭建模型来完 ...

  2. (数据科学学习手札36)tensorflow实现MLP

    一.简介 我们在前面的数据科学学习手札34中也介绍过,作为最典型的神经网络,多层感知机(MLP)结构简单且规则,并且在隐层设计的足够完善时,可以拟合任意连续函数,而除了利用前面介绍的sklearn.n ...

  3. (数据科学学习手札44)在Keras中训练多层感知机

    一.简介 Keras是有着自主的一套前端控制语法,后端基于tensorflow和theano的深度学习框架,因为其搭建神经网络简单快捷明了的语法风格,可以帮助使用者更快捷的搭建自己的神经网络,堪称深度 ...

  4. (数据科学学习手札55)利用ggthemr来美化ggplot2图像

    一.简介 R中的ggplot2是一个非常强大灵活的数据可视化包,熟悉其绘图规则后便可以自由地生成各种可视化图像,但其默认的色彩和样式在很多时候难免有些过于朴素,本文将要介绍的ggthemr包专门针对原 ...

  5. (数据科学学习手札50)基于Python的网络数据采集-selenium篇(上)

    一.简介 接着几个月之前的(数据科学学习手札31)基于Python的网络数据采集(初级篇),在那篇文章中,我们介绍了关于网络爬虫的基础知识(基本的请求库,基本的解析库,CSS,正则表达式等),在那篇文 ...

  6. (数据科学学习手札49)Scala中的模式匹配

    一.简介 Scala中的模式匹配类似Java中的switch语句,且更加稳健,本文就将针对Scala中模式匹配的一些基本实例进行介绍: 二.Scala中的模式匹配 2.1 基本格式 Scala中模式匹 ...

  7. (数据科学学习手札47)基于Python的网络数据采集实战(2)

    一.简介 马上大四了,最近在暑期实习,在数据挖掘的主业之外,也帮助同事做了很多网络数据采集的内容,接下来的数篇文章就将一一罗列出来,来续写几个月前开的这个网络数据采集实战的坑. 二.马蜂窝评论数据采集 ...

  8. (数据科学学习手札42)folium进阶内容介绍

    一.简介 在上一篇(数据科学学习手札41)中我们了解了folium的基础内容,实际上folium在地理信息可视化上的真正过人之处在于其绘制图像的高度可定制化上,本文就将基于folium官方文档中的一些 ...

  9. (数据科学学习手札32)Python中re模块的详细介绍

    一.简介 关于正则表达式,我在前一篇(数据科学学习手札31)中已经做了详细介绍,本篇将对Python中自带模块re的常用功能进行总结: re作为Python中专为正则表达式相关功能做出支持的模块,提供 ...

随机推荐

  1. 【java开发系列】—— 嵌套类与内部类

    嵌套类与内部类在java中使用的很广泛,为了避免难以理解,这里用了几个小例子,说明它的用法. 嵌套类与内部类的结构如下图 静态嵌套类 静态嵌套类,是一种在类之外声明的嵌套类,由于是静态的,所以不经过初 ...

  2. June 12th 2017 Week 24th Monday

    All the splendor in the world is not worth a good friend. 人世间所有的荣华富贵都比不上有一个好朋友. It's great to have a ...

  3. flume-ng 自定义sink消费flume source

    如何从一个已经存在的Flume source消费数据 1.下载flume wget http://www.apache.org/dist/flume/stable/apache-flume-1.5.2 ...

  4. 郑州Day6

    今天考了毕姥爷的一套题,差点保龄 题目 挺良心的一套题,至少我不用再搬一遍题面了 T1.B君的第一题 我为什么当时去写了一个树形\(dp\)还妄图\(A\)掉啊 这题保龄感觉舒爽 首先如果我们要求的是 ...

  5. jmeter自动生成测试报告

    环境要求1:jmeter3.0版本之后开始支持动态生成测试报表 2:jdk版本1.7以上 3:需要jmx脚本文件 基本操作 1:在你的脚本文件路径下,执行cmd命令:jmeter -n -t test ...

  6. caffe整体框架的学习的博客,这个博客山寨了一个caffe框架

    http://www.cnblogs.com/neopenx/default.html?page=1 这个博主很牛逼,写的东西也很好,多学学,无论是对框架,还是对自己学习c++帮助都非常大

  7. 原生ajax、XMLHttpRequest和FetchAPI简单描述

    什么是ajax ajax的出现,刚好解决了传统方法的缺陷.AJAX 是一种用于创建快速动态网页的技术.通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新.这意味着可以在不重新加载整个 ...

  8. HTML5标签应用

    <!doctype html> <html> <head> <style> /* *{border:1px solid red;height:20px} ...

  9. HDU 1258 Sum It Up(dfs 巧妙去重)

    传送门: http://acm.hdu.edu.cn/showproblem.php?pid=1258 Sum It Up Time Limit: 2000/1000 MS (Java/Others) ...

  10. 我想写一个前端开发工具(一):在npm发布模块

    有必要说说我为什么要开始写这个,正文从下面的第一条开始 我最近忙于公司的项目,一直没有抽出时间来写文章.本来想每个月写一片文章,保质保量,无奈上个月没有坚持. 这段时间有点忙,主要是由于公司业务调整, ...