Tensorflow基础

1 深度学习

深度学习,如深度神经网络、卷积神经网络和递归神经网络已被应用 计算机视觉、语音识别、自然语言处理、音频识别与生物信息学等领域 并获取了极好的效果。

机器学习与深度学习的简单区别:

 机器学习深度学习
应用场景指纹识别、特征物体检测等领域应用于文字识别、人脸技术、语义分析、智能监控等领域。
数据量机器学习能够适应各种数据量,特别是数据量较小的场景需要大量数据才能完美理解
执行时间执行时间更少包含有很多参数需要很多时间
解决问题方法遵循标准程序以解决问题。它将问题拆分成数个部分,对其进行分别解决,而后再将结果结合起来以获得所需的答案以集中方式解决问题,而不必进行问题拆分。

2 深度学习框架之Tensorflow

Tensorflow特点如下:

(1)真正的可移植性:引入各种计算设备的支持包括CPU/GPU/TPU,以及能够很好地运行在移动端, 如安卓设备、ios、树莓派等等 ;

(2)多语言支持:Tensorflow 有一个合理的c++使用界面,也有一个易用的python使用界面来构建和 执行你的graphs,你可以直接写python/c++程序;

(3)高度的灵活性与效率:TensorFlow是一个采用数据流图(data flow graphs),用于数值计算的开源软件库 能够灵活进行组装图,执行图。随着开发的进展,Tensorflow的效率不算在提高 ;

(4)支持:TensorFlow 由谷歌提供支持,谷歌投入了大量精力开发 TensorFlow,它希望 TensorFlow 成为机器学习研究人员和开发人员的通用语言

镜像下载地址https://pypi.org/project/tensorflow/1.14.0/#files

3 op,图和会话

3.1 op

operation(op):用来专门运算的操作节点,只要用tensorflow的API定义的函数都是op。计算都是使用tensor去计算的,op只是一个载体,tensor是一个被载的物体

类型示例
标量运算Add、Sub、Mul、Div、Exp、Log、Greater、Less、Equal
向量运算Concat、Slice、Splot、Constant、Rank、Shape、Shuffle
矩阵运算Matmul、MatrixInverse、MatrixDeterminant
带状态的运算Variable、Assign、AssignAdd
神经网络组件SoftMax、Sigmoid、ReLU、Convolution2D、MaxPooling
存储、恢复Save、Restore
队列及同步运算Enqueue、Dequeue、MutexAcquire、MutexRelease
控制流Merge、Switch、Enter、Leave、NextIteration

3.2 图

graph(图):整个程序的结构,包含了一组op和tensor。没有特别的作用,就是指代整个程序结构,分配内存。默认已经注册,一组表示 tf.Operation计算单位的对象和tf.Tensor 表示操作之间流动的数据单元的对象

图是可以创建的,相当于单独分配一个内存存储另外一个图即程序的结构,就相当于两部分互不干扰

①获取调用: tf.get_default_graph() op、sess或者tensor 的graph属性

②图的创建:tf.Graph() 使用新创建的图     

g = tf.Graph()     
with g.as_default():             
    a = tf.constant(1.0)             
    assert c.graph is g

Tensorflow的程序有个特点,很多with(上下文管理器),比如使用设备是with,在某个设备下面进行计算也是with,使用会话进行计算,使用这张图也是with。

3.3 会话

(1)会话:运行TensorFlow操作图的类,使用默认注册的图(可以指定运行图)。tf.Session()

注意:会话当中只能运行一个图

会话资源:会话可能拥有很多资源,如 tf.Variable,tf.QueueBase 和tf.ReaderBase,会话结束后需要进行资源释放

会话作用:运行图的结构;分配资源计算;掌握资源(如变量的资源,队列,线程)

①sess = tf.Session()     sess.run(...)      sess.close()

②使用上下文管理器 with tf.Session() as sess:     sess.run(...)  加参数config=tf.ConfigProto(log_device_placement=True)可以看到程序在哪里进行运算

