第三周作业:卷积神经网络(Part1)

一、从全连接到卷积

引入:分类猫和狗图片时,当使用一个还不错的相机采集图片时(12M像素),RGB图片有36M元素,使用100大小的单隐藏层MLP,模型有3.6B元素,远多于世界上所有猫和狗总数,数据存储也需要很大的空间。

在图片中发现模型的两个原则:平移不变性局部性

怎么从全连接层出发利用这两个原则得到卷积

 第三周作业:卷积神经网络(Part1)

 第三周作业:卷积神经网络(Part1)

 在上图中,v也就是识别器,不应该因为输入x的变化而变化。

 第三周作业:卷积神经网络(Part1)

 二、卷积层

第三周作业:卷积神经网络(Part1)

 第三周作业:卷积神经网络(Part1)

 核矩阵的大小是超参数,决定了局部的大小,核矩阵和偏移是可学习的参数。

 第三周作业:卷积神经网络(Part1)

 第三周作业:卷积神经网络(Part1)

此处h、w是卷积核的属性值。

 第三周作业:卷积神经网络(Part1)

 三、卷积层里的填充与步幅

控制卷积层输出大小的两个超参数:填充步幅

第三周作业:卷积神经网络(Part1)

 但有时候我们并不想要经过卷积后的输出太小,因为深度学习就是为了使用更深的模型,使用有更多卷积层的模型,一旦输出结果太小就没有办法继续计算。所以我们使用填充来增大输出大大小。

 第三周作业:卷积神经网络(Part1)

 第三周作业:卷积神经网络(Part1) 

 根据老师的讲解我觉得那里要加一个+1.

 第三周作业:卷积神经网络(Part1)

 根据计算我认为应该是经过55层即(224-4)/(5-1)=55

第三周作业:卷积神经网络(Part1)

 第三周作业:卷积神经网络(Part1)

 四、卷积层里的多输入多输出通道

第三周作业:卷积神经网络(Part1)

 第三周作业:卷积神经网络(Part1)

 第三周作业:卷积神经网络(Part1)

 第三周作业:卷积神经网络(Part1)

 第三周作业:卷积神经网络(Part1)

 第三周作业:卷积神经网络(Part1)

 五、池化层

卷积层对位置敏感,检测垂直边缘时,使用一个1x2的卷积核-1和1,X经卷积后得到Y

第三周作业:卷积神经网络(Part1)

 但是当X的一个元素移位会导致0输出,卷积结果发生变化(?)

 第三周作业:卷积神经网络(Part1)

最大池化返回滑动窗口中的最大值

 第三周作业:卷积神经网络(Part1)

 对卷积结果Y进行最大池化

 第三周作业:卷积神经网络(Part1)

 Y的一个像素移位不会导致池化结果改变。

 填充、步幅和多个通道

池化层和卷积层类似,都具有填充和步幅。

池化层没有可学习的参数。

在每个输入通道应用池化层以获得相应的输出通道。

输出通道数=输入通道数。

平均池化层

 第三周作业:卷积神经网络(Part1)

 六、经典卷积神经网络LeNet

LeNet最初是为了识别手写数字。

MNIST数据集

第三周作业:卷积神经网络(Part1)

 LeNet是早期成功的神经网络,先试用卷积层来学习图片空间信息,再利用池化层降低敏感度,然后使用全连接层来转换到类别空间。

第三周作业:卷积神经网络(Part1)

在上图中,输入32x32image,放到5x5的卷积层中,输出通道为6,输出结果就是feature map,用2x2的pooling层,再放到5x5的卷积层中,输出通道为16,再用一个pooling层,最后拉成一个向量,放到全连接层。 

猫狗大战练习

竞赛代码分析

导入包

import torch 
import torch.nn as nn
import torchvision
import torchvision.transforms as transforms
from torch.autograd import Variable
import csv
import cv2
from PIL import Image
import os
'''定义参数'''
batch_size=200
lr=0.001
'''设置transform'''

