Continuing from Last time [Introduction to mathematics starting from Python](https://www.amazon.co.jp/Python%E3%81%8B%E3% 82% 89% E3% 81% AF% E3% 81% 98% E3% 82% 81% E3% 82% 8B% E6% 95% B0% E5% AD% A6% E5% 85% A5% E9% 96% 80-Amit-Saha / dp / 4873117682) series. This time
Is involved.
In the explanation in the book, the result is plotted with matplotlib and output to an image (still image, of course), but I wanted to see how the gradient descent algorithm works with animation. So this time I tried to output it as a gif animation. The gradient descent method and gradient descent method are only included in the code and will not be explained.
First, find the minimum value of the function using gradient descent. Next, we will output an animation in gif format to visualize how the value decreases with each step.
This time
f(x) = 3x^2 + 2x
Find the minimum value of the quadratic function.
gradient_descent.py
from sympy import Derivative, Symbol, sympify, solve
from numpy import arange
import matplotlib.pyplot as plt
import matplotlib.animation as ani
def gradient_descent(x0, f1x, x, epsilon=1e-6, step_size=1e-4):
# f1x =Find out if it has a solution of 0.
if not solve(f1x):
return
x_old = x0
x_new = x_old - step_size * f1x.subs({x: x_old}).evalf()
X_traversed = []
while abs(x_old - x_new) > epsilon:
X_traversed.append(x_new)
x_old = x_new
x_new = x_old - step_size * f1x.subs({x: x_old}).evalf()
return x_new, X_traversed
def draw_graph(f, x):
X = arange(-1, 1, 0.01)
Y = [f.subs({x: x_val}) for x_val in X]
plt.plot(X, Y)
def draw_frame(i, x, X, Y):
plt.clf()
draw_graph(f, x)
plt.scatter(X[i], Y[i], s=20, alpha=0.8)
if __name__ == '__main__':
x = Symbol('x')
f = 3 * x ** 2 + 2 * x
var0 = 0.75 #Initial value of gradient descent
d = Derivative(f, x).doit()
# gradient_descent()Returns the minimum value obtained by gradient descent and the value of x at each step.
var_min, X_traversed = gradient_descent(var0, d, x)
print('Total number of steps: {0}'.format(len(X_traversed)))
print('minimum value(Gradient descent): {0}'.format(var_min))
print('minimum value(f1x =0 solution): {0}'.format(float(solve(d)[0])))
X = X_traversed[::100] # (1)
Y = [f.subs({x: x_val}) for x_val in X]
fig = plt.figure(figsize=(6.5, 6.5))
anim = ani.FuncAnimation(fig, draw_frame, fargs=(x, X, Y), frames=len(X)) # (2)
anim.save('gradient_descent.gif', writer='imagemagick', fps=10) # (3)
Total number of steps: 10792
minimum value(Gradient descent): -0.331667951428822
minimum value(f1x =0 solution): -0.3333333333333333
X = X_traversed[::100]
X_traversed
is an array that contains all the values of x
at each step of the steepest descent.
The total number of steps len (X_traversed)
is 10,792. If you draw a frame at 10fps, or 10 frames per second, it will take about 1,079 seconds to finish the animation. To reduce this to a few seconds of animation, we generate a new array x
that takes every 100 elements of the resulting array X_traversed
and use it to create the animation.
This method excludes the element stored at the end of X_traversed, that is, the value of x corresponding to the minimum value. However, I am compromising because I think it's okay if I can grasp the atmosphere with animation.
Call FuncAnimation () [matplotlib.animation.Animation](http://matplotlib.org/ api / _as_gen / matplotlib.animation.Animation.html # matplotlib.animation.Animation) Creating an object.
The arguments are as follows.
argument | Description |
---|---|
fig | The origin of the graphFigureobject. |
draw_frame | A function called for each frame. draw_The frame number is automatically passed to the first argument of frame. |
fargs | draw_The value passed after the second argument of frame. |
frames | The number of frames in the animation. |
Call Animation.save () and actually save the animation.
By specifying ʻimagemagick for the argument
writer`, we were able to output a gif animation. However, it is assumed that ImageMagick is installed on your machine. I'm using macOS, but I didn't have ImageMagick installed, so I installed it with Homebrew.
$ brew install imagemagick
No other settings were made.
** This guy ... works! ** **
It's a lot of fun to visualize how the algorithm works like this: blush :: hearts:
If you want to see the stronger and stronger ones, I recommend the article Explanation of what is stochastic gradient descent in Python. Do: + 1: It is upward compatible. I was also strongly motivated to output such an animation. Thank you: pray :: sparkles:
Recommended Posts