③交互式:tf.InteractiveSession()

(2)会话的run()方法:

run(fetches, feed_dict=None,graph=None)    运行ops和计算tensor

嵌套列表,元组, namedtuple,dict或OrderedDict(重载的运算符也能运行)

feed_dict 允许调用者覆盖图中指定张量的值,提供给 placeholder使用

返回值异常:① RuntimeError:如果它Session处于无效状态(例如已关闭)②TypeError:如果fetches或feed_dict键是不合适的类型③ValueError:如果fetches或feed_dict键无效或引用 Tensor不存在。

整个框架的设计思想:数据在整个图的结构里面进行运算流动

Tensorflow Feed操作

意义:在程序执行的时候,不确定输入的是什么,提前“占个坑”

语法:placeholder提供占位符,run时候通过feed_dict指定参数

4 张量

4.1 张量

tensor(张量):就是指代tensorflow中的数据,可以把一个张量想象成一个n维的数组或列表。一个张量有一个静态类型和动态类型的维数,张量可以在图中的节点之间流通.其实张量更代表的就是一种多位数组。

张量由三部分,名字(它用于键值对的存储,用于后续的检索,如Const: 0),形状(描述数据的每一维度的元素个数,如(1,2)),数据类型(如int32)组成。

(1)阶:张量的维数来被描述为阶,但是张量的阶和矩阵的阶并不是同一个概念,张量的阶(有时是关于如顺序或度数或者是n维)是张量维数的一个数量描述。

数学实例Python例子
0纯量(只有大小)t = 66
1向量(大小和方向)t = [6.6,8.8]
2矩阵(数据表)t = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
33阶张量(数据立体)t = [[[2], [4], [6]], [[8], [10], [12]], [[14], [16], [18]]]
nn阶 ....

(2)数据类型

(3)张量的属性:

graph 张量所属的默认图
op张量的操作名
name张量的字符串描述
shape张量形状

(4)TensorFlow中,张量具有静态形状和动态形状。张量的动态形状与静态形状:

①静态形状: 创建一个张量或者由操作推导出一个张量时,初始状态的形状

tf.Tensor.get_shape:获取静态形状

tf.Tensor.set_shape():更新Tensor对象的静态形状,通常用于在不能直接推断的情况下

②动态形状: 一种描述原始张量在执行过程中的一种形状

tf.reshape:创建一个具有不同动态形状的新张量

③注意:

1)对于静态形状来说,一旦张量形状固定了,不能在此设置静态形状,不能跨维度修改,1-D到1-D,2-D到2-D。

2)动态形状可以去创建一个新的张量,tf.reshape()动态创建新张量时,元素个数不能不匹配,1-D到2-D,1-D到3-D

3)动态形状和静态形状的区别在于:有没有生成一个新的张量数据

4.2 张量的操作

(1)常用生成张量

①生成固定值张量

tf.zeros(shape, dtype=tf.float32, name=None)         创建所有元素设置为零的张量。此操作返回一个dtype具有形状shape和所有元素设置为零的类型的张量

tf.zeros_like(tensor, dtype=None, name=None)            给tensor定单张量(),此操作返回tensor与所有元素设置为零相同的类型和形状的张量。

tf.ones(shape, dtype=tf.float32, name=None)            创建一个所有元素设置为1的张量。此操作返回一个类型的张量,dtype形状shape和所有元素设置为1。

tf.ones_like(tensor, dtype=None, name=None)            给tensor定单张量(),此操作返回tensor与所有元素设置为1 相同的类型和形状的张量。

tf.fill(dims, value, name=None)                 创建一个填充了标量值的张量。此操作创建一个张量的形状dims并填充它value。

tf.constant(value, dtype=None, shape=None, name='Const')            创建一个常数张量。

②创建随机张量

