深度学习---2. TensorFlow框架介绍

2.1 TF数据流图

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

1 代码

# 实现一个加法运算
con_a = tf.constant(3.0)
con_b = tf.constant(4.0)

sum_c = tf.add(con_a, con_b)

print("打印con_a:\n", con_a)
print("打印con_b:\n", con_b)
print("打印sum_c:\n", sum_c)

# 会话,默认只能运行默认的图,不能运行其它的(可以通过参数解决)
with tf.Session() as sess:
    print("con_a的值为:\n", sess.run(con_a))
    print("con_b的值为:\n", sess.run(con_b))
    print("sum_c的值为:\n", sess.run(sum_c))

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

import os
os.environ['TF_CPP_MIN_LOG_LEVEL']='2'

2 TensorFlow结构分析

TensorFlow 程序通常被组织成一个构建图阶段和一个执行图阶段。

在构建阶段,数据与操作的执行步骤被描述成一个图。

在执行阶段,使用会话执行构建好的图中的操作。

  • 图和会话 :
    • 图:这是 TensorFlow 将计算表示为指令之间的依赖关系的一种表示法
    • 会话:TensorFlow 跨一个或多个本地或远程设备运行数据流图的机制
  • 张量:TensorFlow 中的基本数据对象
  • 节点:提供图当中执行的操作

2.1.2 数据流图介绍

TensorFlow是一个采用数据流图(data flow graphs),用于数值计算的开源框架。

节点(Operation)在图中表示数学操作,线(edges)则表示在节点间相互联系的多维数据数组,即张量(tensor)。

2.2 图与TensorBoard

2.2.1 什么是图结构

图包含了一组tf.Operation代表的计算单元对象和tf.Tensor代表的计算单元之间流动的数据。

2.2.2 图相关操作

1 默认图

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

# 实现一个加法运算
con_a = tf.constant(3.0)
con_b = tf.constant(4.0)

sum_c = tf.add(con_a, con_b)

print("打印con_a:\n", con_a)
print("打印con_b:\n", con_b)
print("打印sum_c:\n", sum_c)

# 图:打印出来,就是一个分配内存的地址
# 所有的张量、op、会话默认都在一张图当中
print("获取默认图:\n", tf.get_default_graph())
print("con_a的图属性为:\n", con_a.graph)
print("con_b的图属性为:\n", con_b.graph)
print("sum_c的图属性为:\n", sum_c.graph)

# 会话,默认只能运行默认的图,不能运行其它的(可以通过参数解决)
with tf.Session() as sess:
    print("con_a的值为:\n", sess.run(con_a))
    print("con_b的值为:\n", sess.run(con_b))
    print("sum_c的值为:\n", sess.run(sum_c))
    print("该会话的图属性为:\n", sess.graph)
  • 结论:op、sess都含有graph属性 ,默认都在一张图中

2 创建图

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

new_g = tf.Graph()
with new_g.as_default():
    # 在g图中定义了一个operation
    con_d = tf.constant(30.0)

    print("con_d的图属性为:\n", con_d.graph)

with tf.Session(graph=new_g) as new_sess:
    print("con_d的值为:\n", new_sess.run(con_d))
    print("新会话的图属性为:\n", new_sess.graph)

TensorFlow有一个亮点就是,我们能看到自己写的程序的可视化效果,这个功能就是Tensorboard。在这里我们先简单介绍一下其基本功能。

2.2.3 TensorBoard:可视化学习

TensorFlow 可用于训练大规模深度神经网络所需的计算,使用该工具涉及的计算往往复杂而深奥。为了更方便 TensorFlow 程序的理解、调试与优化,TensorFlow提供了TensorBoard 可视化工具。

实现程序可视化过程:

1 数据序列化-events文件

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

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

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

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

2 启动TensorBoard

tensorboard  --logdir="./tmp/tensorflow/summary/test/"

在浏览器中打开 TensorBoard 的图页面 127.0.0.1:6006 ,会看到与以下图形类似的图,在GRAPHS模块我们可以看到以下图结构

2.2.4 OP

1 常见OP

哪些是OP?

