In order to visualize the machine learning process and preserve it, I wanted to use it directlyDuring the preservation of the GIF, I referred to a lot of materials, the process is quite difficult, so I want to record it. Of course, this article also references many other articles on the web, and thanks to those who love to shareAnd a link is provided in Resources. All code sorted intoGitHub.
Effect first!
0. Prepare
The installation 和 . Specific installation can be directly on the official website, what problems can be found on the Internet the answer, here is not introduced. It’s going to be easy to useGenerate some test data if yesUnfamiliar, referenceOfficial NumPy Quickstart tutorial, if theUnfamiliar, referenceMatplotlib Basic operation. Of course if you want to be able to saveWe need another toolImageMagick, just follow the official instructions to install, be sure to enter in the commandmagick
Have a response. If you are usingSuch asPlease configure environment variables globally to avoid inCommand could not be found in.
1. Draw basic GIFs
Make sure you have ImageMagick installed and available before continuing, otherwise the code will run.
There are two ways to draw giFs
1.1 Reset and redraw
Reset redraw is basically to update the value of the original graph each time to achieve the effect of drawing a GIF.
- Import base library
import numpy as np
from matplotlib import pyplot as plt
from matplotlib import animation
Copy the code
- Generate the data, draw the original graph
Plot (x, np.cos(x)) line, = ax.plot(x, np.sin(x)), and plots(x, np.plots () x = np.arange(0, 2 * np.pi, 0.01) line = ax.plot(x, np.cos(x)) line, = ax.plot(x, np.sin(x))Copy the code
Notice, it’s declared here 中 .
No less, as if to match the type when updating the value. Did not investigate deeply, hope to know can give directions.
- Define initial and new functions
def init():
line.set_ydata(np.sin(x))
returnLine, def animate(I): animate(np.sin(x + I / 10.0))return line,
Copy the code
It’s just an updateThe value of the coordinates.
- Perform the animation
animation = animation.FuncAnimation(fig=fig, func=animate, frames=100, init_func=init, interval=20, blit=False)
Copy the code
The parameters of this function can be seen in the source code, as well as the official website introduction, here is eachI’m going to draw one frameThe frame.
- save
animation.save('resetvalue.gif', writer='imagemagick')
Copy the code
So I’m just going to save it asThe format is fine.
- According to dynamic figure
plt.show()
Copy the code
The resulting image looks like the following:
1.2 Erase and redraw
Compared to the previous method, this method does not use any coordinates last time, just erase, and thenGraph up.
- Import base library
import numpy as np
from matplotlib import pyplot as plt
from matplotlib import animation
Copy the code
- Generate the data, draw the original graph
Arange (0, 2 * np.pi, 0.01) ax.plot(x, np.cos(x)).Copy the code
I don’t have that requirement here, because it doesn’t depend on the previous graph.
- Define initial and new functions
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,
Copy the code
Initialization is nothing to say, in fact, you can not initialize, too short time interval is basically invisible. Let me introduce youax.lines.pop(1)
This “erase” function. Here,You can think of it as storageImage stack up, frontI have a cosine, and I draw the second one when I initialize it, so the index isThe sine function of omega is omegaAnd then I’m going to draw the next one. Then performLine = ax.plot(x, np.sin(x + I / 10.0), 'r') line = ax.plot(x, np.sin(x + I / 10.0), 'r')
- subsequent
animation = animation.FuncAnimation(fig=fig, func=animate, frames=100, init_func=init, interval=20, blit=False)
animation.save('redraw.gif', writer='imagemagick')
plt.show()
Copy the code
No difference between
The resulting image looks like the following:
2. Visualization of machine learning process
This is basically enough, but it’s not practical. If you’re not a machine learning person, and you have the basics, you can skip this section. However, if you want to learn machine learning, here’s a small example to help you understand more clearly what happens to the data during machine learning. However, this is only focused on drawing, and part of the machine learning reference is from TensorFlow for introduction to machine learning
Again, let’s take linear regression.
The original code
# 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))
Copy the code
The above code will not be explained, but the number of iterations is kept small for testing purposes. Let’s expand on the above.
Let’s first visualize, first extract the data that we find useful. Because of the test, the range of changes in the front is relatively large, so non-uniform sampling is deliberately carried out in order to make the diagram obvious.
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))
Copy the code
Refer to the previous small example, fill in the data, do the move diagram.
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()
Copy the code
The effect is shown below:
Then put theThe function is also added and displayed at the end.
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,
Copy the code
As you can see, the lines are very sharp, and then you can use themLet’s make a smooth transition.
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,
Copy the code
In fact, yes.I’m going to sample this interval. addnp.max(c_trace) - np.min(c_trace)
Point to draw this line.
Add legend.
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,
Copy the code
Let’s deal with the details of the data.
Learning_rate = 0.001 training_EPOchs = 500 display_step = 40Copy the code
As you can see,Function is not strictly decreasing, we use gradient descent algorithm for optimization, so the problem lies in the learning rate, the specific reason is also a problem that should be paid attention to in machine learning. Another thing you can do is try to increase the learning rate and see what’s interesting about it?
If we adjust the learning rate to 0.0001, we will get the following results:
In fact, if you look at the output, it might not quite fit the original function. And when you constantly adjust the training parameters, you will find that the degree of fitting does not seem to be very good every time. In fact, the reason lies in the addition of interference, as to why interference causes this, is beyond the scope of this article. Okay, so at this point you should be able to draw your own.
See GitHub for the source code
3. Summary
Taking the time to understand the small details can save you time, when the question at hand can lead to other questions worth thinking about. Connect and think.
4. Reference materials
- Morvan: Markdown + video
- The official documentation
- Matplotlib tutorial
- Matplotlib tutorial
- How to draw GIFs with Matplotlib