本文共 5478 字,大约阅读时间需要 18 分钟。
,为了比较的来学习,我们应当先明确什么是全连接网络:全部的线性层都是可以穿起来的时候就是一个全连接层,既任何一个输出的节点都是需要在下一层参与计算的是全连接的神经网络。
我们在对一个图像进行全连接的时候我们需要把一个图片转化为一个一维的矩阵,这就产生了这样的一种情况,本身是相互挨着的两个点在展开的时候,可能就离得特别遥远,这就会使得原有的特征丧失。
卷积的过程可能会将通道数和宽和高,一般于此同时要使用下采样来减少运算量,不改变通道数但是改变了宽和高,来减少运算的消耗。
通过不断卷积和下采样,来不断降低w和h最后得到一个一维的张量。如下图所示: 可以看出,这里的卷积其实是一个特征提取的过程。将输入的图片变成一个向量,之后再接一个全连接的网络来实现分类。这里只是一个初级的认识,下面有更为详细的说明。我们其实是将图片分割成一个一个格子,每个格子都有三种颜色来填充。
RGB的产生 光敏电阻,可以根据光照来改变电阻。然后根据电路当中的电压情况,可以通过利用这种特性来用电压确定光照。也就是最终确定一个光照的强度。其实这就是像素的来源,像素就是一个光敏电阻制成的采集器采集出的数据。我们的RGB图其实就是来自于三种颜色的光敏电阻传感器,分别从不同的传感器得到不同的颜色分量。得到不同颜色的光照强度,然后再将拿到的图像转化为0-255来存储。 矢量图像: 就是在图像当中加入各种圆,每个圆记录的有大小、边和填充颜色三个要素,实际上在显示的时候是再重新勾画整个图片。这个是pytorch一个特色,每次都只能输入一小部分,所以每次输入必须是一个batch一个batch的输入,所以我们一般是上来就在开始部分定义一个batch_size来完成操作。
我们其实不是对整个的一个RGB图像在进行操作,我们是在对RGB上的一个一个小块进行操作。
之后拿这个块的大小对整个图像进行遍历。从左到右从上到下进行遍历。 我们在对每一个小块在进行卷积的时候,其实是对原有数据的一个融合过程,原来的情况当中,某一个块中的一个像素仅仅是代表着自己的信息,新得到的内容的一个像素,则是代表着原来块中全部元素的一个特征。不断地进行卷积则会使得每一个块中的每个像素都融合了全部像素的信息。 那么卷积具体是怎么计算的呢?首先我们需要一个卷积核,然后让个卷积和和其中内容逐渐进行点乘。然后得到一个输出: 我们在明白了一个单通道的输入的卷积之后,如果我们遇见一个多通道的卷积又该如何是好呢?如果我们给三个通道使用同一个卷积核,是否可行呢?仔细想一下这样子其实是不行的,如果我们使用同一个卷积核其实就相当于将这个输入加和之后再整体进行卷积,那么输入分成三个通道的意义将完全没有,所以我们每个通道要使用独立的卷积核,再卷积之后再将他们相加。 我们如果每次这么画图,那么将变得十分麻烦,所以我们要使用更加简单的方法来表示一个卷积层,大致有下面几种: 1. 2. 3. 但是我们注意我们的输出只有一个输出通道,那么我们想要有多个输出通道又该怎么办呢?其实我们不难发现我们只需要有多个卷积核就可以了。具体如下图: 我们其实不难发现卷积层也是一个线性计算,所以有加入偏置量的问题。大致如下图:其实就是依据参数,将原有的输入划分为小格子,进而在其中挑选最大的元素出来。
可以看到其中是对一个通道进行操作,不会涉及到其他通道的问题,所以经过Maxpooling层之后,channel的数值不变。 maxpooling_layer=torch.nn.Maxpooling(kernal=2)我们先画一个图来明确我们需要实现什么:
好了画完这个图,我们就知道要怎么实现了。import numpyimport torchfrom torchvision import transformsfrom torchvision import datasetsimport torch.nn.functional as Fimport torch.optim as optimfrom torch.utils.data import Datasetfrom torch.utils.data import DataLoader#这里我们要理解这个from的作用,使用一个from#transeforms 主要是用来做图像处理# optim主要是包含优化器的#首先明白下面这个东西是个什么东西?#这个东西是个转化器,可以对输入的内容做我们规定好的操作,# 具体操作就是下面[]中定义的。#这里注意一个细节transforms和transform的区别,带s的表示是一片,不带s的是一个,我们实例化的一个batch_size1=64transform= transforms.Compose([ #这个首先转化为一个张量 transforms.ToTensor(), #为了更好的学习效果我们需要一个标准化的过程,前一个参数是均值后一个是方差 # 这两个参数都是MNIST数据集使用的,如果是自己的数据集这个要算一下。 transforms.Normalize((0.1307,),(0.3081,))])#这里其实和之前的一样的,只是加了一个transform=的参数trian_set = datasets.MNIST(root='./data',train=True,download=True,transform=transform)trian_loader= DataLoader(trian_set,shuffle=True,batch_size=batch_size1)test_set =datasets.MNIST(root='./data',train=False,download=True,transform=transform)test_loader= DataLoader(test_set,shuffle=True,batch_size=batch_size1)class myModol(torch.nn.Module): def __init__(self): super(myModol,self).__init__() self.conv1=torch.nn.Conv2d(1,10,kernel_size=5) self.pool=torch.nn.MaxPool2d(kernel_size=2)#这个东西没有权重可以只做一个。 self.conv2=torch.nn.Conv2d(10,20,kernel_size=5) self.l1=torch.nn.Linear(320,512) self.l2=torch.nn.Linear(512,256) self.l3=torch.nn.Linear(256,128) self.l4=torch.nn.Linear(128,64) self.l5=torch.nn.Linear(64,10) def forward(self,x): #前面的-1代表着看着情况进行变化。 #这里我们注意我们的这里输入的784不是随便输入的, # 是有实际意义的,MNIST的数据集的输入是1*28*28的, # 所以我们想要转化为二维的时候,一定要尊重原有的实际意义 #这里卷积层其实也是一个线性模型,所以也应当使用一个激活函数。 x=F.relu(self.pool(self.conv1(x))) x=F.relu(self.pool(self.conv2(x))) x=x.view(-1,320)#我们注意这里我们开始线性层的时候,要转化为一个二维的矩阵 x=F.relu(self.l1(x)) x=F.relu(self.l2(x)) x=F.relu(self.l3(x)) x=F.relu(self.l4(x)) return self.l5(x) #因为我们最后使用的是交叉熵损失函数已经将激活层抱进去了不用再单独写了model=myModol()#z这里我们进行一个迁移到显卡的操作,我们在进行运算的时候可以将运算迁移到显卡上,# 这里我们注意cuda:0的意思是第0块显卡,显卡有很多需要标记一下,# 这里我们注意模型和数据需要在同一个显卡上才能运算,在不同的显卡上将不能运算。device=torch.device("cuda:0"if torch.cuda.is_available()else "cpu")model.to(device)#模型的所有数据都迁移到显卡上#使用一个交叉熵损失函数criterion=torch.nn.CrossEntropyLoss()#因为我们计算量已经比较大了所以要使用一个带有冲量的优化器。opminster= optim.SGD(model.parameters(),lr=0.01,momentum=0.5)def train(epoch): train_loss=0.0 for batch_idx,data in enumerate(trian_loader,0): m_input,target=data #将数据迁移到对应的设备上 m_input,targe=m_input.to(device),target.to(device) opminster.zero_grad() outputs= model(m_input) loss=criterion(outputs,target) loss.backward() opminster.step() train_loss+=loss.item() if batch_idx%300==299: #每300次才输出一次,另外因为我们都是从0开始计数所以我们需要+1 print('[%d,%5d]loss:%.3f'%(epoch+1,batch_idx+1,train_loss/300)) train_loss=0def test(): #定义几个计数变量 correct=0 total=0 #因为我们在计算损失的时候是不需要进行梯度计算的, # 所以这里取消梯度计算来增加速度。 with torch.no_grad(): for data in test_loader: images,targets=data images,targets=images.to(device),targets.to(device) outputs=model(images) #这里我们注意我们在输出的时候是一个最大值,一个最大值角标,我们只需要最大值角标, # 这里我们注意dim=1的这个问题,dim=0代表每列找一个,dim=1代表每行找。 _,predicted=torch.max(outputs.data,dim=1) #这里我们注意一个问题就是返回的形式是torch.Size, # 这个玩意是一个元组,这里是(行数,列数)所以我们要取出来第0个。 total+=targets.size(0) #我们注意这里张量比较的使用问题 correct+=(predicted==targets).sum().item() print('acc on test set:%d%%'%(100*correct/total))if __name__=='__main__': for epoch in range(10): train(epoch) test()#但是我们这里的全连接层得到的准确度并不高,因为我们是将图上的所有信息都全部利用了#其实决定图片的数字到底是多少并不是由全部的情况决定的。
我们看一下提升:
我们可以看到感觉上这个提升并不大,但是我们不能从正确率的角度来看,我们应当从错误了的角度来看,我们相当于消除了1/3的错误率。转载地址:http://bkywi.baihongyu.com/