day53 神经网络调参指南

目录

一、引言

二、权重初始化:为何如此重要?

(一)随机种子:确保实验的可重复性

(二)权重初始化的重要性

1. 神经网络的对称性问题

2. 避免梯度消失和梯度爆炸

(三)PyTorch中的权重初始化

三、权重可视化:直观理解模型的学习过程

(一)权重分布图

(二)偏置可视化

(三)权重可视化的意义

四、神经网络调参指南

(一)参数分类

(二)调参顺序

(三)调参技巧


一、权重初始化:为何如此重要?

在开始之前,我们先来看一个简单的线性模型。这个模型非常简单,只有一个线性层,输入两个维度的数据,输出一个维度的结果。代码如下:

import torch
import torch.nn as nn# 定义简单的线性模型(无隐藏层)
# 输入2个纬度的数据,得到1个纬度的输出
class SimpleNet(nn.Module):def __init__(self):super(SimpleNet, self).__init__()# 线性层:2个输入特征,1个输出特征self.linear = nn.Linear(2, 1)def forward(self, x):# 前向传播:y = w1*x1 + w2*x2 + breturn self.linear(x)# 创建模型实例
model = SimpleNet()# 查看模型参数
print("模型参数:")
for name, param in model.named_parameters():print(f"{name}: {param.data}")

运行这段代码后,我们会看到模型的权重和偏置被随机初始化了。例如,权重可能是tensor([[ 0.3268, -0.5784]]),偏置可能是tensor([0.6189])。这些随机值看起来似乎没什么特别的,但实际上,它们对模型的训练过程有着深远的影响。

(一)随机种子:确保实验的可重复性

在深度学习中,随机性无处不在。权重的随机初始化、数据的随机加载、数据增强的随机化……这些随机性虽然有助于模型的学习,但也给实验的可重复性带来了挑战。为了确保每次实验的结果都能复现,我们需要设置随机种子。以下是一个全局随机种子设置的函数:

import torch
import numpy as np
import os
import random# 全局随机函数
def set_seed(seed=42, deterministic=True):"""设置全局随机种子,确保实验可重复性参数:seed: 随机种子值,默认为42deterministic: 是否启用确定性模式,默认为True"""# 设置Python的随机种子random.seed(seed) os.environ['PYTHONHASHSEED'] = str(seed) # 确保Python哈希函数的随机性一致,比如字典、集合等无序# 设置NumPy的随机种子np.random.seed(seed)# 设置PyTorch的随机种子torch.manual_seed(seed) # 设置CPU上的随机种子torch.cuda.manual_seed(seed) # 设置GPU上的随机种子torch.cuda.manual_seed_all(seed)  # 如果使用多GPU# 配置cuDNN以确保结果可重复if deterministic:torch.backends.cudnn.deterministic = Truetorch.backends.cudnn.benchmark = False

通过设置随机种子,我们可以确保每次运行代码时,随机生成的值都是一样的。这对于调试代码、验证实验结果以及与他人分享实验过程都非常有帮助。

(二)权重初始化的重要性

权重初始化是神经网络训练的第一步,也是至关重要的一步。如果权重初始化不当,可能会导致模型训练缓慢、无法收敛甚至发散。那么,为什么权重初始化如此重要呢?

1. 神经网络的对称性问题

神经网络的每个神经元本质上都是在做输入到输出的映射。以Sigmoid激活函数为例,其公式为y = sigmoid(wx + b)。如果所有神经元的权重和偏置都一样,那么无论输入如何变化,所有神经元的输出都会一致。在这种情况下,反向传播时的梯度也会完全相同,导致所有神经元的权重更新也完全一致。换句话说,这些神经元在训练过程中始终保持同步,无法学习到不同的特征。

为了避免这种对称性问题,我们需要随机初始化权重和偏置,让每个神经元在训练开始时就有所不同。即使初始差异很小,激活函数的非线性也会放大这种差异。随着训练的进行,这些差异会逐渐扩大,最终形成功能各异的神经元。

2. 避免梯度消失和梯度爆炸

