Относительно недавно заинтересовался нейросетями и стал изучать python. Одной из первых библиотек, которой заинтересовался была matplotlib. Достаточная занимательная библиотека для построения научных графиков в Python. Она включает в себя функции для создания высококачественных визуализаций типа линейных диаграмм, гистограмм, диаграмм разброса и прочих. Такие графики крайне полезны для понимания процесса, вывода аналитики и прочих задач.

Вероятно многие подумают причем же здесь нейросети? Ответ достаточно прост, чтобы понять как обучилась нейросеть или почему она скажем не обучилась можно вывести графическое отображение метрик сети и понять, как от эпохи к эпохи эти метрики менялись, что, вероятно, поможет в понимании процесса обучения. 

Версии библиотек

В данной статье использовался python 3.10, numpy версии 1.26.4 и matplotlib версии 3.10.7. Установить можно просто через pip. Однако ничего принципиально нового в статье показано не будет, так что и в близких к этим версиям работать должно.

Двумерные графики и кастомизация отображения

Итак, не будем тянуть нейросеть за слой и начнем с чего-нибудь попроще:

import matplotlib.pyplot as plt
import numpy as np

x = np.arange(-5, 5, 0.1)
plt.plot(x, x*x)
plt.show()

первые две строчки импортят библиотеки numpy для работы с массивами и matplotlib собственно для построения графиков, np.arange генерирует массив от -5 до 5 с шагом 0.1, plt.plot выводит график, а plt.show() открывает все фигуры. Дело в том, что когда вы пишите plt.plot на самом деле график будет выводится фигуру, которую за кулисами создается matplotlib. 

Вывод графика можно настраивать, добавляя сетку для этого достаточно добавить вызов функции plt.grid(). Если необходимо изменить тип линии, то это делается в функции plot. Можно выводить маркеры в местах точек, выводить только точки или соединять различными методами, задавать цвет, тип и толщину линии и многое другое. Есть возможность настраивать фигуру, оси, легенду, задавать диапазоны и выводить несколько графиков в одной фигуре. Что есть что можно понять по этой схеме: 

Так, например, такой код отображает несколько графиков в одной фигуре:

import matplotlib.pyplot as plt
import numpy as np

x = np.arange(-5, 5, 0.1)
plt.figure('Несколько графиков')
plt.plot(x, x*x, ':*', color='#0000CC')
plt.plot(x, 2*x + 8, '.', color='#FF00CC')
plt.xlim(-7, 7)
plt.ylim(-4, 30)
plt.grid()
plt.show()

функции plot в этом примере не только выводят графики, но и настраивают маркировки и задают цвет графиков, здесь стоит заметить, что первый вариант не только задает маркеры для точек, но и соединяет их, в то время, как второй задает только маркерные точки. plt.xlim задает диапазон от минимального до максимального значения абсциссы. По аналогии работает и plt.ylim. В результате получаем такой вывод.

Внизу видим кнопки из фигуры, которые позволяют масштабировать, сохранять, настраивать отступы, двигать и прочее. 

Данный пример показывает многообразие возможных настроек вывода графиков:

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 2 * np.pi, 100)
plt.figure('Несколько графиков',figsize=(10, 5))
plt.plot(x, np.sin(x), linewidth=2, color='g', dashes=[8, 4], label=r'$\sin x$')
plt.plot(x, np.cos(x), linewidth=2, color='r', dashes=[8, 4, 2, 4], label=r'$\cos x$')
plt.axis([0, 2 * np.pi, -1, 1])
plt.xticks(np.linspace(0, 2 * np.pi, 9), 
           ('0',r'$\frac{1}{4}\pi$',r'$\frac{1}{2}\pi$',  
            r'$\frac{3}{4}\pi$',r'$\pi$',r'$\frac{5}{4}\pi$',
            r'$\frac{3}{2}\pi$',r'$\frac{7}{4}\pi$',r'$2\pi$'),
           fontsize=20)
