深度学习第一天(TensorFlow框架、实现线性回归训练过程)

TensorFlow框架、实现线性回归训练过程

  • 0学习目标
  • 1、TF数据流图
    • 学习目标
    • 1、数据流图介绍
    • 2、案例:TensorFlow实现一个加法运算
      • 2.1 代码
      • 2.2 TensorFlow结构分析
  • 2、图与TensorBoard
    • 学习目标
    • 1、什么是图结构
    • 2、图相关操作
      • 2.1 图中操作、会话默认属性
      • 2.2 获取默认图
      • 2.3 创建图
    • 3、 TensorBoard:可视化学习
      • 3.1 数据序列化-events文件
      • 3.2 启动TensorBoard
    • 4、OP
      • 4.0 哪些是OP?
      • 4.1 指令名称
  • 3会话
    • 学习目标
    • 1、会话
      • 1.1 init(target='', graph=None, config=None)
      • 1.2 会话的run()
      • 1.3 feed操作
  • 4 张量
    • 学习目标
      • 目标
      • 应用
    • 1、张量(Tensor)
      • 1.1张量的类型
      • 1.2 张量的阶(也就是张量的形状)
    • 2、创建张量的指令:固定张量和随机张量
      • 固定值张量
      • 随机值张量
    • 3、张量的变换:类型的变换和形状的变化
      • 3.1 类型改变
      • 3.2 形状改变
    • 4、张量的数学运算
  • 5 变量OP
    • 目标
    • 应用
    • 1、变量
      • 1.1创建变量
      • 1.2 变量OP的方法
    • 2、命名空间与共享变量
      • 2.1 定义一个相同名字的变量
      • 2.2 使用tf.variable_scope()修改OP命名空间
      • 2.2 tf.get_variable共享变量
  • 6 高级API
    • 学习目标
      • 目标
      • 应用
    • 其它基础API
      • 1、 tf.app
      • 2、tf.image
      • 3、tf.gfile
      • 4、tf.summary
      • 5、tf.python_io
      • 6、tf.train
      • 7、tf.nn
    • 高级API
      • 1、tf.keras
      • 2、tf.layers
      • 3、tf.contrib
      • 4、tf.estimator
    • 关于TensorFlow的API图示
  • 7 案例:实现线性回归
    • 学习目标
    • 目标
    • 应用
    • 1、线性回归原理复习
    • 2、案例:实现线性回归的训练
      • 2.1 案例确定
      • 2.2 API
        • 运算
        • 平方
        • 均值
        • 梯度下降优化API
      • 2.3 步骤分析
      • 2.4 实现完整功能
      • 2.5 学习率的设置、步长的设置与梯度爆炸
      • 2.6 变量的trainable设置观察
    • 3、增加其他功能
      • 3.1 增加命名空间
      • 3.2 增加变量显示
      • 3.3 模型的保存与加载
      • 3.4 命令行参数使用

0学习目标

  • 说明TensorFlow的数据流图结构
  • 应用TensorFlow操作图
  • 说明会话在TensorFlow程序中的作用
  • 应用TensorFlow实现张量的创建、形状类型修改操作
  • 应用Variable实现变量op的创建
  • 应用Tensorboard实现图结构以及张量值的显示
  • 应用tf.train.saver实现TensorFlow的模型保存以及加载
  • 应用tf.app.flags实现命令行参数添加和使用
  • 应用TensorFlow实现线性回归

1、TF数据流图

学习目标

  • 目标

    • 说明TensorFlow的数据流图结构
  • 应用

1、数据流图介绍

深度学习第一天(TensorFlow框架、实现线性回归训练过程)_第1张图片
深度学习第一天(TensorFlow框架、实现线性回归训练过程)_第2张图片
TensorFlow是一个采用数据流图(data flow graphs),用于数值计算的开源软件库。节点(Operation)在图中表示数学操作,图中的线(edges)则表示在节点间相互联系的多维数据数组,即张量(tensor)。

2、案例:TensorFlow实现一个加法运算

2.1 代码

# 实现一个加法运算
#Session是TensorFlow为了控制和输出文件的执行语句,运行session.run()就能获得运算结果或者部分运算结果
import tensorflow as tf
a = tf.constant(1)
b = tf.constant(2)
# 不能直接使用a+b
sum_=tf.add(a,b)
# TensorFlow的输出并不像之前那样,直接print就可以了,TensorFlow的输出需要建立一个会话才能够输出。#Tensorflow使用Session来执行定义好的计算图
sess = tf.Session() #等价于with tf.Session() as sess:,另外,当使用with tf.Session() as #sess:时,输出也可以使用print(sum.eval())
print(sess.run(sum_))

TensorFlow函数:tf.Session()和tf.Session().as_default()的区别:https://blog.csdn.net/Enchanted_ZhouH/article/details/77571939
tf.Session():创建一个会话 f.Session().as_default():创建一个默认会话

注意问题:警告指出您的CPU支持AVX运算加速了线性代数计算,即点积,矩阵乘法,卷积等。可以从源代码安装TensorFlow来编译,当然也可以选择关闭

import os
os.environ['TF_CPP_MIN_LOG_LEVEL']='2'
# tensorflow-gpu虽然正常执行没有报错,但也会出现红色信息,同理上述两句话仍然适用。

2.2 TensorFlow结构分析

TensorFlow 程序通常被组织成一个构建图阶段和一个执行图阶段. 在构建阶段, op(节点) 的执行步骤 被描述成一个图. 在执行阶段, 使用会话执行执行图中的 op.

TesorFlow的命名来源于本身的运行原理。Tensor(张量)意味着N维数组,Flow(流)意味着基于数据流图的计算。TensorFlow是张量从图像的一端流动到另一端的计算过程,这也是TensorFlow的编程模型。

  • 构建图阶段:图的定义。执行图阶段:通过会话输出。

  • 图和会话 :

    • 图:这是 TensorFlow 将计算表示为指令之间的依赖关系的一种表示法
    • 会话:TensorFlow 跨一个或多个本地或远程设备运行数据流图的机制。即通过会话输出
  • 张量(tensor):TensorFlow 中的基本数据对象。如add(X,Y),其中X,Y为张量,add为节点(op)

  • 节点(op):提供图当中执行的操作,如:add(),sum()

  • 深刻理解graph(图)、session、ophttps://www.cnblogs.com/jiaxblog/p/9054051.html

    import tensorflow as tf
    # 新建一张图
    g=tf.Graph()
    # 为了能够看到输出,Tensorflow使用Session来执行定义好的计算图
    sess = tf.Session()
    a = tf.constant(1)
    b = tf.constant(2)
    sum_=tf.add(a,b)
    #不能看到输出结果
    print(sum_)
    # 能够看到输出结果
    print(sess.run(sum_))
    # 查看系统默认建立的图
    print(tf.get_default_graph())
    # 查看我们自己建立的一张图
    print(g)
    
    # 怎样使用我们自己建立的g图呢?通过with g.as_default():
    with g.as_default():
        pass
    

2、图与TensorBoard

学习目标

  • 目标
    • 说明图的基本使用
    • 应用tf.Graph创建图、tf.get_default_graph获取默认图
    • 知道开启TensorBoard过程
    • 知道图当中op的名字
  • 应用

1、什么是图结构

图包含了一组tf.Operation代表计算单元的对象(如add())和tf.Tensor代表计算单元之间流动的数据(如add(X,Y)中的X,Y)。

2、图相关操作

2.1 图中操作、会话默认属性

默认op、sess都含有graph属性 ,都在一张图中

2.2 获取默认图

