美文网首页
【Tensorflow】编程基础

【Tensorflow】编程基础

作者: 紫晶葫芦 | 来源:发表于2019-05-23 23:08 被阅读0次

前面说了那么多都是理论的东西,太空洞了。从今天开始就着手编程了,并在编程的过程中,会对前面提到的理论一一的实现一遍,以加深对理论的理解,闲话少说,这就开始。

1.Tensorflow编程模型

关键要素:
1.图:它包含训练模型的参数、语句、操作,它是Tensorflow 的核心,例如:上面提到的WX + B 就是放到图中的,图是运行到内存中的,所以在运行的过程中是特别的吃内存的。
2.张量:在线性代数中叫向量,在程序中一般叫多维数组,也就是上个文档中提到的样本(X)和标签(Y),在tensorflow 中使用placeholder表示方式。
3.OP:全称,operate。做的就是把输入的张量组合按W
X + B起来。
4.Variable:W、B就是Variable的表现形式之一。

图1
图的执行流程就是:张量 (输入) -> op (组合成 W*X + B) -> 运算资源(CPU/GPU)-> 输出结果,而整个图则是要放到session中运行的,也就是只有运行了session,图才能运行。

2.Tensorflow编程示例

示例1:

import tensorflow as tf  
hello = tf.constant("Hello Tensorflow!")   #定义一个常量
sess = tf.Session()                        #建立一个Session()
print(sess.run(hello))                     #通过Session中的run来运行结果
sess.close()                               #关闭Session()

运行结果:


图2

注意:1.constant() 是定义一个常量。2.Session创建了以后需要关闭,不然会造成内存泄漏。
示例2

a = tf.constant(3)                         #定义一个常量3
b = tf.constant(4)                         #定义一个常量4
with tf.Session() as sess:                 #建立Session
    print("相加:%i" % sess.run(a+b))      #运行a+b 也就是上面提到的OP
    print("相乘:%i" % sess.run(a*b))

运行结果:


图3

注意:1.使用with创建的Session() ,是不需要调用sess.close()的,它会在使用完了自动的调用close(),释放掉内存。
示例3

c = tf.placeholder(tf.int16)
d = tf.placeholder(tf.int16)
add = tf.add(c, d)
mul = tf.multiply(c, d)
with tf.Session() as sess2:
    print("相加:%i" % sess2.run(add, feed_dict={c: 3, d: 4}))  
    print("相乘:%i" % sess2.run(mul, feed_dict={c: 3, d: 4}))
    print(sess2.run([add, mul], feed_dict={c: 3, d: 4}))

运行结果:


图4

注意:1.这是使用placeholder注入的方式声明变量。

3.Tensorflow 变量的操作

1.variable 和 get_variable 的区别
使用tf.Variable时,如果检测到命名冲突,系统会自己处理。使用tf.get_variable()时,系统不会处理冲突,而会报错。但是,Variable 与get_variable 首次重名可以自动生成。本质就是:tf.Variable() 每次都在创建新对象,而tf.get_variable则不是。

with tf.Session() as sess2:
var1 = tf.Variable(1, name="var1")
var2 = tf.Variable(2, name="var1")
sess2.run(tf.global_variables_initializer())
print(var1.name)
print(var1.eval())
print(var2.name)
print(var2.eval())
print(var1 is var2)
#输出
var1:0
1
var1_1:0
2
False

get_var1 = tf.get_variable(name="var1", initializer=1)
print(get_var1.name)
get_var2 = tf.get_variable(name="var1", initializer=2)
print(get_var2.name)
#输出
var1_2:0
#错误信息
#ValueError: Variable w_1 already exists, disallowed. Did
#you mean to set reuse=True in VarScope?

2.variable_scope 与共享变量
加上作用域以后get_variable可以定义同样的变量名称,系统会自动的生成加作用域的变量。如果在作用域声明的过程中,加入reuse=True,表示可以重复使用,定义了共享部分,如果已经创建的变量对象,就把那个对象返回。

with tf.variable_scope("test1", ""):
    var1 = tf.get_variable(name="var1", shape=[2],dtype=float)  #定义1行2列的var1变量
    with tf.variable_scope("test2"):
        var2 = tf.get_variable(name="var1",shape=[2],dtype=float)
