【深度学习】 零基础介绍卷积神经网络(CNN)

CNN学习

  • 零基础介绍
  • 写个CNN最简单的代码
  • [一. 概述](#一. 概述)
  • [二. 搭建CNN](#二. 搭建CNN)
    • [1. 输入层](#1. 输入层)
    • [2. 卷积层](#2. 卷积层)
    • [3. 激活层](#3. 激活层)
    • [4. 池化层](#4. 池化层)
    • [5. 全连接层](#5. 全连接层)
    • [6. 网络搭建小结](#6. 网络搭建小结)
    • [7. 损失函数](#7. 损失函数)
    • [8. 梯度下降](#8. 梯度下降)
    • [9. 反向传播](#9. 反向传播)
    • [10. 模型评估与正则化](#10. 模型评估与正则化)
    • [11. 尝试搭建自己的第一个CNN](#11. 尝试搭建自己的第一个CNN)
  • [三. 经典CNN结构](#三. 经典CNN结构)
  • [四. 猫狗识别项目实践](#四. 猫狗识别项目实践)
    • [1. Paddle实现版本:](#1. Paddle实现版本:)
    • [2. Keras 和 TensorFlow实现版本](#2. Keras 和 TensorFlow实现版本)
  • 提问检测环节

零基础介绍

卷积神经网络(CNN,Convolutional Neural Network)是深度学习中的一种神经网络,特别擅长处理图像和视频等有空间结构的数据。

假设我们在做一个"照片分类"的任务,比如判断一张照片中是猫还是狗。下面用一个通俗的例子来解释CNN的工作原理。

  1. 看图的方式:模拟人眼

    当我们看一张图片时,并不是从头到尾一口气看完的,而是我们的眼睛会专注于某个小区域,然后逐渐移到其他地方。CNN就是模仿这种"局部视野"的方式来处理图像。它通过滑动一个小窗口(称为"卷积核")来查看图片的不同部分。

  2. 卷积层(Convolutional Layer)

    卷积层的作用就是使用多个卷积核对图像进行扫描。这些卷积核可以看作是一个小的滤镜,它们能提取图像中的特征。假设我们有一张猫的照片,卷积核可能会学习到猫的耳朵形状、眼睛的位置、毛发的纹理等特征。每次卷积操作之后,图像会变成一个包含这些特征的"特征图"(feature map)。

    例如,如果我们有一张3×3的卷积核(就是一个3×3的小矩阵),它会遍历图像的每个部分,计算卷积核和图片的局部区域的点积,产生一个新的值。这就像你用滤镜滤镜了一小块区域。

  3. 激活函数(ReLU)

    卷积层提取到特征之后,接下来会通过一个叫做ReLU(Rectified Linear Unit)的激活函数。ReLU会把负数变为零,保留正数。简单来说,就是"过滤"掉一些不重要的信息,保留对分类有帮助的特征。

  4. 池化层(Pooling Layer)

    池化层的作用是将卷积层生成的特征图进行下采样,减少图像的大小和计算量。通常有两种常用的池化方式:

    最大池化(Max Pooling):从每个小区域中选出最大的值。

    平均池化(Average Pooling):从每个小区域中计算平均值。

    池化的作用就是保留图像中最重要的信息,同时减少不必要的细节,就像是在提炼出最精华的部分。

  5. 全连接层(Fully Connected Layer)

    在经过多个卷积层和池化层之后,CNN会将图像的特征汇聚起来,传递到全连接层。这个层的作用类似于神经网络的最终决策阶段,负责根据之前提取到的特征做出最终的分类决策。比如根据猫耳朵、眼睛、毛发的纹理等信息,最终判断出这是猫还是狗。

  6. 输出层(Output Layer)

    最后,输出层会根据神经网络的结果给出分类结果。如果是猫,输出1;如果是狗,输出0。这个结果就是CNN根据图像学习到的特征做出的决策。

总结:

CNN通过逐层提取图像的特征,模拟人类如何观察图像,最终做出分类决策。它的优势在于能够自动学习图像中的有用特征,而不需要人工提取这些特征,这使得CNN特别适合图像处理任务。

比喻:

你可以把CNN想象成一个侦探,它通过从图片的各个细节(耳朵、眼睛、毛发等)收集线索,最终推理出这是一只猫还是狗。每一个卷积核就像是侦探手中的放大镜,帮助他专注于图片中的不同部分,池化层则是帮助侦探筛选出最重要的线索。最终,侦探通过这些线索得出了结论。

写个CNN最简单的代码

假设我们的输入图像是一个 3x3 的矩阵,卷积核(滤波器)是一个 2x2 的矩阵。

  1. 输入:

    1 2 3

    4 5 6

    7 8 9

  2. 卷积核(滤波器)

    1 0

    0 1

  3. 在卷积操作中,卷积核会在输入图像上滑动,并计算卷积核和当前区域的点积。

    步骤:

    我们从输入图像的左上角开始,把卷积核放在图像的最左上角,然后计算卷积核与图像覆盖区域的点积。卷积核的每个元素与对应区域的每个元素相乘,然后求和。



  4. 结果

    通过这些卷积操作,我们得到了一个 2x2 的特征图(Feature Map):

代码如下:

python 复制代码
import numpy as np

# 输入图像
image = np.array([[1, 2, 3],
                  [4, 5, 6],
                  [7, 8, 9]])

# 卷积核(滤波器)
kernel = np.array([[1, 0],
                   [0, 1]])

# 输出特征图的尺寸
output_height = image.shape[0] - kernel.shape[0] + 1
output_width = image.shape[1] - kernel.shape[1] + 1

# 创建一个空的输出特征图
output = np.zeros((output_height, output_width))

# 执行卷积操作
for i in range(output_height):
    for j in range(output_width):
        # 计算当前区域的点积
        region = image[i:i+kernel.shape[0], j:j+kernel.shape[1]]
        output[i, j] = np.sum(region * kernel)

print("卷积结果(特征图):")
print(output)

输出结果:

卷积结果(特征图):

[[ 6. 8.]

[12. 14.]]


接下来正式介绍CNN!

一. 概述




二. 搭建CNN

1. 输入层

2. 卷积层

对于灰度图:

对于彩色图:







3. 激活层

4. 池化层



5. 全连接层

6. 网络搭建小结

7. 损失函数




8. 梯度下降


9. 反向传播

10. 模型评估与正则化




11. 尝试搭建自己的第一个CNN




三. 经典CNN结构

四. 猫狗识别项目实践

1. Paddle实现版本:

python 复制代码
import paddle
import paddle.fluid as fluid
import numpy as np
from PIL import Image
import sys
from multiprocessing import cpu_count
import matplotlib.pyplot as plt
import os
python 复制代码
BATCH_SIZE = 128
# 用于训练的数据提供器
train_reader = paddle.batch(
    paddle.reader.shuffle(paddle.dataset.cifar.train10(),
                            buf_size = BATCH_SIZE * 100),
    batch_size = BATCH_SIZE)

#用于测试的数据提供器
test_reader = paddle.batch(
    paddle.dataset.cifar.test10(),
     batch_size = BATCH_SIZE
)
python 复制代码
def  convolutional_neural_network(img):
    # 第一个卷积 - 池化层
    conv1 = fluid.layers.conv2d(input= img, # 输入图像
                        num_filters =20,      #卷积核的大小
                        filter_size = 5,    #卷积核数量,它与输出的通道相同
                        act = 'relu')     #激活函数
    pool1 = fluid.layers.pool2d(
        input = conv1,  # 输入
        pool_size = 2, #池化核大小
        pool_type = 'max', # 池化类型
        pool_stride = 2)  # 池化步长
    conv_pool_1 = fluid.layers.batch_norm(pool1)

    # 第二个卷积 - 池化层
    conv2 = fluid.layers.conv2d(input= conv_pool_1, # 输入图像
                        num_filters =50,      #卷积核的大小
                        filter_size = 5,    #卷积核数量,它与输出的通道相同
                        act = 'relu')     #激活函数
    pool2 = fluid.layers.pool2d(
        input = conv2,  # 输入
        pool_size = 2, #池化核大小
        pool_type = 'max', # 池化类型
        pool_stride = 2)  # 池化步长
    conv_pool_2 = fluid.layers.batch_norm(pool2)

    # 第三个卷积 - 池化层
    conv3 = fluid.layers.conv2d(input= conv_pool_2, # 输入图像
                        num_filters =50,      #卷积核的大小
                        filter_size = 5,    #卷积核数量,它与输出的通道相同
                        act = 'relu')     #激活函数
    pool3 = fluid.layers.pool2d(
        input = conv3,  # 输入
        pool_size = 2, #池化核大小
        pool_type = 'max', # 池化类型
        pool_stride = 2)  # 池化步长
    # 以softmax 为激活函数的全连接输出层,10类数据输出10个数字
    prediction = fluid.layers.fc(input = pool3,size = 10,act = 'softmax')
    return prediction
    
python 复制代码
paddle.enable_static()
# 3 代表图像RGB三通道,32✖32的彩色图片
data_shape = [3,32,32]
# 定义全局变量 image 和 label 
images = fluid.layers.data(name = 'images',shape = data_shape,dtype = 'float32')
label = fluid.layers.data(name = 'label',shape=[1],dtype = 'int64')
python 复制代码
# 获取分类器,用cnn分类
predict = convolutional_neural_network(images)
python 复制代码
cost = fluid.layers.cross_entropy(input=predict,label = label)
avg_cost = fluid.layers.mean(cost)
acc = fluid.layers.accuracy(input=predict,label = label)
python 复制代码
optimizer = fluid.optimizer.Adam(learning_rate =0.001)
optimizer.minimize(avg_cost)
python 复制代码
place =  fluid.CUDAPlace(0)
exe = fluid.Executor(place)
exe.run(fluid.default_startup_program())
python 复制代码
feeder = fluid.DataFeeder(feed_list=[images,label],place = place)
python 复制代码
EPOCH_NUM = 15
for pass_id in range(EPOCH_NUM):
    train_cost = 0
    for batch_id,data in enumerate(train_reader()):
        train_cost,train_acc = exe.run(program = fluid.default_main_program(),
                                        feed = feeder.feed(data),
                                        fetch_list =[avg_cost,acc])
        if batch_id % 100 ==0:
            print('Pass: %d, Batch: %d, Cost: %0.5f, Accuarcy: %0.5f'%(pass_id,batch_id,train_cost[0],train_acc[0]))
    
   
    test_costs = []
    test_accs = []
    for batch_id,data in enumerate(test_reader()):
        test_cost,test_acc = exe.run(program = fluid.default_main_program(),
                                            feed = feeder.feed(data),
                                            fetch_list = [avg_cost,acc])
        test_costs.append(test_cost[0])
        test_accs.append(test_acc[0])

    # 求测试结果的平均值
    test_cost = (sum(test_costs) / len(test_costs))                         #计算误差平均值(误差和/误差的个数)
    test_acc = (sum(test_accs) / len(test_accs))                            #计算准确率平均值( 准确率的和/准确率的个数)
    print('Test:%d, Cost:%0.5f, ACC:%0.5f' % (pass_id, test_cost, test_acc))
    model_save_dir = "/home/aistudio/data/catdog.inference.model"
    if not os.path.exists(model_save_dir):
        os.makedirs(model_save_dir)
    fluid.io.save_inference_model(model_save_dir,
                              ['images'],
                              [predict],
                              exe)

        
python 复制代码
infer_exe = fluid.Executor(place)
inference_scope = fluid.core.Scope() 
python 复制代码
def load_image(file):
        #打开图片
        im = Image.open(file)
        #将图片调整为跟训练数据一样的大小  32*32
        im = im.resize((32, 32), Image.ANTIALIAS)
        #建立图片矩阵 类型为float32
        im = np.array(im).astype(np.float32)
        #矩阵转置 
        im = im.transpose((2, 0, 1))                               
        #将像素值从【0-255】转换为【0-1】
        im = im / 255.0    
        im = np.expand_dims(im, axis=0)
        return im
python 复制代码
with fluid.scope_guard(inference_scope):
    #从指定目录中加载 推理model(inference model)
    [inference_program, # 预测用的program
     feed_target_names,  
     fetch_targets] = fluid.io.load_inference_model(model_save_dir,
                                                    infer_exe)  
    
    infer_path='/home/aistudio/data/cat.png'
    img = Image.open(infer_path)
    plt.imshow(img)   
    plt.show()    
    
    img = load_image(infer_path)

    results = infer_exe.run(inference_program,               
                            feed={feed_target_names[0]: img}, 
                            fetch_list=fetch_targets)        
    
    label_list = [
        "airplane", "automobile", "bird", "cat", "deer", "dog", "frog", "horse",
        "ship", "truck"
        ]
    print("infer results: %s" % label_list[np.argmax(results[0])])

2. Keras 和 TensorFlow实现版本

完整CNN代码:

python 复制代码
import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Conv2D, MaxPooling2D, Flatten, Dense, Dropout
from tensorflow.keras.optimizers import Adam

# 构建一个简单的CNN模型
model = Sequential()

# 第一个卷积层:使用32个3x3的卷积核,激活函数为ReLU,输入图像尺寸为64x64x3(RGB图像)
model.add(Conv2D(32, (3, 3), activation='relu', input_shape=(64, 64, 3)))

# 第一个池化层:使用2x2的池化窗口,减少空间尺寸
model.add(MaxPooling2D(pool_size=(2, 2)))

# 第二个卷积层:使用64个3x3的卷积核,激活函数为ReLU
model.add(Conv2D(64, (3, 3), activation='relu'))

# 第二个池化层:同样使用2x2的池化窗口
model.add(MaxPooling2D(pool_size=(2, 2)))

# 第三个卷积层:使用128个3x3的卷积核,激活函数为ReLU
model.add(Conv2D(128, (3, 3), activation='relu'))

# 第三个池化层:同样使用2x2的池化窗口
model.add(MaxPooling2D(pool_size=(2, 2)))

# 将3D的卷积输出展平为1D的向量
model.add(Flatten())

# 添加一个全连接层:512个神经元,激活函数为ReLU
model.add(Dense(512, activation='relu'))

# 添加一个Dropout层:随机丢弃30%的神经元,防止过拟合
model.add(Dropout(0.3))

# 添加输出层:2个神经元(分类为猫或狗),使用Softmax激活函数
model.add(Dense(2, activation='softmax'))

# 编译模型:使用Adam优化器,损失函数为交叉熵,评估指标为准确率
model.compile(optimizer=Adam(), loss='sparse_categorical_crossentropy', metrics=['accuracy'])

# 打印模型总结,查看模型结构
model.summary()

代码逐行解释:

tensorflow 是深度学习的框架,keras 是其中的高级API,用于构建神经网络。

Sequential 是模型的线性堆叠结构,表示网络各层按顺序堆叠。

Conv2D 是卷积层,用于图像特征提取。

MaxPooling2D 是池化层,用于降维,减少计算量。

Flatten 是将多维数据转换为一维向量,方便进入全连接层。

Dense 是全连接层,用于决策输出。

Dropout 是一种正则化技术,随机丢弃神经元,防止模型过拟合。

Adam 是一种常用的优化算法,用于调整网络中的权重。

python 复制代码
model = Sequential()

这行代码创建了一个空的 Sequential 模型,表示我们将按顺序添加各个网络层。

python 复制代码
model.add(Conv2D(32, (3, 3), activation='relu', input_shape=(64, 64, 3)))

Conv2D(32, (3, 3)):这是一个卷积层,使用 32 个 3x3 的卷积核。

activation='relu':激活函数使用 ReLU(Rectified Linear Unit),它可以帮助模型引入非线性。

input_shape=(64, 64, 3):输入图像的大小为 64x64 像素,3 个颜色通道(RGB)。

卷积层的作用是通过卷积核对图像进行扫描,提取局部特征,如边缘、纹理等。

python 复制代码
model.add(MaxPooling2D(pool_size=(2, 2)))

MaxPooling2D(pool_size=(2, 2)):这是一个池化层,使用 2x2 的窗口来对图像进行降维。池化层通常将图像的空间尺寸缩小一半,减少计算量,并保留最重要的特征。

bash 复制代码
model.add(Flatten())

Flatten():将卷积层和池化层输出的 3D 张量(如 64x64x128)展平成 1D 向量(如 512),准备输入到全连接层。

bash 复制代码
model.add(Dense(512, activation='relu'))

Dense(512):全连接层,包含 512 个神经元,每个神经元与前一层的每个神经元都有连接。

activation='relu':使用 ReLU 激活函数。

全连接层的作用是结合从卷积层提取到的所有特征,进行更高层次的抽象和决策。

bash 复制代码
model.add(Dropout(0.3))

Dropout(0.3):这是一个 Dropout 层,随机丢弃 30% 的神经元,防止模型过拟合。过拟合是指模型过于依赖训练数据,导致对新数据的预测效果差。

bash 复制代码
model.add(Dense(2, activation='softmax'))

Dense(2):输出层,包含 2 个神经元,因为我们要分类的是 2 类(比如猫和狗)。

activation='softmax':使用 Softmax 激活函数,它将输出转化为概率值,表示属于每个类别的概率。

bash 复制代码
model.compile(optimizer=Adam(), loss='sparse_categorical_crossentropy', metrics=['accuracy'])

optimizer=Adam():使用 Adam 优化器,自动调整学习率以最小化损失。

loss='sparse_categorical_crossentropy':使用交叉熵作为损失函数,适用于多分类任务。

sparse 表示目标标签是整数。

metrics=['accuracy']:我们会评估模型的准确率。

bash 复制代码
model.summary()

model.summary():输出模型的结构,显示各层的类型、输出形状和参数数量

提问检测环节

  1. CNN 的基本组成部分有哪些?
  2. 卷积层(Convolutional Layer):作用是什么?如何提取特征?
  3. 池化层(Pooling Layer):种类、作用及原理(如 MaxPooling 和 AveragePooling)。
  4. 为什么池化层没有参数?
  5. 激活函数(Activation Function):常见的 ReLU、Sigmoid、Softmax 等作用和区别。
  6. 全连接层(Fully Connected Layer):为什么需要展平(Flatten)?
  7. Dropout:在什么场景使用?如何防止过拟合?
  8. 简述 CNN 的基本组成部分及其功能。
  9. 什么是池化?它对特征图有何作用?
  10. SGD、Adam、RMSprop 的特点与适用场景。
  11. 准确率(Accuracy)、损失(Loss)、混淆矩阵(Confusion Matrix)的解读。
  12. 过拟合模型的表现特点。
  13. 为什么 Adam 优化器适合深层网络?

你都答对了吗?

感谢点赞关注👍

相关推荐
小楼先森2 小时前
【数据集】车内视角拍摄道路路面缺陷数据集1075张3类标签YOLO+VOC格式
深度学习·yolo·车内视角·路面缺陷·道路缺陷
看星猩的柴狗2 小时前
机器学习-多元线性回归
人工智能·机器学习·线性回归
IT古董2 小时前
【漫话机器学习系列】013.贝叶斯误差(Bayes Error)
人工智能·机器学习
宸码2 小时前
【机器学习】【集成学习——决策树、随机森林】从零起步:掌握决策树、随机森林与GBDT的机器学习之旅
人工智能·python·算法·决策树·随机森林·机器学习·集成学习
小陈phd4 小时前
深度学习之目标检测——RCNN
python·深度学习·算法·计算机视觉
凳子花❀4 小时前
CNN和Transfomer介绍
人工智能·神经网络·cnn·transformer
⊙ ∀ ⊙5 小时前
电脑充当树莓派屏幕(无线连接)
人工智能
Odoo老杨5 小时前
Odoo:免费开源ERP的AI技术赋能出海企业电子商务应用介绍
人工智能·odoo·数字化转型·erp·企业信息化·出海企业
Srlua6 小时前
Llama2及法律判决分类实战
人工智能·python