重生归来,我要成功 Python 高手--day38 CNN卷积神经网络
CNN:含有卷积层的神经网络 由:卷积层 池化层 全连接层组成
作用:用来自动学习提取图像的特征
1.卷积层:负责提取图像中的局部特征
2.池化层:用来大幅度降低参数量级
3.全连接层:用来输出想要的结果
应用:图像分类,目标检测,图像分割,人脸识别,医学影像分析,自动驾驶
卷积层:
input:表示输入的图像
filter:表示卷积核
input经过filter得到的图像叫做特征图
卷积的计算:就是在卷积核和输入数据的局部特征做点积,对应位置相乘结果做相加

通过上面的计算。最终的特征图比原始图像小得多,如果想要保持特征图不变,可以在原图的周围添加padding来实现 目的:在输入图像的边缘添加额外的元素,从而解决卷积操作时边缘信息丢失的问题
步长:卷积核在图像上滑动时步伐的大小,即每次卷积时卷积核在图像右(向下)移动的像素数
步长影响卷积操作后输出的特征图的尺寸,以及计算量和模型的特征提取能力
多通道做计算,每个通道与对应卷积核做点乘最后结果相加就是当前点的结果
特征图的大小:
1.size:卷积核的大小
2.padding:零填充的方式
3.stride:步长
计算方式如下:
输入图像大小:W*W
卷积核的大小:F*F
Stride:s
padding:P
输出图像的大小:N*N
N=w-f+2p/s+1
卷积层的API:
提取局部特征:
1.读取图像,numpy(维度为:HWC:
2.将图像转化为tensor,维度为:HWC:
3.因为tensor要求的维度为CHW,所以需要交换维度,permute
4.使用cnn要求为四维,所以在第零维增加一个维度
5.调用api进行处理
调用api 传入的通道数为3,输出的通道数为4 卷积核为3 步长为2 填充为0
输出的通道数为多个图片的堆叠
6.拿你想要输出的图像为三维
7,因为时CHW需要交换维度为 HWC进行numpy的输出
import torch
import torch.nn as nn
import matplotlib.pyplot as plt
# 读取图片,类型为numpy
def dm01():
# 读取图像
img=plt.imread('../img/img.jpg')
# 转化数据类型,numpy转化为tensor,转化数据格式为torch.
img=torch.tensor(img,dtype=torch.float)
# 进行数据维度的改变 原本的为whc 要转化为chw
img=img.permute(2,0,1)
# 因为使用conv2d需要的数据为四维的所有需要进行升维
# 转化成 nchw 会在零轴添加一个1的维度
img=img.unsqueeze(0)
# 调用api 传入的通道数为3,输出的通道数为4 卷积核为3 步长为2 填充为0
conv=nn.Conv2d(3,4,3,2,0)
# 对图像进行处理
img_conv=conv(img)
# 生成的图片是一张,四通道的图片,所有我们要获取第一张图
img=img_conv[0]
# 这个图片是chw 要转化为hwc
img1=img.permute(1,2,0)
# 将这个图像转化为numpy
img1_feature1 = img1[:, :, 2].detach().numpy()
plt.imshow(img1_feature1)
plt.show()
if __name__=='__main__':
dm01()
池化层:减低维度,从而减少计算量,减少内存消耗,并提高模型的鲁棒性
池化层通常位与卷积层之后,他通过对池化层输出的特征图进行下采样,保留最重要的特征信息要的细节
最大池化演示,例如你池化层是2*2,步长为1,在这个2*2的范围中找最大值
平均池化演示:例如你池化层是2*2,步长为1,在这个2*2的范围所有数的哦平均值就是你得输出
3*3的特征经过2*2的池化层得到一个2*2的输出结果
多通道的池化层计算,与卷积层不同,不对结果进行相加每一个通道数对应一个池化层的输出
填充和步长与卷积层类似
API:
import torch
import torch.nn as nn
#1.定义函数 ,演示单通道池化
def dm01():
#1.创建一个 1通道 3*3 二维矩阵
inputs=torch.tensor([
[
[0,1,2],
[3,4,5],
[6,7,8]
]
])
# print(f"inputs:{inputs.shape}") #([1, 3, 3])
#2.创建最大池化 池化窗口 步长 填充的值
max_pool=nn.MaxPool2d(2,1,0)
output=max_pool(inputs)
print(f"{output}")
#3.平均池化
avg_pool=nn.AvgPool2d(2,1,0)
output=avg_pool(inputs)
print(f"{output}")
#2、定义函数 演示多通道池化
def dm02():
#1.创建1个 3通道啊 3*3 二维矩阵
inputs=torch.tensor([
[ #通道1 HW :3,3
[0, 1, 2],
[3, 4, 5],
[6, 7, 8]
],
[ # 通道2 HW :3,3
[10, 1, 2],
[3, 4, 5],
[6, 7, 8]
],
[ # 通道3 HW :3,3
[11, 1, 2],
[3, 4, 5],
[6, 7, 8]
],
])
print(f"inputs:{inputs.shape}")
#2.创建最大池化
max_pool=nn.MaxPool2d(2,1,0)
output=max_pool(inputs)
print(f"最大池化:{output}")
#3.平均池化
avg_pool=nn.AvgPool2d(2,1,0)
output=avg_pool(inputs)
print(f"平均池化:{output}")
if __name__ == '__main__':
# dm01()
dm02()
CNN案例:
思路:
1.获取数据:
1.df对象-》张量-》张量数据集-》数据加载器
2.搭建卷积神纪网络:
1.自定义模型类继承:nn.module
2.重写__init__和forward方法
3,训练模型:
1。获取训练数据
2.获取模型
3.创建损失函数
4.创建优化器
5.双层for循环
6.保存模型
4.评估模型
1.获取验证集数据
2.加载模型参数
3.模型预测
4.模型计算评估结果
5.模型调优
from torchvision.datasets import CIFAR10
from torchvision.transforms.transforms import ToTensor
import matplotlib.pyplot as plt
from torch.utils.data import DataLoader
import torch
import torch.nn as nn
from torchsummary import summary # 查看参数
import time
# 中文乱码问题
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
#TODO 1:获取数据
def get_data_loader(batch_size):
# 获取数据集
train_dataset=CIFAR10(root='../data',train=True,download=True,transform=ToTensor())
test_dataset=CIFAR10(root='../data',train=False,download=True,transform=ToTensor())
# 查看数据集的类和对应的标签
# print(test_dataset.class_to_idx)
# # 展示其中的一个
# plt.imshow(train_dataset.data[9])
# # 获取对应的啊标签
# plt.title(train_dataset.targets[9])
# plt.show()
# 将张量数据集转化为数据加载器,训练集需要打乱数据
train_loader = DataLoader(train_dataset,batch_size=batch_size,shuffle=True)
# 测试集不需要打乱数据
test_loader = DataLoader(test_dataset,batch_size=batch_size,shuffle=False)
return train_loader,test_loader
# 创建CNN卷积神经网络
class CoMdel(nn.Module):
# 继承父类的init方法
def __init__(self):
super().__init__()
#创建第一个卷积层 输入为3是RGB三个颜色 ,输出为6是说这一层有六个卷积核
self.conv1 = nn.Conv2d(3,6,3,1,0)
# 池化层1, 参数 池化核的大小 步长,填充为0
self.pool1 = nn.MaxPool2d(2,2,0)
# 卷积层2
self.conv2 = nn.Conv2d(6,16,3,1,0)
# 池化层2
self.pool2 = nn.MaxPool2d(2,2,0)
# 隐藏层1
self.linear1 = nn.Linear(576,120)
# 隐藏层2
self.linear2 = nn.Linear(120,84)
# 输出层
self.output = nn.Linear(84,10)
# forward
def forward(self,x):
# 先进行卷积再进行激活函数最后进行池化
# 所以池化层不需要relu函数
# 第一次的卷积激活池化
x=self.pool1(torch.relu(self.conv1(x)))
# 第二次的卷积激活池化
x=self.pool2(torch.relu(self.conv2(x)))
# 因为全连接层只能处理二维的张量,所以需要对数据进行维度的拉平
x=x.reshape(x.shape[0],-1)
# print(f'shape:{x.shape}')
# 隐藏层1
x=torch.relu(self.linear1(x))
# 隐藏层2
x=torch.relu(self.linear2(x))
# 后续需要使用多变量交叉熵,所以此不进行softmax激活函数处理
x=self.output(x)
return x
# 模型的训练
# #传入的参数是训练加载器和模型,轮次
def train_model(train_loader,model,epochs):
# 创建损失函数,使用多类别交叉熵
loss_fn=torch.nn.CrossEntropyLoss()
# 创建优化器
optimizer=torch.optim.Adam(model.parameters(),lr=0.001)
# 进行循环
epochs=epochs
for epoch in range(epochs):
# 初始一些参数,方便展示
total_loss, corrent, sample_cut, start = 0.0, 0, 0, time.time()
for x,y in train_loader:
# 模型的训练
y_pred=model(x)
# 损失函数的计算
loss=loss_fn(y_pred,y)
# 梯度清零
optimizer.zero_grad()
# 前向传播
loss.backward()
# 更新梯度
optimizer.step()
# 当前轮次的总的损失值
total_loss += loss.item()*len(x)
# 当前轮次实际参与的样本数
sample_cut+=len(x)
# 累计预测正确数量
# 指向最后一个维度,最后一个维度为样本的类别
corrent += (torch.argmax(y_pred, dim=-1) == y).sum()
# 走到这里,说明一轮结束,计算损失值和准确率
epoch_loss = total_loss / sample_cut
epoch_acc = corrent / sample_cut
print(
f"第{epoch + 1}轮,运行时间:{time.time() - start:.2f}秒,损失值:{epoch_loss:.2f},准确率为:{epoch_acc:.2f}")
# 6.保存训练好的模型参数字典
torch.save(model.state_dict(), "../model/imge_model.pth")
# todo 4.模型评估&测试
def evaluate(test_loader): # test_dataset
# 1.创建测试集(已经当参数传递)
# 2.创建模型对象
model = CoMdel()
# 3.加载模型参数
model.load_state_dict(torch.load("../model/imge_model.pth"))
# 4.定义变量统计
total_correct, total_samples = 0, 0
# .遍历数据加载器
for x, y in test_loader:
# 5.1切换模型模式
model.eval()
# 5.2模型预测
y_pred = model(x)
# 5.3因为训练的时候使用多分类交叉熵。
y_pred = torch.argmax(y_pred, dim=-1)
#5.4统计预测正确样本个数
total_correct+=(y_pred==y).sum()
#5.5统计总的样本数
total_samples+=len(y)
# 6.打印正确率(预测结果)
print(f"ACC:{total_correct/total_samples:.2f}")
if __name__ == '__main__':
batch_size=8
# 创建模型对象
model=CoMdel()
train_loader, test_loader = get_data_loader(batch_size)
# 查看模型参数
# summary(model,(3,32,32),batch_size=batch_size)
# 模型的训练
#
# epochs = 5
# train_model(train_loader, model, epochs)
# 模型的测试
evaluate(test_loader)
更多推荐


所有评论(0)