1. 什么是逻辑回归
逻辑回归是一种广泛使用的分类器。分类器是一个算法,它使用特征向量(通常称为x)将将数据点 分类为不同的类,例如1、2或3。通常,我们在使用分类器时用y表示我们想要预测的类。
逻辑回归的目标是根据给定的一些特征,将数据点分为2个类
逻辑回归算法使用函数来将输入特征和预测的输出值联系起来。这些函数称为“激活函数”或“sigmoid函数”。Sigmoid函数本身非常简单。该函数由以下公式给出:
def sigmoid(x):
return 1 / (1 + torch.exp(-x))
sigmoid函数将任何实数映射到区间[0, 1]中的一个值,这样我们就可以将输出解释为概率。例如,如果我们要判断一张照片里的物品是不是一只猫,逻辑回归可以输出一个概率值,如果这个概率值大于0.5,我们就认为这张照片里看到的是一只猫。
2. 数据预处理
2.1 数据集加载
我们将使用pytorch的自带手写数字数据集MNIST。MNIST数据集包含60,000个用于训练和10,000个用于测试的手写数字示例。我们可以使用以下代码将数据集载入PyTorch,并定义一些转换以标准化输入图像:
import torch
from torch.utils.data import DataLoader
from torchvision import datasets, transforms
# 数据转换
transform = transforms.Compose([
transforms.ToTensor(), # 将数据转换成torch张量
transforms.Normalize((0.5, ), (0.5, )) # 归一化
])
# 加载训练数据
trainset = datasets.MNIST(
root='data/',
train=True,
download=True,
transform=transform
)
trainloader = DataLoader(
trainset,
batch_size=64,
shuffle=True
)
# 加载测试数据
testset = datasets.MNIST(
root='data/',
train=False,
download=True,
transform=transform
)
testloader = DataLoader(
testset,
batch_size=64,
shuffle=True
)
2.2 数据可视化
数据集可以使用Matplotlib进行可视化。
import matplotlib.pyplot as plt
images, labels = next(iter(trainloader))
plt.imshow(images[0].numpy().squeeze(), cmap='gray_r')
plt.title(str(labels[0].item()))
plt.show()
根据结果可以看到,我们得到了一个手写数字图像和该图像对应的标签。
3. 构建模型
要使用PyTorch构建逻辑回归模型,需要创建继承自nn.Module的模型,并在__init__函数中定义隐藏层的大小(输入维数和输出维数)和Sigmoid层:
from torch import nn
class LogisticRegression(nn.Module):
def __init__(self):
super(LogisticRegression, self).__init__()
self.linear1 = nn.Linear(784, 512) # 输入维度为28*28=784,输出维度为512
self.linear2 = nn.Linear(512, 128) # 输出维度为128
self.linear3 = nn.Linear(128, 10) # 输出维度为10
self.sigmoid = nn.Sigmoid()
def forward(self, x):
x = self.sigmoid(self.linear1(x)) # 隐藏层1:Sigmoid(x * weight + bias)
x = self.sigmoid(self.linear2(x)) # 隐藏层2:Sigmoid(x * weight + bias)
x = self.linear3(x) # 输出层:x * weight + bias
return x
模型架构如下:
LogisticRegression(
(linear1): Linear(in_features=784, out_features=512, bias=True)
(linear2): Linear(in_features=512, out_features=128, bias=True)
(linear3): Linear(in_features=128, out_features=10, bias=True)
(sigmoid): Sigmoid()
)
4. 定义损失函数和优化器
要定义损失函数,我们使用交叉熵作为目标函数。在PyTorch中,有一个功能称为“nn.CrossEntropyLoss()”,它可以在模型输出和期望输出之间计算交叉熵。
有几个优化器可以在PyTorch中使用,包括SGD、Adam和Adagrad等。我们将使用Adam优化器:
learning_rate = 0.001
# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)
5. 训练模型
现在我们终于准备好训练我们的模型了。我们将在训练数据集上使用模型进行训练,然后在测试数据集上进行评估。PyTorch使训练和评估非常容易。
import torch.nn.functional as F
total_step = len(trainloader)
num_epochs = 10
for epoch in range(num_epochs):
for i, (images, labels) in enumerate(trainloader):
# 将张量调整为784维的向量并将0-1的图像转换为-1到1之间的值
images = images.view(-1, 28*28)
images = (images - 0.5) * 2
# 向模型传递输入
outputs = model(images)
# 计算损失值
loss = criterion(outputs, labels)
# 清空梯度
optimizer.zero_grad()
# 反向传播和优化
loss.backward()
optimizer.step()
# 每100个batch打印一次训练状态
if (i+1) % 100 == 0:
print ('Epoch [{}/{}], Step [{}/{}], Loss: {:.4f}'
.format(epoch+1, num_epochs, i+1, total_step, loss.item()))
运行结果如下:
Epoch [1/10], Step [100/938], Loss: 0.4734
Epoch [1/10], Step [200/938], Loss: 0.2864
Epoch [1/10], Step [300/938], Loss: 0.3573
Epoch [1/10], Step [400/938], Loss: 0.4332
Epoch [1/10], Step [500/938], Loss: 0.2347
Epoch [1/10], Step [600/938], Loss: 0.3576
Epoch [1/10], Step [700/938], Loss: 0.1910
Epoch [1/10], Step [800/938], Loss: 0.2556
Epoch [1/10], Step [900/938], Loss: 0.2741
Epoch [2/10], Step [100/938], Loss: 0.1974
Epoch [2/10], Step [200/938], Loss: 0.2118
Epoch [2/10], Step [300/938], Loss: 0.2906
Epoch [2/10], Step [400/938], Loss: 0.2006
Epoch [2/10], Step [500/938], Loss: 0.3036
Epoch [2/10], Step [600/938], Loss: 0.2008
Epoch [2/10], Step [700/938], Loss: 0.1561
Epoch [2/10], Step [800/938], Loss: 0.1506
Epoch [2/10], Step [900/938], Loss: 0.2447
Epoch [3/10], Step [100/938], Loss: 0.2022
Epoch [3/10], Step [200/938], Loss: 0.2669
Epoch [3/10], Step [300/938], Loss: 0.0517
Epoch [3/10], Step [400/938], Loss: 0.1444
Epoch [3/10], Step [500/938], Loss: 0.1569
Epoch [3/10], Step [600/938], Loss: 0.1654
Epoch [3/10], Step [700/938], Loss: 0.2206
Epoch [3/10], Step [800/938], Loss: 0.1651
Epoch [3/10], Step [900/938], Loss: 0.1248
Epoch [4/10], Step [100/938], Loss: 0.1171
Epoch [4/10], Step [200/938], Loss: 0.2148
Epoch [4/10], Step [300/938], Loss: 0.2085
Epoch [4/10], Step [400/938], Loss: 0.1758
Epoch [4/10], Step [500/938], Loss: 0.2142
Epoch [4/10], Step [600/938], Loss: 0.1893
Epoch [4/10], Step [700/938], Loss: 0.1438
Epoch [4/10], Step [800/938], Loss: 0.1558
Epoch [4/10], Step [900/938], Loss: 0.1655
Epoch [5/10], Step [100/938], Loss: 0.1676
Epoch [5/10], Step [200/938], Loss: 0.1935
Epoch [5/10], Step [300/938], Loss: 0.1319
Epoch [5/10], Step [400/938], Loss: 0.1198
Epoch [5/10], Step [500/938], Loss: 0.1087
Epoch [5/10], Step [600/938], Loss: 0.1734
Epoch [5/10], Step [700/938], Loss: 0.0975
Epoch [5/10], Step [800/938], Loss: 0.0986
Epoch [5/10], Step [900/938], Loss: 0.1509
Epoch [6/10], Step [100/938], Loss: 0.1663
Epoch [6/10], Step [200/938], Loss: 0.1157
Epoch [6/10], Step [300/938], Loss: 0.0542
Epoch [6/10], Step [400/938], Loss: 0.1429
Epoch [6/10], Step [500/938], Loss: 0.1428
Epoch [6/10], Step [600/938], Loss: 0.1166
Epoch [6/10], Step [700/938], Loss: 0.1500
Epoch [6/10], Step [800/938], Loss: 0.1614
Epoch [6/10], Step [900/938], Loss: 0.1257
Epoch [7/10], Step [100/938], Loss: 0.0780
Epoch [7/10], Step [200/938], Loss: 0.1527
Epoch [7/10], Step [300/938], Loss: 0.0767
Epoch [7/10], Step [400/938], Loss: 0.1028
Epoch [7/10], Step [500/938], Loss: 0.0815
Epoch [7/10], Step [600/938], Loss: 0.1039
Epoch [7/10], Step [700/938], Loss: 0.0908
Epoch [7/10], Step [800/938], Loss: 0.1013
Epoch [7/10], Step [900/938], Loss: 0.0977
Epoch [8/10], Step [100/938], Loss: 0.0443
Epoch [8/10], Step [200/938], Loss: 0.1171
Epoch [8/10], Step [300/938], Loss: 0.0893
Epoch [8/10], Step [400/938], Loss: 0.1235
Epoch [8/10], Step [500/938], Loss: 0.0858
Epoch [8/10], Step [600/938], Loss: 0.0964
Epoch [8/10], Step [700/938], Loss: 0.1956
Epoch [8/10], Step [800/938], Loss: 0.0784
Epoch [8/10], Step [900/938], Loss: 0.1079
Epoch [9/10], Step [100/938], Loss: 0.1038
Epoch [9/10], Step [200/938], Loss: 0.0431
Epoch [9/10], Step [300/938], Loss: 0.1246
Epoch [9/10], Step [400/938], Loss: 0.1199
Epoch [9/10], Step [500/938], Loss: 0.1456
Epoch [9/10], Step [600/938], Loss: 0.1238
Epoch [9/10], Step [700/938], Loss: 0.1275
Epoch [9/10], Step [800/938], Loss: 0.1513
Epoch [9/10], Step [900/938], Loss: 0.1011
Epoch [10/10], Step [100/938], Loss: 0.1043
Epoch [10/10], Step [200/938], Loss: 0.0608
Epoch [10/10], Step [300/938], Loss: 0.0960
Epoch [10/10], Step [400/938], Loss: 0.1052
Epoch [10/10], Step [500/938], Loss: 0.0582
Epoch [10/10], Step [600/938], Loss: 0.0633
Epoch [10/10], Step [700/938], Loss: 0.0626
Epoch [10/10], Step [800/938], Loss: 0.0665
Epoch [10/10], Step [900/938], Loss: 0.0427
6. 测试模型
测试的过程与训练的过程基本相同,只是数据源改为测试集,不会对模型参数进行更新
# 计算测试集上的准确率
correct = 0
total = 0
for images, labels in testloader:
images = images.reshape(-1, 28*28)
images = (images - 0.5) * 2
outputs = model(images)
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
correct += (predicted == labels).sum().item()
print('Accuracy of the model on the 10000 test images: {} %'.format(100 * correct / total))
输出结果如下:
Accuracy of the model on the 10000 test images: 97.88 %
7. 总结
在本文中,我们介绍了如何使用PyTorch实现逻辑回归算法,并使用PyTorch自带数据集MNIST进行了训练和测试。在完成本文后,您现在应该已经熟悉了PyTorch的基本概念以及如何构建模型并训练和测试它们。
未来,您可以尝试在此基础上添加更多隐藏层数,调整学习率、批处理大小等超参数来提高模型的性能。祝您好运!