用PyTorch的逻辑回归实现图像分类

数据集来自MNIST手写数字数据库。它由手写数字(0到9)的28px乘28px灰度图像以及每个图像的标签组成。

导入torch、torchvision和MNIST

看一下lengh:

这个数据集有60000张图片,可以用来训练模型。还有一个10,000个图像的附加测试集,可以通过将train= False传递给MNIST类来创建。

组内变量逻辑回归模型_逻辑回归算法_sklearn逻辑回归算法

该图像是PIL.Image.Image类的对象,由28×28图像和标签组成。PIL是Python成像库Pillow。

逻辑回归算法_组内变量逻辑回归模型_sklearn逻辑回归算法

我们可以使用matplotlib在Jupyter中查看图像,matplotlib是Python中数据科学的事实绘图和图形库。

先看数据集里的几个图片:

sklearn逻辑回归算法_逻辑回归算法_组内变量逻辑回归模型

组内变量逻辑回归模型_逻辑回归算法_sklearn逻辑回归算法

除了导入matplotlib之外,还添加了一个特殊声明%matplotlib inline,告知Jupyter要在Notebook中绘制图形。

没有这个声明的话,Jupyter将在弹出窗口中显示图像。以%开头的语句称为IPython magic命令,用于配置Jupyter本身的行为。

PyTorch无法直接处理图像,需要将图像转换成tensor。

PyTorch数据集允许我们指定一个或多个转换函数,这些函数在加载时应用于图像。

torchvision.transforms包含许多这样的预定义函数,我们将使用ToTensor变换将图像转换为PyTorchtensor。

组内变量逻辑回归模型_逻辑回归算法_sklearn逻辑回归算法

现在图像转换为1x28x28的tensor。第一个维度用于跟踪颜色通道。由于MNIST数据集中的图像是灰度级的,因此只有一个通道。 其他数据集具有彩色图像,在这种情况下有3个通道:红色,绿色和蓝色(RGB)。

让我们看一下tensor内的一些样本值:

逻辑回归算法_组内变量逻辑回归模型_sklearn逻辑回归算法

0表示黑色,1表示白色,中间的值表示不同的灰度。嗯还可以使用plt.imshow将tensor绘制为图像。

组内变量逻辑回归模型_sklearn逻辑回归算法_逻辑回归算法

请注意,我们只需要将28×28矩阵传递给plt.imshow,而不需要通道尺寸。

我们还传递了一个颜色映射(cmap =’gray’),表示我们想要查看灰度图像。

训练和验证数据集

在构建真实世界的机器学习模型时,将数据集分成3个部分是很常见的:

训练集:用于训练模型,即计算损失并使用梯度下降调整模型的权重 验证集:用于在训练时评估模型,调整超参数(学习率等)并选择最佳版本的模型 测试集:用于比较不同的模型或不同类型的建模方法,并报告模型的最终准确性

在MNIST数据集中,有60,000个训练图像和10,000个测试图像。测试集是标准化的,以便不同的研究人员可以针对同一组图像报告其模型的结果。

由于没有预定义的验证集,我们必须手动将60,000个图像拆分为训练和验证数据集

让我们定义一个函数,随机选择验证集的图像的给定部分。

sklearn逻辑回归算法_逻辑回归算法_组内变量逻辑回归模型

split_indices随机地混洗数组索引0,1,… n-1,并从中为验证集分离出所需的部分。

在创建验证集之前对索引进行混洗是很重要的,因为训练图像通常由目标标签排序,即0s的图像,然后是1s的图像,接着是2s的图像,依此类推。

如果我们仅通过选择最后20%的图像来选择20%的验证集,则验证集将仅包括8s和9s的图像逻辑回归算法,而训练集将不包含8s和9s的图像,这样就不可能训练一个好的模型。

我们随机调整了指数,并选择了一小部分(20%)作为验证集。

现在可以使用SubsetRandomSampler为每个创建PyTorch数据加载器,SubsetRandomSampler从给定的索引列表中随机采样元素,同时创建batch数据。

逻辑回归算法_sklearn逻辑回归算法_组内变量逻辑回归模型