Graph默认注册,并可通过调用访问 tf.get_default_graph,要将操作添加到默认图形中,直接创建OP即可。

 # 实现一个加法运算
    a = tf.constant(3.0)
    b = tf.constant(4.0)
    
    sum = tf.add(a, b)
    
    # 图:打印出来,其实就是一个分配内存的地址。图中包含的所有东西都共用同一个地址
    # more所有的张量、op、会话都在一张图当中
    print(tf.get_default_graph())
    
    # print(sum)
    # 会话,默认只能运行默认的图,不能运行其它的(可以通过参数解决)
    with tf.Session() as sess:
        print(sess.run(sum1))
        print(a.graph)
        print(b.graph)
        print(sess.graph)

2.3 创建图

可以通过tf.Graph自己创建图,如果要在这张图中创建OP,典型用法是使用tf.Graph.as_default上下文管理器

 # 自己创建一张图
    g = tf.Graph()
    with g.as_default():
      # 在g图中定义了一个operation
      c = tf.constant(30.0)
      assert c.graph is g

那么TensorFlow有一个亮点就是,我们能看到自己写的程序,这个功能就是Tensorboard,在这里我们先简单介绍一下基本功能。后面根据能力在使用一些高级功能

3、 TensorBoard:可视化学习

TensorFlow 可用于训练大规模深度神经网络所需的计算,使用该工具涉及的计算往往复杂而深奥。为了更方便 TensorFlow 程序的理解、调试与优化,有了TensorBoard 的可视化工具。
深度学习第一天(TensorFlow框架、实现线性回归训练过程)_第3张图片

3.1 数据序列化-events文件

TensorBoard 通过读取 TensorFlow 的事件文件来运行,需要将数据生成一个序列化的 Summary protobuf 对象。

  # 切记:尽量存放到绝对目录,而且路径中不要出现中文。
    # 返回filewriter,写入事件文件到指定目录(最好用绝对路径),以提供给tensorboard使用。graph后面是指将哪张图序列化到文件中。
    # 一般在会话中序列化文件
    tf.summary.FileWriter('/tmp/tensorflow/summary/test/', graph=sess.graph)

这将在指定目录中生成一个 event 文件,其名称格式如下:

 events.out.tfevents.{timestamp}.{hostname}

3.2 启动TensorBoard

 #在anaconda中输入下面命令,conda list查看是否安装TensorBoard,如果没有安装,需要安装好后才能使用。本机安装的tensorboard==1.8版本,然后找到event 文件所在的目录,输入以下命令,logdir后面是event所在的目录
    # 相对路径
    tensorboard  --logdir="/tmp/tensorflow/summary/test/"
    # 绝对路径。 切记:尽量存放到绝对目录,而且路径中不要出现中文
    tensorboard  --logdir="F:/tmp/summary"
    如果在执行其他的程序时,仍然将event文件保存在了同一目录下,在启动TensorBoard后,它会调用最近的event文件,因为event文件名中有时间戳。

注意:在浏览器中打开网址的时候,直接复制粘贴,是什么就是什么,如在浏览器窗口中粘贴http://aa:6006会出现提示TensorBoardhttp://aa:6006,不要选TensorBoardhttp://aa:6006,直接粘贴http://aa:6006运行,否则无法找到图。

在浏览器中打开 TensorBoard 的图页面 127.0.0.1:6006 ,会看到与以下图形类似的图,在GRAPHS模块我们可以看到以下图结构
深度学习第一天(TensorFlow框架、实现线性回归训练过程)_第4张图片

# 代码如下
import os
os.environ['TF_CPP_MIN_LOG_LEVEL']='2'

import tensorflow as tf
# 实现一个加法运算
a = tf.constant(3.0)
b = tf.constant(4.0)

sum = tf.add(a, b)
with tf.Session() as sess:
    tf.summary.FileWriter("F:/tmp/summary/",graph=sess.graph)
    print(sess.run(sum))

4、OP

4.0 哪些是OP?

深度学习第一天(TensorFlow框架、实现线性回归训练过程)_第5张图片
只要是tf下的API我们都可以称之为一个OP,也称之为指令

a = tf.constant(3.0, dtype=tf.float32)
b = tf.constant(4.0) # also tf.float32 implicitly
total = a + b
print(a)
print(b)
print(total)

打印语句会生成:

Tensor("Const:0", shape=(), dtype=float32)
Tensor("Const_1:0", shape=(), dtype=float32)
Tensor("add:0", shape=(), dtype=float32)

注意,打印出来的是张量值,可以理解成OP当中包含了这个值。并且每一个OP指令都对应一个唯一的名称,如上面的Const:0,这个在TensorBoard上面也可以显示

请注意,tf.Tensor 对象以输出张量的 tf.Operation 明确命名。张量名称的形式为 “:”,其中:

  • ” 是生成该张量的指令的名称
  • ” 是一个整数,它表示该张量在指令的输出中的索引

4.1 指令名称

  • 上面的是系统自动命名的,也可以自己手动给OP重新命一个名字去覆盖系统命名的名字

tf.Graph对象为其包含的 tf.Operation对象定义一个命名空间。TensorFlow 会自动为您的图中的每个指令选择一个唯一名称,但您也可以指定描述性名称,使程序阅读起来更轻松。我们可以以下方式改写指令名称

  • 每个创建新的 tf.Operation 或返回新的 tf.Tensor 的 API 函数可以接受可选的 name 参数。

    例如,tf.constant(42.0, name=“answer”) 创建一个名为 “answer” 的新 tf.Operation 并返回一个名为 “answer:0” 的 tf.Tensor。如果默认图已包含名为 “answer” 的指令,则 TensorFlow 会在名称上附加 “1”、“2” 等字符,以便让名称具有唯一性。

  • 当修改好之后,我们在Tensorboard显示的名字也会被修改

  a = tf.constant(3.0, name="a")
    b = tf.constant(4.0, name="b" )

深度学习第一天(TensorFlow框架、实现线性回归训练过程)_第6张图片

3会话

学习目标

  • 目标
    • 应用sess.run或者eval运行图程序并获取张量值
    • 应用feed_dict机制实现运行时填充数据
    • 应用placeholder实现创建占位符
  • 应用

1、会话

一个运行TensorFlow operation的类。相当于连接前端和后端的一个枢纽,开启程序,分配资源的一个作用。会话包含以下两种开启方式

  • tf.Session:用于完整的python程序当中。python程序中通过使用sess.run()来运行operation
  • tf.InteractiveSession():用于交互式(命令行)上下文中的TensorFlow ,例如shell。交互式中通过使用sess.eval()来运行operation
  • sess是会话,graph是图
 #在命令行中输入:
  import tensorflow as tf
  # 开启图程序
  tf.InteractiveSession()
  
  # 建立一个固定张量
  tf.zeros([3,4],dtype=tf.float32)
  #输出张量的结果
  tf.zeros([3,4],dtype=tf.float32)
  
  
  #建立一个随机张量,并输出结果
  tf.random_normal([3,4],mean=0.0,stddev=1.0).eval()

1、TensorFlow 使用 tf.Session 类来表示客户端程序(通常为 Python 程序,但也提供了使用其他语言的类似接口)与 C++ 运行时之间的连接

2、tf.Session 对象使用分布式 TensorFlow ,运行时提供对本地计算机中的设备和远程设备的访问权限。

1.1 init(target=’’, graph=None, config=None)

会话可能拥有的资源,如 tf.Variable,tf.QueueBase和tf.ReaderBase。当这些资源不再需要时,释放这些资源非常重要。因此,需要调用tf.Session.close会话中的方法,或将会话用作上下文管理器。以下两个例子作用是一样的:

# 第一种方法
# 使用close()方法,这种比较麻烦,通常使用第二种方法,它会自动的关闭
sess = tf.Session()
sess.run(...)
sess.close()


