Вернуться на страницу brain2net: https://brain2net.ru/post/pytorch-primer-linejnoj-regressii/#more-202
import torch
import torch.nn as nn
import matplotlib.pyplot as plt
%matplotlib inline
Для формирования нейронной сети на PyTorch целесообразно подготовить специальный класс, определяющий конкретный тип модели на основе родительского класса nn.Module.
В этом классе формируются два метода. Метод init , который с помощью модуля torch.nn описывает все требуемые слои нейронной сети. Метод forward задает последовательность следования слоев и соединяет выходы и входы соседних слоев.
# Standard model class
class LinearModel(nn.Module):
def __init__(self, in_dim, out_dim):
# nn.Module является базовым классом и вызывается через функцию super() при инициализации.
super(LinearModel, self).__init__()
self.linear = nn.Linear(in_dim, out_dim)
def forward(self, x):
out = self.linear(x)
return out
Формируется модель, экземпляр созданного класса - в данном случае для линейной регрессии. При инициализации класса задаются размерность входа и выхода модели.
model = LinearModel(1, 1)
До начала процесса поиска коэффициентов линейной регрессии надо задать коэффициент скорости обучения, выбрать метод оптимизации и критерий оценки потерь.
# Коэффициент скорости обучения. При большом значении результат будет "скакать". При малом - длительное время оптимизации.
learnRate = 0.01
# Выбор оптимизатора. Выбирается стохастический градиентный спуск.
optimiser = torch.optim.SGD(model.parameters(), lr =learnRate)
# Выбор критерия оценки потерь. Выбирается среднеквадратичная ошибка.
criterion = nn.MSELoss()
Для примера необходимо задать точки на плоскости и описать их прямой, полученной в результате линейной регрессии.
# Случайные 9 чисел на отрезке от 0 до 10
x_train = 10 * torch.rand([12,1])
x_train
# Случайный шум
noise = 1.2 * torch.rand([12,1])
noise
# Линейная функция от x_train с добавлением "шума"
# Для получения матрицы [12, 1] добавляется .reshape(-1,1). Без этого будет матрица [1, 12]
y_train = torch.tensor([2*x+9 for x in x_train]).reshape(-1,1)
y_train += noise
y_train
Проводится цикл поиска коэффициентов линейной регрессии, при котором минимизируется функция потерь
# Количество циклов - эпох
# Для примера принято 50, но реально для сходимости процесса это очень мало. Надо брать больше.
epochs = 30
for epoch in range(epochs):
epoch += 1
inputs = x_train
labels = y_train
out = model(inputs)
# Важно отметить, что нам нужно очистить градиенты, чтобы они не накапливались в течение эпох и
# не искажали модель. Это достигается путем вызова функции zero_grade() в
# оптимизаторе для каждой эпохи.
optimiser.zero_grad()
# Вычисление функции потеть - среднеквадратичного отклонения
loss = criterion(out, labels)
# Вычисление градиента
loss.backward()
# Очередной шаг стохастического градиентного спуска
optimiser.step()
predicted = model.forward(x_train)
print('epoch {}, loss {}'.format(epoch, loss.item()))
# Коэффициенты линейной регрессии, полученные в результате стохастического градиентного спуска
coef = model.state_dict()
# Результат близкий к начальной линейной функции, использованной для формирования обучающей выборки
coef
Предсказание точек методом линейной регрессии.
y_predict = predicted
y_predict
Графическое изображение результата.
NB Совпадение полученной линии с исходными точками плохое из-за малого количества эпох, которое было взято для примера.
Для построения графика torch.tensor преобразуются в numpy.array.
С torch.tensor предварительно проводится процедура .detach(). tensor.detach() создает тензор для которого не требуется градиент. Он отделяет выходные данные от вычислительного графика. Таким образом, никакой градиент не будет распространяться обратно вдоль этой переменной.
x = x_train.detach().numpy()
plt.plot(x, y_predict.detach().numpy(), label = 'predicted')
plt.plot(x, y_train.detach().numpy(),'mo', label = 'from data')
plt.legend()
plt.grid()
plt.show()
Вернуться на страницу brain2net: https://brain2net.ru/post/pytorch-primer-linejnoj-regressii/#more-202