为什么要做个人网站,营销型旅游网站建设,苏州网站建设问问q778925409强涵,源码下载网站cms深度学习 — 过拟合与欠拟合 文章目录深度学习 --- 过拟合与欠拟合一.概念1.1 过拟合1.2 欠拟合1.3 判断方式二#xff0c;解决欠拟合三#xff0c;解决过拟合3.1 L2正则化3.1.1 定义以及作用3.1.2 代码3.2 L1正则化3.3 L1与L2对比3.4 Dropout示例3.5 数据增强3.5.1 图片缩放…深度学习 — 过拟合与欠拟合 文章目录深度学习 --- 过拟合与欠拟合一.概念1.1 过拟合1.2 欠拟合1.3 判断方式二解决欠拟合三解决过拟合3.1 L2正则化3.1.1 定义以及作用3.1.2 代码3.2 L1正则化3.3 L1与L2对比3.4 Dropout示例3.5 数据增强3.5.1 图片缩放3.5.2 随机裁剪3.5.3 随机水平翻转3.5.4 调整图片颜色3.5.5 随机旋转3.5.6 图片转Tensor3.5.7 Tensor转图片3.5.8 归一化3.5.9 数据增强整合一.概念 1.1 过拟合
过拟合是指模型对训练数据拟合能力很强并表现很好但在测试数据上表现较差。
过拟合常见原因有
数据量不足当训练数据较少时模型可能会过度学习数据中的噪声和细节。模型太复杂如果模型很复杂也会过度学习训练数据中的细节和噪声。正则化强度不足如果正则化强度不足可能会导致模型过度学习训练数据中的细节和噪声。
1.2 欠拟合
欠拟合是由于模型学习能力不足无法充分捕捉数据中的复杂关系。
1.3 判断方式
过拟合
训练误差低但验证时误差高。模型在训练数据上表现很好但在验证数据上表现不佳说明模型可能过度拟合了训练数据中的噪声或特定模式。
欠拟合
训练误差和测试误差都高。模型在训练数据和测试数据上的表现都不好说明模型可能太简单无法捕捉到数据中的复杂模式。
二解决欠拟合
欠拟合的解决思路比较直接
增加模型复杂度引入更多的参数、增加神经网络的层数或节点数量使模型能够捕捉到数据中的复杂模式。增加特征通过特征工程添加更多有意义的特征使模型能够更好地理解数据。减少正则化强度适当减小 L1、L2 正则化强度允许模型有更多自由度来拟合数据。训练更长时间如果是因为训练不足导致的欠拟合可以增加训练的轮数或时间.
三解决过拟合
避免模型参数过大是防止过拟合的关键步骤之一。
模型的复杂度主要由权重w决定而不是偏置b。偏置只是对模型输出的平移不会导致模型过度拟合数据。
怎么控制权重w使w在比较小的范围内
考虑损失函数损失函数的目的是使预测值与真实值无限接近如果在原来的损失函数上添加一个非0的变量 L1(y^,y)L(y^,y)f(w)L_1(\hat{y},y) L(\hat{y},y) f(w) L1(y^,y)L(y^,y)f(w) 其中f(w)f(w)f(w)是关于权重w的函数f(w)0f(w)0f(w)0
要使L1变小就要使L变小的同时也要使f(w)f(w)f(w)变小。从而控制权重w在较小的范围内。
3.1 L2正则化
L2 正则化通过在损失函数中添加权重参数的平方和来实现目标是惩罚过大的参数值。
3.1.1 定义以及作用
维度内容数学表达式解释与作用原始损失函数模型未加正则化的损失函数如 MSE、交叉熵L(θ)L(\theta)L(θ)仅衡量模型在训练数据上的误差。L2 正则化项所有权重参数的平方和12∑iθi2\frac{1}{2} \sum_i \theta_i^221∑iθi2惩罚大权重防止模型复杂度过高。总损失函数原始损失 L2 正则化项Ltotal(θ)L(θ)λ2∑iθi2L_{\text{total}}(\theta) L(\theta) \frac{\lambda}{2} \sum_i \theta_i^2Ltotal(θ)L(θ)2λ∑iθi2加入惩罚项平衡拟合能力与复杂度。梯度更新规则参数更新时考虑原始梯度 L2 项的梯度θt1θt−η(∇L(θt)λθt)\theta_{t1} \theta_t - \eta \left( \nabla L(\theta_t) \lambda \theta_t \right)θt1θt−η(∇L(θt)λθt)每次更新都“衰减”参数乘以 1−ηλ1 - \eta \lambda1−ηλ防止权重过大。12\frac{1}{2}21 的作用简化梯度计算∂∂θi(12θi2)θi\frac{\partial}{\partial \theta_i} \left( \frac{1}{2} \theta_i^2 \right) \theta_i∂θi∂(21θi2)θi消去系数 2使梯度更新公式更简洁避免 2λθi2\lambda \theta_i2λθi。防止过拟合抑制权重过大降低模型对训练噪声的敏感性-权重越小模型对输入扰动越不敏感泛化能力增强。限制模型复杂度强制权重接近 0避免过拟合-通过惩罚大权重减少模型自由度降低 VC 维。提高泛化能力在训练集和测试集上表现更均衡-正则化项使模型更关注数据的真实规律而非噪声。平滑权重分布权重逐渐缩小但不直接为 0-保留所有特征贡献避免稀疏性与 L1 不同使模型更平滑。
3.1.2 代码
import torch
import torch.nn as nn
import torch.optim as optim
import matplotlib.pyplot as plt# 设置随机种子以保证可重复性
torch.manual_seed(42)# 生成随机数据
n_samples 100
n_features 20
X torch.randn(n_samples, n_features) # 输入数据
y torch.randn(n_samples, 1) # 目标值# 定义一个简单的全连接神经网络
class SimpleNet(nn.Module):def __init__(self):super(SimpleNet, self).__init__()self.fc1 nn.Linear(n_features, 50)self.fc2 nn.Linear(50, 1)def forward(self, x):x torch.relu(self.fc1(x))return self.fc2(x)# 训练函数
def train_model(use_l2False, weight_decay0.01, n_epochs100):# 初始化模型model SimpleNet()criterion nn.MSELoss() # 损失函数均方误差# 选择优化器if use_l2:optimizer optim.SGD(model.parameters(), lr0.01, weight_decayweight_decay) # 使用 L2 正则化else:optimizer optim.SGD(model.parameters(), lr0.01) # 不使用 L2 正则化# 记录训练损失train_losses []# 训练过程for epoch in range(n_epochs):optimizer.zero_grad() # 清空梯度outputs model(X) # 前向传播loss criterion(outputs, y) # 计算损失loss.backward() # 反向传播optimizer.step() # 更新参数train_losses.append(loss.item()) # 记录损失if (epoch 1) % 10 0:print(fEpoch [{epoch 1}/{n_epochs}], Loss: {loss.item():.4f})return train_losses# 训练并比较两种模型
train_losses_no_l2 train_model(use_l2False) # 不使用 L2 正则化
train_losses_with_l2 train_model(use_l2True, weight_decay0.01) # 使用 L2 正则化# 绘制训练损失曲线
plt.plot(train_losses_no_l2, labelWithout L2 Regularization)
plt.plot(train_losses_with_l2, labelWith L2 Regularization)
plt.xlabel(Epoch)
plt.ylabel(Loss)
plt.title(Training Loss: L2 Regularization vs No Regularization)
plt.legend()
plt.show()3.2 L1正则化
设模型的原始损失函数为 L(θ)L(\theta)L(θ)其中 θ\thetaθ 表示模型权重参数则加入 L1 正则化后的损失函数表示为 Ltotal(θ)L(θ)λ∑i∣θi∣L_{\text{total}}(\theta) L(\theta) \lambda \sum_{i} |\theta_i| Ltotal(θ)L(θ)λi∑∣θi∣
梯度更新 在 L1 正则化下梯度更新时的公式是 θt1θt−η(∇L(θt)λ⋅sign(θt))\theta_{t1} \theta_t - \eta \left( \nabla L(\theta_t) \lambda \cdot \text{sign}(\theta_t) \right) θt1θt−η(∇L(θt)λ⋅sign(θt))作用 稀疏性L1 正则化的一个显著特性是它会促使许多权重参数变为 零。这是因为 L1 正则化倾向于将权重绝对值缩小到零使得模型只保留对结果最重要的特征而将其他不相关的特征权重设为零从而实现 特征选择 的功能。 防止过拟合通过限制权重的绝对值L1 正则化减少了模型的复杂度使其不容易过拟合训练数据。相比于 L2 正则化L1 正则化更倾向于将某些权重完全移除而不是减小它们的值。 简化模型由于 L1 正则化会将一些权重变为零因此模型最终会变得更加简单仅依赖于少数重要特征。这对于高维度数据特别有用尤其是在特征数量远多于样本数量的情况下。 特征选择因为 L1 正则化会将部分权重置零因此它天然具有特征选择的能力有助于自动筛选出对模型预测最重要的特征。
3.3 L1与L2对比
特性L2 正则化RidgeL1 正则化Lasso惩罚项∑iθi2\sum_i \theta_i^2∑iθi2∑_iθ_i\sum\_i \theta\_i∑_iθ_i效果权重平滑趋近于 0权重稀疏部分变为 0梯度λθi\lambda \theta_iλθiλ⋅sign(θi)\lambda \cdot \text{sign}(\theta_i)λ⋅sign(θi)适用场景特征共线性强、需要保留所有特征特征选择自动忽略无关特征
3.4 Dropout
Dropout 的工作流程如下
在每次训练迭代中随机选择一部分神经元通常以概率 p丢弃比如 p0.5。被选中的神经元在当前迭代中不参与前向传播和反向传播。在测试阶段所有神经元都参与计算但需要对权重进行缩放通常乘以 1−p以保持输出的期望值一致。 Dropout 是一种在训练过程中随机丢弃部分神经元的技术。它通过减少神经元之间的依赖来防止模型过于复杂从而避免过拟合。
import torchimport torch.nn as nndef test01():xtorch.randint(1,10,(5,5),dtypetorch.float)dropoutnn.Dropout(p0.5)print(x)print(dropout(x))if __name__ __main__:test01()
示例
对图片进行随机丢弃
import torch
from torch import nn
from PIL import Image
from torchvision import transforms
import osfrom matplotlib import pyplot as plttorch.manual_seed(42)def load_img(path, resize(224, 224)):pil_img Image.open(path).convert(RGB)print(Original image size:, pil_img.size) # 打印原始尺寸transform transforms.Compose([transforms.Resize(resize),transforms.ToTensor() # 转换为Tensor并自动归一化到[0,1]])return transform(pil_img) # 返回[C,H,W]格式的tensorif __name__ __main__:dirpath os.path.dirname(__file__)path os.path.join(dirpath, img, torch-fcnn/fcnn-demo/100.jpg) # 使用os.path.join更安全# 加载图像 (已经是[0,1]范围的Tensor)trans_img load_img(path)# 添加batch维度 [1, C, H, W]因为Dropout默认需要4D输入trans_img trans_img.unsqueeze(0)# 创建Dropout层dropout nn.Dropout2d(p0.2)drop_img dropout(trans_img)# 移除batch维度并转换为[H,W,C]格式供matplotlib显示trans_img trans_img.squeeze(0).permute(1, 2, 0).numpy()drop_img drop_img.squeeze(0).permute(1, 2, 0).numpy()# 确保数据在[0,1]范围内drop_img drop_img.clip(0, 1)# 显示图像fig plt.figure(figsize(10, 5))ax1 fig.add_subplot(1, 2, 1)ax1.imshow(trans_img)ax2 fig.add_subplot(1, 2, 2)ax2.imshow(drop_img)plt.show()3.5 数据增强
样本数量不足即训练数据过少是导致过拟合Overfitting的常见原因之一可以从以下角度理解
当训练数据过少时模型容易“记住”有限的样本包括噪声和无关细节而非学习通用的规律。简单模型更可能捕捉真实规律但数据不足时复杂模型会倾向于拟合训练集中的偶然性模式噪声。样本不足时训练集的分布可能与真实分布偏差较大导致模型学到错误的规律。小数据集中个别样本的噪声如标注错误、异常值会被放大模型可能将噪声误认为规律。
数据增强Data Augmentation是一种通过人工生成或修改训练数据来增加数据集多样性的技术常用于解决过拟合问题。数据增强通过“模拟”更多训练数据迫使模型学习泛化性更强的规律而非训练集中的偶然性模式。其本质是一种低成本的正则化手段尤其在数据稀缺时效果显著。
在了解计算机如何处理图像之前需要先了解图像的构成元素。
图像是由像素点组成的每个像素点的值范围为: [0, 255], 像素值越大意味着较亮。比如一张 200x200 的图像, 则是由 40000 个像素点组成, 如果每个像素点都是 0 的话, 意味着这是一张全黑的图像。
我们看到的彩色图一般都是多通道的图像, 所谓多通道可以理解为图像由多个不同的图像层叠加而成, 例如我们看到的彩色图像一般都是由 RGB 三个通道组成的还有一些图像具有 RGBA 四个通道最后一个通道为透明通道该值越小则图像越透明。
数据增强是提高模型泛化能力鲁棒性的一种有效方法尤其在图像分类、目标检测等任务中。数据增强可以模拟更多的训练样本从而减少过拟合风险。数据增强通过torchvision.transforms模块来实现。
3.5.1 图片缩放
def test01():pathtorch-fcnn/fcnn-demo/datasets/100.jpgimgImage.open(path)print(img.size)transformtransforms.Compose([transforms.Resize((224,224)),transforms.ToTensor()])t_imgtransform(img)print(t_img.shape)t_img torch.permute(t_img, (1, 2, 0))plt.imshow(t_img)plt.show()
3.5.2 随机裁剪
def test02():pathtorch-fcnn/fcnn-demo/datasets/100.jpgimgImage.open(path)print(img.size)transformtransforms.Compose([transforms.RandomCrop((224,224)),transforms.ToTensor()])t_imgtransform(img)# print(t_img.shape)t_img torch.permute(t_img, (1, 2, 0))plt.imshow(t_img)plt.show()
3.5.3 随机水平翻转
def test03():pathtorch-fcnn/fcnn-demo/datasets/100.jpgimgImage.open(path)print(img.size)transformtransforms.Compose([transforms.RandomHorizontalFlip(p1),transforms.ToTensor()])t_imgtransform(img)# print(t_img.shape)t_img torch.permute(t_img, (1, 2, 0))plt.imshow(t_img)plt.show()
3.5.4 调整图片颜色
img Image.open(./img/100.jpg)transform transforms.Compose([transforms.ColorJitter(brightness0.2, contrast0.2, saturation0.2, hue0.2), transforms.ToTensor()])r_img transform(img)print(r_img.shape)r_img r_img.permute(1, 2, 0)plt.imshow(r_img)plt.show()3.5.5 随机旋转
def test04():pathtorch-fcnn/fcnn-demo/datasets/100.jpgimgImage.open(path)print(img.size)transformtransforms.RandomRotation((30,60), expandFalse, centerNone, fill0)3.5.6 图片转Tensor
def test05():ttorch.randn(3,224,224)transformtransforms.Compose([# 转换为PIL图片transforms.ToPILImage(),transforms.ToTensor(),])t_imgtransform(t)# print(t_img.shape)t_img torch.permute(t_img, (1, 2, 0))plt.imshow(t_img)plt.show()3.5.7 Tensor转图片
import torch
from PIL import Image
from torchvision import transformsdef test002():# 1. 随机一个数据表示图片img_tensor torch.randn(3, 224, 224)# 2. 创建一个transformstransform transforms.ToPILImage()# 3. 转换为图片img transform(img_tensor)img.show()# 4. 保存图片img.save(./test.jpg)if __name__ __main__:test002()3.5.8 归一化
def test06():pathtorch-fcnn/fcnn-demo/datasets/100.jpgimgImage.open(path)print(img.size)ttorch.randn(3,224,224)transform transforms.Compose([transforms.ToTensor(),# 归一化transforms.Normalize(mean[0.485, 0.456, 0.406], std[0.229, 0.224, 0.225])])t_imgtransform(t)# print(t_img.shape)t_img torch.permute(t_img, (1, 2, 0))plt.imshow(t_img)plt.show()3.5.9 数据增强整合
from PIL import Image
from pathlib import Path
import matplotlib.pyplot as plt
import numpy as np
import torch
from torchvision import transforms, datasets, utilsdef test01():# 定义数据增强和归一化transform transforms.Compose([transforms.RandomHorizontalFlip(), # 随机水平翻转transforms.RandomRotation(10), # 随机旋转 ±10 度transforms.RandomResizedCrop(32, scale(0.8, 1.0)), # 随机裁剪到 32x32缩放比例在0.8到1.0之间transforms.ColorJitter(brightness0.2, contrast0.2, saturation0.2, hue0.1), # 随机调整亮度、对比度、饱和度、色调transforms.ToTensor(), # 转换为 Tensortransforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)), # 归一化这是一种常见的经验设置适用于数据范围 [0, 1]使其映射到 [-1, 1]])# 加载 CIFAR-10 数据集并应用数据增强trainset datasets.CIFAR10(root./cifar10_data, trainTrue, downloadTrue, transformtransform)dataloader DataLoader(trainset, batch_size4, shuffleFalse)# 获取一个批次的数据images, labels next(iter(dataloader))# 还原图片并显示plt.figure(figsize(10, 5))for i in range(4):# 反归一化将像素值从 [-1, 1] 还原到 [0, 1]img images[i] / 2 0.5# 转换为 PIL 图像img_pil transforms.ToPILImage()(img)# 显示图片plt.subplot(1, 4, i 1)plt.imshow(img_pil)plt.axis(off)plt.title(fLabel: {labels[i]})plt.show()if __name__ __main__:test01()