深度学习9. 全连接及Dropout概念
创始人
2025-05-29 07:21:19
0

深度学习9. 全连接及Dropout概念

  • 一、基本概念
    • 1. 什么是全连接层
    • 2. 全连接层的作用
    • 3. 过拟合的概念
    • 4. Dropout介绍
    • 5. L1/L2正则化简介
      • (1)L1
      • (2)L2
  • 二、Python简单实现
    • 1. Python实现全连接层
    • 2. Python实现 Dropout
  • 三、使用PyTorch

一、基本概念

1. 什么是全连接层

全连接层是神经网络中的一种常见的层类型,也称为密集连接层(Dense Layer)或者全连接层(Fully Connected Layer)。全连接层可以将输入特征与每个神经元之间的连接权重进行矩阵乘法和偏置加法操作,从而得到输出结果。

在全连接层中,每个神经元都与上一层的所有神经元相连,每个输入特征都与每个神经元之间都存在一定的连接权重。在训练过程中,神经网络通过反向传播算法来优化每个神经元的权重和偏置,从而使得输出结果能够更好地拟合训练数据。

2. 全连接层的作用

全连接层的作用是将输入特征映射到输出结果,通常在神经网络的最后一层使用,用于分类、回归等任务。全连接层的输出结果可以看作是对输入特征的一种非线性变换,这种变换可以将输入特征空间映射到输出结果空间,从而实现模型的复杂性和非线性拟合能力。

需要注意的是,全连接层的参数量非常大,因此容易出现过拟合的情况。为了避免过拟合,可以使用一些正则化方法,比如Dropout、L1/L2正则化等。

3. 过拟合的概念

过拟合(overfitting)是指机器学习模型在训练数据集上表现得很好,但是在新的、未见过的数据集上表现得很差的现象。

过拟合的原因一般是模型过于复杂,导致模型在训练数据上过于准确地拟合了噪声和细节,从而失去了泛化能力。

过拟合的表现包括模型在训练集上的损失(或错误率)很小,但在测试集或验证集上的损失很大,或者模型在训练集上的预测效果很好,但是在测试集或验证集上的预测效果很差。

解决过拟合的方法包括:

  • 简化模型结构,如减少模型参数、降低网络层数等;
  • 增加数据量,如采集更多的数据或使用数据增强技术;
  • 添加正则化,如L1、L2正则化、dropout等;
  • 早停法(early stopping),即在模型在验证集上表现开始下降时停止训练。

4. Dropout介绍

Dropout是一种常用的正则化方法,用于减少神经网络的过拟合现象。它的基本思想是在训练神经网络的过程中,随机地将一部分神经元的输出值置为0,从而使得神经网络的结构变得不稳定,从而强制网络学习到更加鲁棒的特征表示。

具体来说,Dropout在训练过程中,对于每个神经元以一定的概率进行保留或者丢弃。通常情况下,保留概率为ppp,丢弃概率为1−p1-p1−p,可以通过一些随机采样的方法来实现。在前向传播过程中,被丢弃的神经元的输出值会被置为0;在反向传播过程中,被丢弃的神经元也不参与误差反向传播,从而减少神经网络的参数量和模型复杂度,进而避免过拟合。

Dropout的好处是可以让神经网络学习到更加鲁棒的特征表示,从而提高模型的泛化能力。同时,Dropout还可以起到一定的正则化作用,使得神经网络中的权重参数更加平滑,进一步减少过拟合的风险。

需要注意的是,Dropout只在训练过程中使用,在测试过程中应该关闭Dropout,以便得到更加准确的输出结果。

5. L1/L2正则化简介

(1)L1

L1(也称为Lasso)正则化是指在神经网络的损失函数中添加一个L1范数惩罚项,用来惩罚模型权重参数中的大值,使得模型权重变得更加稀疏。L1正则化的效果是使得模型中的一些无关紧要的特征的权重变为0,从而减小模型的复杂度。
L1正则化的公式为:L1(w)=∑i=1n∣wi∣L1(w) = \sum_{i=1}^{n}|w_i|L1(w)=∑i=1n​∣wi​∣。

(2)L2

L2正则化是指在神经网络的损失函数中添加一个L2范数惩罚项,用来惩罚模型权重参数的平方和。L2正则化的效果是让所有的权重都尽可能小,从而减小模型的复杂度。

L2正则化的公式为:L2(w)=∑i=1n∣wi∣2L2(w) = \sum_{i=1}^{n}|w_i|^2L2(w)=∑i=1n​∣wi​∣2。

在实际应用中,L1和L2正则化可以分别通过在损失函数中添加对应的惩罚项来实现。在优化过程中,加上正则化项对应的梯度会影响权重的更新,使得权重不会过大。同时,正则化项的权重需要根据实际情况进行调整,以充分发挥正则化的作用。

