基于resnet框架结构实现caltech256数据集图片分类过拟合了怎么办?
resnet框架我是从李沐《动手学深度学习》搬的,然后书中由于用的时mnist数据集,是1通道的,我的数据集是3通道,所以修改了通道数。
My_train函数是将d2l.train_ch6复制过来稍作修改的。
代码如下:
import torch
from torch import nn
from torch.nn import functional as F
# from d2l import torch as d2l
import d2l
from d2l import torch as d2l
from torchvision import transforms
from torch.utils.data import Dataset, DataLoader
from PIL import Image
import os
# 残差
class Residual(nn.Module): #@save
def __init__(self, input_channels, num_channels,
use_1x1conv=False, strides=1):
super().__init__()
self.conv1 = nn.Conv2d(input_channels, num_channels,
kernel_size=3, padding=1, stride=strides)
self.conv2 = nn.Conv2d(num_channels, num_channels,
kernel_size=3, padding=1)
if use_1x1conv:
self.conv3 = nn.Conv2d(input_channels, num_channels,
kernel_size=1, stride=strides)
else:
self.conv3 = None
self.bn1 = nn.BatchNorm2d(num_channels)
self.bn2 = nn.BatchNorm2d(num_channels)
def forward(self, X):
Y = F.relu(self.bn1(self.conv1(X)))
Y = self.bn2(self.conv2(Y))
if self.conv3:
X = self.conv3(X)
Y += X
return F.relu(Y)
b1 = nn.Sequential(nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3),
nn.BatchNorm2d(64), nn.ReLU(),
nn.MaxPool2d(kernel_size=3, stride=2, padding=1))
def resnet_block(input_channels, num_channels, num_residuals,
first_block=False):
blk = []
for i in range(num_residuals):
if i == 0 and not first_block:
blk.append(Residual(input_channels, num_channels,
use_1x1conv=True, strides=2))
else:
blk.append(Residual(num_channels, num_channels))
return blk
b2 = nn.Sequential(*resnet_block(64, 64, 2, first_block=True))
b3 = nn.Sequential(*resnet_block(64, 128, 2))
b4 = nn.Sequential(*resnet_block(128, 256, 2))
b5 = nn.Sequential(*resnet_block(256, 512, 2))
net = nn.Sequential(b1, b2, b3, b4, b5,
nn.AdaptiveAvgPool2d((1,1)),
nn.Flatten(), nn.Linear(512, 257))
root='/Users/hh/PycharmProjects/DeepLearning/'
def default_loader(path):
return Image.open(path).convert('RGB')
class MyDataset(Dataset):
def __init__(self, txt, transform=None, target_transform=None, loader=default_loader):
fh = open(txt, 'r', encoding='UTF-8')
imgs = []
for line in fh:
line = line.rstrip()
line = line.strip('\n')
line = line.rstrip()
words = line.split()
imgs.append((words[0],int(words[1])))
self.imgs = imgs
self.transform = transform
self.target_transform = target_transform
self.loader = loader
def __getitem__(self, index):
fn, label = self.imgs[index]
img = self.loader(fn)
if self.transform is not None:
img = self.transform(img)
return img,label
def __len__(self):
return len(self.imgs)
mean = [ 0.485, 0.456, 0.406 ]
std = [ 0.229, 0.224, 0.225 ]
transform = transforms.Compose([
transforms.Resize(256),
transforms.CenterCrop(224),
transforms.ToTensor(),
transforms.Normalize(mean = mean, std = std),
])
train_data = MyDataset(txt=root+'dataset-trn.txt', transform=transform)
test_data = MyDataset(txt=root+'dataset-val.txt', transform=transform)
train_loader = DataLoader(dataset=train_data, batch_size=64, shuffle=True)
test_loader = DataLoader(dataset=test_data, batch_size=64)
def My_train(net, train_iter, test_iter, num_epochs, lr,
device=d2l.try_gpu()):
# def My_train(net, train_iter, test_iter, num_epochs, device=d2l.try_gpu()):
def init_weights(m):
if type(m) == nn.Linear or type(m) == nn.Conv2d:
torch.nn.init.xavier_uniform_(m.weight)
# 保存参数
save_path = './resnet02.pth'
if os.path.exists(save_path):
weights_dict = torch.load(save_path, map_location=device)
load_weights_dict = {k: v for k, v in weights_dict.items()
if net.state_dict()[k].numel() == v.numel()}
net.load_state_dict(load_weights_dict, strict=False)
print('using resnet pretrain-weights.')
else:
print("not using pretrain-weights.")
print('training on', device)
net.to(device)
optimizer = torch.optim.SGD(net.parameters(), lr=lr,momentum=0.9,weight_decay=0.00006)
loss = nn.CrossEntropyLoss()
timer, num_batches = d2l.Timer(), len(train_iter)
# 最优参数
best_accu=0
for epoch in range(num_epochs):
# Sum of training loss, sum of training accuracy, no. of examples
print("epoch:%d" % epoch)
metric = d2l.Accumulator(3)
for i, (X, y) in enumerate(train_iter):
timer.start()
net.train()
optimizer.zero_grad()
X, y = X.to(device), y.to(device)
y_hat = net(X)
l = loss(y_hat, y)
l.backward()
optimizer.step()
with torch.no_grad():
metric.add(l * X.shape[0], d2l.accuracy(y_hat, y), X.shape[0])
timer.stop()
train_l = metric[0] / metric[2]
train_acc = metric[1] / metric[2]
test_acc = d2l.evaluate_accuracy_gpu(net, test_iter)
if test_acc > best_accu:
best_accu = test_acc
torch.save(net.state_dict(), save_path)
print("save")
print(f'loss {train_l:.3f}, train acc {train_acc:.3f}, '
f'test acc {test_acc:.3f}')
print(f'loss {train_l:.3f}, train acc {train_acc:.3f}, '
f'test acc {test_acc:.3f}')
print(f'{metric[2] * num_epochs / timer.sum():.1f} examples/sec '
f'on {str(device)}')
lr, num_epochs, batch_size = 0.05, 15, 512
train_iter, test_iter = train_loader, test_loader
My_train(net, train_iter, test_iter, num_epochs, lr, d2l.try_gpu())
输出:
epoch:44
loss 0.002, train acc 1.000, test acc 0.425
epoch:45
loss 0.002, train acc 1.000, test acc 0.424
epoch:46
loss 0.002, train acc 1.000, test acc 0.426
epoch:47
loss 0.002, train acc 1.000, test acc 0.430
epoch:48
loss 0.002, train acc 1.000, test acc 0.424
epoch:49
loss 0.002, train acc 1.000, test acc 0.425
过拟合了,不知道怎么修改,有没有人帮帮忙,谢谢大家T-T
简单的看了一下 确实过拟合了
代码需要优化
你试试把学习率调小为0.01:
python
lr = 0.01试试