模型

现在我们已经准备好了数据加载器,我们可以定义我们的模型。

逻辑回归算法_组内变量逻辑回归模型_sklearn逻辑回归算法

我们看看权重和偏差

组内变量逻辑回归模型_逻辑回归算法_sklearn逻辑回归算法

组内变量逻辑回归模型_sklearn逻辑回归算法_逻辑回归算法

虽然这里我们的额参数量编程了7850个,但总的思路是类似的。我们从的数据集中,取得第一个batch,包含100张图片,传递给模型。

直接输出的话报错。因为我们的输入数据的形状不正确。我们的图像形状为1x28x28,但我们需要它们是784的矢量。

即我们需要将它们“展评”。我们将使用一个tensor的.reshape方法,这将允许我们有效地“查看”每个图像作为平面向量,而无需真正更改基础数据。

要在我们的模型中包含此附加功能,我们需要通过从PyTorch扩展nn.Module类来定义自定义模型。

sklearn逻辑回归算法_组内变量逻辑回归模型_逻辑回归算法

在__init__构造函数方法中,我们使用nn.Linear实例化权重和偏差。

在我们将一批输入传递给模型时调用的forward方法中,我们将输入tensor展平,然后将其传递给self.linear。

xb.reshape(-1,28 * 28)向PyTorch指明,我们想要具有两个维度的xbtensor的视图,其中沿第二维度的长度是28 * 28(即784)。

.reshape的一个参数可以设置为-1(在这种情况下是第一个维度),让PyTorch根据原始tensor的形状自动计算出来。

请注意,模型不再具有.weight和.bias属性(因为它们现在位于.linear属性中),但它确实有一个.parameters方法,该方法返回包含权重和偏差的列表,并且可以使用PyTorch优化器。

sklearn逻辑回归算法_组内变量逻辑回归模型_逻辑回归算法

我们的新自定义模型可以像以前一样使用。 让我们看看它是否有效。

sklearn逻辑回归算法_组内变量逻辑回归模型_逻辑回归算法

对于100个输入图像中的每一个,我们得到10个输出,每个类别一个。 如前所述,我们希望这些输出表示概率,但是为此,每个输出行的元素必须介于0到1之间并且加起来为1,这显然不是这里的情况。

要将输出行转换为概率,我们使用softmax函数,它具有以下公式:

逻辑回归算法_组内变量逻辑回归模型_sklearn逻辑回归算法

首先,我们将输出行中的每个元素yi替换为e ^ yi,这使得所有元素都为正,然后我们将每个元素除以所有元素的总和,以确保它们加起来为1。

虽然很容易实现softmax函数,我们将使用PyTorch中提供的实现,因为它适用于多维tensor(在我们的例子中是输出行列表)。

softmax函数包含在torch.nn.functional包中,并要求我们指定必须应用softmax的维度。

逻辑回归算法_sklearn逻辑回归算法_组内变量逻辑回归模型

最后,我们可以通过简单地选择每个输出行中具有最高概率的元素的索引来确定每个图像的预测标签。

这是使用torch.max完成的,它返回最大元素和沿tensor的特定维度的最大元素的索引。

逻辑回归算法_sklearn逻辑回归算法_组内变量逻辑回归模型

上面打印的数字是第一批训练图像的预测标签。 我们将它们与实际标签进行比较。

逻辑回归算法_组内变量逻辑回归模型_sklearn逻辑回归算法

显然,预测标签和实际标签完全不同。这是因为我们已经开始使用随机初始化的权重和偏差。

我们需要训练模型,即使用梯度下降调整权重以做出更好的预测。

评估度量和损失函数

与线性回归一样,我们需要一种方法来评估模型的执行情况。一种自然的方法是找到正确预测的标签百分比,即预测的准确性。

==运算符执行具有相同形状的两个tensor的逐元素比较,并返回相同形状的tensor,对于不相等的元素包含0,对于相等的元素包含1。

将结果传递给torch.sum会返回正确预测的标签数。最后,我们除以图像总数来获得准确性。

让我们计算第一批数据的当前模型的准确性。显然,我们预计它会非常糟糕。

