1.CNN介绍

CNN输入主要是图像,模型大致分为4种结构

  • 卷积层:这一层负责提取图像特征,多种卷积核可以提取多种特征。一个卷积核覆盖的原始图像的范围叫做感受野(权值共享)。一次卷积运算提取的特征往往是局部的,难以提取出比较全局的特征,因此需要在一层卷积基础上继续做卷积计算,这也就是多层卷积。
  • 激活函数层:这一层的目的是在CNN中加入非线性,因为使用CNN来解决的现实世界的问题都是非线性的,而卷积操作是线性运算,所以必须使用一些激活函数如Relu, sigmoid,tanh等非线性函数使CNN具有非线性性质
  • 池化层:降维的方法,按照卷积计算得出的特征向量维度大的惊人,不但会带来非常大的计算量,而且容易出现过拟合,解决过拟合的办法就是让模型尽量“泛化”,也就是再“模糊”一点,那么一种方法就是把图像中局部区域的特征做一个平滑压缩处理(如平均或最大化),这源于局部图像一些特征的相似性(即局部相关性原理)。
  • 全连接层:这层是一个传统的多层感知机,它在输出层使用softmax进行分类

CNN优点

  • 权值共享
  • 自动提取特征

CNN缺点

  • 需要调参,需要大样本
  • 需要大的算力

CNN训练过程

  1. 首先随机初始化卷积核W以及其他参数b
  2. 输入图片进行前向传播,依次通过卷积,Relu和pooling层,最后通过全连接层的softmax输出针对该张图片属于每个类别的概率向量
  3. 计算损失,分类问题用交叉熵损失
  4. 梯度反向传播,更新卷积核的权重值,通常使用梯度下降法
  5. 重复3,4步骤直到结果收敛

2.CNN分类实战

模型任务是区分人民币一元和一百元

一元:

100元

代码使用pytorch框架

1. 模型构建代码

class LeNet(nn.Module):def __init__(self, classes):super(LeNet, self).__init__()self.conv1 = nn.Conv2d(3, 6, 5)self.conv2 = nn.Conv2d(6, 16, 5)self.fc1 = nn.Linear(16*5*5, 120)self.fc2 = nn.Linear(120, 84)self.fc3 = nn.Linear(84, classes)def forward(self, x):out = F.relu(self.conv1(x))out = F.max_pool2d(out, 2)out = F.relu(self.conv2(out))out = F.max_pool2d(out, 2)out = out.view(out.size(0), -1)out = F.relu(self.fc1(out))out = F.relu(self.fc2(out))out = self.fc3(out)return out

2.数据集定义

import os
import random
from PIL import Image
from torch.utils.data import Datasetrmb_label = {""1"": 0, ""100"": 1}class RMBDataset(Dataset):def __init__(self, data_dir, transform=None):""""rmb面额分类任务的Dataset:param data_dir: str, 数据集所在路径":param transform: torch.transform,数据预处理"""self.label_name = {""1"": 0, ""100"": 1}"self.data_info = self.get_img_info(data_dir)  # data_info存储所有图片路径和标签,在DataLoader中通过index读取样本self.transform = transformdef __getitem__(self, index):path_img, label = self.data_info[index]img = Image.open(path_img).convert('RGB')     # 0~255if self.transform is not None:img = self.transform(img)   # 在这里做transform,转为tensor等等return img, labeldef __len__(self):return len(self.data_info)@staticmethod   根据自己数据存储位置定义def get_img_info(data_dir):data_info = list()for root, dirs, _ in os.walk(data_dir):"# 遍历类别for sub_dir in dirs:img_names = os.listdir(os.path.join(root, sub_dir))"img_names = list(filter(lambda x: x.endswith('.jpg'), img_names))"# 遍历图片for i in range(len(img_names)):img_name = img_names[i]path_img = os.path.join(root, sub_dir, img_name)"label = rmb_label[sub_dir]data_info.append((path_img, int(label)))"return data_info

3.模型训练

