当前位置: 首页 > news >正文

PyTorch深度学习网络(二:CNN)

卷积神经网络(CNN)是一种专门用于处理具有类似网格结构数据的深度学习模型,例如图像(2D网格的像素)和时间序列数据(1D网格的信号强度)。CNN在图像识别、图像分类、物体检测、语音识别等领域有着广泛的应用。

CNN的核心特点包括局部连接和权值共享:

  1. 局部连接意味着每个神经元只与输入数据的一个局部区域相连,这大大减少了参数的数量,提高了计算效率;
  2. 权值共享是指在卷积层中,相同的卷积核被用于整个输入数据,这不仅进一步减少了参数数量,还使得模型具有平移不变性,即无论物体出现在图像的哪个位置,都能被识别出来。

CNN的基本结构包括输入层、卷积层、激活函数、池化层、全连接层和输出层:

  1. 输入层接收原始图像数据;
  2. 卷积层通过卷积操作提取图像的特征;
  3. 激活函数引入非线性,增强模型的表达能力;
  4. 池化层通过下采样减少数据量,同时保留重要特征,增强模型的鲁棒性,此外多层卷积和池化层的堆叠使得模型能够逐层提取更高层次的特征;
  5. 全连接层将前面各层提取的特征综合起来,用于最终的分类或回归任务。

这种结构使得CNN特别适合处理图像数据,能够自动学习图像中的复杂特征,实现高效准确的图像识别。

本文展示了几种CNN网络结构在图像或文本分类中的应用,包含以下内容:

  1. LeNet的搭建和应用
  2. 微调预训练的VGG16网络
  3. TextCNN的搭建和应用

一、LeNet的搭建和应用

LeNet是早期最经典的卷积神经网络,由 Yann LeCun 等人在 1998 年提出,最初用于手写数字识别(MNIST 数据集),取得了十分显著的效果,其网络结构如图所示:

图片来自 LeNet - Wikipedia

 代码如下:

import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.optim import Adam
import torch.utils.data as Data
import torchvision
from torchvision import models, transforms, datasetsfrom process import classify  # procss的代码见:https://blog.csdn.net/moyao_miao/article/details/141466047class LeNet(nn.Module):"""LeNet模型"""def __init__(self, size):super().__init__()self.conv1 = nn.Conv2d(1, 6, 5)self.pool1 = nn.MaxPool2d(2, 2)self.conv2 = nn.Conv2d(6, 16, 5)self.pool2 = nn.MaxPool2d(2, 2)s = size // 4 - 3self.fc1 = nn.Linear(16 * s * s, 120)self.fc2 = nn.Linear(120, 84)self.output = nn.Linear(84, 10)def forward(self, x):x = F.relu(self.conv1(x))x = self.pool1(x)x = F.relu(self.conv2(x))x = self.pool2(x)x = x.view(x.size(0), -1)x = F.relu(self.fc1(x))x = F.relu(self.fc2(x))output = self.output(x)return output

使用MNIST数据集训练模型:

if __name__ == '__main__':train_data = torchvision.datasets.MNIST(root=r"C:\Users\57158\data\MNIST",train=True,transform=transforms.ToTensor(),download=False,)test_data = torchvision.datasets.MNIST(root=r"C:\Users\57158\data\MNIST",train=False,transform=transforms.ToTensor(),download=False,)model = LeNet(28)optimizer = Adam(model.parameters(), lr=0.0003)criterion = nn.CrossEntropyLoss()device = torch.device("cuda" if torch.cuda.is_available() else "cpu")classify((train_data, test_data),model,optimizer,criterion,batch_size=64,epochs=5,device=device,)

分类效果:

 二、微调预训练的VGG16网络

VGG网络是由牛津大学视觉几何组(Visual Geometry Group)在2014年提出的一种卷积神经网络架构。它在当年的ImageNet图像分类挑战赛中取得了优异的成绩,并因其简洁的架构和良好的性能而广受欢迎。其网络结构如图所示:

VGG系列网络结构,图片来自 VGGNet-16 Architecture: A Complete Guide (kaggle.com)