虽然精度是我们(人类)评估模型的好方法,但它不能用作使用梯度下降优化模型的损失函数,原因如下:

这不是一个可区分的功能。torch.max和==都是非连续和非可微操作,因此我们无法使用精度来计算重量和偏差的梯度它没有考虑模型预测的实际概率,因此无法为渐进式改进提供足够的反馈

由于这些原因,准确性是分类的一个很好的评估指标,但不是一个好的损失函数。 分类问题常用的损失函数是交叉熵,其具有以下公式:

组内变量逻辑回归模型_sklearn逻辑回归算法_逻辑回归算法

虽然它看起来很复杂,但实际上非常简单:

与准确度不同,交叉熵是一种连续且可微分的函数,它还为模型中的渐进改进提供了良好的反馈(正确标签导致较低损失的概率略高)。这使它成为损失函数的一个很好的选择。

PyTorch提供了一种有效且张量友好的交叉熵实现,作为torch.nn.functionalpackage的一部分。

此外,它还在内部执行softmax,因此我们可以直接传递模型的输出而不将它们转换为概率。

sklearn逻辑回归算法_组内变量逻辑回归模型_逻辑回归算法

由于交叉熵是在所有训练样本上平均的正确标签的预测概率的负对数,因此一种解释结果数的方法,例如,2.23是e ^ -2.23,平均值约为0.1,作为正确标签的预测概率。降低损失,改善模型。

优化

我们将使用optim.SGD优化器在训练期间更新权重和偏差,但学习率更高,为1e-3。

组内变量逻辑回归模型_sklearn逻辑回归算法_逻辑回归算法

batch大小,学习率等参数需要在训练机器学习模型时提前选取,并称为超参数。

选择正确的超参数对于在合理的时间内训练准确的模型至关重要,并且是研究和实验的活跃领域。随意尝试不同的学习率,看看它如何影响训练过程。

训练模型

现在我们已经定义了数据加载器,模型,损失函数和优化器,我们已准备好训练模型。

训练过程几乎与线性回归相同。但是,我们将增加我们之前定义的拟合函数,以使用每个epoch末尾的验证集来评估模型的准确性和损失。

我们首先定义一个函数loss_batch:

组内变量逻辑回归模型_逻辑回归算法_sklearn逻辑回归算法

优化器是一个可选参数,以确保我们可以重用loss_batch来计算验证集上的损失。

我们还将batch处理的长度作为结果的一部分返回,因为它在组合整个数据集的损失/度量时非常有用。

接下来,我们定义一个函数evaluate,它计算验证集的总体损失。

逻辑回归算法_组内变量逻辑回归模型_sklearn逻辑回归算法

如果不能立即清楚此函数的作用,请尝试在单独的单元格中执行每个语句,然后查看结果。

我们还需要重新定义精确度以直接操作整批输出,以便我们可以将其用作拟合度量。

逻辑回归算法_sklearn逻辑回归算法_组内变量逻辑回归模型

请注意,我们不需要将softmax应用于输出,因为它不会更改结果的相对顺序。

这是因为e ^ x是增加函数,即如果y1> y2,则e ^ y1> e ^ y2,并且在对值求平均值以获得softmax之后也是如此。

让我们看看模型如何使用初始权重和偏差集在验证集上执行。

逻辑回归算法_组内变量逻辑回归模型_sklearn逻辑回归算法

初始准确度低于10%,这是人们对随机初始化模型的预期(因为它有十分之一的机会通过随机猜测获得标签)。

另请注意,我们使用.format方法和消息字符串仅打印小数点后的前四位数。

我们现在可以使用loss_batch和evaluate轻松定义拟合函数。

逻辑回归算法_sklearn逻辑回归算法_组内变量逻辑回归模型

我们现在准备训练模型。 让我们训练5个epoch并观察结果。

组内变量逻辑回归模型_逻辑回归算法_sklearn逻辑回归算法

不错哦!来更多点eploch

组内变量逻辑回归模型_sklearn逻辑回归算法_逻辑回归算法

线图更直观的显示一下效果