不同的激活函数有不同的饱和区和非饱和区。以Sigmoid激活函数为例,其导数在输入绝对值较大时趋近于0。如果初始权重过大,输入x = w・input + b可能会导致激活函数进入饱和区,反向传播时梯度接近0,权重更新缓慢,这就是梯度消失问题。相反,如果初始权重过小,可能会导致梯度爆炸,使训练过程不稳定。

为了避免这些问题,初始权重通常设置在接近0的小范围内,如[-0.1, 0.1][-0.01, 0.01],或者通过特定分布(如正态分布、均匀分布)生成小值。这样可以确保神经元的输入在激活函数的非饱和区内,从而避免梯度消失和梯度爆炸。

(三)PyTorch中的权重初始化

在PyTorch中,权重初始化可以通过多种方式实现。默认情况下,PyTorch会根据不同的层类型自动选择合适的初始化方法。例如,对于卷积层,PyTorch使用Kaiming初始化(适配ReLU激活函数);对于全连接层,PyTorch使用Xavier初始化(适配Sigmoid/Tanh激活函数)。

我们可以通过以下代码查看PyTorch默认初始化的权重:

import torch
import torch.nn as nn
import matplotlib.pyplot as plt
import numpy as np# 设置设备
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")# 定义极简CNN模型(仅1个卷积层+1个全连接层)
class SimpleCNN(nn.Module):def __init__(self):super(SimpleCNN, self).__init__()# 卷积层:输入3通道,输出16通道,卷积核3x3self.conv1 = nn.Conv2d(3, 16, kernel_size=3, padding=1)# 池化层:2x2窗口,尺寸减半self.pool = nn.MaxPool2d(kernel_size=2)# 全连接层:展平后连接到10个输出(对应10个类别)# 输入尺寸:16通道 × 16x16特征图 = 16×16×16=4096self.fc = nn.Linear(16 * 16 * 16, 10)def forward(self, x):# 卷积+池化x = self.pool(self.conv1(x))  # 输出尺寸: [batch, 16, 16, 16]# 展平x = x.view(-1, 16 * 16 * 16)  # 展平为: [batch, 4096]# 全连接x = self.fc(x)  # 输出尺寸: [batch, 10]return x# 初始化模型
model = SimpleCNN()
model = model.to(device)# 查看模型结构
print(model)# 查看初始权重统计信息
def print_weight_stats(model):# 卷积层conv_weights = model.conv1.weight.dataprint("\n卷积层 权重统计:")print(f"  均值: {conv_weights.mean().item():.6f}")print(f"  标准差: {conv_weights.std().item():.6f}")print(f"  理论标准差 (Kaiming): {np.sqrt(2/3):.6f}")  # 输入通道数为3# 全连接层fc_weights = model.fc.weight.dataprint("\n全连接层 权重统计:")print(f"  均值: {fc_weights.mean().item():.6f}")print(f"  标准差: {fc_weights.std().item():.6f}")print(f"  理论标准差 (Kaiming): {np.sqrt(2/(16*16*16)):.6f}")# 打印权重统计
print_weight_stats(model)

运行这段代码后,我们可以看到卷积层和全连接层的权重统计信息。例如,卷积层的权重均值为-0.005068,标准差为0.109001;全连接层的权重均值为-0.000031,标准差为0.009038。这些统计信息可以帮助我们了解权重的分布情况。

二、权重可视化:直观理解模型的学习过程

权重可视化是将神经网络的权重以图形的形式展示出来,帮助我们直观地理解模型的学习过程。通过权重可视化,我们可以观察到权重从初始化(如随机分布)到逐渐收敛、形成规律模式的动态变化。这对于理解模型如何一步步“学习”特征非常有帮助。

(一)权重分布图

权重分布图可以直观地展示权重的分布情况。以下是一个可视化权重分布的函数:

