机器学习笔记(3)

机器学习笔记(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
        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)
        )
        #全连接层
        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)
        x = x.view(x.size(0),-1) #将张量reshape为一维
        x = self.layer6(x)
        return (x)

###MNIST数据集下载
#定义数据参数
batch_size = 100
#图像预处理: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=True,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 = 3
#使用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):
    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.data.item()
        #梯度置零
        optimizer.zero_grad()
        #反向传播
        loss.backward()
        optimizer.step()
    end = time.clock()
    epoch+=1
    print('第',epoch,'轮耗时',end-start)
    print('epoch:{},loss:{}'.format(epoch, loss_print))
    loss_log.append(loss_print)
#绘制损失函数曲线
plt.figure(1)
plt.plot(epoch, loss_log)
plt.show()

###测试
CNN_model.eval()
eval_loss = 0
eval_acc = 0

for data in test_loader:
    img_test,lable_test = data
    if torch.cuda.is_available():
        img_test = img_test.cuda()
        lable_test = lable_test.cuda()
        
    output_test = CNN_model.forward(img_test)
    loss_test = lossfunction(output_test,lable_test)
    eval_loss += loss_test.data.item()*lable_test.size(0)
    _, pred = torch.max(output_test, 1)
    num_correct = (pred == lable_test).sum()
    eval_acc += num_correct.item()
print('Test Loss: {:.6f}, Acc: {:.6f}'.format(
    eval_loss / (len(dataset_test)),
    eval_acc / (len(dataset_test))
))

训练集损失函数曲线:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/dbdxwyl/article/details/108317702