本节再介绍一个实例,对二次函数进行非线性回归
,并且使用 python 的matplotlib
库使训练结果动起来。
生成二次函数模拟数据
首先,创建一个等差数列,作为二次函数的自变量,然后按照 y = x^2 - 0.5
生成数据组。
#encoding=utf8
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
# 构建数据
xdata = np.linspace(-1,1,200, dtype=np.float32)[:, np.newaxis] # -1 到 1 范围,共 200 个数据,类型为 float32
ydata = np.square(xdata) - 0.5
xdata[:, np.newaxis],是将数据转成矩阵形式。
>> x = np.arange(3)
array([0, 1, 2])
>> x.shape
(3,)
>> x[:, np.newaxis]
array([[0],
[1],
[2]])
>> x[:, np.newaxis].shape
(3, 1)
为了让数据看起来更像是真实数据,加入随机噪声:
noise = np.random.normal(0, 0.05, xdata.shape).astype(np.float32)
ydata = ydata + noise
利用 matplotlib 库将生成的数据绘制成散点图(matplotlib 库的使用,可参考:python基础,安装并使用matplotlib库画图),添加代码:
fig = plt.figure()
ax = fig.add_subplot(1,1,1)
ax.scatter(xdata, ydata)
plt.show()
执行,得到:
构建网络模型
输入 x 和实际值 y_ 使用占位符
,权值和偏置使用变量
(关于占位符和变量的使用可参考placeholder 和 variable op的使用)。
# 输入和实际值
x = tf.placeholder(tf.float32)
y_ = tf.placeholder(tf.float32)
隐藏层我们使用 10 个神经元,那么隐藏层的权重w1
的形状就是[1,10],偏置b1
的形状为[1,10]。权重初始化为随机值,偏置初始化为一个较小的值,这是参考官方文档的。隐藏层的输出,使用ReLU
激活函数,否则网络将无法提供非线性信息,效果肯定不好。关于这一点,第八节说的非常清楚。
# 隐藏层
w1 = tf.Variable(tf.random_normal([1, 10]))
b1 = tf.Variable(tf.zeros([1, 10]) + 0.1)
l1 = tf.nn.relu(tf.matmul(x, w1) + b1)
每次训练,我们只需输出 1 个值,所以输出层权重w2
的形状为[10,1],偏置形状[1,1]。
# 输出层
w2 = tf.Variable(tf.random_normal([10, 1]))
b2 = tf.Variable(tf.zeros([1, 1]) + 0.1)
y = tf.matmul(l1, w2) + b2
接下来,定义好损失函数和训练方法,就可以训练网络了。
# 定义损失函数和训练方法
loss = tf.reduce_mean(tf.reduce_sum(tf.square(y - y_),
reduction_indices=[1]))
train = tf.train.GradientDescentOptimizer(0.2).minimize(loss)
训练网络,并且使结果可视化
初始化后,就可以在 session 里训练网络了。这里共训练 1001 次,每 50 次打印一次损失,并且描点作图一次,因此我们可以动态的看到训练结果。
# 初始化
init = tf.global_variables_initializer()
# 训练
with tf.Session() as sess:
sess.run(init)
for i in range(1001):
sess.run(train, feed_dict={x:xdata, y_:ydata})
if i%50 == 0:
print sess.run(loss, feed_dict={x:xdata, y_:ydata})
try:
ax.lines.remove(lines[0])
except Exception:
pass
lines = ax.plot(xdata, sess.run(y, feed_dict={x:xdata}), 'r-', lw=2)
plt.pause(0.1)
最终,全部代码如下:
#encoding=utf8
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
# 构建数据
xdata = np.linspace(-1,1,200, dtype=np.float32)[:, np.newaxis]
noise = np.random.normal(0, 0.05, xdata.shape).astype(np.float32)
ydata = np.square(xdata) - 0.5 + noise
# 绘制构建的数据
fig = plt.figure()
plt.ylim(-1,1) # 限制 y 轴的绘制区域
ax = fig.add_subplot(1,1,1)
ax.scatter(xdata, ydata)
plt.ion()#本次运行请注释,全局运行不要注释
plt.show()
# 构建网络
x = tf.placeholder(tf.float32)
y_ = tf.placeholder(tf.float32)
# 隐藏层
w1 = tf.Variable(tf.random_normal([1, 10]))
b1 = tf.Variable(tf.zeros([1, 10]) + 0.1)
l1 = tf.nn.relu(tf.matmul(x, w1) + b1)
# 输出层
w2 = tf.Variable(tf.random_normal([10, 1]))
b2 = tf.Variable(tf.zeros([1, 1]) + 0.1)
y = tf.matmul(l1, w2) + b2
# 定义损失函数和训练方法
loss = tf.reduce_mean(tf.reduce_sum(tf.square(y - y_),
reduction_indices=[1]))
train = tf.train.GradientDescentOptimizer(0.2).minimize(loss)
# 初始化
init = tf.global_variables_initializer()
# 训练
with tf.Session() as sess:
sess.run(init)
for i in range(1001):
sess.run(train, feed_dict={x:xdata, y_:ydata})
if i%50 == 0:
print sess.run(loss, feed_dict={x:xdata, y_:ydata})
try:
ax.lines.remove(lines[0])
except Exception:
pass
lines = ax.plot(xdata, sess.run(y, feed_dict={x:xdata}), 'r-', lw=2)
plt.pause(0.1)
运行之,可在终端里看到损失不断减小。
$ python t.py
0.00894436
0.0060519846
0.004842156
0.0042339526
0.0038231497
...
而且,训练的曲线也在不断往参考数据靠近,如下图,整个训练结果的变化,清晰的显示了出来。
[…] […]
[…] […]
[…] […]