print(var1.name)
print(var2.name)
#输出
test1/var1:0
test1/test2/var1:0

with tf.variable_scope("test1", reuse=True):
    var3 = tf.get_variable(name="var1", shape=[2], dtype=float)
    with tf.variable_scope("test2"):
        var4 = tf.get_variable(name="var1", shape=[2], dtype=float)
print(var3.name)
print(var4.name)
#输出
test1/var1:0
test1/test2/var1:0

3.variable_scope 与name_scope的区别
variable_scope :是作用域,
name_scope:是操作符,针对上面提到的OP。如:下面的x = var2 + 0.1,就是一个操作。
示例:

with tf.variable_scope("scope3"):
    var1 = tf.get_variable("var1", [1])
    with tf.name_scope("scope_name"):  # 针对操作而言的
        var2 = tf.get_variable("var2", [1])
        x = var2 + 0.1
        with tf.variable_scope(""):
            with tf.name_scope(""):
                var3 = tf.get_variable("var3", [1])
                y = var2 + 0.2
print(var1.name)
print(var2.name)
print(x.op.name)
print(var3.name)
print(y.op.name)
# 输出
scope3/var1:0
scope3/var2:0
scope3/scope_name/add
scope3//var3:0
add_2

注意:
1.如果tf.name_scope(""),则提到顶层。
2.tf.variable_scope(""),则相当于增加了“”的域。
3.name_scope对变量的作用域variable_scope是没有任何影响的,但是variable_scope对name_scope是有影响的。

3.Tensorflow 图的操作

1.建立图

import tensorflow as tf
# 定义在全局默认图上的常量
c = tf.constant(0.0)  
# 重新的定义一个图
g = tf.Graph()
with g.as_default():
    c1 = tf.constant(0.0)
    # 获取c1所在的图的地址
    print(c1.graph)
    # 获取创建图的地址
    print(g)
    # 获取c所在图的地址,也就是全局图的地址
    print(c.graph)
# 获取全局图的地址
g2 = tf.get_default_graph()
print(g2)
# 重新生成全局图,并把旧的图销毁
tf.reset_default_graph()
# 获取全局图的地址
g3 = tf.get_default_graph()
print("g3:", g3)
#输出
<tensorflow.python.framework.ops.Graph object at 0x000001CD50C4AB70>
<tensorflow.python.framework.ops.Graph object at 0x000001CD50C4AB70>
<tensorflow.python.framework.ops.Graph object at 0x000001CD4BDA9EF0>
<tensorflow.python.framework.ops.Graph object at 0x000001CD4BDA9EF0>
g3: <tensorflow.python.framework.ops.Graph object at 0x000001CD50C4AE10>

注意:
1.如果在局部图的作用域中获取全局的默认图是不成功的,它只能得到局部的图。
2.重新设置全局图的方法tf.reset_default_graph()

with g.as_default():
    c1 = tf.constant(0.0)
    print(c1.graph)
    print(g)
    print(c.graph)
    g3 = tf.get_default_graph()
    print(g3)
# 输出
<tensorflow.python.framework.ops.Graph object at 0x000002138838BCF8>
<tensorflow.python.framework.ops.Graph object at 0x000002138838BCF8>
<tensorflow.python.framework.ops.Graph object at 0x00000213FF0CB0B8>
<tensorflow.python.framework.ops.Graph object at 0x000002138838BCF8>

2.获取张量

print(c1.name)
# 通过名字,使用所在的图获取张量
t = g.get_tensor_by_name(name="Const:0")
# 打印张量的属性
print(t)
#输出
Const:0
Tensor("Const:0", shape=(), dtype=float32)

3.获取节点操作OP