# 第二种方法
# 使用上下文管理器,它会自动调用tf.Session.close
with tf.Session() as sess:
  sess.run(...)
  • tf.Session(target=’’, graph=None, config=None)里面有三个参数。可以指定也可以不指定
  • target。 如果将此参数留空(默认设置),会话将仅使用本地计算机中的设备。可以指定 grpc:// 网址,以便指定 TensorFlow 服务器的地址,这使得会话可以访问该服务器控制的计算机上的所有设备。
  • graph: 默认情况下,新的 tf.Session 将绑定到当前的默认图而不是新建的.并且只能运行当前的默认图中operation。如果通过graph参数去修改运行图,当然修改了图就要运行对应图当中的OP,否则报错
 import tensorflow as tf
  g=tf.Graph()
  with g.as_default():
      con_g=tf.constant(4.0)
      print(con_g.graph)
  # 实现一个加法运算
  a = tf.constant(3.0)
  b = tf.constant(4.0)
  
  sum = tf.add(a, b)
  
  # 会话,默认只能运行默认的图,不能运行其它的(可以通过参数解决)
  with tf.Session(graph=g) as sess:
      tf.summary.FileWriter("./modal/",graph=sess.graph)
      # 如果此时打印sess.run(sum)
      print(sess.run(con_g))
  • config: 此参数允许您指定一个 tf.ConfigProto 以便控制会话的行为。例如,ConfigProto协议用于打印设备使用信息
# 运行会话并打印设备信息
sess = tf.Session(config=tf.ConfigProto(allow_soft_placement=True,
                                        log_device_placement=True))

系统默认是在CPU上运行的,想要在GPU上运行,只需要哦一行代码就行了,即:

 with tf.device("GPU:0"):
        pass

会话可以分配不同的资源在不同的设备上运行。

 /job:worker/replica:0/task:0/device:CPU:0

device_type:类型设备(例如CPU,GPU,TPU)

1.2 会话的run()

  • run(fetches,feed_dict=None, options=None, run_metadata=None)
    • python程序中通过使用sess.run()来运行operation
    • fetches:单一的operation,或者列表、元组(其它不属于tensorflow的类型不行)
      • fetches:运行多个使用列表,运行对象不能是一些非op,tensor一些对象,比如int, double
例如:
      a=5
      b=1
      c=a+b
      with tf.Session() as sess:
          # 由于c是非op,tensor,此时运行会报错
          print(sess.run(c))
  • feed_dict:参数允许调用者覆盖图中张量的值,运行时赋值
    • 通常与tf.placeholder搭配使用,则会检查值的形状是否与占位符兼容。tf.placeholder用来制定数据的形状。placeholder(dtype, shape=None, name=None)
    • 每个值feed_dict必须可转换为相应键的dtype的numpy数组。feed_dict作用是运行的时候实时填充数据,注意:填充的数据必须是字典的形式
    • feed_dict:运行时候提供数据,一般不确定数据形状时,可以结合placeholder去使用。用在训练的时候实时提供要训练的批次数据
  • 交互式中通过使用sess.eval()来运行operation

使用tf.operation.eval()也可运行operation

# 创建图
a = tf.constant(5.0)
b = tf.constant(6.0)
c = a * b

# 创建会话
sess = tf.Session()

# 计算C的值
print(sess.run([a,b,c]))

1.3 feed操作

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

 # 实现一个加法运算
    a = tf.constant(3.0)
    b = tf.constant(4.0)
    
    # 可以使用重载的运算 + --> 加法op操作
    sum_ma = b + x1
    print(sum_ma)
    
    sum_ = tf.add(a, b)
    
    # 结合feed_dict使用
    # 当不确定数据的形状,可以使用none
    # [None, 3]
    # 这个数据,在图中没有明确定义好数据的内容
    plt = tf.placeholder(tf.float32, [None, 3])
    
    # print(sum)
    # 会话,默认只能运行默认的图,不能运行其它的图(可以通过graph参数解决)
    # 1、会话:运行图结构
    # 2、会话掌握了资源,会话运行结束,资源释放,无法再去使用这些资源计算
    # with : , close()
    with tf.Session() as sess:
        # run你要运行的内容, 必须是一个op
        # 允许调用的时候去覆盖原来的值,运行时候提供数据
        print(sess.run([sum_, sum_ma, a, b, plt], feed_dict = {plt: [[1, 2, 3], [4, 5, 6]]}))
        
    # 
    p = tf.placeholder(tf.float32)
    t = p + 1.0
    # eval也支持这样的操作
    t.eval(feed_dict={p:2.0})

请注意运行时候报的错误error:

  RuntimeError:如果这Session是无效状态(例如已关闭)。
    TypeError:如果fetches或者feed_dict键的类型不合适。如tf.placeholder给的类型和feed_dict中的类型不一致
    ValueError:如果fetches或feed_dict键无效或引用 Tensor不存在的键。

4 张量

学习目标

目标

  • 知道常见的TensorFlow创建张量
  • 知道常见的张量数学运算操作
  • 说明numpy的数组和张量相同性
  • 说明张量的两种形状改变特点
  • 应用set_shape和tf.reshape实现张量形状的修改
  • 应用tf.matmul实现张量的矩阵运算修改
  • 应用tf.cast实现张量的类型

应用

在编写 TensorFlow 程序时,程序传递和运算的主要目标是tf.Tensor

1、张量(Tensor)

TensorFlow 的张量就是一个 n 维数组, 类型为tf.Tensor。Tensor具有以下两个重要的属性

-     a = tf.constant(3.0)
      print(a)
      # 打印结果如下:
      Tensor("Const:0", shape=(), dtype=float32)
- type:数据类型
- shape:形状()

1.1张量的类型

深度学习第一天(TensorFlow框架、实现线性回归训练过程)_第7张图片

8位无符号整型之前的为常用的类型

1.2 张量的阶(也就是张量的形状)

深度学习第一天(TensorFlow框架、实现线性回归训练过程)_第8张图片
形状有0阶、1阶、2阶….

tensor1 = tf.constant(4.0)
tensor2 = tf.constant([1, 2, 3, 4])
linear_squares = tf.constant([[4], [9], [16], [25]], dtype=tf.int32)

print(tensor1.shape)
# 0维:()   1维:(10, )   2维:(3, 4)   3维:(3, 4, 5)

2、创建张量的指令:固定张量和随机张量

固定值张量

 # 在交互式环境中的代码如下:
  import tensorflow as tf
  tf.InteractiveSession()
  tf.zeros([3,4],dtype=tf.float32).eval()
  # 创建随机张量
  tf.random_normal([3,4],mean=0.0,stddev=1.0,dtype=tf.float32).eval()
  # 改变张量的类型
  tf.cast(tf.zeros([3,4],dtype=tf.float32),tf.int32).eval()

深度学习第一天(TensorFlow框架、实现线性回归训练过程)_第9张图片

随机值张量

深度学习第一天(TensorFlow框架、实现线性回归训练过程)_第10张图片

  • 其它特殊的创建张量的op
    • tf.Variable
    • tf.placeholder

3、张量的变换:类型的变换和形状的变化

3.1 类型改变

深度学习第一天(TensorFlow框架、实现线性回归训练过程)_第11张图片

常用tf.cast()可进行类型的转化,它是万能的,因为它可以进行类型之间的随意转化。

3.2 形状改变

TensorFlow的张量具有两种形状变换:动态形状和静态形状

  • tf.reshape:动态形状
  • tf.set_shape:静态形状

