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
模型的测试,其实主要区别就在**函数上,其它方面和我们之前了解的差别不大。然后我们发现光用线性函数似乎是不够的,所以我们需要更好的结构。敬请期待后续的教程吧!
上一篇: Oracle 导入 dmp 文件
下一篇: javascript函数怎么写