Рубрики
Без рубрики

Pytorch Hello World

Сравните результаты Pytorch с ручным расчетом обратной задачи. Помечено с Python, Pytorch, NeuralnetWorks, MachineLearning.

Я недавно начал работать с Pytorch , Python Framework для нейронных сетей и машинного обучения. Поскольку машинное обучение включает в себя обработку большого количества данных, иногда может быть трудно понять результаты, которые получают от сети. Прежде чем попасть во что-то сложное, давайте повторим действительно базовую обратную обработку в качестве достоверности чека. Чтобы запустить код в этой статье, вам нужно установить Numpy и Pytorch Отказ

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

Мы провели вход 0,8 Через сеть, затем обратно использовать использование 1 Как целевое значение, с темпом обучения 0,1 Отказ Мы использовали Sigmoid в качестве функции активации и функцию квадратичной стоимости для сравнения фактической вывода из сети с желаемым выходом.

Ниже приведен код Pytorch, чтобы сделать то же самое:

import torch
import torch.nn as nn
import torch.optim as optim


class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.hidden_layer = nn.Linear(1, 1)
        self.hidden_layer.weight = torch.nn.Parameter(torch.tensor([[1.58]]))
        self.hidden_layer.bias = torch.nn.Parameter(torch.tensor([-0.14]))

        self.output_layer = nn.Linear(1, 1)
        self.output_layer.weight = torch.nn.Parameter(torch.tensor([[2.45]]))
        self.output_layer.bias = torch.nn.Parameter(torch.tensor([-0.11]))

    def forward(self, x):
        x = torch.sigmoid(self.hidden_layer(x))
        x = torch.sigmoid(self.output_layer(x))
        return x


net = Net()
print(f"network topology: {net}")

print(f"w_l1 = {round(net.hidden_layer.weight.item(), 4)}")
print(f"b_l1 = {round(net.hidden_layer.bias.item(), 4)}")
print(f"w_l2 = {round(net.output_layer.weight.item(), 4)}")
print(f"b_l2 = {round(net.output_layer.bias.item(), 4)}")

# run input data forward through network
input_data = torch.tensor([0.8])
output = net(input_data)
print(f"a_l2 = {round(output.item(), 4)}")

# backpropagate gradient
target = torch.tensor([1.])
criterion = nn.MSELoss()
loss = criterion(output, target)
net.zero_grad()
loss.backward()

# update weights and biases
optimizer = optim.SGD(net.parameters(), lr=0.1)
optimizer.step()

print(f"updated_w_l1 = {round(net.hidden_layer.weight.item(), 4)}")
print(f"updated_b_l1 = {round(net.hidden_layer.bias.item(), 4)}")
print(f"updated_w_l2 = {round(net.output_layer.weight.item(), 4)}")
print(f"updated_b_l2 = {round(net.output_layer.bias.item(), 4)}")

output = net(input_data)
print(f"updated_a_l2 = {round(output.item(), 4)}")

Некоторые заметки по этому коду:

  • посадка Линейный используется для полностью подключенных или плотных, слоев. Для этого простого случая у нас есть один вход и один вывод для каждого слоя.
  • вперед Способ вызывается, когда мы передаем ввод в сеть с помощью Выход (input_data) Отказ
  • По умолчанию Pytorch устанавливает случайные веса и предубеждения. Однако здесь мы инициализируем их напрямую, поскольку мы хотим, чтобы результаты соответствовали нашему ручному расчету (позже в статье).
  • В питорче, тензор аналогичен Массив в Numpy.
  • критерий. MSELOSS () Настраивает функцию квадратичной стоимости – хотя она называется функцией потери ошибок в квадрате в Pyyorch.
  • потеря (вывод, цель) рассчитывает стоимость, также известную как потери.
  • Далее мы используем net.zero_grad () Для сброса градиента до нуля (в противном случае обратная обработка кумулятивна). Здесь не нужно строго, но приятно держать это в виду при запуске обратной обработки в цикле.
  • потеря. Backward () Вычисляет градиент, то есть производная стоимости в отношении всех весов и предубеждений.
  • Наконец мы используем этот градиент для обновления весов и предубеждений в сети, используя SGD (Стохастический градиентный спуск) Оптимизатор, с учебной скоростью 0,1 Отказ

Результаты ниже:

C:\Dev\python\pytorch>python backprop_pytorch.py
network topology: Net(
  (hidden_layer): Linear(in_features=1, out_features=1, bias=True)
  (output_layer): Linear(in_features=1, out_features=1, bias=True)
)
w_l1 = 1.58
b_l1 = -0.14
w_l2 = 2.45
b_l2 = -0.11
a_l2 = 0.8506
updated_w_l1 = 1.5814
updated_b_l1 = -0.1383
updated_w_l2 = 2.4529
updated_b_l2 = -0.1062
updated_a_l2 = 0.8515

Мы распечатаем топологию сети, а также веса, смещения и вывод, как до, так и после шага обратной задачи.