tf.truncated_normal(shape, mean=0.0, stddev=1.0, dtype=tf.float32, seed=None, name=None)             从截断的正态分布中输出随机值,和 tf.random_normal() 一样,但是所有数字都不超过两个标准差

tf.random_normal(shape, mean=0.0, stddev=1.0, dtype=tf.float32, seed=None, name=None)              从正态分布中输出随机值,由随机正态分布的数字组成的矩阵

(2)张量变换

①改变类型

tf.string_to_number(string_tensor, out_type=None, name=None)  将输入Tensor中的每个字符串转换为指定的数字类型。

tf.to_double(x, name='ToDouble')

tf.to_float(x, name='ToFloat')

tf.to_bfloat16(x, name='ToBFloat16')

tf.to_int32(x, name='ToInt32')

tf.to_int64(x, name='ToInt64')

tf.cast(x, dtype, name=None)

②形状和变换

tf.shape(input, name=None)    返回张量的形状

tf.size(input, name=None)

tf.rank(input, name=None)

tf.reshape(tensor, shape, name=None)

tf.squeeze(input, squeeze_dims=None, name=None )  默认将input中维度是1的那一维去掉。可以使用squeeze_dims参数,来指定需要去掉的位置。

tf.expand_dims(input, dim, name=None)   作用与squeeze相反,添加一个指定维度

③切片与扩展

tf.concat(concat_dim, values, name='concat')

 

5 变量

变量也是一种OP,是一种特殊的张量,能够进行存储持久化,它的 值就是张量

5.1 Variable类

tf.Variable.init(initial_value, trainable=True, collections=None, validate_shape=True, name=None)      创建一个带值的新变量initial_value

initial_value:A Tensor或Python对象可转换为a Tensor.变量的初始值.必须具有指定的形状,除非 validate_shape设置为False.

trainable:如果True,默认值也将该变量添加到图形集合GraphKeys.TRAINABLE_VARIABLES,该集合用作Optimizer类要使用的变量的默认列表

collections:图表集合键列表,新变量添加到这些集合中.默认为[GraphKeys.VARIABLES]

validate_shape:如果False允许使用未知形状的值初始化变量,如果True,默认形状initial_value必须提供.

name:变量的可选名称,默认'Variable'并自动获取

5.1 变量的创建

tf.Variable(initial_value=None,name=None)    创建一个带值initial_value的新变量

assign(value) 为变量分配一个新值 返回新值

eval(session=None) 计算并返回此变量的值

name属性表示变量名字

5.2 变量的初始化

tf.global_variables_initializer() 添加一个初始化所有变量的op

注意:要在会话中开启

import tensorflow as tf
a = tf.constant([6,6,6])
var = tf.Variable(tf.random_normal([2,2], mean=0.0, stddev=1.0), name="variable")
print(a, var)
# 显示的初始化op,必须要做
init_op = tf.global_variables_initializer()

with tf.Session() as sess:
    # 必须运行初始化op
    sess.run(init_op)
    print(sess.run([a, var]))

5.3 tensorflow变量作用域

作用:让模型代码更加清晰,作用分明。也相当于上下文环境,相当于定义函数一样

通过tf.variable_scope()创建指定名字的变量作用域。加上with语句就可以在整个itcast变量作用域下就行操作。

加了作用域后的后台显示对比

6 Tensorboard可视化

Tensorboard可视化步骤如上图

(1)数据序列化-events文件:TensorBoard 通过读取 TensorFlow 的事件文件来运行

(2)tf.summary.FileWriter('/tmp/', graph= default_graph)                                    返回filewriter,写入事件文件到指定目录(最好用绝对路径),以提供给tensorboard使用

(3)开启tensorboard。命令:tensorboard    --logdir=/tmp/

一般浏览器打开为127.0.0.1:6006,1.14.0版本打开后如下图

GRAPHS:用于显示程序的结构

SCALARS:一般用于显示0维度值,如准确率,损失

HISROGRAMS:一般用于显示高纬度的值如权重,偏置

