模型训练坎坷路--逐步提升模型准确率从40%到90%+

news2025/1/10 20:57:42

文章目录

  • 〇、前言
  • 一、更改学习率
    • 1.原理:欠拟合需要减小学习率
    • 2.效果-->有用!
  • 二、更改训练批次batch_size
    • 1.原理:更大的批量大小时,梯度估计更加精确
    • 2.效果-->有点用
  • 三、更改数据预处理方式
    • 1.原理:数据可能没有正确标准化或归一化,影响模型学习
    • 2.效果
  • 四、更改正则化强度
    • 1.原理:过大的正则化会限制模型的学习能力,导致欠拟合
    • 2.效果
  • 五、更改优化器
    • 1.原理
    • 2.效果-->有用
  • 六、更改调度器
    • 1.原理
    • 2.效果-->有用,本质上还是更改学习率
  • 七、终极大招:改模型结构+数据增强 双管齐下
    • 1.原理:通过将第一层的7x7卷积核改为3x3、去掉最大池化+使用了 RandomCrop、RandomHorizontalFlip、Normalize 和 Cutout 进行数据增强+250轮
      • a. 卷积核大小与感受野的关系
      • b. 避免过度池化
    • 2.效果
    • 3.实验对比Adam和SGD
  • 八、结论
    • 1.最终代码
    • 2.思考体会

〇、前言

剪枝实验的基准得是一个微调好的准确率保持较高的模型,按照我之前yolov5的经验来看,这还不简单? 选模型+合适的数据集,20轮就OK!

我计划使用 ResNet-18模型加上Cifar-10数据集,训练轮次100轮,准确度达到95%我就立马停下。
可是过程却不大对劲,都20轮了我的准确率还是40%上下窜,一点进步的痕迹都没有,于是,果断按下停止键…

import copy
import math
import random
import time
from collections import OrderedDict, defaultdict
from typing import Union, List

import numpy as np
import torch
from matplotlib import pyplot as plt
from torch import nn
from torch.optim import *
from torch.optim.lr_scheduler import *
from torch.utils.data import DataLoader
from torchprofile import profile_macs
from torchvision.datasets import *
from torchvision.transforms import *
from torchvision import models  # 引入torchvision.models
from tqdm.auto import tqdm

from torchprofile import profile_macs

assert torch.cuda.is_available(), \
    "The current runtime does not have CUDA support." \
    "Please go to menu bar (Runtime - Change runtime type) and select GPU"

random.seed(0)
np.random.seed(0)
torch.manual_seed(0)

def download_url(url, model_dir='.', overwrite=False):
    import os, sys, ssl
    from urllib.request import urlretrieve
    ssl._create_default_https_context = ssl._create_unverified_context
    target_dir = url.split('/')[-1]
    model_dir = os.path.expanduser(model_dir)
    try:
        if not os.path.exists(model_dir):
            os.makedirs(model_dir)
        model_dir = os.path.join(model_dir, target_dir)
        cached_file = model_dir
        if not os.path.exists(cached_file) or overwrite:
            sys.stderr.write('Downloading: "{}" to {}\n'.format(url, cached_file))
            urlretrieve(url, cached_file)
        return cached_file
    except Exception as e:
        # remove lock file so download can be executed next time.
        os.remove(os.path.join(model_dir, 'download.lock'))
        sys.stderr.write('Failed to download from url %s' % url + '\n' + str(e) + '\n')
        return None

def train(
    model: nn.Module,
    train_dataloader: DataLoader,
    test_dataloader: DataLoader,
    criterion: nn.Module,
    optimizer: Optimizer,
    scheduler: LambdaLR,
    num_epochs: int,
    target_accuracy: float = 95.0,  # 目标准确率
    save_path: str = "finetuned_model.pth",  # 模型保存路径
    callbacks=None
) -> None:
    for epoch in range(num_epochs):  # 使用指定的训练轮数
        model.train()
        for inputs, targets in tqdm(train_dataloader, desc=f'train epoch {epoch+1}/{num_epochs}', leave=False):
            # Move the data from CPU to GPU
            inputs = inputs.cuda()
            targets = targets.cuda()

            # Reset the gradients (from the last iteration)
            optimizer.zero_grad()

            # Forward inference
            outputs = model(inputs)
            loss = criterion(outputs, targets)

            # Backward propagation
            loss.backward()

            # Update optimizer and LR scheduler
            optimizer.step()
            scheduler.step()

            if callbacks is not None:
                for callback in callbacks:
                    callback()

        # 训练完一个epoch后进行评估
        accuracy = evaluate(model, test_dataloader)
        print(f"Epoch {epoch+1}: Accuracy = {accuracy:.2f}%")

        # 检查是否达到目标准确率
        if accuracy >= target_accuracy:
            print(f"Reached target accuracy of {target_accuracy}%. Saving model...")
            torch.save(model.state_dict(), save_path)
            print(f"Model saved to {save_path}")
            return

