pytorch入门——边学边练03逻辑回归

访问本站观看效果更佳

写在前面

我们来探讨一下逻辑回归的问题吧!顺便把前面的知识点再整合一次!完整代码参见logistic_regression

什么是逻辑回归

我们先想想逻辑回归问题是什么样的一个问题。简单的说,Logistic Regression是一个解决0/1分类问题的方法。那么再往深处想一想,Logistics Regression的数学模型是什么?为什么我们可以实现0,1分类?逻辑回归(Logistic Regression)与线性回归(Linear Regression)都是一种广义线性模型(generalized linear model)。逻辑回归假设因变量 y 服从伯努利分布,而线性回归假设因变量 y 服从高斯分布。 因此与线性回归有很多相同之处,去除Sigmoid映射函数的话,逻辑回归算法就是一个线性回归。可以说,逻辑回归是以线性回归为理论支持的,但是逻辑回归通过Sigmoid函数引入了非线性因素,因此可以轻松处理0/1分类问题。
既然与线性如此相似,那么我们是否可以继续套用上一节使用的模型呢?似乎是可行的。

设定待解决的问题

深度学习最经典的hello world问题是什么?我说mnist手写分类问题,恐怕没几个人会反对吧!可是用逻辑回归解决mnist问题可行吗?当然是可行的。上文提到逻辑回归模型是一个广义线性模型,即使输入是图像矩阵,也是可行的。再说下输出,一个Sigmod函数可以输出0,1,那么处理多分类问题时,我们多设置几个Sigmod函数不就可以了吗?所以我们的大体思路就是nn.Linear加上几个Sigmod函数,开始动手吧~

具体实现

一如既往我们先导入所需要的包

import torch
import torch.nn as nn
import torchvision
import torchvision.transforms as transforms

设定一下超参数

# Hyper-parameters 
input_size = 784
num_classes = 10
num_epochs = 5
batch_size = 100
learning_rate = 0.001

加载数据,还是利用我们先前使用过的方法DataLoader,然后再去遍历每个batch

# MNIST dataset (images and labels)
train_dataset = torchvision.datasets.MNIST(root='../../data', 
                                           train=True, 
                                           transform=transforms.ToTensor(),
                                           download=True)

test_dataset = torchvision.datasets.MNIST(root='../../data', 
                                          train=False, 
                                          transform=transforms.ToTensor())

# Data loader (input pipeline)
train_loader = torch.utils.data.DataLoader(dataset=train_dataset, 
                                           batch_size=batch_size, 
                                           shuffle=True)

test_loader = torch.utils.data.DataLoader(dataset=test_dataset, 
                                          batch_size=batch_size, 
                                          shuffle=False)

下面我们来定制模型,前面说过我们就用线性模型解决问题,所以就像前两节讲的一样使用一个nn.Linear就足够了

# Logistic regression model
model = nn.Linear(input_size, num_classes)

接着需要设置Loss,注意前面的章节里,计算损失大多是利用MSE Loss(公式见复杂一些的例子),本节利用的是CrossEntropyLoss交叉熵函数。一般处理分类问题我们使用交叉熵函数,而处理回归问题我们使用MSE及与之类似的函数。在后面的章节里,会专门讲解信息熵在计算Loss时的应用,因为篇幅较长在此暂时跳过。

# Loss and optimizer
# nn.CrossEntropyLoss() computes softmax internally
criterion = nn.CrossEntropyLoss()  
optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate)  

我们来训练模型,各位读者是否还记得前面讲过的如何单步求导,如何设置多轮次的训练模型?我们再写一遍,和上一节中的代码是非常类似的。

# Train the model
total_step = len(train_loader)
for epoch in range(num_epochs):
    for i, (images, labels) in enumerate(train_loader):
        # Reshape images to (batch_size, input_size)
        images = images.reshape(-1, 28*28)
        
        # Forward pass
        outputs = model(images)
        loss = criterion(outputs, labels)
        
        # Backward and optimize
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        
        if (i+1) % 100 == 0:
            print ('Epoch [{}/{}], Step [{}/{}], Loss: {:.4f}' 
                   .format(epoch+1, num_epochs, i+1, total_step, loss.item()))

mnist数据集含有60000个训练样本,这里batch设置为了100,所以total_step也就是600。我们读取数据后为了使图像矩阵的大小和我们预设的nn.Linear输入一致,需要加一个reshape操作,-1是指自动调节剩余维度,在本例也就是图像通道数。
images送进model吧!然后计算损失,再反向传播,使Loss逐渐减小。

Epoch [1/5], Step [100/600], Loss: 2.1771
Epoch [1/5], Step [200/600], Loss: 2.1135
Epoch [1/5], Step [300/600], Loss: 1.9930
Epoch [1/5], Step [400/600], Loss: 1.9215
Epoch [1/5], Step [500/600], Loss: 1.8631
Epoch [1/5], Step [600/600], Loss: 1.8200
Epoch [2/5], Step [100/600], Loss: 1.7647
Epoch [2/5], Step [200/600], Loss: 1.6751
Epoch [2/5], Step [300/600], Loss: 1.5775
Epoch [2/5], Step [400/600], Loss: 1.5787
Epoch [2/5], Step [500/600], Loss: 1.5148
Epoch [2/5], Step [600/600], Loss: 1.5332
Epoch [3/5], Step [100/600], Loss: 1.4024
Epoch [3/5], Step [200/600], Loss: 1.3784
Epoch [3/5], Step [300/600], Loss: 1.4034
Epoch [3/5], Step [400/600], Loss: 1.2751
Epoch [3/5], Step [500/600], Loss: 1.2699
Epoch [3/5], Step [600/600], Loss: 1.2829
Epoch [4/5], Step [100/600], Loss: 1.2370
Epoch [4/5], Step [200/600], Loss: 1.2452
Epoch [4/5], Step [300/600], Loss: 1.1577
Epoch [4/5], Step [400/600], Loss: 1.1664
Epoch [4/5], Step [500/600], Loss: 1.0990
Epoch [4/5], Step [600/600], Loss: 1.0721
Epoch [5/5], Step [100/600], Loss: 1.0359
Epoch [5/5], Step [200/600], Loss: 1.0466
Epoch [5/5], Step [300/600], Loss: 1.0024
Epoch [5/5], Step [400/600], Loss: 0.9867
Epoch [5/5], Step [500/600], Loss: 1.0728
Epoch [5/5], Step [600/600], Loss: 0.9967

我们看到最后结果就开始抖动了,说明Linear的表达能力还是不够啊,那么模型正确率有多少呢?

# Test the model
# In test phase, we don't need to compute gradients (for memory efficiency)
with torch.no_grad():
    correct = 0
    total = 0
    for images, labels in test_loader:
        images = images.reshape(-1, 28*28)
        outputs = model(images)
        _, predicted = torch.max(outputs.data, 1)
        total += labels.size(0)
        correct += (predicted == labels).sum()

    print('Accuracy of the model on the 10000 test images: {} %'.format(100 * correct / total))

结果如下

Accuracy of the model on the 10000 test images: 83 %

最后别忘了保存一下模型

# Save the model checkpoint
torch.save(model.state_dict(), 'model.ckpt')

小结

今天我们用一个逻辑回归模型进行了mnist模型的测试,其实主要区别就在激活函数上,其它方面和我们之前了解的差别不大。然后我们发现光用线性函数似乎是不够的,所以我们需要更好的结构。敬请期待后续的教程吧!

猜你喜欢

转载自blog.csdn.net/zcgyq/article/details/83088067