类型实例
标量运算add, sub, mul, div, exp, log, greater, less, equal
向量运算concat, slice, splot, constant, rank, shape, shuffle
矩阵运算matmul, matrixinverse, matrixdateminant
带状态的运算Variable, assgin, assginadd
神经网络组件softmax, sigmoid, relu,convolution,max_pool
存储, 恢复Save, Restroe
队列及同步运算Enqueue, Dequeue, MutexAcquire, MutexRelease
控制流Merge, Switch, Enter, Leave, NextIteration

一个操作对象(Operation)是TensorFlow图中的一个节点, 可以接收0个或者多个输入Tensor, 并且可以输出0个或者多个Tensor,Operation对象是通过op构造函数(如tf.matmul())创建的。

例如: c = tf.matmul(a, b) 创建了一个Operation对象,类型为 MatMul类型, 它将张量a, b作为输入,c作为输出,,并且输出数据,打印的时候也是打印的数据。其中tf.matmul()是函数,在执行matmul函数的过程中会通过MatMul类创建一个与之对应的对象

# 实现一个加法运算
con_a = tf.constant(3.0)
con_b = tf.constant(4.0)

sum_c = tf.add(con_a, con_b)

print("打印con_a:\n", con_a)
print("打印con_b:\n", con_b)
print("打印sum_c:\n", sum_c)

打印语句会生成:

打印con_a:
 Tensor("Const:0", shape=(), dtype=float32)
打印con_b:
 Tensor("Const_1:0", shape=(), dtype=float32)
打印sum_c:
 Tensor("Add:0", shape=(), dtype=float32)

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

请注意,tf.Tensor 对象以输出该张量的 tf.Operation 明确命名。张量名称的形式为 "<OP_NAME>:<i>",其中:

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

2 指令名称

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" )

2.3 会话

2.3.1 会话

一个运行TensorFlow operation的类。会话包含以下两种开启方式

  • tf.Session:用于完整的程序当中
  • tf.InteractiveSession:用于交互式上下文中的TensorFlow ,例如shell

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

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

1 __init__(target='', graph=None, config=None)

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

def session_demo():
    # 会话的演示

    # 1、不使用上下文管理器:
    a = tf.constant(10)
    b = tf.constant(20)
    c = tf.add(a, b)
    # 创建会话对象:
    sess = tf.Session()
    # 执行操作c
    print("不使用上下文管理器:\n", sess.run(c))
    # 关闭会话
    sess.close()
    # 2、使用上下文管理器:
    with tf.Session() as sess:
        print("使用上下文管理器:\n", sess.run(c))

    return None
  • target:如果将此参数留空(默认设置),会话将仅使用本地计算机中的设备。可以指定 grpc:// 网址,以便指定 TensorFlow 服务器的地址,这使得会话可以访问该服务器控制的计算机上的所有设备。
  • graph:默认情况下,新的 tf.Session 将绑定到当前的默认图。
  • config:此参数允许您指定一个 tf.ConfigProto 以便控制会话的行为。例如,ConfigProto协议用于打印设备使用信息
# 运行会话并打印设备信息
sess = tf.Session(config=tf.ConfigProto(allow_soft_placement=True,
                                        log_device_placement=True))

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

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

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

2 会话的run()

  • run(fetches,feed_dict=None, options=None, run_metadata=None)
    • 通过使用sess.run()来运行operation
    • fetches:单一的operation,或者列表、元组(其它不属于tensorflow的类型不行)
    • feed_dict:参数允许调用者覆盖图中张量的值,运行时赋值
      • 与tf.placeholder搭配使用,则会检查值的形状是否与占位符兼容。

使用tf.operation.eval()也可运行operation,但需要在会话中运行

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

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

# 计算C的值
print(sess.run(c))
print(c.eval(session=sess))

3 feed操作

  • placeholder提供占位符,run时候通过feed_dict指定参数
def session_demo():
    """
    会话相关演示
    :return:
    """
    # 实例化会话对象
    a = tf.constant(10)
    b = tf.constant(20)
    c = tf.add(a, b)
    # 定义placeholder
    ph = tf.placeholder(dtype=tf.int32, shape=[None, 4])

    # 会话的创建
    # 1、实例化一个Session对象
    sess = tf.Session(config=tf.ConfigProto(allow_soft_placement=True,
                                        log_device_placement=True))

    # print("a, b, c的值为:\n", sess.run([a, b, c]))
    print("c.eval:\n", c.eval(session=sess))
    a, b, c = sess.run([a, b, c])
    print("a:\n", a)
    print("b:\n", b)
    print("c:\n", c)

    # 运行placeholder
    print("placeholder:\n", sess.run(ph, feed_dict={ph: [[2, 4, 6, 8], [1, 3, 5, 7]]}))
    print("ph_eval:\n", ph.eval(session=sess, feed_dict={ph: [[2, 4, 6, 8], [1, 3, 5, 7]]}))
    # 2、用完会话的资源之后应该把资源回收
    sess.close()

    # 最常用的还是用上下文管理器的方式

    return None

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

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

 2.4 张量