# 定义一行两列的数组
a = tf.constant([[1.0, 2.0]])
print(a.shape)
# 定义两行一列的数组
b = tf.constant([[1.0], [2.0]])
print(b.shape)
# 定义矩阵的乘法,操作的名字为:exampleop
tensor1 = tf.matmul(a, b, name="exampleop")
# 打印张量的名字、属性
print(tensor1.name, tensor1)
# 打印张量的名字、属性
test = g3.get_tensor_by_name("exampleop:0")
# 打印张量的属性
print(test)
# 输出
(1, 2)
(2, 1)
exampleop:0 Tensor("exampleop:0", shape=(1, 1), dtype=float32)
Tensor("exampleop:0", shape=(1, 1), dtype=float32)
print("获取操作的属性")
print('tensor1.op.name', tensor1.op.name)
# 通过名称使用所在的图得到操作OP的属性
testop = g3.get_operation_by_name("exampleop")
# 打印操作OP的属性
print(testop)
# 输出
tensor1.op.name exampleop
name: "exampleop"
op: "MatMul"
input: "Const"
input: "Const_1"
attr {
  key: "T"
  value {
    type: DT_FLOAT
  }
}
attr {
  key: "transpose_a"
  value {
    b: false
  }
}
attr {
  key: "transpose_b"
  value {
    b: false
  }
}

4.获取元素列表

# 返回图中的操作节点列表
tt2 = g.get_operations()
print(tt2)
# 输出 由上面可以看出在g图中只有c1 定义
[<tf.Operation 'Const' type=Const>]

5.获取对象

print("获取对象")
tt3 = g.as_graph_element(c1)
print(tt3)
# 输出
Tensor("Const:0", shape=(), dtype=float32)

4.深度学习训练模型简介

深度学习的基本开发流程为:
1.准备数据
2.搭建模型
3.训练模型
4.保存模型
5.测试模型
6.查看模型
下面以线性回归拟合为例(Y=2X)说明:
说明:1.numpy .random.randn(d0,d1,…,dn):randn函数返回一个或一组样本,具有标准正态分布 ,dn表格每个维度。2.tf.random.normal([1]):从正太分布中随机输出一个值。3.tf.zeros([1]):创建一个所有元素都设置为零的张量,例如:tf.zeros([2]) ,其中的值就是[0. 0.]。

import tensorflow as tf
# 生成数据时使用
import numpy as np
# 图形化生成数据
import matplotlib.pyplot as plt
# 生成字典记录训练批次和loss值
plotdata = {"batchsize": [], "loss": []}
# 1.准备数据
t_X = np.linspace(-1, 1, 100)
t_Y = 2 * t_X + np.random.randn(100) * 0.3
# 显示模拟数据
plt.plot(t_X, t_Y, "ro", label="original data")
plt.legend()
plt.show()

# 重新初始化图
tf.reset_default_graph();
# 2.搭建模型
# 占位符
X = tf.placeholder("float")
Y = tf.placeholder("float")
# 2.1模型参数
W = tf.Variable(tf.random.normal([1]), name="weight")
b = tf.Variable(tf.zeros([1]), name="bias")
# 2.2向前结构
z = tf.multiply(X, W) + b
# 2.3反向优化(均方差)
cost = tf.reduce_mean(tf.square(Y-z))
learning_rate = 0.01
# 2.4使用tf的梯度下降优化器设定的学利率不断优化W和b使的loss最小化,最终使z于Y的误差最小
optimizer = tf.train.GradientDescentOptimizer(learning_rate).minimize(cost)

# 3.训练模型
# 3.1初始化变量
init = tf.global_variables_initializer()
# 3.2训练参数
training_epochs = 20
display_step = 2

# 4.保存模型
saver = tf.train.Saver()
savedir = "Model/"
# 3.4启动Session
with tf.Session() as sess:
    sess.run(init)
    for epoch in range(training_epochs):
        for (x, y) in zip(t_X, t_Y):
            sess.run(optimizer, feed_dict={X: x, Y: y})

        # 显示训练中详细信息
        if epoch % display_step == 0:
            loss = sess.run(cost, feed_dict={X: t_X, Y: t_Y})
            print("测试cost:", cost)
            print("测试loss:", loss)
            print("Epoch:", epoch+1, "loss=", loss, "W=", sess.run(W), "b=", sess.run(b))
            if not (loss == "NA"):
                plotdata["batchsize"].append(epoch)
                plotdata["loss"].append(loss)

    print(" Finsohed!")
    print("loss=", sess.run(cost, feed_dict={X: t_X, Y: t_Y}), "")
    #  4-1保存模型
    saver.save(sess, savedir+"linermodel.cpkt")

    # 图形显示
    plt.plot(t_X, t_Y, "go", label="original data")
    plt.plot(t_X, sess.run(W)*t_X+sess.run(b), label="Fitted")
    plt.legend()
    plt.show()

    def moving_average(a, w=10):
        if len(a) < w:
            return a[:]
        return [val if idx < w else sum(a[(idx-w):idx])/w for idx, val in enumerate(a)]
    plotdata["avgloss"] = moving_average(plotdata["loss"])
    # plt.figure(1)
    # plt.subplot(211)
    plt.plot(plotdata["batchsize"], plotdata["avgloss"], "b--")
    plt.xlabel('Minibatch number')
    plt.ylabel('loss')
    plt.title('Minibatch run vs.Training loss')
    plt.show()

