1. 程式人生 > >Tensorflow+matplotlib視覺化梯度下降

Tensorflow+matplotlib視覺化梯度下降

這篇文章主要是為了展示matplotlib 3D圖視覺化梯度下降路徑的效果。

模型選擇了最簡單的y=w*x+b模型,建立一組資料,迭代訓練500次後,畫出平面曲線圖和原始資料散點圖,看看我們訓練處的模型擬合原始資料的表現如何。再畫一個3D圖,x軸為w,y軸為b,z軸為每次訓練的loss值,看看我們的梯度下降路徑的變化。

程式碼如下:

import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import os

os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
os.environ["CUDA_VISIBLE_DEVICES"] = '0'

lr = 0.1
iteration = 500
# 真正的w和b
real_params = [1.2, 2.5]

X = tf.placeholder(tf.float32, [None, 1])
Y = tf.placeholder(tf.float32, [None, 1])
# 要訓練的w和b初始化為5和4
weight = tf.Variable(initial_value=[[5]], dtype=tf.float32)
bias = tf.Variable(initial_value=[[4]], dtype=tf.float32)
y = tf.matmul(X, weight) + bias

loss = tf.losses.mean_squared_error(Y, y)
train_op = tf.train.GradientDescentOptimizer(lr).minimize(loss)

x_data = np.linspace(-1, 1, 200)[:, np.newaxis]
noise = np.random.normal(0, 0.1, x_data.shape)
y_data = x_data * real_params[0] + real_params[1] + noise

with tf.Session() as sess:
	sess.run(tf.global_variables_initializer())
	# 記錄訓練過程中的w、b和loss
	w_record = []
	b_record = []
	loss_record = []
	for i in range(iteration):
		w, b, cost, _ = sess.run([weight, bias, loss, train_op], feed_dict={X: x_data, Y: y_data})
		w_record.append(w)
		b_record.append(b)
		loss_record.append(cost)
	result = sess.run(y, feed_dict={X: x_data, Y: y_data})

plt.figure(1)
plt.scatter(x_data, y_data, s=1, color='r', alpha=0.5)
plt.plot(x_data, result, lw=1)
plt.show()
plt.close()

fig = plt.figure(2)
ax_3d = Axes3D(fig)
w_3d, b_3d = np.meshgrid(np.linspace(-4.2, 6.2, 50), np.linspace(-2.5, 7.5, 50))
loss_3d = np.array(
	[np.mean(np.square((x_data * w_ + b_) - y_data)) for w_, b_ in zip(w_3d.ravel(), b_3d.ravel())]).reshape(w_3d.shape)
ax_3d.plot_surface(w_3d, b_3d, loss_3d, cmap=plt.get_cmap('rainbow'))
# .ravel()函式會直接修改原始矩陣,也是將矩陣降成一維
w_record = np.array(w_record).ravel()
b_record = np.array(b_record).ravel()
# 梯度下降曲線
ax_3d.plot(w_record, b_record, loss_record, lw=6, c='blue')
# 起始點
ax_3d.scatter(w_record[0], b_record[0], loss_record[0], s=10, color='black')
ax_3d.set_xlabel('w')
ax_3d.set_ylabel('b')
plt.show()
plt.close()

首先將lr=0.1,看看效果如何:

這個時候曲線擬合的很好。

觀察3D圖,可以發現梯度下降直接到了最低的loss點。

現在我們將lr設為1.0,看看效果如何:

可以看到由於學習率過大,這個時候曲線很顯然不能擬合原始資料。

再看3D圖,我們可以發現loss值由於學習率過大,一直在"山谷"兩側震盪,無法到達最低點。