简介程序流程基础概念TensorconstantVariableplaceholerSparseTensorSessionGraphopFetchFeedTensorBoard模型保存与恢复实现卷积常用函数1. tf.nn.conv2d2. tf.nn.relu3. tf.nn.max_pool4. tf.contrib.layers.flatten5. tf.contrib.layers.fully_connected6. tf.nn.softmax_cross_entropy_with_logits7. tf.reduce_mean
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)来维护计算状态。
类型 | 描述 | 用途 |
---|---|---|
Session | 会话 | 图必须在称之为“会话”的上下文中执行。会话将图的op分发到诸如CPU或者GPU上计算 |
Graph | 描述计算过程 | 必须在Session中启动 |
tensor | 数据 | 数据类型之一,代表多维数组 |
op | 操作 | 图中的节点被称之为op,一个op获得0或者多个Tensor,执行计算,产生0或者多个Tensor |
Variable | 变量 | 数据类型之一,运行过程中可以被改变,用于维护状态 |
feed | 赋值 | 为op的tensor赋值 |
fetch | 取值 | 从op的tensor中取值 |
Constant | 常量 | 数据类型之一,不可变 |
通过化学实验进行形象比喻,整个图就是Graph,对试管加热等操作就是Operation,而在导管中流动就是我们的Tensor。
先来看个简单的示例,来大体有个了解:
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()
在TensorFlow中,用tensor来表示其所使用的数据结构,简单点理解tensor就是一个多维数组。任何一个物体,我们都可以用几个特征来描述它,每个特征可以划分成一个维度。
属性 | 用途 |
---|---|
tf.Tensor.dtype | tensor中数据类型 |
tf.Tensor.name | tensor名称 |
tf.Tensor.shape | 形状 |
tf.Tensor.op | 产生该tensor的op |
tf.Tensor.graph | 该tensor所在的 |
tf.constant
值不能改变的一种Tensor
tf.Varivable
是值可以改变的Tensor。Variable通常可以将一个统计模型中的参数表示为一组变量。例如,可以将一个神经网络的权重当作一个tensor存储在变量中。在训练图的重复运行过程中去更新这个tensor
# 创建变量
name_variable = tf.Variable(value, name)
TensorFlow提供一种占位符操作,在执行时需要为其提供数据。这有点类似我们编写sql语句时使用?占位符一样,可以理解为预编译。
方法 | 用途 |
---|---|
tf.placeholder(dtype,shape=None,name=None) | 为一个tensor插入一个占位符 |
# 创建占位符
input_value = tf.placeholder(type, shape, name)
一种稀疏的Tensor,类似线性代数的稀疏矩阵。
# 定义稀疏矩阵,只需要定义非零值,自动填充0值,indices指定非0下标,values对应下标出的值,dense_shape总矩阵shape
SparseTensor(indices=[[0, 0], [1, 2]], values=[1, 2], dense_shape=[3, 4])
[[1, 0, 0, 0]
[0, 0, 2, 0]
[0, 0, 0, 0]]
Session的作用是用来启动Graph的绘画。用tensorflow构建的数据流图是静态的图,session.run()
可以让静态图里的某一部分动起来。
方法 | 用途 |
---|---|
tf.Session.run(fetches,feed-dict=Noe,options=Node,run_metadata=None) | 运行fetches中的操作节点并求其 |
tf.Session.close() | 关闭会话 |
tf.Session.graph | 返回加载该会话的图() |
tf.Session.as_default() | 设置该对象为默认会话,并返回一个上下文管理器 |
示例代码:
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)123
Graph:要组装的结构,由许多操作组成,其中的每个连接点代表一种操作
方法 | 用途 |
---|---|
tf.Graph.as_graph_def() | 返回一个图的序列化的GraphDef,表示序列化的GraphDef可以导入到另外一个图(使用import_graph_def() ) |
tf.Graph.get_operations() | 返回图中的操作节点列表 |
tf.Operation.name | 操作节点op的名称 |
tf.Operation.type | 操作节点op的类型 |
tf.Operation.inputs | 操作节点的输入与输出 |
tf.Operation.run(session=None,feed_dict=None) | 在会话中执行该操作 |
tf.add_to_collection(name,value) | 基于默认的图,其功能便为Graph.add_to_collection() |
tf.get_collection(key,scope=None) | 基于默认的图,其功能便为Graph.get_collection() |
op:接受零个或多个输入Tensor,返回零个或多个Tensor
为了获取操作输出的内容,可以在使用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]))
可以通过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.]}))
用TensorFlow保存图的信息到日志中:
tf.summary.FileWriter("保存路径", sess.graph)
用TensorBoard读取并展示日志
$tensorboard --logdir=日志路径
summary总结:
在tensorflow中最简单的保存与加载模型的方式是通过Saver对象.
方法 | 用途 |
---|---|
tf.train.Saver.save(sess,save_path,global_step=None, latest_filename=None,meta_graph_suffix=’meta’,write_meta_graph=True) | 保存变量 |
tf.train.Saver.restore(sess,save_path) | 恢复变量 |
tf.train.Saver.last_checkpoints() | 列出最近未删除的checkpoint文件名 |
tf.train.Saver.set_last_checkpoints(last_checkpoints) | 设置checkpoint文件名列表 |
tf.train.Saver.set_last_checkpoints_with_time(last_checkpoints_with_time) | 设置checkpoint文件名列表和时间戳 |
保存模型:
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")
tf.nn.conv2d(input,filter,strides,padding,use_cudnn_on_gpu=True,data_format='NHWC',dilations=[1, 1, 1, 1],name=None)
实现卷积函数,tf.nn.conv2d(X,W, strides = [1,s,s,1], padding = 'SAME')
"NHWC"
, "NCHW"
。默认为 "NHWC"
,即[batch, in_height, in_width,in_channels]tf.nn.relu(features,name=None)
对features按元素求relu
函数,features可以是任意shape
tf.nn.max_pool(value,ksize,strides,padding,data_format='NHWC',name=None)
最大值池化操作,tf.nn.max_pool(A, ksize = [1,f,f,1], strides = [1,s,s,1], padding = 'SAME')
tf.contrib.layers.flatten(inputs,outputs_collections=None,scope=None)
tf.contrib.layers.flatten(P)
输入P,此函数将每个示例展平为1D向量,同时保持批量大小。 它返回一个形状为[batch_size,k]的平坦张量。
tf.contrib.layers.fully_connected(inputs,num_outputs,activation_fn=tf.nn.relu ...)
全连接层,tf.contrib.layers.fully_connected(F, num_outputs)
tf.nn.softmax_cross_entropy_with_logits(labels=None,logits=None,dim=-1,name=None)
进行交叉熵运算:
流程大概分为三步:第一步是先对logits做一个softmax,第二步对softmax和labels按元素做一个交叉熵,最后是根据dim指定的维度做求和
tf.reduce_mean(input_tensor,axis=None,keepdims=None ...)
求输入的input_tensor均值,keepdims指定是否保持之前的维度