data_transform={
    
    "train":transforms.Compose([
            
            transforms.RandomResizedCrop(32),
            transforms.RandomHorizontalFlip(),
            transforms.ToTensor(),
            transforms.Normalize((0.5,0.5,0.5), (0.5,0.5,0.5))
    
        ]),
    
    "val":transforms.Compose([
            
            transforms.Resize((32,32)),
            transforms.ToTensor(),
            transforms.Normalize((0.5,0.5,0.5), (0.5,0.5,0.5))
    
        ]),
     "test":transforms.Compose([
            
            transforms.Resize((32,32)),
            transforms.ToTensor(),           
            transforms.Normalize((0.5,0.5,0.5), (0.5,0.5,0.5))
            
    
        ])
}
image_root="D:\\Downloads\\theory\\cat_dog\\"


'''获取数据'''

train_dataset=torchvision.datasets.ImageFolder(root=image_root+"train",transform=data_transform["train"])

val_dataset=torchvision.datasets.ImageFolder(root=image_root+"val",transform=data_transform["val"])
'''装载数据'''

train_loader=torch.utils.data.DataLoader(dataset=train_dataset,batch_size=batch_size,shuffle=True)

val_loader=torch.utils.data.DataLoader(dataset=val_dataset,batch_size=batch_size,shuffle=False)
'''搭建神经网络'''
net = torch.nn.Sequential( nn.Conv2d(3, 6, kernel_size=5),nn.Sigmoid(),
                          nn.AvgPool2d(kernel_size=2, stride=2),
                          nn.Conv2d(6, 16, kernel_size=5), nn.Sigmoid(),
                          nn.AvgPool2d(kernel_size=2, stride=2), nn.Flatten(),
                          nn.Linear(16 * 5 * 5, 120), nn.Sigmoid(),
                          nn.Linear(120, 84), nn.Sigmoid(), 
                          nn.Linear(84, 2))
net=net

'''设置损失函数'''
criterion=nn.CrossEntropyLoss()

'''设置优化器'''
optimizer=torch.optim.Adam(net.parameters(),lr=lr)
'''开始训练'''
total_step = len(train_loader)  #几个批量
for epoch in range(10):
    for i, (images, labels) in enumerate(train_loader):

        images=Variable(images)
        labels=Variable(labels)
        
        outputs = net(images)
        
        loss = criterion(outputs, labels)
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        
        if (i+1) % 100 == 0:
            print ('Epoch [{}/{}], Step [{}/{}], Loss: {:.4f}' 
                   .format(epoch+1, 10, i+1, total_step, loss.item()))
'''写入csv文件'''
f=open('catdog.csv','w',encoding='utf-8')
csv_writer=csv.writer(f)
#csv_writer.writerow([num,i.item()])
'''val数据集'''
with torch.no_grad():
    correct=0    
    total=0
    
    for image,label in val_loader:        
        pred=net(image)    
        predict=torch.max(pred,1)[1]  
        correct += (predict == label).sum().item()        
        total+=label.shape[0]
        
    print('Test Accuracy of the model on the  val images: {} %'.format(100 * correct / total))
'''读取test数据集'''
root_path = "D:\\Downloads\\theory\\cat_dog\\test"  #操作文件路径
dir = root_path

'''进行测试'''
with torch.no_grad():
    n=0
    for root,dirs,files in os.walk(dir):
        for file in files:
            img = cv2.imread(root_path+"\\"+str(file))
            img=Image.fromarray(img)
            
            newImg = data_transform["test"](img)  #想调整的大小
            newImg=Variable(torch.unsqueeze(newImg, dim=0).float(), requires_grad=False)
            pred2=net(newImg)
            predict2=torch.max(pred2,1)[1]
            for i in predict2:
                csv_writer.writerow([n,i.item()])
                n+=1

训练结果

第三周作业:卷积神经网络(Part1)

使用val数据得到的正确率

第三周作业:卷积神经网络(Part1)

 第三周作业:卷积神经网络(Part1)

 

问题:

通过这次的代码练习发现学习中的问题还是很多,能够看懂lenet的图和老师上课讲的代码,但是自己写的时候,图片变了之后就有很多问题,比如输入图片大小必须是32x32吗,如果不是,增加卷积层还是在全连接层直接通道数x大小,如果增加卷积层,通道数也要一直变大吗。还是对于lenet网络了解不够,修改也无从下手。

上一篇:leetcode-289-生命游戏


下一篇:LeetCode 289.生命游戏