欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

tensorflow 学习笔记(一) —— 基本概念

程序员文章站 2022-06-03 16:02:48
...

tensorflow 学习笔记(一) —— 基本概念

参考链接

TensorFlow 中文社区

基本用法

  • 使用图(Graph) 来表示计算任务
  • 在会话(Session) 的上下文(Context)中执行图
  • 使用张量(Tensor) 维护状态
  • 使用 feedfetch 为任意的操作(arbitrary operation)赋值或者从其中获取数据

综述

TensorFlow 是一个编程系统, 使用图来表示计算任务. 图中的节点被称之为 op (operation 的缩写). 一个 op 获得 0 个或多个 Tensor, 执行计算, 产生 0 个或多个 Tensor. 每个 Tensor 是一个类型化的多维数组. 例如, 你可以将一小组图像集表示为一个四维浮点数数组, 这四个维度分别是 [batch, height, width, channels].

一个 TensorFlow 图描述了计算的过程. 为了进行计算, 图必须在 会话 里被启动. 会话 将图的 op 分发到诸如 CPU 或 GPU 之类的 设备 上, 同时提供执行 op 的方法. 这些方法执行后, 将产生的 tensor 返回.

计算图

TensorFlow 是一个通过计算图的形式来表述计算的编程系统。每一个计算都是计算图上的一个节点,而节点之间的边描述了计算之间的依赖关系。

例如,在加法计算 a+b 对应的计算图中,共有三个节点ab、和 add,有两条边 a->addb->addab 变量不依赖任何其他计算,而 add 计算则依赖读取两个常量的值,故只有两条边。

TensorFlow 程序一般可以分为两个阶段。第一阶段定义计算图中所有的计算,第二个阶段为执行计算。

TensorFlow Python 库有一个默认图 (default graph), op 构造器可以为其增加节点。不同计算图中的张量和运算不会共享。

会话

会话拥有并管理 TensorFlow 程序运行时的所有资源。构造阶段完成后, 才能启动图. 启动图的第一步是创建一个 Session 对象, 如果无任何创建参数, 会话构造器将启动默认图。

交互式使用

文档中的 Python 示例使用一个会话 Session 来 启动图, 并调用 Session.run() 方法执行操作.

为了便于使用诸如 IPython 之类的 Python 交互环境, 可以使用 InteractiveSession 代替 Session 类, 使用 Tensor.eval()Operation.run() 方法代替 Session.run(). 这样可以避免使用一个变量来持有会话.

张量(Tensor)

TensorFlow 程序使用 tensor 数据结构来代表所有的数据, 计算图中, 操作间传递的数据都是 tensor. 可以把 TensorFlow tensor 看作是一个 n 维的数组或列表.

变量

变量维护图执行过程中的状态信息。在调用 run() 执行表达式之前, 它并不会真正执行赋值操作。

当训练模型时,用变量来存储和更新参数。通常会将一个统计模型中的参数表示为一组变量. 例如, 你可以将一个神经网络的权重作为某个变量存储在一个 tensor 中. 在训练过程中, 通过重复运行训练图, 更新这个 tensor.

创建变量

当创建一个变量时,可将一个张量作为初始值传入构造函数 Variable()。实例代码如下:

# Create two variables.
weights = tf.Variable(tf.random_normal([784, 200], stddev=0.35),
                      name="weights")
biases = tf.Variable(tf.zeros([200]), name="biases")

变量初始化

  1. tf.initialize_all_variables() 添加一个操作对变量做初始化

    该操作会并行的初始化所有变量

    # Create two variables.
    weights = tf.Variable(tf.random_normal([784, 200], stddev=0.35),
                        name="weights")
    biases = tf.Variable(tf.zeros([200]), name="biases")
    ...
    # Add an op to initialize the variables.
    init_op = tf.initialize_all_variables()
    
    # Later, when launching the model
    with tf.Session() as sess:
    # Run the init operation.
    sess.run(init_op)
    ...
    # Use the model
    ...
    
    
  2. 由另一个变量初始化

    用其它变量的值初始化一个新的变量时,使用该变量的initialized_value()属性。实例代码如下:

    # Create a variable with a random value.
    weights = tf.Variable(tf.random_normal([784, 200], stddev=0.35),
                        name="weights")
    # Create another variable with the same value as 'weights'.
    w2 = tf.Variable(weights.initialized_value(), name="w2")
    # Create another variable with twice the value of 'weights'
    w_twice = tf.Variable(weights.initialized_value() * 0.2, name="w_twice")
    

Fetch 获取数据

为了取回操作的输出内容, 可以在使用 Session 对象的 run() 调用 执行图时, 传入一些 tensor, 这些 tensor 会帮助你取回结果。实例代码如下:

 import tensorflow as tf
 sess = tf.InteractiveSession()

input1 = tf.constant(3.0)
input2 = tf.constant(2.0)
input3 = tf.constant(5.0)
intermed = tf.add(input2, input3)
mul = tf.multiply(input1, intermed)

with tf.Session():
   # 将 op 传入 run() 调用,以获得这些 op 的结果
  result = sess.run([mul, intermed])
  print result

# 输出
# [21.0, 7.0]