2.4.1 张量(Tensor)

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

  • type:数据类型
  • shape:形状(阶)

1 张量的类型

 

 

 

 

 

 

 

 

 

2 张量的阶

形状有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.4.2 创建张量的指令

 

 

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

2.4.3 张量的变换

1 类型改变

 

 

2 形状改变

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

  • tf.reshape
  • tf.set_shape

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

  • 静态形状
    • 转换静态形状的时候,1-D到1-D,2-D到2-D,不能跨阶数改变形状
    • 对于已经固定的张量的静态形状的张量,不能再次设置静态形状
  • 动态性状
    • tf.reshape()动态创建新张量时,张量的元素个数必须匹配
# 能用set_shape就优先使用,不能用的话,使用reshape

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

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

new_tensor = tf.reshape(ph, [4, 3])

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

with tf.Session() as sess:

    print(sess.run(tensor1))

2.4.4 张量的数学运算

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

详细请参考: https://www.tensorflow.org/versions/r1.8/api_guides/python/math_ops

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

2.5 变量OP

2.5.1 变量

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

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

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 = tf.global_variables_initializer()

with tf.Session() as sess:
    # 运行初始化变量的OP
    sess.run(init_op)

2 变量OP的方法

  • new_var = assign(value)
    • 给变量赋值一个新的值
  • new_var = assign_add(delta)
var = tf.Variable(tf.random_normal([2, 2], mean=0.0, stddev=1.0), name="var", trainable=True)
var1 = var.assign([[2, 3], [4, 5]])
init_op = tf.global_variables_initializer()
va = var.assign_add([[1, 3], [4, 5]])
with tf.Session() as sess:
    # 运行初始化op
    sess.run(init_op)
    print(sess.run(va))
    print(sess.run(var))

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

2.5.2 命名空间与共享变量

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

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 使用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>

3 tf.get_variable共享变量

通过tf.get_variable的初始化与Variable参数一样,但是要是实现共享需要打开tf.variable_scope("name")中的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 = 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:
    sess.run(tf.global_variables_initializer())
    print(var1)
    print(var1_double)

2.6 高级API 

2.6.1 其它基础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 构建网络的核心模块。其中包含了添加各种层的函数,比如添加卷积层、池化层等。

2.6.2 高级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 的网络,只是全连接网络,没有提供卷积之类的。

2.7 案例:实现线性回归

2.7.1 线性回归原理复习

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

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

1 案例确定

  • 假设随机指定100个点,只有一个特征
  • 数据本身的分布为 y = 0.7 * x + 0.8

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

2 API

运算

  • 矩阵运算
    • tf.matmul(x, w)
  • 平方
    • tf.square(error)
  • 均值
    • tf.reduce_mean(error)

梯度下降优化

  • tf.train.GradientDescentOptimizer(learning_rate)
    • 梯度下降优化
    • learning_rate:学习率,一般为0~1之间比较小的值
    • method:
      • minimize(loss)
    • return:梯度下降op

3 步骤分析

  • 1 准备好数据集:y = 0.8x + 0.7 100个样本
  • 2 建立线性模型
    • 随机初始化W1和b1
    • y = W·X + b,目标:求出权重W和偏置b
  • 3 确定损失函数(预测值与真实值之间的误差)-均方误差
  • 4 梯度下降优化损失:需要指定学习率(超参数)

4 实现完整功能

import tensorflow as tf
import os