# 5.测试模型-1
    print("方式1:", "x= 0.2,z=", sess.run(z, feed_dict={X: 0.2}))

#   测试模型-2
with tf.Session() as sess2:
    # 从新初始一下变量
    sess2.run(tf.global_variables_initializer())
    saver.restore(sess2, savedir+"linermodel.cpkt")
    print("方式2:", "x= 0.2,z=", sess2.run(z, feed_dict={X: 0.2}))
# 输出


方式1: x= 0.2,z= [0.41271693]
方式2: x= 0.2,z= [0.41271693]

图5
图6
图7
查看模型:
import tensorflow as tf
# 从tensorflow.python.tools.inspect_checkpoint 引入 方法 print_tensors_in_checkpoint_file
from tensorflow.python.tools.inspect_checkpoint import print_tensors_in_checkpoint_file
savedir = "Model/"
# 打印参数
print_tensors_in_checkpoint_file(savedir +  "linermodel.cpkt",, tensor_name=None, all_tensors=True)

从新的修改参数:

import tensorflow as tf
# 从tensorflow.python.tools.inspect_checkpoint 引入 方法 print_tensors_in_checkpoint_file
from tensorflow.python.tools.inspect_checkpoint import print_tensors_in_checkpoint_file
savedir = "Model/"
# 修改参数
W = tf.Variable(1.0, name="weight")
b = tf.Variable(2.0, name="bias")
saver = tf.train.Saver({'weight': b, 'bias': W})

with tf.Session() as see:
    # 调用方式和以前的不一样
    tf.global_variables_initializer().run()
    # 保存参数
    saver.save(see, savedir + "linermodel.cpkt")
# 打印参数
print_tensors_in_checkpoint_file(savedir + "linermodel.cpkt", , tensor_name=None, all_tensors=True)

保存模型注意:
1.保存模型。由于训练的时间较长,且对内存要求过高,所以在训练的过程中,难免会出现异常,那么怎么样才能,不用多次重复的训练了呢。解决的最简单的办法就是训练几轮后对训练的结果进行保存,所以上面的演示代码是有问题的。修改的结果如下:

# 每次保存一次的检测点
saver = tf.train.Saver(max_to_keep=1)
savedir = "Model/"

if not (loss == "NA"):
    plotdata["batchsize"].append(epoch)
    plotdata["loss"].append(loss)
    # 加上保存的第几次循环
    saver.save(sess, savedir + "linermodel.cpkt", global_step=epoch)

2.使用模型的其他方式

with tf.Session() as sess2:
    # 从新初始一下变量
    sess2.run(tf.global_variables_initializer())
    saver.restore(sess2, savedir+"linermodel.cpkt")
    print("方式2:", "x= 0.2,z=", sess2.run(z, feed_dict={X: 0.2}))

with tf.Session() as sess3:
    sess3.run(tf.global_variables_initializer())
    ckpt = tf.train.get_checkpoint_state(savedir)
    # 判断ckpt 存在
    if ckpt and ckpt.model_checkpoint_path:
        saver.restore(sess3, ckpt.model_checkpoint_path)
        print("方式3:", "x= 0.2,z=", sess3.run(z, feed_dict={X: 0.2}))

with tf.Session() as sess4:
    sess4.run(tf.global_variables_initializer())
    # 检测最后一个文件
    ckpt = tf.train.latest_checkpoint(savedir)
    if ckpt != None:
        saver.restore(sess4, ckpt)
        print("方式4:", "x= 0.2,z=", sess4.run(z, feed_dict={X: 0.2}))

相关文章

网友评论

      本文标题:【Tensorflow】编程基础

      本文链接:https://www.haomeiwen.com/subject/woldzqtx.html