# 改进的可视化权重分布函数
def visualize_weights(model, layer_name, weights, save_path=None):plt.figure(figsize=(12, 5))# 权重直方图plt.subplot(1, 2, 1)plt.hist(weights.cpu().numpy().flatten(), bins=50)plt.title(f'{layer_name} 权重分布')plt.xlabel('权重值')plt.ylabel('频次')# 权重热图plt.subplot(1, 2, 2)if len(weights.shape) == 4:  # 卷积层权重 [out_channels, in_channels, kernel_size, kernel_size]# 只显示第一个输入通道的前10个滤波器w = weights[:10, 0].cpu().numpy()plt.imshow(w.reshape(-1, weights.shape[2]), cmap='viridis')else:  # 全连接层权重 [out_features, in_features]# 只显示前10个神经元的权重,重塑为更合理的矩形w = weights[:10].cpu().numpy()# 计算更合理的二维形状(尝试接近正方形)n_features = w.shape[1]side_length = int(np.sqrt(n_features))# 如果不能完美整除,添加零填充使能重塑if n_features % side_length != 0:new_size = (side_length + 1) * side_lengthw_padded = np.zeros((w.shape[0], new_size))w_padded[:, :n_features] = ww = w_padded# 重塑并显示plt.imshow(w.reshape(w.shape[0] * side_length, -1), cmap='viridis')plt.colorbar()plt.title(f'{layer_name} 权重热图')plt.tight_layout()if save_path:plt.savefig(f'{save_path}_{layer_name}.png')plt.show()

通过这个函数,我们可以将卷积层和全连接层的权重分别可视化为直方图和热图。例如,卷积层的权重直方图可以直观地展示权重的分布范围和频率,而热图则可以展示权重的空间分布情况。

(二)偏置可视化

除了权重,偏置也是神经网络的重要组成部分。我们可以通过以下代码可视化偏置:

# 可视化偏置
plt.figure(figsize=(12, 5))# 卷积层偏置
conv_bias = model.conv1.bias.data
plt.subplot(1, 2, 1)
plt.bar(range(len(conv_bias)), conv_bias.cpu().numpy())
plt.title('卷积层 偏置')# 全连接层偏置
fc_bias = model.fc.bias.data
plt.subplot(1, 2, 2)
plt.bar(range(len(fc_bias)), fc_bias.cpu().numpy())
plt.title('全连接层 偏置')plt.tight_layout()
plt.savefig('biases_initial.png')
plt.show()

通过可视化偏置,我们可以了解偏置的分布情况。例如,卷积层的偏置均值为-0.031176,标准差为0.086302;全连接层的偏置均值为0.003063,标准差为0.010418

(三)权重可视化的意义

通过权重可视化,我们可以直观地观察到权重的变化情况,从而更好地理解模型的学习过程。例如,如果权重分布越来越集中在0附近,且更新幅度极小,可能是梯度消失;如果权重值突然大幅震荡、超出合理范围,可能是梯度爆炸。通过这些观察,我们可以及时调整模型的训练策略,避免训练过程出现问题。

此外,权重可视化还可以帮助我们理解模型如何学习特征。例如,卷积层的权重在训练初期可能比较杂乱,但随着训练的进行,可能会逐渐聚焦于边缘、纹理等特定模式。通过观察这些变化,我们可以更好地理解模型的工作原理。

三、神经网络调参指南

在深度学习中,调参是一个非常重要且复杂的过程。合理的调参可以显著提高模型的性能。以下是一些调参的建议和技巧:

(一)参数分类

通常可以将超参数分为三类:网络参数、优化参数和正则化参数。

  • 网络参数:包括网络层之间的交互方式(如相加、相乘或串接)、卷积核的数量和尺寸、网络层数(深度)和激活函数等。

  • 优化参数:一般指学习率、批样本数量、不同优化器的参数及部分损失函数的可调参数。

  • 正则化参数:如权重衰减系数、丢弃比率(dropout)。

(二)调参顺序

调参的顺序非常重要,一般遵循“先保证模型能训练(基础配置)→ 再提升性能(核心参数)→ 最后抑制过拟合(正则化)”的思路。具体步骤如下:

  1. 参数初始化:如果有预训练参数,直接使用预训练参数初始化模型。如果没有,可以选择合适的初始化方法,如Kaiming初始化或Xavier初始化。

  2. Batch Size:尽可能选择较大的Batch Size,但要根据硬件资源进行调整。

  3. Epoch:训练到收敛位置,可以采取早停策略。

  4. 学习率与调度器:学习率是调参中收益最高的参数。一般最开始用Adam快速收敛,然后SGD收尾。可以使用学习率调度器,如CosineAnnealingLR、StepLR或ReduceLROnPlateau。

  5. 模型结构:通过消融实验或对照试验调整模型结构。

  6. 损失函数:根据任务选择合适的损失函数,如交叉熵损失函数、二元交叉熵损失函数或Focal Loss。

  7. 激活函数:一般默认选择ReLU或其变体,如Leaky ReLU。

  8. 正则化参数:如果模型出现过拟合,可以增加正则化参数,如Dropout或L2权重衰减。

