CIFAR-100数据集Python处理与深度学习实战项目

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:CIFAR-100是由Alex Krizhevsky等人创建的计算机视觉数据集,包含60,000张32×32彩色图像,涵盖100个类别,广泛用于多类图像分类研究。本压缩包“cifar-100-python.zip”专为Python环境设计,包含数据集文件及“read_cifar100.py”解析脚本,支持加载、解码、标签解析与数据预处理。结合TensorFlow、PyTorch等框架,可用于构建卷积神经网络(CNN)模型,完成图像特征提取、分类训练与性能评估,是深度学习图像识别任务的理想实验平台。

CIFAR-100实战全解析:从数据到模型的端到端深度学习之旅

你有没有试过打开一张32×32的小图,盯着它看了半天却还是分不清那是“向日葵”还是“郁金香”?🤯 别担心——这不怪你,连最先进的神经网络在这上面也常常“眼花”。而这就是我们今天要深入挑战的对象: CIFAR-100数据集

这个看似不起眼的小数据集,藏着100个细粒度类别、每类仅600张微型图像,却是检验模型泛化能力的“试金石”。在它的世界里,“狼”和“郊狼”只差一根毛的距离,“苹果”和“梨”可能只是颜色深浅的区别。🎯 要想在这里取得好成绩,光堆参数可不行,必须从 数据加载、预处理、模型设计到训练优化 ,每一步都做到极致。

那么问题来了:
👉 如何正确读取那个神秘的 .tar.gz 文件?
👉 像素值到底是先归一化还是先增强?
👉 为什么你的模型总是在“兰花”和“罂粟花”之间反复横跳?

别急,接下来我们将像拆解一台精密仪器一样,层层揭开CIFAR-100背后的秘密,并手把手带你走完一条完整的深度学习流水线。准备好了吗?Let’s go!🚀


数据加载:别让第一步就卡住你 🚧

我们常说“垃圾进,垃圾出”,但在实际项目中,更多时候是:“pickle进,报错出”。😅

CIFAR-100的数据并不是以常见的JPG或PNG格式存储的,而是被打包成了一个叫 cifar-100-python.tar.gz 的压缩包,里面是一堆用Python pickle 序列化的二进制文件。如果你直接双击打开……抱歉,它不会给你任何友好提示,只会返回一堆乱码字节流。

所以第一步,我们要做的不是写模型,而是学会“解封”这些数据。

解压与定位关键文件

