tensorflow入门学习,对二次函数的非线性回归,并使用matplotlib库使训练结果动态可视化(11)

本节再介绍一个实例,对二次函数进行非线性回归,并且使用 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
...

而且,训练的曲线也在不断往参考数据靠近,如下图,整个训练结果的变化,清晰的显示了出来。

阅读更多:   tensorflow