1、 tensorflow简介
Tensorflow 是 google 开源的机器学习工具,在2015年11月其实现正式开源,开源协议Apache 2.0。
Tensorflow采用数据流图(data flow graphs)来计算, 所以首先我们得创建一个数据流流图,然后再将我们的数据(数据以张量(tensor)的形式存在)放在数据流图中计算. 节点(Nodes)在图中表示数学操作,图中的边(edges)则表示在节点间相互联系的多维数据数组, 即张量(tensor).训练模型时tensor会不断的从数据流图中的一个节点flow到另一节点, 这就是TensorFlow名字的由来.
张量(Tensor):张量有多种. 零阶张量为 纯量或标量 (scalar) 也就是一个数值. 比如 [1],一阶张量为 向量 (vector), 比如 一维的 [1, 2, 3],二阶张量为 矩阵 (matrix), 比如 二维的 [[1, 2, 3],[4, 5, 6],[7, 8, 9]],以此类推, 还有三维以上的多维。
2、 tensorflow基础
实际上编写tensorflow可以总结为两步.
(1)组装一个graph;
(2)使用session去执行graph中的operation。
2.1、概念说明
下面是 graph , session , operation , tensor 四个概念的简介。
Tensor:类型化的多维数组,图的边;
Operation:执行计算的单元,图的节点;
Graph:一张有边与点的图,其表示了需要进行计算的任务;
Session:称之为会话的上下文,用于执行图。
2.2、一个例子:
import tensorflowas tf
import numpyas np
#tensorflow中大部分数据是float32
# create real data 用numpy生成训练数据
x_data= np.random.rand(100).astype(np.float32)
y_data= x_data* 0.1 + 0.3
### create tensorflow structure start! ###
# 定义变量 用tf.Variable来定义变量w和b
Weights= tf.Variable(tf.random_uniform([1], -1.0, 1.0))
biases= tf.Variable(tf.zeros([1]))
# 定义如何计算预测值
y= Weights* x_data+ biases
# 损失函数 平方损失函数
loss= tf.reduce_mean(tf.square(y- y_data))
# 梯度下降优化器,定义learning rate optimizer = 优化器
optimizer= tf.train.GradientDescentOptimizer(0.5)
# 训练目标是损失最小化
train= optimizer.minimize(loss)
# 初始化变量, 即初始化weights和biases
init= tf.global_variables_initializer()
# 创建session,进行参数初始化
sess= tf.Session()
sess.run(init)
# 开始训练200步, 每20步输出一下两个参数
for stepin range(201):
sess.run(train)
if step% 20 == 0:
print(step, sess.run(Weights), sess.run(biases))
### create tensorflow structure end ###
在上面的例子中,我们想要预测的方程式y=0.1*x + 0.3,给定训练样本,通过梯度下降法来预测参数W和偏置b,我们使用numpy生成了我们的训练数据:
x_data = np.random.rand(100).astype(np.float32)
y_data = x_data * 0.1 + 0.3
随后,我们使用tf.Variable定义了我们的变量Weights和biases(以下简称w和b),Weights通过一个均匀分布随机产生,而bias则设置为0,同时二者的形状均为1维,即就是一个数:
Weights = tf.Variable(tf.random_uniform([1],-1.0,1.0))
biases = tf.Variable(tf.zeros([1]))
好了,有了变量,我们想要学习w和b,只需要用训练数据x来得到预测值,最小化预测值和实际值的差距就好,所以,我们定义了损失函数为平方损失函数,并通过0.5学习率的梯度下降法来进行参数调整:
#如何计算预测值
y = Weights * x_data + biases# loss functionloss = tf.reduce_mean(tf.square(y-y_data))
#梯度下降优化器,定义learning rate
optimizer = tf.train.GradientDescentOptimizer(0.5)
#训练目标是loss最小化
train = optimizer.minimize(loss)
在tf中定义的变量都需要经过初始化的操作,所以我们定义了一个初始化变量的操作:
#初始化变量,即初始化 Weights 和 biases
init = tf.global_variables_initializer()
接下来我们就可以开始训练了,训练必须创建一个session,通过run方法对指定的节点进行训练,这里一定要注意先要对参数进行初始化,否则后面是无法开始训练的。想要观察训练过程中的参数变化的话,也需要通过run方法:
# 创建session,进行参数初始化
# 开始训练200步, 每20步输出一下两个参数
for step in range(201):
sess.run(train)
if step% 20 == 0:
print(step, sess.run(Weights), sess.run(biases))
这里我们直接run的是train这一步,想要运行这一步,必须先得到optimizier和loss,想要得到loss就要得到预测值....依次往前推,所以run(train)实际上就是对整个tensor流图的训练。
最后贴出来看一下输出结果:
0 [-0.05120224] [ 0.5192185]
20 [ 0.04687011] [ 0.32806551]
40 [ 0.08647783] [ 0.307143]
60 [ 0.09655845] [ 0.30181798]
80 [ 0.09912409] [ 0.30046269]
100 [ 0.09977707] [ 0.30011776]
120 [ 0.09994329] [ 0.30002996]
140 [ 0.09998558] [ 0.30000764]
160 [ 0.09999632] [ 0.30000195]
180 [ 0.09999906] [ 0.30000052]
200 [ 0.09999976] [ 0.30000013]
2.3、数据结构
Tensorflow的数据结构有着rank,shape,data types的概念,下面来分别讲解。
(1)rank
Rank一般是指数据的维度,其与线性代数中的rank不是一个概念。
例如我们所说的标量(Scalar):
s = 8,维数为 0,所以它的 rank 为 0。
例如矢量(Vector):
v = [1, 2, 3],rank 为 1。
例如矩阵(Matrix):
一个二维矩阵 rank 为 2
又例如 rank 为 3 的 tensor:
t = [[[2], [4], [6]], [[8], [10], [12]], [[14], [16], [18]]],以此类推。
(2)shape
tensorflow 用 3 种方式描述一个 tensor 的维数:
rank, shape(shape指tensor每个维度数据的个数), 以及 dimension number (维数)
所以 shape 和 rank 的意思的一样的,只是表达的形式不同。
shape 写成只包含整数的 list 或者 tuple 形式,例如 [1, 4, 2]
(3)datatype
tensor 的数据结构除了 维数(dimensionality),还有 数据类型(data type)。
例如 32位浮点数(32 bits floating point) 等等,可以从下面的链接中查看完整的:
https://www.tensorflow.org/programmers_guide/dims_types#data_types
3、 Variables
(1)介绍
当训练模型时,需要使用Variables保存与更新参数。Variables会保存在内存当中,所有tensor一旦拥有Variables的指向就不会在session中丢失。其必须明确的初始化而且可以通过Saver保存到磁盘上。Variables可以通过Variables初始化。
weights = tf.Variable(tf.random_normal([784, 200], stddev=0.35),name="weights")
biases = tf.Variable(tf.zeros([200]), name="biases")
其中,tf.random_normal是随机生成一个正态分布的tensor,其shape是第一个参数,stddev是其标准差。tf.zeros是生成一个全零的tensor。之后将这个tensor的值赋值给Variable。
(2)初始化
实际在其初始化过程中做了很多的操作,比如初始化空间,赋初值(等价于tf.assign),并把Variable添加到graph中等操作。注意在计算前需要初始化所有的Variable。一般会在定义graph时定义global_variables_initializer,其会在session运算时初始化所有变量。
直接调用global_variables_initializer会初始化所有的Variable,如果仅想初始化部分Variable可以调用tf.variables_initializer。
Init_ab = tf.variables_initializer([a,b],name=”init_ab”)
Variables可以通过eval显示其值,也可以通过assign进行赋值。Variables支持很多数学运算,具体可以参照官方文档。
(3)Variables与constant的区别
值得注意的是Variables与constant的区别。Constant一般是常量,可以被赋值给Variables,constant保存在graph中,如果graph重复载入那么constant也会重复载入,其非常浪费资源,如非必要尽量不使用其保存大量数据。而Variables在每个session中都是单独保存的,甚至可以单独存在一个参数服务器上。可以通过代码观察到constant实际是保存在graph中。
(4)命名
另外一个值得注意的地方是尽量每一个变量都明确的命名,这样易于管理命令空间,而且在导入模型的时候不会造成不同模型之间的命名冲突,这样就可以在一张graph中容纳很多个模型。
4、 placeholders与feed_dict
当我们定义一张graph时,有时候并不知道需要计算的值,比如模型的输入数据,其只有在训练与预测时才会有值。这时就需要placeholder(用占位符表示)与feed_dict的帮助。占位符并没有初始值,它只会分配必要的内存。在会话中,占位符可以使用 feed_dict 馈送数据。
feed_dict是一个字典,在字典中需要给出每一个用到的占位符的取值。(sess.run使用的时候要给出前面的占位符的取值。)
定义一个placeholder,可以使用tf.placeholder(dtype,shape=None,name=None)函数。
foo = tf.placeholder(tf.int32,shape=[1],name='foo')
bar = tf.constant(2,name='bar')
result = foo + bar
with tf.Session() as sess:
print(sess.run(result))
在上面的代码中,会抛出错误(InvalidArgumentError),因为计算result需要foo的具体值,而在代码中并没有给出。这时候需要将实际值赋给foo。最后一行修改如下(其中最后的dict就是一个feed_dict,一般会使用python读入一些值后传入,当使用minbatch的情况下,每次输入的值都不同):
print(sess.run(result,{foo:[3]}))