1. 참고사항
1. 기본 프레임워크, 기본 프레임워크 참조에 활성화 기능 및 표준화를 추가합니다.
합성곱 신경망 코드(CIFAR 이미지 분류) 및 Pytorch 기반 기본 프레임워크 - 프로그래머 구함
2. 데이터 셋 읽기 경로가 로컬에서 실행되도록 변경되어 현재 Kaggle 직접 학습은 지원하지 않습니다.Kaggle 서버를 실행해야 하는 경우 직접 읽기 경로를 변경해야 합니다.읽기 방법은 기본 프레임워크에 있습니다. .
3. 이 최적화 라운드는 활성화 기능과 표준화를 추가한 후의 개선만 비교합니다.
4. 서로 다른 최적화 방식의 효과를 비교하기 위해 학습률을 0.001로 설정
5. 최적화 전 기본 프레임워크에서 테스트 세트 정확도는 68.5, epoch = 165, 학습률 = 0.001
2. 최적화 과정
솔루션 1: 풀링 후 표준화 추가 및 relu 활성화 기능 추가
네트워크 구성 코드:
class Model(nn.Module):
def __init__(self):
super(Tudui, self).__init__()
self.model1 = nn.Sequential(
nn.Conv2d(3, 32, 5, padding=2),
nn.MaxPool2d(2), nn.BatchNorm2d(32), nn.ReLU(),
nn.Conv2d(32, 32, 5, padding=2),
nn.MaxPool2d(2), nn.BatchNorm2d(32), nn.ReLU(),
nn.Conv2d(32, 64, 5, padding=2),
nn.MaxPool2d(2), nn.BatchNorm2d(64), nn.ReLU(),
nn.Flatten(),
nn.Linear(1024, 64),# 182528
nn.Linear(64, 10)
)
효과:
![](https://img-blog.csdnimg.cn/3e284301037846799b0cf76c1c8fce15.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA55m-54K85oiQ5Li5,size_20,color_FFFFFF,t_70,g_se,x_16)
![](https://img-blog.csdnimg.cn/db20f2087e02453ab602e8646df92636.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA55m-54K85oiQ5Li5,size_20,color_FFFFFF,t_70,g_se,x_16)
![](https://img-blog.csdnimg.cn/caa4c088a4124ac28fdd99fd814fe71e.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA55m-54K85oiQ5Li5,size_20,color_FFFFFF,t_70,g_se,x_16)
![](https://img-blog.csdnimg.cn/90f47bc091084d669afeff0f3f637155.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA55m-54K85oiQ5Li5,size_15,color_FFFFFF,t_70,g_se,x_16)
결론 : 훈련 세트의 정확도는 100 epoch에서 99.8%에 도달했지만 이 시점에서 훈련 세트의 정확도는 떨어졌다. 10세대 시간은 79.76초입니다.
41 epoch에서 테스트 세트의 정확도는 최고치인 72%에 도달했지만 훈련 세트는 84.6%에 불과했습니다.
분석: 100배에서 명백한 오버피팅 현상이 있었고 훈련 후 0.7 부근에서 대략 안정됨
솔루션 2, 풀링 전에 표준화 추가 및 relu 활성화 기능 추가
네트워크 구성 코드:
class Model(nn.Module):
def __init__(self):
super(Tudui, self).__init__()
self.model1 = nn.Sequential(
nn.Conv2d(3, 32, 5, padding=2), nn.BatchNorm2d(32),
nn.MaxPool2d(2), nn.ReLU(),
nn.Conv2d(32, 32, 5, padding=2), nn.BatchNorm2d(32),
nn.MaxPool2d(2), nn.ReLU(),
nn.Conv2d(32, 64, 5, padding=2), nn.BatchNorm2d(64),
nn.MaxPool2d(2), nn.ReLU(),
nn.Flatten(),
nn.Linear(1024, 64),# 182528
nn.Linear(64, 10)
)
효과
![](https://img-blog.csdnimg.cn/a281788acde84097b50e65092d0680d1.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA55m-54K85oiQ5Li5,size_19,color_FFFFFF,t_70,g_se,x_16)
![](https://img-blog.csdnimg.cn/46038e30f58a47ba9d45f25b1fa3e545.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA55m-54K85oiQ5Li5,size_19,color_FFFFFF,t_70,g_se,x_16)
![](https://img-blog.csdnimg.cn/72678e400df9489aa24f886513c22b4a.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA55m-54K85oiQ5Li5,size_19,color_FFFFFF,t_70,g_se,x_16)
![](https://img-blog.csdnimg.cn/882d9d4338fd43deb9acda0cc40cb188.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA55m-54K85oiQ5Li5,size_19,color_FFFFFF,t_70,g_se,x_16)
결론 : 위에서 표준화된 BN 레이어를 풀링 앞에 추가했을 때 더 나은 성능 효과가 있음을 알 수 있으며 피크 값은 73.1%로 첫 번째 솔루션보다 약 1% 더 정확합니다. . 테스트 세트의 손실 함수는 먼저 감소한 다음 증가하며, 10세대 에포크 시간은 80.8초이고 체계 2는 79.76초입니다.
분석 : 여전히 과대적합이 발생하고 있으며, 풀링 전에 데이터를 표준화하고 있으나 시간이 크게 증가한 경우는 거의 없음
옵션 3. 옵션 2를 기준으로 relu를 prelu 활성화로 변경
네트워크 구축 코드
class Model(nn.Module):
def __init__(self):
super(Tudui, self).__init__()
self.model1 = nn.Sequential(
nn.Conv2d(3, 32, 5, padding=2), nn.BatchNorm2d(32),
nn.MaxPool2d(2), nn.PReLU(),
nn.Conv2d(32, 32, 5, padding=2), nn.BatchNorm2d(32),
nn.MaxPool2d(2), nn.PReLU(),
nn.Conv2d(32, 64, 5, padding=2), nn.BatchNorm2d(64),
nn.MaxPool2d(2), nn.PReLU(),
nn.Flatten(),
nn.Linear(1024, 64),# 182528
nn.Linear(64, 10)
)
효과: 피크값은 71.6%로 방법 1과 방법 2보다 수렴이 느리다.
결론: 여전히 과대적합이 발생하며 그 효과는 방법 1과 방법 2보다 나쁩니다.
3. 전체 코드(스킴 2를 예로 들어)
import torch
import torchvision
from torch import nn
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
import time
#../input/cifar10-python
train_data = torchvision.datasets.CIFAR10("../dataset", train=True, transform=torchvision.transforms.ToTensor())
test_data = torchvision.datasets.CIFAR10("../dataset", train=False, transform=torchvision.transforms.ToTensor())
train_dataloader = DataLoader(train_data, batch_size=64, drop_last=True)
test_dataloader = DataLoader(test_data, batch_size=64, drop_last=True)
# print(len(train_dataloader)) #781
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
test_data_size = len(test_dataloader) * 64
train_data_size = len(train_dataloader) * 64
print(f'测试集大小为:{test_data_size}')
print(f'训练集大小为:{train_data_size}')
writer = SummaryWriter("../model_logs")
loss_fn = nn.CrossEntropyLoss(reduction='mean')
loss_fn = loss_fn.to(device)
time_able = False # True
class Model(nn.Module):
def __init__(self):
super(Model, self).__init__()
self.model1 = nn.Sequential(
nn.Conv2d(3, 32, 5, padding=2), nn.BatchNorm2d(32),
nn.MaxPool2d(2), nn.ReLU(),
nn.Conv2d(32, 32, 5, padding=2), nn.BatchNorm2d(32),
nn.MaxPool2d(2), nn.ReLU(),
nn.Conv2d(32, 64, 5, padding=2), nn.BatchNorm2d(64),
nn.MaxPool2d(2), nn.ReLU(),
nn.Flatten(),
nn.Linear(1024, 64),# 182528
nn.Linear(64, 10)
)
def forward(self, x):
x = self.model1(x)
return x
model = Model()
model = model.to(device)
optimizer = torch.optim.SGD(model.parameters(), lr=0.001)
epoch = 100
running_loss = 0
total_train_step = 0
total_test_step = 0
if time_able:
str_time = time.time()
for i in range(epoch):
print(f'第{i + 1}次epoch')
total_accuracy1 = 0
for data in train_dataloader:
imgs, targets = data
imgs = imgs.to(device)
targets = targets.to(device)
output = model(imgs)
loss = loss_fn(output, targets)
optimizer.zero_grad()
loss.backward()
optimizer.step()
total_train_step += 1
if total_train_step % 200 == 0:
if time_able:
end_time = time.time()
print(f'{end_time-str_time}')
print(f'第{total_train_step}次训练,loss = {loss.item()}')
writer.add_scalar("train_loss", loss.item(), total_train_step)
accuracy1 = (output.argmax(1) == targets).sum()
total_accuracy1 += accuracy1
# 测试
total_test_loss = 0
total_accuracy = 0
with torch.no_grad():
for data in test_dataloader:
imgs, targets = data
imgs = imgs.to(device)
targets = targets.to(device)
outputs = model(imgs)
loss = loss_fn(outputs, targets)
total_test_loss = total_test_loss + loss
accuracy = (outputs.argmax(1) == targets).sum()
total_accuracy += accuracy
total_test_loss = total_test_loss / test_data_size
print(f'整体测试集上的loss = {total_test_loss}')
print(f'整体测试集正确率 = {total_accuracy / test_data_size}')
print(f'整体训练集正确率 = {total_accuracy1 / train_data_size}')
writer.add_scalar("test_loss", total_test_loss.item(), total_test_step)
writer.add_scalar("test_accuracy", total_accuracy / test_data_size, total_test_step)
writer.add_scalar("train_accuracy", total_accuracy1 / train_data_size, total_test_step) # test_step == epoch
total_test_step += 1
writer.close()