SCALARS和HISROGRAMS是需要自己手动指定的

import tensorflow as tf
a = tf.constant(6.0, name="a")
b = tf.constant(8.0, name="b")
c = tf.add(a, b, name="add")
var = tf.Variable(tf.random_normal([2,2], mean=0.0, stddev=1.0), name="variable")
print(a, var)
# 显示的初始化op,必须要做
init_op = tf.global_variables_initializer()

with tf.Session() as sess:
    # 必须运行初始化op
    sess.run(init_op)
    # 把程序的图结构写入事件文件, graph:把指定的图写进事件文件当中
    filewriter = tf.summary.FileWriter("./tmp/", graph=sess.graph)
    print(sess.run([c, var]))

//总结:①变量op能够持久化保存,普通张量op是不行的

//②当定义一个变量op的时候,一定要在会话当中去运行初始化

//③name参数:在tensorboard使用的时候显示名字,可以让相同op名字的进行区分

该图结构显示如下

图中符号的意义如下:

回归和线性是一个迭代的过程,如果时间非常长,有不想输出日志文件,就可以用Tensorboard观察里面一些值的变化,所以有增加变量显示

6.2 增加变量显示

目的:观察模型的参数、损失值等变量值的变化

(1)收集变量

tf.summary.scalar(name=’’,tensor)收集对于损失函数和准确率 等单值变量,name为变量的名字,tensor为值
tf.summary.histogram(name=‘’,tensor)收集高维度的变量参数
tf.summary.image(name=‘’,tensor)收集输入的图片张量能显示图片

(2)合并变量写入事件文件

merged = tf.summary.merge_all()

运行合并:summary = sess.run(merged),每次迭代都需运行

添加:FileWriter.add_summary(summary,i),i表示第几次的值

 

7 模型的保存与加载

在训练或者测试过程中,总会遇到需要保存训练完成的模型,然后从中恢复继续我们的测试或者其它使用。模型的保存和恢复也是通过tf.train.Saver类去实现,它主要通过将Saver类添加OPS保存和恢复变量到checkpoint。它还提供了运行这些操作的便利方法。

tf.train.Saver(var_list=None, reshape=False, sharded=False, max_to_keep=5, keep_checkpoint_every_n_hours=10000.0, name=None, restore_sequentially=False, saver_def=None, builder=None, defer_build=False, allow_empty=False, write_version=tf.SaverDef.V2, pad_step_number=False)

var_list:指定将要保存和还原的变量。它可以作为一个dict或一个列表传递.

max_to_keep:指示要保留的最近检查点文件的最大数量。创建新文件时,会删除较旧的文件。如果无或0,则保留所有检查点文件。默认为5(即保留最新的5个检查点文件。)

keep_checkpoint_every_n_hours:多久生成一个新的检查点文件。默认为10,000小时

(1)保存

调用Saver.save()方法。save(sess, save_path, global_step=None),checkpoint是专有格式的二进制文件,将变量名称映射到张量值。

注意:保存要指定路径和文件名,与事件文件不一样(指定路径就行)。

(2)恢复

方法是restore(sess, save_path),save_path是以前保存参数的路径,我们可以使用tf.train.latest_checkpoint来获取最近的检查点文件(也恶意直接写文件目录)

8 自定义命令行

tf.app.run(),默认调用main()函数,运行程序。main(argv)必须传一个参数。

tf.app.flags,它支持应用从命令行接受参数,可以用来指定集群配置等。在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)

tf.app.flags.FLAGS,在flags有一个FLAGS标志,它在程序中可以调用到我们前面具体定义的flag_name.

9 tensorflow实现一个简单的线性回归

线性回归模型:W1X1+W2X2+WnXn+bias

线性回归定义:权重与特征乘积相加的和再加一个偏置bias,有多个个特征就有多少权重。

线性回归目的:找到一个合适的参数使得参数与特征组合之后,他预测的值与目标值很相近