@torch.inference_mode()
def evaluate(
    model: nn.Module,
    dataloader: DataLoader,
    verbose=True,
) -> float:
    model.eval()

    num_samples = 0
    num_correct = 0

    for inputs, targets in tqdm(dataloader, desc="eval", leave=False,
                                disable=not verbose):
        # Move the data from CPU to GPU
        inputs = inputs.cuda()
        targets = targets.cuda()

        # Inference
        outputs = model(inputs)

        # Convert logits to class indices
        outputs = outputs.argmax(dim=1)

        # Update metrics
        num_samples += targets.size(0)
        num_correct += (outputs == targets).sum()

    return (num_correct / num_samples * 100).item()

# 加载预训练模型和权重
model = models.resnet18(pretrained=True).cuda()  # 直接加载预训练的ResNet18模型
model.fc = nn.Linear(model.fc.in_features, 10).cuda()  # 修改最后的全连接层以适应CIFAR-10

# 数据处理
image_size = 32
transforms = {
    "train": Compose([
        RandomCrop(image_size, padding=4),
        RandomHorizontalFlip(),
        ToTensor(),
    ]),
    "test": Compose([
        ToTensor(),
    ]),
}

# 数据加载
train_dataset = CIFAR10(
    root="data/cifar10",
    train=True,
    download=True,
    transform=transforms["train"],
)
test_dataset = CIFAR10(
    root="data/cifar10",
    train=False,
    download=True,
    transform=transforms["test"],
)

train_dataloader = DataLoader(
    train_dataset,
    batch_size=512,
    shuffle=True,
    num_workers=0,
    pin_memory=True,
)

test_dataloader = DataLoader(
    test_dataset,
    batch_size=512,
    shuffle=False,
    num_workers=0,
    pin_memory=True,
)

# 设置训练轮数
num_epochs = 100  # 设置为一个较大的值,如果达到准确率要求会提前停止

