卷积神经网络基础

1. 图像基础知识

1.1 图像的基本概念

图像是由像素点组成的,每个像素点的取值范围为: 0, 255 。像素值越接近于0,颜色越暗,接近于黑色;像素值越接近于255,颜色越亮,接近于白色。

我们使用的图像大多是彩色图,彩色图由RGB3个通道组成

什么是RGB3个通道?

RGB:red、green、blue 三原色

HWC ->heiget, width, channel

3通道指转换后数组的格式为 heiget, width, 3

数据示例:

HWC ->heiget, width, channel ->(640, 640, 3):

\[\[212 113 94

212 113 94

212 113 94

...

115 40 63

108 34 57

103 31 55\]

\[212 113 94

212 113 94

212 113 94

...

107 32 55

99 27 51

94 24 48\]

\[212 113 94

211 112 93

211 112 93

...

96 23 50

88 18 44

84 15 43\]

...

\[205 183 196

205 183 196

205 183 195

...

229 193 205

231 193 204

231 193 204\]

\[240 230 239

240 230 238

240 230 238

...

251 230 237

251 230 237

250 229 236\]

\[255 252 255

255 253 255

255 253 255

...

255 249 253

255 248 252

255 247 251\]\]

1.2 使用matplotlib加载图片方法

plt.imshow(img) # 加载

img = plt.imread(r'./data/img.jpg') # 读取本地图片,转换为HWC 格式数据

python 复制代码
import matplotlib
import matplotlib.pyplot as plt
import numpy as np

matplotlib.use("TkAgg")

# img = np.zeros(shape=[300, 200, 3])
# img = np.full(shape=[300, 200, 3], fill_value=255)

# plt.imshow(img)
# plt.show()

# 读取本地图片,并加载展示
img = plt.imread(r'./data/img.jpg')
print(img.shape)
print(img)
plt.imshow(img)
plt.show()

2. CNN概述

2.1 什么是卷积神经网络?

卷积神经网络(Convolutional Neural Network)是含有卷积层的神经网络。 卷积层的作用就是用来自动学习、提取图像的特征.

用途:大多用来处理图像

2.2 卷积神经网络组成部分

CNN网络主要由三部分构成:卷积层、池化层和全连接层构成:

卷积层负责提取图像中的局部特征;

池化层用来大幅降低参数量级(降维);

全连接层用来输出想要的结果

3. 卷积层------提取图像中的局部特征

3.1 掌握卷积层计算过程

3.1.1 单通道卷积计算

input 表示输入的图像

filter 表示卷积核, 也叫做卷积核(滤波矩阵)

input 经过 filter 得到输出为最右侧的图像,该图叫做特征图(feature map)

计算过程:

卷积运算本质上就是在卷积核和输入数据的局部区域间做点积。

4 = (1x1 + 1x0 + 1x1) + (0x1+1x1+1x0) + (0x1+0x0+1x1)

最终的特征图结果为:

Padding:

作用:中间的数据可以多次扫描,边上的只能扫描一次。通过在边上添加一圈0的方式,实现对边上的数据实现多次扫描

Stride(步长):

移动卷积核的步长,一般步长都为1

3.1.2 多通道卷积计算:

计算过程:

① 分别计算各个通道的卷积 (-78, -81,88)

② 各个通道的结果相加,得最后结果 (相加得 -71)

3.1.3 多卷积核卷积:

计算过程:

① 两个卷积核:w0,w1

② 分别对w0,w1做多通道卷积

③ 最终得到两个结果

多卷积核卷积会形成多个结果

3.2 【掌握】特征图大小计算方法

输出特征图的大小与以下参数息息相关:

size: 卷积核/过滤器大小,一般会选择为奇数,比如有 1*1 、3*3、5*5

Padding: 零填充的方式

Stride: 步长

计算方法如下图所示:

输入图像大小: W x W

卷积核大小: F x F

Stride: S

Padding: P

输出图像大小: N x N

3.3 掌握PyTorch卷积层API