实现步骤:

①准备特征值和目标值:这里简单实现使用1个特征值一个目标值,准备100个样本

②建立模型:随机初始化准备权重和偏置,这里准备一个权重一个偏置,y_predict=xw+b  xw为两个矩阵相乘

③求损失函数即误差:均方误差为(y-y')^2+...+(y100-y100')^2/100

④梯度下降优化损失过程,tensorflow有实现,调用他的实现,指定学习率。

注意:模型参数必须用变量,因为变量有一个参数默认trainable=true,变量会随着梯度下降的更新与变化。

涉及的API:矩阵相乘运算: tf.matmul(x, w)                    平方:tf.square(error)                     均值: tf.reduce_mean(error)

梯度下降优化:tf.train.GradientDescentOptimizer(learning_rate)               参数:learning_rate:学习率

方法:minisize(loss)最小优化损失                     返回值:梯度下降op

实现代码如下:

import tensorflow as tf
import os

# 定义命令行参数,第一个参数:名字,默认值,说明
tf.app.flags.DEFINE_integer("max_step", 100, "模型训练的步数")
tf.app.flags.DEFINE_string("model_dir", " ", "模型文件的加载的路径")

# 定义获取命令行参数名字
FLAGS = tf.app.flags.FLAGS

with tf.variable_scope("data"):
    # 1、准备数据,x 特征值 [100, 1] 100行1列   y 目标值[100]
    x = tf.random_normal([100, 1], mean=1.6, stddev=0.6, name="x_data")
    # 真实值,假设已经知道是y=0.6x+0.8  矩阵相乘必须是二维的
    y_true = tf.matmul(x, [[0.6]]) + 0.8

with tf.variable_scope("model"):
    # 2、建立线性回归模型 1个特征,1个权重, 一个偏置 y = x w + b
    # 随机给一个权重和偏置的值,让他去计算损失,然后再当前状态下优化,用变量定义才能优化
    weight = tf.Variable(tf.random_normal([1, 1], mean=0.0, stddev=1.0), name="w")
    bias = tf.Variable(0.0, name="b")

    # 预测值
    y_predict = tf.matmul(x, weight) + bias

with tf.variable_scope("loss"):
    # 3、建立损失函数,均方误差
    loss = tf.reduce_mean(tf.square(y_true - y_predict))

with tf.variable_scope("optimizer"):
    # 4、梯度下降优化损失 leaning_rate,不能指定太大,一帮有2-3位小数,越小循环训练的次数就要越多
    train_op = tf.train.GradientDescentOptimizer(0.01).minimize(loss)

    # 1、收集tensor
tf.summary.scalar("losses", loss)
tf.summary.histogram("weights", weight)

# 定义合并tensor的op
merged = tf.summary.merge_all()

# 定义一个初始化变量的op
init_op = tf.global_variables_initializer()

# 定义一个保存模型的实例
saver = tf.train.Saver()

# 通过会话运行程序
with tf.Session() as sess:
    # 初始化变量
    sess.run(init_op)

    # 打印随机最先初始化的权重和偏置
    print("随机初始化的参数权重为:%f, 偏置为:%f" % (weight.eval(), bias.eval()))

    # 建立事件文件
    filewriter = tf.summary.FileWriter("./tmp/event", graph=sess.graph)

    # 加载模型,覆盖模型当中随机定义的参数,从上次训练的参数结果开始
    if os.path.exists("./tmp/checkpoint"):
        saver.restore(sess, FLAGS.model_dir)

    # 循环训练 运行优化
    for i in range(FLAGS.max_step):
        sess.run(train_op)

        # 运行合并的tensor
        summary = sess.run(merged)

        # 添加变量显示
        filewriter.add_summary(summary, i)
        print("第%d次优化的参数权重为:%f, 偏置为:%f" % (i, weight.eval(), bias.eval()))

    # 保存模型
    saver.save(sess,  FLAGS.model_dir)

 

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