目录
3>.全连接层(Fully Connected Layer):
一、引言
1、什么是卷积神经网络?
1)定义:
卷积神经网络(Convolutional Neural Network,CNN)是一种深度学习神经网络模型,主要用于处理和分析具有网格结构的数据,如图像和视频。CNN的设计灵感来源于生物学中视觉皮层的工作原理,它通过模拟人类视觉系统的方式来自动提取图像中的特征,因此在图像处理和计算机视觉任务中取得了巨大成功。
2)CNN的主要特点和组成部分包括:
1>.卷积层(Convolutional Layer):
卷积层是CNN的核心部分,它通过应用一系列滤波器(也称为卷积核)来提取图像中的特征。这些滤波器在整个输入图像上滑动,执行卷积操作,从而检测图像中的边缘、纹理和其他局部特征。
2>.池化层(Pooling Layer):
池化层用于减小特征图的尺寸,同时保留最重要的信息。最常见的池化操作是最大池化,它选择每个池化区域中的最大值作为代表性特征。
3>.全连接层(Fully Connected Layer):
全连接层将池化层输出的特征映射连接到神经网络的输出层,用于进行分类或回归任务。这些层通常包括多个神经元,进行高级特征的组合和学习。
3)训练过程:
CNN的训练过程通常包括前向传播和反向传播两个阶段。在前向传播中,输入数据通过网络,逐层计算并生成预测。然后,使用损失函数来比较预测和实际标签之间的差异。反向传播阶段通过梯度下降算法来调整网络的权重和偏置,以最小化损失函数,从而优化网络的性能。
4)应用场景:
CNN在计算机视觉任务中广泛应用,包括图像分类、物体检测、人脸识别、自动驾驶等领域。它的优势在于能够自动学习和提取图像中的特征,而无需手动设计特征提取器。这使得CNN成为处理大规模图像数据的有力工具。
2.为什么要用卷积神经网络?
卷积神经网络(Convolutional Neural Networks,CNNs)在深度学习领域被广泛使用的原因包括以下几点:
1).有效的特征提取:
CNNs 可以自动学习图像、视频和其他网格数据中的重要特征。卷积层通过卷积操作能够捕捉到输入数据的局部模式,而池化层则能够减小数据维度,从而提取出更加抽象的特征。这种特征提取能力对于处理具有空间结构的数据非常有用。
2).参数共享:
CNNs 中的卷积操作使用相同的权重(卷积核)对输入数据的不同区域进行处理,这被称为参数共享。这减少了模型的参数数量,使其更加高效,并且有助于防止过拟合。参数共享也使得CNNs对平移不变性具有很好的适应性,即模型可以识别相同特征在图像中的不同位置。
3).层次化表示:
CNNs 通常由多个卷积层和池化层组成,这种层次化结构允许网络从低级别的特征逐渐构建出高级别的特征表示。这有助于网络理解复杂的数据结构,并且能够更好地进行分类、检测和分割等任务。
4).适用于大规模数据:
CNNs 在大规模数据集上表现出色。由于它们的深度和参数共享特性,它们能够在大量数据上进行训练,并且通常能够取得良好的泛化性能。
5).广泛的应用领域:
CNNs 广泛用于图像处理、计算机视觉、自然语言处理等领域。它们被用于图像分类、目标检测、人脸识别、图像生成、自动驾驶、医学图像分析等众多应用中。
6).预训练模型:
现代CNNs还借助预训练的模型来加速和改善特定任务的训练。例如,可以使用在大规模图像数据上预训练的模型,然后微调它们来适应特定任务,这被称为迁移学习。
7).硬件加速支持:
卷积神经网络的计算需求较高,但现代硬件如图形处理单元(GPU)和专用的神经网络处理单元(NPU)已经针对深度学习任务进行了优化,使得CNNs 的训练和推理变得更加高效。
总之,卷积神经网络以其在图像和网格数据处理中的卓越性能和效率而闻名,适用于各种计算机视觉和自然语言处理任务,并在实际应用中取得了巨大成功。
3、卷积神经网络与神经网络的区别
卷积神经网络(CNN)和普通的神经网络(也称为全连接神经网络)在结构和应用领域上有一些重要区别,下面是它们之间的主要区别:
1.结构和层次化特征提取:
1>.CNN:CNN具有卷积层和池化层,这些层用于逐层提取图像的局部特征,例如边缘、纹理和形状。卷积操作通过卷积核在图像上滑动来检测这些特征,池化层用于减小特征图的尺寸。CNN的结构更加层次化,有助于自动学习和表示图像中的特征。
2>.普通神经网络:普通神经网络由全连接层组成,每个神经元与前一层的所有神经元相连接。这种结构适用于处理向量数据,但对于高维数据(如图像)来说,参数量非常庞大,容易导致过拟合,而且无法捕捉空间局部性。
2.参数共享:
1>.CNN:CNN在卷积层中使用参数共享的机制,即卷积核在整个输入上共享权重。这减少了参数数量,使网络更具可训练性,同时允许网络检测相同特征的不同位置。
2>.普通神经网络:在普通神经网络中,每个神经元都有独立的权重,导致参数数量庞大,容易产生过拟合。
3.适用领域:
1>.CNN:CNN主要用于处理具有网格结构的数据,如图像、视频和语音。它在计算机视觉和自然语言处理领域取得了巨大成功。
2>.普通神经网络:普通神经网络可以用于各种数据类型的任务,包括分类、回归和序列建模,但在处理图像等高维数据时,需要更多的参数和计算资源。
4.局部感知:
1>.CNN:CNN通过卷积核的局部感知机制,可以有效地捕捉输入数据中的局部特征,这对于图像处理非常重要。
2>.普通神经网络:普通神经网络在每一层都连接到上一层的所有神经元,不具备局部感知能力,适用于更抽象的特征表示。
总之,卷积神经网络和普通的神经网络在结构、参数共享、适用领域和特征提取等方面存在显著区别,使得CNN在处理图像等网格结构数据时更加高效和有效。普通神经网络则更适合处理向量型数据和一般性的神经网络任务。
二、项目实现
1、提出问题
处理MINST数据集(什么是MNIST数据?可见https://blog.csdn.net/AI_dataloads/article/details/133067624?spm=1001.2014.3001.5501)
2、代码部分
import torch #导入PyTorch库,这是一个用于构建深度学习模型的流行框架。
from torchvision import datasets
#从PyTorch的torchvision模块中导入datasets,这个模块提供了许多常见的计算机视觉数据集。
from torchvision.transforms import ToTensor
#从torchvision.transforms模块中导入ToTensor,这个变换用于将图像数据转换为PyTorch张量的格式。
training_data = datasets.MNIST(#使用datasets.MNIST构造函数创建MNIST数据集对象。
root='data', # 指定数据集的根目录,数据将会下载到这个目录下。
train=True, # 表示这是用于训练的数据集。
download=True, # 如果数据集不存在,将自动下载。
transform=ToTensor(), #将图像数据转换为PyTorch张量的格式。
)
# datasets.MNIST的参数:
# root(string): 表示数据集的根目录,
# train(bool, optional): 如果为True,则从training.pt创建数据集,否则从test.pt创建数据集
# download(bool, optional): 如果为True,则从internet下载数据集并将其放入根目录。如果数据集已下载,则不会再次下载
# transform(callable, optional): 接收PIL图片并返回转换后版本图片的转换函数
testing_data = datasets.MNIST(
root='data',
train=False,
download=True,
transform=ToTensor()
)
import matplotlib.pyplot as plt
#导入Matplotlib库:导入用于数据可视化的Matplotlib库。
figure=plt.figure()
#创建一个Matplotlib图像对象:使用plt.figure()创建一个空白的Matplotlib图像对象,后续将在这个图像上添加子图。
for i in range(9):#使用for循环可视化前9张训练集图像:
img,label=training_data[i]
#从training_data数据集中获取第i个图像和对应的标签。
figure.add_subplot(3,3,i+1)
#在Matplotlib图像上添加一个子图,3行3列,第i+1个子图。
plt.title(label)
#设置子图标题为图像的标签(数字0到9)。
plt.axis('off')
#关闭子图的坐标轴。
plt.imshow(img.squeeze(),cmap='gray')
#显示图像,img.squeeze()用于去除可能存在的单维度,
# cmap='gray'指定使用灰度颜色映射。
# plt.show()
#显示Matplotlib图像,它会展示出9张训练集图像的子图,每个子图上显示了图像的标签(对应的手写数字)。
from torch.utils.data import DataLoader
#此行从模块导入类。此类有助于在训练和测试期间批量加载数据。DataLoadertorch.utils.data
train_dataloader =DataLoader(training_data,batch_size=64)
#在这里,使用类创建一个对象。它初始化为 和 批大小 64。是用于训练模型的数据集。train_dataloaderDataLoadertraining_datatraining_data
test_dataloader = DataLoader(testing_data,batch_size=64)
#与上一行类似,为 创建批大小为 64 的对象。表示用于评估模型性能的数据集。test_dataloadertesting_datatesting_data
for X,y in test_dataloader:
print(f'Shape of X [N,C,H,E]{X.shape}')
print(f'Shape of y: {y.shape} {y.dtype}')
break
#此循环用于循环访问对象,提取批量数据。对于每个批次,它将输入数据分配给 ,并将相应的标签分配给 。由于语句,循环仅执行一次。
#在循环内部,它使用字符串插值 () 打印形状,表示它具有 尺寸 ,其中 是批大小,表示通道数,是高度,是输入数据的宽度或长度。它还打印形状及其数据类型 ()。
device = "cuda" if torch.cuda.is_available() else "mps" if torch.backends.mps.is_available() else 'cpu'
print(f"Using {device} device")
#此行根据支持 CUDA 的 GPU 和 MPS 的可用性设置变量。
# 它使用 检查启用了 CUDA 的 GPU 是否可用。如果为 true,则设置为“cuda”。
# 否则,它将使用 检查 MPS 是否可用。如果为 true,则设置为“mps”。如果两个条件都为 false,则设置为“cpu”。
from torch import nn
#此行从 PyTorch 库中导入(神经网络)模块,该模块提供了用于构建神经网络的各种类和函数。
class CNN(nn.Module):
def __init__(self):
super(CNN,self).__init__()#此代码定义一个名为从该类继承的类。该方法是类的构造函数,用于初始化对象。
self.conv1 = nn.Sequential(
nn.Conv2d(
in_channels=1,
out_channels=16,
kernel_size=5,
stride=1,
padding=2,
),#一个 2D 卷积层,它接受具有 1 个通道的输入,产生 16 个输出通道,使用内核大小为 5x5、步幅为 1 和填充为 2。
nn.ReLU(),#应用逐元素整流线性单元 (ReLU) 激活的激活函数。
nn.MaxPool2d(kernel_size=2),#最大池化层,以 2 的步幅执行 2x2 池化操作。
)#此代码定义了第一个卷积层。它是用于按顺序堆叠多个图层创建的。
self.conv2 = nn.Sequential(
nn.Conv2d(16,32,5,1,2),
nn.ReLU(),
nn.Conv2d(32,32,5,1,2),
nn.ReLU(),
nn.MaxPool2d(2),
)#此代码定义了第二个卷积层。它遵循与输入和输出通道大小相似的结构,但具有不同的输入和输出通道大小。
# self.conv3 = nn.Sequential(
# nn.Conv2d(32, 64, 5, 1, 2),
# nn.ReLU(),
# )
self.out=nn.Linear(32*7*7,10)
#这一行定义了输出层,它是一个全连接(线性)层。它接受前面卷积层的平坦化输入(32 * 7 * 7)并生成一个大小为10的输出,与分类任务中的类别数匹配。
def forward(self,x):
#forward方法定义了模型的前向传播。它指定了输入x如何流经网络的不同层
x=self.conv1(x)
x = self.conv2(x)
# x = self.conv3(x)
x=x.view(x.size(0),-1)
#在这种情况下,输入x通过conv1和conv2,然后通过展平操作(view)将输出展平。
x=self.out(x)
# 最后,展平后的张量被送入输出层(self.out),并返回结果。
return x
model=CNN().to(device)
#一个CNN类的实例被创建并赋值给model变量。.to(device)调用将模型参数移到指定的设备(例如,GPU上的“cuda”或CPU上的“cpu”)进行计算。
print(model)
def train(dataloader,model,loss_fn,optimizer):
model.train()
#通过这个方法将神经网络模型设置为训练模式,以确保在训练期间所需的操作(如批量归一化和丢弃)生效。
batch_size_num = 1
#初始化一个变量 batch_size_num,用于跟踪处理的批次数目。
for X,y in dataloader:#开始遍历训练数据加载器中的每个批次,每个批次包括输入数据 X 和相应的标签 y。
X , y = X.to(device),y.to(device)
#将输入数据 X 和标签 y 移动到指定的设备(可能是GPU或CPU),以便与模型的设备匹配。
pred = model.forward(X)
#使用神经网络模型进行前向传播,得到预测结果 pred。
loss = loss_fn(pred,y)
#使用指定的损失函数 loss_fn 计算模型的预测结果 pred 与真实标签 y 之间的损失。
optimizer.zero_grad()
#使用优化器zero_grad()方法将模型的梯度清零,以准备进行反向传播。
loss.backward()
#使用反向传播计算模型参数的梯度,以便优化器可以更新模型权重以最小化损失。
optimizer.step()
#使用优化器的 step() 方法来执行一步优化,即更新模型的权重。
loss_value = loss.item()#将损失值从 PyTorch 张量中提取出来,并存储在 loss_value 变量中。
# print(f'loss:{loss_value:>7f} [number:{batch_size_num}]')
batch_size_num+=1
#增加 batch_size_num 的值,以跟踪处理的批次数目。
def test(dataloader,model,loss_fn):
size= len (dataloader.dataset)
#计算测试数据集的总样本数。
num_batches = len(dataloader)
#计算测试数据集的总样本数。
model.eval()
#通过这个方法将神经网络模型设置为评估模式,以关闭一些在训练时启用的操作,例如丢弃。
test_loss,correct=0,0
#初始化两个变量 test_loss 和 correct,分别用于累积测试损失和正确分类的样本数量。
with torch.no_grad():
#使用 torch.no_grad() 上下文管理器,将其包裹的代码块中的梯度计算禁用,以减少内存使用和加速计算。
for X,y in dataloader:
#开始遍历测试数据加载器中的每个批次,每个批次包括输入数据 X 和相应的标签 y。
X,y=X.to(device),y.to(device)
#将测试数据移动到指定的设备,以确保与模型的设备匹配。
pred=model.forward(X)
#使用神经网络模型进行前向传播,得到预测结果 pred。
test_loss += loss_fn(pred,y).item()
#计算并累积测试损失,通过使用损失函数 loss_fn 计算模型的预测结果 pred 与真实标签 y 之间的损失。
correct += (pred.argmax(1)==y).type(torch.float).sum().item()
#计算并累积正确分类的样本数量。这里使用了 argmax 函数来找到预测结果中的最大值对应的类别,然后检查是否与真实标签匹配,并将匹配的结果转换为浮点数。
test_loss /=num_batches
#计算测试的平均损失,将累积的损失值除以批次数目。
correct /= size
#计算准确率,将正确分类的样本数量除以总样本数,然后将其乘以 100 得到百分比形式。
print(f'Test result:\n Accuracy:{(100*correct)}%,Avg loss: {test_loss}')
#打印测试结果,包括准确率和平均损失。
loss_fn = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(),lr=0.001)
#使用交叉熵损失函数和Adam优化器来训练模型,并在测试集上评估模型的性能。
epoch=10
for i in range(epoch):
print(f'Epoch{i+1}----------------')
train(train_dataloader, model, loss_fn, optimizer)
print('Done')
test(test_dataloader,model,loss_fn)
3、代码结果
三、总结:
其过程无非比普通神经网络多了卷积操作。。。