PyTorch入门一文学会线性回归逻辑回归及图像分类
【导读】本文通过详实的代码,从如何安装PyTorch开始,一步一步带领读者熟悉PyTorch和JupyterNotebook,最终使用PyTorch实现线性回归、逻辑回归以及图像分类,非常适合0基础初学者。
今天为大家带来一份非常详尽的PyTorch教程。本文共分3大部分:安装PyTorch和JupyterNotebook用PyTorch实现线性回归使用逻辑回归实现图像分类
文章超长,秉承用代码搞定一切的原则,内含大量代码,建议收藏,并分享给你喜欢的人。同时如果有什么疑问,也欢迎留言告知我们。
Tips:为了方便演示,文中代码和返回结果是用截图形式给出。本系列中的所有代码都以JupyterNotebook形式提供,托管在Jovian。托管链接:
https:jvn。ioaakashnse5cfe043873f4f3c9287507016747ae5
安装PyTorch和JupyterNotebook
我们将使用Anaconda的Python发行版来安装库和管理虚拟环境,对于交互式编码和实验,我们将使用JupyterNotebook。
首先按照官方教程安装Anaconda,接下来安装jovian:pipinstalljovianupgrade
下载针对本教程的notebook:jovianclonee5cfe043873f4f3c9287507016747ae5
此时会创建一个01pytorchbasics的目录,包含01pytorchbasics。ipynb和environment。yml文件。cd01pytorchbasicscondaenvupdate
目的是不破坏本地Python环境,使用一个虚拟环境。接下来激活condaactivate01pytorchbasics
启动Jupyterjupyternotebook
打开浏览器,输入http:localhost:8888。然后点有01pytorchbasics。ipynb字样的就开始了。
本质上PyTorch是处理Tensor的库。所以我们先来简单看下tensor类型:
因为很多时候我们需要在NumPy的数组和PyTorch数组之间进行转换。
Commit并上传:
上传的项目还可以用jovianclone下载回来。操作类似git,这里不再累述。
简单的开场之后,我们直接进入硬核阶段。
用PyTorch实现线性回归
对于线性回归,相信大家都很熟悉了,各种机器学习的书第一个要讲的内容必定有线性回归。
这一部分,我们首先通过最原始的手动操作,来理解整个线性回归的原理和操作程。
接着我们会再介绍使用PyTorch内置的函数,通过自动化的方式实现线性回归。
线性回归模型中,每个目标变量都被估算为输入变量的加权和及偏差。
先看一张表:
表格第一列是地区,第二类是温度单位华氏度,第二列是降水量单位毫米,第四列是湿度,第五列是苹果产量,第六列是橙子产量。
下面这段代码的目的是为了预估出苹果和橙子在不同地区、不同环境中的产量。yieldapplew11tempw12rainfallw13humidityb1yieldorangew21tempw22rainfallw23humidityb2
分别个温度temp、降水量rainfall、湿度humidity加上不同的权重(w11,w12,w13),最后再加一个b1或者b2的偏差。
通过使用被称为梯度下降的优化技术,少量多次调整权重以获得更精准的预测结果。
训练数据
在JupyterNotebook里导入NumPy和PyTorch
训练数据我们inputs和targets两个矩阵表示,每个观察一行,每个变量一列。
接下来转换成PyTorch的tensors:
变量和偏差也用矩阵表示,从随机数值开始
模型可以表示为
我们这样定义模型:
生成预测
对比一下原始数据
发现差距很大,因为一开始我们用的是随机数值,所以数据合不上很正常。
接下来我们需要通过损失函数,来评估我们的模型和实际差距多大。分为3个步骤计算两个矩阵(preds和targets)之间的差异平方差矩阵的所有元素以消除负值计算结果矩阵中元素的平均值
最终结果为均方误差MSE
计算梯度:
使用PyTorch可以自动计算损耗的梯度或导数w。r。t。权重和偏差,因为requiresgrad被设置为True。
计算权重梯度:
重置梯度:
使用梯度下降调整重量和偏差
我们将使用梯度下降优化算法减少损失并改进我们的模型,该算法具有以下步骤:
生成预测计算损失计算梯度w。r。t权重和偏差通过减去与梯度成比例的小量来调整权重将渐变重置为零让我们逐步实现上述步骤
接下来分别用代码表示:
最终效果:
再来看看损失:
说明有进步。那么我们就重复上面的过程,把损失减到最小。每词重复,我们成为1个epoch。我们先来100个epoch:
再看看效果:
损失很低了。print一下结果:
用PyTorch内置函数实现线性回归
了解了上述原理后,我们就可以用PyTorch内置的函数,简化我们的工作量。
接下来我们创建一个TensorDataset和一个DataLoader:
TensorDataset允许我们使用数组索引表示法(上面代码中的〔0:3〕)访问训练数据的一小部分。它返回一个元组(或对),其中第一个元素包含所选行的输入变量,第二个元素包含目标。
用forin循环就可以了
用nn。linear自动初始化
刚开始我们是手动随机输入的初识权重。现在我们可以使用nn。linear自动完成初始化工作。
对于我们的线性回归模型,我们有一个权重矩阵和一个偏差矩阵。
接下来我们重复上面的流程,首先通过损失函数计算出差距,接着不断的降低损失。
以及用内置损失函数mseloss:
优化的时候,我们可以使用优化器optim。SGD,不用手动操作模型的权重和偏差。
SGD代表随机梯度下降。它被称为随机因为样本是分批选择的(通常是随机抽样)而不是单个组。
训练模型,思路上面已经讲过了,直接看代码
上面要注意的一些事项:
我们使用前面定义的数据加载器来获取每次迭代的batch数据我们不是手动更新参数(权重和偏差),而是使用opt。step来执行更新,而使用opt。zerograd将梯度重置为零我们还添加了一个日志语句,用于打印每10个时期最后一批数据的丢失,以跟踪训练的进度。loss。item返回存储在损失tensor中的实际值
来100个epoch
结果:
对比一下:
Commit并上传
现在可以将你的代码上传到我们的Notebook了。看了这么多代码估计你可能已经忘记怎么Commit了。
用PyTorch的逻辑回归实现图像分类
数据集来自MNIST手写数字数据库。它由手写数字(0到9)的28px乘28px灰度图像以及每个图像的标签组成。
导入torch、torchvision和MNIST
看一下lengh:
这个数据集有60000张图片,可以用来训练模型。还有一个10,000个图像的附加测试集,可以通过将trainFalse传递给MNIST类来创建。
该图像是PIL。Image。Image类的对象,由28x28图像和标签组成。PIL是Python成像库Pillow。
我们可以使用matplotlib在Jupyter中查看图像,matplotlib是Python中数据科学的事实绘图和图形库。
先看数据集里的几个图片:
除了导入matplotlib之外,还添加了一个特殊声明matplotlibinline,告知Jupyter要在Notebook中绘制图形。
没有这个声明的话,Jupyter将在弹出窗口中显示图像。以开头的语句称为IPythonmagic命令,用于配置Jupyter本身的行为。
PyTorch无法直接处理图像,需要将图像转换成tensor。
PyTorch数据集允许我们指定一个或多个转换函数,这些函数在加载时应用于图像。
torchvision。transforms包含许多这样的预定义函数,我们将使用ToTensor变换将图像转换为PyTorchtensor。
现在图像转换为1x28x28的tensor。第一个维度用于跟踪颜色通道。由于MNIST数据集中的图像是灰度级的,因此只有一个通道。其他数据集具有彩色图像,在这种情况下有3个通道:红色,绿色和蓝色(RGB)。
让我们看一下tensor内的一些样本值:
0表示黑色,1表示白色,中间的值表示不同的灰度。嗯还可以使用plt。imshow将tensor绘制为图像。
请注意,我们只需要将28x28矩阵传递给plt。imshow,而不需要通道尺寸。
我们还传递了一个颜色映射(cmapgray),表示我们想要查看灰度图像。
训练和验证数据集
在构建真实世界的机器学习模型时,将数据集分成3个部分是很常见的:
训练集:用于训练模型,即计算损失并使用梯度下降调整模型的权重验证集:用于在训练时评估模型,调整超参数(学习率等)并选择最佳版本的模型测试集:用于比较不同的模型或不同类型的建模方法,并报告模型的最终准确性
在MNIST数据集中,有60,000个训练图像和10,000个测试图像。测试集是标准化的,以便不同的研究人员可以针对同一组图像报告其模型的结果。
由于没有预定义的验证集,我们必须手动将60,000个图像拆分为训练和验证数据集
让我们定义一个函数,随机选择验证集的图像的给定部分。
splitindices随机地混洗数组索引0,1,。。。n1,并从中为验证集分离出所需的部分。
在创建验证集之前对索引进行混洗是很重要的,因为训练图像通常由目标标签排序,即0s的图像,然后是1s的图像,接着是2s的图像,依此类推。
如果我们仅通过选择最后20的图像来选择20的验证集,则验证集将仅包括8s和9s的图像,而训练集将不包含8s和9s的图像,这样就不可能训练一个好的模型。
我们随机调整了指数,并选择了一小部分(20)作为验证集。
现在可以使用SubsetRandomSampler为每个创建PyTorch数据加载器,SubsetRandomSampler从给定的索引列表中随机采样元素,同时创建batch数据。
模型
现在我们已经准备好了数据加载器,我们可以定义我们的模型。
逻辑回归模型几乎与线性回归模型相同,即存在权重和偏差矩阵,并且使用简单矩阵运算(predxw。t()b)获得输出就像我们使用线性回归一样,我们可以使用nn。Linear来创建模型,而不是手动定义和初始化矩阵由于nn。Linear期望每个训练示例都是一个tensor,因此每个1x28x28图像tensor需要在传递到模型之前被展平为大小为784(2828)的tensor每个图像的输出是大小为10的tensor,tensor的每个元素表示特定目标标记(即0到9)的概率。图像的预测标签只是具有最高概率的标签
我们看看权重和偏差
虽然这里我们的额参数量编程了7850个,但总的思路是类似的。我们从的数据集中,取得第一个batch,包含100张图片,传递给模型。
直接输出的话报错。因为我们的输入数据的形状不正确。我们的图像形状为1x28x28,但我们需要它们是784的矢量。
即我们需要将它们展评。我们将使用一个tensor的。reshape方法,这将允许我们有效地查看每个图像作为平面向量,而无需真正更改基础数据。
要在我们的模型中包含此附加功能,我们需要通过从PyTorch扩展nn。Module类来定义自定义模型。
在init构造函数方法中,我们使用nn。Linear实例化权重和偏差。
在我们将一批输入传递给模型时调用的forward方法中,我们将输入tensor展平,然后将其传递给self。linear。
xb。reshape(1,2828)向PyTorch指明,我们想要具有两个维度的xbtensor的视图,其中沿第二维度的长度是2828(即784)。
。reshape的一个参数可以设置为1(在这种情况下是第一个维度),让PyTorch根据原始tensor的形状自动计算出来。
请注意,模型不再具有。weight和。bias属性(因为它们现在位于。linear属性中),但它确实有一个。parameters方法,该方法返回包含权重和偏差的列表,并且可以使用PyTorch优化器。
我们的新自定义模型可以像以前一样使用。让我们看看它是否有效。
对于100个输入图像中的每一个,我们得到10个输出,每个类别一个。如前所述,我们希望这些输出表示概率,但是为此,每个输出行的元素必须介于0到1之间并且加起来为1,这显然不是这里的情况。
要将输出行转换为概率,我们使用softmax函数,它具有以下公式:
首先,我们将输出行中的每个元素yi替换为eyi,这使得所有元素都为正,然后我们将每个元素除以所有元素的总和,以确保它们加起来为1。
虽然很容易实现softmax函数,我们将使用PyTorch中提供的实现,因为它适用于多维tensor(在我们的例子中是输出行列表)。
softmax函数包含在torch。nn。functional包中,并要求我们指定必须应用softmax的维度。
最后,我们可以通过简单地选择每个输出行中具有最高概率的元素的索引来确定每个图像的预测标签。
这是使用torch。max完成的,它返回最大元素和沿tensor的特定维度的最大元素的索引。
上面打印的数字是第一批训练图像的预测标签。我们将它们与实际标签进行比较。
显然,预测标签和实际标签完全不同。这是因为我们已经开始使用随机初始化的权重和偏差。
我们需要训练模型,即使用梯度下降调整权重以做出更好的预测。
评估度量和损失函数
与线性回归一样,我们需要一种方法来评估模型的执行情况。一种自然的方法是找到正确预测的标签百分比,即预测的准确性。
运算符执行具有相同形状的两个tensor的逐元素比较,并返回相同形状的tensor,对于不相等的元素包含0,对于相等的元素包含1。
将结果传递给torch。sum会返回正确预测的标签数。最后,我们除以图像总数来获得准确性。
让我们计算第一批数据的当前模型的准确性。显然,我们预计它会非常糟糕。
虽然精度是我们(人类)评估模型的好方法,但它不能用作使用梯度下降优化模型的损失函数,原因如下:
这不是一个可区分的功能。torch。max和都是非连续和非可微操作,因此我们无法使用精度来计算重量和偏差的梯度它没有考虑模型预测的实际概率,因此无法为渐进式改进提供足够的反馈
由于这些原因,准确性是分类的一个很好的评估指标,但不是一个好的损失函数。分类问题常用的损失函数是交叉熵,其具有以下公式:
虽然它看起来很复杂,但实际上非常简单:
对于每个输出行,选择正确标签的预测概率。例如。如果图像的预测概率是〔0。1,0。3,0。2,。。。〕并且正确的标签是1,我们选择相应的元素0。3并忽略其余的然后,取所选概率的对数。如果概率很高,即接近1,则其对数是非常小的负值,接近于0。如果概率低(接近0),则对数是非常大的负值。我们还将结果乘以1,结果是预测不良的损失的大正值最后,获取所有输出行的交叉熵的平均值,以获得一批数据的总体损失
与准确度不同,交叉熵是一种连续且可微分的函数,它还为模型中的渐进改进提供了良好的反馈(正确标签导致较低损失的概率略高)。这使它成为损失函数的一个很好的选择。
PyTorch提供了一种有效且张量友好的交叉熵实现,作为torch。nn。functionalpackage的一部分。
此外,它还在内部执行softmax,因此我们可以直接传递模型的输出而不将它们转换为概率。
由于交叉熵是在所有训练样本上平均的正确标签的预测概率的负对数,因此一种解释结果数的方法,例如,2。23是e2。23,平均值约为0。1,作为正确标签的预测概率。降低损失,改善模型。
优化
我们将使用optim。SGD优化器在训练期间更新权重和偏差,但学习率更高,为1e3。
batch大小,学习率等参数需要在训练机器学习模型时提前选取,并称为超参数。
选择正确的超参数对于在合理的时间内训练准确的模型至关重要,并且是研究和实验的活跃领域。随意尝试不同的学习率,看看它如何影响训练过程。
训练模型
现在我们已经定义了数据加载器,模型,损失函数和优化器,我们已准备好训练模型。
训练过程几乎与线性回归相同。但是,我们将增加我们之前定义的拟合函数,以使用每个epoch末尾的验证集来评估模型的准确性和损失。
我们首先定义一个函数lossbatch:
计算一批数据的损失如果提供了优化程序,则可以选择执行梯度下降更新步骤可选地使用预测和实际目标来计算度量(例如,准确度)
优化器是一个可选参数,以确保我们可以重用lossbatch来计算验证集上的损失。
我们还将batch处理的长度作为结果的一部分返回,因为它在组合整个数据集的损失度量时非常有用。
接下来,我们定义一个函数evaluate,它计算验证集的总体损失。
如果不能立即清楚此函数的作用,请尝试在单独的单元格中执行每个语句,然后查看结果。
我们还需要重新定义精确度以直接操作整批输出,以便我们可以将其用作拟合度量。
请注意,我们不需要将softmax应用于输出,因为它不会更改结果的相对顺序。
这是因为ex是增加函数,即如果y1y2,则ey1ey2,并且在对值求平均值以获得softmax之后也是如此。
让我们看看模型如何使用初始权重和偏差集在验证集上执行。
初始准确度低于10,这是人们对随机初始化模型的预期(因为它有十分之一的机会通过随机猜测获得标签)。
另请注意,我们使用。format方法和消息字符串仅打印小数点后的前四位数。
我们现在可以使用lossbatch和evaluate轻松定义拟合函数。
我们现在准备训练模型。让我们训练5个epoch并观察结果。
不错哦!来更多点eploch
线图更直观的显示一下效果
从上面的图片中可以清楚地看出,即使经过很长时间的训练,该模型也可能不会超过90的准确度阈值。
一个可能的原因是学习率可能太高。模型的参数可能会围绕具有最低损耗的最佳参数集弹跳。
您可以尝试降低学习速度和训练几个epoch,看看它是否有帮助。
更可能的原因是该模型不够强大。如果你还记得我们的初始假设,我们假设输出(在这种情况下是类概率)是输入(像素强度)的线性函数,通过对权重矩阵执行矩阵乘法并添加偏差来获得。
这是一个相当弱的假设,因为图像中的像素强度和它所代表的数字之间可能实际上不存在线性关系。
虽然它对于像MNIST这样的简单数据集(使我们达到85的准确度)工作得相当好,但我们需要更复杂的模型来捕捉图像像素和标签之间的非线性关系,以便识别日常物品,动物等复杂任务。
使用单个图像进行测试
虽然到目前为止我们一直在跟踪模型的整体精度,但在一些样本图像上查看模型的结果也是一个好主意。
让我们用10000个图像的预定义测试数据集中的一些图像测试我们的模型。我们首先使用ToTensor变换重新创建测试数据集。
数据集中单个图像的样本:
让我们定义一个辅助函数predictimage,它返回单个图像张量的预测标签。
img。unsqueeze只是在1x28x28张量的开始处添加另一个维度,使其成为1x1x28x28张量,模型将其视为包含单个图像的批处理。
通过收集更多的训练数据,增加减少模型的复杂性以及更改超参数,确定我们的模型表现不佳的位置可以帮助我们改进模型。
最后,让我们看看测试集上模型的整体损失和准确性。
我们希望这与验证集上的准确度损失相似。如果没有,我们可能需要一个更好的验证集,它具有与测试集类似的数据和分布(通常来自现实世界数据)。
保存并加载模型
由于我们已经长时间训练模型并获得了合理的精度,因此将权重和偏置矩阵保存到磁盘是个好主意,这样我们可以在以后重用模型并避免从头开始重新训练。以下是保存模型的方法。
。statedict方法返回一个OrderedDict,其中包含映射到模型右侧属性的所有权重和偏置矩阵。
要加载模型权重,我们可以实例化MnistModel类的新对象,并使用。loadstatedict方法。
正如完整性检查一样,让我们验证此模型在测试集上具有与以前相同的损失和准确性。
好了。大功告成了。又到了我们的commit环节。以防你已经忘记了怎么操作:
文章来源于网络,仅做交流分享,侵权删除
狂飙满足我对扫黑除恶剧的所有幻想最近,在爱奇艺热播的狂飙电视剧,收视率节节攀升,可惜我没有爱奇艺会员只看了一两集,我是深深的被剧中的情节,揪住了心,忍不住购买了爱奇艺会员,下定决心把这部电视剧看完追完。我个人看这
早安,黄山黄山旅游精彩亮相伦敦新春庆典黄山中院获最高法院通报表扬25hr202301黄山旅游精彩亮相伦敦新春庆典孙勇与张舜华李梢一行举行工作会谈黄山中院获最高法院通报表扬黄山风景区昨日接待游客34385人屯溪区黟县新春茶话会谋发展黄山各地欢欢喜
每日一习话温暖聆听促进各族人民大团结,携手共建美好家园视频加载中(欢迎点击视频,观看本期每日一习话)习近平要全面贯彻党的民族政策和宗教政策,加强民族团结进步教育,加快民族地区发展,多为各族群众办好事办实事解难题,促进各族群众共同富裕,
大年初五!焚香点烛要警惕,远离隐患人安康今日是大年初五正月初五,俗称破五节是历史悠久的中国传统节日之一这一天民间各商店开市一大早就金锣爆竹牲醴毕陈以迎接财神民间传说宋朝蔡京富有传说他是富神降生他恰生于正月初五所以中国民间
港人北上消费,人民币需求旺盛!深港口岸通关,跨境理财望升温点蓝字关注,不迷路自1月8日起,深港口岸分阶段有序恢复内地与香港人员正常往来。口岸恢复通关,不仅香港居民的人民币需求有所增加,也对金融行业尤其是深港跨境金融服务产生了积极作用。港人
简单孤独者的快乐云衡微语等春来愿你平安喜乐万事如意当一个人孤独地游走于荒芜,那不仅仅是一场置身于无助,或许他是在发泄在享受来之不易的单曲恋歌,清洗尘世的繁华落幕。愿你平安喜乐万事胜意当我还在徘徊犹
杨紫戴了一套房上春晚?兔年春晚珠宝赏析头条创作挑战赛兔年春晚已经热热闹闹地落幕了,余韵还在发散。大家都热烈讨论节目,讨论主持人,讨论明星的穿搭。今天讨论一下明星的珠宝吧。先说一下女明星,杨紫今年的春晚造型佩戴的珠宝是都
储能是构建新型电力系统的必要环节目前,新能源大规模利用仍面临间歇性波动性不稳定的挑战。储能可以平抑波动,支撑光电风电大规模并网,被视为新型电力系统的必要环节。实现双碳目标,传统能源逐步退出必须建立在新能源安全可靠
第三方厂商推出摇杆零件声称永久解决Switch手柄飘移问题Switch手柄一向都有飘移问题,用一段时间之后就会发生,相当令人困扰。最近有第三方厂商就针对这个问题推出零件,声称可以永久解决问题。据报道指,一家名为谷粒的厂商推出了一个Swit
大S又有新动作!张兰,又要被大S和具俊晔扎心了汪小菲和大S的事,从年前闹到了如今,双方依然没有善罢甘休的意思。这不,大S又有了新动作,跟张兰又战了起来。大过年的,很多人都想跟家里人团聚,热热闹闹过大年。张兰自然也想跟孙子孙女团
明日破五节,老话说破五3不破,财神不进门,3不破指啥?正月初五,俗称破五节,是历史悠久的中国传统节日之一。民间传统习俗,在春节期间有很多的禁忌,但到了正月初五就可以一一解除了。尤其是大年三十到正月初四,人们为了迎合新年的习俗,会有各种