寫在前面:爲了可視化機器學習過程,而且保存下來,因此想直接利用 保存動圖,期間參考了好多資料,過程比較艱辛,因此想記錄下來。固然,此文還參考了好多網上的其它文章,再此一併感謝那些熱愛分享的 ,而且參考資料中給出連接。全部代碼整理到GitHub。php
先上效果! html
安裝 和 。具體安裝直接上官網即可,遇到什麼問題在網上基本能夠搜到答案的,這裏就不介紹了。這裏要簡單的使用 生成一些測試數據,若是對 不熟悉,參考 NumPy 官方快速入門教程(譯),若是對 不熟悉,參考Matplotlib 基本操做。固然若是要可以保存 還須要一個工具 ImageMagick,按照官方指導安裝就好,確保在命令中輸入 magick
有響應。若是使用 之類的 請將環境變量配置到全局,避免在 中找不到命令。python
請確保已經安裝了 ImageMagick 而且可用的狀況下再繼續,否則代碼跑步起來。git
這裏採用兩種方式繪製動圖github
重置重繪主要是每次更新原來圖形的值來達到繪製動圖的效果。算法
import numpy as np
from matplotlib import pyplot as plt
from matplotlib import animation
複製代碼
fig, ax = plt.subplots()
x = np.arange(0, 2 * np.pi, 0.01)
line0 = ax.plot(x, np.cos(x))
line, = ax.plot(x, np.sin(x))
複製代碼
注意,這裏申明的 中 ,
不能少,好像是爲了更新值時類型匹配。沒深究,但願知道的能夠指點一下。macos
def init():
line.set_ydata(np.sin(x))
return line,
def animate(i):
line.set_ydata(np.sin(x + i / 10.0))
return line,
複製代碼
其實就是更新一下 座標的值。bash
animation = animation.FuncAnimation(fig=fig, func=animate, frames=100, init_func=init, interval=20, blit=False)
複製代碼
這個函數的參數能夠看源碼,以及官網的介紹,這裏就是每一個 繪製一幀,總共有 幀。markdown
animation.save('resetvalue.gif', writer='imagemagick')
複製代碼
這裏就是直接保存成 格式就行了。app
plt.show()
複製代碼
生成圖片的效果如圖所示:
與上一種方法比較,這種就是不利用上一次的任何座標,直接擦除,而後再 圖形上去。
import numpy as np
from matplotlib import pyplot as plt
from matplotlib import animation
複製代碼
fig, ax = plt.subplots()
x = np.arange(0, 2 * np.pi, 0.01)
ax.plot(x, np.cos(x))
複製代碼
這裏就沒有那個要求了,由於這種方式不依賴於前面的圖形。
def init():
return ax.plot(x, np.sin(x))
def animate(i):
try:
ax.lines.pop(1)
except Exception:
pass
line = ax.plot(x, np.sin(x + i / 10.0), 'r')
return line,
複製代碼
初始化沒什麼好說的,其實也能夠不初始化,時間間隔過短效果基本是看不出來的。下面介紹一下 ax.lines.pop(1)
這句「擦除」函數。這裏的 能夠理解爲存儲 上來的圖像棧,前面 了一個餘弦函數,在初始化的時候繪製了第二條,因此索引是 的正弦函數被 了而後進行下一條繪製。因而執行 line = ax.plot(x, np.sin(x + i / 10.0), 'r')
animation = animation.FuncAnimation(fig=fig, func=animate, frames=100, init_func=init, interval=20, blit=False)
animation.save('redraw.gif', writer='imagemagick')
plt.show()
複製代碼
沒區別
生成圖片的效果如圖所示:
前面介紹了的知識基本夠用了,但終究不是實操。若是你不是學習機器學習的,其實有上面的基礎就能夠了,這一節能夠跳過。可是,若是你想學機器學習的話,這裏提供一個小例子讓你更加清晰的理解機器學習的過程當中的數據變化。不過這裏只專一於繪製,機器學習的部分參考從 TensorFlow 入門機器學習
一樣仍是拿線性迴歸做爲例子。
原始代碼
# coding: utf-8
from __future__ import print_function
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from scipy.interpolate import spline
train_X = np.linspace(0, 10, 50)
noise = np.random.normal(0, 1, train_X.shape)
train_Y = train_X * 1 - 2 + noise
X = tf.placeholder(tf.float32)
Y = tf.placeholder(tf.float32)
W = tf.Variable(-1., name="weight")
b = tf.Variable(1., name="bias")
activation = tf.add(tf.multiply(X, W), b)
learning_rate = 0.0001
cost = tf.reduce_sum(tf.pow(activation - Y, 2))
optimizer = tf.train.GradientDescentOptimizer(learning_rate).minimize(cost)
training_epochs = 20
display_step = 10
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
for epoch in range(training_epochs):
for (x, y) in zip(train_X, train_Y):
sess.run(optimizer, feed_dict={X: x, Y: y})
if epoch < 10 or epoch % display_step == 0:
c_tmp = sess.run(cost, feed_dict={X: train_X, Y: train_Y})
W_tmp = sess.run(W)
b_tmp = sess.run(b)
activation_tmp = sess.run(activation, feed_dict={X: train_X})
print("Epoch: %04d" % (epoch + 1), "cost=", "{:.9f}".format(c_tmp), "W=", W_tmp, "b=", b_tmp)
print("Optimization Finished!")
print("cost=", sess.run(cost, feed_dict={X: train_X, Y: train_Y}), "W=", sess.run(W), "b=", sess.run(b))
複製代碼
上面的代碼就不解釋了,爲了方便測試,把迭代次數調的比較小。接下來咱們在上面的基礎上進行擴充。
首先進行可視化,首先把咱們以爲有用的數據提取出來吧。由於通過測試,前面的變化幅度比較大,爲了圖示明顯,刻意進行非均勻採樣。
c_trace = []
W_trace = []
b_trace = []
activation_trace = []
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
for epoch in range(training_epochs):
for (x, y) in zip(train_X, train_Y):
sess.run(optimizer, feed_dict={X: x, Y: y})
if epoch < 10 or epoch % display_step == 0:
c_tmp = sess.run(cost, feed_dict={X: train_X, Y: train_Y})
W_tmp = sess.run(W)
b_tmp = sess.run(b)
activation_tmp = sess.run(activation, feed_dict={X: train_X})
print("Epoch: %04d" % (epoch + 1), "cost=", "{:.9f}".format(c_tmp), "W=", W_tmp, "b=", b_tmp)
c_trace.append(c_tmp)
W_trace.append(W_tmp)
b_trace.append(b_tmp)
activation_trace.append(activation_tmp)
print("Optimization Finished!")
print("cost=", sess.run(cost, feed_dict={X: train_X, Y: train_Y}), "W=", sess.run(W), "b=", sess.run(b))
複製代碼
參考前面的小例子,把數據填進去,作出動圖來。
fig, ax = plt.subplots()
l1 = ax.scatter(train_X, train_Y, color='red', label=r'$Original\ data$')
ax.set_xlabel(r'$X\ data$')
ax.set_ylabel(r'$Y\ data$')
def update(i):
try:
ax.lines.pop(0)
except Exception:
pass
line, = ax.plot(train_X, activation_trace[i], 'g--', label=r'$Fitting\ line$', lw=2)
return line,
ani = animation.FuncAnimation(fig, update, frames=len(activation_trace), interval=100)
ani.save('linearregression.gif', writer='imagemagick')
plt.show()
複製代碼
效果以下圖所示:
接着把 函數也加上來而且在最後顯示。
def update(i):
try:
ax.lines.pop(0)
except Exception:
pass
line, = ax.plot(train_X, activation_trace[i], 'g--', label=r'$Fitting\ line$', lw=2)
if i == len(activation_trace) - 1:
twinax = ax.twinx()
twinax.plot(np.linspace(0, 10, np.size(c_trace)), c_trace, 'b', label='Cost line', lw=2)
return line,
複製代碼
能夠看到,線條十分鋒利,這時就可使用 平滑過渡一下。
def update(i):
try:
ax.lines.pop(0)
except Exception:
pass
line, = ax.plot(train_X, activation_trace[i], 'g--', label=r'$Fitting\ line$', lw=2)
if i == len(activation_trace) - 1:
xnew = np.linspace(0, 10, np.max(c_trace) - np.min(c_trace))
smooth = spline(np.linspace(0, 10, np.size(c_trace)), c_trace, xnew)
twinax = ax.twinx()
twinax.set_ylabel(r'Cost')
twinax.plot(xnew, smooth, 'b', label=r'$Cost\ line$', lw=2)
return line,
複製代碼
其實就是對 這個區間進行採樣。添加 np.max(c_trace) - np.min(c_trace)
個點來繪製這線條。
加上圖例。
def update(i):
try:
ax.lines.pop(0)
except Exception:
pass
line, = ax.plot(train_X, activation_trace[i], 'g--', label=r'$Fitting\ line$', lw=2)
plt.legend(handles=[l1, line], loc='upper center')
if i == len(activation_trace) - 1:
ax.text(6, -2, 'Cost: %s' % c_trace[i], fontdict={'size': 16, 'color': 'r'})
xnew = np.linspace(0, 10, np.max(c_trace) - np.min(c_trace))
smooth = spline(np.linspace(0, 10, np.size(c_trace)), c_trace, xnew)
twinax = ax.twinx()
twinax.set_ylabel(r'Cost')
costline, = twinax.plot(xnew, smooth, 'b', label=r'$Cost\ line$', lw=2)
plt.legend(handles=[l1, line, costline], loc='upper center')
return line,
複製代碼
下面把數據細節處理下。
learning_rate = 0.001
training_epochs = 500
display_step = 40
複製代碼
能夠看到, 函數並不是嚴格遞減的,咱們採用的是梯度降低算法求最優,因此問題出在學習率,具體爲何也是一個機器學習中應該注意的問題。另外你們還能夠試試繼續把學習率調大看看會發生什麼有趣的事情?
咱們把學習率調整到 0.0001
將會獲得如下結果:
其實你觀察輸出可能並不怎麼符合原始函數。並且在不斷調整訓練參數的時候會發現擬合程度彷佛也無法每次後很好。緣由其實在於加的干擾,至於爲何干擾會形成這樣,就不在本文的討論範圍了。好了,到這裏你應該能夠繪製本身的 了吧。
源碼詳見 GitHub
花時間把小細節搞懂就是節省時間,其實眼前的問題能夠引伸出其它更多值得思考的問題。多聯繫,多思考。