前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >【AI 成长笔记】DNN 为什么不适合做图像识别?

【AI 成长笔记】DNN 为什么不适合做图像识别?

原创
作者头像
繁依Fanyi
发布2025-03-22 22:55:59
发布2025-03-22 22:55:59
6500
代码可运行
举报
运行总次数:0
代码可运行

前言

当你在社交媒体上看到一只傲娇的猫或一只憨态可掬的狗时,你会不会好奇:计算机是怎样识别这些萌宠的呢?在深度学习的世界里,主要有两大模型来完成这一任务:深度神经网络(DNN)卷积神经网络(CNN)。但事实证明,面对图像数据,这两位选手的表现可大相径庭!

自己学习了几天后,我将通过生动的理论讲解和实战代码演示,让你看到 DNN 在处理图片时的各种“囧态”,以及 CNN 如何迎难而上,完美解决问题。


理论讲解——DNN 与 CNN 处理图像的“天壤之别”

1. DNN 处理图像

1、DNN 的工作原理

深度神经网络(DNN)的基本思路非常简单:

在这里插入图片描述
在这里插入图片描述
  • 将图像展平:把一张二维甚至三维的图片“拉直”成一长串数字。
  • 全连接处理:每一个神经元都和输入向量中的所有像素点相连接,再经过加权求和和激活函数,输出一个结果。

想象一下,你拿到一张可爱的猫咪照片,它的尺寸是 150x150 像素,每个像素有 3 个颜色通道。整个图片就有 150×150×3 = 67,500 个数据!DNN 要把这 67,500 个数据当成一长条“特征向量”,然后每个神经元都“盯”这整条数据看。这就好比让你记住一本小说中的每一个字,然后回答:“这本小说讲的是猫还是狗?”很明显,这种方法既累赘又不靠谱!

2、DNN 的问题与不足

以一张猫咪图片来做形象化讲解:

在这里插入图片描述
在这里插入图片描述
  1. 局部特征丢失:在图像中,猫咪的耳朵、眼睛、胡须等细节是关键特征。但是,当图片被展平后,像素的二维空间关系就不见了!DNN 只能依靠“全部数字”的组合来区分猫和狗,根本无法识别“局部”的模式。就像你把一本漫画书打乱成一页页的散乱数字,根本看不出故事情节!
  2. 参数爆炸与内存消耗:全连接层需要连接每一个输入数据,假设第一层有 512 个神经元,那么这一层的参数数量就是 67,500×512(外加偏置),参数数目巨大,内存占用和计算量直线上升。这不仅导致训练速度变慢,还容易过拟合——模型“记住”训练数据,却无法泛化到新图像上。
  3. 对图像大小和位置的敏感性:DNN 是基于固定的输入向量设计的。如果图像尺寸变化(比如猫咪照片大小不同),就必须重新设计网络结构。更糟糕的是,如果同一只猫在图片中出现多个相似区域(比如花纹分布不均),DNN 很难区分到底哪个区域代表猫咪特征,因为它无法理解图像的空间结构。
  4. 无法处理平移和旋转:假如猫咪稍微转个头或者移动一下位置,由于展平后的数字顺序被打乱,DNN 可能就会“看不懂”这张图。这就像是把同一篇文章的段落顺序打乱后,让你判断文章主题——绝对是灾难!

总的来说,DNN 就像一个只会死记硬背的学生,面对复杂多变的图像信息,显得力不从心,内存消耗大,泛化能力弱。


2. CNN 处理图像

1、CNN 的设计理念

与 DNN 大相径庭的是,卷积神经网络(CNN)专门为图像识别设计。它主要包含以下几个关键部分:

在这里插入图片描述
在这里插入图片描述
  1. 卷积层(Convolutional Layer):CNN 使用“小窗口”或称“卷积核”在图像上滑动,这些卷积核只关注图像的局部区域,能够捕捉到如边缘、角落等重要特征。换句话说,它不需要把整张图片“拉直”,而是直接在图片的二维结构上提取有用信息。
  2. 权重共享:卷积核在整个图像上反复使用同一组权重。这不仅大大减少了参数数量,还能保证无论特征出现在图像的哪个位置,都能被检测到。这就像你在不同地方都能看到同样的猫耳朵——不管猫在图片中怎么跑,耳朵永远一样可爱!
  3. 池化层(Pooling Layer):池化层通过对局部区域进行采样(如取最大值或平均值),进一步压缩特征图,降低计算复杂度,同时保留关键信息。它还能提供平移不变性,让模型对图像的小幅变动更稳健。
