图片分类器-初步建立简单模型

使用pytorch框架。

使用CIFAR10数据集, 图片数据大小3*32*32

加载并标准化数据

导入包

1
2
3
import torch
import torchvision
import torchvision.transforms as transforms

导入数据并标准化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from enum import Flag
from logging import root
from random import shuffle
from turtle import down


transform = 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=False, transform=transform)
testset = torchvision.datasets.CIFAR10(root='./data', train=False, download=False, transform=transform)

trainloader = torch.utils.data.DataLoader(trainset, batch_size=4, shuffle=True, num_workers=2)
testloader = torch.utils.data.DataLoader(testset, batch_size=4, shuffle=False, num_workers=2)

classes = ('plain', 'car', 'bird', 'cat',
'deer', 'dog', 'frog', 'horse', 'ship', 'truck')

配置设备

1
2
3
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")

print(device)
cuda:0

构建神经网络模型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
from turtle import forward
import torch.nn as nn
import torch.nn.functional as F

class Net(nn.Module):
def __init__(self) -> None:
super(Net, self).__init__()
self.conv1 = nn.Conv2d(3, 6, 5)
self.pool = nn.MaxPool2d(2, 2)
self.conv2 = nn.Conv2d(6, 16, 5)
self.fc1 = nn.Linear(16*5*5, 120)
self.fc2 = nn.Linear(120, 84)
self.fc3 = nn.Linear(84, 10)

def forward(self, x):
x = self.pool(F.relu(self.conv1(x)))
x = self.pool(F.relu(self.conv2(x)))
x = x.view(-1, 16*5*5)
x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
x = self.fc3(x)
return x

net = Net()
net = net.to(device)

定义损失函数和优化器

1
2
3
4
import torch.optim as optim

criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)

初步训练网络

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
for epoch in range(2):

running_loss = 0.0
for i, data in enumerate(trainloader, 0):
inputs, labels = data
inputs, labels = inputs.to(device), labels.to(device)

optimizer.zero_grad()

outputs = net(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()

running_loss += loss.item()
if i % 2000 == 1999:
print('[%d, %5d] loss: %.3f' % (epoch+1, i+1, running_loss/2000))
running_loss = 0.0

[1,  2000] loss: 1.185
[1,  4000] loss: 1.199
[1,  6000] loss: 1.180
[1,  8000] loss: 1.177
[1, 10000] loss: 1.164
[1, 12000] loss: 1.156
[2,  2000] loss: 1.083
[2,  4000] loss: 1.094
[2,  6000] loss: 1.095
[2,  8000] loss: 1.086
[2, 10000] loss: 1.086
[2, 12000] loss: 1.083

可以看到损失有在正确下降

训练和验证

修改一下代码, 每一轮训练中加入验证。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
from imghdr import tests
from msilib import datasizemask


dataloaders = {
'train': trainloader,
'valid': testloader

}
dataset_sizes = {
'train' : trainset.data.shape[0],
'valid': testset.data.shape[0]
}
for epoch in range(10):
print('Epoch {}/{}'.format(epoch, 9))
print('-'*10)

for phase in ['train', 'valid']:
if phase == 'train':
net.train(True)
else:
net.train(False)

running_loss = 0.0
running_corrects = 0

for data in dataloaders[phase]:
inputs, labels = data
inputs, labels = inputs.to(device), labels.to(device)
optimizer.zero_grad()

outputs = net(inputs)
loss = criterion(outputs, labels)
_, preds = torch.max(outputs.data, 1)

if phase == 'train':
loss.backward()
optimizer.step()

running_loss += loss.item()
running_corrects += torch.sum(preds == labels.data)

epoch_loss = running_loss / dataset_sizes[phase]
epoch_acc = running_corrects / dataset_sizes[phase]

print('{} Loss: {:.4f} Acc: {:.4f}'.format(phase, epoch_loss, epoch_acc))


Epoch 0/9
----------
train Loss: 0.2568 Acc: 0.6373
valid Loss: 0.2746 Acc: 0.6204
Epoch 1/9
----------
train Loss: 0.2426 Acc: 0.6585
valid Loss: 0.2782 Acc: 0.6150
Epoch 2/9
----------
train Loss: 0.2312 Acc: 0.6738
valid Loss: 0.2725 Acc: 0.6286
Epoch 3/9
----------
train Loss: 0.2236 Acc: 0.6827
valid Loss: 0.2706 Acc: 0.6312
Epoch 4/9
----------
train Loss: 0.2136 Acc: 0.6965
valid Loss: 0.2773 Acc: 0.6221
Epoch 5/9
----------
train Loss: 0.2072 Acc: 0.7040
valid Loss: 0.2901 Acc: 0.6130
Epoch 6/9
----------
train Loss: 0.2005 Acc: 0.7132
valid Loss: 0.2922 Acc: 0.6229
Epoch 7/9
----------
train Loss: 0.1956 Acc: 0.7229
valid Loss: 0.2950 Acc: 0.6200
Epoch 8/9
----------
train Loss: 0.1898 Acc: 0.7292
valid Loss: 0.3046 Acc: 0.6161
Epoch 9/9
----------
train Loss: 0.1859 Acc: 0.7321
valid Loss: 0.3106 Acc: 0.6163

可以看到随着训练进行, 训练集准确度不断增加, 但测试集准确度没有提高, 模型开始过拟合。