首先,确保你已经把原始压缩包下载下来了(通常来自 https://www.cs.toronto.edu/~kriz/cifar.html )。然后执行:

tar -xzf cifar-100-python.tar.gz

你会看到目录结构如下:

cifar-100-python/
├── train
├── test
└── meta

其中:
- train :包含50,000张训练图像及其标签;
- test :10,000张测试图像;
- meta :元信息,比如每个类别的名字。

这些文件本质上是一个Python字典对象通过 pickle.dump() 写入磁盘的结果。因此,我们需要用 pickle.load() 来反序列化它。

import pickle

def load_cifar_batch(file_path):
    with open(file_path, 'rb') as f:
        data_dict = pickle.load(f, encoding='bytes')
    return data_dict

# 加载训练集
train_data = load_cifar_batch('cifar-100-python/train')

⚠️ 注意这里的 encoding='bytes' 是关键!因为这些文件最初是由Python 2生成的,键名都是字节字符串(如 b'data' ),如果不指定编码,在Python 3环境下会抛出 UnicodeDecodeError

来看看这个字典里都有啥:

键(bytes) 含义
b’data’ 形状为 (50000, 3072) 的NumPy数组
b’fine_labels’ 长度为50000的列表,表示100个具体类别
b’coarse_labels’ 20个粗粒度超类标签
b’filenames’ 图像文件名(调试用)

是不是有点懵?别慌,让我们一步步来。

把扁平像素还原成彩色图像

data 字段中的每一行代表一张图片,总共3072个数值。它是怎么排列的呢?

答案是:按通道优先顺序展平!

即:

[R1, R2, ..., R1024, G1, G2, ..., G1024, B1, B2, ..., B1024]

所以我们需要将其重塑为 (3, 32, 32) ,再转置为 (32, 32, 3) 才能被正确显示。

import numpy as np

def reshape_images(flat_images):
    N = flat_images.shape[0]
    # Reshape: (N, 3072) -> (N, 3, 32, 32)
    images = flat_images.reshape(N, 3, 32, 32)
    # Transpose to NHWC: (N, 32, 32, 3)
    images = images.transpose(0, 2, 3, 1)
    return images.astype(np.float32)

X_train = reshape_images(train_data[b'data'])

现在你可以试着可视化第一张图看看效果:

import matplotlib.pyplot as plt

plt.imshow(X_train[0].astype(np.uint8))
plt.title("Reconstructed Image")
plt.axis('off')
plt.show()

如果画面偏红或者发绿,八成是你忘了 transpose 或者通道顺序搞错了。记住一句话: OpenCV/TensorFlow 爱 HWC,PyTorch 偏 NCHW 。🧠


数据预处理:让模型看得更清楚 👓

你以为加载完数据就能直接喂给模型了吗?Too young too simple 😅

原始像素值范围是 [0, 255] ,这是典型的 uint8 格式。但现代神经网络喜欢的是浮点数输入,尤其是当使用ReLU这类激活函数时,过大的输入很容易导致梯度爆炸。

所以,我们必须进行 归一化(Normalization)

方法一:简单粗暴缩放到 [0,1]

最简单的做法就是除以255:

X_train_scaled = X_train / 255.0

这样所有像素值都被压缩到了 [0,1] 区间内,符合大多数激活函数的理想输入分布。

但这还不够智能——它没有考虑数据本身的统计特性。

方法二:Z-score标准化(推荐!)

更好的方式是使用 Z-score 标准化:

$$
x’ = \frac{x - \mu}{\sigma}
$$

对于CIFAR-100,官方提供的均值和标准差如下:

通道 均值 μ 标准差 σ
Red 0.4914 0.2470
Green 0.4822 0.2435
Blue 0.4465 0.2616

注意:这里的均值和标准差是基于训练集计算得出的,单位已经是 [0,1] 范围内的浮点数。

mean = np.array([0.4914, 0.4822, 0.4465])
std = np.array([0.2470, 0.2435, 0.2616])

X_train_norm = (X_train_scaled - mean) / std

✅ 关键原则: 测试集必须使用训练集的统计量进行标准化

# ✅ 正确:用训练集的μ和σ去处理测试集
X_test_norm = (X_test / 255.0 - mean) / std

# ❌ 错误:用自己的均值标准差
test_mean = X_test.mean(axis=(0,1,2)) / 255.0
X_test_wrong = (X_test / 255.0 - test_mean) / ...

否则会造成 信息泄露(data leakage) ,导致评估结果虚高,误导判断。

我们可以用Mermaid流程图来表达正确的数据流:

flowchart LR
    TrainData --> ComputeStats[计算训练集 μ, σ]
    ComputeStats --> NormalizeTrain[标准化训练集]
    ComputeStats --> NormalizeTest[使用相同参数标准化测试集]
    NormalizeTrain --> ModelTraining
    NormalizeTest --> ModelEvaluation

看,这才是工业级的做法 💪


双层标签体系:不只是100个类别那么简单 🧩

CIFAR-100的独特之处在于它提供了两套标签系统:

  • Fine Labels :100个细粒度类别,如 “apple”, “boy”, “bee”
  • Coarse Labels :20个粗粒度超类,如 “fruits and vegetables”, “people”, “insects”

这种层次化结构给了我们很大的灵活性。例如,可以先在一个大类上做预训练,然后再微调到具体的子类任务,有点像人类先学会“认识动物”,再去分辨“狗 vs 狼”。

我们可以通过 meta 文件获取语义名称:

meta = load_cifar_batch('cifar-100-python/meta')

fine_names = [name.decode() for name in meta[b'fine_label_names']]
coarse_names = [name.decode() for name in meta[b'coarse_label_names']]

# 构建映射表
label_to_name = {i: name for i, name in enumerate(fine_names)}
name_to_label = {name: i for i, name in label_to_name.items()}

这样以后就可以打印出预测结果的真实类别名,而不是冷冰冰的数字了。


数据增强:小数据集的秘密武器 🔥

CIFAR-100最大的痛点是什么?—— 太小了!

每类只有600张图,去掉验证集后更是雪上加霜。这时候, 数据增强(Data Augmentation) 就成了提升泛化能力的关键手段。

在线增强 vs 离线生成?

有两种思路:
1. 离线生成 :提前把所有变形图像保存下来 → 占空间,不够灵活;
2. 在线增强 :每次训练时动态生成 → 实时性强,节省存储。

显然,在GPU算力充足的今天,我们都选第2种。

使用 torchvision.transforms 快速构建增强流水线

import torchvision.transforms as T

transform_train = T.Compose([
    # 随机填充并裁剪:模拟局部平移不变性
    T.RandomCrop(32, padding=4),
    # 水平翻转:适用于对称物体(飞机、汽车)
    T.RandomHorizontalFlip(p=0.5),
    # 颜色抖动:增强光照鲁棒性
    T.ColorJitter(brightness=0.4, contrast=0.4, saturation=0.4, hue=0.1),
    # 转为Tensor并标准化
    T.ToTensor(),
    T.Normalize(mean, std)
])
参数小贴士 📝
  • RandomCrop(32, padding=4) :先把图像填充到40×40,再随机裁剪回32×32,相当于做了轻微的位置扰动。
  • ColorJitter(...) :控制亮度、对比度、饱和度和色相的变化幅度。数值越大越激进,但也可能导致失真。
  • Normalize(...) :一定要放在最后!因为前面的操作期望输入是 [0,1] 的Tensor。

如果是TensorFlow用户,也可以用 tf.image 实现类似功能:

@tf.function
def augment_image(image, label):
    image = tf.image.resize_with_pad(image, 40, 40)
    image = tf.image.random_crop(image, size=[32, 32, 3])
    image = tf.image.random_flip_left_right(image)
    image = tf.image.random_brightness(image, max_delta=0.2)
    image = tf.clip_by_value(image, 0., 1.)
    return image, label

两种框架都支持图模式编译,可以在GPU上高效执行,避免成为训练瓶颈。


模型构建:什么样的CNN适合CIFAR-100?🧠

面对32×32这么小的图像,很多人第一反应是:“随便搭个VGG就行了”。但实际上,盲目堆叠层数反而会导致性能下降。

因为感受野太大,早期卷积层可能会“一口吞掉”整个目标;而且深层网络容易出现梯度弥散问题。

那怎么办?答案是: 轻量+残差

从零搭建一个BasicCNN

import torch.nn as nn

class BasicCNN(nn.Module):
    def __init__(self, num_classes=100):
        super().__init__()
        self.features = nn.Sequential(
            nn.Conv2d(3, 32, kernel_size=3, padding=1),
            nn.BatchNorm2d(32),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(2),

            nn.Conv2d(32, 64, kernel_size=3, padding=1),
            nn.BatchNorm2d(64),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(2),

            nn.Conv2d(64, 128, kernel_size=3, padding=1),
            nn.BatchNorm2d(128),
            nn.ReLU(inplace=True),
            nn.AdaptiveAvgPool2d((1, 1))  # 自适应全局池化
        )
        self.classifier = nn.Sequential(
            nn.Flatten(),
            nn.Linear(128, 512),
            nn.ReLU(),
            nn.Dropout(0.5),
            nn.Linear(512, num_classes)
        )

    def forward(self, x):
        x = self.features(x)
        x = self.classifier(x)
        return x

这个结构有几个小心机:
- 使用 BatchNorm2d 加速收敛;
- 最后一层不用FC前先做 AdaptiveAvgPool2d ,减少参数量;
- Dropout放在全连接层中间防过拟合。

不过说实话,这样的浅层网络最多也就跑到70%左右的准确率。要想突破80%,还得靠ResNet家族出场!

ResNet才是王者?Yes and No

ResNet-20 在CIFAR-100上能达到约76.8%的Top-1准确率,WideResNet-28-10甚至可以冲到82.5%以上。它们的成功秘诀在于 残差连接(skip connection) ,解决了深层网络的退化问题。

但你也得付出代价——参数量暴涨到3600万!而在一个只有5万训练样本的数据集上跑这么大的模型,简直就是“杀鸡用牛刀”🙃

所以我的建议是:
✅ 如果你是初学者,用 ResNet-20 或 PreAct-ResNet-18
✅ 如果你想追求SOTA,试试 WideResNet 或 PyramidNet + ShakeDrop
✅ 如果你要部署上线,考虑 MobileNetV2 或 TinyNet 这类轻量化结构。


训练优化:别让错误的策略毁了你的模型 🛠️

模型搭好了,接下来就是训练。但你有没有发现,有时候明明结构差不多,别人的模型就能收敛得又快又好?

差别往往不在架构本身,而在 训练策略的设计

损失函数:交叉熵是默认选择

对于多分类任务,毫无疑问应该用 CrossEntropyLoss

criterion = nn.CrossEntropyLoss()

它内部自动对 logits 做 LogSoftmax,再计算负对数似然,数值稳定性更好。

✅ 提示:不要手动加 Softmax 层!否则损失函数会重复归一化,导致训练不稳定。

如果某些类别特别难学(比如“bee”总是被判成“ladybug”),还可以引入 类别权重

class_weights = torch.ones(100)
class_weights[bee_idx] *= 2.0  # 给蜜蜂更高的惩罚
criterion = nn.CrossEntropyLoss(weight=class_weights)

优化器怎么选?SGD > Adam?!

等等,你说SGD比Adam还强?不是说Adam自适应学习率很香吗?

确实,在大数据集(如ImageNet)上Adam表现优异,但在中小规模数据集(如CIFAR)上,大量实验证明: 带动量的SGD泛化能力更强

optimizer = torch.optim.SGD(
    model.parameters(),
    lr=0.1,
    momentum=0.9,
    weight_decay=5e-4
)

为什么?
- SGD更新方向更稳定,不容易陷入尖锐极小值;
- 动量项帮助穿越平坦区域;
- weight_decay 相当于L2正则,进一步抑制过拟合。

Adam虽然收敛快,但容易找到“尖”的最小值,泛化差一些。

学习率调度:余弦退火了解一下?

固定学习率太呆板,阶梯衰减又太生硬。近年来流行的 Cosine Annealing 更加平滑:

scheduler = torch.optim.lr_scheduler.CosineAnnealingLR(
    optimizer,
    T_max=200,      # 总epoch数
    eta_min=1e-6     # 最小学习率
)

它会按照余弦曲线缓慢降低学习率,有助于模型在后期精细调整权重,跳出局部最优。

相比之下,StepLR就显得有些粗暴了:

step_scheduler = torch.optim.lr_scheduler.StepLR(
    optimizer,
    step_size=60,
    gamma=0.1
)

每60个epoch直接砍掉90%,容易错过最佳点。

我一般的做法是:前期用 StepLR 快速下降,后期切到 Cosine 收敛微调。


验证与调优:如何不让模型过拟合?🛡️

CIFAR-100最容易犯的错误就是: 训练准确率飙到95%,测试才60% 。这说明模型已经完全记住了训练集的噪声模式。

怎么办?三招搞定:

1. 划分验证集监控性能

虽然官方有固定的测试集,但我们自己调参时还是要留一部分出来作为验证集:

from sklearn.model_selection import train_test_split

X_tr, X_val, y_tr, y_val = train_test_split(
    X_train_norm, y_train,
    test_size=0.1,
    stratify=y_train,
    random_state=42
)

每轮训练结束后跑一次验证:

model.eval()
val_loss = 0
correct = 0
with torch.no_grad():
    for x, y in val_loader:
        x, y = x.to(device), y.to(device)
        output = model(x)
        val_loss += criterion(output, y).item()
        pred = output.argmax(dim=1)
        correct += pred.eq(y).sum().item()

val_acc = correct / len(val_loader.dataset)

记录下每个epoch的 train_loss , val_loss , val_acc ,画个曲线图就知道有没有过拟合了。

2. 早停机制(Early Stopping)

一旦验证损失连续几个epoch不再下降,立刻停止训练:

class EarlyStopping:
    def __init__(self, patience=10, min_delta=0):
        self.patience = patience
        self.min_delta = min_delta
        self.counter = 0
        self.best_loss = float('inf')
        self.early_stop = False

    def __call__(self, val_loss):
        if val_loss < self.best_loss - self.min_delta:
            self.best_loss = val_loss
            self.counter = 0
        else:
            self.counter += 1
            if self.counter >= self.patience:
                self.early_stop = True

再也不用手动守着训练跑了,美滋滋 😎

3. 正则化组合拳:Dropout + Weight Decay

  • 卷积层后加 Dropout2d(0.2~0.3)
  • 全连接层前加 Dropout(0.5)
  • 优化器设置 weight_decay=5e-4

但注意: 不要在 BatchNorm 后面接 Dropout ,否则会破坏其统计估计。


超参数搜索:别再手动调参了!🤖

学习率设多少?batch size 用64还是128?层数该不该加?

这些问题如果靠猜,效率太低。我们应该借助自动化工具。

推荐神器:Optuna

import optuna

def objective(trial):
    lr = trial.suggest_float('lr', 1e-5, 1e-1, log=True)
    batch_size = trial.suggest_categorical('batch_size', [64, 128, 256])
    n_layers = trial.suggest_int('n_layers', 2, 5)
    dropout = trial.suggest_float('dropout', 0.1, 0.5)

    model = build_model(n_layers, dropout)
    optimizer = torch.optim.SGD(model.parameters(), lr=lr, momentum=0.9)
    train_loader = DataLoader(train_set, batch_size=batch_size)

    for epoch in range(50):  # 快速训练评估
        train_one_epoch(model, train_loader, optimizer)
    _, val_acc = validate(model, val_loader)

    return val_acc

study = optuna.create_study(direction='maximize')
study.optimize(objective, n_trials=50)

print("Best params:", study.best_trial.params)

Optuna采用贝叶斯优化策略,能聪明地避开无效区域,通常几十次试验就能找到不错的配置。


模型评估:不只是看准确率那么简单 📊

训练完了,终于可以松口气了吗?No no no,真正的洞察才刚刚开始。

宏平均F1分数:更公平的评价指标

由于CIFAR-100类别均衡,我们更关心 每个类的表现是否一致 。这时候就不能只看总体准确率,而要用 宏平均F1

from sklearn.metrics import f1_score

f1_macro = f1_score(y_true, y_pred, average='macro')

它对每个类平等对待,哪怕某个类别只有几十张图,也不会被忽略。

混淆矩阵:找出模型的“盲区”

from sklearn.metrics import confusion_matrix
import seaborn as sns

cm = confusion_matrix(y_true, y_pred)
cm_norm = cm.astype('float') / cm.sum(axis=1)[:, None]

plt.figure(figsize=(14, 12))
sns.heatmap(cm_norm[:30,:30], annot=False, cmap="Blues",
            xticklabels=fine_names[:30],
            yticklabels=fine_names[:30])
plt.title("Normalized Confusion Matrix (Top 30 Classes)")
plt.show()

你会发现很多高频错误对:

真实类别 预测类别 可能原因
orchid poppy 花瓣颜色相似
bee ladybug 小型红色昆虫外观雷同
aquarium_fish flatfish “fish”语义干扰
wardrobe cabinet 家具功能重叠
boy man 年龄过渡连续

这些分析可以直接指导下一步改进:
- 对易混淆类加强数据增强;
- 引入注意力机制聚焦判别区域;
- 设计层次化损失函数,利用粗标签辅助训练。


端到端Pipeline封装:一键启动训练 🔧

最后一步,把所有模块整合成一个可复用的脚本:

# train_cifar100_pipeline.py
import argparse

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("--data-path", type=str, default="./cifar-100-python")
    parser.add_argument("--epochs", type=int, default=200)
    parser.add_argument("--batch-size", type=int, default=128)
    parser.add_argument("--lr", type=float, default=0.1)
    parser.add_argument("--augment", action="store_true")
    args = parser.parse_args()

    # 加载 & 预处理
    X_train, y_train, X_test, y_test = load_and_preprocess(args.data_path)

    # 数据增强
    if args.augment:
        train_dataset = AugmentedDataset(X_train, y_train, is_training=True)
    else:
        train_dataset = TensorDataset(torch.tensor(X_train), torch.tensor(y_train))

    train_loader = DataLoader(train_dataset, batch_size=args.batch_size, shuffle=True)

    # 模型 & 优化器
    model = ResNet20(num_classes=100).to(device)
    optimizer = torch.optim.SGD(model.parameters(), lr=args.lr, momentum=0.9, weight_decay=5e-4)
    scheduler = torch.optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max=args.epochs)

    # 训练循环
    for epoch in range(args.epochs):
        train_one_epoch(model, train_loader, optimizer, device)
        val_acc = validate(model, val_loader, device)
        scheduler.step()

        if epoch % 10 == 0:
            print(f"Epoch {epoch}, Val Acc: {val_acc:.4f}")

    # 评估报告
    evaluate_and_save_report(model, X_test, y_test, "logs/report.txt")