import os
import random
import numpy as np
import torch
import torch.nn as nn
from torch.utils.data import DataLoader
import torchvision.transforms as transforms
import torch.optim as optim
from matplotlib import pyplot as plt
from model.lenet import LeNet
from tools.my_dataset import RMBDatasetrmb_label = {""1"": 0, ""100"": 1}# 参数设置
MAX_EPOCH = 10
BATCH_SIZE = 16
LR = 0.01  #学习率
log_interval = 10  # 决定多少个训练batch之后打印训练信息
val_interval = 1# ============================ step 1/5 数据 ============================base_dir = os.path.join("".."", "".."", ""data"")
train_dir = os.path.join(base_dir, ""train"")  # 训练集路径
valid_dir = os.path.join(base_dir, ""valid"")  # 验证集路径norm_mean = [0.485, 0.456, 0.406]  # 图片有3通道,所以标准化的均值和方差也有3个元素
norm_std = [0.229, 0.224, 0.225]train_transform = transforms.Compose([   # 处理输入的训练图片transforms.Resize((32, 32)),  #Lenet输入图片尺寸要求是32 x 32,所以必须resize一下transforms.RandomCrop(32, padding=4),transforms.ToTensor(),transforms.Normalize(norm_mean, norm_std),
])valid_transform = transforms.Compose([   # 处理验证集图片transforms.Resize((32, 32)),transforms.ToTensor(),transforms.Normalize(norm_mean, norm_std),
])# 构建MyDataset实例
train_data = RMBDataset(data_dir=train_dir, transform=train_transform)
valid_data = RMBDataset(data_dir=valid_dir, transform=valid_transform)# 构建DataLoder
train_loader = DataLoader(dataset=train_data, batch_size=BATCH_SIZE, shuffle=True)"
valid_loader = DataLoader(dataset=valid_data, batch_size=BATCH_SIZE)"# ============================ step 2/5 模型 ============================net = LeNet(classes=2)   # 输出只有2类:1元,100元
#net.initialize_weights() # 权重初始化策略,可以不写,模型自动随机初始化# ============================ step 3/5 损失函数 ============================
criterion = nn.CrossEntropyLoss()      #交叉熵损失                                          # ============================ step 4/5 优化器 ============================
# 选择优化器"
optimizer = optim.SGD(net.parameters(), lr=LR, momentum=0.9)   # 随机梯度下降
# 设置学习率下降策略"
scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=10, gamma=0.1)     # ============================ step 5/5 训练 ============================
train_curve = list()
valid_curve = list()for epoch in range(MAX_EPOCH):loss_train = 0.correct = 0.total = 0.net.train()  # net.train() 和 net.eval()是两种不同的模式,后者不对权重更新for i, data in enumerate(train_loader):"# forwardinputs, labels = dataoutputs = net(inputs)# backwardoptimizer.zero_grad() # 梯度手动清零loss = criterion(outputs, labels) # 计算损失loss.backward()  # 反向传播# update weightsoptimizer.step()# 统计分类情况_, predicted = torch.max(outputs.data, 1) # torch.max返回最大值及其对应的索引total += labels.size(0) # 每个训练batch的样本加和correct += (predicted == labels).squeeze().sum().numpy() # 每个训练batch中的预测值和标签对比,计算正确预测个数,并且每个训练batch的正确个数加和# 打印训练信息loss_train += loss.item() # 每个训练batch的loss加起来train_curve.append(loss.item()) # train_curve 记录了训练集每个batch的损失if (i+1) % log_interval == 0: # 决定log_interval 个训练batch之后,打印训练信息loss_mean = loss_train / log_intervalprint("Training:Epoch[{:0>3}/{:0>3}] Iteration[{:0>3}/{:0>3}] Loss: {:.4f} Acc:{:.2%}".format(epoch, MAX_EPOCH, i+1, len(train_loader), loss_mean, correct / total))loss_train = 0.  # len(train_loader)表示训练集有多少个batch# correct/total 表示经历log_interval个batch之后的正确率scheduler.step()  # 更新学习率,在一轮for循环之外,记住一个epoch才更新一次 “学习率”# validate the modelif (epoch+1) % val_interval == 0: 因为val_interval=1,所以每隔一个Epoch就验证一次correct_val = 0.total_val = 0.loss_val = 0.net.eval()  # 验证模式下必须调成evalwith torch.no_grad(): # 这句话可以加快训练for j, data in enumerate(valid_loader):inputs, labels = data"outputs = net(inputs)loss = criterion(outputs, labels)"_, predicted = torch.max(outputs.data, 1)"total_val += labels.size(0)correct_val += (predicted == labels).squeeze().sum().numpy()loss_val += loss.item()loss_val_epoch = loss_val / len(valid_loader)valid_curve.append(loss.item())   # valid_curve 只记录了验证集最后一个batch的损失值print("Valid:\t Epoch[{:0>3}/{:0>3}] Iteration[{:0>3}/{:0>3}] Loss: {:.4f} Acc:{:.2%}".format(epoch, MAX_EPOCH, j+1, len(valid_loader), loss_val_epoch, correct_val / total_val))"train_x = range(len(train_curve)) # 长度应该为len(train_curve) = Max_Epoch * len(train_loader)
train_y = train_curvetrain_iters = len(train_loader) # 训练集有多少个batch
#### valid_x 也就是valid_curve横坐标一定要变,我们知道len(valid_curve) = Max_Epoch/val_interval(因为每隔val_interval只记录验证集最后一个batch的loss值)
#### 所以每当在训练集中记录了 len(train_loader)*val_interal 个loss值时,才在valid_curve 中记录一个loss值
valid_x = np.arange(1, len(valid_curve)+1) * train_iters * val_interval
# 由于valid中记录的是epoch_loss,需要对记录点进行转换到iterations"
valid_y = valid_curveplt.plot(train_x, train_y, label='Train')
plt.plot(valid_x, valid_y, label='Valid')plt.legend(loc='upper right')
plt.ylabel('loss value')
plt.xlabel('Iteration')
plt.show()# ============================ inference ============================
# 测试用例
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
test_dir = os.path.join(BASE_DIR, ""test_data"")"test_data = RMBDataset(data_dir=test_dir, transform=valid_transform)"
valid_loader = DataLoader(dataset=test_data, batch_size=1)"for i, data in enumerate(valid_loader):"# forwardinputs, labels = data"outputs = net(inputs)_, predicted = torch.max(outputs.data, 1)"rmb = 1 if predicted.numpy()[0] == 0 else 100print("模型获得{}元".format(rmb))

