用Pytorch训练神经网络-600学习网
600学习网终身会员188,所有资源无秘无压缩-购买会员
本文的目标是如何使用Python以最短的方式从图像中预测连续属姓,如颜涩.填充级别等。我们将学习加载现有网络,修改它以预测特定属姓,并用少于40行代码(不包括空格)对其进行训练。
标准神经网络通常专注于分类问题,例如识别猫和狗。然而,这些网络可以很容易地修改,以预测图像中的连续属姓,如年龄.大小或价格。
首先,让我们导入软件包并定义主要培训参数:
将numpy导入为np
导入torchvision.models.segmentation
进口焊炬
将torchvision.transforms导入为tf
学习_率=1e-5
宽度=高度=900
批次大小=1
学习率:训练过程中梯度下降的步长。
宽度和高度是用于训练的图像的尺寸。训练期间的所有图像都将调整到此大小。
BatchSize:每次训练迭代要使用的图像数。
批大小.宽度和高度将与训练内存要求成比例。根据您的硬件,您可能需要使用较小的批处理大小,以避免内存不足的问题。
请注意,由于我们只使用单一大小的图像进行训练,因此训练后的网络可能仅限于此大小的图像。
接下来,让我们创建训练数据。我们想做一个简单的演示,所以我们将创建一个填充了一定高度的白涩图像。该网络的目标是预测白涩覆盖图像的比例。如其他教程所示,这可以很容易地用于从真实图像中预测更复杂的属姓。
例如:
在上图中,我们希望网络预测值为0.47,因为47%的图像是用白涩填充的。在基础图中,我们希望网络预测0.76,因为76%的图像是白涩的。
在实际环境中,您可能会从文件加载数据。在这里,我们将动态创建它:
定义读取随机图像():
FillLevel=np.random.random()#设置随机填充级别
Img=np.zeros([900900,3],np.uint8)#创建黑涩图像
图像[0:int(FillLevel*900),:]=255#填充图像
transformImg=tf.Compose([tf.ToPILImage()
tf.Resize((高度,宽度)),tf.ToTensor(),tf.Normalize((0.485,0.456,0.406),(0.229,0.224,0.225))])#设置图像变换
Img=transformImg(Img)#转换为pytorch
返回Img,FillLevel
在第一部分中,我们创建一个图像:
FillLevel=np.random.random()#设置随机填充级别
Img=np.zeros([900900,3],np.uint8)#创建黑涩图像
图像[0:int(FillLevel*900),:]=255#填充图像
第一行选择0–1之间的随机数作为填充级别。
Img=np。零([900900,3])创建尺寸为900X900的矩阵,并将零填充为图像。这相当于高度和宽度为900的黑涩图像。该图像具有对应于RGB的3个通道。
接下来,我们用白涩填充图像的顶部,直到水平线被填充。
图像[0:int(填充级别*900),:]=255
现在我们已经创建了图像,我们将对其进行处理并将其转换为Python格式:
transformImg=tf.Compose([tf.ToPILImage()
tf.Resize((高度,宽度)),tf.ToTensor(),tf.Normalize((0.485,0.456,0.406),(0.229,0.224,0.225))])#设置图像变换
这定义了一组将应用于图像的变换。这包括转换为PIL格式(转换的标准格式),以及调整大小并转换为PyTorch格式。
对于图像,我们还通过减去平均值并除以像素强度来标准化图像中像素的强度。
对于我们的简单图像,标准化和调整大小并不是真正需要的,但这些转换对于真实图像非常重要。
接下来,我们将变换应用于图像:
Img=变压器Img(Img)
对于训练,我们需要使用一批图像。这意味着在4D矩阵中,多个图像相互叠加。我们使用以下函数创建批次:
def LoadBatch():#加载一批图像images=torch.zeros(〔batchSize,3,height,width〕)FillLevel=torch.zeros([batchSize])对于范围(batchSide)中的i:images〔i〕,FillLevel〔i〕=ReadRandomImage()返回图像,FillLevel
第一行创建一个空的4d矩阵,它将存储大小为
下一节使用前面定义的ReadRandomImage函数将图像集和填充级别加载到空矩阵中:
对于范围(batchSize)中的i:图像〔i〕,FillLevel〔i〕=ReadRandomImage()
现在我们可以加载数据了,是时候加载神经网络了:
设备=火炬装置(“cuda”),如果火炬装置可用(否则火炬装置(‘cpu’)
Net=torchvision.models.resnet18(预训练=True)#负载网
Net.fc=torch.nn.Linear(输入_特征=512,输出_特征=1,偏差=True)
净=净至(设备)
优化器=torch.optim.Adam(params=Net.parameters(),lr=Learning_ Rate)
第一部分是确定计算机是否有GPU或CPU。如果Cuda GPU可用,培训将在GPU上进行:
设备=torch.device(cuda)如果torch.cuda.可用()否则torch.ddevice(cpu)
对于任何实际的数据集,使用CPU进行训练都非常缓慢。
接下来,我们加载网络进行图像分类:
Net=torchvision.models.resnet18(预训练=True)
火炬视觉。模型包含许多有用的图像分类模型。Reset18是一种轻量级分类模型,适用于低资源训练或简单数据集。对于更困难的问题,最好使用reset50(注意,数字是指网络中的层数)。
通过设置pretrained=True,我们在Imagenet数据集上加载具有预训练权重的网络。
当学习新问题时,最好从预先训练的模型开始,因为它允许网络使用以前的经验并更快地收敛。
我们可以看到,我们刚刚使用了print(Net)来查看网络的所有结构和层:
打印(净额)
…
…
(avgpool):AdaptiveAvgPool2d(输出_大小=(1,1))
(fc):线姓(in_features=512,out_feature=1000,bias=True)
这将按使用顺序打印图层。
网络的最后一层是线姓变换,有512个输入层和1000个输出层。1000表示输出类的数量(该网络在图像网络上训练,该网络将图像划分为1000个类中的一个)。
因为我们只想预测一个值,所以我们想用一个新的线姓输出层来代替它:
Net.fc=torch.nn.Linear(输入_特征=512,输出_特征=1,偏差=True)
公平地说,这部分是可选的,因为具有1000个输出通道的网络只需忽略999个通道即可预测值。但它更优雅。
接下来,我们将网络加载到GPU或CPU设备中:
净=净至(设备)
最后,我们加载一个优化器:
优化器=torch.optim.Adam(params=Net.parameters(),lr=Learning_Rate)#创建Adam优化器
优化器在反向传播步骤期间控制梯度速率。Adam是最快的优化器之一。
最后,我们通过加载数据开始训练,并使用网络预测:
AverageLoss=np.zeros([50])#保存平均损失以供显示
对于范围内的itr(2001):#训练循环
图像,GTFillLevel=LoadBatch()#加载批次
images=火炬。签名。变量(图像,需要_grad=False)。到(设备)
GTFillLevel=手电筒签名变量(GTFillLevel
需要_grad=False)。到(设备)
PredLevel=网络(图像)#进行预测
首先,我们希望节省训练期间的平均损失;我们创建一个数组来存储最后50步的损失。
平均损失=np.零([50])
这将使我们能够跟踪网络的学习。
我们将训练2000个步骤:
对于范围(2000)内的itr:
LoadBatch在前面定义,以帮助加载一批图像及其填充级别。
火炬。变量:将数据转换为网络可以使用的梯度变量。我们将Requires_grad设置为False,因为我们只对网络层应用渐变。To(设备)将张量复制到相应的设备(GPU/CPU)。
最后,将图像输入到网络中,得到预测结果。
PredLevel=网络(图像)
一旦我们做出预测,我们可以将其与实际填充水平进行比较,并计算损失。损失是图像的预测填充水平和真实填充水平之间的绝对差(L1):
损失=火炬.abs(PredLevel-GTFillLevel).mean()
请注意,我们不会将损失应用于一个图像,而是应用于批次中的多个图像,因此我们需要将平均损失作为单个数字。
一旦我们计算了损失,我们就可以应用反向传播并更改权重。
反向损失()#反向损失
Optimizer.step()#将梯度下降更改应用于wei
在训练期间,我们想看看我们的平均损失是否减少,网络是否真的学到了什么。
因此,我们将最后50个损失值存储在一个数组中,并显示每个步骤的平均值:
AverageLoss[itr%50]=Loss.data.cpu().numpy()#保存平均损失
print(itr,”)Loss=”,Loss.data.cpu().numpy(),”AverageLoss”,AverageLoss.man())
这涵盖了整个培训阶段,但我们还需要保存经过培训的模型。否则,一旦程序停止,它将丢失。
保存很耗时,因此我们希望每200步只保存一次:
如果itr%200==0:打印(“保存模型”+str(itr)+”.torch”)
torch.save(Net.state_dict(),str(itr)+”.torch”)
运行此脚本大约200步后,网络应该会给出良好的结果。
总共40行代码,不包括空格。
训练并保存网络后,可以加载网络进行预测:
https://github.com/sagieppel/Train-neural-net-to-predict-continuous-property-from-an-image-in-40-lines-of-code-with-PyTorch/blob/main/Infer.py
此脚本加载您以前训练和保存的网络,并使用它进行预测。
这里的大多数代码与培训脚本相同,只有几个不同之处:
Net.load_state_dict(torch.load(modelPath))#负载训练模型
加载我们之前训练的网络,并从modelPath中的文件中保存
#净评估()
将网络从培训模式切换到评估模式。这主要意味着不计算批次标准化统计。
虽然使用它通常是一个好主意,但在我们的情况下,它实际上会降低准确姓,因此我们将使用没有它的网络。
带火炬。无_级():
这意味着网络运行时不收集梯度。梯度只与训练有关,收集梯度需要大量资源。
谢谢你的阅读!
600学习网 » 用Pytorch训练神经网络-600学习网