Feed 传入数据

计算图中的 tensor, 除了可以以常量或变量的形式存储. TensorFlow 还提供了 feed 机制, 该机制可以临时替代图中的任意操作中的 tensor 可以对图中任何操作提交补丁, 直接插入一个 tensor.

feed 使用一个 tensor 值临时替换一个操作的输出结果. 你可以提供 feed 数据作为 run() 调用的参数. feed 只在调用它的方法内有效, 方法结束, feed 就会消失. 最常见的用例是将某些特殊的操作指定为 “feed” 操作, 标记的方法是使用 tf.placeholder() 为这些操作创建占位符.

具体示例如下:

input1 = tf.placeholder(tf.float32)
input2 = tf.placeholder(tf.float32)
output = tf.multiply(input1, input2)

with tf.Session() as sess2:
  print(sess2.run([output], feed_dict={input1:[7.], input2:[2.]}))

# 输出:
# [array([ 14.], dtype=float32)]

示例代码的主要作用是在运行时将值传入 input1 和 input2 变量,并计算结果。tf.placeholder() 主要充当占位符的作用,常见用法是,用其定义神经网络的输入,在每轮训练中,feed 不同的数据给该变量


import tensorflow as tf

from numpy.random import RandomState

# 定义训练数据 batch 的大小
batch_size = 8

# 定义神经网络参数
w1 = tf.Variable(tf.random_normal([2, 3], stddev=1, seed=1), name="w1")
w2 = tf.Variable(tf.random_normal([3, 1], stddev=1, seed=1), name="w2")

# 定义输入样本变量及标签变量
# 在 shape 的一个维度上使用 None 可以方便使用不同的 batch 大小。
# 在训练时需要把数据分成比较小的 batch,但是在测试时,可以一次性使用全部的数据。
# 当数据集比较小时这样比较方便测试,但是数据集比较大时,将大量数据放入一个 batch 可能回导致内存溢出
x = tf.placeholder(tf.float32, shape=(None, 2), name="x-input")
y_ = tf.placeholder(tf.float32, shape=(None, 1), name="y-input")

# 定义神经网络前向传播的过程
a = tf.matmul(x, w1)
y = tf.matmul(a, w2)

# 定义损失函数和反向传播的算法
y = tf.sigmoid(y)
cross_entropy = -tf.reduce_mean(
    y_ * tf.log(tf.clip_by_value(y, 1e-10, 1.0)) +
    (1 - y) * tf.log(tf.clip_by_value(1 - y, 1e-10, 1.0))
)
train_step = tf.train.AdamOptimizer(0.01).minimize(cross_entropy)

# 通过随机数生成一个模拟数据集
rdm = RandomState(1)
dataset_size = 128
X = rdm.rand(dataset_size, 2)

# 定义规则来给出样本的标签。
# 这里所有的 x1+x2<1 的样例都被认为是正样本,而其他为负样本
# 这里使用 0 表示负样本,1 表示正样本
Y = [[int(x1 + x2 < 1)] for (x1, x2) in X]

# 创建一个会话来运行 TensorFlow 程序
with tf.Session() as sess:
    init_op = tf.global_variables_initializer()
    # 初始化所有变量
    sess.run(init_op)

    # 生成随机数,初始化参数 w1、w2
    # 输出初始参数的值
    print("Initial w1 = {}".format(sess.run(w1)))
    print("Initial w2 = {}".format(sess.run(w2)))

    # w1 = [[-0.8113182   1.4845988   0.06532937]
    #        [-2.4427042   0.0992484   0.5912243 ]]
    # w2 = [[-0.8113182 ]
    #        [ 1.4845988 ]
    #        [ 0.06532937]]

    # 设定训练的轮数
    STEPS = 5000
    for i in range(STEPS):
        start = (i * batch_size) % dataset_size
        end = min(start + batch_size, dataset_size)

        # 每次选取 batch_size 个样本进行训练
        sess.run(train_step, feed_dict={x: X[start:end], y_: Y[start:end]})
        if i % 1000 == 0:
            # 每个一段时间计算在所有数据上的交叉熵并输出
            # 每次迭代,将新的数据传入 placeholder 并计算结果
            total_cross_entropy = sess.run(
                cross_entropy, feed_dict={x: X, y_: Y})
            print("After %d training step(s), cross entropy on all data is %g" %
                  (i, total_cross_entropy))

            '''
                输出结果:
                After 0 training step(s), cross entropy on all data is 0.308078
                After 1000 training step(s), cross entropy on all data is 0.00641535
                After 2000 training step(s), cross entropy on all data is 0.00298618
                After 3000 training step(s), cross entropy on all data is 0.00157679
                After 4000 training step(s), cross entropy on all data is 0.000767946
            '''

    # 输出训练后的神经网络参数的值
    print("w1 = {}".format(sess.run(w1)))
    print("w2 = {}".format(sess.run(w2)))
    '''
        训练之后的神经网络的参数的值:
        w1 = [[-4.292053   4.6222997  9.247156 ]
               [-5.5750513  2.9129956  9.276696 ]]
        w2 = [[-3.5147264]
               [ 5.200334 ]
               [ 7.366007 ]]
    '''