机器学习笔记(3)CNN

机器学习笔记(3)CNN

参考网址:https://blog.csdn.net/out_of_memory_error/article/details/81434907
https://blog.csdn.net/cxmscb/article/details/71023576

基本概念学习

输入层

对于黑白图片,输入层为nm,对于RGB图片,输入层为3nm。(nm为图片大小)

卷积

卷积是指使用卷积核进行特征提取和特征映射的过程。具有局部连接和共享权重的特点。
几个关键词:
感受视野(local receptive fields):一个像素对应回原图的区域大小,这里为卷积核的大小3*3
深度(depth):卷积核的维度
步长(stride):卷积核每次在图上移动的步长
填充值(zero-padding):是不是要在外圈加0

在这里插入图片描述
卷积就是对原图上和卷积核大小相同的区域做矩阵内积,对于上述图片,输入为3通道77的矩阵,卷积核深度为2,大小为33,即卷积核为2(深度)*3(每维个数)33,卷积结果加上偏执(3[每维个数]33)就得到输出(2[深度]33)。

池化

图片来自知乎。
在这里插入图片描述
池化也称为下采样,可以增大感受野,池化有平均池化,最大值池化。

经典网络LeNet-5学习

在这里插入图片描述
0.输入为一张13232的黑白图片。
1.第一层为卷积C1,卷积核为6155(深度,每维个数,长,宽),步长为1,输出为62828.
2.第二层为池化S2,pool核为1
622,步长为2,输出为61414.
3.第三层为卷积C3,卷积核为16655,步长为1,输出为161010
4.第四层为池化S4,pool核为1
1622,步长为2,输出为1655
5.第五层为卷积C5,卷积核为120655,卷积核大小与输入图像大小相同,输出为12011
6.第六层为全连接层F6,权重参数有120
84个,阈值参数有84个。输出为84
7.第七层为输出层,参数有10*(84+1)个,输出为10

CNN实战:手写数字识别MNIST数据集

环境

python 3.6
pytorch 1.6.0
cuda 10.2

CNN代码

import torch
import time
import numpy as np
from matplotlib import pyplot as plt
from torch import nn, optim
from torch.autograd import Variable
from torch.utils.data import DataLoader
from torchvision import datasets, transforms

###CNN网络结构
class CNN(nn.Module):
    def __init__(self):
        # 初始化
        super(CNN,self).__init__()
        #卷积1*28*28->25*26*26,并进行归一化和激活函数,inplace-选择是否覆盖原值
        self.layer1 = nn.Sequential(
            nn.Conv2d(1,25,kernel_size=3),
            nn.BatchNorm2d(25),
            nn.ReLU(inplace=True)
        )
        #卷积25*26*26 -> 50*24*24
        self.layer2 = nn.Sequential(
            nn.Conv2d(25,50,kernel_size=3),
            nn.BatchNorm2d(50),
            nn.ReLU(inplace=True)
        )
        #池化50*24*24 -> 50*12*12
        self.layer3 = nn.Sequential(
            nn.MaxPool2d(kernel_size= 2 ,stride=2)
        )
        #卷积50*12*12 -> 100*10*10
        self.layer4 = nn.Sequential(
            nn.Conv2d(50,100,kernel_size=3),
            nn.BatchNorm2d(100),
            nn.ReLU(inplace = True)
        )
        #池化100*10*10 -> 100*5*5
        self.layer5 = nn.Sequential(
            nn.MaxPool2d(kernel_size=2,stride=2)
        )
        #全连接层100*5*5 -> 10
        self.layer6 = nn.Sequential(
            nn.Linear(100*5*5,1024),
            nn.ReLU(inplace=True),
            nn.Linear(1024,128),
            nn.ReLU(inplace=True),
            nn.Linear(128,10),
        )

    def forward(self,x):
        x = self.layer1(x)
        x = self.layer2(x)
        x = self.layer3(x)
        x = self.layer4(x)
        x = self.layer5(x)
        # 将张量reshape为一维
        x = x.view(x.size(0),-1)
        x = self.layer6(x)
        return (x)

###MNIST数据集下载
#一批送入100个
batch_size = 50
#图像预处理:Totensor归一化到(0,1),Normalize标准化到(-1,1)
data_tf = transforms.Compose(
    [transforms.ToTensor(),
        transforms.Normalize([0.5],[0.5])
    ])
#使用dataset类定义数据集
dataset_train = datasets.MNIST(root='./MNIST',
    train=True,transform=data_tf,download=True)
dataset_test = datasets.MNIST(root='./MNIST',
    train=False,transform=data_tf)
#使用Dataloader加载数据(shuffle表示是否打乱数据顺序)
train_loader = DataLoader(dataset_train,batch_size=batch_size,shuffle=True)
test_loader = DataLoader(dataset_test,batch_size=batch_size,shuffle=True)

###定义和初始化
learning_rate = 0.01
epoches_num = 30
#使用GPU
CNN_model = CNN()
if torch.cuda.is_available():
    CNN_model = CNN_model.cuda()
#损失函数和优化器
lossfunction = nn.CrossEntropyLoss()
optimizer = optim.SGD(CNN_model.parameters(),lr=learning_rate)

###训练
epoch = 0
loss_log = []
for i in range(epoches_num):
    loss_print = 0
    start = time.clock()
    for data in train_loader:
        img,lable = data
        #变量初始化
        if torch.cuda.is_available():
            img = img.cuda()
            lable = lable.cuda()
        else:
            img = Variable(img)
            lable = Variable(lable)
        output = CNN_model.forward(img)
        #计算LOSS
        loss = lossfunction(output,lable)
        loss_print += loss.item() * lable.size(0)
        #梯度置零
        optimizer.zero_grad()
        #反向传播
        loss.backward()
        optimizer.step()
    end = time.clock()
    epoch+=1
    loss_print = loss_print  / (len(dataset_train))
    print('第',epoch,'轮耗时',end-start)
    print('epoch:{},loss:{}'.format(epoch, loss_print))
    loss_log.append(loss_print)



###测试
CNN_model.eval()
eval_loss = 0
eval_acc = 0
for data in test_loader:
    img, label = data
    if torch.cuda.is_available():
        img = img.cuda()
        label = label.cuda()

    out = CNN_model.forward(img)
    loss = lossfunction(out, label)
    #上一步计算loss时对这一batch的loss进行了平均,所以现在要乘label.size(0)也就是乘batc_size
    eval_loss += loss.item() * label.size(0)
    _, pred = torch.max(out, 1)
    #统计这一批次中正确预测的个数
    num_correct = (pred == label).sum()
    eval_acc += num_correct.item()
print('Test Loss: {:.6f}, Acc: {:.6f}'.format(
    eval_loss / (len(dataset_test)),
    eval_acc / (len(dataset_test)))
)


#绘制损失函数曲线
epoch_range = range(epoch)
plt.figure(1)
plt.plot(epoch_range, loss_log)
plt.show()

训练集损失函数曲线:
在这里插入图片描述
训练30轮后的训练集损失函数为0.0011,测试集损失函数为0.0256,测试集准确率为0.992.
在这里插入图片描述

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值