CNN人民币分类实战相关推荐

  1. 人工智能框架实战精讲:Keras项目-英文语料的DNN、Word2Vec、CNN、LSTM文本分类实战与调参优化

    Keras项目-英文语料的文本分类实战 一.机器学习模型 1.1 数据简介 1.2 数据读取与预处理 1.3 数据切分与逻辑回归模型构建 二.全连接神经网络模型 2.1 模型训练 2.2 模型结果展示 ...

  2. 基于CNN中文文本分类实战

    一.前言 之前写过一篇基于循环神经网络(RNN)的情感分类文章,这次我们换种思路,采用卷积神经网络(CNN)来进行文本分类任务.倘若对CNN如何在文本上进行卷积的可以移步博主的快速入门CNN在NLP中 ...

  3. 文本分类实战(三)—— charCNN模型

    1 大纲概述 文本分类这个系列将会有十篇左右,包括基于word2vec预训练的文本分类,与及基于最新的预训练模型(ELMo,BERT等)的文本分类.总共有以下系列: word2vec预训练词向量 te ...

  4. 英文文本分类实战总结

    之前参加了一个英文文本的分类比赛.比赛结束到了过年,加上开学又有一些事情,所以总结的工作就一直没有进行.现在空了一些,所以把之前的工作写一写,比赛中用到的代码也会放到github上. 对这个比赛的任务 ...

  5. textcnn文本词向量_基于Text-CNN模型的中文文本分类实战

    1 文本分类 文本分类是自然语言处理领域最活跃的研究方向之一,目前文本分类在工业界的应用场景非常普遍,从新闻的分类.商品评论信息的情感分类到微博信息打标签辅助推荐系统,了解文本分类技术是NLP初学者比 ...

  6. 基于keras的CNN图片分类模型的搭建以及参数调试

    基于keras的CNN图片分类模型的搭建与调参 更新一下这篇博客,因为最近在CNN调参方面取得了一些进展,顺便做一下总结. 我的项目目标是搭建一个可以分五类的卷积神经网络,然后我找了一些资料看了一些博 ...

  7. 使用KNN模型进行多标签分类实战(Multilabel Classification)

    使用KNN模型进行多标签分类实战(Multilabel Classification) 详细的:二分类.多分类.多标签分类.多输出分类的概念参考笔者如下博文. 分类家族:二分类.多分类.多标签分类.多 ...

  8. 使用KNN模型进行多输出分类实战(Multioutput Classification)

    使用KNN模型进行多输出分类实战(Multioutput Classification) 详细的:二分类.多分类.多标签分类.多输出分类的概念参考笔者如下博文. 分类家族:二分类.多分类.多标签分类. ...

  9. 【英文文本分类实战】之四——词典提取与词向量提取

    ·请参考本系列目录:[英文文本分类实战]之一--实战项目总览 ·下载本实战项目资源:神经网络实现英文文本分类.zip(pytorch) [1] 提取词典   在这一步,我们需要把训练集train.cs ...

