pytorch学习笔记(三)

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值