二、Python简单实现

1. Python实现全连接层

下面的代码里实现了一个简单的全连接层,以更容易理解全连接层。

import numpy as np
from PIL import Image
import matplotlib.pyplot as pltclass DenseLayer:def __init__(self, input_size, output_size):self.weights = np.random.randn(input_size, output_size)self.bias = np.zeros((1, output_size))self.inputs = Noneself.outputs = Nonedef forward(self, inputs):self.inputs = inputsself.outputs = np.dot(self.inputs, self.weights) + self.biasreturn self.outputs# 定义一个两层的神经网络模型
input_size = 784 * 3
hidden_size = 100
output_size = 10layer1 = DenseLayer(input_size, hidden_size)
layer2 = DenseLayer(hidden_size, output_size)# 读取一张图片
img = Image.open('example_pool.jpg').convert('RGB')
img = img.resize((28, 28))
# 将 PIL.Image 对象转换成 numpy 数组,并且将像素值缩放到 [0, 1] 的范围内
data = np.array(img, dtype=np.float32).reshape((1, 784*3)) / 255.0# 前向传播
h = layer1.forward(data)
y = layer2.forward(h)# 使用softmax函数将输出的数值转化为概率
y = np.exp(y - np.max(y, axis=1, keepdims=True))
y = y / np.sum(y, axis=1, keepdims=True)# 将输出结果绘制成条形图
result = np.argmax(y)
labels = [str(i) for i in range(10)]
plt.bar(labels, y.flatten())
plt.title('Output from Neural Network')
plt.xlabel('Digit')
plt.ylabel('Output Probability')
plt.show()

这里实现的简单的全连接,只写了前向传播,没有定义后向传播。
从前向传播的构造方法中,可以看出使用了一个单层感知机,是一个线性的神经元。

2. Python实现 Dropout

下面定义的 Dropout 类,其构造函数接收一个 dropout_rate 参数表示要 dropout 的比例。
forward 方法接收一个输入 x,如果是训练状态,则生成一个掩码 mask 并将其应用到输入上,输出结果。如果是测试状态,则直接输出输入结果。

backward 方法接收一个梯度 dout,将其乘以之前生成的掩码 mask 后输出。本程序没有使用反向传播。

np.random.binomial 用于生成一个二项分布的数组,值为 0 或 1。
其中的参数 1 - self.dropout_rate 表示成功概率为 1 - dropout_rate。数组中的每个元素代表输入中对应位置的值是否应该被保留。最后除以 (1 - self.dropout_rate) 是为了保证训练时输出结果的期望与测试时相同。

import numpy as np# 定义 Dropout 类
class Dropout:def __init__(self, dropout_rate=0.5):self.dropout_rate = dropout_rateself.mask = Nonedef forward(self, x, is_train=True):if is_train:# 生成掩码self.mask = np.random.binomial(1, self.dropout_rate, size=x.shape)return x * self.mask / self.dropout_rateelse:return xdef backward(self, dout):return dout * self.mask / self.dropout_rate# 使用 Dropout 的示例
dropout_rate = 0.5
x = np.array([[1.0, 2.0, 3.0, 4.0], [5.0, 6.0, 7.0, 8.0]])
dropout = Dropout(dropout_rate)# 训练阶段使用 Dropout
x_train = dropout.forward(x, is_train=True)
print('Training output:', x_train)# 推理阶段不使用 Dropout
x_test = dropout.forward(x, is_train=False)
print('Test output:', x_test)

运行示例:

Training output: [[ 0.  0.  0.  8.][10. 12.  0.  0.]]
Test output: [[1. 2. 3. 4.][5. 6. 7. 8.]]

可以看到在训练阶段,部分元素赋了0,而在测试阶段,输出与输入相同。

三、使用PyTorch

在使用全连接层时,需要将每个样本的输入数据展平为一维向量,以便于输入到全连接层中进行处理。

在PyTorch中,每个batch的数据的形状为(batch_size, channels, height, width),需要使用view()方法将其转化为(batch_size, input_size),其中input_size表示展平后的向量长度,即channels * height * width。

