Шаг за шагом научим вас сохранять GIF-анимацию с помощью Matplotlib

машинное обучение NumPy
Шаг за шагом научим вас сохранять GIF-анимацию с помощью Matplotlib

Написано впереди: Чтобы визуализировать процесс машинного обучения и сохранить его, я хочу использовать его напрямую.Matplotlib.animationЧтобы сохранить движущуюся картину, я ссылался на множество материалов в тот период, процесс был достаточно сложным, поэтому я захотел его записать. Конечно, эта статья также относится ко многим другим статьям в Интернете, и спасибо тем, кто любит делитьсяcoder, а ссылки даны в References. Весь код организован вGitHub.

Получите эффект первым!

0. Предварительная подготовка

УстановитьNumPyиMatplotlib. Конкретная установка может быть прямо на официальном сайте, Если у вас возникнут какие-либо проблемы, вы можете в основном найти ответ в Интернете, поэтому я не буду его здесь представлять. Здесь просто использоватьNumPyСгенерируйте некоторые тестовые данные, если они правыNumPyнезнакомый, ссылкаОфициальное руководство по началу работы с NumPy (перевод), если правильноMatplotlibнезнакомый, ссылкаОсновные операции Matplotlib. Конечно, если вы хотите сэкономитьGIFеще один инструментImageMagick, просто следуйте официальным инструкциям по установке, обязательно введите командуmagickЕсть ответ. При использованииPyCharmкакой-то типIDEПожалуйста, настройте переменные среды глобально, чтобы избежатьIDEкоманда не найдена в .

1. Нарисуйте базовую анимацию

Убедитесь, что вы установилиImageMagickИ продолжить, если доступно, иначе код будет работать.

Есть два способа рисовать анимацию

1.1 Сброс и перерисовка

Сброс и перерисовка в основном предназначены для обновления значения исходной графики каждый раз для достижения эффекта анимации рисования.

  • импортировать базовую библиотеку
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))

Обратите внимание, что заявление здесьline,середина,Не меньше, как бы для соответствия типу при обновлении значения. Я не знаю, я надеюсь, что вы можете дать некоторые указатели.

  • Определите начальную функцию и функцию обновления
def init():
    line.set_ydata(np.sin(x))
    return line,

def animate(i):
    line.set_ydata(np.sin(x + i / 10.0))
    return line,

На самом деле просто обновитьYЗначение координат.

  • выполнить анимацию
animation = animation.FuncAnimation(fig=fig, func=animate, frames=100, init_func=init, interval=20, blit=False)

Параметры этой функции можно увидеть в исходном коде и во введении на официальном сайте.20\ msнарисовать рамку, всего100Рамка.

  • спастиGIF
animation.save('resetvalue.gif', writer='imagemagick')

Вот прямое сохранение какGIFФормат просто отличный.

  • Показать гифку
plt.show()

Эффект сгенерированного изображения показан на рисунке:

1.2 Стереть и перерисовать

По сравнению с предыдущим методом этот метод заключается в прямом стирании без использования каких-либо координат предыдущего времени, а затемplotГрафика вверх.

  • импортировать базовую библиотеку
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)Функция фразы «стереть». здесьlinesможно понимать как хранениеplotСтопка изображений вверху, спередиplotРисуется функция косинуса, а вторая линия рисуется во время инициализации, поэтому индекс1Функция синусаpopи затем приступайте к следующему рисунку. Так выполнить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()

нет разницы

Эффект сгенерированного изображения показан на рисунке:

2. Визуализация процесса машинного обучения

Приведенных выше знаний в принципе достаточно, но они все-таки не практичны. Если вы не изучаете машинное обучение, у вас действительно может быть вышеуказанная основа, и этот раздел можно пропустить. Однако, если вы хотите научиться машинному обучению, вот небольшой пример, который даст вам более четкое представление об изменениях данных в процессе машинного обучения. Но здесь сосредоточено только на рисовании, часть справочника по машинному обучению.Начало работы с машинным обучением с 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()

Результаты, как показано ниже:

тогда поставьCostФункция также добавляется и отображается в конце.

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,

Видно, что линии очень четкие, и вы можете использовать это в это время.splineПлавный переход.

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,

На самом деле это правильно[0, 10]выборка в этом интервале. Добавить к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

можно увидеть,CostФункция не является строго убывающей, Мы используем алгоритм градиентного спуска, чтобы найти оптимум, поэтому проблема заключается в скорости обучения, и почему это также проблема, на которую следует обратить внимание в машинном обучении. Кроме того, вы можете попробовать продолжать увеличивать скорость обучения, чтобы увидеть, что интересного будет происходить?

Мы корректируем скорость обучения, чтобы0.0001Будут получены следующие результаты:

На самом деле результат, который вы видите, может не совсем совпадать с исходной функцией. И когда вы постоянно настраиваете параметры тренировки, вы обнаружите, что степень соответствия не каждый раз кажется очень хорошей. Причина на самом деле дополнительные помехи Что касается того, почему помехи вызывают это, это выходит за рамки этой статьи. Ну, на этом этапе вы должны быть в состоянии нарисовать свой собственныйGIFНу давай же.

Подробности смотрите в исходном кодеGitHub

3. Резюме

Если вы потратите время на то, чтобы разобраться в мелких деталях, это сэкономит время, ведь проблема может привести к другим проблемам, о которых стоит подумать. Подключайтесь больше, думайте больше.

4. Ссылки