关于动态形状和静态形状必须符合以下规则

  • 静态形状
    • 转换静态形状的时候,1-D到1-D,2-D到2-D,不能跨阶数改变形状
 tensor1 = tf.constant([1, 2, 3, 4])
    
    #此时会报错,因为跨阶数
    tensor1.set_shape([2, 2]) 
  • 对于已经固定的张量的静态形状的张量,不能再次设置静态形状。如上面的情况
# 那静态形状有什么用呢?静态形状常用于下面这种情况
    #plt的形状不确定
    plt = tf.placeholder(tf.float32, [None, 4])
    
    # 确定plt的形状
    plt.set_shape([3, 4])
    print(plt)
  • 动态形状
    • tf.reshape()动态创建新张量时,张量的元素个数必须匹配
# 能用set_shape就优先使用,不能用的话,使用reshape

tensor1 = tf.constant([1, 2, 3, 4])
plt = tf.placeholder(tf.float32, [None, 4])
# tensor2 = tf.constant(11.0)

# tensor1.set_shape([2, 2])  错误
plt.set_shape([3, 4])
print(plt)

# 此时的plt是3行4列的,经过动态形状改变后,成为4行3列,动态形状改变后必须保证元素个数一样。
new_tensor = tf.reshape(plt, [4, 3])

print(plt, new_tensor)
# 打印的形状,在定义数据的时候形状使用[]
# 不确定的形状:(?, 4)

with tf.Session() as sess:

    print(sess.run(tensor1))

在进行使用时,静态形状和动态形状怎样进行选择使用呢?当选择形状不确定的时候,优先选择静态形状。

4、张量的数学运算

  • 算术运算符
  • 基本数学函数
  • 矩阵运算
  • reduce操作
  • 序列索引操作

详细请参考: 参考1

参考2

这些API使用,我们在使用的时候介绍,具体参考文档

5 变量OP

目标

  • 说明变量op的特殊作用
  • 说明变量op的trainable参数的作用
  • 应用global_variables_initializer实现变量op的初始化

应用

1、变量

TensorFlow变量是表示程序处理的共享持久状态的最佳方法。变量OP是一种特殊的OP。变量通过 tf.Variable OP类以及tf.get_variable()类进行操作。它是一种特殊的张量OP,变量的特点

  • 存储持久化
  • 可修改值
  • 可指定被训练

1.1创建变量

  • tf.Variable(initial_value=None,trainable=True,collections=None,name=None)
    • initial_value:初始化的值
    • trainable:是否被训练
    • collections:新变量将添加到列出的图的集合中collections,默认为[GraphKeys.GLOBAL_VARIABLES],如果trainable是True变量也被添加到图形集合 GraphKeys.TRAINABLE_VARIABLES
var = tf.Variable(tf.random_normal([2, 2], mean=0.0, stddev=1.0), name="var", trainable=True)

with tf.Session() as sess:
    sess.run(var)
# 运行会发现报错
  • 变量需要显示初始化,才能运行值
   # 在上述的基础上,添加一个初始化变量的OP,注意:init_op必须放置var之后,否则报错。也就是说创建variable在前,初始化在后
    init_op = tf.global_variables_initializer()
    
    with tf.Session() as sess:
        # 运行初始化变量的OP,然后才能打印变量OP值
        sess.run(init_op)
        # 此时才能得到变量OP的结果
        print(sess.run(var))

1.2 变量OP的方法

  • new_var = assign(value)
    • 给变量赋值一个新的值,它会把之前的值给覆盖掉
  • new_var = assign_add(delta)
var = tf.Variable(tf.random_normal([2, 3], mean=0.0, stddev=1.0), name="var", trainable=True)
#给变量赋值一个新的值
#var1 = var.assign([[2, 3, 8], [4, 5, 7]])
# 变量初始化
init_op = tf.global_variables_initializer()

# 覆盖var中的值,产生新的值
va = var.assign_add([[1, 3, 2], [4, 5, 6]])

#给va的基础上增加一个新的值
va1 = var.assign_add([[5, 3, 2], [4, 5, 6]])
with tf.Session() as sess:
    # 运行初始化op,如果没有该步骤,则无法得到后续变量的结果
    sess.run(init_op)
    print(sess.run(var))
    print(sess.run(va))
    print(sess.run(va1))

关于变量的被训练,我们在后面的线性回归案例当中介绍

2、命名空间与共享变量

共享变量的主要用途在一些网络当中的参数共享, 由于在TensorFlow当中,只要我们定义的OP,name参数指定一样,其实并不是同一个变量。如果想要达到重复利用变量的效果,我们就要使用tf.variable_scope()结合tf.get_variable()一起使用,两者通常结合一起使用.

创建命名空间有两个作用:

  • 共享变量
  • 相当于python中的自动缩进的作用一样,缩进相同的被看成一块,不容易乱,同理,创建一个命名空间就相当于作用域

2.1 定义一个相同名字的变量

 var = tf.Variable(name='var', initial_value=[4], dtype=tf.float32)
    var_double = tf.Variable(name='var', initial_value=[4], dtype=tf.float32)
    
    <tf.Variable 'var:0' shape=() dtype=float32_ref>
    <tf.Variable 'var_1:0' shape=() dtype=float32_ref>

2.2 使用tf.variable_scope()修改OP命名空间

会在OP的名字前面增加命名空间的指定名字

with tf.variable_scope("name"):
    var = tf.Variable(name='var', initial_value=[4], dtype=tf.float32)
    var_double = tf.Variable(name='var', initial_value=[4], dtype=tf.float32)
    
<tf.Variable 'name/var:0' shape=() dtype=float32_ref>
<tf.Variable 'name/var_1:0' shape=() dtype=float32_ref>

2.2 tf.get_variable共享变量

  • 注意:如果没有tf.variable_scope(),则tf.get_variable一点用也没有
  • 命名空间与共享变量(全局变量)name全局唯一
    • tfvariable_scope去创建,会在op的名字前面继续加上空间的名字
    • tf.get_variable:如果一个命名空间当中存在名字一样的,那么会报冲突错误,怎么解决?
      • 功能:创建或获取名字叫name=""的变量。目的:让同一个命名空间当中的可以同时存在同一个名字
      • with tf.variable_scope(“my_scope1”) as scope+ scope.reuse_variables()
      • with tf.variable_scope(“name”, reuse=tf.AUTO_REUSE):
      • var2 = tf.get_variable(initializer=tf.random_normal([2, 3], mean=0.0, stddev=1.0),
        name=“var2”)
  • 通过tf.get_variable的初始化与Variable参数一样,但是要想实现共享,需要打开tf.variable_scope()中的reuse=tf.AUTO_REUSE参数 ,即添加reuse=tf.AUTO_REUSE参数,只有开启了,才能获取原来变量的值

第一种方式:未运行成功,不知道哪里出错了

 # 打开共享参数
    # 或者
    #  with tf.variable_scope("name") as scope:
    #  在需要使用共享变量的前面定义: scope.reuse_variables()
    with tf.variable_scope("name", reuse=tf.AUTO_REUSE):
        var = tf.Variable(initial_value=4.0, name="var", dtype=tf.float32)
        var_double = tf.Variable(initial_value=4.0, name="var", dtype=tf.float32)
    	# 可将var1实现变量的共享
        var1 = tf.get_variable(initializer=tf.random_normal([2, 2], mean=0.0, stddev=1.0),
                               name="var1",
                               dtype=tf.float32)
        var1_double = tf.get_variable(initializer=tf.random_normal([2, 2], mean=0.0, stddev=1.0),
                               name="var1",
                               dtype=tf.float32)
    
    
    with tf.Session() as sess:
        #只要使用tf.Variable(),就需要sess.run(tf.global_variables_initializer())初始化变量,只有初始化化后变量才有值,即生效
        sess.run(tf.global_variables_initializer())
        print(var1)
        print(var1_double)