逻辑回归算法_sklearn逻辑回归算法_组内变量逻辑回归模型

从上面的图片中可以清楚地看出,即使经过很长时间的训练,该模型也可能不会超过90%的准确度阈值。

一个可能的原因是学习率可能太高。模型的参数可能会围绕具有最低损耗的最佳参数集“弹跳”。

您可以尝试降低学习速度和训练几个epoch,看看它是否有帮助。

更可能的原因是该模型不够强大。如果你还记得我们的初始假设,我们假设输出(在这种情况下是类概率)是输入(像素强度)的线性函数,通过对权重矩阵执行矩阵乘法并添加偏差来获得。

这是一个相当弱的假设,因为图像中的像素强度和它所代表的数字之间可能实际上不存在线性关系。

虽然它对于像MNIST这样的简单数据集(使我们达到85%的准确度)工作得相当好,但我们需要更复杂的模型来捕捉图像像素和标签之间的非线性关系,以便识别日常物品逻辑回归算法,动物等复杂任务。

使用单个图像进行测试

虽然到目前为止我们一直在跟踪模型的整体精度,但在一些样本图像上查看模型的结果也是一个好主意。

让我们用10000个图像的预定义测试数据集中的一些图像测试我们的模型。 我们首先使用ToTensor变换重新创建测试数据集。

sklearn逻辑回归算法_逻辑回归算法_组内变量逻辑回归模型

数据集中单个图像的样本:

让我们定义一个辅助函数predict_image,它返回单个图像张量的预测标签。

sklearn逻辑回归算法_逻辑回归算法_组内变量逻辑回归模型

img.unsqueeze只是在1x28x28张量的开始处添加另一个维度,使其成为1x1x28x28张量,模型将其视为包含单个图像的批处理。

逻辑回归算法_组内变量逻辑回归模型_sklearn逻辑回归算法

sklearn逻辑回归算法_组内变量逻辑回归模型_逻辑回归算法

通过收集更多的训练数据,增加/减少模型的复杂性以及更改超参数,确定我们的模型表现不佳的位置可以帮助我们改进模型。

最后,让我们看看测试集上模型的整体损失和准确性。

sklearn逻辑回归算法_逻辑回归算法_组内变量逻辑回归模型

我们希望这与验证集上的准确度/损失相似。如果没有,我们可能需要一个更好的验证集,它具有与测试集类似的数据和分布(通常来自现实世界数据)。

保存并加载模型

由于我们已经长时间训练模型并获得了合理的精度,因此将权重和偏置矩阵保存到磁盘是个好主意,这样我们可以在以后重用模型并避免从头开始重新训练。以下是保存模型的方法。

.state_dict方法返回一个OrderedDict,其中包含映射到模型右侧属性的所有权重和偏置矩阵。

sklearn逻辑回归算法_逻辑回归算法_组内变量逻辑回归模型

要加载模型权重,我们可以实例化MnistModel类的新对象,并使用.load_state_dict方法。

sklearn逻辑回归算法_组内变量逻辑回归模型_逻辑回归算法

正如完整性检查一样,让我们验证此模型在测试集上具有与以前相同的损失和准确性。

逻辑回归算法_组内变量逻辑回归模型_sklearn逻辑回归算法

好了。大功告成了。又到了我们的commit环节。以防你已经忘记了怎么操作:

参考链接:

【2019新智元 AI 技术峰会倒计时16天】

2019年的3月27日,新智元再汇AI之力,在北京泰富酒店举办AI开年盛典——2019新智元AI技术峰会。峰会以“智能云•芯世界“为主题,聚焦智能云和AI芯片的发展,重塑未来AI世界格局。

同时,新智元将在峰会现场权威发布若干AI白皮书,聚焦产业链的创新活跃,评述华人AI学者的影响力,助力中国在世界级的AI竞争中实现超越。

购票二维码

活动行购票链接:2019新智元AI技术峰会–智能云•芯世界_精彩城市生活,尽在活动行!!

限时特惠:本站每日持续更新海量设计资源,一年会员只需29.9元,全站资源免费下载
站长微信:ziyuanshu688