谷歌开源深度学习工具—TensorFlow 初探

前言

TensorFlow 是谷歌开源的深度学习工具包,它将深度学习复杂的计算过程抽象成了数据流图(Data Flow Graph),并提供简介灵活的高级抽象接口,让小白用户通过简单的学习就可以使用「高大上」的深度学习了。当谷歌被问到为什么要开源 TensorFlow 时,他们的回答是:「我们相信机器学习是未来创新产品和技术的关键因素」。其实目前我们生活的很多方面已经被机器学习深切的影响着了,从谷歌搜索到淘宝购物,以及在刚刚结束的老罗手机发布会上,引起台下欢呼不断的语音输入以及 「BigBang」,背后的核心技术都是机器学习。因此,我觉得广大程序员有必要学习下机器学习,以免被很快就会到来的「未来」所抛弃。

安装

官方的安装文档是最详细的,以我本人的电脑(MacBook Pro,python 2.7)为例,安装过程如下:

// 指定 TensorFlow 地址
export TF_BINARY_URL=https://storage.googleapis.com/tensorflow/mac/cpu/tensorflow-0.11.0rc1-py2-none-any.whl
// 使用 pip 安装(如果没有 pip,得先安装 pip)
sudo pip install --upgrade $TF_BINARY_URL

安装好后,可以进入 python 交互界面,执行以下代码确认是否安装成功:

$ python
>>> import tensorflow as tf
>>> hello = tf.constant('Hello, TensorFlow!')
>>> sess = tf.Session()
>>> print(sess.run(hello))
Hello, TensorFlow!
>>> a = tf.constant(10)
>>> b = tf.constant(32)
>>> print(sess.run(a + b))
42

简介

整体工作方式

TensorFlow 最基本的一次计算过程是这样的:接受 n 个固定格式的数据输入,通过给定的高级函数,转化为 n 个 Tensor 格式的输出。当然一次机器学习的过程会有很多次这样的计算,一次计算的输出可能是下一次计算的(部分或全部)输入,TensorFlow 将这一系列的计算过程抽象为了一张数据流图(Data Flow Graph),如图:

一张复杂的数据流图
一张复杂的数据流图

上图中从数据 Input 开始,沿着有向图进行计算,图中每个节点都是一次计算,称为 op(option),TensorFlow 中数据以 Tensor 为格式,输入一个 Tensor ,经过一次 op 后输出另一个 Tensor,然后根据数据流图进入下一个 op 作为输入,因此,整个计算过程其实是一个 Tensor 数据的流动过程,所以谷歌将这个系统形象的叫做 TensorFlow。

有了数据流图后下一个问题是如何在各种设备上很好的运行,TensorFlow 通过一个会话(Session)来控制整个数据流图的执行。TensorFlow 一个很大的优点是将复杂的运算(如矩阵运算,softmax)封装成了高级函数,用户只要使用就好了,在内部,TensorFlow 将这些函数转化成可以高效在 CPU 或 GPU 执行的机器码。Session 的主要作用是将这张数据流图合理的切分(尽量减少 Session 与 CPU 或 GPU 之间的交互,因为很慢),按照一定的顺序提交给 CPU 或者 GPU,然后(可能)还进行一些容错的机制,总之 Session 就是负责高效地让数据流图被 CPU 或 GPU 执行完成的。

如果读者对 spark 熟悉,看完以上介绍后会不会觉得其实 TensorFlow 的整个工作流程其实跟 Spark 有很多类似之处(我看完文档之后是这样认为的)。 TensorFlow 的数据流图对应于 Spark 的 DAG,TensorFlow 的 Tensor 对应于 Spark 的 RDD, TensorFlow 的 Session 对应于 Spark 的 SparkContext。待后面深入学习后再分析分析他们的异同。

基本概念

其实很多概念上面已经提到,这里统一介绍下,不过官网的文档是最详细的。

  • 数据流图:用来逻辑上描述一次机器学习计算的过程。
  • Session:负责管理协调整个数据流图的计算过程。
  • op:数据流图中的一个节点,也就是一次基本的操作过程。
  • Tensor:所有 TensorFlow 中计算的数据的格式,是一个 n 维的数组,如 t = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] 。
  • Variable:这个在上面没有提到。之前我们说一个 Tensor 经过一次 op 后会转化为另一个 Tensor,完成之后上一步的输入 Tensor 就会被回收掉。如果有些数据(如模型)我们需要一直保存,每次迭代计算只是改变其值,这时我们就需要 Variable,Variable 本质上也是一个 Tensor,只不过他是不会被回收,常驻的 Tensor。
基本使用

关于 TensorFlow 的基本使用,其实还是建议看官网,我这边列一个小的 demo 大致看下一个最基本的 TensorFlow 是怎么写的。

// 导入 tensorflow
import tensorflow as tf

// 上面说了数据是从输入到 op 再到输出,用 tf.constant() 生成的是一个源 op,
// 是一个不需要输入(输入已经定义在代码里了),只有输出的 op。
// matrix1、matrix2 都是常量 op
matrix1 = tf.constant([[3., 3.]])
matrix2 = tf.constant([[2.],[2.]])

