赞
踩
1、 计算图概念
1.1 Tensor
Tensor就是张量, 可以简单理解为多维数组,表明了数据结构
1.2 Flow
Flow 表达了张量之间通过计算相互转化的过程,体现了数据模型
1.3 数据流图基础
- 数据流图是每个 TensorFlow 程序的核心,用于定义计算结构
-
- 每一个节点都是一个运算,每一条边代表了计算之间的依赖关系
上图展示了可完成基本加法运算的数据流图。在该图中,加法运算是用圆圈表示的,它可接收两个输入 (以指向该函数的箭头表示),并将 1 和 2 之和 3 输出 (对应从该函数引出的箭头)。该函数的运算结果可传递给其他函数,也可直接返回给客户。
节点(node) :
在数据流图的语境中,节点通常以圆圈、椭圆和方框表示,代表了对数据所做的运算或某种操作。在上例中,“add”对应于一个孤立节点。
边(edge) :
对应于向Operation传入和从Operation传出的实际数值,通常以箭头表示。在“add”这个例子中,输入1和2均为指向运算节点的边,而输出3则为 从运算节点引出的边。可从概念上将边视为不同Operation之间的连接,因为它们将信息从一个节点传输到另一个节点。
2、计算图的使用
TensorFlow 程序一般可以分成两个阶段
- 第一阶段 定义计算图中的所有计算
- 第二阶段 为执行计算
这里定义了 “input” 节点 a 和 b。语句第一次引用了 TensorFlow Operation:tf.constant()。在 TensorFlow 中,数据流图中的每个节点都被称为一个 Operation (简记为 Op )。各 Op 可接收 0 个或多个 Tensor 对象作为输入,并输出 0 个或多个 Tensor 对象。要创建一个 Op,可调用与其关联的 Python 构造方法,在本例中,tf.constant() 创建了一个 “常量” Op,它接收单个张量值,然后将同样的值输出给与其直接连接的节点。为方便起见,该函数自动将标量值 6 和 3 转换为 Tensor 对象。此外,我们还为这个构造方法传入了一个可选的字符串参数 name,用于对所创建的节点进行标识。
3、数据流图的可视化
3.1 添加代码
writer = tf.summary.FileWriter('./my_graph', sess.graph)
3.2 在 Terminal 输入命令
tensorboard --logdir="my_graph"
如图所示即成功
3.3 在浏览器输入 http://localhost:6006
切换到 GRAPHS 导航栏,就能看到数据流图
2.1 Python原生类型
TensorFlow 可接收 Python 数值、布尔值、字符串或由它们构成的列表。单个数值将被转化为 0 阶张量(或标量),数值列表将被转化为 1 阶张量(向量),由列表构成的列表将被转化为 2 阶张量(矩阵),以此类推。下面给出一些例子。
2.2 Numpy 类型
2.3 张量的形状
2.4 张量的使用
从上面的代码可以看出 TensorFlow 中的张量和 Numpy 中的数组不同,TensorFlow 计算的结果不是一个具体的数字, 而是一个张量的结构。
一个张量中主要保存了三个属性:名字(name),纬度(shape)和类型(type)。
名字(name):张量的第一个属性名字不仅是一个张量的唯一标识符,它同样也给出了这个张量是如何计算出来的
纬度(shape):描述了一个张量的维度信息
类型(type):每个张量会有一个唯一的类型
会话用来执行定义好的运算
3.1 使用会话的模式一般有两种,第一种是需要明确调用会话生成函数和关闭会话函数
代码:
- import tensorflow as tf
-
- a = tf.constant([1.0, 2.0], name = 'a')
- b = tf.constant([3.0, 4.0], name = 'b')
- c = tf.add(a, b, name = 'c')
-
- # 创建一个会话
- sess = tf.Session()
- sess.run(c)
- # 关闭会话使得本次运行中使用到的资源可以被释放
- sess.close()
然而,第一种模式在程序因异常退出时,关闭会话的函数可能不被执行从而导致资源泄漏, 第二种模式是通过上下文管理器来管理
- import tensorflow as tf
-
- a = tf.constant([1.0, 2.0], name = 'a')
- b = tf.constant([3.0, 4.0], name = 'b')
- c = tf.add(a, b, name = 'c')
-
- # 通过 python 中的上下文管理器来管理这个会话
- with tf.Session() as sess:
- sess.run()
-
- # 当上下文退出时会话关闭和资源释放也自动完成
3.2 交互式会话
在交互式环境下,通过设置默认会话的方式来获取张量的取值更加方便,使用 tf.InteractiveSession 会自动将生成的会话注册成为默认会话
4.1 feed_dict 参数
参数 feed_dict 用于覆盖数据流图中的 Tensor 对象值,它需要 Python 字典对象作为输入。字典中的“键”为指向应当被覆盖的 Tensor 对象的句柄,而字典的“值”可以是 数字、字符串、列表或 NumPy 数组(之前介绍过)。这些“值”的类型必须与 Tensor 的“键”相同,或能够转换为相同的类型。下面通过一些代码来展示如何利用 feed_dict 重写之前的数据流图中a的值:
- import tensorflow as tf
-
- a = tf.add(2, 5)
- b = tf.multiply(a, 3)
-
- sess = tf.Session()
-
- replace_dict = {a:15}
-
- sess.run(b, feed_dict=replace_dict)
-
4.2 占位节点应用
之前定义的数据流图并未使用真正的“输入”,它总是使用相同的数值 5 和 3。我们真正希望做的是从客户那里接收输入值,这样便可对数据流图中所描述的变换 以各种不同类型的数值进行复用,借助“占位符”可达到这个目的。正如其名称所预示的那样,占位符的行为与 Tensor 对象一致,但在创建时无须为它们指定具体的 数值。它们的作用是为运行时即将到来的某个 Tensor 对象预留位置,因此实际上变成了“输入”节点。利用 tf.placeholder Op 可创建占位符:
- import tensorflow as tf
- import numpy as np
-
- a = tf.placeholder(tf.int32, shape=[2], name = 'my_input')
- b = tf.reduce_prod(a, name = 'prod_a')
- c = tf.reduce_sum(a, name = 'sum_c')
-
- d = tf.add(b, c, name = 'add_d')
-
- sess = tf.Session()
-
- input_dict = {a : np.array([5, 3], dtype = np.int32)}
-
- sess.run(d, feed_dict = input_dict)
输出:23
现实世界中的模型往往会包含几十或上百个节点,以及数以百万计的参数。为使这种级别的复杂性可控,TensorFlow当前提供了一种帮助用户组织数据流图的机制 ——名称作用域(name scope)。
程序1:
- import tensorflow as tf
-
- with tf.name_scope('scope_a'):
- a = tf.add(1,2, name = 'a')
- b = tf.multiply(3, 4, name = 'b')
-
- with tf.name_scope('scope_b'):
- c = tf.add(4, 5, name = 'c')
- d = tf.multiply(6, 7, name = 'd')
-
- writer = tf.summary.FileWriter('./name_scope_1', graph = tf.get_default_graph())
- writer.close()
程序2:
- import tensorflow as tf
-
- graph = tf.Graph()
-
- with graph.as_default():
- in_1 = tf.placeholder(tf.float32, shape = [], name = 'input_a')
- in_2 = tf.placeholder(tf.float32, shape = [], name = 'input_b')
- const = tf.constant(3, dtype = tf.float32, name = 'static_value')
-
- with tf.name_scope('Transformation'):
-
- with tf.name_scope('A'):
- A_mul = tf.multiply(in_1, const)
- A_out = tf.subtract(A_mul, in_1)
-
- with tf.name_scope('B'):
- B_mul = tf.multiply(in_2, const)
- B_out = tf.subtract(B_mul, in_2)
-
- with tf.name_scope('C'):
- C_div = tf.div(A_out, B_out)
- C_out = tf.add(C_div, const)
-
- with tf.name_scope('D'):
- D_div = tf.div(B_out, A_out)
- D_out = tf.add(D_div, const)
- out = tf.maximum(C_out, D_out)
-
- writer = tf.summary.FileWriter('./name_scope_2', graph = graph)
- writer.close()
7.1 数据流图
- import tensorflow as tf
-
- graph = tf.Graph()
-
- with graph.as_default():
-
- with tf.name_scope("variables"):
- # 追踪数据流图运行次数
- global_step = tf.Variable(0, dtype = tf.int32, trainable = False, name = 'global_step')
-
- # 所有输出随时间的累加和
- total_output = tf.Variable(0.0, dtype = tf.float32, trainable = False, name = 'total_output')
-
- # 主要变换的 OP
- with tf.name_scope("transformation"):
-
- with tf.name_scope("input"):
- # 独立的输入层
- # 创建一个可以接收变量的占位符
- a = tf.placeholder(tf.float32, shape = [None], name = 'input_placeholder_a')
-
- # 独立的中间层
- with tf.name_scope("intermediate_layer"):
- b = tf.reduce_prod(a, name = 'b')
- c = tf.reduce_sum(a, name = 'c')
-
- # 独立的输出层
- with tf.name_scope("output"):
- output = tf.add(b, c, name = 'output')
-
- # 更新全局变量
- with tf.name_scope("update"):
- update_total = total_output.assign_add(output)
- increment_step = global_step.assign_add(1)
-
- #
- with tf.name_scope("summaries"):
- # 计算平均值
- avg = tf.div(update_total, tf.cast(increment_step, tf.float32), name = 'average')
- tf.summary.scalar('output', output)
- tf.summary.scalar('sum_of_outputs_overtime', update_total)
- tf.summary.scalar('average_of_outputs_over_time', avg)
-
-
- with tf.name_scope('global_ops'):
- # 初始化 OP
- init = tf.global_variables_initializer()
- # 将所有汇总数据合并到一个 OP 中
- merged_summaries = tf.summary.merge_all()
-
-
- sess = tf.Session(graph = graph)
-
- writer = tf.summary.FileWriter('./improved_graph', graph)
-
- sess.run(init)
-
- # 1)首先创建一个赋给Session.run()中feed_dict参数的字典,这对应于tf.placeholder节点,并用到了其句柄a。
- # 2)然后,通知Session对象使用feed_dict运行数据流图,我们希望确保output、increment_step以及merged_summaries Op能够得到执行。为写入汇总数据,需要保存 global_step和merged_summaries的值,因此将它们保存到Python变量step和summary中。这里用下划线“_”表示我们并不关心output值的存储。
- # 3)最后,将汇总数据添加到SummaryWriter对象中。global_step参数非常重要,因为它使TensorBoard可随时间对数据进行图示(稍后将看到,它本质上创建了一 个折线图的横轴)。
- def run_graph(input_tensor):
- feed_dict = {a : input_tensor}
- _, step, summary = sess.run([output, increment_step, merged_summaries], feed_dict = feed_dict)
- writer.add_summary(summary, global_step = step)
-
-
- run_graph([2, 8])
- run_graph([3, 1, 1, 3])
-
- writer.flush()
在 TensorBoard 显示为
8.1 神经网络解决分类问题主要步骤
1、提取问题中实体的特征向量作为神经网络的输入。不同的实体可以提取不同的特征向量
2、定义神经网络的结构,并定义如何从神经网络的输入得到输出,这个过程就是神经网络的前向传播算法
3、通过训练数据来调整神经网络中参数的取值
4、使用训练好的神经网络来预测未知的数据
8.2 神经网络前向传播
示意图:
代码1:
- import tensorflow as tf
-
- w1 = tf.Variable(tf.random_normal([2, 3], stddev = 1, seed = 1))
- w2 = tf.Variable(tf.random_normal([3, 1], stddev = 1, seed = 1))
-
- x = tf.constant([[0.7, 0.9]])
-
- a = tf.matmul(x, w1)
- y = tf.matmul(a, w2)
-
- sess = tf.Session()
-
- sess.run(w1.initializer)
- sess.run(w2.initializer)
-
- print(sess.run(y))
- sess.close()
代码2:使用占位函数,就不需要生成大量常量来提供输入数据
- import tensorflow as tf
-
- w1 = tf.Variable(tf.random_normal([2, 3], stddev = 1, seed = 1))
- w2 = tf.Variable(tf.random_normal([3, 1], stddev = 1, seed = 1))
-
- x = tf.placeholder(tf.float32, shape = (3, 2), name = 'input')
-
- a = tf.matmul(x, w1)
- y = tf.matmul(a, w2)
-
- sess = tf.Session()
- init = tf.initialize_all_variables()
- sess.run(init)
-
-
- print(sess.run(y, feed_dict = {x : [[0.7, 0.9], [0.1, 0.4], [0.5, 0.8]]}))
- sess.close()
8.3 反向传播算法
在神经网络优化算法中,最常用的就是反向传播算法
8.4 神经网络完整程序
- 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))
- w2 = tf.Variable(tf.random_normal([3, 1], stddev = 1, seed = 1))
-
- 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)
-
- # 定义损失函数和反向传播算法
- cross_entropy = -tf.reduce_mean(y_ * tf.log(tf.clip_by_value(y, 1e-10, 1.0)))
- train_step = tf.train.AdamOptimizer(0.001).minimize(cross_entropy)
-
- # 通过随机数生成一个模拟数据集
- rdm = RandomState(1)
- dataset_size = 128
- X = rdm.rand(dataset_size, 2)
- Y = np.array([[int(x1 + x2 < 1) for (x1, x2) in X]]).reshape(128, 1)
-
- with tf.Session() as sess:
- init = tf.initialize_all_variables()
-
- sess.run(init)
-
- print(sess.run(w1))
- print(sess.run(w2))
-
- # 设定训练轮数
- STEPS = 5000
- for i in range(STEPS):
-
- # 每次选取 batch_size 个样本进行训练
- start = (i * batch_size) % dataset_size
- end = min(start + batch_size, dataset_size)
-
- # 通过选取的样本训练神经网络并更新参数
- sess.run(train_step, feed_dict = {x : X[start : end], y_ : Y[start : end]})
-
- if i % 1000 == 0:
- # 每隔一段时间计算在所有数据上的交叉熵并输出
- total_cross_entropy = sess.run(cross_entropy, feed_dict = {x : X, y_ : Y})
- print("After %d training steps, cross entropy on all data is %g" % (i, total_cross_entropy))
-
- print(sess.run(w1))
- print(sess.run(w2))
输出:
- [[-0.81131822 1.48459876 0.06532937]
- [-2.44270396 0.0992484 0.59122431]]
- [[-0.81131822]
- [ 1.48459876]
- [ 0.06532937]]
- After 0 training steps, cross entropy on all data is 0.0674925
- After 1000 training steps, cross entropy on all data is 0.0163385
- After 2000 training steps, cross entropy on all data is 0.00907547
- After 3000 training steps, cross entropy on all data is 0.00714436
- After 4000 training steps, cross entropy on all data is 0.00578471
- [[-1.9618274 2.58235407 1.68203783]
- [-3.4681716 1.06982327 2.11788988]]
- [[-1.8247149 ]
- [ 2.68546653]
转载地址:http://blog.csdn.net/qq_21046135/article/details/76168639
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。