if __name__ == "__main__":
    main()

运行命令:

python train_cifar100_pipeline.py \
  --data-path ./data/cifar-100-python \
  --epochs 200 \
  --batch-size 256 \
  --lr 0.1 \
  --augment

从此告别重复劳动,真正实现“一次编写,处处运行” ✨


总结与思考:通往更高精度的道路 🛤️

回顾整个流程,我们走过了一条完整的深度学习路径:

🔧 数据加载 → 🧹 预处理 → 🎨 增强 → 🧱 模型构建 → 🚀 训练优化 → 📈 评估分析 → 📦 流水线封装

每一步看似简单,实则暗藏玄机。正是这些细节决定了最终性能的上限。

如果你想进一步提升准确率,不妨尝试以下方向:

  • 更深的网络 + 残差连接 :如ResNet-56、WRN-40-2;
  • 更强的数据增强 :CutOut、MixUp、AutoAugment;
  • 知识蒸馏 :用大模型指导小模型训练;
  • 半监督学习 :结合未标注数据扩展训练集;
  • Transformer架构 :ViT-Tiny、T2T-ViT等轻量视觉Transformer也开始在CIFAR上崭露头角。

但请记住: 没有银弹,只有权衡

追求极致准确率的同时,也要考虑推理速度、内存占用、训练成本等因素。真正的工程能力,是在约束条件下做出最优决策的艺术。

