深度学习 tensorflow 计算图,会话,张量

1. 计算模型---计算图:

tensorflow是一个通过计算图的形式来表示计算的编程系统,每一个计算都是计算图上的一个节点,节点之间的边描述计算之间的依赖关系。所以计算过程一般分为两个步骤:

1.定义计算图

2.执行计算

tf.Graph函数支持生成新的计算图,不同计算图上的张量和运算都不会共享:

import tensorflow as tf

graph_1 = tf.Graph()   # 生成一个图
with graph_1.as_default():
    # 在图1中定义变量并且初始化
    v = tf.get_variable(name='v', initializer=tf.zeros_initializer(), shape=[1])

graph_2 = tf.Graph()    # 生成一个图
with graph_2.as_default():
    v = tf.get_variable(name='v', initializer=tf.ones_initializer(), shape=[1])


# 在graph_1中读取变量值
with tf.Session(graph=graph_1) as sess:  # 计算图1中
    tf.global_variables_initializer().run()
    with tf.variable_scope("", reuse=True):
        print(sess.run(tf.get_variable('v')))

# 在graph_1中读取变量值
with tf.Session(graph=graph_2) as sess:  # 计算图1中
    tf.global_variables_initializer().run()
    with tf.variable_scope("", reuse=True):
        print(sess.run(tf.get_variable('v')))

计算图可以用来隔离张量和计算。还可以指定运行图中计算的设备;

with graph_1.device('/gpu:0'):
    res = a + b

在计算图中,可以通过不同的集合来管理里资源,tf.add_to_collection()函数可以将不同的资源加入到不同的集合中进行管理。tensorflow自动管理了一些集合:
1.  Variables   ,  所有变量,持久化模型

2. Trainable Variable  ,   可训练的变量

3. Summary    日志相关的变量

4. Queue_runners   处理输入的变量(队列)

5. Moving Average Variables   滑动平均值

2. 数据模型--张量

张量是tensorflow管理数据的形式,但是张量实际上并不是保存的数据,而实如何得到这些数据的计算过程。张量中主要保存了三个属性: 名称(name), 维度(shape), 类型(type)

若果没指定类型,tensorflow会给出默认的类型,但是为了避免潜在的风险(类型不匹配),需要指定类型

int8, int16, int32, int64, uint8

float32,  float64

bool

complex64

complex128

3. 运行模型---会话

会话拥有和管理tensorflow程序运行时的所有资源,所有计算完成之后需要关闭会话来帮助系统回收资源。强烈推荐使用python的上下文管理器来使用会话。这样会避免程序因为异常而退出时未关闭会话导致资源泄露。

在tensorflow中可以对会话进行配置 tf.ConfigProto():

graph_1 = tf.Graph()   # 生成一个图
with graph_1.as_default():
    # 在图1中定义变量并且初始化
    v = tf.get_variable(name='v', initializer=tf.zeros_initializer(), shape=[1])

# 对会话进行配置
config = tf.ConfigProto(allow_soft_placement=True, log_device_placement=True)
# 在graph_1中读取变量值
with tf.Session(graph=graph_1, config=config) as sess:  # 计算图1中
    tf.global_variables_initializer().run()
    with tf.variable_scope("", reuse=True):
        print(sess.run(tf.get_variable('v')))

tf.ConfigProto()可以配置并行的线程数,GPU分配此策略,运算超时时间等参数。常用的参数有两个:
allow_soft_placement: 当这个参数为真时:

1. 运算无法在GPU上执行

2. 没有GPU资源

3. 运算输入包含对cpu运算结果的引用。

发生上述中的一种或多种情况,GPU上的运算可以放到CPU上执行。

因为不同GPU驱动版本对计算的支持会略有差别,通过设置这个参数为True,当某些运算无法被GPU执行时,会调整到CPU上,而不是报错。这提高了代码的可移植性。

log_device_placement为True时会记录每个节点被安排在那个设备上,方便调试。

神经网络参数与tensorflow变量:

变量tf.Variable()的作用就是更新和保存神经网络中的参数。

变量的初始化方法:
tf.random_normal  正态分布的随机数 , 参数(mean, std, dtype)

tf.truncated_normal 正态分布,如果随机出来的值如果偏离平均值超过两个标准差,则重新随机   。 参数(mean, std, dtype)

tf.uniform  均匀分布     参数(min,  max, dtype)

tf.random_gamma   gamma分布    参数(形状alpha, 尺度参数beta,  dtype)

tf.zeros ,   tf.ones,  tf.fill全为给定数字, tf.constant

一个前向传播的例子:

import tensorflow as tf

graph_1 = tf.Graph()   # 生成一个图
with graph_1.as_default():
    # 在图1中定义变量并且初始化
    w1 = tf.Variable(tf.random_normal(shape=[2, 3], stddev=1, dtype=tf.float32, seed=1))
    w2 = tf.Variable(tf.random_normal(shape=[3, 1], stddev=1, dtype=tf.float32, seed=1))
    x = tf.constant(value=[[0.7, 0.9]], dtype=tf.float32)

    # 前行传播
    a = tf.matmul(x, w1)
    y = tf.matmul(a, w2)