第二种方式:可运行成功

with tf.variable_scope("my_scope1") as scope:
    var = tf.Variable(tf.random_normal([2, 3], mean=0.0, stddev=1.0), name="var")
    var_double = tf.Variable(tf.random_normal([2, 3], mean=0.0, stddev=1.0), name="var")
	var_three = tf.Variable(initial_value=4.0, name="var", dtype=tf.float32)
    
    #创建名字叫var1的变量
    var1 = tf.get_variable(initializer=tf.random_normal([2, 2], mean=0.0, stddev=1.0),
                           name="var1",dtype=tf.float32)
    # 注意:必须在共享变量前面加这句话,一定要放在这个位置。因为要共享前面
    scope.reuse_variables()
    # 可将var1实现变量的共享,创建或获取名字叫var1的变量
    var1_double = tf.get_variable(initializer=tf.random_normal([2, 3], mean=0.0, stddev=1.0),name="var1",dtype=tf.float32)
    
    scope.reuse_variables()
    var1_three = tf.get_variable(initializer=tf.random_normal([2, 3], mean=0.0, stddev=1.0),name="var1",dtype=tf.float32)
    
with tf.Session() as sess:
     print(var)
    print(var_double)
    print(var_three)
    print(var1)
    print(var1_double)
    print(var1_three)
在同一个命名空间当中同时存在同一个名字的结果如下
<tf.Variable 'name/var:0' shape=() dtype=float32_ref>
<tf.Variable 'name/var_1:0' shape=() dtype=float32_ref>
<tf.Variable 'name/var_2:0' shape=() dtype=float32_ref>
<tf.Variable 'name/var1:0' shape=(2, 2) dtype=float32_ref>
<tf.Variable 'name/var1:0' shape=(2, 2) dtype=float32_ref>
<tf.Variable 'name/var1:0' shape=(2, 2) dtype=float32_ref>

6 高级API

学习目标

目标

应用

其它基础API

1、 tf.app

这个模块相当于为 TensorFlow 进行的脚本撮供了一个 main 函数入口,可以定义脚本运行的 flags。

2、tf.image

TensorFlow 的图像处理操作。主要是一些颜色变换、变形和图像的编码和解码。

3、tf.gfile

这个模块提供了一组文件操作函数。

4、tf.summary

用来生成 TensorBoard 可用的统计日志,目前 Summary 主要提供了 4 种类型:audio、image、histogram、scalar

5、tf.python_io

用来读写 TFRecords文件

6、tf.train

这个模块提供了一些训练器,与 tf.nn 组合起来,实现一些网络的优化计算。

7、tf.nn

这个模块提供了一些构建神经网络的底层函数。 TensorFlow 构建网络的核心模块。其中包含了添加各种层的函数,比如添加卷积层、池化层等。

高级API

1、tf.keras

Keras 本来是一个独立的深度学习库,tensorflow将其学习过来,增加这部分模块在于快速构建模型。

2、tf.layers

高级 API,以更高级的概念层来定义一个模型。类似tf.keras。

3、tf.contrib

tf.contrib.layers提供够将计算图中的 网络层、正则化、摘要操作、是构建计算图的高级操作,但是tf.contrib包含不稳定和实验代码,有可能以后API会改变。

4、tf.estimator

一个 Estimator 相当于 Model + Training + Evaluate 的合体。在模块中,已经实现了几种简单的分类器和回归器,包括:Baseline,Learning 和 DNN。这里的 DNN 的网络,只是全连接网络,没有提供卷积之类的。

关于TensorFlow的API图示

深度学习第一天(TensorFlow框架、实现线性回归训练过程)_第12张图片
能够看到tensorboard中图Graph的代码,运行前,先将保存目录中的event文件删除掉,且命令窗口关闭,重新打开一个命令窗口

初始代码:未训练时的权重和偏置

 import tensorflow as tf
    # 去掉红色部分
    import os
    os.environ['TF_CPP_MIN_LOG_LEVEL']='2'
    
    
    # 实现线性回归训练
    class MyLinearRegression(object):
        """
        实现线性回归训练
        """
        def __init__(self):
            self.leaning_rate = 0.1
    
        def inputs(self):
            """
            获取需要训练的数据
            :return:
            """
            # x: [100, 1]  y_true = x * 0.7 + 0.8
            x_data = tf.random_normal(shape=[100, 1], mean=0.0, stddev=1.0, name='x_data')
    
            # [100, 1] * [1, 1] = [100, 1]
            y_true = tf.matmul(x_data, [[0.7]]) + 0.8
    
            return x_data, y_true
    
        def inference(self, feature):
            """
            根据数据特征值,建立线性回归模型
            :param feature: 数据特征值 [100, 1]
            :return: y_predict
            """
            # 定义一个命名空间
            with tf.variable_scope("linear_model"):
                # w, b
                # x [100, 1] * w [1, 1] + b = y_predict
                # 随机初始化权重和偏置
                # 注意:权重和偏置必须使用tf.Variable去定义,因为只有Variable才能被梯度下降所训练,否则不能被训练。trainable指定该参数是否可训练。trainable默认的值是True,即可训练
                self.weight = tf.Variable(tf.random_normal(shape=[1, 1],
                                                           mean=0.0,
                                                           stddev=1.0),
                                          name="weight")
    
                self.bias = tf.Variable(tf.random_normal(shape=[1],
                                                           mean=0.0,
                                                           stddev=1.0), name="bias")
                # 建立模型预测
                y_predict = tf.matmul(feature, self.weight) + self.bias
    
            return y_predict
    
        def loss(self, y_true, y_predict):
            """
            根据预测值和真实值求出均方误差损失
            :param y_true: 真实值
            :param y_predict: 预测值
            :return: loss
            """
            # 定义一个命名空间
            #  sum((y_true - y_predict)^2) mean()
            with tf.variable_scope("losses"):
    
                # 求出损失
                # tf.reduce_mean 对列表中的数据求和之后求出平均值
                loss = tf.reduce_mean(tf.square(y_true - y_predict))
    
            return loss
    
        def sgd_op(self, loss):
            """
            利用梯度下降优化器去优化损失(优化模型参数)
            :param loss: 损失大小
            :return: 梯度下降OP
            """
            # 定义一个命名空间
            with tf.variable_scope("train_op"):
    
                train_op = tf.train.GradientDescentOptimizer(self.leaning_rate).minimize(loss)
    
            return train_op
    
        def train(self):
            """
            专门用于训练的函数
            :return: None
            """
            # 获取默认的图,没有这句话也是在默认的这张图中进行的操作
            g = tf.get_default_graph()
    
            # 在默认图当中去做操作
            with g.as_default():
    
                # 进行训练
                # 1、获取数据
                x_data, y_true = self.inputs()
    
                # 2、利用模型得出预测结果
                y_predict = self.inference(x_data)
    
                # 3、损失计算
                loss = self.loss(y_true, y_predict)
    
                # 4、优化损失。根据损失进行优化
                train_op = self.sgd_op(loss)
    
    
                # 开启回话去训练
                with tf.Session() as sess:
    
                    # 初始化变量
                    sess.run(tf.global_variables_initializer())
    
                    # 打印模型没有训练的初始化的参数。注意:要想得到变量的值必须使用.eval()或run()
                    print("模型初始化的参数权重:%f ,  偏置为:%f " % (
                        self.weight.eval(),
                        self.bias.eval()
                    ))
                    # 此时会打印一次的训练结果,如果想要训练多次,可在该行加一个for循环就可以了。如训练200次:for i in range(200):
                    #sess.run(train_op)
                    # 打印模型没有训练的初始化的参数
                    #print("模型优化参数权重:%f ,  偏置为:%f " % (
                    #     self.weight.eval(),
                    #     self.bias.eval()
                    # ))
                    #打印多次训练结果
                    for i in range(200):
                        sess.run(train_op)
    
                        # 打印模型没有训练的初始化的参数
                        print("第%d次, 总损失变化:%f, 模型优化参数权重:%f ,  偏置为:%f " % (i,loss.eval(),self.weight.eval(),self.bias.eval() ))
                    
                    
    if __name__ == '__main__':
        lr = MyLinearRegression()
        lr.train()
    
    第一次模型加载结果:
    # 由于在设置权重和偏置时,tf.Variable中的参数trainable默认为True,因此权重和偏置被训练一次    
    模型初始化的参数权重:-0.011007 ,  偏置为:1.172049 
    模型优化参数权重:0.104960 ,  偏置为:1.088836 