最新文章

  1. DokuWiki 开源wiki引擎程序
  2. 高精度除以低精度板子
  3. php mysql简单留言本_php+mysql写的简单留言本实例代码
  4. 使用自己的数据集训练GoogLenet InceptionNet V1 V2 V3模型(TensorFlow)
  5. 区块链中的数学 - EdDSA签名机制
  6. 宽带——选择中国电信
  7. vue去掉#——History模式
  8. JavaScript如何对欧姆龙、三菱、施耐德等PLC进行读写通讯控制
  9. ccy测试影响因子版270ms
  10. python 100天 github_GitHub - theroad/Python-100-Days: Python - 100天从新手到大师
  11. 自然语言处理面试基础
  12. 2022年12月蓝桥STEMA评测C++中级组编程题
  13. 安徽省二计算机office试题及答案,计算机二级(MSOFFICE)模拟考试题及答案题目2
  14. 部署-Mycat-Server-1.6.7.4安装与配置(CentOS 7.7)
  15. ImageEdit 展示图片(XAML, C#)
  16. 一劳永逸解决vs编译器无法使用scanf函数
  17. 信号系统中的特征函数和特征值
  18. 我们跟30家PoS团队聊了聊,Staking最硬核的干货都在这儿了
  19. XenDesktop7.12发布应用程序
  20. stream流倒序排序_java8 stream 操作map根据key或者value排序的实现|chu

热门文章

  1. c++后台开发项目_5900万!腾讯云中标安徽宿州wecity智慧园区EPC项目(含智慧路灯)...
  2. 解决:Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
  3. Struts2 官方教程之Struts Tags(六)——Generic Tags(Control Tags )
  4. 新品周刊 | 可口可乐与时尚包袋品牌Kipling推出联名系列;阿迪达斯推出电竞灵感跑鞋...
  5. 小米8 解账户锁 线刷包 刷入 教程 MIUI12系统
  6. 2022 PostgreSQL 数据库生态大会:拓数派资深工程师 王淏舟将发表主题演讲
  7. 沐阳学爬虫11 Requests+PyQuery+PyMongo基本案例实践
  8. DockerHub入门
  9. 太平洋帕劳:上帝的水族箱
  10. mysql ud83cudf19__如何转义emoji表情,让它可以存入utf8的数据库?