(三)调参技巧

  • 初始化参数:预训练参数是最好的参数初始化方法。如果没有预训练参数,可以选择Kaiming初始化或Xavier初始化。

  • Batch Size:Batch Size越大越好,但要根据硬件资源进行调整。

  • 学习率调整:学习率过大可能导致模型无法收敛,学习率过小可能导致训练停滞。可以通过学习率调度器动态调整学习率。

  • 激活函数选择:一般默认选择ReLU或其变体,如Leaky ReLU。在二分类任务中,最后的输出层使用Sigmoid激活函数;在多分类任务中,使用Softmax激活函数。

  • 损失函数选择:在分类任务中,可以选择交叉熵损失函数或Focal Loss;在回归任务中,可以选择均方误差(MSE)或绝对误差(MAE)。

  • 正则化系数:Dropout一般控制在0.2-0.5之间。如果模型出现过拟合,可以增加正则化参数。@浙大疏锦行

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/web/83474.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【大模型02---Megatron-LM】

文章目录 Megatron-LM数据并行模型并行张量并行流水线并行 3D并行 Megatron-LM Megatron是当前大模型训练时经常使用的一种分布式并行框架,它通过采用DP,TP,PP等来加速模型的训练,反正就是一个字,好。 大模型在训练的时候,显存占…

魔百和网络机顶盒CM211-1硬件解析

先来个正面照 背面照 核芯 无线网卡 支持WiFi与蓝牙 硬盘 正面内存与背面内存

Kratos 与Golang Cms的关系

Kratos 与 Golang CMS 的关系 Kratos 是 Bilibili 开源的一款轻量级 Go 语言微服务框架,专注于构建高性能、可扩展的后端服务。虽然它本身并不是一个完整的 CMS(内容管理系统),但它可以用于开发 CMS 系统的后端或 API 服务。 我们的目标是提供全面的微服务开发技术。基于…

在vue3+vite中给 Video视频 添加字幕

Video视频 添加字幕 方式一: 使用 track标签template标签中css样式修改方式二:直接读取.vtt文件方式一: 使用 track标签 参考1:https://blog.csdn.net/weixin_42321819/article/details/112442773 参考2:https://blog.csdn.net/foren_whb/article/details/80810552 template标…

UE4手动实现billboard效果让物体始终面向相机正面

一个很简单的需求,但在网上竟然没查到。首先不能用FindLookAtRotation,因为这是用location算的,是让物体朝向相机的方向,而不是朝向相机的正面。区别如下图所示: 然后想用billboard component,不过这个原生…

在阿里云上搭建n8n

0.安装docker 0.1 删除Docker相关源 #删除Docker相关源 sudo rm -f /etc/yum.repos.d/docker*.repo #卸载Docker和相关的软件包 sudo dnf -y remove \ docker-ce \ containerd.io \ docker-ce-rootless-extras \ docker-buildx-plugin \ docker-ce-cli \ docker-compose-plug…

Qt中的OpenGL (4)[纹理]

文章说明 本文是学习OpenGL的笔记,主要参考大神JoeyDeVries的LearnOpenGL第六课《纹理》,并将教程中的代码基于Qt进行实现。 学习目标 掌握纹理基本知识掌握纹理贴图目录结构 |- |-- HelloTextures|--- hello_textures.cpp|--- hello_textures.h|--- main.cpp|--- CMakeLi…

【Java多线程从青铜到王者】阻塞队列(十)

阻塞队列 阻塞队列也是一种队列,先进的先出 阻塞队列就是对普通的队列做出的拓展 阻塞队列的特性 1.线程安全的,我们普通的队列值线程不安全的 2.具有阻塞的特性: a》如果针对一个已经满了的队列进行如队列操作的话,入队列操作就…

Python打卡第52天

