2019-01-11TensorFlow入门

随着 TensorFLow 在研究及产品中的应用日益广泛,很多开发者及研究者都希望能深入学习这一深度学习框架。而在昨天机器之心发起的框架投票中,2144 位参与者中有 1441 位都在使用 TensorFlow 框架,是所有框架中使用率最高的。但 TensorFLow 这种静态计算图有一定的学习成本,因此也阻挡了很多初学者入坑。本文介绍了学习 TensorFlow 的系列教程,旨在通过简单的理论与实践帮助初学者一步步掌握 TensorFlow 的编程技巧。这一系列教程分为 6 部分,从为什么选择 TensorFlow 到卷积神经网络的实现,介绍了初学者所需要的技能。机器之心在本文介绍了 PyTorch 和 Caffe 等深度学习框架的优缺点及 TensorFlow 基础,包括静态计算图、张量、TensorBoard 可视化和模型参数的保存等。

机器之心此前也介绍过很多 TensorFlow 的学习资源,读者可结合这些资源阅读该系列教程:

学习了!谷歌今日上线基于 TensorFlow 的机器学习速成课程(中文版)机器之心 GitHub 项目:从零开始用 TensorFlow 搭建卷积神经网络教程 | 从零开始:TensorFlow 机器学习模型快速部署指南分布式 TensorFlow 入坑指南:从实例到代码带你玩转多机器深度学习三天速成!香港科技大学 TensorFlow 课件分享TensorFlow 从基础到实战:一步步教你创建交通标志分类神经网络为什么选择 TensorFlow?在本文中,我们将对比当前最流行的深度学习框架(包括 Caffe、Theano、PyTorch、TensorFlow 和 Keras),帮助你为应用选择最合适的框架。

1. Caffe:第一个主流产品级深度学习库,于 2014 年由 UC Berkeley 启动。

优点:

快速支持 GPU漂亮的 Matlab 和 Python 接口。

缺点:

不灵活。在 Caffe 中,每个节点被当做一个层,因此如果你想要一种新的层类型,你需要定义完整的前向、后向和梯度更新过程。这些层是网络的构建模块,你需要在无穷无尽的列表中进行选择。(相反,在 TensorFlow 中,每个节点被当做一个张量运算例如矩阵相加、相乘或卷积。你可以轻易地定义一个层作为这些运算的组合。因此 TensorFlow 的构建模块更小巧,允许更灵活的模块化。)需要大量的非必要冗长代码。如果你希望同时支持 CPU 和 GPU,你需要为每一个实现额外的函数。你还需要使用普通的文本编辑器来定义你的模型。真令人头疼!几乎每个人都希望程序化地定义模型,因为这有利于不同组件之间的模块化。有趣的是,Caffe 的主要架构师现在在 TensorFlow 团队工作。专一性。仅定位在计算机视觉(但做得很不错)。不是以 Python 编写!如果你希望引入新的变动,你需要在 C++和 CUDA 上编程(对于更小的变动,你可以使用它的 Python 和 Matlab 接口)。糟糕的文档。安装比较困难!有大量的依赖包。只有少量种类的输入格式,仅有一种输出格式 HDF5(虽然你总是可以使用它的 Python/C++/Matlab 接口来运行,并从中得到输出数据)。不适用于构建循环网络。

2. Theano:

由蒙特利尔大学研究团队构建。Theano 的顶层构建了数值开源深度库,包括 Keras、Lasagne 和 Blocks。Yoshua Bengio 在 2017 年 9 月 28 日宣布,Theano 的开发将终止。因此实际上 Theano 已死!

优点:

计算图的抽象很漂亮(可媲美 TensorFlow)为 CPU 和 GPU 都做了优化很好地适应数值优化任务高级封装(Keras、Lasagne)

缺点:

原始的 Theano 只有比较低级的 APIimport numpy for _ in range(T): h = torch.matmul(W, h) + b大型模型可能需要很长的编译时间不支持多 GPU错误信息可能没有帮助(有时候令人懊恼)

3. Pytorch:

2017 年 1 月,Facebook 将 Python 版本的 Torch 库(用 Lua 编写)开源。

优点:

提供动态计算图(意味着图是在运行时生成的),允许你处理可变长度的输入和输出,例如,在使用 RNN 时非常有用。另一个例子是,在 PyTorch 中,可以使用标准 Python 语法编写 for 循环语句。大量预训练模型大量易于组合的模块化组件易于编写自己的图层类型,易于在 GPU 上运行「Tensorboard」缺少一些关键功能时,「Losswise」可以作为 Pytorch 的替代品缺点:

正式文档以外的参考资料/资源有限无商业支持4. Tensorflow:由较低级别的符号计算库(如 Theano)与较高级别的网络规范库(如 Blocks 和 Lasagne)组合而成。

优点:

由谷歌开发、维护,因此可以保障支持、开发的持续性。巨大、活跃的社区网络训练的低级、高级接口「Tensorboard」是一款强大的可视化套件,旨在跟踪网络拓扑和性能,使调试更加简单。用 Python 编写(尽管某些对性能有重要影响的部分是用 C++实现的),这是一种颇具可读性的开发语言支持多 GPU。因此可以在不同的计算机上自由运行代码,而不必停止或重新启动程序比基于 Theano 的选项更快的模型编译编译时间比 Theano 短TensorFlow 不仅支持深度学习,还有支持强化学习和其他算法的工具。

缺点:

计算图是纯 Python 的,因此速度较慢图构造是静态的,意味着图必须先被「编译」再运行

5. Keras:

Keras 是一个更高级、对用户最友好的 API,具有可配置的后端,由 Google Brain 团队成员 Francis Chollet 编写和维护。

优点:

提供高级 API 来构建深度学习模型,使其易于阅读和使用编写规范的文档大型、活跃的社区位于其他深度学习库(如 Theano 和 Tensorflow,可配置)之上使用面向对象的设计,因此所有内容都被视为对象(如网络层、参数、优化器等)。所有模型参数都可以作为对象属性进行访问。例如:

model.layers[3].output 将提供模型的第三层model.layers[3].weights 是符号权重张量的列表

缺点:

由于用途非常普遍,所以在性能方面比较欠缺与 Tensorflow 后端配合使用时会出现性能问题(因为并未针对其进行优化),但与 Theano 后端配合使用时效果良好不像 Tensorflow 或 PyTorch 那样灵活TensorFlow 基础TensorFlow 是一种采用数据流图(data flow graphs),用于数值计算的开源软件库。其中 Tensor 代表传递的数据为张量(多维数组),Flow 代表使用计算图进行运算。数据流图用「结点」(nodes)和「边」(edges)组成的有向图来描述数学运算。「结点」一般用来表示施加的数学操作,但也可以表示数据输入的起点和输出的终点,或者是读取/写入持久变量(persistent variable)的终点。边表示结点之间的输入/输出关系。这些数据边可以传送维度可动态调整的多维数据数组,即张量(tensor)。


计算图与会话学习 

Tensorflow 的第一步是了解它的主要特色——「计算图」方法。基本上所有的 Tensorflow 代码都包含两个重要部分:

1. 创建「计算图」,表示计算的数据流

2. 运行「会话」,执行图中的运算

事实上,TensorFlow 将计算的定义与其执行分开。这两个部分将在以下各节中详细说明。在此之前,请记住第一步是导入 Tensorflolibrary!

import tensorflow as tf这样,Python 就可以访问 TensorFlow 的所有类、方法和符号。使用此命令,TensorFlow 库将在别名「tf」下导入,以便以后我们可以使用它而不必每次键入其全称「TensorFlow」。


声明:

参考自Python TensorFlow Tutorial – Build a Neural Network,本文简化了文字部分

文中有很多到官方文档的链接,毕竟有些官方文档是中文的,而且写的很好。

Tensorflow入门

资源:付费tensorflow教程

Tensorflow graphs

Tensorflow是基于graph的并行计算模型。关于graph的理解可以参考官方文档。举个例子,计算a=(b+c)∗(c+2)a=(b+c)∗(c+2),我们可以将算式拆分成一下:

d =b + ce =c +2a =d * e

转换成graph后的形式为: 

讲一个简单的算式搞成这样确实大材小用,但是我们可以通过这个例子发现:d=b+cd=b+c和e=c+2e=c+2是不相关的,也就是可以并行计算。对于更复杂的CNN和RNN,graph的并行计算的能力将得到更好的展现。

实际中,基于Tensorflow构建的三层(单隐层)神经网络如下图所示: 


Tensorflow data flow graph 

