前言
由于公司产品的变化,我需要编写一些TensorFlow的代码来测试我们产品的深度学习模块。 最近也在学习TensorFlow。 所以先暂停卷积神经网络部分的更新。开始写一些tensorflow的东西。 话说白话了这么久的理论~~ 终于可以跟大家上点代码了。 对于tensorflow,下面我都简称tf
环境搭建
这个我没细研究,直接docker hub上找到TensorFlow的镜像下载,然后启动。 或者大家也可以搭建一个集成了TensorFlow的notebook
什么是tensorflow
一个2分类单隐藏层的神经网络
先上代码。
这是模拟一个最简单的神经网络的代码。 只有一条样本两个特征维度(只是拿来做demo的), 隐藏层使用relu作为激活函数。有3个神经元,整个神经网络的目的是做二分类,所以输出层的激活函数是sigmoid,损失函数(成本函数)也是sigmoid的损失函数。 前向传播算法是使用矩阵乘法实现。 反向传播是用tf提供的标准的梯度下降,学习率为0.01,训练轮数为100. 没有加正则。 我们查看经过训练后隐藏层和输出层的权重信息如下:
为什么用tensorflow
如果有同学用过类似Keras这种高度封装API的神经网络库的话,就会发现tf的代码简直太复杂太繁琐了。 上面只是最简单的神经网络,没加正则没用mini batch甚至样本只有一个,连实现前向传播都得自己写代码。 实际应用的话代码会更复杂很多。 但是使用Keras可能就是几行代码的事,学习难度小很多。 那我们为什么还要使用tf呢? 我知道的好处是tf灵活,支持分布式执行,比如tf on k8s现在很火。是现在做深度学习平台的不二选择。 据我所知现在各大厂的深度学习平台都是用tf弄出来的。 当然对于我来说,学习tf的目的只有一个,就是测试我们自己的深度学习平台。
tensorflow基础概念
tensorflow = tensor + flow。 其中tensor是tf的数据结构,flow代表着tf的计算框架----计算图
tensor,又名张量。在tf中所有的数据都是以张量的形式表现的。从功能上来看,张量是一个多维数组。比如在我们上面的demo中,我们用来模拟样本数据的x 和对应的label y_都是tensor。但tensor在tf里的实现并不是直接采用数组的或其他任何已知的数据结构。 如果说类似的话,tensor的机制有点像spark中RDD的惰性计算, 在spark中我们的计算流是惰性的,在代码执行每一个transform的时候并不会真正的执行,而是把计算过程记录下来,等到执行到action的时候才会真正的执行。 这是惰性计算。 tensor以及tensor的计算表现也类似。 当我们执行以下代码时,并不会得到真正的结果,而是会得到一个结果的引用。
我们在tf声明了两个常量, a和b。 他们是tf中的tensor(张量)。 当我们执行了一个加法操作的时候,打印出的结果并不是他们的计算结果。 而是一个tensor的结果。其中打印的第一个字段:add_35:0 表示这个节点add_35, 0 是说c这个张量是节点add_35的第一个输出。 打印的第二个字段是shape,也就是维度。 说明这个tensor是几乘几的矩阵。 我们的例子中是shape=(1,2) 表明这是一个1*2的矩阵。 第三个字段是tensor的类型,我们这里是float32类型。
如果用画图的方式表示出来,大概就是下面这样的
上图中的每一个节点都是一个运算,而每一条边代表了计算之间的依赖关系,一个运算的输入依赖于另一个运算的输出。 这就是tf的计算图,也就是tensorflow中flow代表的意思。 在tf遇到真正需要执行的那段代码之前, 所有的计算都不会触发,取而代之的是tf在内部维护一个计算图。 在遇到需要执行的时候, 按照计算图依次进行计算。
计算图的执行节点--会话
刚才我们讲了tf是如何组织数据和计算图的。 它不会真正的执行,而是等待某个时机的到来,按照计算图依次进行计算。 那么这个时机就是会话。 如下:
可以看到上图中我们使用python的with as大法管理tf 的会话声明周期。 在里面我们并没有去管a和b,相反我们只用了一行代码print(session.run(c)) 就打印出了计算结果。 正如我之前所说,tf会维护一个计算图。 当我们真正的去计算c的时候。它会按照计算图从头计算一遍。
结尾
今天就写这么多吧。 快半夜11点了。。。。
领取专属 10元无门槛券
私享最新 技术干货