VGG网络的主要特点:

  1. 深度:VGG网络以其深度著称,最深的版本(VGG16和VGG19)分别有16层和19层。这种深度使得网络能够学习到更复杂的特征。
  2. 小卷积核:VGG网络使用3x3的小卷积核,而不是之前常用的更大的卷积核(如7x7)。小卷积核的优势在于可以减少参数数量,同时通过叠加多个3x3卷积层可以模拟更大的感受野。
  3. 固定结构:VGG网络的结构非常规整,主要由卷积层和全连接层组成。卷积层通常使用ReLU激活函数,全连接层后面通常接一个softmax层用于分类。
  4. 池化层:VGG网络在每几个卷积层之后会插入一个最大池化层(Max Pooling),用于降低特征图的尺寸,减少计算量,并增强特征的平移不变性。

以VGG16为例,其结构如图: 

VGG16网络结构,图片来自 VGGNet-16 Architecture: A Complete Guide (kaggle.com)

尽管VGG网络具有简洁的结构和良好的性能,但由于其网络较深、参数较多,VGG网络的计算量和内存消耗都比较大,导致从头开始训练比较费时,而且对算力的要求也比较高。幸运的是PyTorch提供了预训练好的网络模型可供调用,开发者在其基础上微调即可快速搭建自己的网络。

一个通过微调预训练的VGG16网络用于分类10种猴子的图像分类器代码如下:

class MyVggModel(nn.Module):"""自定义的VGG16模型"""def __init__(self):super().__init__()# 加载预训练的vgg16模型vgg = models.vgg16(weights=models.VGG16_Weights.DEFAULT).features# 冻结参数for param in vgg.parameters():param.requires_grad_(False)# 预训练的vgg16的特征提取层self.vgg = vgg# 自定义的全连接层self.classifier = nn.Sequential(nn.Linear(25088, 512),nn.ReLU(inplace=True),nn.Dropout(p=0.5),nn.Linear(512, 256),nn.ReLU(inplace=True),nn.Dropout(p=0.5),nn.Linear(256, 10),nn.Softmax(dim=1),)# 定义网络的向前传播路径def forward(self, x):x = self.vgg(x)x = x.view(x.size(0), -1)output = self.classifier(x)return output

数据集来源:10 Monkey Species (kaggle.com)

数据预处理:

if __name__ == '__main__':# 对训练集的预处理train_data_transforms = transforms.Compose([transforms.RandomResizedCrop(224),  # 随机将图像裁剪为224*224transforms.RandomHorizontalFlip(),  # 随机水平翻转图像transforms.ToTensor(),  # 转化为张量并归一化至[0,1]transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])  # 图像标准化处理])# 对测试集的预处理test_data_transforms = transforms.Compose([transforms.Resize(256),  # 将图像缩放为256*256transforms.CenterCrop(224),  # 将图像从中心裁剪为224*224transforms.ToTensor(),  # 转化为张量并归一化至[0,1]transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])  # 图像标准化处理])# 读取图像train_data_dir = r'C:\Users\57158\data\10-monkey-species\training\training'train_data = datasets.ImageFolder(train_data_dir, transform=train_data_transforms)test_data_dir = r'C:\Users\57158\data\10-monkey-species\validation\validation'test_data = datasets.ImageFolder(test_data_dir, transform=test_data_transforms)

训练模型:

    model = MyVggModel()optimizer = Adam(model.parameters(), lr=0.0003)criterion = nn.CrossEntropyLoss()device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')classify((train_data, test_data),model,optimizer,criterion,batch_size=32,epochs=10,device=device,)

分类效果:

三、TextCNN的搭建和应用

TextCNN是一种用于文本分类的卷积神经网络模型,它由 Yoon Kim 在 2014 年提出。TextCNN 通过利用卷积层和池化层来捕捉文本中的局部特征,从而实现高效的文本分类。其结构如图:

TextCNN的结构,图片来自 1510.03820 (arxiv.org)

TextCNN 的基本结构包括以下几个部分:

  1. 嵌入层(Embedding Layer):将输入的词索引转换为词向量。这些词向量可以是预训练的,也可以是随机初始化的。
  2. 卷积层(Convolutional Layer):使用多个不同大小的卷积核来提取不同长度的特征。每个卷积核会在输入的词向量序列上滑动,生成特征图。
  3. 池化层(Pooling Layer):通常使用最大池化(Max Pooling)来提取每个特征图中的最大值,从而减少特征维度并保留最重要的特征。
  4. 全连接层(Fully Connected Layer):将池化后的特征向量输入到全连接层中,进行分类。
  5. 输出层(Output Layer):通常使用 softmax 函数来输出每个类别的概率。