torch.nn.Conv2d(in_channels=3, out_channels=5, kernel_size=(3, 5), padding=0, stride=(1, 2))

参数:

in_channels: 输入图像大小

out_channels: 输出图像大小

kernel_size: 卷积核

padding: 添加0的圈数

stride: 步长

python 复制代码
import torch
import matplotlib.pyplot as plt

# 图像获取、数据处理
img = plt.imread(r'./data/img.jpg')
print(img.shape)

data = torch.tensor(img, dtype=torch.float32).permute(2, 0, 1).unsqueeze(0)
print(data.shape)

# 卷积层
conver_layer = torch.nn.Conv2d(in_channels=3, out_channels=5, kernel_size=(3, 5), padding=0, stride=(1, 2))
feature_map = conver_layer(data)
print(feature_map.shape)
# 卷积层2
conver_layer2 = torch.nn.Conv2d(in_channels=5, out_channels=2, kernel_size=3, padding=0, stride=1)
feature_map2 = conver_layer2(feature_map)
print(feature_map2.shape)


'''
输出:
(640, 640, 3)
torch.Size([1, 3, 640, 640])
torch.Size([1, 5, 638, 318])
torch.Size([1, 2, 636, 316])

'''

4. 池化层------大幅降低参数量级(降维)

4.1【掌握】池化层计算过程

4.1.1 【常用】最大池化

取选中区域(池化窗口内)的最大值,0,1,3,4 中的最大值

4.1.2 【了解】平均池化

取选中区域(池化窗口内)的平均值,0,1,3,4 中的平均值

4.2【掌握】PyTorch池化层API

最大池化:torch.nn.MaxPool2d(kernel_size=3, stride=1)

平均池化:torch.nn.AvgPool2d(kernel_size=3, stride=1)

参数:

kernel_size:池化窗口,类似于卷积核

stride:步长

python 复制代码
import torch

data = torch.tensor([[[[1, 3, 4, 5],
                       [2, 6, 8, 10],
                       [7, 9, 6, 2],
                       [6, 5, 8, 1]
                       ],
                      [[1, 3, 4, 5],
                       [2, 6, 8, 10],
                       [7, 9, 6, 2],
                       [6, 5, 8, 1]
                       ]
                      ]], dtype=torch.float32)
print(data.shape)
# 最大池化
pool_max = torch.nn.MaxPool2d(kernel_size=3, stride=1)
print(pool_max(data))
print(pool_max(data).shape)
# 平均池化
pool_avg = torch.nn.AvgPool2d(kernel_size=3, stride=1)
print(pool_avg(data))
print(pool_avg(data).shape)

'''
输出:
torch.Size([1, 2, 4, 4])
tensor([[[[ 9., 10.],
          [ 9., 10.]],

         [[ 9., 10.],
          [ 9., 10.]]]])
torch.Size([1, 2, 2, 2])
tensor([[[[5.1111, 5.8889],
          [6.3333, 6.1111]],

         [[5.1111, 5.8889],
          [6.3333, 6.1111]]]])
torch.Size([1, 2, 2, 2])

Process finished with exit code 0

'''

5. 图像分类案例

构建一个卷积神经网络, 并训练该网络实现图像分类

1、使用CIFAR10 数据集

2、卷积神经网络

3、使用下边指定网络结构

python 复制代码
import time

from torchvision.datasets import CIFAR10
from torchvision.transforms import ToTensor, Compose
import matplotlib.pyplot as plt
import matplotlib
from torch.utils.data import DataLoader
from torch import nn
import torch
from torchsummary import summary

matplotlib.use("TkAgg")


def get_data():
    data_train = CIFAR10(root=r"./data/", train=True, transform=Compose([ToTensor()]))
    data_test = CIFAR10(root=r"./data/", train=False, transform=Compose([ToTensor()]))
    return data_train, data_test


