Как правило, для учебников или видеороликов по глубокому обучению автор объясняет эффект глубокого обучения с помощью набора данных MNIST, но этот набор данных слишком мал, и это монохромное изображение, вы можете получить лучшие результаты всего с несколькими моделями. Но что, если бы нас это не устроило и мы захотели обучить нейросеть классифицировать цветные изображения?
Конечно, можно, но не так просто, как вы можете себе представить.
Когда я впервые настроил нейронную сеть для самостоятельного обучения, точность обучения составляла менее 30%, и она не сходилась. Позже я постепенно использовал свое понимание глубокого обучения, чтобы постоянно корректировать структуру сети, и в то же время внедрил эффективные методы оптимизации, чтобы моя модель могла подняться до 50%, затем до 70% и, наконец, до 99% точности. во время обучения, точность 85% при тестировании, поэтомуЭта модель также показала способность расти в моем собственном процессе глубокого обучения. Вот почему я делюсь этой статьей.
Итак, какие шаги обычно требуются для обучения нейронной сети?
На рисунке выше показан процесс обучения для общего контролируемого обучения.
- Загрузите набор данных и выполните предварительную обработку.
- Предварительно обработанные данные делятся на две части: функция и метка.Функция отправляется в модель, а метка используется в качестве наземной истины.
- Модель получает функцию в качестве входных данных, а выходные данные предсказывают посредством серии операций.
- При использовании прогнозирования и прогнозирования в качестве переменных устанавливается функция потерь Loss, а значение функции Loss должно представлять разрыв между прогнозированием и достоверностью.
- Для установки оптимизатора Optimizer целью оптимизации является функция Loss, и ее значение должно быть как можно меньше.Чем меньше потеря, тем выше точность предсказания Модели.
- В процессе оптимизации Оптимизатора Модель изменяет веса собственных параметров по правилам, это повторяющийся цикл и непрерывный процесс до тех пор, пока значение потерь не станет стабильным, а меньшее значение не может быть получено.
Примечание. Эта статья разработана с помощью PyTorch, но другие среды глубокого обучения, такие как TensorFlow, также могут быть легко реализованы.
Поскольку он основан на описании кода PyTorch, я предполагаю, что читатель имеет базовое представление о PyTorch, платформе глубокого обучения.
1. Загрузите набор данных
Чтобы загрузить набор данных, мы можем написать код самостоятельно, но если он основан на цели обучения, то наложение опыта на код этого шага сделает людей очень сбойными и скучными.
К счастью, pytorch предоставляет очень удобный пакет torchvision.
torchvison предоставляет загрузчик данных для загрузки общих наборов данных MNIST, CIFAR-10, ImageNet и других, а также обеспечивает преобразование для преобразования, нормализации и визуализации изображений.
Основной пакет: torchvision.datasets, torch.utils.data.DataLoader
В этой статье наша цель — создать классификатор изображений на основе набора данных CIFAR-10 с помощью pytorch.
CIFAR-10 имеет 50000 обучающих изображений, 10000 тестовых изображений, всего 10 категорий, а именно «самолет», «автомобиль», «птица», «кошка», «олень», «собака», «лягушка», «лошадь». , 'корабль', 'грузовик' Размер изображения CIFAR-10 32x32x3, поэтому это относительно небольшое цветное изображение.
Как его загрузить?
import torch
import torch.nn as nn
import torch.nn.functional as F
import torchvision
import torchvision.transforms as transforms
import torch.optim as optim
import time
import os
transform = transforms.Compose(
[
transforms.RandomHorizontalFlip(),
transforms.RandomGrayscale(),
transforms.ToTensor(),
transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])
transform1 = transforms.Compose(
[
transforms.ToTensor(),
transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])
trainset = torchvision.datasets.CIFAR10(root='./data', train=True,
download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=100,
shuffle=True, num_workers=2)
testset = torchvision.datasets.CIFAR10(root='./data', train=False,
download=True, transform=transform1)
testloader = torch.utils.data.DataLoader(testset, batch_size=50,
shuffle=False, num_workers=2)
classes = ('plane', 'car', 'bird', 'cat',
'deer', 'dog', 'frog', 'horse', 'ship', 'truck')
Функция преобразования в приведенном выше коде в основном используется для предварительной обработки данных.
transforms.RandomHorizontalFlip(),
transforms.RandomGrayscale(),
Эти две строки кода в основном используются дляувеличение данныхДа, чтобы предотвратить переоснащение во время обучения, обычно на небольших наборах данных, емкость набора данных во время обучения увеличивается путем случайного переворачивания изображения и случайной регулировки яркости изображения.
transforms.ToTensor(),
transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])
Когда набор данных загружается, формат изображения по умолчанию — numpy, поэтому он преобразуется в тензор с помощью преобразований. Затем нормализуйте входное изображение.
Однако при тестировании данные не нужно дополнять, поэтому их преобразования все же немного отличаются.
trainset = torchvision.datasets.CIFAR10(root='./data', train=True,
download=True, transform=transform)
torchvision.datasets.CIFAR10 определяет набор данных CIFAR 10. Этот модуль определяет, как он загружает набор данных и как локально загружать готовые данные.
root указывает место, где хранится набор данных, а train указывает, является ли он обучающим набором данных.
trainloader = torch.utils.data.DataLoader(trainset, batch_size=100,
shuffle=True, num_workers=2)
Набор данных необходимо использовать с DataLoader, который постоянно извлекает данные из набора данных и отправляет их в модель для обучения и прогнозирования.
Здесь размер пакета указан как 100, то есть количество изображений в одном пакете мини-пакета равно 100.
shuffle = True указывает, что при извлечении данных порядок перемешивается случайным образом, потому что мы все основаны на стохастическом градиентном спуске для оптимизации обучения, но при тестировании, поскольку нет необходимости обновлять параметры, нет необходимости перемешивать порядок.
num_workers = 2 указывает количество рабочих потоков.
После запуска кода набор данных будет автоматически загружен и сохранен в файле данных в текущем каталоге.
Downloading https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz to ./data/cifar-10-python.tar.gz
Files already downloaded and verified
2. Определение нейронной сети
Можем еще раз посмотреть на картинку в начале статьи, Модель — это основная часть, а нейросеть — это Модель.
В этом сообщении в блоге я создал относительно глубокую нейронную сеть, и это копия VGG, Цель состоит в том, чтобы сделать тест более точным. Но я не стал полностью ссылаться на VGG-16, потому что у меня был GPU GTX1080i.В то время, когда я экспериментировал с Tensorflow, была проблема нехватки памяти, поэтому я уменьшил количество ядер свертки на основе VGG- 16.
Самая большая особенность VGG заключается в том, что он использует большое количество ядер свертки размером 3 x 3. Для получения более подробной информации, пожалуйста, обратитесь к моему сообщению в блоге.[Глубокое обучение] Интерпретация классических статей VGG по нейронной сети
| input (32x32x3) color image |
|---|
| Conv1 3x3,64 |
| Conv2 3x3,64 |
| Maxpool 2x2,strides=2 |
| Batch Normalization |
| Relu |
| – |
| Conv3 3x3,128 |
| Conv4 3x3,128 |
| Maxpool 2x2,strides=2 |
| Batch Normalization |
| Relu |
| – |
| Conv5 3x3,128 |
| Conv6 3x3,128 |
| Conv7 1x1,128 |
| Maxpool 2x2,strides=2 |
| Batch Normalization |
| Relu |
| – |
| Conv8 3x3,256 |
| Conv9 3x3,256 |
| Conv10 1x1,256 |
| Maxpool 2x2,strides=2 |
| Batch Normalization |
| Relu |
| – |
| Conv11 3x3,512 |
| Conv12 3x3,512 |
| Conv13 1x1,512 |
| Maxpool 2x2,strides=2 |
| Batch Normalization |
| Relu |
| – |
| FC14 (8192,1024) |
| Dropout |
| Relu |
| FC15 (1024,1024) |
| Dropout |
| Relu |
| FC16 (1024,10) |
class Net(nn.Module):
def __init__(self):
super(Net,self).__init__()
self.conv1 = nn.Conv2d(3,64,3,padding=1)
self.conv2 = nn.Conv2d(64,64,3,padding=1)
self.pool1 = nn.MaxPool2d(2, 2)
self.bn1 = nn.BatchNorm2d(64)
self.relu1 = nn.ReLU()
self.conv3 = nn.Conv2d(64,128,3,padding=1)
self.conv4 = nn.Conv2d(128, 128, 3,padding=1)
self.pool2 = nn.MaxPool2d(2, 2, padding=1)
self.bn2 = nn.BatchNorm2d(128)
self.relu2 = nn.ReLU()
self.conv5 = nn.Conv2d(128,128, 3,padding=1)
self.conv6 = nn.Conv2d(128, 128, 3,padding=1)
self.conv7 = nn.Conv2d(128, 128, 1,padding=1)
self.pool3 = nn.MaxPool2d(2, 2, padding=1)
self.bn3 = nn.BatchNorm2d(128)
self.relu3 = nn.ReLU()
self.conv8 = nn.Conv2d(128, 256, 3,padding=1)
self.conv9 = nn.Conv2d(256, 256, 3, padding=1)
self.conv10 = nn.Conv2d(256, 256, 1, padding=1)
self.pool4 = nn.MaxPool2d(2, 2, padding=1)
self.bn4 = nn.BatchNorm2d(256)
self.relu4 = nn.ReLU()
self.conv11 = nn.Conv2d(256, 512, 3, padding=1)
self.conv12 = nn.Conv2d(512, 512, 3, padding=1)
self.conv13 = nn.Conv2d(512, 512, 1, padding=1)
self.pool5 = nn.MaxPool2d(2, 2, padding=1)
self.bn5 = nn.BatchNorm2d(512)
self.relu5 = nn.ReLU()
self.fc14 = nn.Linear(512*4*4,1024)
self.drop1 = nn.Dropout2d()
self.fc15 = nn.Linear(1024,1024)
self.drop2 = nn.Dropout2d()
self.fc16 = nn.Linear(1024,10)
def forward(self,x):
x = self.conv1(x)
x = self.conv2(x)
x = self.pool1(x)
x = self.bn1(x)
x = self.relu1(x)
x = self.conv3(x)
x = self.conv4(x)
x = self.pool2(x)
x = self.bn2(x)
x = self.relu2(x)
x = self.conv5(x)
x = self.conv6(x)
x = self.conv7(x)
x = self.pool3(x)
x = self.bn3(x)
x = self.relu3(x)
x = self.conv8(x)
x = self.conv9(x)
x = self.conv10(x)
x = self.pool4(x)
x = self.bn4(x)
x = self.relu4(x)
x = self.conv11(x)
x = self.conv12(x)
x = self.conv13(x)
x = self.pool5(x)
x = self.bn5(x)
x = self.relu5(x)
# print(" x shape ",x.size())
x = x.view(-1,512*4*4)
x = F.relu(self.fc14(x))
x = self.drop1(x)
x = F.relu(self.fc15(x))
x = self.drop2(x)
x = self.fc16(x)
return x
В PyTorch вы можете настроить нейронную сеть, унаследовав nn.Module, задав структуру в init() и задав процесс прямого распространения в forward(). Поскольку PyTorch может автоматически вычислять градиенты, нет необходимости специально определять обратное распространение.
Стоит отметить, что я использовал пакетную нормализацию для ускорения обучения нейронных сетей, более подробную информацию можно найти в моем блоге.[Глубокое обучение] Подробное объяснение роли и теоретической основы пакетной нормализации
Кроме того, forward не выполняет операцию softmax на выходе в конце, поэтому это просто вывод.На этапе обучения Loss будет определять эту операцию, и если это тестирование или прогнозирование, операция softmax не требуется.
3. Определите функцию потерь и оптимизатор
Согласно блок-схеме в начале статьи, после определения модели нейронной сети необходимо определить функцию потерь Loss и оптимизатор Optimizer.
Здесь в качестве функции потерь используется функция перекрестных энтропийных потерь, а в качестве оптимизатора используется Адам.Конечно, можно использовать и SGD.
loss = nn.CrossEntropyLoss()
#optimizer = optim.SGD(self.parameters(),lr=0.01)
optimizer = optim.Adam(self.parameters(), lr=0.0001)
Следует отметить, что nn.CrossEntropyLoss() содержит две операции: logsoftmax и loss.
4. Обучение
После определения потерь и оптимизатора можно приступать к обучению.Метод обучения заключается в том, чтобы с помощью оптимизатора сделать значение потерь как можно меньше, чтобы предсказание нейронной сети становилось все выше и выше.
for epoch in range(100): # loop over the dataset multiple times
timestart = time.time()
running_loss = 0.0
total = 0
correct = 0
for i, data in enumerate(trainloader, 0):
# get the inputs
inputs, labels = data
inputs, labels = inputs.to(device),labels.to(device)
# zero the parameter gradients
optimizer.zero_grad()
# forward + backward + optimize
outputs = self(inputs)
l = loss(outputs, labels)
l.backward()
optimizer.step()
# print statistics
running_loss += l.item()
# print("i ",i)
if i % 500 == 499: # print every 500 mini-batches
print('[%d, %5d] loss: %.4f' %
(epoch, i, running_loss / 500))
running_loss = 0.0
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
correct += (predicted == labels).sum().item()
print('Accuracy of the network on the %d tran images: %.3f %%' % (total,
100.0 * correct / total))
total = 0
correct = 0
print('epoch %d cost %3f sec' %(epoch,time.time()-timestart))
print('Finished Training')
Программа устанавливает тренировочный процесс на 100 эпох и затем завершается.
Некоторые учащиеся могут не знать разницы между эпохой и итерацией.Итерация относится к обучению одного мини-пакета, а эпоха связана с размером набора данных и размером партии.
Количество изображений в обучающем наборе CIFAR-10 составляет 50 000, а размер пакета — 100, поэтому для завершения эпохи требуется 500 итераций.
Эпоху можно грубо рассматривать как нейронную сеть, которая просматривает все фотографии в обучающей выборке от начала до конца.
inputs, labels = data
inputs, labels = inputs.to(device),labels.to(device)
PyTorch может указать устройство, такое как GPU или CPU.Вышеприведенный код на самом деле является этой операцией, конечно, по умолчанию используется CPU.
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
Приведенный выше код определяет тип устройства.
optimizer.zero_grad()
# forward + backward + optimize
outputs = self(inputs)
l = loss(outputs, labels)
l.backward()
optimizer.step()
Приведенные выше несколько строк кода являются основной частью обучения.
соответственноПрямое распространение + обратное распространение + оптимизация, Согласно официальному примеру PyTorch, просто напишите это так.
running_loss += l.item()
# print("i ",i)
if i % 500 == 499: # print every 500 mini-batches
print('[%d, %5d] loss: %.4f' %
(epoch, i, running_loss / 500))
running_loss = 0.0
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
correct += (predicted == labels).sum().item()
print('Accuracy of the network on the %d tran images: %.3f %%' % (total,
100.0 * correct / total))
total = 0
correct = 0
Только что упоминалось, что в этой статье 500 итераций достигают 1 эпохи, и мы надеемся обнаружить эффект обучения во время обучения, поэтому для каждой эпохи выводите значение потерь и точность. Точность — это процент от общего числа выборок, которые точно предсказаны в эту эпоху.
4.1 Сохранение и восстановление модели обучения
Возможно, компьютеры некоторых студентов не имеют доступных графических процессоров, или версия графического процессора относительно низкая, поэтому время обучения будет очень долгим, поэтому очень важно иметь возможность сохранять и восстанавливать модель обучения в любое время.
PyTorch, безусловно, поддерживает и такую функцию.
torch.save({'epoch':epoch,
'model_state_dict':net.state_dict(),
'optimizer_state_dict':optimizer.state_dict(),
'loss':loss
},path)
torch.save() может сохранять эпоху, state_dict и потери во время обучения.
Что такое state_dict?Это словарь параметров, которые можно выучить. Следует отметить, что можно сохранить как state_dict сети, так и state_dict оптимизатора.
path указывает путь сохранения модели.
Таким образом, мы можем сохранить ход обучения и указать в нужный момент в соответствии с реальной ситуацией.
path = 'weights.tar'
checkpoint = torch.load(path)
self.load_state_dict(checkpoint['model_state_dict'])
optimizer.load_state_dict(checkpoint['optimizer_state_dict'])
initepoch = checkpoint['epoch']
loss = checkpoint['loss']
Загрузить контрольную точку через torch.load()
Затем параметры восстанавливаются с помощью метода load_state_dict() сети и оптимизатора.
В то же время можно восстановить предыдущее значение эпохи и потери.
Таким образом, полный код обучающей функции с функцией сохранения и восстановления модели выглядит следующим образом:
def train_sgd(self,device):
optimizer = optim.Adam(self.parameters(), lr=0.0001)
path = 'weights.tar'
initepoch = 0
if os.path.exists(path) is not True:
loss = nn.CrossEntropyLoss()
# optimizer = optim.SGD(self.parameters(),lr=0.01)
else:
checkpoint = torch.load(path)
self.load_state_dict(checkpoint['model_state_dict'])
optimizer.load_state_dict(checkpoint['optimizer_state_dict'])
initepoch = checkpoint['epoch']
loss = checkpoint['loss']
for epoch in range(initepoch,100): # loop over the dataset multiple times
timestart = time.time()
running_loss = 0.0
total = 0
correct = 0
for i, data in enumerate(trainloader, 0):
# get the inputs
inputs, labels = data
inputs, labels = inputs.to(device),labels.to(device)
# zero the parameter gradients
optimizer.zero_grad()
# forward + backward + optimize
outputs = self(inputs)
l = loss(outputs, labels)
l.backward()
optimizer.step()
# print statistics
running_loss += l.item()
# print("i ",i)
if i % 500 == 499: # print every 500 mini-batches
print('[%d, %5d] loss: %.4f' %
(epoch, i, running_loss / 500))
running_loss = 0.0
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
correct += (predicted == labels).sum().item()
print('Accuracy of the network on the %d tran images: %.3f %%' % (total,
100.0 * correct / total))
total = 0
correct = 0
torch.save({'epoch':epoch,
'model_state_dict':net.state_dict(),
'optimizer_state_dict':optimizer.state_dict(),
'loss':loss
},path)
print('epoch %d cost %3f sec' %(epoch,time.time()-timestart))
print('Finished Training')
5. Тест
Цель обучения нейронной сети — делать прогнозы, но чтобы проверить возможности модели, ее необходимо протестировать после обучения.
Тестовые изображения и обучающие изображения не находятся в одной и той же стопке данных.
Во время тестирования параметры модели фиксируются и расчет градиентов не требуется. Затем выполняется основная оценка, определяющая процентное соотношение между структурой, предсказанной моделью, и достоверностью.
def test(self,device):
correct = 0
total = 0
with torch.no_grad():
for data in testloader:
images, labels = data
images, labels = images.to(device), labels.to(device)
outputs = self(images)
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
correct += (predicted == labels).sum().item()
print('Accuracy of the network on the 10000 test images: %.3f %%' % (
100.0 * correct / total))
Наконец, мы наблюдаем окончательный результат.
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
net = Net()
net = net.to(device)
net.train_sgd(device)
net.test(device)
Сетевые объекты создаются, затем обучаются, а затем тестируются после обучения.
Files already downloaded and verified
Files already downloaded and verified
[99, 499] loss: 0.0383
Accuracy of the network on the 100 tran images: 99.000 %
epoch 99 cost 15.083664 sec
Finished Training
Accuracy of the network on the 10000 test images: 85.050 %
На прогон эпохи у меня ушло около 15 секунд, и в итоге точность теста этой нейросети достигла 85%. Самая известная оценка CIFAR-10 - 96,53. Согласно 85%, которые я показываю здесь, он, вероятно, займет 37-е место.
Полный код, используемый в этой статье, выглядит следующим образом.
import torch
import torch.nn as nn
import torch.nn.functional as F
import torchvision
import torchvision.transforms as transforms
import torch.optim as optim
import time
import os
transform = transforms.Compose(
[
transforms.RandomHorizontalFlip(),
transforms.RandomGrayscale(),
transforms.ToTensor(),
transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])
transform1 = transforms.Compose(
[
transforms.ToTensor(),
transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])
trainset = torchvision.datasets.CIFAR10(root='./data', train=True,
download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=100,
shuffle=True, num_workers=2)
testset = torchvision.datasets.CIFAR10(root='./data', train=False,
download=True, transform=transform1)
testloader = torch.utils.data.DataLoader(testset, batch_size=50,
shuffle=False, num_workers=2)
classes = ('plane', 'car', 'bird', 'cat',
'deer', 'dog', 'frog', 'horse', 'ship', 'truck')
class Net(nn.Module):
def __init__(self):
super(Net,self).__init__()
self.conv1 = nn.Conv2d(3,64,3,padding=1)
self.conv2 = nn.Conv2d(64,64,3,padding=1)
self.pool1 = nn.MaxPool2d(2, 2)
self.bn1 = nn.BatchNorm2d(64)
self.relu1 = nn.ReLU()
self.conv3 = nn.Conv2d(64,128,3,padding=1)
self.conv4 = nn.Conv2d(128, 128, 3,padding=1)
self.pool2 = nn.MaxPool2d(2, 2, padding=1)
self.bn2 = nn.BatchNorm2d(128)
self.relu2 = nn.ReLU()
self.conv5 = nn.Conv2d(128,128, 3,padding=1)
self.conv6 = nn.Conv2d(128, 128, 3,padding=1)
self.conv7 = nn.Conv2d(128, 128, 1,padding=1)
self.pool3 = nn.MaxPool2d(2, 2, padding=1)
self.bn3 = nn.BatchNorm2d(128)
self.relu3 = nn.ReLU()
self.conv8 = nn.Conv2d(128, 256, 3,padding=1)
self.conv9 = nn.Conv2d(256, 256, 3, padding=1)
self.conv10 = nn.Conv2d(256, 256, 1, padding=1)
self.pool4 = nn.MaxPool2d(2, 2, padding=1)
self.bn4 = nn.BatchNorm2d(256)
self.relu4 = nn.ReLU()
self.conv11 = nn.Conv2d(256, 512, 3, padding=1)
self.conv12 = nn.Conv2d(512, 512, 3, padding=1)
self.conv13 = nn.Conv2d(512, 512, 1, padding=1)
self.pool5 = nn.MaxPool2d(2, 2, padding=1)
self.bn5 = nn.BatchNorm2d(512)
self.relu5 = nn.ReLU()
self.fc14 = nn.Linear(512*4*4,1024)
self.drop1 = nn.Dropout2d()
self.fc15 = nn.Linear(1024,1024)
self.drop2 = nn.Dropout2d()
self.fc16 = nn.Linear(1024,10)
def forward(self,x):
x = self.conv1(x)
x = self.conv2(x)
x = self.pool1(x)
x = self.bn1(x)
x = self.relu1(x)
x = self.conv3(x)
x = self.conv4(x)
x = self.pool2(x)
x = self.bn2(x)
x = self.relu2(x)
x = self.conv5(x)
x = self.conv6(x)
x = self.conv7(x)
x = self.pool3(x)
x = self.bn3(x)
x = self.relu3(x)
x = self.conv8(x)
x = self.conv9(x)
x = self.conv10(x)
x = self.pool4(x)
x = self.bn4(x)
x = self.relu4(x)
x = self.conv11(x)
x = self.conv12(x)
x = self.conv13(x)
x = self.pool5(x)
x = self.bn5(x)
x = self.relu5(x)
# print(" x shape ",x.size())
x = x.view(-1,512*4*4)
x = F.relu(self.fc14(x))
x = self.drop1(x)
x = F.relu(self.fc15(x))
x = self.drop2(x)
x = self.fc16(x)
return x
def train_sgd(self,device):
optimizer = optim.Adam(self.parameters(), lr=0.0001)
path = 'weights.tar'
initepoch = 0
if os.path.exists(path) is not True:
loss = nn.CrossEntropyLoss()
# optimizer = optim.SGD(self.parameters(),lr=0.01)
else:
checkpoint = torch.load(path)
self.load_state_dict(checkpoint['model_state_dict'])
optimizer.load_state_dict(checkpoint['optimizer_state_dict'])
initepoch = checkpoint['epoch']
loss = checkpoint['loss']
for epoch in range(initepoch,100): # loop over the dataset multiple times
timestart = time.time()
running_loss = 0.0
total = 0
correct = 0
for i, data in enumerate(trainloader, 0):
# get the inputs
inputs, labels = data
inputs, labels = inputs.to(device),labels.to(device)
# zero the parameter gradients
optimizer.zero_grad()
# forward + backward + optimize
outputs = self(inputs)
l = loss(outputs, labels)
l.backward()
optimizer.step()
# print statistics
running_loss += l.item()
# print("i ",i)
if i % 500 == 499: # print every 500 mini-batches
print('[%d, %5d] loss: %.4f' %
(epoch, i, running_loss / 500))
running_loss = 0.0
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
correct += (predicted == labels).sum().item()
print('Accuracy of the network on the %d tran images: %.3f %%' % (total,
100.0 * correct / total))
total = 0
correct = 0
torch.save({'epoch':epoch,
'model_state_dict':net.state_dict(),
'optimizer_state_dict':optimizer.state_dict(),
'loss':loss
},path)
print('epoch %d cost %3f sec' %(epoch,time.time()-timestart))
print('Finished Training')
def test(self,device):
correct = 0
total = 0
with torch.no_grad():
for data in testloader:
images, labels = data
images, labels = images.to(device), labels.to(device)
outputs = self(images)
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
correct += (predicted == labels).sum().item()
print('Accuracy of the network on the 10000 test images: %.3f %%' % (
100.0 * correct / total))
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
net = Net()
net = net.to(device)
net.train_sgd(device)
net.test(device)
Приведенный выше код можно запустить, протестировав его самостоятельно.
области, которые необходимо оптимизировать
1. Количество слоев нейронной сети и количество ядер свертки
У некоторых студентов могут быть лучшие графические процессоры, чем у меня, поэтому вы можете попытаться углубить слои или увеличить количество ядер свертки в каждом слое.
Студенты со слабым GPU или без GPU могут попробовать уменьшить количество слоев нейронной сети и количество ядер свертки в каждом слое, иначе обучение может занять определенное время.
2. Настроить архитектуру нейросети
Моя нейронная сеть улучшена со ссылкой на VGG-16.Заинтересованные студенты могут обратиться к Inception-V3 или ResNet для преобразования, и точность будет выше.
3. Визуализируйте результаты тренировки
Tensorflow имеет TensorBoard, инструмент визуализации, а PyTorch может выполнять визуализацию с помощью Visdom.
Надеюсь, вы попрактикуетесь в этом сами, а затем улучшите точность теста.