上图中,圆形或方形的节点被称为node,在node中流动的数据流被称为张量(tensor)。更多关于tensor的描述见官方文档

0阶张量 == 标量 

1阶张量 == 向量(一维数组) 

2阶张量 == 二维数组 

… 

n阶张量 == n维数组

tensor与node之间的关系: 

如果输入tensor的维度是5000×645000×64,表示有5000个训练样本,每个样本有64个特征,则输入层必须有64个node来接受这些特征。

上图表示的三层网络包括:输入层(图中的input)、隐藏层(这里取名为ReLU layer表示它的激活函数是ReLU)、输出层(图中的Logit Layer)。

可以看到,每一层中都有相关tensor流入Gradient节点计算梯度,然后这些梯度tensor进入SGD Trainer节点进行网络优化(也就是update网络参数)。

Tensorflow正是通过graph表示神经网络,实现网络的并行计算,提高效率。下面我们将通过一个简单的例子来介绍TensorFlow的基础语法。

A Simple TensorFlow example

用Tensorflow计算a=(b+c)∗(c+2)a=(b+c)∗(c+2), 1. 定义数据:

importtensorflowastf# 首先,创建一个TensorFlow常量=>2const = tf.constant(2.0, name='const')# 创建TensorFlow变量b和cb = tf.Variable(2.0, name='b')c = tf.Variable(1.0, dtype=tf.float32, name='c')

如上,TensorFlow中,使用tf.constant()定义常量,使用tf.Variable()定义变量。Tensorflow可以自动进行数据类型检测,比如:赋值2.0就默认为tf.float32,但最好还是显式地定义。更多关于TensorFlow数据类型的介绍查看官方文档。 

2. 定义运算(也称TensorFlow operation):

# 创建operationd = tf.add(b, c, name='d')e = tf.add(c, const, name='e')a = tf.multiply(d, e, name='a')

发现了没,在TensorFlow中,+−×÷+−×÷都有其特殊的函数表示。实际上,TensorFlow定义了足够多的函数来表示所有的数学运算,当然也对部分数学运算进行了运算符重载,但保险起见,我还是建议你使用函数代替运算符。

!!TensorFlow中所有的变量必须经过初始化才能使用,初始化方式分两步:

定义初始化operation

运行初始化operation

# 1. 定义init operationinit_op = tf.global_variables_initializer()

以上已经完成TensorFlow graph的搭建,下一步即计算并输出。

运行graph需要先调用tf.Session()函数创建一个会话(session)。session就是我们与graph交互的handle。更多关于session的介绍见官方文档

# sessionwithtf.Session()assess:# 2. 运行init operationsess.run(init_op)# 计算a_out = sess.run(a)    print("Variable a is {}".format(a_out))

值得一提的是,TensorFlow有一个极好的可视化工具TensorBoard,详见官方文档。将上面例子的graph可视化之后的结果为: 

The TensorFlow placeholder

对上面例子的改进:使变量b可以接收任意值。TensorFlow中接收值的方式为占位符(placeholder),通过tf.placeholder()创建。

# 创建placeholderb = tf.placeholder(tf.float32, [None,1], name='b')

第二个参数值为[None, 1],其中None表示不确定,即不确定第一个维度的大小,第一维可以是任意大小。特别对应tensor数量(或者样本数量),输入的tensor数目可以是32、64…

现在,如果得到计算结果,需要在运行过程中feed占位符b的值,具体为将a_out = sess.run(a)改为:

a_out = sess.run(a, feed_dict={b: np.arange(0,10)[:, np.newaxis]})

输出:

Variable a is[[  3.]

[  6.]

[  9.]

[ 12.]

[ 15.]

[ 18.]

[ 21.]

[ 24.]

[ 27.]

[ 30.]]

A Neural Network Example

神经网络的例子,数据集为MNIST数据集。 

1. 加载数据:

fromtensorflow.examples.tutorials.mnistimportinput_datamnist = input_data.read_data_sets("MNIST_data/", one_hot=True)

one_hot=True表示对label进行one-hot编码,比如标签4可以表示为[0, 0, 0, 0, 1, 0, 0, 0, 0, 0]。这是神经网络输出层要求的格式。

Setting things up

2. 定义超参数和placeholder

# 超参数learning_rate =0.5epochs =10batch_size =100# placeholder# 输入图片为28 x 28 像素 = 784x = tf.placeholder(tf.float32, [None,784])# 输出为0-9的one-hot编码y = tf.placeholder(tf.float32, [None,10])