plt.yticks(fontsize=12)
plt.xlabel(r'$x$', fontsize=20)
plt.ylabel(r'$y$', fontsize=20)
plt.title(r'$\sin x$, $\cos x$', fontsize=20)
plt.legend(fontsize=20, loc=0)
plt.show()

np.linspace делает похожую на arange работу, только третий параметр указывает сколько точек нам необходимо из чего уже вычисляется шаг. Здесь также добавляется подпись осей (plt.xlabel), название графика (plt.title), легенда и даже подпись точек абсцисс (plt.xticks). В итоге получаем:

Трехмерные графики

Думаю, многие понимают, но всё же скажу, отображать графики можно не только двухмерные. Вот несложный пример отображения трехмерного графика:

import matplotlib.pyplot as plt
import numpy as np

fig = plt.figure()
ax = fig.add_subplot(projection='3d')

# Создаем сетку в полярных координатах и ​​вычислите соответствующее значение Z.
r = np.linspace(0, 1.25, 50)
p = np.linspace(0, 2*np.pi, 50)
R, P = np.meshgrid(r, p)
Z = ((R**2 - 1)**2)

# Переводим в декартовые координаты.
X, Y = R*np.cos(P), R*np.sin(P)

# Строим поверхность.
ax.plot_surface(X, Y, Z, cmap=plt.cm.YlGnBu_r)

# Поменяем пределы и добавляем математические метки Latex.
ax.set_zlim(0, 1)
ax.set_xlabel(r'$\phi_\mathrm{real}$')
ax.set_ylabel(r'$\phi_\mathrm{im}$')
ax.set_zlabel(r'$V(\phi)$')
plt.show()

в целом комментарии исчерпывающие, поясню что np.meshgrid создает координатную матрицу из координатного вектора, за счет множественного повторения (��апример r=np.array([1,2,3,4]), а p = np.array([11,22,33,44]), тогда R, P = np.meshgrid(r, p) в переменной R будем иметь матрицу [[1,2,3,4],[1,2,3,4],[1,2,3,4],[1,2,3,4]]), в свою очередь R**2 это возведение в квадрат. В начале добавляется проекция на 3d за счет вызова add_subplot, без него не будет поддержки plot_surface которая непосредственно строит поверхность, а аргумент cmap задает в какие оттенки он будет окрашен. В целом, все остальные функции упоминались выше, разве только их стало больше за счет координаты Z. Такой результат мы получаем:

Анимации

Помимо построения графиков matplotlib предоставляет возможность создавать анимации. Так скажем можно создать график, который постоянно поворачивается. Это можно сделать за счет матриц ��оворотов или за счет поворота координатного пространства или поворачивая наблюдателя вокруг координатного пространства. Так например,

from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt
 
fig = plt.figure()
ax = fig.add_subplot(111, projection ='3d')

# генерируем тестовые данные с delta = 0.1
X, Y, Z = axes3d.get_test_data(0.1)

ax.plot_wireframe(X, Y, Z, rstride = 5, cstride = 5)
fig.canvas.draw()
renderer = fig.canvas.renderer  
for angle in range(0, 900):
    ax.view_init(30, angle)
    ax.axis('off')
    ax.draw(renderer)
    plt.pause(.001)

функция plot_wireframe строит каркасную поверхность, rstride и cstride определяют величину шага элементов построения из массивов, view_init задает высоту и угол с которого смотрит наблюдатель на построенный график, axis(‘off’) отключает координатное пространство, а fig.canvas.draw, renderer и ax.draw нужны для перерисовки. Заметим, что в цикле угол постоянно меняется именно это создает эффект поворота:

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

Заключение

В заключении хочется сказать, что с использованием такой библиотеки как matplotlib границы возможностей в отрисовке графиков и работы с ними значительно расширяются. Библиотека постоянно развивается и предоставляет все новые возможности.