官网链接:The CIFAR-10 dataset
# download cifar-10 datasets
train_set = torchvision.datasets.CIFAR10('./data',train=True,transform=transform,download=True)
test_set = torchvision.datasets.CIFAR10('./data',train=False,transform=transform,download=True)
参数说明:
# 没有进行ToTensor()的数据集
train_set
----------------------OUT---------------------
Dataset CIFAR10
Number of datapoints: 50000
Root location: ./data
Split: Train
train_set[1]
----------------------OUT---------------------
(<PIL.Image.Image image mode=RGB size=32x32 at 0x122A0F150>, 9)
需要注意的是,我们下载下来的CIFAR-10数据集的格式是PIL文件,而送入CNN中进行训练的都是Tensor格式的数据,所以先要对数据集中的图片进行transform成Tensor类型的数据
train_set
----------------------OUT---------------------
Dataset CIFAR10
Number of datapoints: 50000
Root location: ./data
Split: Train
StandardTransform
Transform: Compose(
ToTensor()
)
train_set[1]
----------------------OUT---------------------
(tensor([[[0.6039, 0.4941, 0.4118, ..., 0.3569, 0.3412, 0.3098],
[0.5490, 0.5686, 0.4902, ..., 0.3765, 0.3020, 0.2784],
[0.5490, 0.5451, 0.4510, ..., 0.3098, 0.2667, 0.2627],
...,
[[0.7333, 0.5333, 0.3725, ..., 0.2784, 0.2784, 0.2745],
[0.6627, 0.6039, 0.4627, ..., 0.3059, 0.2431, 0.2392],
[0.6431, 0.5843, 0.4392, ..., 0.2510, 0.2157, 0.2157],
...,
[0.6510, 0.6275, 0.6667, ..., 0.1412, 0.2235, 0.3569],
[0.5020, 0.5098, 0.5569, ..., 0.3765, 0.4706, 0.5137],
[0.4706, 0.4784, 0.5216, ..., 0.5451, 0.5569, 0.5647]]]),
9)
import pickle
import os
def unpickle(file):
with open(file, 'rb') as fo:
dict = pickle.load(fo, encoding='bytes')
return dict
file = os.getcwd()+'data/cifar-10-batches-py/data_batch_1'
data_batch_1_dict = unpickle(file)
每个batch文件包含一个字典,每个字典包含有:
数据集除了6个batch之外,还有一个文件batches.meta。它包含一个python字典对象,内容有:
一个包含10个元素的列表,每一个描述了labels array中每个数字对应类标的名字。比如:label_names[0] == “airplane”, label_names[1] == “automobile”
torch.utils.data中的Dataloader(注意这个D是大写)模块可以很方便的将dataset装载起来,相当于一个数据读取器,使其可以iterable方便对数据集进行处理
# 创建训练/测试加载器,
# trainset/testset -- 数据集
# batch_size -- 不解释
# shuffle -- 是否打乱顺序
# num_workers -- 子进程数
dataloaders = { x:torch.utils.data.DataLoader(datasets[x],batch_size=BATCH_SIZE,
shuffle=True,num_workers=NUM_WORKERS,pin_memory=True)
for x in ['train_set','test_set']
}
# 显示单个图片
def imshow(inp,title=None):
inp = inp.numpy().transpose(1,2,0)
plt.imshow(inp)
if title is not None:
plt.title(title)
# plt.pause(0.1)
# 显示一个batch的图片
def visualize_batch():
(inputs,classes) = next(iter(dataloaders['train_set'])) # 读取一个batch的数据
for num in range(inputs.shape[0]):
plt.subplot(4,8,num+1)
imshow(inputs[num],class_names[classes[num].item()])
Conv2d
H o u t = ⌊ H i n + 2 ∗ p a d d i n g [ 0 ] − d i l a t i o n [ 0 ] × ( k e r n e l s i z e [ 0 ] − 1 ) − 1 s t r i d e [ 0 ] + 1 ⌋ H_{out} =⌊\frac{H_{in}+2∗padding[0]−dilation[0]×(kernel_{size}[0]−1)−1}{ stride[0]}+1⌋ Hout=⌊stride[0]Hin+2∗padding[0]−dilation[0]×(kernelsize[0]−1)−1+1⌋
Maxpool2d
H o u t = ⌊ H i n + 2 ∗ p a d d i n g [ 0 ] − d i l a t i o n [ 0 ] × ( k e r n e l s i z e [ 0 ] − 1 ) − 1 s t r i d e [ 0 ] + 1 ⌋ H_{out} =⌊\frac{H_{in}+2∗padding[0]−dilation[0]×(kernel_{size}[0]−1)−1}{ stride[0]}+1⌋ Hout=⌊stride[0]Hin+2∗padding[0]−dilation[0]×(kernelsize[0]−1)−1+1⌋
import torch
from torch import nn
import torchvision
from torchvision import transforms
import torch.nn.functional as F
class AlexNet(nn.Module):
def __init__(self):
super(AlexNet, self).__init__()
self.Conv = nn.Sequential(
# IN : 3*32*32
nn.Conv2d(in_channels=3,out_channels=96,kernel_size=5,stride=2,padding=2), # 论文中kernel_size = 11,stride = 4,padding = 2
nn.ReLU(),
# IN : 96*16*16
nn.MaxPool2d(kernel_size=2,stride=2), # 论文中为kernel_size = 3,stride = 2
# IN : 96*8*8
nn.Conv2d(in_channels=96, out_channels=256, kernel_size=5, stride=1, padding=2),
nn.ReLU(),
# IN :256*8*8
nn.MaxPool2d(kernel_size=2,stride=2), # 论文中为kernel_size = 3,stride = 2
# IN : 256*4*4
nn.Conv2d(in_channels=256, out_channels=384, kernel_size=3, stride=1, padding=1),
nn.ReLU(),
# IN : 384*4*4
nn.Conv2d(in_channels=384, out_channels=384, kernel_size=3, stride=1, padding=1),
nn.ReLU(),
# IN : 384*4*4
nn.Conv2d(in_channels=384, out_channels=384, kernel_size=3, stride=1, padding=1),
nn.ReLU(),
# IN : 384*4*4
nn.MaxPool2d(kernel_size=2, stride=2), # 论文中为kernel_size = 3,stride = 2
# OUT : 384*2*2
)
self.linear = nn.Sequential(
nn.Linear(in_features=384 * 2 * 2, out_features=4096),
nn.ReLU(),
nn.Linear(in_features=4096, out_features=4096),
nn.ReLU(),
nn.Linear(in_features=4096, out_features=10),
)
def forward(self,x):
x = self.Conv(x)
x = x.view(-1, 384 * 2 * 2)
x = self.linear(x)
return x
# 显示网络参数量
def Init_net():
model = AlexNet()
data_input = Variable(torch.randn(8,3,32,32))
print(data_input.size())
model(data_input)
print(summary(model,(3,32,32)))
torch.Size([8, 3, 32, 32])
----------------------------------------------------------------
Layer (type) Output Shape Param #
================================================================
Conv2d-1 [-1, 96, 16, 16] 7,296
ReLU-2 [-1, 96, 16, 16] 0
MaxPool2d-3 [-1, 96, 8, 8] 0
Conv2d-4 [-1, 256, 8, 8] 614,656
ReLU-5 [-1, 256, 8, 8] 0
MaxPool2d-6 [-1, 256, 4, 4] 0
Conv2d-7 [-1, 384, 4, 4] 885,120
ReLU-8 [-1, 384, 4, 4] 0
Conv2d-9 [-1, 384, 4, 4] 1,327,488
ReLU-10 [-1, 384, 4, 4] 0
Conv2d-11 [-1, 384, 4, 4] 1,327,488
ReLU-12 [-1, 384, 4, 4] 0
MaxPool2d-13 [-1, 384, 2, 2] 0
Linear-14 [-1, 4096] 6,295,552
ReLU-15 [-1, 4096] 0
Linear-16 [-1, 4096] 16,781,312
ReLU-17 [-1, 4096] 0
Linear-18 [-1, 10] 40,970
================================================================
Total params: 27,279,882
Trainable params: 27,279,882
Non-trainable params: 0
----------------------------------------------------------------
Input size (MB): 0.01
Forward/backward pass size (MB): 1.12
Params size (MB): 104.06
Estimated Total Size (MB): 105.20
----------------------------------------------------------------
None
cost_fun = nn.CrossEntropyLoss() # 选择交叉熵作为损失函数
optimizer = torch.optim.SGD(net.parameters(),lr=1e-3) # 选择SGD作为优化器
参数说明:
def train_model(model,criterion,optimizer,scheduler,num_epochs=25):
since = time.time()
best_acc = 0.0
for epoch in range(num_epochs):
print('Epoc{}/{}'.format(epoch,num_epochs-1))
print('-'*10)
# epoch一次完成后切换到测试phase
for phase in ['train','test']:
if phase == 'train':
model.train() # 切换到train mode
else:
model.eval()
running_loss = 0.0
running_corrects = 0
# Iterate over data
for inputs,labels in tqdm(dataloaders[phase]):
inputs = inputs.to(device)
labels = labels.to(device)
optimizer.zero_grad() # 梯度清零
# forward
with torch.set_grad_enabled(phase == 'train'):
outputs = model(inputs)
_,preds = torch.max(outputs,1)
loss = criterion(outputs,labels)
# backward + optimize only if in trainning phase
if phase == 'train':
loss.backward()
optimizer.step()
# statistics
running_loss += loss.item() * inputs.size(0)
running_corrects += torch.sum(preds==labels.data)
if phase == 'train':
epoch_loss = running_loss / dataset_sizes[phase]
epoch_acc = running_corrects.double() / dataset_sizes[phase]
print('{} Loss: {:.4f} Acc: {:.4f}'.format(phase,epoch_loss,epoch_acc))
lr = next(iter(optimizer.param_groups))['lr']
print(lr)
writer.add_scalar('Train/Loss',epoch_loss,epoch)
writer.add_scalar('Train/Acc',epoch_acc,epoch)
else:
epoch_loss = running_loss / dataset_sizes[phase]
epoch_acc = running_corrects.double() / dataset_sizes[phase]
print('{} Loss: {:.4f} Acc: {:.4f}'.format(phase,epoch_loss,epoch_acc))
writer.add_scalar('Test/Loss',epoch_loss,epoch)
writer.add_scalar('Test/Acc',epoch_acc,epoch)
if epoch_acc > best_acc:
best_acc = epoch_acc
lr_list.append(optimizer.state_dict()['param_groups'][0]['lr'])
lr_scheduler.step() # 更新
print()
writer.close()
time_elapsed = time.time() - since
print('Trainning complete in {:.0f}m {:.0f}s'.format(
time_elapsed // 60 , time_elapsed % 60
))
print('Best test Acc: {:4f}'.format(best_acc))
return model
# 只保存网络中训练好的权重文件
def save_state():
print('===> Saving models...')
state = {
'state': net.state_dict(),
'epoch': epoch # 将epoch一并保存
}
if not os.path.isdir('checkpoint'): # 如果没有这个目录就创建一个
os.mkdir('./checkpoint')
torch.save(state, path_model + 'Epoch:' + str(epoch) + ' Loss:' +
str(train_loss[-1].item()) + '.pth')
参考文章:
https://blog.csdn.net/qq_41185868/article/details/82793025
https://blog.csdn.net/qq_30129009/article/details/98772599?ops_request_misc=&request_id=&biz_id=102&utm_term=alexnet%20%20torch&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduweb~default-0-98772599.pc_search_result_hbase_insert
实验记录:
使用lenet+adam lr=1e-4 结果最好的为54%, loss=1.3284
使用alexnet+adam lr=1e-4 结果最好是69.2%,test_loss=5.7270,train_loss=0,过拟合了
使用alexnet+adam lr=1e-4+dropout0.5 69.6% test_loss=4.0592
使用alexnet+adam lr=1e-4+dropout0.5+weight_decay=5e-4 Best test Acc: 0.675800 test Loss: 2.2339