# 对会话进行配置
config = tf.ConfigProto(allow_soft_placement=True, log_device_placement=True)
# 在graph_1中读取变量值
with tf.Session(graph=graph_1, config=config) as sess:  # 计算图1中
    # sess.run(w1.initializer)   # 初始化变量
    # sess.run(w2.initializer)
    init_op = tf.global_variables_initializer()   # 初始化算有变量  初始化所有变量,这个函数会处理变量之间的依赖关系
    sess.run(init_op)
    print(sess.run(y))

反向传播:

在神经网络的优化算法中,最常用的方法是反向传播。反向传播算法的训练神经网络的流程:

placeholder: 相当于在途中定义一个位置,作为训练数据的传入接口:

import tensorflow as tf

graph_1 = tf.Graph()   # 生成一个图
with graph_1.as_default():
    # 在图1中定义变量并且初始化
    w1 = tf.Variable(tf.random_normal(shape=[2, 3], stddev=1, dtype=tf.float32, seed=1))
    w2 = tf.Variable(tf.random_normal(shape=[3, 1], stddev=1, dtype=tf.float32, seed=1))
    x = tf.placeholder(dtype=tf.float32, shape=[None, 2], name='input')   # placeholder的行数可以设置为None, 根据具体的传入数据再得到

    # 前行传播
    a = tf.matmul(x, w1)
    y = tf.matmul(a, w2)

# 对会话进行配置
config = tf.ConfigProto(allow_soft_placement=True, log_device_placement=True)
# 在graph_1中读取变量值
with tf.Session(graph=graph_1, config=config) as sess:  # 计算图1中
    # sess.run(w1.initializer)   # 初始化变量
    # sess.run(w2.initializer)
    init_op = tf.global_variables_initializer()   # 初始化算有变量
    sess.run(init_op)
    feed_dict = {x: [[0.7, 0.9], [0.1, 0.4], [0.6, 0.8]]}
    print(sess.run(y, feed_dict=feed_dict))

损失函数:

简单介绍一下损失函数:

在得到一个batch的计算结果后,需要定义一个损失函数来刻画当前的预测值和真实值之间的差距,然后通过优化算法来调整神经网络参数以减小差距。例如定义交叉熵损失函数。

tensorflow常用的三种优化方法:
1. tf.train.GridientDescentOptimizer     梯度下降法

2. tf.train.AdamOptimizer

3. tf.train.MomnteumOptimizer

完整程序:

import tensorflow as tf
from numpy.random import RandomState
import numpy as np


graph_1 = tf.Graph()   # 生成一个图
with graph_1.as_default():
    # 在图1中定义变量并且初始化
    w1 = tf.Variable(tf.random_normal(shape=[2, 3], stddev=1, dtype=tf.float32, seed=1))
    w2 = tf.Variable(tf.random_normal(shape=[3, 1], stddev=1, dtype=tf.float32, seed=1))

    x = tf.placeholder(dtype=tf.float32, shape=[None, 2], name='x-input')   # placeholder的行数可以设置为None, 根据具体的传入数据再得到
    y_ = tf.placeholder(dtype=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))) + (1-y)*tf.log(tf.clip_by_value(1-y, 1e-10, 1.0))
    # 通过clip_value(x, x_min. x_max)可以将x限制在合理的范围内
    train_step = tf.train.AdamOptimizer(learning_rate=0.001).minimize(cross_entropy)    # 定义损失函数


if __name__ == "__main__":
    batch_size = 8
    rdm = RandomState(1)
    data_size = 128
    X = rdm.rand(data_size, 2)    # 训练数据
    Y = [int(x1+x2 < 1) for(x1, x2) in X]
    Y = np.array(Y)  

    print(type(X))
    print(type(Y))
    # 对会话进行配置
    config = tf.ConfigProto(allow_soft_placement=True, log_device_placement=False)
    # 在graph_1中读取变量值
    with tf.Session(graph=graph_1, config=config) as sess:  # 计算图1中
        init_op = tf.global_variables_initializer()   # 初始化算有变量
        sess.run(init_op)

        print("训练前的权值")
        print(sess.run(w1))
        print(sess.run(w2))

        steps = 1000
        for i in range(steps):
            start = (i * batch_size) % data_size
            end = min(start + batch_size, data_size)
            sess.run(train_step, feed_dict={x: X[start: end], y_: Y[start: end].reshape([-1, 1])})
            # 每隔一段时间计算在所有数据上的交叉熵
            if i % 50 == 0:
                cross_entropy_value = sess.run(cross_entropy, feed_dict={x: X, y_: Y.reshape([-1, 1])})
                print("The loss is {}".format(cross_entropy_value))
        print("训练后的权值")
        print(sess.run(w1))
        print(sess.run(w2))

猜你喜欢

转载自blog.csdn.net/zj1131190425/article/details/89480716