完整代码如下:

   import tensorflow as tf
    import os
    os.environ['TF_CPP_MIN_LOG_LEVEL']='2'
    
    
    
    # 定义模型训练的步数
    
    tf.app.flags.DEFINE_integer("tran_step", 0, "训练模型的步数")
    
    tf.app.flags.DEFINE_string("model_dir", " ", "模型保存的路径")
    
    FLAGS = tf.app.flags.FLAGS
    
    
    # 实现线性回归训练
    class MyLinearRegression(object):
        """
        实现线性回归训练
        """
        def __init__(self):
            self.leaning_rate = 0.1
    
        def inputs(self):
            """
            获取需要训练的数据
            :return:
            """
            # x: [100, 1]  y_true = x * 0.7 + 0.8
            x_data = tf.random_normal(shape=[100, 1], mean=0.0, stddev=1.0, name='x_data')
    
            # [100, 1] * [1, 1] = [100, 1]
            y_true = tf.matmul(x_data, [[0.7]]) + 0.8
    
            return x_data, y_true
    
        def inference(self, feature):
            """
            根据数据特征值,建立线性回归模型
            :param feature: 数据特征值 [100, 1]
            :return: y_predict
            """
            # 定义一个命名空间
            with tf.variable_scope("linear_model"):
                # w, b
                # x [100, 1] * w [1, 1] + b = y_predict
                # 随机初始化权重和偏置
                # 注意:权重和偏置必须使用tf.Variable去定义,因为只有Variable才能被梯度下降所训练,否则不能被训练。trainable指定该参数是否可训练
                self.weight = tf.Variable(tf.random_normal(shape=[1, 1],
                                                           mean=0.0,
                                                           stddev=1.0),
                                          trainable=False,
                                          name="weight")
    
                self.bias = tf.Variable(tf.random_normal(shape=[1],
                                                           mean=0.0,
                                                           stddev=1.0), name="bias")
                # 建立模型预测
                y_predict = tf.matmul(feature, self.weight) + self.bias
    
            return y_predict
    
        def loss(self, y_true, y_predict):
            """
            根据预测值和真实值求出均方误差损失
            :param y_true: 真实值
            :param y_predict: 预测值
            :return: loss
            """
            # 定义一个命名空间
            #  sum((y_true - y_predict)^2) mean()
            with tf.variable_scope("losses"):
    
                # 求出损失
                # tf.reduce_mean 对列表中的数据求和之后求出平均值
                loss = tf.reduce_mean(tf.square(y_true - y_predict))
    
            return loss
    
        def sgd_op(self, loss):
            """
            利用梯度下降优化器去优化损失(优化模型参数)
            :param loss: 损失大小
            :return: 梯度下降OP
            """
            # 定义一个命名空间
            with tf.variable_scope("train_op"):
    
                train_op = tf.train.GradientDescentOptimizer(self.leaning_rate).minimize(loss)
    
            return train_op
    
        def merge_summary(self, loss):
            """
            定义收集张量的函数
            :param loss: 损失
            :return:
            """
            # 收集对于损失函数和准确率等单值变量
            tf.summary.scalar("losses", loss)
    
            # 收集高维度张量值
            tf.summary.histogram("w", self.weight)
            tf.summary.histogram('b', self.bias)
    
            # 合并变量(OP)
            merged = tf.summary.merge_all()
    
            return merged
    
        def train(self):
            """
            专门用于训练的函数
            :return: None
            """
            # 获取默认的图,没有这句话也是在默认的这张图中进行的操作
            g = tf.get_default_graph()
    
            # 在默认图当中去做操作
            with g.as_default():
    
                # 进行训练
                # 1、获取数据
                x_data, y_true = self.inputs()
    
                # 2、利用模型得出预测结果
                y_predict = self.inference(x_data)
    
                # 3、损失计算
                loss = self.loss(y_true, y_predict)
    
                # 4、优化损失。根据损失进行优化
                train_op = self.sgd_op(loss)
    
                # 收集要观察张量值
                merged = self.merge_summary(loss)
    
                # # 定义一个保存文件的saverOP
                # saver = tf.train.Saver()
    
                # 开启回话去训练
                with tf.Session() as sess:
    
                    # 初始化变量
                    sess.run(tf.global_variables_initializer())
    
                    # 创建events文件
                    file_writer = tf.summary.FileWriter("F:/tmp/summary/", graph=sess.graph)
    
                    # 打印模型没有训练的初始化的参数
                    print("模型初始化的参数权重:%f ,  偏置为:%f " % (
                        self.weight.eval(),
                        self.bias.eval()
                    ))
    
                    # # 加载模型,从模型当中找出与当前训练的模型代码当中(名字一样的OP操作),覆盖原来的值
                    # ckpt = tf.train.latest_checkpoint("./tmp/model/")
    
                    # # 判断模型是否存在
                    # if ckpt:
                    #     saver.restore(sess, ckpt)
                    # sess.run(train_op)
                    # 打印模型没有训练的初始化的参数
                    # print("第一次加载保存的模型参数变为权重:%f ,  偏置为:%f " % (
                    #     self.weight.eval(),
                    #     self.bias.eval()
                    # ))
                    # print("以模型当中的参数继续去进行训练")
                    #
                    # 接下来?
                    for i in range(200):
                    # for i in range(FLAGS.tran_step):
    
                        _, summary = sess.run([train_op, merged])
    
                        # 把summary,张量的值写入到events文件当中
                        file_writer.add_summary(summary, i)
                        # sess.run(train_op)
                        print("第 %d 步,总损失变化:%f , 模型优化参数权重:%f ,  偏置为:%f " % (
                            i,
                            loss.eval(),
                            self.weight.eval(),
                            self.bias.eval()
                        ))
                    #
                    #     # 每隔100步保存一次模型
                    #     if i % 100 == 0:
                    #
                    #         # 要指定路径+名字
                    #         saver.save(sess, FLAGS.model_dir)
    
    
    if __name__ == '__main__':
        lr = MyLinearRegression()
        lr.train()

7 案例:实现线性回归

学习目标

  • sess是会话,graph是图

目标

  • 应用op的name参数实现op的名字修改
  • 应用variable_scope实现图程序作用域的添加
  • 应用scalar或histogram实现张量值的跟踪显示
  • 应用merge_all实现张量值的合并
  • 应用add_summary实现张量值写入文件
  • 应用tf.train.saver实现TensorFlow的模型保存以及加载
  • 应用tf.app.flags实现命令行参数添加和使用
  • 应用reduce_mean、square实现均方误差计算
  • 应用tf.train.GradientDescentOptimizer实现有梯度下降优化器创建
  • 应用minimize函数优化损失
  • 知道梯度爆炸以及常见解决技巧

应用

  • 实现线性回归模型

1、线性回归原理复习

