一、TensorFlow基础
TensorFlow是Google开源的机器学习库,基于DistDelief进行研发的第二代人工智能系统,用来帮助我们快速的实现DL和CNN等各种算法公式。其名字本身描述了它自身的执行原理:Tensor(张量)意味着N维数组,Flow(流)意味着基于数据流图的计算。
数据流图中的图就是我们所说的有向图。我们知道,在图这种数据结构中包含两种基本元素:节点和边。这两种元素在数据流图中有各自的作用。节点用来表示要进行的数学操作,另外,任何一种操作都有输入/输出,因此它也可以表示数据的输入的起点/输出的终点。边表示节点与节点之间的输入/输出关系,一种特殊类型的数据沿着这些边传递。这种特殊类型的数据在TensorFlow被称之为tensor,即张量,所谓的张量通俗点说就是多维数组。当我们向这种图中输入张量后,节点所代表的操作就会被分配到计算设备完成计算。
下图是TensorFlow设计图中数据的流向,他会帮助你更好的认识TensorFlow工作过程:
到现在,我们只是认识了TensorFlow。接下来通过TensorFlowd的四个特性,来说明我们为什么要使用TensorFlow:
灵活性: 非严格的“神经网络”库。这意味这我们的计算只要能够表示为数据流图,就能够使用。
可移植性:底层核心采用C++编译,可以运行在台式机、服务器、手机移动等设备上,提供对分布式的支持,能够快速构建深度学习集群。
多语言支持:前端支持Python,C/C++,Java以及Go,以及非官方支持的Scala,但是目前对Python接口支持最好。
高效:提供对线程、队列、异步操作支持,同时支持运行在CPU和GPU上,能够充分发挥硬件潜力.
可以说正是由于以上四个特性,使得TensorFlow的使用逐渐流行开来。其中我认为TensorFlow最关键的一点是允许我们将计算的过程描述为一张图(Graph),我将其称这张图为”计算图”,能让我们很容易的操作其中的网络结构。
TensorFlow使用Graph来描述计算任务。图中的节点被称之为op,一个op可以接受0或多个tensor作为输入,也可产生0或多个tensor作为输出。任何一个Graph要想运行,都必须借助上下文Session。通过Session启动Graph,并将Graph中的op分发到CPU或GPU上,借助Session提供执行这些op。op被执行后,将产生的tensor返回。借助Session提供的feed和fetch操作,我们可以为op赋值或者获取数据。计算过程中,通过变量(Variable)来维护计算状态。
下表说明TensorFlow中常用的库函数:
二、TensorFlow理论与实践
TensorFlow程序的基本过程通常分为两步:构建阶段和执行阶段。在构建阶段,我们组织多个op,最终形成Graph。在执行阶段,使用会话执行op。
import tensorflow as tf
# 定义‘符号’变量,也称为占位符
a = tf.placeholder("int32")
b = tf.placeholder("int32")
# 构造一个op节点
y = tf.multiply(a, b)
# 建立会话
sess = tf.Session()
# 运行会话,输入数据,并计算节点,同时打印结果
print(sess.run(y, feed_dict={a: 3, b: 3}))
# 任务完成, 关闭会话.
sess.close()
1.构建阶段
构造阶段的主要目的是为了构建一张计算图。构建图的第一步是创建源op,源op不需要任何输入,源op的输出被传递给其他op作为输入,例如常量(Constant)。
op:接受(流入)零个或多个输入,返回(流出)零个或多个输出。
数据类型主要分为tensor,variable,constant。
tensor:多维array或list
# 创建tensor,指定类型、名称
tensor_name=tf.placeholder(type, shape, name)
variable:通常可以将一个统计模型中的参数表示为一组变量。例如,你可以将一个神经网络的权重当作一个tensor存储在变量中。在训练图的重复运行过程中去更新这个tensor。
# 创建变量
name_variable = tf.Variable(value, name)
# 初始化单个变量
init_op=variable.initializer()
# 初始化所有变量
init_op=tf.initialize_all_variables()
# 更新操作
update_op=tf.assign(variable to be updated, new_value)
简单示例
这里我们来创建一个包含三个op的图,其中两个constant op,一个matmul op。
import tensorflow as tf
# 创建作为第一个常量op,该op会被加入到默认的图中
# 1*2的矩阵,构造器的返回值代表该常量op的返回值
matrix_1 = tf.constant([[3., 3.]])
# 创建第二个常量op,该op会被加入到默认的图中
# 2*1的矩阵
matrix_2 = tf.constant([[2.], [2.]])
# 创建第三个op,为矩阵乘法op,接受matrix_1和matrix_2作为输入,product代表乘法矩阵结果
product = tf.matmul(matrix_1, matrix_2)
到现在我们已经创建好了包含三个op的图。下面我们要通启动该图,执行运算。
2.执行阶段
Session
首先我们需要创建一个Session对象。在不传参数的情况下,该Session的构造器将启动默认的图。之后我们可以通过Session对象的run(op)来执行我们想要的操作。
简单示例
# 创建会话
sess = tf.Session()
# 赋值操作
sess.run([output], feed_dict={input1:value1, input2:value1})
# 用创建的会话执行操作
sess.run(op)
# 取值操作
# 关闭会话
sess.close()
结合构建阶段和执行阶段,完整示例如下:
import tensorflow as tf
# 创建作为第一个常量op,该op会被加入到默认的图中
# 1*2的矩阵,构造器的返回值代表该常量op的返回值
matrix_1 = tf.constant([[3., 3.]])
# 创建第二个常量op,该op会被加入到默认的图中
# 2*1的矩阵
matrix_2 = tf.constant([[2.], [2.]])
# 创建第三个op,为矩阵乘法op,接受matrix_1和matrix_2作为输入,product代表乘法矩阵结果
product = tf.matmul(matrix_1, matrix_2)
# 获取sess
sess = tf.Session()
# 来执行矩阵乘法op
result = sess.run(product)
# 输出矩阵乘法结果
print("result:",result)
# 任务完毕,关闭Session
sess.close()
除了通过Session的close()的手动关闭外,也可以使用with代码块:
with tf.Session() as sess:
result=sess.run(product)
print("result:",result)
输出结果:
result:[[ 12.]]
3.构建数据结构
在TensorFlow中,用tensor来表示其所使用的数据结构,简单点理解tensor就是一个多维数组.任何一个物体,我们都可以用几个特征来描述它.每个特征可以划分成一个维度.比如:一小组图像集表示为一个四维浮点数数组, 这四个维度分别是 [batch, height,width, channels].
Variables
TensorFlow使用Variables来维护图执行过程中的状态信息.下面我们演示一个计数器:
import tensorflow as tf
#创建一个变量,初始化为0
state = tf.Variable(0, name="counter")
#创建一个常量
one = tf.constant(1)
#加法计算
new_value = tf.add(state, one)
#更新变量值
update = tf.assign(state, new_value)
init_op = tf.initialize_all_variables()
sess = tf.Session()
sess.run(init_op)
print(sess.run(state))
for _ in range(10):
sess.run(update)
print(sess.run(state))
输出结果:
0
1
2
3
4
5
6
7
8
9
10
Fetch
为了获取操作输出的内容,可以在使用Session对象的run(op)时,传入一些tensor,这些tensor用来取回我们想要的结果。
import tensorflow as tf
value_1 = tf.constant(3.0)
value_2 = tf.constant(2.0)
value_3 = tf.constant(5.0)
# 2.0+5.0
temp_value=tf.add(value_2,value_3)
# 3.0+(2.0+5.0)
result=tf.add(value_1,temp_value)
sess = tf.Session()
print(sess.run([temp_value,result]))
Feed
我们可以通过TensorFlow对象的placeholder()为变量创建指定数据类型占位符,在执行run(op)时通过feed_dict来为变量赋值。
import tensorflow as tf
input_1 = tf.placeholder(tf.float32)
input_2 = tf.placeholder(tf.float32)
output = tf.add(input_1, input_2)
with tf.Session() as sess:
# 通过feed_dict来输入,outpu表示输出
print(sess.run([output],feed_dict={input_1:[7.],input_2:[2.]}))
placeholder
TensorFlow提供一种占位符操作,在执行时需要为其提供数据.这有点类似我们编写sql语句时使用?占位符一样,你可以理解为预编译.
input_value = tf.placeholder(tf.float32,shape=(1024,1024))
4.模型保存和恢复
在tensorflow中最简单的保存与加载模型的方式是通过Saver对象。
保存模型
import tensorflow as tf
def save_model():
v1 = tf.Variable(tf.random_normal([1, 2]), name="v1")
v2 = tf.Variable(tf.random_normal([2, 3]), name="v2")
init_op = tf.global_variables_initializer()
saver = tf.train.Saver()
with tf.Session() as sess:
sess.run(init_op)
saver_path = saver.save(sess, "./model.ckpt")
print("model saved in file: ", saver_path)
加载模型
用同一个Saver对象来恢复变量,注意,当你从文件恢复变量是,不需要对它进行初始化,否则会报错。
import tensorflow as tf
def load_model():
v1 = tf.Variable(tf.random_normal([1, 2]), name="v1")
v2 = tf.Variable(tf.random_normal([2, 3]), name="v2")
saver = tf.train.Saver()
with tf.Session() as sess:
saver.restore(sess,"./model.ckpt")
print("mode restored")
有兴趣的读者可以继续学习训练模型,移植到移动设备教程。