вводить
Большую часть последних двух лет я довольно много работал в области глубокого обучения. Это был довольно хороший опыт, во время которого я работал над несколькими проектами, связанными с изображениями и видеоданными.
До этого я был на периферии, избегая таких концепций глубокого обучения, как обнаружение объектов и распознавание лиц. Только в конце 2017 года началось углубленное изучение. За это время я столкнулся со всевозможными трудностями. Я хотел бы коснуться четырех наиболее распространенных проблем, с которыми сталкиваются большинство практиков и энтузиастов глубокого обучения на своем пути.
Если вы уже работали над проектами глубокого обучения, вы можете быстро понять эти барьеры. Хорошая новость заключается в том, что преодолеть их не так сложно, как вы думаете!
В этой статье мы будем использовать очень практичный подход. Во-первых, мы будем основываться на четырех общих головоломках, о которых я упоминал выше. Затем мы погрузимся прямо в код Python, чтобы изучить ключевые советы и приемы для борьбы и преодоления этих проблем. Здесь есть что распаковать, так что давайте начнем!
содержание
- Общая дилемма для моделей глубокого обучения
- Обзор тематического исследования по классификации транспортных средств
- Узнайте о каждой проблеме и о том, как ее преодолеть, чтобы повысить производительность моделей глубокого обучения.
- Практический пример: повышение эффективности нашей модели классификации транспортных средств
Общая дилемма для моделей глубокого обучения
Модели глубокого обучения обычно очень хорошо работают с большинством данных. Когда дело доходит до данных изображения, модели глубокого обучения, особенно сверточные нейронные сети (CNN), превосходят почти все другие модели.
Мой обычный подход заключается в использовании модели CNN при столкновении с проектами, связанными с изображениями, такими как проекты классификации изображений.
Этот подход работает хорошо, но в некоторых случаях CNN или другие модели глубокого обучения не работают. Я сталкивался с этим несколько раз. Мои данные в порядке, архитектура модели определена правильно, функция потерь и оптимизатор настроены правильно, но моя модель не делает того, что я ожидаю.
Это распространенная дилемма, с которой сталкивается большинство из нас при работе с моделями глубокого обучения.
Как было сказано выше, я решу четыре таких головоломки:
- Отсутствие данных для обучения
- переоснащение
- недооснащение
- долгое время обучения
Прежде чем углубиться в эти загадки и разобраться в них, давайте кратко рассмотрим тематические исследования, которые мы рассмотрим в этой статье.
Обзор тематического исследования по классификации транспортных средств
Эта статья является частью серии статей о PyTorch для начинающих, которую я пишу. Вы можете ознакомиться с первыми тремя статьями здесь (мы приведем некоторые из них):
- Начало работы с PyTorch
- Построение моделей классификации изображений с использованием сверточных нейронных сетей в PyTorch
- Перенос обучения с PyTorc
Мы продолжим чтение тематического исследования, которое мы видели в предыдущей статье. Цель здесь состоит в том, чтобы классифицировать изображения транспортных средств как срочные или несрочные.
Во-первых, давайте быстро построим модель CNN и используем ее в качестве эталона. Мы также постараемся улучшить производительность этой модели. Эти шаги очень просты, и мы видели их несколько раз в предыдущих статьях.
Поэтому я не буду вдаваться в каждый шаг здесь. Вместо этого мы сосредоточимся на коде, который вы всегда можете изучить более подробно в предыдущей статье, ссылку на которую я дал выше.Вы можете получить набор данных здесь: https://drive.Google.com/file//1EB vi send JP0FQ can B1 Axinba 7K Q26YP TW Mn EAP J/view.
Вот полный код для построения модели CNN для нашего проекта классификации транспортных средств.
библиотека импорта
# 导入库
import pandas as pd
import numpy as np
from tqdm import tqdm
# 用于读取和显示图像
from skimage.io import imread
from skimage.transform import resize
import matplotlib.pyplot as plt
%matplotlib inline
# 用于创建验证集
from sklearn.model_selection import train_test_split
# 用于评估模型
from sklearn.metrics import accuracy_score
# PyTorch库和模块
import torch
from torch.autograd import Variable
from torch.nn import Linear, ReLU, CrossEntropyLoss, Sequential, Conv2d, MaxPool2d, Module, Softmax, BatchNorm2d, Dropout
from torch.optim import Adam, SGD
# 预训练模型
from torchvision import models
Загрузить набор данных
# 加载数据集
train = pd.read_csv('emergency_train.csv')
# 加载训练图片
train_img = []
for img_name in tqdm(train['image_names']):
# 定义图像路径
image_path = '../Hack Session/images/' + img_name
# 读取图片
img = imread(image_path)
# 标准化像素值
img = img/255
img = resize(img, output_shape=(224,224,3), mode='constant', anti_aliasing=True)
# 转换为浮点数
img = img.astype('float32')
# 添加图片到列表
train_img.append(img)
# 转换为numpy数组
train_x = np.array(train_img)
train_x.shape
Создание обучающих и проверочных наборов
# 定义目标
train_y = train['emergency_or_not'].values
# 创建验证集
train_x, val_x, train_y, val_y = train_test_split(train_x, train_y, test_size = 0.1, random_state = 13, stratify=train_y)
(train_x.shape, train_y.shape), (val_x.shape, val_y.shape)
Преобразование изображения в формат факела
# 转换训练图片到torch格式
train_x = train_x.reshape(1481, 3, 224, 224)
train_x = torch.from_numpy(train_x)
# 转换目标到torch格式
train_y = train_y.astype(int)
train_y = torch.from_numpy(train_y)
# 转换验证图像到torch格式
val_x = val_x.reshape(165, 3, 224, 224)
val_x = torch.from_numpy(val_x)
# 转换目标到torch格式
val_y = val_y.astype(int)
val_y = torch.from_numpy(val_y)
Определить архитектуру модели
torch.manual_seed(0)
class Net(Module):
def __init__(self):
super(Net, self).__init__()
self.cnn_layers = Sequential(
# 定义2D卷积层
Conv2d(3, 16, kernel_size=3, stride=1, padding=1),
ReLU(inplace=True),
MaxPool2d(kernel_size=2, stride=2),
# 另一个2D卷积层
Conv2d(16, 32, kernel_size=3, stride=1, padding=1),
ReLU(inplace=True),
MaxPool2d(kernel_size=2, stride=2)
)
self.linear_layers = Sequential(
Linear(32 * 56 * 56, 2)
)
# 前项传播
def forward(self, x):
x = self.cnn_layers(x)
x = x.view(x.size(0), -1)
x = self.linear_layers(x)
return x
Задайте параметры модели
# 定义模型
model = Net()
# 定义优化器
optimizer = Adam(model.parameters(), lr=0.0001)
# 定义损失函数
criterion = CrossEntropyLoss()
# 检查GPU是否可用
if torch.cuda.is_available():
model = model.cuda()
criterion = criterion.cuda()
print(model)
Обучите модель
torch.manual_seed(0)
# 模型batch大小
batch_size = 128
# epoch数
n_epochs = 25
for epoch in range(1, n_epochs+1):
# 保持记录训练与验证集损失
train_loss = 0.0
permutation = torch.randperm(train_x.size()[0])
training_loss = []
for i in tqdm(range(0,train_x.size()[0], batch_size)):
indices = permutation[i:i+batch_size]
batch_x, batch_y = train_x[indices], train_y[indices]
if torch.cuda.is_available():
batch_x, batch_y = batch_x.cuda(), batch_y.cuda()
optimizer.zero_grad()
outputs = model(batch_x)
loss = criterion(outputs,batch_y)
training_loss.append(loss.item())
loss.backward()
optimizer.step()
training_loss = np.average(training_loss)
print('epoch: \t', epoch, '\t training loss: \t', training_loss)
Прогноз на тренировочном наборе
# 训练集预测
prediction = []
target = []
permutation = torch.randperm(train_x.size()[0])
for i in tqdm(range(0,train_x.size()[0], batch_size)):
indices = permutation[i:i+batch_size]
batch_x, batch_y = train_x[indices], train_y[indices]
if torch.cuda.is_available():
batch_x, batch_y = batch_x.cuda(), batch_y.cuda()
with torch.no_grad():
output = model(batch_x.cuda())
softmax = torch.exp(output).cpu()
prob = list(softmax.numpy())
predictions = np.argmax(prob, axis=1)
prediction.append(predictions)
target.append(batch_y)
# 训练集精度
accuracy = []
for i in range(len(prediction)):
accuracy.append(accuracy_score(target[i],prediction[i]))
print('training accuracy: \t', np.average(accuracy))
Прогноз на проверочном наборе
# 验证集预测
prediction_val = []
target_val = []
permutation = torch.randperm(val_x.size()[0])
for i in tqdm(range(0,val_x.size()[0], batch_size)):
indices = permutation[i:i+batch_size]
batch_x, batch_y = val_x[indices], val_y[indices]
if torch.cuda.is_available():
batch_x, batch_y = batch_x.cuda(), batch_y.cuda()
with torch.no_grad():
output = model(batch_x.cuda())
softmax = torch.exp(output).cpu()
prob = list(softmax.numpy())
predictions = np.argmax(prob, axis=1)
prediction_val.append(predictions)
target_val.append(batch_y)
# 验证集精度
accuracy_val = []
for i in range(len(prediction_val)):
accuracy_val.append(accuracy_score(target_val[i],prediction_val[i]))
print('validation accuracy: \t', np.average(accuracy_val))
Это наша модель CNN. Точность обучения составляет около 88%, а точность проверки близка к 70%.
Мы будем усердно работать, чтобы улучшить производительность этой модели. Но перед этим давайте на минутку разберемся в загадках, которые могут быть причиной такой низкой производительности.
Загадки глубокого обучения
Загадка глубокого обучения 1: отсутствие доступных данных для обучения наших моделей
Модели глубокого обучения обычно требуют больших объемов обучающих данных. Как правило, чем больше данных, тем лучше производительность модели. Проблема с нехваткой данных заключается в том, что наша модель глубокого обучения может быть не в состоянии изучить шаблоны или функции из данных, поэтому она может не дать хорошей производительности на невидимых данных.
Если вы посмотрите на пример классификации автомобилей, у нас есть только около 1650 изображений, поэтому эта модель не очень хорошо работает на проверочном наборе. Трудности с меньшим количеством данных распространены при работе с компьютерным зрением и моделями глубокого обучения.
Как вы понимаете, сбор данных вручную — утомительная и трудоемкая задача. Поэтому мы можем использоватьТехнология увеличения данныхВместо того, чтобы тратить дни на сбор данных.
Увеличение данных — это процесс создания новых данных или дополнения данных для обучения модели без фактического сбора новых данных.
Существуют различные методы улучшения данных для данных изображения, и обычно используемые методы улучшения включают вращение, сдвиг и отражение.
Это настолько хорошая тема, что я решил написать целую статью. Я планирую обсудить эти методы и их реализацию в PyTorch в следующей статье.
2: Переоснащение моделиЯ уверен, что вы слышали о подгонке. Это одна из самых распространенных головоломок (и ошибок), которую допускают специалисты по данным, когда они плохо знакомы с машинным обучением. Но проблема на самом деле выходит за рамки области, и она также применима к глубокому обучению.
Когда модель очень хорошо работает на тренировочном наборе, но ухудшается на проверочном наборе (или невидимых данных), она считается переоснащенной.
Например, предположим, что у нас есть набор для обучения и набор для проверки. Мы используем обучающие данные для обучения модели и проверки ее производительности на обучающем и проверочном наборах (показатель оценки — точность). Точность обучения составляет 95 %, а точность проверочного набора — 62 %. Звучит знакомо?
Поскольку точность проверки намного ниже точности обучения, можно сделать вывод, что у модели есть проблема переобучения.. Следующий пример поможет вам лучше понять, что такое переобучение:
Часть, отмеченная синим цветом на рисунке выше, является моделью переобучения, потому что ошибка обучения очень мала, а ошибка теста очень высока. Причина переобучения заключается в том, что модель даже извлекает ненужную информацию из обучающих данных, поэтому она очень хорошо работает на обучающем наборе.
Однако он не будет выполняться при вводе новых данных.Мы можем ввести Dropout в архитектуру модели, чтобы решить проблему переобучения..
С помощью Dropout мы случайным образом отключаем определенные нейроны нейросети. Допустим, мы добавляем слой Dropout с вероятностью 0,5 к слою, в котором изначально было 20 нейронов, поэтому 10 из этих 20 нейронов будут подавлены, и в итоге мы получим менее сложную архитектуру.
Таким образом, модель не будет изучать слишком сложные закономерности и сможет избежать переобучения. Теперь добавим в нашу архитектуру слой Dropout и проверим его работоспособность.
Архитектура модели
torch.manual_seed(0)
class Net(Module):
def __init__(self):
super(Net, self).__init__()
self.cnn_layers = Sequential(
# 定义2D卷积层
Conv2d(3, 16, kernel_size=3, stride=1, padding=1),
ReLU(inplace=True),
MaxPool2d(kernel_size=2, stride=2),
# Dropout层
Dropout(),
#另一个2D卷积层
Conv2d(16, 32, kernel_size=3, stride=1, padding=1),
ReLU(inplace=True),
MaxPool2d(kernel_size=2, stride=2),
# Dropout层
Dropout(),
)
self.linear_layers = Sequential(
Linear(32 * 56 * 56, 2)
)
# 前向传播
def forward(self, x):
x = self.cnn_layers(x)
x = x.view(x.size(0), -1)
x = self.linear_layers(x)
return x
Здесь я добавляю слой Dropout к каждому сверточному блоку. Значение по умолчанию равно 0,5, что означает, что половина нейронов будет отключена случайным образом. Это гиперпараметр, вы можете выбрать любое значение от 0 до 1.
Далее мы определим параметры модели, такие как функция потерь, оптимизатор и скорость обучения.
Параметры модели
# 定义模型
model = Net()
# 定义优化器
optimizer = Adam(model.parameters(), lr=0.0001)
# 定义损失函数
criterion = CrossEntropyLoss()
# 检查GPU是否可用
if torch.cuda.is_available():
model = model.cuda()
criterion = criterion.cuda()
print(model)
Здесь вы можете видеть, что значение по умолчанию в Dropout равно 0,5. Наконец, давайте обучим модель после добавления слоя Dropout:
Обучите модель
torch.manual_seed(0)
# 模型batch大小
batch_size = 128
# epoch数
n_epochs = 25
for epoch in range(1, n_epochs+1):
# 保持记录训练与验证集损失
train_loss = 0.0
permutation = torch.randperm(train_x.size()[0])
training_loss = []
for i in tqdm(range(0,train_x.size()[0], batch_size)):
indices = permutation[i:i+batch_size]
batch_x, batch_y = train_x[indices], train_y[indices]
if torch.cuda.is_available():
batch_x, batch_y = batch_x.cuda(), batch_y.cuda()
optimizer.zero_grad()
outputs = model(batch_x)
loss = criterion(outputs,batch_y)
training_loss.append(loss.item())
loss.backward()
optimizer.step()
training_loss = np.average(training_loss)
print('epoch: \t', epoch, '\t training loss: \t', training_loss)
Теперь давайте проверим точность обучения и проверки, используя эту обученную модель.
Проверить работоспособность модели
#
prediction = []
target = []
permutation = torch.randperm(train_x.size()[0])
for i in tqdm(range(0,train_x.size()[0], batch_size)):
indices = permutation[i:i+batch_size]
batch_x, batch_y = train_x[indices], train_y[indices]
if torch.cuda.is_available():
batch_x, batch_y = batch_x.cuda(), batch_y.cuda()
with torch.no_grad():
output = model(batch_x.cuda())
softmax = torch.exp(output).cpu()
prob = list(softmax.numpy())
predictions = np.argmax(prob, axis=1)
prediction.append(predictions)
target.append(batch_y)
# 训练集精度
accuracy = []
for i in range(len(prediction)):
accuracy.append(accuracy_score(target[i],prediction[i]))
print('training accuracy: \t', np.average(accuracy))
Опять же, давайте проверим точность набора проверки:
# 验证集预测
prediction_val = []
target_val = []
permutation = torch.randperm(val_x.size()[0])
for i in tqdm(range(0,val_x.size()[0], batch_size)):
indices = permutation[i:i+batch_size]
batch_x, batch_y = val_x[indices], val_y[indices]
if torch.cuda.is_available():
batch_x, batch_y = batch_x.cuda(), batch_y.cuda()
with torch.no_grad():
output = model(batch_x.cuda())
softmax = torch.exp(output).cpu()
prob = list(softmax.numpy())
predictions = np.argmax(prob, axis=1)
prediction_val.append(predictions)
target_val.append(batch_y)
# 验证集精度
accuracy_val = []
for i in range(len(prediction_val)):
accuracy_val.append(accuracy_score(target_val[i],prediction_val[i]))
print('validation accuracy: \t', np.average(accuracy_val))
Сравним с предыдущими результатами:
точность тренировочного набора |
Проверка правильности набора |
|
---|---|---|
нет отсева |
87.80 | 69.72 |
Имеет отсев |
73.56 | 70.29 |
В приведенной выше таблице представлена точность без выпадения и с выпадением. Если вы посмотрите на точность обучения и проверки моделей без пропусков, они не синхронизированы. Точность обучения слишком высока, а точность проверки низка. Так что это может быть примером переобучения.
Когда мы представили Dropout, точность набора для обучения и проверки была синхронизирована.Поэтому, если ваша модель переоснащена, вы можете попробовать добавить отсевающие слои, чтобы уменьшить сложность модели..
Количество добавляемых исключений — это гиперпараметр, которым вы можете управлять с помощью этого значения. Теперь давайте рассмотрим еще одну головоломку.
Задача глубокого обучения 3: Недообучение модели
Модели глубокого обучения также могут не соответствовать требованиям, как бы маловероятно это ни звучало.
Недообучение — это когда модель не может изучить шаблоны из самих обучающих данных и, следовательно, имеет более низкую производительность на обучающем наборе.
Это может быть связано с разными причинами, например, с недостатком данных для обучения, слишком простой архитектурой, обучением модели реже и т. д.
Чтобы решить проблему недообучения, вы можете попробовать следующие решения:
- добавить тренировочные данные
- сделать сложную модель
- Увеличить эпоху обучения
Для нашей задачи недообучение не является проблемой, поэтому мы перейдем к следующему способу повышения производительности моделей глубокого обучения.
Задача глубокого обучения 4: слишком долгое время обучения
В некоторых случаях вы можете обнаружить, что вашей нейронной сети требуется много времени для сходимости. Основная причина этого заключается в том, что изменилось распределение входных данных для слоев нейронной сети.
В процессе обучения меняются веса каждого слоя нейронной сети, а также активация. Теперь эти активации являются входными данными для следующего уровня, поэтому каждая последующая итерация меняет распределение.
Из-за этого изменения распределения каждый слой должен адаптироваться к изменяющимся входным данным, поэтому время обучения увеличивается.
Чтобы преодолеть эту проблему, мы можем применить пакетную нормализацию, при которой мы нормализуем активацию скрытых слоев и пытаемся создать такое же распределение.
Теперь добавим в схемуbatchnormслой и проверить его работоспособность на задаче классификации транспортных средств:
torch.manual_seed(0)
class Net(Module):
def __init__(self):
super(Net, self).__init__()
self.cnn_layers = Sequential(
# 定义2D卷积层
Conv2d(3, 16, kernel_size=3, stride=1, padding=1),
ReLU(inplace=True),
# BN层
BatchNorm2d(16),
MaxPool2d(kernel_size=2, stride=2),
#另一个2D卷积层
Conv2d(16, 32, kernel_size=3, stride=1, padding=1),
ReLU(inplace=True),
# BN层
BatchNorm2d(32),
MaxPool2d(kernel_size=2, stride=2),
)
self.linear_layers = Sequential(
Linear(32 * 56 * 56, 2)
)
# 前向传播
def forward(self, x):
x = self.cnn_layers(x)
x = x.view(x.size(0), -1)
x = self.linear_layers(x)
return x
Задайте параметры модели
# 定义模型
model = Net()
# 定义优化器
optimizer = Adam(model.parameters(), lr=0.00005)
# 定义损失函数
criterion = CrossEntropyLoss()
# 检查GPU是否可用
if torch.cuda.is_available():
model = model.cuda()
criterion = criterion.cuda()
print(model)
Давайте обучим модель
torch.manual_seed(0)
# 模型batch大小
batch_size = 128
# epoch数
n_epochs = 5
for epoch in range(1, n_epochs+1):
# 保持记录训练与验证集损失
train_loss = 0.0
permutation = torch.randperm(train_x.size()[0])
training_loss = []
for i in tqdm(range(0,train_x.size()[0], batch_size)):
indices = permutation[i:i+batch_size]
batch_x, batch_y = train_x[indices], train_y[indices]
if torch.cuda.is_available():
batch_x, batch_y = batch_x.cuda(), batch_y.cuda()
optimizer.zero_grad()
outputs = model(batch_x)
loss = criterion(outputs,batch_y)
training_loss.append(loss.item())
loss.backward()
optimizer.step()
training_loss = np.average(training_loss)
print('epoch: \t', epoch, '\t training loss: \t', training_loss)
Очевидно, что модель способна очень быстро обучаться. В эпоху 5 наши потери при обучении составляют 0,3386, а после 25 эпох, когда мы не используем пакетную нормализацию, наши потери при обучении составляют 0,3851.
Поэтому введение пакетной нормализации определенно сокращает время обучения. Давайте проверим производительность на обучающем и проверочном наборах:
prediction = []
target = []
permutation = torch.randperm(train_x.size()[0])
for i in tqdm(range(0,train_x.size()[0], batch_size)):
indices = permutation[i:i+batch_size]
batch_x, batch_y = train_x[indices], train_y[indices]
if torch.cuda.is_available():
batch_x, batch_y = batch_x.cuda(), batch_y.cuda()
with torch.no_grad():
output = model(batch_x.cuda())
softmax = torch.exp(output).cpu()
prob = list(softmax.numpy())
predictions = np.argmax(prob, axis=1)
prediction.append(predictions)
target.append(batch_y)
# 训练集精度
accuracy = []
for i in range(len(prediction)):
accuracy.append(accuracy_score(target[i],prediction[i]))
print('training accuracy: \t', np.average(accuracy))
# 验证集预测
prediction_val = []
target_val = []
permutation = torch.randperm(val_x.size()[0])
for i in tqdm(range(0,val_x.size()[0], batch_size)):
indices = permutation[i:i+batch_size]
batch_x, batch_y = val_x[indices], val_y[indices]
if torch.cuda.is_available():
batch_x, batch_y = batch_x.cuda(), batch_y.cuda()
with torch.no_grad():
output = model(batch_x.cuda())
softmax = torch.exp(output).cpu()
prob = list(softmax.numpy())
predictions = np.argmax(prob, axis=1)
prediction_val.append(predictions)
target_val.append(batch_y)
# 验证集精度
accuracy_val = []
for i in range(len(prediction_val)):
accuracy_val.append(accuracy_score(target_val[i],prediction_val[i]))
print('validation accuracy: \t', np.average(accuracy_val))
Добавление пакетной нормализации может сократить время обучения, но здесь есть проблема. Вы можете понять, что это такое? Теперь модель переобучена, так как точность обучения составляет 91 %, а проверочного набора — 63 %. Помните, что мы не добавили выпадающий слой в последнюю модель.
Вот некоторые приемы, которые мы можем использовать для повышения производительности наших моделей глубокого обучения. Теперь давайте объединим все методы, которые мы уже изучили.
Практический пример: повышение эффективности модели классификации транспортных средств
Мы видели, как отсев и нормализация партии могут помочь уменьшить переоснащение и ускорить процесс обучения. Настало время объединить все эти методы и построить модель.
torch.manual_seed(0)
class Net(Module):
def __init__(self):
super(Net, self).__init__()
self.cnn_layers = Sequential(
# 定义2D卷积层
Conv2d(3, 16, kernel_size=3, stride=1, padding=1),
ReLU(inplace=True),
# BN层
BatchNorm2d(16),
MaxPool2d(kernel_size=2, stride=2),
# 添加dropout
Dropout(),
#另一个2D卷积层
Conv2d(16, 32, kernel_size=3, stride=1, padding=1),
ReLU(inplace=True),
# BN层
BatchNorm2d(32),
MaxPool2d(kernel_size=2, stride=2),
# 添加dropout
Dropout(),
)
self.linear_layers = Sequential(
Linear(32 * 56 * 56, 2)
)
# 前向传播
def forward(self, x):
x = self.cnn_layers(x)
x = x.view(x.size(0), -1)
x = self.linear_layers(x)
return x
Теперь определим параметры модели:
# 定义模型
model = Net()
# 定义优化器
optimizer = Adam(model.parameters(), lr=0.00025)
# 定义损失函数
criterion = CrossEntropyLoss()
# 检查GPU是否可用
if torch.cuda.is_available():
model = model.cuda()
criterion = criterion.cuda()
print(model)
Наконец, давайте обучим модель:
torch.manual_seed(0)
# 模型batch大小
batch_size = 128
# epoch数
n_epochs = 10
for epoch in range(1, n_epochs+1):
# 保持记录训练与验证集损失
train_loss = 0.0
permutation = torch.randperm(train_x.size()[0])
training_loss = []
for i in tqdm(range(0,train_x.size()[0], batch_size)):
indices = permutation[i:i+batch_size]
batch_x, batch_y = train_x[indices], train_y[indices]
if torch.cuda.is_available():
batch_x, batch_y = batch_x.cuda(), batch_y.cuda()
optimizer.zero_grad()
outputs = model(batch_x)
loss = criterion(outputs,batch_y)
training_loss.append(loss.item())
loss.backward()
optimizer.step()
training_loss = np.average(training_loss)
print('epoch: \t', epoch, '\t training loss: \t', training_loss)
Далее проверим работоспособность модели:
prediction = []
target = []
permutation = torch.randperm(train_x.size()[0])
for i in tqdm(range(0,train_x.size()[0], batch_size)):
indices = permutation[i:i+batch_size]
batch_x, batch_y = train_x[indices], train_y[indices]
if torch.cuda.is_available():
batch_x, batch_y = batch_x.cuda(), batch_y.cuda()
with torch.no_grad():
output = model(batch_x.cuda())
softmax = torch.exp(output).cpu()
prob = list(softmax.numpy())
predictions = np.argmax(prob, axis=1)
prediction.append(predictions)
target.append(batch_y)
# 训练集精度
accuracy = []
for i in range(len(prediction)):
accuracy.append(accuracy_score(target[i],prediction[i]))
print('training accuracy: \t', np.average(accuracy))
# 验证集预测
prediction_val = []
target_val = []
permutation = torch.randperm(val_x.size()[0])
for i in tqdm(range(0,val_x.size()[0], batch_size)):
indices = permutation[i:i+batch_size]
batch_x, batch_y = val_x[indices], val_y[indices]
if torch.cuda.is_available():
batch_x, batch_y = batch_x.cuda(), batch_y.cuda()
with torch.no_grad():
output = model(batch_x.cuda())
softmax = torch.exp(output).cpu()
prob = list(softmax.numpy())
predictions = np.argmax(prob, axis=1)
prediction_val.append(predictions)
target_val.append(batch_y)
# 验证集精度
accuracy_val = []
for i in range(len(prediction_val)):
accuracy_val.append(accuracy_score(target_val[i],prediction_val[i]))
print('validation accuracy: \t', np.average(accuracy_val))
Точность проверки значительно улучшилась до 73%. чудесный!
конец
В этом посте мы рассмотрим различные проблемы, с которыми можно столкнуться при использовании моделей глубокого обучения, таких как CNN. Мы также узнали решения всех этих сложных проблем и, в конце концов, построили модель, используя эти решения.
После того, как мы добавили эти методы в модель, точность модели на проверочном наборе улучшилась. Всегда есть место для улучшения, вот несколько вещей, которые вы можете попробовать:
- Отрегулируйте процент отсева
- Увеличьте или уменьшите количество сверточных слоев
- Увеличьте или уменьшите количество плотных слоев
- Отрегулируйте количество нейронов в скрытом слое и т. д.