根据数据建立回归模型,w1x1+w2x2+……+b = y,通过真实值与预测值之间建立误差,使用梯度下降优化得到损失最小对应的权重和偏置。最终确定模型的权重和偏置参数。最后可以用这些参数进行预测。

2、案例:实现线性回归的训练

2.1 案例确定

  • 假设随机指定100个点,只有一个特征值X,并没有目标值Y。
  • 数据本身的分布为 y = 0.7 * x + 0.8,即数据的真实分布构成的关系式

这里将数据分布的规律确定,是为了使我们训练出的参数跟真实的参数(即0.7和0.8)比较是否训练准确

2.2 API

运算
  • 矩阵相乘运算:注意和点相乘的区别
    • tf.matmul(x, w):https://www.jianshu.com/p/b6be1cacd94c
 import tensorflow as tf
    #两个矩阵相乘
    x3=tf.constant([[1.,2.,3.],[1.,2.,3.],[1.,2.,3.]])
    y3=tf.constant([[0.,0.,1.],[0.,0.,1.],[0.,0.,1.]])
    #注意这里x,y要满足矩阵相乘的格式要求
    z3=tf.matmul(x3,y3)
    with tf.Session() as sess:
        print(sess.run(z3))
        
     [[0. 0. 6.]
     [0. 0. 6.]
     [0. 0. 6.]]
平方
  • tf.square(error)
  • 作用:https://blog.csdn.net/liuyingying0418/article/details/80070538
均值
  • tf.reduce_mean(error)
梯度下降优化API
  • tf.train.GradientDescentOptimizer(learning_rate)
    • 梯度下降优化
    • learning_rate:学习率,一般为0~1之间比较小的值。传学习率的目的是优化我们的损失
    • method:
      • minimize(loss),去优化损失
 tf.train.GradientDescentOptimizer(learning_rate).minimize(loss)
  • return:梯度下降op

2.3 步骤分析

  • 1、准备数据的特征值和目标值 inputs
  • 2、根据特征值建立线性回归模型(确定参数个数形状) inference
    • 模型的参数必须使用变量OP创建
  • 3、根据模型得出预测结果,建立损失 loss
  • 4、梯度下降优化器优化损失 sgd_op

2.4 实现完整功能

1、准备数据X、 y_true=0.7 * x + 0.8
   2、根据数据建立线性模型:w:随机初始化一个权重;b:随机初始化一个偏置,得到y_predict=x*w+b
   3、利用y_true和y_predict求出均方误差损失
   4、利用梯度下降法去减少模型的损失,从而优化模型参数,指定学习率:一般0-1之间
    # 准备数据
    def inputs(self):
        """
        获取特征值目标值数据
        :return:
        """
        #假设随机指定100个点,只有一个特征X。因为要实现矩阵相乘,所以必须是多维的
        # 随机生成100行1列的数据,打印出来它是二维的,因此,在进行矩阵相乘的时候0.7也要是二维的
        x_data = tf.random_normal([100, 1], mean=1.0, stddev=1.0, name="x_data")
        # [100, 1] * [1, 1] = [100, 1]
        y_true = tf.matmul(x_data, [[0.7]]) + 0.8

        return x_data, y_true
	
    # 建立模型
    def inference(self, feature):
        """
        根据输入数据建立模型
        :param feature:
        :param label:
        :return:
        """
        # 建立一个命名空间,创建命名空间既可以作为共享内存空间,也可以当成一个作用域(一个整体,看起来不那么乱)
        with tf.variable_scope("linea_model"):
            # 2、建立回归模型,分析别人的数据的特征数量--->权重数量, 偏置b
            # 由于有梯度下降算法优化,所以一开始给随机的参数,权重和偏置
            # 被优化的参数,必须得使用变量op去定义,否则,该参数不能被优化
            # 变量初始化权重和偏置
            # weight 2维[1, 1]    bias [1]
            # 变量op当中会有trainable参数,它决定该值是否优化
            # 注意:必须用变量的OP去初始化权重和偏置
            # 随机初始化权重和偏置
			# # 注意:权重和偏置必须使用tf.Variable去定义,因为只有Variable去定义才能被梯度下降所训练,否则不能被训练。trainable指定该参数是否被训练。trainable默认的值是True,即可训练
            self.weight = tf.Variable(tf.random_normal([1, 1], mean=0.0, stddev=1.0),
                                 name="weights")

            self.bias = tf.Variable(0.0, name='biases')

            # 建立模型得出预测结果
            y_predict = tf.matmul(feature, self.weight) + self.bias

        return y_predict

    def loss(self, y_true, y_predict):
        """
        目标值和真实值计算损失
        :return: loss
        """
        # 3、求出我们模型跟真实数据之间的损失
        # 均方误差公式
        loss = tf.reduce_mean(tf.square(y_true - y_predict))

        return loss
    
    def sgd_op(self, loss):
        """
        获取训练OP
        :return:
        """
        # 4、使用梯度下降优化器优化
        # 填充学习率:0 ~ 1    学习率是非常小,
        # 学习率大小决定你到达损失一个步数多少
        # 最小化损失
        train_op = tf.train.GradientDescentOptimizer(0.1).minimize(loss)

        return train_op
    
     def train(self):
        """
        专门用于训练的函数
        :return: None
        """
        # 获取默认的图,没有这句话也是在默认的这张图中进行的操作
        g = tf.get_default_graph()

        # 在默认图当中去做操作
        with g.as_default():

            # 进行训练
            # 1、获取数据
            x_data, y_true = self.inputs()

            # 2、利用模型得出预测结果
            y_predict = self.inference(x_data)

            # 3、损失计算
            loss = self.loss(y_true, y_predict)

            # 4、优化损失。根据损失进行优化
            train_op = self.sgd_op(loss)


            # 开启回话去训练
            with tf.Session() as sess:

                # 初始化变量
                sess.run(tf.global_variables_initializer())

                # 打印模型没有训练的初始化的参数。注意:要想得到变量的值必须使用.eval()或run()
                print("模型初始化的参数权重:%f ,  偏置为:%f " % (
                    self.weight.eval(),
                    self.bias.eval()
                ))
                # 此时会打印一次的训练结果,如果想要训练多次,可在该行加一个for循环就可以了。如训练200次:for i in range(200):
                #sess.run(train_op)
                # 打印模型没有训练的初始化的参数
                #print("模型优化参数权重:%f ,  偏置为:%f " % (
                #     self.weight.eval(),
                #     self.bias.eval()
                # ))
                #打印多次训练结果
                for i in range(200):
                    sess.run(train_op)

                    # 打印模型没有训练的初始化的参数
                    print("第%d次, 总损失变化:%f, 模型优化参数权重:%f ,  偏置为:%f " % (i,loss.eval(),self.weight.eval(),self.bias.eval() ))
                
                
if __name__ == '__main__':
    lr = MyLinearRegression()
    lr.train()

2.5 学习率的设置、步长的设置与梯度爆炸

明白学习率和步长的关系。

学习率越大,训练到较好结果的步长越小;学习率越小,训练到较好结果的步长越大。为了防止梯度爆炸,学习率一般设置的都比较小

但是学习率过大则会导致梯度爆炸现象,就是损失、权重、偏置等其他参数的值变为NaN 值。关于梯度爆炸/梯度消失 ?

在极端情况下,权重的值变得非常大,以至于溢出,导致 NaN 值
如何解决梯度爆炸问题(深度神经网络当中更容易出现)
1、重新设计网络
2、调整学习率
3、使用梯度截断(在训练过程中检查和限制梯度的大小)
4、使用激活函数

2.6 变量的trainable设置观察

trainable的参数作用,指定参数是否被训练。当为True时,随着训练值会发生改变,当为False时,不会进行训练,即值也不会发生改变