Ниже давайте повторим этот расчет простым питоном. Этот расчет почти такой же, как тот, который мы видели в грунтовке нейронных сетей. Единственное отличие состоит в том, что Pytorch’s MSELOSS Функция не имеет дополнительного подразделения на 2, поэтому в код ниже я настроил dc_da_l2 * (a_l2-1) Чтобы соответствовать тому, что делает Pytorch:

import numpy as np


def sigmoid(z_value):
    return 1.0/(1.0+np.exp(-z_value))


def z(w, a, b):
    return w * a + b


def sigmoid_prime(z_value):
    return sigmoid(z_value)*(1-sigmoid(z_value))


def dc_db(z_value, dc_da):
    return sigmoid_prime(z_value) * dc_da


def dc_dw(a_prev, dc_db_value):
    return a_prev * dc_db_value


def dc_da_prev(w, dc_db_value):
    return w * dc_db_value


a_l0 = 0.8
w_l1 = 1.58
b_l1 = -0.14
print(f"w_l1 = {round(w_l1, 4)}")
print(f"b_l1 = {round(b_l1, 4)}")

z_l1 = z(w_l1, a_l0, b_l1)
a_l1 = sigmoid(z_l1)

w_l2 = 2.45
b_l2 = -0.11
print(f"w_l2 = {round(w_l2, 4)}")
print(f"b_l2 = {round(b_l2, 4)}")

z_l2 = z(w_l2, a_l1, b_l2)
a_l2 = sigmoid(z_l2)
print(f"a_l2 = {round(a_l2, 4)}")

dc_da_l2 = 2 * (a_l2-1)
dc_db_l2 = dc_db(z_l2, dc_da_l2)
dc_dw_l2 = dc_dw(a_l1, dc_db_l2)
dc_da_l1 = dc_da_prev(w_l2, dc_db_l2)

step_size = 0.1
updated_b_l2 = b_l2 - dc_db_l2 * step_size
updated_w_l2 = w_l2 - dc_dw_l2 * step_size

dc_db_l1 = dc_db(z_l1, dc_da_l1)
dc_dw_l1 = dc_dw(a_l0, dc_db_l1)

updated_b_l1 = b_l1 - dc_db_l1 * step_size
updated_w_l1 = w_l1 - dc_dw_l1 * step_size

print(f"updated_w_l1 = {round(updated_w_l1, 4)}")
print(f"updated_b_l1 = {round(updated_b_l1, 4)}")

print(f"updated_w_l2 = {round(updated_w_l2, 4)}")
print(f"updated_b_l2 = {round(updated_b_l2, 4)}")

updated_z_l1 = z(updated_w_l1, a_l0, updated_b_l1)
updated_a_l1 = sigmoid(updated_z_l1)
updated_z_l2 = z(updated_w_l2, updated_a_l1, updated_b_l2)
updated_a_l2 = sigmoid(updated_z_l2)
print(f"updated_a_l2 = {round(updated_a_l2, 4)}")

Вот результаты:

C:\Dev\python\pytorch>python backprop_manual_calculation.py
w_l1 = 1.58
b_l1 = -0.14
w_l2 = 2.45
b_l2 = -0.11
a_l2 = 0.8506
updated_w_l1 = 1.5814
updated_b_l1 = -0.1383
updated_w_l2 = 2.4529
updated_b_l2 = -0.1062
updated_a_l2 = 0.8515

Мы видим, что результаты совпадают с теми из сети Pytorch! В следующей статье мы будем использовать Pytorch для распознавания цифр из базы данных Mnist.

Код доступен на GitHub:

NestedSoftware/pytorch.

Демонстрации базового использования Pytorch. Включает распознавание Mnist, используя плотные, а также сверточные сети.

Этот проект содержит скрипты для демонстрации базового использования Pytorch. Код требует Python 3, Numpy и Pytorch.

Руководство по сравнению с Pyyorch CallProp

Для сравнения ручного расчета Backprop с эквивалентной версией Pytorch, запустите:

python backprop_manual_calculation.py
w_l1 = 1.58
b_l1 = -0.14
w_l2 = 2.45
b_l2 = -0.11
a_l2 = 0.8506
updated_w_l1 = 1.5814
updated_b_l1 = -0.1383
updated_w_l2 = 2.4529
updated_b_l2 = -0.1062
updated_a_l2 = 0.8515

и

python backprop_pytorch.py
network topology: Net(
  (hidden_layer): Linear(in_features=1, out_features=1, bias=True)
  (output_layer): Linear(in_features=1, out_features=1, bias=True)
)
w_l1 = 1.58
b_l1 = -0.14
w_l2 = 2.45
b_l2 = -0.11
a_l2 = 0.8506
updated_w_l1 = 1.5814
updated_b_l1 = -0.1383
updated_w_l2 = 2.4529
updated_b_l2 = -0.1062
updated_a_l2 = 0.8515

Blog Post: Pytorch Hello World

Мнист признание

Следующие примеры распознают цифры Mnist, используя плотную сеть сначала, а затем несколько конструкций ключевых сетей (примеры адаптированы из книги Михаила Нильсена, нейронные сети и глубокому обучению).

Я добавил…

Связанный

  • Грунтовка нейронных сетей

Оригинал: “https://dev.to/nestedsoftware/pytorch-hello-world-37mo”