def linear_regression():
    """
    自实现线性回归
    :return: None
    """
    # 1)准备好数据集:y = 0.8x + 0.7 100个样本
    # 特征值X, 目标值y_true
    X = tf.random_normal(shape=(100, 1), mean=2, stddev=2)
    # y_true [100, 1]
    # 矩阵运算 X(100, 1)* (1, 1)= y_true(100, 1)
    y_true = tf.matmul(X, [[0.8]]) + 0.7
    # 2)建立线性模型:
    # y = W·X + b,目标:求出权重W和偏置b
    # 3)随机初始化W1和b1
    weights = tf.Variable(initial_value=tf.random_normal(shape=(1, 1)))
    bias = tf.Variable(initial_value=tf.random_normal(shape=(1, 1)))
    y_predict = tf.matmul(X, weights) + bias
    # 4)确定损失函数(预测值与真实值之间的误差)-均方误差
    error = tf.reduce_mean(tf.square(y_predict - y_true))
    # 5)梯度下降优化损失:需要指定学习率(超参数)
    # W2 = W1 - 学习率*(方向)
    # b2 = b1 - 学习率*(方向)
    optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.01).minimize(error)

    # 初始化变量
    init = tf.global_variables_initializer()
    # 开启会话进行训练
    with tf.Session() as sess:
        # 运行初始化变量Op
        sess.run(init)
        print("随机初始化的权重为%f, 偏置为%f" % (weights.eval(), bias.eval()))
        # 训练模型
        for i in range(100):
            sess.run(optimizer)
            print("第%d步的误差为%f,权重为%f, 偏置为%f" % (i, error.eval(), weights.eval(), bias.eval()))

    return None

5 学习率的设置、步数的设置与梯度爆炸

学习率越大,训练到较好结果的步数越小;学习率越小,训练到较好结果的步数越大。

但是学习过大会出现梯度爆炸现象。关于梯度爆炸/梯度消失 ?

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

6 变量的trainable设置观察

trainable的参数作用,指定是否训练

weight = tf.Variable(tf.random_normal([1, 1], mean=0.0, stddev=1.0), name="weights", trainable=False)

2.7.3 增加其他功能

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

1 增加命名空间

是代码结构更加清晰,Tensorboard图结构清楚

with tf.variable_scope("lr_model"):

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),每次迭代都需运行
    • 添加:FileWriter.add_summary(summary,i),i表示第几次的值
def linear_regression():
    # 1)准备好数据集:y = 0.8x + 0.7 100个样本
    # 特征值X, 目标值y_true
    with tf.variable_scope("original_data"):
        X = tf.random_normal(shape=(100, 1), mean=2, stddev=2, name="original_data_x")
        # y_true [100, 1]
        # 矩阵运算 X(100, 1)* (1, 1)= y_true(100, 1)
        y_true = tf.matmul(X, [[0.8]], name="original_matmul") + 0.7
    # 2)建立线性模型:
    # y = W·X + b,目标:求出权重W和偏置b
    # 3)随机初始化W1和b1
    with tf.variable_scope("linear_model"):
        weights = tf.Variable(initial_value=tf.random_normal(shape=(1, 1)), name="weights")
        bias = tf.Variable(initial_value=tf.random_normal(shape=(1, 1)), name="bias")
        y_predict = tf.matmul(X, weights, name="model_matmul") + bias
    # 4)确定损失函数(预测值与真实值之间的误差)-均方误差
    with tf.variable_scope("loss"):
        error = tf.reduce_mean(tf.square(y_predict - y_true), name="error_op")
    # 5)梯度下降优化损失:需要指定学习率(超参数)
    # W2 = W1 - 学习率*(方向)
    # b2 = b1 - 学习率*(方向)
    with tf.variable_scope("gd_optimizer"):
        optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.01, name="optimizer").minimize(error)

    # 2)收集变量
    tf.summary.scalar("error", error)
    tf.summary.histogram("weights", weights)
    tf.summary.histogram("bias", bias)

    # 3)合并变量
    merge = tf.summary.merge_all()

    # 初始化变量
    init = tf.global_variables_initializer()
    # 开启会话进行训练
    with tf.Session() as sess:
        # 运行初始化变量Op
        sess.run(init)
        print("随机初始化的权重为%f, 偏置为%f" % (weights.eval(), bias.eval()))
        # 1)创建事件文件
        file_writer = tf.summary.FileWriter(logdir="./summary", graph=sess.graph)
        # 训练模型
        for i in range(100):
            sess.run(optimizer)
            print("第%d步的误差为%f,权重为%f, 偏置为%f" % (i, error.eval(), weights.eval(), bias.eval()))
            # 4)运行合并变量op
            summary = sess.run(merge)
            file_writer.add_summary(summary, i)

    return None

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')