weight = tf.Variable(tf.random_normal([1, 1], mean=0.0, stddev=1.0), name="weights", trainable=False)
# 由于trainable=False,weight的值在训练的时候不会发生改变

3、增加其他功能

  • 增加命名空间
  • 变量在Tensorboard显示
  • 模型保存与加载
  • 命令行参数设置

3.1 增加命名空间

命名空间能够实现共享变量,它的另一个作用:使代码结构更加清晰,Tensorboard图结构清楚,使代码更加模块化

 with tf.variable_scope("lr_model"):

3.2 增加变量显示

目的:在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()
    • 运行合并:summary = sess.run(merged),每次迭代都需运行
    • 添加到event文件中:FileWriter.add_summary(summary,i),i表示第几次的值
 def merge_summary(self, loss):

        # 1、收集张量的值
        tf.summary.scalar("losses", loss)

        tf.summary.histogram("w", self.weight)
        tf.summary.histogram('b', self.bias)

        # 2、合并变量
        merged = tf.summary.merge_all()

        return merged


# 生成事件文件,观察图结构
file_writer = tf.summary.FileWriter("./tmp/summary/", graph=sess.graph)


# 运行收集变量的结果
summary = sess.run(merged)

# 添加到文件
file_writer.add_summary(summary, i)

3.3 模型的保存与加载

  • tf.train.Saver(var_list=None,max_to_keep=5)
    • 保存和加载模型(保存文件格式:checkpoint文件)
    • var_list:指定将要保存和还原的变量。它可以作为一个dict或一个列表传递.
    • max_to_keep:指示要保留的最近检查点文件的最大数量。创建新文件时,会删除较旧的文件。如果无或0,则保留所有检查点文件。默认为5(即保留最新的5个检查点文件。)

使用:保存要指定路径,和要保存的会话

例如:
指定目录+模型名字
# 保存
saver.save(sess, '/tmp/ckpt/test/myregression.ckpt')
# 恢复模型。
saver.restore(sess, '/tmp/ckpt/test/myregression.ckpt')
#myregression就是自动生成文件的名字

加载模型,也就是恢复模型,如果模型存在的话,在调用模型后会接着训练,而不是再从0开始训练

恢复模型:可判断模型是否存在,直接指定目录,而不指定模型名字myregression,这一点和保存模型不同

checkpoint = tf.train.latest_checkpoint("./tmp/model/")

saver.restore(sess, checkpoint)

3.4 命令行参数使用

  • 2、 tf.app.flags.,在flags有一个FLAGS标志,它在程序中可以调用到我们

前面具体定义的flag_name

  • 3、通过tf.app.run()启动main(argv)函数
python中的代码
# 定义一些常用的命令行参数
# 定义模型训练步数,第一个参数是变量的名字,第二个参数是默认值(即:不赋值的情况下的值),第三个参数是注释。
tf.app.flags.DEFINE_integer("max_step", 0, "训练模型的步数")
# 定义模型的路径
tf.app.flags.DEFINE_string("model_dir", " ", "模型保存的路径+模型名字")

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

# 开启训练
# 训练的步数(依据模型大小而定)
for i in range(FLAGS.max_step):
     sess.run(train_op)
        
        
        
命令行中的代码:首先进入文件所在的目录,然后输入以下命令:
python day14.py --train_step=500 --model_dir="F:/tmp/model/myregression

完整代码

# 用tensorflow自实现一个线性回归案例

# 定义一些常用的命令行参数
# 训练步数
tf.app.flags.DEFINE_integer("max_step", 0, "训练模型的步数")
# 定义模型的路径
tf.app.flags.DEFINE_string("model_dir", " ", "模型保存的路径+模型名字")

FLAGS = tf.app.flags.FLAGS

class MyLinearRegression(object):
    """
    自实现线性回归
    """
    def __init__(self):
        pass

    def inputs(self):
        """
        获取特征值目标值数据数据
        :return:
        """
        x_data = tf.random_normal([100, 1], mean=1.0, stddev=1.0, name="x_data")
        y_true = tf.matmul(x_data, [[0.7]]) + 0.8

        return x_data, y_true

    def inference(self, feature):
        """
        根据输入数据建立模型
        :param feature:
        :param label:
        :return:
        """
        with tf.variable_scope("linea_model"):
            # 2、建立回归模型,分析别人的数据的特征数量--->权重数量, 偏置b
            # 由于有梯度下降算法优化,所以一开始给随机的参数,权重和偏置
            # 被优化的参数,必须得使用变量op去定义
            # 变量初始化权重和偏置
            # weight 2维[1, 1]    bias [1]
            # 变量op当中会有trainable参数决定是否训练
            self.weight = tf.Variable(tf.random_normal([1, 1], mean=0.0, stddev=1.0),
                                 name="weights")

            self.bias = tf.Variable(0.0, name='biases')

            # 建立回归公式去得出预测结果
            y_predict = tf.matmul(feature, self.weight) + self.bias

        return y_predict

    def loss(self, y_true, y_predict):
        """
        目标值和真实值计算损失
        :return: loss
        """
        # 3、求出我们模型跟真实数据之间的损失
        # 均方误差公式
        loss = tf.reduce_mean(tf.square(y_true - y_predict))

        return loss

    def merge_summary(self, loss):

        # 1、收集张量的值
        tf.summary.scalar("losses", loss)

        tf.summary.histogram("w", self.weight)
        tf.summary.histogram('b', self.bias)

        # 2、合并变量
        merged = tf.summary.merge_all()

        return merged

    def sgd_op(self, loss):
        """
        获取训练OP
        :return:
        """
        # 4、使用梯度下降优化器优化
        # 填充学习率:0 ~ 1    学习率是非常小,
        # 学习率大小决定你到达损失一个步数多少
        # 最小化损失
        train_op = tf.train.GradientDescentOptimizer(0.1).minimize(loss)

        return train_op

    def train(self):
        """
        训练模型
        :param loss:
        :return:
        """

        g = tf.get_default_graph()

        with g.as_default():

            x_data, y_true = self.inputs()

            y_predict = self.inference(x_data)

            loss = self.loss(y_true, y_predict)

            train_op = self.sgd_op(loss)

            # 收集观察的结果值
            merged = self.merge_summary(loss)

            saver = tf.train.Saver()

            with tf.Session() as sess:

                sess.run(tf.global_variables_initializer())
                
                # 在没训练,模型的参数值
        		print("初始化的权重:%f, 偏置:%f" % (self.weight.eval(), self.bias.eval()))

                # 加载模型
                checkpoint = tf.train.latest_checkpoint("./tmp/model/")
        		# print(checkpoint)
        		if checkpoint:
            		print('Restoring', checkpoint)
            		saver.restore(sess, checkpoint)
                # 开启训练
                # 训练的步数(依据模型大小而定)
                for i in range(FLAGS.max_step):

                    sess.run(train_op)

                    # 生成事件文件,观察图结构
                    file_writer = tf.summary.FileWriter("./tmp/summary/", graph=sess.graph)

                    print("训练第%d步之后的损失:%f, 权重:%f, 偏置:%f" % (
                        i,
                        loss.eval(),
                        self.weight.eval(),
                        self.bias.eval()))

                    # 运行收集变量的结果
                    summary = sess.run(merged)

                    # 添加到文件
                    file_writer.add_summary(summary, i)
					# 每隔100步保存一次模型
                    if i % 100 == 0:
                        # 保存的是会话当中的变量op值,其他op定义的值不保存
                        # 必须要指定目录+名字
                        saver.save(sess, FLAGS.model_dir)


if __name__ == '__main__':
    lr = MyLinearRegression()
    lr.train()

你可能感兴趣的:(深度学习课件)