一 基本概念:
Tensorflow是一个计算密集型的编程系统,使用图(graphs)来表示计算任务,图(graphs)中的节点称之为op(operation),一个op获得0个或多个Tensor,执行计算,产生0个或多个Tensor。 Tensor 看作是一个 n 维的数组或列表。图必须在会话(Session)里被启动
使用图(graphs)来表示计算任务
在被称之为会话(Session)的上下文(context)中执行图
使用tensor表示数据
通过变量(Variable)维护状态
使用feed和fetch可以为任意的操作赋值或者从其中获取数据
Tensorflow结构
二 安装:
ubantu py3.5版:
CPU版本:
pip install http://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-1.0.1-cp35-cp35m-linux_x86_64.whl
Windows 在有 安装Anaconda的情况下
CPU版本:
pip install --upgrade --ignore-installed tensorflow
三 初识tensorflow (以下内容都基于1.0版本,不同版本会有些差异)
1、图
图默认已经注册,一组表示 tf.Operation计算单位的对象和tf.Tensor 表示操作之间流动的数据单元的对象
获取默认图:
tf.get_default_graph()
创建新图并使用:
g = tf.Graph() with g.as_default():#在上下文管理器(with模块)中,g作为默认图 a = tf.constant(1.0)
2、会话
运行TensorFlow操作图的类,使用默认注册的图(可以指定运行图)
会话可能拥有很多资源,如 tf.Variable,tf.QueueBase 和tf.ReaderBase,会话结束后需要进行资源释放(可以用with上下文管理器实现)
会话运行后返回值异常: RuntimeError:如果它Session处于无效状态(例如已关闭)。
TypeError:如果fetches或feed_dict键是不合适的类型。
ValueError:如果fetches或feed_dict键无效或引用 Tensor不存在
Tensorflow 中Feed操作(占位):
意义:在程序执行的时候,不确定输入的是什么,提前“占个坑”
语法:placeholder提供占位符,run时候通过feed_dict指定参数
例:
import tensorflow as tf val1 = tf.placeholder(tf.float32) val2 = tf.placeholder(tf.float32) sum = tf.add(val1, val2) with tf.Session() as sess: print(sess.run(sum,feed_dict={val1:1.0, val2:2.0}))
3、张量
张量是Tensorflow基本的数据格式, 有三部分:形状,数据类型,名字
张量的阶:
张量的数据类型:
张量的属性: graph(张量所属的默认图) op(张量的操作名) name(张量的字符串描述) shape(张量形状)
张量的动态形状与静态形状:
静态形状: 创建一个张量或者由操作推导出一个张量时,初始状态的形状
tf.Tensor.get_shape:获取静态形状
tf.Tensor.set_shape():更新Tensor对象的静态形状,通常用于在不能直接推 断的情况下
注意:
1、转换静态形状的时候,遵循1-D到1-D,2-D到2-D的规则,不能跨阶数改变形状
2、 对于已经固定或者设置静态形状的张量/变量,不能再次设置静态形状
动态形状: 一种描述原始张量在执行过程中的一种形状
tf.reshape:改变原来的形状创建一个具有不同动态形状的新张量
注意:
1、tf.reshape()动态创建新张量时,元素个数需要和改变前的个数匹配
生成张量:
tf.random_normal(shape,mean=0.0, stddev=1.0,dtype=tf.float32,seed=None,name=None) (常用)
tf.zeros(shape,dtype=tf.float32,name=None)
tf.ones(shape,dtype=tf.float32,name=None)
tf.constant(value,dtype=None,shape=None,name="Const")
... ...
详细的可以参考API(中文):http://wiki.jikexueyuan.com/project/tensorflow-zh/api_docs/python/index.html
张量的转换(常用):
tf.String_to_number(string_tensor,out_type=None,name=None)
tf.cast(x, dtype, name=None)
tf.shape(input, name=None)
tf.reshape(tensor, shape, name=None)
... ...
张量的拓展:
tf.concat(values, axis, name=‘concat‘)
4、变量
变量也是一种OP,是一种特殊的张量,能够进行存储持久化,它的 值就是张量
1)、变量的创建
tf.Variable(initial_value=None,name=None) 创建一个带值initial_value的新变量 name属性表示变量名字
assign(value) 为变量分配一个新值 返回新值
eval(session=None) 计算并返回此变量的值
2)、变量的初始化
tf.global_variables_initializer()
3)、变量的作用域
作用 : 让模型代码更加清晰,作用分明, 在tensorboard中更易阅读
创建:
tf.variable_scope(<scope_name>)创建指定名字的 变量作用域
如:
with tf.variable_scope("train"): ‘‘‘ 作用域内的代码 ‘‘‘
5、可视化学习Tensorboard
TensorBoard 通过读取 TensorFlow 的数据序列化-events文件来运行
在程序中加入代码:
tf.summary.FileWriter(‘路径‘, graph= 想可视化的图) 返回filewriter,写入事件文件到指定目录(最好用绝对路径),以提供给tensorboard使用
在命令行开启:
tensorboard --logdir=/tmp/tensorflow/summary/test/
一般浏览器打开为127.0.0.1:6006
注:修改程序后,再保存一遍会有新的事件文件,打开默认为最新
tensorboard中,图的符号意义:
在tensorboard中显示变量的变化:
1、收集变量: tf.summary.scalar(name=’’,tensor) 收集对于损失函数和准确率 等单值变量,name为变量的名字,tensor为值
tf.summary.histogram(name=‘’,tensor) 收集高维度的变量参数
tf.summary.image(name=‘’,tensor) 收集输入的图片张量能显示图片
2、合并变量写入事件文件:merged = tf.summary.merge_all()
3、运行合并:summary = sess.run(merged),每次迭代都需运行
4、添加:FileWriter.add_summary(summary,i),i表示第几次的值
6、模型保存和加载
创建一个Saver对象(假设返回saver,用于模型保存和加载):
tf.train.Saver(var_list=None,max_to_keep=5) 其中:
var_list:指定将要保存和还原的变量。它可以作为一个 dict或一个列表传递.
max_to_keep:指示要保留的最近检查点文件的最大数量。 创建新文件时,会删除较旧的文件。如果无或0,则保留所有 检查点文件。默认为5(即保留最新的5个检查点文件。)
保存模型:
saver.save(sess,"保存模型的路径(自己指定目录即可)"
保存文件格式:checkpoint文件
加载模型:
saver.restore(sess,"保存模型的路径(和上面的路径一致)"
7、自定义命令行参数
1、tf.app.flags,它支持应用从命令行接收参数,可以用来指定集群配置等.在它下面有各种定义参数的类型:
DEFINE_string(flag_name, default_value, docstring)
DEFINE_integer(flag_name, default_value, docstring)
DEFINE_boolean(flag_name, default_value, docstring)
DEFINE_float(flag_name, default_value, docstring)
2、tf.app.flags.,在flags有一个FLAGS标志,它在程序中可以调用到我们 前面具体定义的flag_name
3、通过tf.app.run()启动main(argv)函数
8、用以上知识实现一个简单的线性回归案例
def mylinearregression(): """ 自实现线性回归 :return: None """ with tf.variable_scope("data"): #作用域 # 手动创建训练数据 # x表示训练数据的特征 有100个样本,1个特征 X = tf.random_normal([100, 1], mean=0.0, stddev=1.0, name="X") #生成一组服从标准正太分布的数据 # y_true表示训练数据的标签, 跟x是线性关系 y_true = tf.matmul(X, [[0.7]]) + 0.8 with tf.variable_scope("model"): #作用域 # 建立模型 # 由准备的数据(x是100行1列的数据,y_true也是100行1列的数据)可以看出,权重是 1行1列的数据 weights = tf.Variable(tf.random_normal([1, 1], mean=0.0, stddev=1.0), name="weights") bias = tf.Variable(0.0) # 得出预测值 y_predict = tf.matmul(X, weights) + bias with tf.variable_scope("Optimize"): #作用域 # 计算真实值与预测值之间的均方误差(损失函数) loss = tf.reduce_mean(tf.square(y_true - y_predict)) #tf.square求方差 tf.reduce_mean求均值 # 梯度下降优化误差,指定学习率,返回一个梯度下降优化器 train_op = tf.train.GradientDescentOptimizer(0.2).minimize(loss) # 收集变量 tf.summary.scalar("loss", loss) tf.summary.scalar("bias", bias) tf.summary.histogram("weight", weights) # 定义初始化变量OP init_op = tf.global_variables_initializer() # 定义一个合并变量的OP merged = tf.summary.merge_all() # 创建一个Saver saver = tf.train.Saver() # 开启会话 with tf.Session() as sess: # 运行初始化 sess.run(init_op) # 打印一下初始化随机的权重和偏置 print("随机初始化的权重为%f,偏置为%f" % (weights.eval(), bias.eval())) # 创建事件文件 filewriter = tf.summary.FileWriter("./tmp/summary/test/", graph=sess.graph) #此路径只须指定目录且目录存在 # 加载模型 if os.path.exists("./tmp/ckpt/checkpoint"): #此路径中目录与模型保存的目录一致,文件名固定为checkpoint saver.restore(sess, "./tmp/ckpt/regressionmodel")#此路径与模型保存的路径一致 # 循环优化, 30是指定训练的步数(可更改) for i in range(30): # 运行优化 sess.run(train_op) # 运行合并结果 summary = sess.run(merged) # 写入变量结果 filewriter.add_summary(summary, i) print("训练第%d次的结果:权重为%f,偏置为%f" % (i, weights.eval(), bias.eval())) # 保存模型 saver.save(sess, "./tmp/ckpt/regressionmodel")#路径中的目录路径须存在,且要指定文件名称
return None
# 自定义命令行参数 tf.app.flags.DEFINE_string("data_home", "./data/", "训练数据来源") tf.app.flags.DEFINE_integer("max_step", 10000, "训练步数") FLAGS = tf.app.flags.FLAGS def main(argv): print(argv) print(FLAGS.data_home) print(FLAGS.max_step) if __name__ == "__main__": tf.app.run()