如要判断模型是否存在,直接指定目录

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

saver.restore(sess, checkpoint)

4 命令行参数使用

  • 1、

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

前面具体定义的flag_name

  • 3、通过tf.app.run()启动main(argv)函数
# 定义一些常用的命令行参数
# 训练步数
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)

完整代码

import tensorflow as tf
import os

tf.app.flags.DEFINE_string("model_path", "./linear_regression/", "模型保存的路径和文件名")
FLAGS = tf.app.flags.FLAGS


def linear_regression():
    # 1)准备好数据集:y = 0.8x + 0.7 100个样本
    # 特征值X, 目标值y_true
    with tf.variable_scope("original_data"):
        X = tf.random_normal(shape=(100, 1), mean=2, stddev=2, name="original_data_x")
        # y_true [100, 1]
        # 矩阵运算 X(100, 1)* (1, 1)= y_true(100, 1)
        y_true = tf.matmul(X, [[0.8]], name="original_matmul") + 0.7
    # 2)建立线性模型:
    # y = W·X + b,目标:求出权重W和偏置b
    # 3)随机初始化W1和b1
    with tf.variable_scope("linear_model"):
        weights = tf.Variable(initial_value=tf.random_normal(shape=(1, 1)), name="weights")
        bias = tf.Variable(initial_value=tf.random_normal(shape=(1, 1)), name="bias")
        y_predict = tf.matmul(X, weights, name="model_matmul") + bias
    # 4)确定损失函数(预测值与真实值之间的误差)-均方误差
    with tf.variable_scope("loss"):
        error = tf.reduce_mean(tf.square(y_predict - y_true), name="error_op")
    # 5)梯度下降优化损失:需要指定学习率(超参数)
    # W2 = W1 - 学习率*(方向)
    # b2 = b1 - 学习率*(方向)
    with tf.variable_scope("gd_optimizer"):
        optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.01, name="optimizer").minimize(error)

    # 2)收集变量
    tf.summary.scalar("error", error)
    tf.summary.histogram("weights", weights)
    tf.summary.histogram("bias", bias)

    # 3)合并变量
    merge = tf.summary.merge_all()

    # 初始化变量
    init = tf.global_variables_initializer()

    # 创建saver对象
    saver = tf.train.Saver()

    # 开启会话进行训练
    with tf.Session() as sess:
        # 运行初始化变量Op
        sess.run(init)
        # 未经训练的权重和偏置
        print("随机初始化的权重为%f, 偏置为%f" % (weights.eval(), bias.eval()))
        # 当存在checkpoint文件,就加载模型
        if os.path.exists("./linear_regression/checkpoint"):
            saver.restore(sess, FLAGS.model_path)
        # 1)创建事件文件
        file_writer = tf.summary.FileWriter(logdir="./summary", graph=sess.graph)
        # 训练模型
        for i in range(100):
            sess.run(optimizer)
            print("第%d步的误差为%f,权重为%f, 偏置为%f" % (i, error.eval(), weights.eval(), bias.eval()))
            # 4)运行合并变量op
            summary = sess.run(merge)
            file_writer.add_summary(summary, i)
            if i % 10 == 0:
                saver.save(sess, FLAGS.model_path)

    return None


def main(argv):
    print("这是main函数")
    print(argv)
    print(FLAGS.model_path)
    linear_regression()

if __name__ == "__main__":
    tf.app.run()

将面向过程改为面向对象

参考代码

# 用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)

                    if i % 100 == 0:
                        # 保存的是会话当中的变量op值,其他op定义的值不保存
                        saver.save(sess, FLAGS.model_dir)


