1.神经网络
首先定义一个网络:
# 定义一个网络
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = nn.Conv2d(1, 6, 5)
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 = F.max_pool2d(F.relu(self.conv1(x)), (2, 2))
x = F.max_pool2d(F.relu(self.conv2(x)), 2)
x = x.view(-1, self.num_flatten_features(x))
x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
x = self.fc3(x)
return x
def num_flatten_features(self, x):
size = x.size()[1:]
num_features = 1
for s in size:
num_features = num_features * s
return num_features
可以查看一下网络的参数:
net = Net()
print(net)
Net(
(conv1): Conv2d(1, 6, kernel_size=(5, 5), stride=(1, 1))
(conv2): Conv2d(6, 16, kernel_size=(5, 5), stride=(1, 1))
(fc1): Linear(in_features=400, out_features=120, bias=True)
(fc2): Linear(in_features=120, out_features=84, bias=True)
(fc3): Linear(in_features=84, out_features=10, bias=True)
)
# 查看一下网络的参数
parms = list(net.parameters())
for p in parms:
print(p.size())
torch.Size([6, 1, 5, 5])
torch.Size([6])
torch.Size([16, 6, 5, 5])
torch.Size([16])
torch.Size([120, 400])
torch.Size([120])
torch.Size([84, 120])
torch.Size([84])
torch.Size([10, 84])
torch.Size([10])
之后看一下网络的输出是什么样的:
# 输入一个(1, 1, 32, 32)的tensor, 得到一个输出
input = torch.randn(1, 1, 32, 32)
output = net(input)
print(output)
output.shape
tensor([[ 0.0476, -0.1101, 0.0313, -0.0317, 0.0934, -0.0156, -0.0314, 0.0333,
0.0541, -0.0064]], grad_fn= < AddmmBackward> )
使用SDG进行反向传播并更新权重:
import torch.optim as optim
# 创建一个优化器
optimizer = optim.SGD(net.parameters(), lr=0.001)
# 在训练的时候迭代
optimizer.zero_grad()
outputt = net(input)
loss = criterion(target, outputt)
loss.backward()
optimizer.step()
print(net.conv1.bias.grad)
tensor([-0.0065, -0.0036, 0.0090, -0.0074, 0.0044, 0.0002])
2.训练分类器
有了以上的一点点知识后,接下来训练一个图片分类器:
- 通过torchvision训练数据和测试数据,并对其进行标准化处理
# 先将数据转换为tensor,再将其标准化到(-1. 1)
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 = ('plane', 'car', 'bird', 'cat',
'deer', 'dog', 'frog', 'horse', 'ship', 'truck')
- 定义一个网络
class Net(nn.Module):
def __init__(self):
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()
- 定义损失函数和优化策略
# 定义损失函数和优化器, 使用交叉熵定义损失函数,使用随机梯度下降进行优化
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)
- 利用训练数据进行训练
for epoch in range(2):
running_loss = 0.0
for i, data in enumerate(trainloader, 0):
img, labels = data
optimizer.zero_grad()
pre = net(img)
loss = criterion(pre, labels)
loss.backward()
optimizer.step()
running_loss += loss.item()
if i % 2000 == 0:
print('[epoch:%d, iteartion:%5d]:loss = %f' % (epoch, i, running_loss / 2000))
running_loss = 0.0
print('finish training')
[epoch:0, iteartion: 0]:loss = 0.000771
[epoch:0, iteartion: 2000]:loss = 1.535242
[epoch:0, iteartion: 4000]:loss = 1.512504
[epoch:0, iteartion: 6000]:loss = 1.451304
[epoch:0, iteartion: 8000]:loss = 1.397936
[epoch:0, iteartion:10000]:loss = 1.343793
[epoch:0, iteartion:12000]:loss = 1.326585
[epoch:1, iteartion: 0]:loss = 0.000421
[epoch:1, iteartion: 2000]:loss = 1.249600
[epoch:1, iteartion: 4000]:loss = 1.241016
[epoch:1, iteartion: 6000]:loss = 1.223059
[epoch:1, iteartion: 8000]:loss = 1.235657
[epoch:1, iteartion:10000]:loss = 1.218032
[epoch:1, iteartion:12000]:loss = 1.195369
finish training
- 最后利用测试数据测试一下训练后的性能
先简单的看一下效果:
# ground truth
dataiter = iter(testloader)
img, labels = dataiter.next()
print('ground truth:', ''.join('%5s ' % classes[labels[j]] for j in range(4)))
ground truth: cat ship ship plane
# predict
outputs = net(img)
_, predict = torch.max(outputs, 1)
print('predict:', ''.join('%5s ' % classes[predict[j]] for j in range(4)))
predict: cat truck truck plane
乍一看效果还真不怎么样。。。
# 在测试集上测试一下效果
total = 0
correct = 0
with torch.no_grad():
for data in testloader:
img, labels = data
output = net(img)
_, predict = torch.max(output, 1)
total += labels.size(0)
correct += (predict == labels).sum().item()
print('accuracy: %f' % (correct / total))
accuracy: 0.537700
果然真的不怎么样。。。
接下来查看一下是哪些类的预测效果不理想:
# 看一下各个类预测的准确性
class_num = list(0.for i in range(10))
class_correct = list(9.for i in range(10))
with torch.no_grad():
for data in testloader:
img, labels = data
output = net(img)
_, predict = torch.max(output, 1)
c = (predict == labels).squeeze()
for i in range(4):
class_num[labels[i]] += 1
class_correct[labels[i]] += c[i].item()
for i in range(10):
print('%5s: %f' % (classes[i], class_correct[i] / class_num[i]))
plane: 0.616000
car: 0.402000
bird: 0.293000
cat: 0.286000
deer: 0.552000
dog: 0.487000
frog: 0.682000
horse: 0.704000
ship: 0.618000
truck: 0.827000