2、CNN 如何解决 DNN 的问题

让我们具体看看 CNN 是如何应对前面 DNN 遇到的各种问题:

  1. 局部特征提取:卷积层就像一双慧眼,每次只关注猫咪的一小块区域(比如猫耳朵),自动提取出边缘、纹理等局部信息。这样,即使图像尺寸变化或猫咪位置不同,CNN 都能通过局部特征判断图像内容。
  2. 参数大幅减少:由于卷积核共享权重,一个 3×3 的卷积核只需要 9 个参数,而在全连接层中,每个像素都有单独参数。比如,处理一张 150×150×3 的图像,DNN 的第一层参数数量可能达到数千万,而 CNN 的卷积层参数只需要几百个。这不仅降低了内存消耗,也加快了训练速度。
  3. 平移、旋转不变性:CNN 通过局部扫描和池化操作,天然具有平移和旋转不变性。即使同一只猫咪在图片中稍微移动、旋转,卷积核依然能识别出关键特征,保证分类结果稳定。
  4. 多层次特征融合:CNN 中的多层卷积和池化操作可以将低层次的简单特征(如边缘、纹理)逐层组合成高层次的复杂特征(如猫的形状、眼神)。这种层次化特征抽象使得模型能够更好地捕捉到图像的整体语义。

CNN 就像一个有经验的侦探,能通过局部细节中找出蛛丝马迹,然后组合成完整的“证据链”,最终精确判断图片中到底是猫还是狗!


代码实践——基于 PyTorch 实现猫狗分类

在前面详细介绍了理论部分后,下面我们通过实际的 PyTorch 代码来对比 DNN 和 CNN 在猫狗分类任务中的表现。我们将依次介绍两种模型的实现、训练过程以及网络结构的可视化。

1. 数据预处理与加载

首先,我们需要加载猫狗分类数据集,并对图像进行预处理。假设数据集已经按目录结构分为训练集和测试集。

代码语言:python
代码运行次数:0
运行
复制
import torch
from torch.utils.data import DataLoader
from torchvision import datasets, transforms

# 定义图像预处理:调整大小、转换为 Tensor、归一化
transform = transforms.Compose([
    transforms.Resize((150, 150)),    # 调整图像为 150x150
    transforms.ToTensor(),            # 转换为 Tensor
    transforms.Normalize(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5])
])

# 加载数据集
train_data = datasets.ImageFolder(root='data/train', transform=transform)
test_data = datasets.ImageFolder(root='data/test', transform=transform)

train_loader = DataLoader(train_data, batch_size=32, shuffle=True)
test_loader = DataLoader(test_data, batch_size=32, shuffle=False)

2. DNN 模型实现

1、模型代码
代码语言:python
代码运行次数:0
运行
复制
import torch.nn as nn
import torch.optim as optim

class DNN(nn.Module):
    def __init__(self):
        super(DNN, self).__init__()
        self.fc1 = nn.Linear(150*150*3, 512)  # 第一层,全连接层
        self.fc2 = nn.Linear(512, 512)          # 第二层,全连接层
        self.fc3 = nn.Linear(512, 1)            # 输出层

    def forward(self, x):
        # 将输入图像展平成一维向量
        x = x.view(-1, 150*150*3)
        x = torch.relu(self.fc1(x))
        x = torch.relu(self.fc2(x))
        x = torch.sigmoid(self.fc3(x))
        return x

model_dnn = DNN()
2、模型结构说明
  • 输入层:150x150x3 像素,共 67,500 个特征。
  • 全连接层1:从 67,500 个输入到 512 个神经元,参数量巨大。
  • 全连接层2:512 到 512。
  • 输出层:输出 1 个数,经 Sigmoid 激活函数得到概率(猫或狗)。

由于 DNN 需要处理所有像素之间的关系,因此参数数量非常庞大,不仅内存消耗高,而且训练过程也相对较慢。我就不尝试了,内存大的小伙伴可以试一下。


3. CNN 模型实现