if __name__ == '__main__':
    lr = MyLinearRegression()
    lr.train()
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: dncnn-denoise-gaussian-noise-tensorflow-master 是一个基于 TensorFlow 框架的去噪神经网络模型。 DNCNN(Dense Convolutional Neural Network)是一种密集卷积神经网络,用于图像去噪任务。它具有多个卷积层,每个卷积层都具有更多的卷积核,以增加网络的感知能力。这使得 DNCNN 在处理图像中的高斯噪声方面表现出色。 该模型的主要目标是去除图像中的高斯噪声。高斯噪声是一种常见的图像噪声,它具有随机性和连续性,由于传感器的限制、信号传输中的干扰或图像采集过程中的其他因素而产生。这种噪声会降低图像的质量并影响后续图像处理任务的效果。 通过训练,dncnn-denoise-gaussian-noise-tensorflow-master 模型学习如何通过卷积层进行特征提取,并使用残差学习来学习重建干净图像。网络的输入是噪声图像,输出是去噪后的图像。通过对许多含有噪声和干净图像对的训练样本进行迭代训练,模型能够学习去除高斯噪声,并还原出更清晰的图像。 该模型主要依赖于 TensorFlow 框架来构建神经网络结构和进行训练。TensorFlow 是一个开源机器学习框架,提供了一套丰富的工具和库,方便有效地实现各种深度学习模型。通过使用 TensorFlow,我们可以更方便地搭建、训练和测试 DNCNN 模型,以实现图像去噪的目标。 总而言之,dncnn-denoise-gaussian-noise-tensorflow-master 是一个使用 TensorFlow 构建的神经网络模型,旨在通过训练去除图像中的高斯噪声,并恢复出清晰的图像。它通过密集卷积神经网络结构和残差学习来实现这一目标,并利用 TensorFlow 提供的功能来简化模型的构建和训练过程。 ### 回答2: "DnCNN-denoise-gaussian-noise-tensorflow-master"是一个基于TensorFlow开发的用于去除高斯噪声的深度神经网络模型。DnCNN代表深度卷积神经网络去噪,它是一种用于图像去噪的先进方法。高斯噪声是一种常见的图像噪声类型,它以正态分布为基础生成,对于图像质量和清晰度有很大影响。 这个项目的目标是利用DnCNN模型,使用TensorFlow实现去除高斯噪声的功能。TensorFlow是一个开源的机器学习框架,提供了丰富的工具和函数库,用于构建和训练深度神经网络模型。通过使用TensorFlow,我们可以高效地创建、训练和优化深度学习模型。 该项目的"master"表示主分支,通常是最新、最稳定的版本。这意味着"DnCNN-denoise-gaussian-noise-tensorflow-master"是基于最新版本的DnCNN网络,并且已经在TensorFlow上进行了实现。 通过使用这个项目,我们可以将含有高斯噪声的图像输入到DnCNN模型中,并得到去噪后的输出图像。这个模型能够学习和理解高斯噪声的特征,并将其从图像中去除,以恢复图像的真实细节和清晰度。这对于许多计算机视觉任务,如人脸识别、图像增强和图像分析等都是非常有用的。 总之,"DnCNN-denoise-gaussian-noise-tensorflow-master"是一个基于TensorFlow实现的高斯噪声去除深度学习模型,它可以帮助我们有效地去除图像中的高斯噪声,提高图像质量和清晰度。 ### 回答3: dncnn-denoise-gaussian-noise-tensorflow-master 是一个基于TensorFlow框架实现的深度卷积神经网络(DnCNN)用于去噪高斯噪声的开源项目。 去噪是数字图像处理中的一个重要任务,因为图像数据常常受到各种噪声的干扰,其中高斯噪声是一种常见的噪声类型。dncnn-denoise-gaussian-noise-tensorflow-master提供了一种通过深度学习方法去除高斯噪声的解决方案。 该项目的实现基于深度卷积神经网络(DnCNN)。深度卷积神经网络是一种具有多层卷积和池化层的神经网络结构,通过学习数据的高级特征来实现图像去噪。DnCNN主要由卷积层、批归一化层和ReLU激活函数组成,通过多层卷积操作来逐渐去噪图像。 在dncnn-denoise-gaussian-noise-tensorflow-master项目中,程序提供了对高斯噪声图像进行训练和测试的功能。用户可以使用该项目来训练自己的去噪模型,也可以使用已经训练好的模型来去噪自己的图像数据。项目还提供了一些辅助功能,如数据加载和保存、网络模型的定义和训练等。 使用dncnn-denoise-gaussian-noise-tensorflow-master可以帮助用户实现高效的图像去噪处理,降低图像中的噪声干扰,提升图像的质量。该项目的开源特性使得用户可以根据自己的需求进行修改和扩展,也可以从中学习深度学习和图像去噪的相关知识和技术。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值