For that we can use the FuncAnimation class provided by matplotlib. I’ll quickly go over how animations are built using this library, but feel free to check out matplotlib’s documentation and examples as well. Before anything we need to import:
from matplotlib.animation import FuncAnimation
Now we can define a FuncAnimation object as:
anim = FuncAnimation(fig, animate, init_func=init_plot, fargs=(X, y,), frames=50, interval=200, blit=True)
This object takes a pyplot figure ‘fig’ then uses the ‘init_func’ to initialize the plot data which in our case will be a straight line, then it iteratively calls the ‘animate’ function which is passed as our second parameter to update the values of our straight line 50 times as indicted by the ‘frames’ parameter, maintaining a 200 millisecond ‘interval’ between each frame. ‘fargs’ is used when we want to pass parameters to the animate function.
Before we start animating we need to make an adjustment to our fit() function. Since we want to get the seperation line for each iteration we cannot call fit() in our animate() function, because we’ll basically be fitting our data with each frame (i.e each frame will have the optimized weights) instead we define a new function step_fit() where we only run the inner loop and leave our animate function to handle the outer loop:
Now that we have a step_fit() and a plot_data() functions we can start building our animation functions, namely the init_func() & animate().
Our initialization function is straightforward, we just need to set our line with empty x’s and y’s to be filled by the animate function. We will later define self.line once we have all our components complete but for now you can ignore the ‘undefined’ error:
Next we can define our animate function, in it we need to call step_fit(), then run plot_data() to get update our seperation line according to the weight update in that iteration.
The function takes 3 parameters, ‘i’ is passed by default by our FuncAnimation object and is the frame number. ‘X’ and ‘y’ are the features and labels for our training data, respectively, which will be passed to the step_fit() function to update the weights.
Now that we have all the components we can define one last function that integrates them all:
The weights are randomly initialized here, we can’t define the weight in our new step_fit() function because that will cause them to reset to a random value with each call of animate(). We also initialize our figure, setting all the required labels, defining the axis, plotting the training data, and defining our seperation line.
We use the parameter ‘fargs’ to tell our object that we need to pass these variables to our animate() function, that is our training data.
Note that when we pass a function as a parameter as with animate and init_plot we dont include the parentheses because we’re technically passing a pointer to that function and not actually calling it. Also we pass the n_iter value as the number of frames simply because each frame is an iteration.
Finally we use anim.save() to start the whole process and save the resulting plot animation as a gif file in the same python file directory.