再次强调,[None, 784]中的None表示任意值,特别对应tensor数目。

3. 定义参数w和b

# hidden layer => w, bW1 = tf.Variable(tf.random_normal([784,300], stddev=0.03), name='W1')b1 = tf.Variable(tf.random_normal([300]), name='b1')# output layer => w, bW2 = tf.Variable(tf.random_normal([300,10], stddev=0.03), name='W2')b2 = tf.Variable(tf.random_normal([10]), name='b2')

在这里,要了解全连接层的两个参数wb都是需要随机初始化的,tf.random_normal()生成正态分布的随机数。

4. 构造隐层网络

# hidden layerhidden_out = tf.add(tf.matmul(x, W1), b1)hidden_out = tf.nn.relu(hidden_out)

上面代码对应于公式: 

z=wx+bz=wx+b

h=relu(z)h=relu(z)

5. 构造输出(预测值)

# 计算输出y_ = tf.nn.softmax(tf.add(tf.matmul(hidden_out, W2), b2))

对于单标签多分类任务,输出层的激活函数都是tf.nn.softmax()。更多关于softmax的知识见维基百科

6. BP部分—定义loss 

损失为交叉熵,公式为 

J=−1m∑i=1m∑j=1nyijlog(y(i)j)+(1−y(i)jlog(1−y(i)j)J=−1m∑i=1m∑j=1nyjilog(yj(i))+(1−yj(i)log(1−yj(i))

公式分为两步:

对n个标签计算交叉熵

对m个样本取平均

y_clipped = tf.clip_by_value(y_,1e-10,0.9999999)cross_entropy = -tf.reduce_mean(tf.reduce_sum(y * tf.log(y_clipped) + (1- y) * tf.log(1- y_clipped), axis=1))

7. BP部分—定义优化算法

# 创建优化器,确定优化目标optimizer = tf.train.GradientDescentOptimizer(learning_rate=learning_rate).minimizer(cross_entropy)

TensorFlow中更多优化算法详见官方文档

8. 定义初始化operation和准确率node

# init operatorinit_op = tf.global_variables_initializer()# 创建准确率节点correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1))accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

correct_predicion会返回一个m×1m×1的tensor,tensor的值为True/False表示是否正确预测。

Setting up the trianing

9. 开始训练

# 创建sessionwithtf.Session()assess:# 变量初始化sess.run(init)    total_batch = int(len(mnist.train.labels) / batch_size)forepochinrange(epochs):        avg_cost =0foriinrange(total_batch):            batch_x, batch_y = mnist.train.next_batch(batch_size=batch_size)            _, c = sess.run([optimizer, cross_entropy], feed_dict={x: batch_x, y: batch_y})            avg_cost += c / total_batch        print("Epoch:", (epoch +1),"cost = ","{:.3f}".format(avg_cost))    print(sess.run(accuracy, feed_dict={x: mnist.test.images, y: mnist.test.labels}))

输出:

Epoch:1 cost = 0.586Epoch:2 cost = 0.213Epoch:3 cost = 0.150Epoch:4 cost = 0.113Epoch:5 cost = 0.094Epoch:6 cost = 0.073Epoch:7 cost = 0.058Epoch:8 cost = 0.045Epoch:9 cost = 0.036Epoch:10 cost = 0.027Trainingcomplete!0.9787

通过TensorBoard可视化训练过程: 

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

推荐阅读更多精彩内容

  • 今天的作品 红衣少女 耗时不算多 上色到崩溃 新到的彩铅难上色 手绘板上的色 我只能说 加点黄色就可以成蕃茄炒鸡蛋了
    flowla阅读 260评论 6 6
  • 译者:这篇文章更适用于国外的教学体系下的学生,他们很多大作业、需要进行大量的阅读;而我们则很少有这种类型的任务。但...
    ThinkCodeAct阅读 794评论 0 1
  • 服务工作讲究的是用心,细致,像是对于在Linckia海星客这样有着开放工位以及独立办公间的联合办公空间里的客户们,...
    skyjun阅读 206评论 1 1
  • 2017.06.17 姓名:代利云 公司:宁波慈星股份有限公司 宁波盛和塾《六项精进》235期学员。 【日精进打卡...
    代利云阅读 140评论 0 0