简介程序流程基础概念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总矩阵shapeSparseTensor(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)# 获取sesssess = tf.Session()# 来执行矩阵乘法opresult = sess.run(product)# 输出矩阵乘法结果print("result:",result)# 任务完毕,关闭Sessionsess.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 tfvalue_1 = tf.constant(3.0)value_2 = tf.constant(2.0)value_3 = tf.constant(5.0)# 2.0+5.0temp_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 tfinput_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 tfdef 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 tfdef 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指定是否保持之前的维度