所以,下次当你面对一个新的图像分类任务时,不妨问问自己:

“我是要造一辆赛车,还是一辆家用车?” 🚗

根据需求选择合适的方案,才是高手的思维方式 💡


🎉 好了,这篇长达七千多字的实战指南就到这里啦!希望你能从中获得启发,顺利拿下自己的CIFAR-100项目。如果觉得有用,别忘了点赞收藏,也欢迎留言交流你的训练经验~我们一起进步!🌟

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:CIFAR-100是由Alex Krizhevsky等人创建的计算机视觉数据集,包含60,000张32×32彩色图像,涵盖100个类别,广泛用于多类图像分类研究。本压缩包“cifar-100-python.zip”专为Python环境设计,包含数据集文件及“read_cifar100.py”解析脚本,支持加载、解码、标签解析与数据预处理。结合TensorFlow、PyTorch等框架,可用于构建卷积神经网络(CNN)模型,完成图像特征提取、分类训练与性能评估,是深度学习图像识别任务的理想实验平台。


本文还有配套的精品资源,点击获取
menu-r.4af5f7ec.gif

内容概要:本文介绍了一个基于Matlab的综合能源系统优化调度仿真资源,重点实现了含光热电站、有机朗肯循环(ORC)和电含光热电站、有机有机朗肯循环、P2G的综合能源优化调度(Matlab代码实现)转气(P2G)技术的冷、热、电多能互补系统的优化调度模型。该模型充分考虑多种能源形式的协同转换利用,通过Matlab代码构建系统架构、设定约束条件并求解优化目标,旨在提升综合能源系统的运行效率经济性,同时兼顾灵活性供需不确定性下的储能优化配置问题。文中还提到了相关仿真技术支持,如YALMIP工具包的应用,适用于复杂能源系统的建模求解。; 适合人群:具备一定Matlab编程基础和能源系统背景知识的科研人员、研究生及工程技术人员,尤其适合从事综合能源系统、可再生能源利用、电力系统优化等方向的研究者。; 使用场景及目标:①研究含光热、ORC和P2G的多能系统协调调度机制;②开展考虑不确定性的储能优化配置经济调度仿真;③学习Matlab在能源系统优化中的建模求解方法,复现高水平论文(如EI期刊)中的算法案例。; 阅读建议:建议读者结合文档提供的网盘资源,下载完整代码和案例文件,按照目录顺序逐步学习,重点关注模型构建逻辑、约束设置求解器调用方式,并通过修改参数进行仿真实验,加深对综合能源系统优化调度的理解。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值