// 创建一个矩阵乘法 matmul op , 把 'matrix1' 和 'matrix2' 作为输入.
// 返回值 'product' 代表矩阵乘法的结果。
product = tf.matmul(matrix1, matrix2)

// 创建 session
sess = tf.Session()

// 使用 session 运算整个数据流图。这里我们可以看到,
// 定义整个计算过程的时候,我们是从数据输入的方向上往下定义的,
// 而给 session 运行的时候,我们只把最后我们想要结果的那个方法
// 给了 session,说明 session 会根据最终的那步,逆向去追溯计算
// 过程,从而构建整个数据流图(猜的)。
result = sess.run(product)

//输出 [[ 12.]]
print result

//运行结束,关闭 session
sess.close()

看到这里,其实会发现 TensorFlow 并不仅仅是一个训练深度神经网络的工具,它更像是一个计算框架,其实可以在其基础上实现各种算法,有朝一日,如果越来越多的开发者参与其中,构建出更丰富的机器学习库,替代 spark 也是有可能的(虽然我觉得可能性不高)。

一个简单的机器学习实例

官方文档 给出了一个利用 MNIST 数据集训练图像识别模型的入门例子,我这里做一些简单的分析。

MNIST 数据集包含了一个训练集和一个测试集,集合中包含一些 28 像素 X 28 像素的图片(这些图片是手写的 0-9 的数字),以及每张图片的真实数字,我们的目的是通过训练集训练出一个机器学习模型,用以预测任意的手写输入图片所对应的数字。

文档中给的入门示例是一个逻辑回归模型。输入是28 X 28 像素的图片,为了方便,我们将其转化为一个长度为 28 * 28=784 的数组;输出是用 softmax 回归后该图片属于 0-9 各个数字的概率数组。整个模型通过随机梯度下降的方法进行训练,详细的文档里都有,我就其代码简单分析一下:

// 导入 tensorflow
import tensorflow as tf 
// 导入处理 MNIST 数据集的工具类
import input_data

// 加载 MNIST 数据集,获得一个封装好的对象 mnist
mnist = input_data.read_data_sets('MNIST_data', one_hot=True)

// 设置输入(即手写图像),placeholder 表示 x是一个占位符,
// shape 的 None 表示输入数据的第一维可以任意大小
x = tf.placeholder(tf.float32, shape=[None, 784])
// 设置针对输入图像,其期望的输出
y_ = tf.placeholder(tf.float32, shape=[None, 10])

// 定义 Variable,用于存储隐藏层的权重,W 是一个二维权重矩阵,
// W[i][j] 表示第 i 个像素属于第 j 个数字的概率;b 是一维数组,b[i] 
// 表示第 i 个数字的偏移量。因此,要求输入 x 属于各个数字的概率
// 公式为:W * x + b
W = tf.Variable(tf.zeros([784,10]))
b = tf.Variable(tf.zeros([10]))

/** 定义好需要的参数变量后,就可以设置训练过程了,训练过程主要分为 3 步:
   1. 定义隐藏层的输入输出过程
   2. 定义损失函数
   3. 选择训练方法开始训练 **/

// 1.定义隐藏层的输入输出过程 :
//    之前我们说用 softmax 回归模型来做隐藏层,TensorFlow 已经实现了
//    softmax 的具体方法,所以我们只要一行代码就能表示整个前馈的过程
y = tf.nn.softmax(tf.matmul(x, W) + b)

// 2.定义损失函数:
//    我们使用交叉熵来衡量结果的好坏
cross_entropy = -tf.reduce_sum(y_*tf.log(y))

// 3.选择训练方法开始训练:
//    由于我们已经知道了损失函数,我们的训练目的是让损失函数最小,
//    这里我们使用梯度下降的方法求最小值
train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)

// 定义好训练过程后,就可以开始真正的训练过程了

// 初始化 session
sess = tf.Session() 

//加载所有 variable
init = tf.initialize_all_variables() 
sess.run(init)

// 使用随机梯度下降的方法,分批次多次训练
for i in range(1000): 
    batch_xs, batch_ys = mnist.train.next_batch(100)   
    //这里随机获取的 batch_xs, batch_ys 用来填充之前定义的占位符 x, y_
    sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys})

我们可以看到,只要告诉 TensorFlow 待训练参数、损失函数、具体的训练方法,区区三行代码,它就能自动地进行训练出一个图像识别模型。当然,这只是最简单的一个逻辑回归模型,要想获得好效果,需要用到 卷积神经网络(CNN),等后面深入学习后再跟读者分享。

总结

本文简单介绍了 TensorFlow 的一些基本的概念和工作方式,后面有精力的话再深入的学习下。另外,由于自己对机器学习不是很熟悉,对 TensorFlow 也是刚接触,所以文中可能会有比较多低级错误,望读者看到后指出。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,524评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,869评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,813评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,210评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,085评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,117评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,533评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,219评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,487评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,582评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,362评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,218评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,589评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,899评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,176评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,503评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,707评论 2 335

推荐阅读更多精彩内容