pytorch——人工智能的开源深度学习框架
pytorch深度学习框架之tensor张量
计算机视觉的基石——读懂CNN卷积神经网络
本期文章的主要内容:
1、CNN卷积神经网络
2、torchvision.datasets
3、MINIST数据集
4、神经网络的训练
5、pytorch训练模型的保存
CNN
PyTorch提供了许多预加载的数据集(例如FashionMNIST),所有数据集都是torch.utils.data.Dataset的子类,它们具有__getitem__和__len__实现的方法。因此,它们都可以传递给torch.utils.data.DataLoader也可以使用torch.multiprocessing并行加载多个样本的数据。例如:
以下是如何从TorchVision加载Fashion-MNIST数据集的示例。Fashion-MNIST由60,个训练示例和10,个测试示例组成。每个示例都包含一个28×28灰度图像和来自10个类别之一的相关标签。
MINIST数据
MINIST的数据分为2个部分:55份训练数据(mnist.train)和10份测试数据(mnist.test)。这个划分有重要的象征意义,他展示了在机器学习中如何使用数据。在训练的过程中,我们必须单独保留一份没有用于机器训练的数据作为验证的数据,这才能确保训练的结果的可行性。
前面已经提到,每一份MINIST数据都由图片以及标签组成。我们将图片命名为“x”,将标记数字的标签命名为“y”。训练数据集和测试数据集都是同样的结构,例如:训练的图片名为mnist.train.images而训练的标签名为mnist.train.labels。
每一个图片均为28×28像素,我们可以将其理解为一个二维数组的结构:
MNIST
我们使用以下参数加载MNIST数据集:
root(string)–数据集所在MNIST/processed/training.pt和MNIST/processed/test.pt存在的根目录。train(bool,optional)–如果为True,则从中创建数据集training.pt,否则从test.pt.download(bool,optional)–如果为true,则从Internet下载数据集并将其放在根目录中。如果数据集已经下载,则不会再次下载。transform(callable,optional)–一个函数/转换,它接收一个PIL图像并返回一个转换后的版本。例如,transforms.RandomCroptarget_transform(callable,optional)–一个接收目标并对其进行转换的函数/转换。
torchvision.datasets.MNIST(root:str,train:bool=True,transform:Optional[Callable]=None,target_transform:Optional[Callable]=None,download:bool=False)
所有数据集都有几乎相似的API。它们都有两个共同的参数:transform和target_transform,本期文章,我们基于MNIST数据集来写一个简单的神经网络,并进行神经网络的训练
下载数据集torchvision.datasets
importtorchimporttorch.nnasnnimporttorch.utils.dataasDataimporttorchvision#数据库模块importmatplotlib.pyplotasplt#torch.manual_seed(1)#producibleEPOCH=20#训练整批数据次数,训练次数越多,精度越高BATCH_SIZE=50#每次训练的数据集个数LR=0.#学习效率DOWNLOAD_MNIST=False#如果你已经下载好了mnist数据就设置False#Mnist手写数字训练集train_data=torchvision.datasets.MNIST(root=./data/,#保存或者提取位置train=True,#thisistrainingdatatransform=torchvision.transforms.ToTensor(),#转换PIL.Imageornumpy.ndarray成tensor#torch.FloatTensor(CxHxW),训练的时候normalize成[0.0,1.0]区间download=DOWNLOAD_MNIST,#没下载就会自动下载数据集,当等于true)#Mnist手写数字测试集test_data=torchvision.datasets.MNIST( root=./mnist/, train=False,#thisistrainingdata)
通过以上代码,我们便在工程目录下的data文件夹下下载了MNIST的全部数据集,torchvision.datasets是pytorch为了方便研发者,进行了绝大部分的数据库的集合,通过torchvision.datasets可以很方便地下载使用其包含的数据集,其torchvision.datasets下面主要包含如下数据集,其他方面的数据集可以自行下载尝试
torchvision.datasetsCaltechCelebACIFARCityscapesCOCOEMNISTFakeDataFashion-MNISTFlickrHMDB51ImageNetKinetics-KITTIKMNISTLSUNMNISTOmniglotPhotoTourPlacesQMNISTSBDSBUSEMEIONSTL10SVHNUCFUSPSVOCWIDERFace
CNN卷积神经网络搭建
CNN
#批训练50samples,1channel,28x28(50,1,28,28)train_loader=Data.DataLoader(dataset=train_data,batch_size=BATCH_SIZE,shuffle=True)#每一步loader释放50个数据用来学习#为了演示,我们测试时提取2个数据先#shapefrom(2,28,28)to(2,1,28,28),valueinrange(0,1)test_x=torch.unsqueeze(test_data.data,dim=1).type(torch.FloatTensor)[:2]/.test_y=test_data.targets[:2]#test_x=test_x.cuda()#若有cuda环境,取消注释#test_y=test_y.cuda()#若有cuda环境,取消注释#定义神经网络classCNN(nn.Module):def__init__(self):super(CNN,self).__init__()self.conv1=nn.Sequential(#inputshape(1,28,28)nn.Conv2d(in_channels=1,#输入通道数out_channels=16,#输出通道数kernel_size=5,#卷积核大小stride=1,#卷积部数padding=2,#如果想要con2d出来的图片长宽没有变化,#padding=(kernel_size-1)/2当stride=1),#outputshape(16,28,28)nn.ReLU(),#activationnn.MaxPool2d(kernel_size=2),#在2x2空间里向下采样,outputshape(16,14,14))self.conv2=nn.Sequential(#inputshape(16,14,14)nn.Conv2d(16,32,5,1,2),#outputshape(32,14,14)nn.ReLU(),#activationnn.MaxPool2d(2),#outputshape(32,7,7))self.out=nn.Linear(32*7*7,10)#全连接层,0-9一共10个类#前向反馈defforward(self,x):x=self.conv1(x)x=self.conv2(x)x=x.view(x.size(0),-1)#展平多维的卷积图成(batch_size,32*7*7)output=self.out(x)turnoutput
我们使用Data.DataLoader来加载我们下载好的MNIST数据集,并分开训练集与测试集
接下来我们建立一个CNN卷积神经网络:
第一层,我们输入minist的数据集,minist的数据图片是一维28*28的图片,所以第一层的输入(1,28,28),高度为1,设置输出16通道,使用5*5的卷积核对图片进行卷积运算,每步移动一格,为了避免图片尺寸变化,设置pading为2,则经过第一层卷积就输出(16,28,28)数据格式
再经过lu与maxpooling(使用2*2卷积核)数据输出(16,14,14)
第二层卷积层是简化写法nn.Conv2d(16,32,5,1,2)的第一个参数为输入通道数in_channels=16,其第二个参数是输出通道数out_channels=32,#n_filters(输出通道数),第三个参数为卷积核大小,第四个参数为卷积步数,最后一个为pading,此参数为保证输入输出图片的尺寸大小一致
self.conv2=nn.Sequential(#inputshape(16,14,14)nn.Conv2d(16,32,5,1,2),#outputshape(32,14,14)nn.ReLU(),#activationnn.MaxPool2d(2),#outputshape(32,7,7))
全连接层,最后使用nn.linear()全连接层进行数据的全连接数据结构(32*7*7,10)以上便是整个卷积神经网络的结构,
大致为:input-卷积-Relu-pooling-卷积-Relu-pooling-linear-output
卷积神经网络建完后,使用forward()前向传播神经网络进行输入图片的训练
通过以上的神经网络的搭建,我们便建立一个神经网络,此神经网络类似MINIST的双隐藏层结构
神经网络的训练
神经网络搭建完成后,我们便可以进行神经网络的训练
cnn=CNN()#创建CNN#cnn=cnn.cuda()#若有cuda环境,取消注释optimizer=torch.optim.Adam(cnn.parameters(),lr=LR)loss_func=nn.CrossEntropyLoss()forepochinrange(EPOCH):forstep,(b_x,b_y)inenumerate(train_loader):#每一步loader释放50个数据用来学习#b_x=b_x.cuda()#若有cuda环境,取消注释#b_y=b_y.cuda()#若有cuda环境,取消注释output=cnn(b_x)#输入一张图片进行神经网络训练loss=loss_func(output,b_y)#计算神经网络的预测值与实际的误差optimizer.zero_grad()#将所有优化的torch.Tensors的梯度设置为零loss.backward()#反向传播的梯度计算optimizer.step()#执行单个优化步骤ifstep%50==0:#我们每50步来查看一下神经网络训练的结果test_output=cnn(test_x)pd_y=torch.max(test_output,1)[1].data.squeeze()#若有cuda环境,使用84行,注释82行#pd_y=torch.max(test_output,1)[1].cuda().data.squeeze()accuracy=float((pd_y==test_y).sum())/float(test_y.size(0))print(Epoch:,epoch,
trainloss:%.4f%loss.data,
testaccuracy:%.2f%accuracy)
首先我们使用CNN()函数进行神经网络的初始化,并建立一个神经网络模型,并利用optim.Adam优化函数建立一个optimizer神经网络优化器,torch.optim是一个实现各种优化算法的包。大部分常用的方法都已经支持,接口也足够通用,以后也可以轻松集成更复杂的方法。
常用的优化器主要有:OptimizerGradientDescentOptimizerAdadeltaOptimizerAdagradOptimizerAdagradDAOptimizerMomentumOptimizerAdamOptimizerFtrlOptimizerProximalGradientDescentOptimizerProximalAdagradOptimizerRMSPropOptimizer
然后建立一个损失函数,我们神经网络的目的就是使用损失函数使神经网络的训练loss越来越小。然后进行神经网络的训练,我们每50步打印一下神经网络的训练效果
测试神经网络的结果与保存神经网络
#test神经网络test_output=cnn(test_x[:10])pd_y=torch.max(test_output,1)[1].data.squeeze()#若有cuda环境,使用92行,注释90行#pd_y=torch.max(test_output,1)[1].cuda().data.squeeze()print(pd_y,pdictionnumber)print(test_y[:10],alnumber)#saveCNN#仅保存CNN参数,速度较快torch.save(cnn.state_dict(),./model/CNN_NO1.pk)#保存CNN整个结构#torch.save(cnn(),./model/CNN.pkl)
我们提取前10个MNIST的数据,并进行神经网络的预测,此时我们可以打印出来神经网络的预测值与实际值,最后并保存神经网络的模型,此模型我们可以直接使用来进行手写数字的识别
从训练结果可以看出,只训练了24*50个循环,神经网络的精度已经达到0.97
Epoch:0
trainloss:2.
testaccuracy:0.18Epoch:0
trainloss:0.
testaccuracy:0.82Epoch:0
trainloss:0.
testaccuracy:0.89Epoch:0
trainloss:0.
testaccuracy:0.92Epoch:0
trainloss:0.
testaccuracy:0.93Epoch:0
trainloss:0.
testaccuracy:0.92Epoch:0
trainloss:0.
testaccuracy:0.95Epoch:0
trainloss:0.
testaccuracy:0.95Epoch:0
trainloss:0.
testaccuracy:0.95Epoch:0
trainloss:0.
testaccuracy:0.96Epoch:0
trainloss:0.
testaccuracy:0.97Epoch:0
trainloss:0.
testaccuracy:0.97Epoch:0
trainloss:0.
testaccuracy:0.97Epoch:0
trainloss:0.
testaccuracy:0.98Epoch:0
trainloss:0.
testaccuracy:0.97Epoch:0
trainloss:0.
testaccuracy:0.97Epoch:0
trainloss:0.
testaccuracy:0.97Epoch:0
trainloss:0.
testaccuracy:0.97Epoch:0
trainloss:0.
testaccuracy:0.97Epoch:0
trainloss:0.
testaccuracy:0.97Epoch:0
trainloss:0.
testaccuracy:0.97Epoch:0
trainloss:0.
testaccuracy:0.97Epoch:0
trainloss:0.
testaccuracy:0.97Epoch:0
trainloss:0.
testaccuracy:0.97tensor([7,2,1,0,4,1,4,9,5,9])pdictionnumbertensor([7,2,1,0,4,1,4,9,5,9])alnumber
最后打印出来的前10个预测模型,完全一致
ok,本期我们分享了神经网络的搭建,并利用MNIST的数据集进行了神经网络的训练,并进行了神经网络的预测,下期文章我们利用训练好的模型进行神经网络的识别。