CH4 简化神经网络模型
- 掌握标量、向量、张量等概念
- 掌握如何用向量形式简化神经网络结构并编程实现
- 了解线性问题
标量、向量、张量
张量
在上一章的代码中添加 print 函数:
代码
# import tensorflow as tf
import tensorflow.compat.v1 as tf
tf.disable_v2_behavior()
x1 = tf.placeholder(dtype = tf.float32)
x2 = tf.placeholder(dtype = tf.float32)
x3 = tf.placeholder(dtype = tf.float32)
yTrain = tf.placeholder(dtype = tf.float32)
print("x1: %s" %x1)
w1 = tf.Variable(0.1, dtype = tf.float32)
w2 = tf.Variable(0.1, dtype = tf.float32)
w3 = tf.Variable(0.1, dtype = tf.float32)
print("w1: %s" %w1)
n1 = x1 * w1
n2 = x2 * w2
n3 = x3 * w3
print("n1: %s" %n1)
y = n1 + n2 + n3
print("y: %s" %y)
loss = tf.abs(y - yTrain)
optimizer = tf.train.RMSPropOptimizer(0.001)
train = optimizer.minimize(loss)
sess = tf.Session()
# init = tf.global_variable_initializer()
init = tf.compat.v1.global_variables_initializer()
sess.run(init)
result = sess.run([train, x1, x2, x3, w1, w2, w3, y, yTrain], feed_dict={x1: 90, x2: 80, x3: 70, yTrain: 96})
print(result)
输出结果:
Placeholder:0 数字代表操作结果的编号(可能有多个输出结果)。x1 是 Tensor 对象。神经网络中,输入节点,隐藏层节点,输出节点都是张量。w1 是 Variable 对象(可变参数对象)。在神经网络中,参与节点运算的可变参数(权重)不是 Tensor 对象。
上一章引入的 “三好学生问题” 神经网络模型:
n1 = x1 * w1
# n1: Tensor("mul:0", dtype=float32)
Tensor(张量):包含 了对于输入数据的计算操作;容纳了一个(或一组)数据,即输出数据。
w1 = tf.Variable(0.1, dtype = tf.float32)
# w1: <tf.Variable 'Variable:0' shape=() dtype=float32_ref>
可变参数不是模型中节点的输出数据,会参与到某个神经元的计算。
总结:
- 张量( Tensor)就是神经网络中神经元节点接收输入数据后经过一定计算操作输出的结果对象;
- 张量( Tensor)在神经网络模型图中表现为各层的节点的输出节点加上连线所组成的整个神经网络模型图标表现的是张量在神经网络中 “流动(flow)” 的过程;
- 张量( Tensor)在程序中的具体表现是一个 Tensor 类型的对象。
向量和标量
向量:一串数字,程序中用一个数组表示例如:[90,80,70]
- 数组有顺序
- 根据数字判断向量维数
总结:
- 张量可以是一个标量,即一个数值
- 张量可以是一个向量,即一个一维数组
- 张量也可以是一个多维数组,来表达二维矩阵、三维矩阵甚至更多
- 张量的 阶 是指这个多维数组的维度数
- 张量的 形态 是指用一维数组表示的张量在各个维度上的数值数量(shape,表达张量中存储的数据的形式)
注意:一维数组:[90,80,70],形态 [3],只有一个维度,顶数 3,一阶;标量:统一用一个空数组便是形态 [] 或者 (),0 阶 ...
代码查看形态结果
import tensorflow as tf
x = tf.placeholder(dtype = tf.float32)
xShape = tf.shape(x) # tf.shape() 函数用于获取张量的形态
简化神经网络
用向量重新组织神经网络:
import tensorflow as tf
x = tf.placeholder(shape=[3], dtype=tf.float32)
yTrain = tf.placeholder(shape=[], dtype=tf.float32)
w = tf.Variable(tf.zeros([3]), dtype=tf.float32)
n = x * w
y = tf.reduce_sum(n)
loss = tf.abs(y - yTrain)
optimizer = tf.train.RMSPropOptimizer(0.001)
train = optimizer.minimize(loss)
sess = tf.Session()
init = tf.global_variables_initializer()
sess.run(init)
result = sess.run([train, x, w, y, yTrain, loss], feed_dict={x: [90, 80, 70], yTrain: 85})
print(result)
result = sess.run([train, x, w, y, yTrain, loss], feed_dict={x:[98, 95, 87], yTrain: 96})
print(result)
- x: shape=[0] 表示 x 的形态,取值为 3,表示输入占位符的数据是一个三维向量
- w: tf.zeros([3]),返回数组 [0,0,0],初始化
- yTrain: [], 标量
- n: 点乘
- tf.reduce_sum(): 将数组中所有数组相加求和得到一个标量 y
result = sess.run([train, x, w, y, yTrain, loss], feed_dict={x: [90, 80, 70], yTrain: 85})
print(result)
喂数据时,yTrain: 85
目标值送入的是 ** 标量形式 ** 的数据, x: [90, 80, 70]
送入 x 的是 ** 向量形式 ** 的输入数据。
代码
# import tensorflow as tf
import tensorflow.compat.v1 as tf
tf.compat.v1.disable_eager_execution()
x = tf.placeholder(shape=[3], dtype=tf.float32)
yTrain = tf.placeholder(shape=[], dtype=tf.float32)
w = tf.Variable(tf.zeros([3]), dtype=tf.float32)
n = x * w
y = tf.reduce_sum(n)
loss = tf.abs(y - yTrain)
optimizer = tf.train.RMSPropOptimizer(0.001)
train = optimizer.minimize(loss)
sess = tf.Session()
# init = tf.global_variable_initializer()
init = tf.compat.v1.global_variables_initializer()
sess.run(init)
result = sess.run([train, x, w, y, yTrain, loss], feed_dict={x: [90, 80, 70], yTrain: 85})
print(result)
result = sess.run([train, x, w, y, yTrain, loss], feed_dict={x:[98, 95, 87], yTrain: 96})
print(result)
注意: 向量形式在计算机中用的是数组来表达。
循环进行多次训练:
代码
# import tensorflow as tf
import tensorflow.compat.v1 as tf
tf.compat.v1.disable_eager_execution()
x = tf.placeholder(shape=[3], dtype=tf.float32)
yTrain = tf.placeholder(shape=[], dtype=tf.float32)
w = tf.Variable(tf.zeros([3]), dtype=tf.float32)
n = x * w
y = tf.reduce_sum(n)
loss = tf.abs(y - yTrain)
optimizer = tf.train.RMSPropOptimizer(0.001)
train = optimizer.minimize(loss)
sess = tf.Session()
# init = tf.global_variable_initializer()
init = tf.compat.v1.global_variables_initializer()
sess.run(init)
for i in range(5000):
result = sess.run([train, x, w, y, yTrain, loss], feed_dict={x: [90, 80, 70], yTrain: 85})
print(result)
result = sess.run([train, x, w, y, yTrain, loss], feed_dict={x:[98, 95, 87], yTrain: 96})
print(result)
误差被有效控制,运行结果基本一致(与 ch3 中的代码比较)。
简化的神经网络图:
用 Softmax 函数来规范可变参数
Softmax 函数:将一个向量规范化为一个所有数值相加和为 1 的新向量。
三好学生问题,几项分数的权重值之和一定为 100%,也就是 1.0。
w = tf.Variable(tf.zeros([3]), dtype = tf.float32)
wn = tf.nn.softmax(2)
n = x * wn
y = tf.reduce_sum(n)
nn(neural network) 是 TensorFlow 重要子类。
代码
# import tensorflow as tf
import tensorflow.compat.v1 as tf
tf.compat.v1.disable_eager_execution()
x = tf.placeholder(shape=[3], dtype=tf.float32)
yTrain = tf.placeholder(shape=[], dtype=tf.float32)
w = tf.Variable(tf.zeros([3]), dtype=tf.float32)
wn = tf.nn.softmax(w)
n = x * wn
y = tf.reduce_sum(n)
loss = tf.abs(y - yTrain)
optimizer = tf.train.RMSPropOptimizer(0.001)
train = optimizer.minimize(loss)
sess = tf.Session()
# init = tf.global_variable_initializer()
init = tf.compat.v1.global_variables_initializer()
sess.run(init)
for i in range(5000):
result = sess.run([train, x, w, y, yTrain, loss], feed_dict={x: [90, 80, 70], yTrain: 85})
print(result)
result = sess.run([train, x, w, y, yTrain, loss], feed_dict={x:[98, 95, 87], yTrain: 96})
print(result)
线性问题
线性问题:用图形来表达输入数值和输出数值的关系,在坐标系中将是一条直线。
增加了偏移量 b 后,可以表达更多的线性问题(适应性)
知识补充
Python 中的 print
# 按字符串输出
name = "Adam"
print("name: %s" %name)
# 按整数输出
x = 101
print("x: %d" %x)
# 按浮点数输出
y = 12.35
print("y: %f" %y)
矩阵
多维数组
x1 = [90, 80, 70]
x2 = [98, 95, 87]
xAll = [x1, x2]
xAll = [[90, 80, 70], [98, 95, 87]]
, xAll 称为 2x3 的二维数组。
点乘
练习
-
试定义一个形态为 [3,2] 的张量,并在 TensorFlow 中查看它与标量 7 相乘的结果。
import tensorflow as tf x = tf.placeholder(shape=[3, 2], dtype=tf.float32) y = tf.placeholder(shape=[], dtype=tf.float32) xy = x * y # xShape = tf.shape(xy) sess = tf.Session() result = sess.run(xy, feed_dict={x: [[1, 2], [3, 4], [5, 6]], y: 7}) print(result)
-
对上题中的张量进行 softmax 计算操作后查看结果
import tensorflow as tf x = tf.placeholder(shape=[3, 2], dtype=tf.float32) y = tf.placeholder(shape=[], dtype=tf.float32) xy = x * y r = tf.nn.softmax(x) # xShape = tf.shape(xy) sess = tf.Session() result = sess.run(r, feed_dict={x: [[1, 2], [3, 4], [5, 6]], y: 7}) print(result)