1、模型代码
代码语言:python
代码运行次数:0
运行
复制
class CNN(nn.Module):
    def __init__(self):
        super(CNN, self).__init__()
        # 第一卷积层:输入通道 3,输出通道 32,使用 3x3 卷积核,边缘填充1
        self.conv1 = nn.Conv2d(3, 32, kernel_size=3, padding=1)
        # 第二卷积层:输入 32,输出 64
        self.conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
        # 池化层:2x2 最大池化
        self.pool = nn.MaxPool2d(2, 2)
        # 全连接层:假设经过两次池化后,图像尺寸变为 37x37(150/2/2 ≈ 37)
        self.fc1 = nn.Linear(64 * 37 * 37, 512)
        self.fc2 = nn.Linear(512, 1)

    def forward(self, x):
        x = self.pool(torch.relu(self.conv1(x)))  # 卷积 + 激活 + 池化
        x = self.pool(torch.relu(self.conv2(x)))  # 卷积 + 激活 + 池化
        x = x.view(-1, 64 * 37 * 37)  # 展平
        x = torch.relu(self.fc1(x))
        x = torch.sigmoid(self.fc2(x))
        return x

model_cnn = CNN()
2、模型结构说明
  • 卷积层1:用 32 个 3x3 卷积核扫描图像,提取局部特征(比如猫的边缘)。
  • 池化层:缩小特征图尺寸,同时保留关键信息。
  • 卷积层2:进一步提取更深层次的特征。
  • 展平与全连接层:将卷积层输出展平后,再通过全连接层整合成最终分类结果。

相比 DNN,CNN 通过局部感知和权重共享,显著减少了参数数量和计算量,还能更好地捕捉图像中的空间结构信息。


4. 模型训练与性能对比

1、定义训练函数

我们为两个模型分别定义训练函数:

代码语言:python
代码运行次数:0
运行
复制
def train_model(model, train_loader, criterion, optimizer, epochs=5):
    model.train()
    for epoch in range(epochs):
        running_loss = 0.0
        correct = 0
        total = 0
        for inputs, labels in train_loader:
            optimizer.zero_grad()
            outputs = model(inputs)
            labels = labels.unsqueeze(1).float()  # 转换标签格式为浮点型
            loss = criterion(outputs, labels)
            loss.backward()
            optimizer.step()

            running_loss += loss.item()
            predicted = (outputs > 0.5).float()
            correct += (predicted == labels).sum().item()
            total += labels.size(0)
        print(f"Epoch [{epoch+1}/{epochs}], Loss: {running_loss/len(train_loader):.4f}, Accuracy: {correct/total:.4f}")

# 定义损失函数和优化器(分别对两个模型)
criterion = nn.BCELoss()

optimizer_dnn = optim.Adam(model_dnn.parameters(), lr=0.001)
optimizer_cnn = optim.Adam(model_cnn.parameters(), lr=0.001)
2、分别训练模型

训练 DNN 模型:

代码语言:python
代码运行次数:0
运行
复制
print("Training DNN Model:")
train_model(model_dnn, train_loader, criterion, optimizer_dnn, epochs=5)

训练 CNN 模型:

代码语言:python
代码运行次数:0
运行
复制
print("Training CNN Model:")
train_model(model_cnn, train_loader, criterion, optimizer_cnn, epochs=5)
3、两者对比总结

如果你成功训练了两个模型,你会发现:

  • DNN 模型:由于全连接层参数量巨大,训练时间长,而且对图像中局部特征捕捉不敏感,容易出现过拟合。训练后的准确率往往较低,且对图像大小、位置变化敏感。
  • CNN 模型:通过卷积层和池化层提取局部特征,计算效率高,训练时间短,最终模型的准确率更高,对图像的平移、旋转等变化也更鲁棒。

结语

通过本文的详细讲解与代码演示,希望你能深刻理解 DNN 与 CNN 在处理图像(如猫狗分类)时的本质区别。对于计算机视觉任务,CNN 无疑是更聪明、更高效的选择。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 理论讲解——DNN 与 CNN 处理图像的“天壤之别”
    • 1. DNN 处理图像
      • 1、DNN 的工作原理
      • 2、DNN 的问题与不足
    • 2. CNN 处理图像
      • 1、CNN 的设计理念
      • 2、CNN 如何解决 DNN 的问题
  • 代码实践——基于 PyTorch 实现猫狗分类
    • 1. 数据预处理与加载
    • 2. DNN 模型实现
      • 1、模型代码
      • 2、模型结构说明
    • 3. CNN 模型实现
      • 1、模型代码
      • 2、模型结构说明
    • 4. 模型训练与性能对比
      • 1、定义训练函数
      • 2、分别训练模型
      • 3、两者对比总结
  • 结语
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档