浙大疏锦行 作业: 对于day41的简单cnn,看看是否可以借助调参指南进一步提高精度。 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import ma…

力扣100- 环形链表

方法一 遍历 循环链表&#xff0c;查找链表节点是否重复出现 public boolean hasCycle(ListNode head) {Set<ListNode> set new HashSet<>(); if (head null) return false; while (head ! null) {if (set.contains(head)) {return true;}set.add(head);head …

Java + Spring Boot + Mybatis 插入数据后,获取自增 id 的方法

在 MyBatis 中使用 useGeneratedKeys"true" 获取新插入记录的自增 ID 值&#xff0c;可通过以下步骤实现&#xff1a; 1. 配置 Mapper XML 在插入语句的 <insert> 标签中设置&#xff1a; xml 复制 下载 运行 <insert id"insertUser" para…

Meta发布V-JEPA 2世界模型及物理推理新基准,推动AI在物理世界中的认知与规划能力

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

触觉智能RK3576核心板工业应用之软硬件全国产化,成功适配开源鸿蒙OpenHarmony5.0

在全球科技竞争加剧和供应链安全日益重要的背景下&#xff0c;实现关键软硬件的全国产化替代已成为国家战略和产业共识。在这一背景下&#xff0c;触觉智能推出RK3576核心板,率先适配开源鸿蒙OpenHarmony5.0操作系统&#xff0c;真正实现了从芯片到操作系统的全栈国产化方案&am…

前端基础知识ES6系列 - 01(var、let、const之间的区别)

一、var 在ES5中&#xff0c;顶层对象的属性和全局变量是等价的&#xff0c;用var声明的变量既是全局变量&#xff0c;也是顶层变量 注意&#xff1a;顶层对象&#xff0c;在浏览器环境指的是window对象&#xff0c;在 Node 指的是global对象 var a 10; console.log(window…

Python Docker 镜像构建完整指南:从基础到优化

Python 是一门广泛使用的编程语言,在容器化环境中,构建和使用 Python 镜像是非常常见的任务。本文将提供一个完整的指南,包括选择基础镜像、制作流程、不同场景下的应用、安全性最佳实践以及镜像优化策略。 1. 选择合适的基础镜像 1.1 官方 Python 镜像 Docker Hub 提供了…

【狂飙AGI】第1课:大模型概述

目录 &#xff08;一&#xff09;大模型概念解析&#xff08;二&#xff09;大模型发展历程&#xff08;三&#xff09;大模型发展现状&#xff08;1&#xff09;OpenAI&#xff08;2&#xff09;微软&#xff08;3&#xff09;谷歌&#xff08;4&#xff09;Meta &#xff08;…

vite ts 配置使用@ 允许js

1.vite.config.ts 配置 import { defineConfig } from vite import vue from vitejs/plugin-vue import { fileURLToPath, URL } from node:url import setup_extend from vite-plugin-vue-setup-extend// https://vite.dev/config/ export default defineConfig({plugins: …

使用Ollama+open-webui搭建本地AI模型

本地搭建AI模型 说明&#xff1a;1、下载Ollama2、下载模型3、pip安装open-webui&#xff08;不推荐&#xff09;1、Python版本不对应2、下载wheels失败 4、docker安装open-webui 说明&#xff1a; 在windows上搭建本地AI&#xff0c;使用Ollamaopen-webui的方式&#xff0c;可…

第 87 场周赛:比较含退格的字符串、数组中的最长山脉、一手顺子、访问所有节点的最短路径

Q1、[简单] 比较含退格的字符串 1、题目描述 给定 s 和 t 两个字符串&#xff0c;当它们分别被输入到空白的文本编辑器后&#xff0c;如果两者相等&#xff0c;返回 true 。# 代表退格字符。 **注意&#xff1a;**如果对空文本输入退格字符&#xff0c;文本继续为空。 示例 …

linux安装阿里DataX实现数据迁移

目录 下载datax工具包(如果下载慢&#xff0c;请尝试其他国内镜像站或其他网站下载相应资源) 解压工具包到当前目录里 接着进入conf配置目录并创建一个myjob.json&#xff08;临时测试json&#xff09;&#xff0c;myjob.json内容如下&#xff0c;用于模拟test库tab1表数据同…