# 训练和评估
criterion = nn.CrossEntropyLoss().cuda()
optimizer = torch.optim.SGD(model.parameters(), lr=0.1, momentum=0.9, weight_decay=5e-4)
scheduler = torch.optim.lr_scheduler.LambdaLR(optimizer, lr_lambda=lambda epoch: 0.1**(epoch // 30))

train(model, train_dataloader, test_dataloader, criterion, optimizer, scheduler, num_epochs, target_accuracy=95.0, save_path="finetuned_resnet18.pth")

一、更改学习率

1.原理:欠拟合需要减小学习率

学习率是深度学习中一个非常重要的超参数,它决定了模型在每一次参数更新时的步长大小。更改学习率可以直接影响模型的收敛速度和准确度。

学习率过大会导致模型在参数更新时跳过最优解,可能会导致模型无法收敛或者收敛到次优解。这种情况下,模型的准确度可能较低。

相反,学习率过小会导致模型收敛速度过慢,需要更多的迭代次数才能达到较好的准确度。在实际中,如果学习率过小,模型可能会陷入局部最优解,无法跳出。

一般来说,选择合适的学习率需要进行实验和调优,可以借助学习率调度策略(如学习率衰减、学习率动态调整等)来逐步调整学习率,以达到更好的模型准确度。

2.效果–>有用!

将学习率从0.1改成0.01,第一轮立马就60%了!可是后面也是一点变化都没有
在这里插入图片描述

二、更改训练批次batch_size

1.原理:更大的批量大小时,梯度估计更加精确

使用更大的批量大小时,梯度估计更加精确,因为它基于更多的数据样本。这通常会导致参数更新更加稳定,损失函数更快下降,因此每轮的训练准确性更高。

2.效果–>有点用

由于我本来使用的训练批次是512,已经很大了,再大俺的GPU受不住,所以反向一下这是使用batch_size=128的结果,可以看到模型维持在55%准确度左右。
在这里插入图片描述

三、更改数据预处理方式

1.原理:数据可能没有正确标准化或归一化,影响模型学习

稳定收敛:归一化数据可以使得特征的数值范围相近,这有助于瞬时下降算法更加稳定和快速地收敛。如果特征值的范围方差很大,模型在训练时可能会出现过多的震荡,收敛影响速度和稳定性。

防止特征主导:在没有归一化的数据集中,数值范围增大的特征可能会对损失函数产生过大的影响,从而更加主导模型的学习过程。归一化后,各个特征对模型的影响程度为队列。

原来的数据预处理方式

# 数据处理
image_size = 32
transforms = {
    "train": Compose([
        RandomCrop(image_size, padding=4),
        RandomHorizontalFlip(),
        ToTensor(),
    ]),
    "test": Compose([
        ToTensor(),
    ]),
}

改成

# 定义图像尺寸
image_size = 32

# 定义训练和测试数据的转换操作
transforms = {
    "train": Compose([
        RandomCrop(image_size, padding=4),   # 随机裁剪,带有4像素的填充
        RandomHorizontalFlip(),              # 随机水平翻转
        ToTensor(),                          # 转换为PyTorch张量
        Normalize(mean=[0.4914, 0.4822, 0.4465], std=[0.2023, 0.1994, 0.2010]) # 标准化
    ]),
    "test": Compose([
        ToTensor(),                          # 转换为PyTorch张量
        Normalize(mean=[0.4914, 0.4822, 0.4465], std=[0.2023, 0.1994, 0.2010]) # 标准化
    ]),
}

2.效果

我是在使用512批次大小以及使用0.01学习率的情况下,来更改这个数据集的预处理的。效果类比上面基本没有变化。
在这里插入图片描述

四、更改正则化强度

1.原理:过大的正则化会限制模型的学习能力,导致欠拟合

optimizer = torch.optim.SGD(model.parameters(), lr=0.01, momentum=0.9, weight_decay=5e-4)
将改成weight_decay=1e-4。

weight_decay=5e-4 参数实际上就是L2正则化的系数。
L2正则化会在损失函数中增加一项与模型权重的平方和成正比的惩罚项。这可以防止模型权重变得过大,从而减少过拟合的风险。本实验的现象是:“训练集和测试集的准确度都较低且不升”,明显的欠拟合

假设你在操场上用树枝弹簧来控制一个弹性球的运动。你的目标是让弹性球精准地击中地上的一组标靶,代表着模型需要一个的数据点。

无正则化(无营养的约束):
如果没有弹簧的约束,弹性球可能会因为自身的弹性,弹得过高或过低,甚至局部乱弹(过度),这就像模型过度重复训练数据,无法很好地泛化到新数据。

正则化强度过大(弹簧过紧):
如果弹簧限制太紧,弹性球的自由度会很严重。球几乎无法弹出太远,甚至连接近标靶的机会都没有,只是在原地有点弹动。这就像模型参数被过度限制,无法有效学习数据的模式,导致不足。

适应的正则化强度(弹簧松紧适中):
如果弹簧的松紧度适中,弹性球能够有一定的自由度弹向目标目标,同时又不会弹得过远而失去控制。这样,弹性球可以多次尝试,最终击中目标目标。这就像模型在正则化强度适中时,既能够避免过度,又能有效地导出数据,从而提高模型的精度。

2.效果

变化不大,看来此处不是这个原因
在这里插入图片描述

五、更改优化器

1.原理

开始实验时:推荐首先尝试 Adam,因为它通常不需要过多的超参数调节。
在优化过程中:如果发现模型过拟合,或者训练不稳定,可以尝试 SGD with Momentum。
高性能模型:对于精细调优的大型模型,考虑 AdamW 或 Nadam。

# 训练和评估
criterion = nn.CrossEntropyLoss().to(device)
#optimizer = torch.optim.SGD(model.parameters(), lr=0.01, momentum=0.9, weight_decay=1e-4)
optimizer = torch.optim.Adam(model.parameters(), lr=0.001, weight_decay=1e-4)
scheduler = torch.optim.lr_scheduler.LambdaLR(optimizer, lr_lambda=lambda epoch: 0.1**(epoch // 30))

2.效果–>有用

准确度显著提高到70%,但是还是停滞住了
在这里插入图片描述

六、更改调度器

1.原理

其实经过上述的尝试,我发现我这个是“”欠拟合“;最有效的方法就是在它准确率停滞的时候降低学习率,因此我尝试更改调度器。
scheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, mode=‘max’, factor=0.1, patience=5)

2.效果–>有用,本质上还是更改学习率

结果可以看出,我最高准确率到了88%,但是后续停滞的原因是因为:精度有限学习率约0了
我觉得以上这些超参数的调优已经到头了,而且我这个训练轮次也差不多数量合适的样子
在这里插入图片描述

七、终极大招:改模型结构+数据增强 双管齐下

1.原理:通过将第一层的7x7卷积核改为3x3、去掉最大池化+使用了 RandomCrop、RandomHorizontalFlip、Normalize 和 Cutout 进行数据增强+250轮

a. 卷积核大小与感受野的关系

  • 卷积核的大小决定了卷积层的感受野,即该层能“看到”的输入图像区域的大小。较大的卷积核(如7x7)能够一次性捕捉到较大的图像区域信息,但这也意味着每次卷积操作后,图像的空间分辨率会下降得更快,导致部分细节丢失。
  • 相比之下,3x3的卷积核感受野较小,它对图像的局部信息捕捉更加精细,能更好地保留图像的空间细节。这对于包含更多局部特征的任务(例如分类较小的物体或细节丰富的图像)尤其重要。

b. 避免过度池化

  • 原始ResNet中的第一个7x7卷积核通常伴随着步幅为2的下采样操作,以及一个最大池化层,这两个操作都会显著减少输入图像的空间尺寸。这种下采样对于非常大的图像可能有帮助,但对于较小的输入图像,会导致信息的丢失,从而影响模型的表现。通过将7x7卷积核换成3x3并移除最大池化层,模型可以在保留更多空间信息的情况下,进行更细致的特征提取,从而提高准确度。
import os
import torch
from torch import nn
from torchvision import models
from torch.utils.data import DataLoader
from torchvision.datasets import CIFAR10
from torchvision.transforms import Compose, RandomCrop, RandomHorizontalFlip, ToTensor, Normalize
from tqdm import tqdm  # 确保你已经导入 tqdm 库

# 检查是否有GPU可用
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

class CustomResNet18(models.ResNet):
    def __init__(self, num_classes=10):
        # 初始化ResNet18
        super().__init__(models.resnet.BasicBlock, [2, 2, 2, 2], num_classes=num_classes)
        # 修改第一层卷积
        self.conv1 = nn.Conv2d(3, 64, kernel_size=3, stride=1, padding=1, bias=False)
        self.maxpool = nn.Identity()  # 移除最大池化层

# 实例化模型
model = CustomResNet18().to(device)

# 加载已保存的模型权重(如果存在)
save_path = "finetuned_resnet18.pth"
if os.path.exists(save_path):
    print(f"Loading model weights from {save_path}...")
    model.load_state_dict(torch.load(save_path))
else:
    print(f"No saved model found at {save_path}. Starting fresh training.")

# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss().to(device)
optimizer = torch.optim.Adam(model.parameters(), lr=0.1, weight_decay=2e-4)  # 初始学习率设置为0.1

# 定义数据转换,包含数据增强
transforms = {
    "train": Compose([
        RandomCrop(32, padding=4),  # 随机裁剪
        RandomHorizontalFlip(),      # 随机水平翻转
        ToTensor(),                  # 转换为张量
        Normalize(mean=[0.4914, 0.4822, 0.4465], std=[0.2023, 0.1994, 0.2010]), # 归一化
        Cutout(n_holes=1, length=16),  # Cutout 数据增强
    ]),
    "test": Compose([
        ToTensor(),
        Normalize(mean=[0.4914, 0.4822, 0.4465], std=[0.2023, 0.1994, 0.2010]),
    ]),
}

# 数据加载
train_dataset = CIFAR10(root="data/cifar10", train=True, download=True, transform=transforms["train"])
test_dataset = CIFAR10(root="data/cifar10", train=False, download=True, transform=transforms["test"])

train_dataloader = DataLoader(train_dataset, batch_size=512, shuffle=True, num_workers=0, pin_memory=True)
test_dataloader = DataLoader(test_dataset, batch_size=512, shuffle=False, num_workers=0, pin_memory=True)

def adjust_learning_rate(optimizer, epoch):
    """Sets the learning rate to the initial LR decayed by 10 every 50 epochs"""
    lr = 0.1 * (0.1 ** (epoch // 35))
    for param_group in optimizer.param_groups:
        param_group['lr'] = lr

@torch.inference_mode()
def evaluate(model: nn.Module, dataloader: DataLoader, verbose=True) -> float:
    model.eval()
    num_samples = 0
    num_correct = 0
    for inputs, targets in tqdm(dataloader, desc="eval", leave=False, disable=not verbose):
        inputs = inputs.to(device)
        targets = targets.to(device)
        outputs = model(inputs)
        outputs = outputs.argmax(dim=1)
        num_samples += targets.size(0)
        num_correct += (outputs == targets).sum()
    return (num_correct / num_samples * 100).item()

def train(
    model: nn.Module,
    train_dataloader: DataLoader,
    test_dataloader: DataLoader,
    criterion: nn.Module,
    optimizer: torch.optim.Optimizer,
    num_epochs: int,
    target_accuracy: float = 92.0,
    save_path: str = "finetuned_resnet18.pth"
) -> None:
    best_accuracy = 0.0
    for epoch in range(num_epochs):
        adjust_learning_rate(optimizer, epoch)
        current_lr = optimizer.param_groups[0]['lr']
        print(f'Epoch {epoch+1}/{num_epochs}, Learning Rate: {current_lr:.6f}')
        model.train()
        for inputs, targets in tqdm(train_dataloader, desc=f'train epoch {epoch+1}/{num_epochs}', leave=False):
            inputs = inputs.to(device)
            targets = targets.to(device)
            optimizer.zero_grad()
            outputs = model(inputs)
            loss = criterion(outputs, targets)
            loss.backward()
            optimizer.step()
        accuracy = evaluate(model, test_dataloader)
        print(f"Epoch {epoch+1}: Accuracy = {accuracy:.2f}%")
        if accuracy > best_accuracy:
            best_accuracy = accuracy
            print(f"New best accuracy: {best_accuracy:.2f}%. Saving model...")
            torch.save(model.state_dict(), save_path)
        if accuracy >= target_accuracy:
            print(f"Reached target accuracy of {target_accuracy}%. Training stopped early.")
            return
    print(f"Training complete. Best accuracy: {best_accuracy:.2f}%. Saving final model...")
    torch.save(model.state_dict(), save_path)

# 设置训练轮数
num_epochs = 250
from google.colab import drive
drive.mount('/content/drive')

os.chdir('/content/drive/My Drive')
print(model)

# 开始训练
train(
    model,
    train_dataloader,
    test_dataloader,
    criterion,
    optimizer,
    num_epochs,
    target_accuracy=92.0,
    save_path="finetuned_resnet18.pth"
)

2.效果

出乎我的意料,效果并没有变好。
在这里插入图片描述
然后我就参考其他人的训练,我发现大家都用的SGD优化器结合学习率衰减的策略来训练的。那么使用Adam优化器和使用SGD有啥区别呢?
1.1 SGD(随机梯度下降)
特点:
基础的优化方法,每次使用一个或一小批样本更新模型参数。
可能会导致收敛速度慢或陷入局部最小值。
引入 动量 可以加速收敛并减少震荡。
适用场景:
大规模数据集。
对数据分布有较好的控制时(如预处理良好,归一化适当)。
希望更直接地控制学习率和动量。
1.2 Adam(自适应矩估计)
特点:
自适应调整学习率,结合了 AdaGrad 和 RMSProp 的优点。
通常不需要手动调整学习率。
在许多任务中表现良好,尤其是复杂的神经网络(如卷积网络、RNN)。
对学习率相对不敏感,初始学习率通常设置为 0.001。
适用场景:
初学者或对超参数调优不敏感的场景。
复杂的深度网络(如 Transformer、BERT)。
不平稳目标(例如在处理 NLP 任务时)。

我发现:使用Adam之后就不要自己再手动减小学习率了。

3.实验对比Adam和SGD

我结合网上大家最常用的SGD和Adam对比一下两者到底区别大不大:都使用128批次大小训练比较前100轮情况(哪个效果好哪个能跑到250轮),当然我都加载我之前那些失败品里面最好的权重(准确度81%)。

  • Adam使用初始学习率为0.01;
    在这里插入图片描述

为什么Adam 不是默认的优化算法?

  • SGD使用optimizer = optim.SGD(model.parameters(), lr=lr, momentum=0.9,
    weight_decay=5e-4)设置初始学习率为0.1,每当经过10个epoch训练的验证集损失没有下降时,学习率变为原来的0.5,共训练250个epoch。

在这里插入图片描述

八、结论

结果表明,哪里用得着300轮,好的训练策略和模型只要30轮嘤嘤嘤

1.最终代码

详细代码以及训练好的模型权重见,各位以后年薪百万的给我个star,小白我也想找工作:
俺的GitHub

# 定义基本残差块
class BasicBlock(nn.Module):
    expansion = 1

    def __init__(self, in_planes, planes, stride=1):
        super(BasicBlock, self).__init__()
        self.conv1 = nn.Conv2d(in_planes, planes, kernel_size=3, stride=stride, padding=1, bias=False)
        self.bn1 = nn.BatchNorm2d(planes)
        self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=1, padding=1, bias=False)
        self.bn2 = nn.BatchNorm2d(planes)

        self.shortcut = nn.Sequential()
        if stride != 1 or in_planes != self.expansion * planes:
            self.shortcut = nn.Sequential(
                nn.Conv2d(in_planes, self.expansion * planes, kernel_size=1, stride=stride, bias=False),
                nn.BatchNorm2d(self.expansion * planes)
            )

    def forward(self, x):
        out = torch.relu(self.bn1(self.conv1(x)))
        out = self.bn2(self.conv2(out))
        out += self.shortcut(x)
        out = torch.relu(out)
        return out

# 定义ResNet18模型
class ResNet(nn.Module):
    def __init__(self, block, num_blocks, num_classes=10):
        super(ResNet, self).__init__()
        self.in_planes = 64
        self.conv1 = nn.Conv2d(3, 64, kernel_size=3, stride=1, padding=1, bias=False)
        self.bn1 = nn.BatchNorm2d(64)
        self.layer1 = self._make_layer(block, 64, num_blocks[0], stride=1)
        self.layer2 = self._make_layer(block, 128, num_blocks[1], stride=2)
        self.layer3 = self._make_layer(block, 256, num_blocks[2], stride=2)
        self.layer4 = self._make_layer(block, 512, num_blocks[3], stride=2)
        self.linear = nn.Linear(512 * block.expansion, num_classes)

    def _make_layer(self, block, planes, num_blocks, stride):
        strides = [stride] + [1] * (num_blocks - 1)
        layers = []
        for stride in strides:
            layers.append(block(self.in_planes, planes, stride))
            self.in_planes = planes * block.expansion
        return nn.Sequential(*layers)

    def forward(self, x):
        out = torch.relu(self.bn1(self.conv1(x)))
        out = self.layer1(out)
        out = self.layer2(out)
        out = self.layer3(out)
        out = self.layer4(out)
        out = F.avg_pool2d(out, 4)  # 使用 F.avg_pool2d
        out = out.view(out.size(0), -1)
        out = self.linear(out)
        return out

# 实例化ResNet18
def Resnet18():
    return ResNet(BasicBlock, [2, 2, 2, 2])



在这里插入图片描述
在这里插入图片描述

2.思考体会

在模型训练过程中,影响模型准确率的关键次要因素主要集中在优化器的选择和学习率的设置上,最重要的还是模型结构的调整。

  1. 优化器的选择:优化器直接影响模型的收敛速度和最终性能。尽管Adam优化器通常是默认的选择,但在特定情况下,使用其他优化器(如SGD或RMSprop)可能会带来更好的效果。因此,优化器的选择应根据具体任务和模型的需求进行评估。

  2. 学习率的动态分阶段设置:学习率是影响模型训练的关键参数之一。固定的学习率可能无法适应整个训练过程的需求,因此通常采用动态调整的策略。在训练的初期,可以使用较高的学习率以加速收敛;在训练的后期,逐步降低学习率以精细化参数调整。这种分阶段的学习率设置有助于在不同的训练阶段优化模型表现。

  3. 明确模型潜力再相应改进:在进行模型训练时,参考与自己任务相似的模型和数据集案例是一个重要的步骤。通过分析这些案例,你可以了解在相同或相似的数据集上,其他模型能够达到的最好效果。这样,你可以明确当前模型在现有数据集上的潜力,进而判断是需要 优化模型结构 ,还是需要 调整数据集(如增加数据量或复杂性) 来进一步提升性能。如果通过参考案例发现你的模型已经接近理论最佳效果,那么就可能需要更改模型结构以适应数据的需求;反之,如果还有较大提升空间,则可能需要优化训练策略或数据处理方式。

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

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

相关文章

【微服务】springboot 整合表达式计算引擎 Aviator 使用详解

目录 一、前言 二、表达式计算框架概述 2.1 规则引擎 2.1.1 什么是规则引擎 2.1.2 规则引擎用途 2.1.3 规则引擎使用场景 2.2 表达式计算框架 2.2.1 表达式计算框架定义 2.2.2 表达式计算框架特点 2.2.3 表达式计算框架应用场景 2.3 表达式计算框架与规则引擎异同点 …

二叉树练习习题集一(Java)

1. 思路: 就是让左孩子和右孩子进行交换,这里需要一个中间变量用来记录,然后完成交换。如果进行优化则添加当左孩子和右孩子都为null时直接返回。 class Solution {public TreeNode invertTree(TreeNode root) {TreeNode tmpnull;//用来进行…

C++适配windows和linux下网络编程TCP简单案例

C网络编程 网络协议是计算机网络中通信双方必须遵循的一套规则和约定,用于实现数据的传输、处理和控制。这些规则包括了数据格式、数据交换顺序、数据处理方式、错误检测和纠正等。网络协议是使不同类型的计算机和网络设备能够相互通信的基础,是网络通信…

PDF转markdown工具:magic-pdf

1. magic-pdf 环境安装 conda create -n MinerU python3.10 conda activate MinerU pip install boto3>1.28.43 -i https://pypi.tuna.tsinghua.edu.cn/simple/ pip install magic-pdf[full]0.7.0b1 --extra-index-url https://wheels.myhloli.com -i https://pypi.tuna.t…

SSA-SVM多变量回归预测|樽海鞘群优化算法-支持向量机|Matalb

目录 一、程序及算法内容介绍: 基本内容: 亮点与优势: 二、实际运行效果: 三、算法介绍: 四、完整程序下载: 一、程序及算法内容介绍: 基本内容: 本代码基于Matlab平台编译&a…

Chrome浏览器更改默认User-Agent

一、业务需求 二、插件下载 三、插件使用 原创文章,请勿转载! 详细教程教你如何更改默认浏览器的User-Agent,几分钟足以! 一、业务需求 当我们遇到一些特定的UA才能访问的网址时,我们就可以通过一些手段来修改我们浏…

Python之字符串练习题(下)

21.nameStr“Albert Einstein",如何使用字符串运算符“:”来提取 nameStr 中的名和姓? mingnameStr[:6] xingnameStr[7:]23.下面哪些语句在运行时不会出错? (a)var xyz ’ * 10.5 (b)var ‘xyz’ * ‘5 ©var‘’xyz’*5 (d)var‘xyz’*5.0 重复运算符…

HTML静态网页成品作业(HTML+CSS)——美食企业介绍设计制作(1个页面)

🎉不定期分享源码,关注不丢失哦 文章目录 一、作品介绍二、作品演示三、代码目录四、网站代码HTML部分代码 五、源码获取 一、作品介绍 🏷️本套采用HTMLCSS,未使用Javacsript代码,共有1个页面。 二、作品演示 三、代…

在亚马逊云科技上对Stable Diffusion模型提示词、输出图像内容进行安全审核

项目简介: 小李哥将继续每天介绍一个基于亚马逊云科技AWS云计算平台的全球前沿AI技术解决方案,帮助大家快速了解国际上最热门的云计算平台亚马逊云科技AWS AI最佳实践,并应用到自己的日常工作里。 本次介绍的是如何在亚马逊云科技机器学习托…

HighPoint SSD7749M2:128TB NVMe 存储卡实现28 GB/s高速传输

HighPoint Technologies推出了一款全新的SSD7749M2 RAID卡,能够在标准的桌面工作站中安装多达16个M.2 SSD,实现高达128TB的闪存存储。该卡通过PCIe Gen4 x16接口提供高达28 GB/s的顺序读写性能。这些令人瞩目的性能规格伴随着高昂的价格标签。 #### 技术…

ArcGIS Pro基础:设置快速访问工具栏

上图【红色框线】内显示就是快速访问工具栏,访问非常方便,不需要切换到选项卡了 上图显示,可以勾选或者取消进行设置,通过【更多命令】可以选择更多的工具 如上图所示,可以选择自己经常使用的命令,可以输入…

手撕线程池

1.手撕线程池原理图 2.代码实现 // 手撕线程池 public class Main {public static void main(String[] args) {ThreadPool threadPool new ThreadPool(1,1000,TimeUnit.MILLISECONDS,1,(queue, task) -> {queue.putByTime(task,1500,TimeUnit.MILLISECONDS);});for (int i…

LangChain 实战演练:借助 LangChain SQL Agent 与 GPT 实现文档智能分析及交互

LangChain实战:利用LangChain SQL Agent和GPT进行文档分析和交互 我最近接触到一个非常有趣的挑战,涉及到人工智能数字化大量文件的能力,并使用户可以在这些文件上提出复杂的与数据相关的问题,比如: 数据检索问题&…

【qt】基于tcp的消息发送

我们需要实现客户端发消息,服务端接收消息 服务端界面新增接收消息 实现客户端发送和清空 发送数据需要将发送栏的信息转化为QByteArray,然后使用socket的write发送过去 实现服务端的接收 效果演示 20240818_111603 代码展示 server Widget.h #ifndef WIDGET_H …

Java的File类与IO流

目录 1. java.io.File类的使用 1.1 概述 1.2 构造器 1.3 常用方法 1、获取文件和目录基本信息 2、列出目录的下一级 3、File类的重命名功能 4、判断功能的方法 5、创建、删除功能 1.4 练习 2. IO流原理及流的分类 2.1 Java IO原理 2.2 流的分类 2.3 流的API 3. …

如何在 Windows/Mac/在线/iPhone/Android 上将 PDF 转换为 Word

PDF(便携式文档格式)是一种流行的格式,广泛用于在数字电子设备中呈现文档。输出文件小且兼容性强,使 PDF 如此受欢迎。但是,编辑 PDF 文件并非免费。您无需购买 PDF 编辑器,而是可以将 PDF 转换为 Word 进行…

「OC」NSPredicate —— 使用谓词过滤元素

「OC」NSPredicate —— 使用谓词过滤元素 文章目录 「OC」NSPredicate —— 使用谓词过滤元素前言介绍常见用法**比较运算符****逻辑运算符****字符串比较运算符****聚合运算符****用于字典或者类当中****格式说明符(占位符)** 实际运用总结参考文章 前…

05创建型设计模式——原型模式

一、原型模式简介 原型模式(Prototype Pattern)模式是一种对象创建型模式,它采取复制原型对象的方法来创建对象的实例。使用原型模式创建的实例,具有与原型一样的数据。 1)由原型对象自身创建目标对象。换句话说&…

python基础语法 010 类和对象-3 方法

1.3 方法 属性表示是一个类当中的成员或类的特征,而方法是?? 方法:表示类、对象的行为,方法本质上是函数,是一个特殊的函数 属性名称一般为名词,方法名称一般为动词 1.3.1 方法 VS 属性 1、…

24/8/17算法笔记 DDPG算法

深度确定性策略梯度(DDPG)算法是一种用于解决连续动作空间强化学习问题的算法。它结合了确定性策略梯度(DPG)和深度学习技术的优点,通过Actor-Critic框架进行策略和价值函数的近似表示。DDPG算法的关键组成部分包括经验…