一个通用的TextCNN网络代码如下:

import re
from functools import partial
from typing import Iteratorimport pandas as pd
import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.nn.utils.rnn import pad_sequence
from torch.optim import Adam
import torchtext;torchtext.disable_torchtext_deprecation_warning()
from torchtext.data.utils import get_tokenizer
from torchtext.vocab import build_vocab_from_iterator
from torchtext.data.functional import numericalize_tokens_from_iterator
from nltk.corpus import stopwordsfrom process import classify
# procss的代码见:https://blog.csdn.net/moyao_miao/article/details/141466047class TextCNN(nn.Module):"""TextCNN模型"""def __init__(self, vocab_size: int, embedding_dim: int, num_filters: int,filter_sizes: Iterator, num_classes: int, dropout: float = 0.5):"""初始化TextCNN模型:param vocab_size:词典大小:param embedding_dim:词向量维度:param num_filters:卷积核个数:param filter_sizes:卷积核尺寸:param num_classes:输出的维度:param dropout:Dropout概率"""super().__init__()# 嵌入层self.embedding = nn.Embedding(vocab_size, embedding_dim)# 卷积层self.convs = nn.ModuleList([nn.Conv2d(in_channels=1, out_channels=num_filters, kernel_size=(fs, embedding_dim)) for fs in filter_sizes])# 最大池化层self.pool = nn.AdaptiveMaxPool1d(1)# Dropout层self.dropout = nn.Dropout(dropout)# 全连接输出层self.fc = nn.Linear(len(filter_sizes) * num_filters, num_classes)# 定义网络的向前传播路径def forward(self, text):# text:(batch_size,MAX_LENGTH)embedded = self.embedding(text).unsqueeze(1)  # embedded:(batch_size,1,MAX_LENGTH,embedding_dim)conved = [F.relu(conv(embedded)).squeeze(3) for conv in self.convs]  # conved[n]:(batch_size,num_filters,MAX_LENGTH-filter_sizes[n]+1)pooled = [self.pool(conv).squeeze(2) for conv in conved]  # pooled[n]:(batch_size,num_filters)cat = self.dropout(torch.cat(pooled, dim=1))  # cat:(batch_size,num_filters*len(filter_sizes))return self.fc(cat)

使用IMDB数据集来训练模型:IMDB Dataset of 50K Movie Reviews (kaggle.com)

数据预处理一,文本清洗:

punctuation_regex = re.compile(r'[!"#$%&\'()*+,-./:;<=>?@\[\\\]^_`{|}~]')
stopwords_regex = re.compile('\\b(' + '|'.join(stopwords.words('english')) + ')\\b')
clean_ops = [str.lower,  # 转化为小写partial(re.sub, '<br /><br />', ' '),  # 去除换行符partial(re.sub, '\d+', ''),  # 去除数字partial(punctuation_regex.sub, ''),  # 去除符号partial(stopwords_regex.sub, ''),  # 去除停用词str.strip,  # 去除两端空格
]
def clean_text(s: str, ops: Iterator) -> str:"""模块化的文本清洗函数:param s: 待清洗的文本:param ops: 清洗函数列表:return: 清洗后的文本"""for op in ops:s = op(s)return stokenizer = get_tokenizer('spacy')
def token_gen(texts):"""生成token迭代器:param texts: 文本列表:return: token迭代器"""for text in texts:yield tokenizer(text)if __name__ == '__main__':df = pd.read_csv(r'C:\Users\57158\data\IMDB Dataset.csv')df['review'] = df['review'].apply(clean_text, ops=clean_ops)  # 文本清洗df['sentiment'] = df['sentiment'].apply(lambda x: 1 if x == 'positive' else 0)  # 标签转换df.to_csv(r'IMDB_Dataset_clean.csv', index=False)

数据预处理二,构建数字化文本矩阵:

    VOCAB_SIZE = 20000MAX_LENGTH = 100df = pd.read_csv(r'IMDB_Dataset_clean.csv')vocab = build_vocab_from_iterator(token_gen(df['review']), specials=['<UNK>'], max_tokens=VOCAB_SIZE)  # 构建词典vocab.set_default_index(vocab['<UNK>'])  # 设置默认索引处理未知词sequence = numericalize_tokens_from_iterator(vocab=vocab, iterator=token_gen(df['review']))  # 数字化文本token_ids = [torch.tensor(list(x)) for x in sequence]  # 将数字化的文本转换为tensorpadded_text = pad_sequence(token_ids, batch_first=True, padding_value=0)[:, :MAX_LENGTH]  # 填充文本并截断