class BuildNetwork(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv1 = nn.Conv2d(in_channels=3, out_channels=6, kernel_size=3)
        self.pool1 = nn.MaxPool2d(kernel_size=2, stride=2)
        self.conv2 = nn.Conv2d(in_channels=6, out_channels=16, kernel_size=3)
        self.pool2 = nn.MaxPool2d(kernel_size=2, stride=2)
        self.linear1 = nn.Linear(in_features=576, out_features=120)
        self.linear2 = nn.Linear(in_features=120, out_features=84)
        self.linear_out = nn.Linear(in_features=84, out_features=10)

    def forward(self, x):
        x = torch.relu(self.conv1(x))
        x = self.pool1(x)
        x = torch.relu(self.conv2(x))
        x = self.pool2(x)
        x = x.reshape(x.shape[0], -1)
        x = torch.relu(self.linear1(x))
        x = torch.relu(self.linear2(x))
        out = self.linear_out(x)
        return out


def train(model, dataloader):
    # 损失函数
    error = nn.CrossEntropyLoss()
    # 优化器
    optimizer = torch.optim.Adam(model.parameters(), lr=0.001, betas=(0.9, 0.99))
    # 循环遍历
    epochs = 100
    for epoch in range(epochs):
        start_time = time.time()
        loss_sum = 0
        iter_num = 0
        for x, y in dataloader:
            # 结果预测
            y_pred = model(x)
            # 损失计算
            loss = error(y_pred, y)
            loss_sum += loss.item()
            iter_num += 1
            # 反向传播
            # 更新梯度
            optimizer.zero_grad()
            loss.backward()
            optimizer.step()
        print(f"epoch:{epoch},loss:{loss_sum / iter_num},time:{time.time() - start_time}")
    torch.save(model.state_dict(), r'./data/model_img.gth')


def evaluate(model, dataloader):
    # 模型加载训练好的参数
    weight = torch.load(r'./data/model_img.gth',weights_only=True)
    model.load_state_dict(weight)
    # 模型预测、准确度计算
    correct_sum = 0
    for x, y in dataloader:
        y_pred = model(x)
        y_pred = torch.argmax(y_pred, dim=-1)
        correct_sum += (y_pred == y).sum()

    acc = correct_sum/len(dataloader.dataset)
    print(f"准确率:{acc}")


if __name__ == '__main__':
    train_dataset, valid_dataset = get_data()
    print("数据集类别:", train_dataset.class_to_idx)
    train_dataloader = DataLoader(dataset=train_dataset, batch_size=10, shuffle=True)
    test_dataloader = DataLoader(dataset=valid_dataset, batch_size=10, shuffle=True)
    # for x, y in train_dataloader:
    #     print(x.shape)
    #     print(y)
    #     break
    model = BuildNetwork()
    # print(summary(model=model, input_size=(3, 32, 32), batch_size=10, device="cpu"))
    train(model=model, dataloader=test_dataloader)
    evaluate(model=model, dataloader=test_dataloader)


# 输出: 准确率:0.9904000163078308
相关推荐
湘美书院--湘美谈教育1 小时前
湘美谈教育AI经验集锦:细分领域的标准定义者
大数据·人工智能·深度学习
把你拉进白名单1 小时前
5.OpenClaw源码解析_提示词8层装载
人工智能·agent
火山引擎开发者社区1 小时前
火山引擎 Milvus 发布官方 CLI + Skill ,终端与对话双通道掌控向量数据库
人工智能
weixin_549808362 小时前
从“大海捞针“到“精准定位“:易薪路AI人才罗盘如何用AI重构企业人才选拔与组织发展
大数据·人工智能·重构
步步为营DotNet2 小时前
Blazor 在边缘计算客户端应用中的创新实践与深度解析
人工智能·microsoft·边缘计算
阿演2 小时前
DataDjinn 新版本更新:国产数据库支持、连接树体验、AI 查询和表格编辑继续增强
数据库·人工智能·ai·ai编程
城事漫游Molly2 小时前
质性研究AI工作流(六):质性研究质量检验的5维清单
人工智能·ai for science·定性研究
keykey6.2 小时前
迁移学习实战:用预训练模型做图像分类
开发语言·人工智能·深度学习·机器学习
码农小旋风2 小时前
上下文工程
人工智能·chatgpt·claude