Оригинальная ссылка:Tickets.WeChat.QQ.com/Yes/Q8 Тоже NX SDH6…
Вторая часть учебника Quick Start PyTorch, в котором описывается, как построить нейронную сеть. Предыдущая статья:
Содержание этой статьи:
3. Нейронные сети
в PyTorchtorch.nn
В частности, используется для реализации нейронных сетей. вnn.Module
Включая построение сетевого уровня и метод...forward(input)
, и возвращает вывод сетиoutptu
.
Ниже представлена классическая сеть LeNet для классификации персонажей.
Для нейронной сети стандартный процесс обучения выглядит так:
- Определить многослойную нейронную сеть
- Предварительная обработка набора данных и подготовка его к вводу в сеть
- Введите данные в сеть
- Рассчитать потери в сети
- Обратное распространение, вычисление градиентов
- Чтобы обновить градиент сети, простое правило обновления
weight = weight - learning_rate * gradient
3.1 Определение сети
Сначала определите нейронную сеть, ниже представлена 5-слойная сверточная нейронная сеть, включающая два сверточных слоя и три полносвязных слоя:
import torch
import torch.nn as nn
import torch.nn.functional as F
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
# 输入图像是单通道,conv1 kenrnel size=5*5,输出通道 6
self.conv1 = nn.Conv2d(1, 6, 5)
# conv2 kernel size=5*5, 输出通道 16
self.conv2 = nn.Conv2d(6, 16, 5)
# 全连接层
self.fc1 = nn.Linear(16*5*5, 120)
self.fc2 = nn.Linear(120, 84)
self.fc3 = nn.Linear(84, 10)
def forward(self, x):
# max-pooling 采用一个 (2,2) 的滑动窗口
x = F.max_pool2d(F.relu(self.conv1(x)), (2, 2))
# 核(kernel)大小是方形的话,可仅定义一个数字,如 (2,2) 用 2 即可
x = F.max_pool2d(F.relu(self.conv2(x)), 2)
x = x.view(-1, self.num_flat_features(x))
x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
x = self.fc3(x)
return x
def num_flat_features(self, x):
# 除了 batch 维度外的所有维度
size = x.size()[1:]
num_features = 1
for s in size:
num_features *= s
return num_features
net = Net()
print(net)
Распечатайте структуру сети:
Net(
(conv1): Conv2d(1, 6, kernel_size=(5, 5), stride=(1, 1))
(conv2): Conv2d(6, 16, kernel_size=(5, 5), stride=(1, 1))
(fc1): Linear(in_features=400, out_features=120, bias=True)
(fc2): Linear(in_features=120, out_features=84, bias=True)
(fc3): Linear(in_features=84, out_features=10, bias=True)
)
должно быть реализовано здесьforward
функция, в то время какbackward
функция используетautograd
автоматически определяется, когдаforward
Метод может принимать любую тензорную операцию.
net.parameters()
Параметры обучения сети могут быть возвращены.Примеры использования следующие:
params = list(net.parameters())
print('参数数量: ', len(params))
# conv1.weight
print('第一个参数大小: ', params[0].size())
вывод:
参数数量: 10
第一个参数大小: torch.Size([6, 1, 5, 5])
Затем просто протестируйте сеть и случайным образом сгенерируйте ввод 32*32:
# 随机定义一个变量输入网络
input = torch.randn(1, 1, 32, 32)
out = net(input)
print(out)
Выходной результат:
tensor([[ 0.1005, 0.0263, 0.0013, -0.1157, -0.1197, -0.0141, 0.1425, -0.0521,
0.0689, 0.0220]], grad_fn=<ThAddmmBackward>)
Затем обратное распространение должно сначала очистить кеш градиента и выполнить обратное распространение стохастического градиента:
# 清空所有参数的梯度缓存,然后计算随机梯度进行反向传播
net.zero_grad()
out.backward(torch.randn(1, 10))
Уведомление:
torch.nn
Поддерживает только **мини-пакеты** данных, то есть ввод не может быть одним образцом, например, дляnn.Conv2d
Полученный вход представляет собой 4-мерный тензор --nSamples * nChannels * Height * Width
.Итак, если ваш ввод представляет собой один образец,нужно принять
input.unsqueeze(0)
увеличить размер поддельной партии, т. е. с 3-мерного на 4-мерный.
3.2 Функция потерь
Вход в функцию потерь(output, target)
, то есть данные пары выходных данных сети и истинной метки, а затем возвращает числовое значение, представляющее разрыв между выходными данными сети и истинной меткой.
PyTorch на самом деле определил множествофункция потерь, здесь используется только простая среднеквадратическая ошибка:nn.MSELoss
, пример следующий:
output = net(input)
# 定义伪标签
target = torch.randn(10)
# 调整大小,使得和 output 一样的 size
target = target.view(1, -1)
criterion = nn.MSELoss()
loss = criterion(output, target)
print(loss)
Результат выглядит следующим образом:
tensor(0.6524, grad_fn=<MseLossBackward>)
Здесь ниже показана схема расчета ввода-вывода данных всей сети, по сути данные идут от входного слоя к выходному слою, а расчетloss
процесс.
input -> conv2d -> relu -> maxpool2d -> conv2d -> relu -> maxpool2d
-> view -> linear -> relu -> linear -> relu -> linear
-> MSELoss
-> loss
если звонишьloss.backward()
, то весь граф дифференцируем, т. е. включаяloss
, все тензорные переменные в графе, если их свойстваrequires_grad=True
, то его градиент.grad
Тензоры всегда накапливаются вместе с градиентом.
Чтобы проиллюстрировать код:
# MSELoss
print(loss.grad_fn)
# Linear layer
print(loss.grad_fn.next_functions[0][0])
# Relu
print(loss.grad_fn.next_functions[0][0].next_functions[0][0])
вывод:
<MseLossBackward object at 0x0000019C0C349908>
<ThAddmmBackward object at 0x0000019C0C365A58>
<ExpandBackward object at 0x0000019C0C3659E8>
3.3 Обратное распространение
Для реализации обратного распространения нужно только вызватьloss.backward()
То есть конечно сначала нужно очистить текущий кеш градиента, т.е..zero_grad()
метода, иначе предыдущий градиент будет накапливаться до текущего градиента, что повлияет на обновление параметров веса.
Вот простой пример дляconv1
Параметр смещения для слояbias
Пример результатов до и после обратного распространения:
# 清空所有参数的梯度缓存
net.zero_grad()
print('conv1.bias.grad before backward')
print(net.conv1.bias.grad)
loss.backward()
print('conv1.bias.grad after backward')
print(net.conv1.bias.grad)
Выходной результат:
conv1.bias.grad before backward
tensor([0., 0., 0., 0., 0., 0.])
conv1.bias.grad after backward
tensor([ 0.0069, 0.0021, 0.0090, -0.0060, -0.0008, -0.0073])
Узнать больше оtorch.nn
библиотеку, вы можете просмотреть официальную документацию:
3.4 Обновление весов
Простейшее правило обновления веса с использованием метода стохастического градиентного спуска (SGD) выглядит следующим образом:
weight = weight - learning_rate * gradient
Следуя этому правилу, реализация кода выглядит так:
# 简单实现权重的更新例子
learning_rate = 0.01
for f in net.parameters():
f.data.sub_(f.grad.data * learning_rate)
Но это всего лишь самое простое правило, глубокое обучение имеет множество алгоритмов оптимизации, не толькоSGD
,иNesterov-SGD, Adam, RMSProp
и так далее, чтобы использовать эти разные подходы, здесь мы беремtorch.optim
библиотеку, пример использования следующий:
import torch.optim as optim
# 创建优化器
optimizer = optim.SGD(net.parameters(), lr=0.01)
# 在训练过程中执行下列操作
optimizer.zero_grad() # 清空梯度缓存
output = net(input)
loss = criterion(output, target)
loss.backward()
# 更新权重
optimizer.step()
Уведомление, тоже надо позвонитьoptimizer.zero_grad()
метод очистки буфера градиента.
Учебник в этом разделе:
Код для этого подраздела:
резюме
Вторая часть в основном знакомит с построением нейронной сети, включая определение сети, выбор функции потерь, обратное распространение для вычисления градиента и обновление параметров веса.
Добро пожаловать, чтобы обратить внимание на мою общедоступную учетную запись WeChat — машинное обучение и компьютерное зрение, или отсканируйте QR-код ниже, давайте общаться, учиться и прогрессировать вместе!
Прекрасная рекомендация в прошлом
Серия машинного обучения
- Вводный урок по машинному обучению для начинающих!
- Методы оценки модели, переобучения, недообучения и настройки гиперпараметров
- Резюме и сравнение часто используемых алгоритмов машинного обучения (конец)
- Резюме и сравнение часто используемых алгоритмов машинного обучения (часть 1)
- Серия «Введение в машинное обучение» (2) — «Как создать полноценный проект по машинному обучению» (1)
- Предварительная обработка данных для разработки признаков (часть 1)
- Узнайте о восьми приложениях компьютерного зрения
Рекомендация руководства по проектам и ресурсам Github
- [Рекомендовано проектом Github] Лучший веб-сайт для чтения и поиска статей
- [Совместное использование ресурсов] Официальное руководство по китайской версии TensorFlow здесь
- Обязательные к прочтению блоги об искусственном интеллекте и глубоком обучении
- [Учебник] Простое для понимания руководство по TensorFlow.
- [Ресурс] Порекомендуйте несколько книг и руководств по Python, как вводных, так и продвинутых!
- [Рекомендация проекта Github] Шпаргалка по машинному обучению и знаниям Python
- [Рекомендация проекта Github] Порекомендуйте три инструмента, которые помогут вам лучше использовать Github.
- Информация о крупных университетах на Github и видео зарубежных публичных курсов
- Вы правильно произнесли эти слова? Кстати, я рекомендую три учебника по английскому языку для программистов!