注意:新版本的torchtext接口较旧版本变化比较大,很多旧版本的用法已经失效了,24年以前的torchtext教程就不用再看了。

训练模型:

    model = TextCNN(vocab_size=len(vocab),embedding_dim=MAX_LENGTH,num_filters=100,filter_sizes=[3, 4, 5],num_classes=2,)model.embedding.weight.data[vocab['<UNK>']] = torch.zeros(MAX_LENGTH)model.embedding.weight.data[vocab['<PAD>']] = torch.zeros(MAX_LENGTH)optimizer = Adam(model.parameters())criterion = nn.CrossEntropyLoss()device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')classify((padded_text, torch.tensor(df['sentiment'])),model,optimizer,criterion,batch_size=32,epochs=3,device=device,to_tensor=False,)

分类效果:

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 袋鼠云《数据资产管理白皮书》重磅发布,提供数据资产管理新思路,激发数据资产新动能(附下载)
  • .net framework 4.8 开发windows系统服务
  • [HZNUCTF 2023 preliminary]ppppop
  • Android活动(activity)与服务(service)进行通信
  • Android Telephony | operator.alpha 运营商名称信息来源代码解读
  • DHU 函数 ACSII 码排序
  • 【STM32】RS485
  • 年薪100万华为员工爆料:华为不存在40岁危机,原因很简单,40岁你都可以退休了!累计375万的股票,每年分红75万,直接养老了
  • redis学习笔记 ——redis中的四大特殊数据结构
  • 第四章(先学习第五章)-openmv和arduino和stm32的通信
  • python把dbc转换成excel
  • Python 中的 `AsyncIterable` 和 `AsyncGenerator`:对比、优缺点及使用场景
  • 兔子序列(c语言)
  • RabbitMQ 常见问题与故障排查
  • 推荐一款强大的 macOS 剪贴板增强工具:CleanClip
  • 【跃迁之路】【463天】刻意练习系列222(2018.05.14)
  • Docker容器管理
  • eclipse的离线汉化
  • iOS编译提示和导航提示
  • IP路由与转发
  • js
  • Node项目之评分系统(二)- 数据库设计
  • session共享问题解决方案
  • webpack4 一点通
  • 从0实现一个tiny react(三)生命周期
  • 猫头鹰的深夜翻译:Java 2D Graphics, 简单的仿射变换
  • 爬虫进阶 -- 神级程序员:让你的爬虫就像人类的用户行为!
  • 前端面试之CSS3新特性
  • 如何进阶一名有竞争力的程序员?
  • 提升用户体验的利器——使用Vue-Occupy实现占位效果
  • 学习笔记TF060:图像语音结合,看图说话
  • MPAndroidChart 教程:Y轴 YAxis
  • 如何在招聘中考核.NET架构师
  • ​secrets --- 生成管理密码的安全随机数​
  • ​VRRP 虚拟路由冗余协议(华为)
  • #Datawhale AI夏令营第4期#AIGC文生图方向复盘
  • #includecmath
  • $refs 、$nextTic、动态组件、name的使用
  • (06)Hive——正则表达式
  • (16)UiBot:智能化软件机器人(以头歌抓取课程数据为例)
  • (done) NLP “bag-of-words“ 方法 (带有二元分类和多元分类两个例子)词袋模型、BoW
  • (超详细)语音信号处理之特征提取
  • (第9篇)大数据的的超级应用——数据挖掘-推荐系统
  • (二)Pytorch快速搭建神经网络模型实现气温预测回归(代码+详细注解)
  • (十六)视图变换 正交投影 透视投影
  • (一)模式识别——基于SVM的道路分割实验(附资源)
  • (轉貼) UML中文FAQ (OO) (UML)
  • (自适应手机端)响应式服装服饰外贸企业网站模板
  • *ST京蓝入股力合节能 着力绿色智慧城市服务
  • .dwp和.webpart的区别
  • .NET Core 通过 Ef Core 操作 Mysql
  • .NET Framework 3.5安装教程
  • .NET(C#) Internals: as a developer, .net framework in my eyes
  • .NET/C# 获取一个正在运行的进程的命令行参数
  • .net对接阿里云CSB服务