import torch
from torch import nn
from torch.utils.data import DataLoader
from torchvision.datasets import MNIST
from torchvision.transforms import ToTensor
from tqdm import tqdm# 定义全连接神经网络模型
class Net(nn.Module):def __init__(self):super(Net, self).__init__()self.fc1 = nn.Linear(784, 128)self.fc2 = nn.Linear(128, 64)self.fc3 = nn.Linear(64, 10)def forward(self, x):x = torch.relu(self.fc1(x))x = torch.relu(self.fc2(x))x = self.fc3(x)return x# 加载 MNIST 数据集
train_dataset = MNIST(root='data/', train=True, transform=ToTensor(), download=True)
test_dataset = MNIST(root='data/', train=False, transform=ToTensor(), download=True)# 创建数据加载器
batch_size = 64
train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False)# 创建模型、损失函数和优化器
model = Net()
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(model.parameters(), lr=0.1)# 训练模型
num_epochs = 10
for epoch in range(num_epochs):for images, labels in tqdm(train_loader):# 将输入数据拉平为一维向量images = images.view(images.size(0), -1)# 向前传播、计算损失和梯度outputs = model(images)loss = criterion(outputs, labels)loss.backward()# 更新参数optimizer.step()optimizer.zero_grad()# 在测试集上评估模型性能correct = 0total = 0for images, labels in test_loader:images = images.view(images.size(0), -1)outputs = model(images)_, predicted = torch.max(outputs.data, 1)total += labels.size(0)correct += (predicted == labels).sum().item()accuracy = correct / totalprint('Epoch [{}/{}], Accuracy: {:.2f}%'.format(epoch+1, num_epochs, accuracy*100))print('Training finished.')

代码要点:

  • 上面示例使用了MNIST数据集;
  • 训练每个批次大小64;
  • tqdm是一个在命令行显示训练进度的库;
  • 每个批次的数据 , images是一个大小为(batch_size, 1, 28, 28)的张量,labels是一个大小为(batch_size,)的张量,表示对应的图像的标签;
  • images.view(images.size(0), -1):将images变换为(batch_size, input_size)的形状。其中,images.size(0)表示batch_size的值,而-1表示剩下的维度根据原有数据的形状自动计算得出。

程序运行结果:
在这里插入图片描述

相关内容

热门资讯

11-STM32F1 -DMA... 11-STM32F1 -DMA(1) DMA:Data Memory A...
促销活动方案 实用的促销活动方案集锦9篇  为了确保工作或事情有序地进行,常常需要预先制定方案,方案是书面计划,是...
清明节主题党日活动方案 清明节主题党日活动方案(通用7篇)  为了确保活动有序有效开展,我们需要事先制定活动方案,活动方案是...
施工现场扬尘专项防治方案 施工现场扬尘专项防治方案  什么是方案  方案是从目的、要求、方式、方法、进度等都部署具体、周密,并...
家电促销活动方案 家电促销活动方案通用15篇  为保证事情或工作高起点、高质量、高水平开展,往往需要预先进行方案制定工...
考研408每周一题(2019 ... 2019年(单链表)         41.(13分)设线性表L=(a1,a2...
【C#进阶】C# 索引器 序号系列文章13【C#进阶】C# 特性14【C#进阶】C# 反射15【C#进阶】C# 属性文章目录前...
社区志愿者活动方案 社区志愿者活动方案模板(精选9篇)  为了确保活动有序地进行,往往需要预先制定好活动方案,活动方案是...
双十一促销活动方案 双十一促销活动方案(精选12篇)  为了确保活动能有条不紊地开展,常常要根据具体情况预先制定活动方案...
最新促销活动方案 最新促销活动方案  一、活动方案的格式  1.活动标题  2.活动时间、地点  3.活动的目的及意义...
微公益策划活动方案 微公益策划活动方案  为了确保工作或事情有序地进行,常常要根据具体情况预先制定方案,一份好的方案一定...
浏览器F12功能总结 不同浏览器F12控制面板的中英文显示360浏览器:英文IE浏览器:中文搜狗:英文谷歌浏览器:英文火狐...
数据结构 | 栈的中缀表达式求... 目录 什么是栈? 栈的基本操作 入栈操作 出栈操作 取栈顶元素 中缀表达式求值 实现思...
[C语言]qsort()排序函... qsort函数C语言编译器函数库自带的排序函数。qsort 的函数原型是void qsort(voi...
民主生活会工作方案 民主生活会工作方案  民主生活会工作方案(精选6篇)  只有深思熟虑之后,才能写好工作方案。在计划开...
体育活动目标方案 体育活动目标方案(精选6篇)  为了确保活动能有条不紊地开展,常常需要提前准备一份具体、详细、针对性...
评选活动方案 评选活动方案  为了确保我们的努力取得实效,就需要我们事先制定方案,方案可以对一个行动明确一个大概的...
摄影活动方案 摄影活动方案(精选15篇)  为了保障事情或工作顺利、圆满进行,常常需要提前进行细致的方案准备工作,...
(Java基础)关键字 关键字 Java 有没有 goto goto 是 Java 中的保留字,在目前版本的 ...
【学习笔记】计算机视觉与深度学... 学习视频: 鲁鹏-计算机视觉与深度学习 1 图像分类任务 图像分类任务是计算机视觉的核...