正则化三剑客——Dropout、L2、数据增强
正则化三剑客——Dropout、L2、数据增强
📚 《从零到一造大脑:AI架构入门之旅》专栏
专栏定位:面向中学生、大学生和 AI 初学者的科普专栏,用大白话和生活化比喻带你从零理解人工智能
本系列共 42 篇,分为八大模块:
- 📖 模块一【AI 基础概念】(3 篇):AI/ML/DL 关系、学习方式、深度之谜
- 🧠 模块二【神经网络入门】(4 篇):神经元、权重、激活函数、MLP
- 🏗️ 模块三【深度学习核心】(6 篇):损失函数、梯度下降、反向传播、过拟合、Batch/Epoch/LR
- 🎯 模块四【注意力机制】(5 篇):从 Attention 到 Transformer
- 🔬 模块五【NCT 与 CATS-NET 案例】(8 篇):真实架构演进全记录
- 🔄 模块六【架构融合方法】(6 篇):如何设计混合架构
- ⚙️ 模块七【参数调优实战】(6 篇):学习率、正则化、超参数搜索
- 🚀 模块八【调参炼丹术】(7 篇):学习率、Batch Size、正则化、学习率调度、实战演示
本文是模块八第 4 篇,全面讲解三种核心正则化方法。👨💻 作者简介:NeuroConscious Research Team,一群热爱 AI 科普的研究者,专注于神经科学启发的 AI架构设计与可解释性研究。理念:“再复杂的概念,也能用大白话讲清楚”。
💻 项目地址:https://github.com/wyg5208/nct.git
🌐 官网地址:https://neuroconscious.link
📝 作者 CSDN:https://blog.csdn.net/yweng18
📦 NCT PyPI:https://pypi.org/project/neuroconscious-transformer/
⭐ 欢迎 Star⭐、Fork🍴、贡献代码🤝
📌 本文核心比喻:考试防作弊
⏱️ 阅读时间:约 25 分钟
🎯 学习目标:理解三种正则化方法的原理,掌握如何选择和组合使用
📝 文章摘要

正则化是防止模型"死记硬背"的关键技术。就像考试防作弊——不能让学生只背答案,要真正理解知识。本文介绍三种最常用的正则化方法:Dropout(随机关掉一些神经元)、L2 正则化(惩罚大权重)、数据增强(变出更多训练数据)。三者各有特点,常常配合使用,让你的模型既能学到东西,又能举一反三。
🎯 你需要先了解
阅读本文前,建议你:
- ✅ 理解什么是过拟合(参考第 12 篇)
- ✅ 知道神经网络的基本结构
- ✅ 了解训练和推理的区别
如果还没读前文,[点这里返回](12-过拟合与欠拟合 背答案vs没学会_version_B.md)
📖 正文
一、为什么需要正则化?
1.1 考试作弊的类比
想象一个学生备考:
死记硬背(过拟合)
- 把所有练习题的答案背下来
- 平时作业 100 分,考试 30 分
- 只会做见过的题,新题完全不会
真正理解(良好泛化)
- 理解解题思路和方法
- 平时作业 90 分,考试 85 分
- 能举一反三,解决新问题
正则化 = 防作弊措施
- 不让学生只背答案
- 强迫学生理解规律
- 提高真正的能力
1.2 过拟合的本质
模型太"聪明":
- 参数太多,容量太大
- 可以记住每个训练样本
- 不需要学习真正的规律
数据太"少":
- 训练数据不足以覆盖所有情况
- 模型学到的是数据的噪声,不是规律
训练太"久":
- 训练轮数过多
- 模型越来越"熟悉"训练数据
- 开始记忆而不是学习
1.3 正则化的目标
| 过拟合 | 正则化后 |
|---|---|
| 训练准确率 99%,测试准确率 70% | 训练准确率 95%,测试准确率 92% |
| 模型复杂,权重很大 | 模型简单,权重较小 |
| 对训练数据高度敏感 | 对新数据更鲁棒 |
让模型"学得更难"
- 不能轻易记住训练数据
- 必须学习更本质的规律
- 牺牲一些训练准确率,换取更好的泛化

二、Dropout:随机关掉神经元
2.1 核心思想
团队协作比喻:
想象一个团队做项目:
- 如果某个员工太关键,他一请假项目就停摆
- 解决方法:随机让一些人"请假"
- 强迫每个人都能独当一面
- 团队整体更强,不依赖单个人
Dropout 就是这样:
- 训练时随机"关掉"一些神经元
- 强迫其他神经元学会更多
- 测试时所有神经元都在,团队更强
2.2 工作原理
| 阶段 | 行为 |
|---|---|
| 训练时 | 每个神经元有 p 的概率被"关掉"(输出 0) |
| 测试时 | 所有神经元都工作,但输出乘以 (1-p) |
训练时:
- 假设 Dropout 率 p = 0.5
- 每个神经元平均只有一半时间在工作
- 输出的期望值是原来的 0.5 倍
测试时:
- 所有神经元都工作
- 如果不缩放,输出会变成 2 倍
- 所以要乘以 (1-p) = 0.5,保持一致
另一种方法:Inverted Dropout
- 训练时除以 (1-p)
- 测试时不用改
- PyTorch 默认使用这种方式
2.3 代码实现
import torch
import torch.nn as nn
# 在模型中使用 Dropout
class NetWithDropout(nn.Module):
def __init__(self):
super().__init__()
self.fc1 = nn.Linear(784, 256)
self.dropout1 = nn.Dropout(p=0.5) # 50% 概率失活
self.fc2 = nn.Linear(256, 128)
self.dropout2 = nn.Dropout(p=0.3) # 30% 概率失活
self.fc3 = nn.Linear(128, 10)
def forward(self, x):
x = torch.relu(self.fc1(x))
x = self.dropout1(x)
x = torch.relu(self.fc2(x))
x = self.dropout2(x)
x = self.fc3(x)
return x
# 演示 Dropout 的效果
def demo_dropout():
dropout = nn.Dropout(p=0.5)
x = torch.ones(10)
print("原始输入:", x)
print("Dropout 后:", dropout(x))
# 可以看到约一半变成了 0,其他的被放大了 2 倍
demo_dropout()
2.4 Dropout 的位置和参数选择
| 位置 | 建议 |
|---|---|
| 全连接层后 | 常用,效果好 |
| 卷积层后 | 较少用,效果有限 |
| 输出层前 | 不推荐 |
| Dropout 率 | 适用场景 |
|---|---|
| 0.1 - 0.3 | 小模型、需要更多容量 |
| 0.5 | 经典值,大多数场景 |
| 0.5 - 0.8 | 大模型、容易过拟合 |
常见配置:
# 经典配置
nn.Sequential(
nn.Linear(784, 512),
nn.ReLU(),
nn.Dropout(0.5), # 全连接层后
nn.Linear(512, 256),
nn.ReLU(),
nn.Dropout(0.5),
nn.Linear(256, 10)
)
# BERT / Transformer 配置
nn.Sequential(
...
nn.Dropout(0.1), # 注意力后,较小的 dropout
...
)
注意:
- Dropout 率太大可能导致欠拟合
- 从小值开始尝试(0.1-0.3)
- 如果还过拟合,再增大
三、L2 正则化:惩罚大权重
3.1 核心思想
学生考试比喻:
假设考试有两个学生:
- 学生 A:答案简洁,逻辑清晰
- 学生 B:答案冗长,绕来绕去
如果两人得分相同,应该更喜欢简洁的答案。
L2 正则化:
- 给损失函数加一个"惩罚项"
- 权重越大,惩罚越重
- 鼓励模型使用更小的权重
- 结果是更简单、更平滑的模型
3.2 数学原理
原始损失函数:
L = CrossEntropy(y_pred, y_true)
加入 L2 正则化:
L_new = L + λ × Σ(w²)
其中:
λ:正则化系数(控制惩罚强度)Σ(w²):所有权重的平方和
梯度更新:
w_new = w - lr × (∂L/∂w + 2λw)
= w × (1 - 2λlr) - lr × ∂L/∂w
这意味着:
- 每次更新,权重会先"缩小一点"
- 然后才根据梯度调整
- 所以 L2 正则化也叫"权重衰减"
3.3 代码实现
import torch
import torch.nn as nn
import torch.optim as optim
# 方法 1:在优化器中设置 weight_decay
model = nn.Linear(784, 10)
optimizer = optim.Adam(model.parameters(), lr=0.001, weight_decay=0.01)
# 方法 2:手动添加 L2 正则化
def l2_regularization(model, lambda_l2):
"""计算 L2 正则化项"""
l2_loss = 0
for param in model.parameters():
l2_loss += torch.sum(param ** 2)
return lambda_l2 * l2_loss
# 训练循环
for data, target in dataloader:
optimizer.zero_grad()
output = model(data)
# 普通损失
loss = nn.CrossEntropyLoss()(output, target)
# 加上 L2 正则化
loss += l2_regularization(model, lambda_l2=0.01)
loss.backward()
optimizer.step()
3.4 L2 系数的选择
| L2 系数 (weight_decay) | 效果 |
|---|---|
| 0 | 无正则化 |
| 1e-5 ~ 1e-4 | 轻微正则化,小模型常用 |
| 1e-3 ~ 1e-2 | 中等正则化,常用 |
| 1e-1 ~ 1 | 强正则化,可能导致欠拟合 |
Adam 和 L2 的问题:
- 标准的 L2 正则化对 Adam 效果不佳
- 因为 Adam 会自适应调整学习率
- 推荐使用 AdamW(Adam with decoupled Weight decay)
# 使用 AdamW 代替 Adam + weight_decay
optimizer = optim.AdamW(model.parameters(), lr=0.001, weight_decay=0.01)
四、数据增强:变出更多训练数据
4.1 核心思想
学习认字比喻:
教小朋友认"猫":
- 只给他看一张标准的猫的照片
- 他可能只认得这张照片
如果给他看:
- 大猫、小猫、花猫、黑猫
- 躺着的、站着的、跑着的猫
- 他会学会"猫"这个概念,而不是某张照片
数据增强就是:
- 把一张图片变成很多变体
- 增加训练数据的多样性
- 让模型学会"概念"而不是"样子"
4.2 图像增强方法
| 方法 | 描述 | 参数 |
|---|---|---|
| 随机翻转 | 左右/上下翻转 | p=0.5 |
| 随机旋转 | 旋转一定角度 | degrees=±10° |
| 随机裁剪 | 裁剪后放大 | size=224 |
| 颜色抖动 | 改变亮度/对比度 | brightness=0.2 |
| 随机噪声 | 加高斯噪声 | std=0.01 |
| 模糊 | 高斯模糊 | kernel_size=3 |
import torch
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
# 定义图像增强流程
train_transform = transforms.Compose([
transforms.Resize(256),
transforms.RandomCrop(224), # 随机裁剪
transforms.RandomHorizontalFlip(p=0.5), # 随机水平翻转
transforms.RandomRotation(10), # 随机旋转 ±10°
transforms.ColorJitter(
brightness=0.2, # 亮度变化
contrast=0.2, # 对比度变化
saturation=0.2, # 饱和度变化
hue=0.1 # 色调变化
),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406],
std=[0.229, 0.224, 0.225])
])
# 测试时通常不增强
test_transform = transforms.Compose([
transforms.Resize(256),
transforms.CenterCrop(224),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406],
std=[0.229, 0.224, 0.225])
])
# 可视化增强效果
def visualize_augmentation(image_path, transform, num_images=9):
"""可视化数据增强效果"""
image = Image.open(image_path)
fig, axes = plt.subplots(3, 3, figsize=(10, 10))
for i, ax in enumerate(axes.flat):
augmented = transform(image)
# 转换回 PIL 格式显示
img_show = transforms.ToPILImage()(augmented)
ax.imshow(img_show)
ax.axis('off')
ax.set_title(f'增强 #{i+1}')
plt.suptitle('数据增强效果展示')
plt.tight_layout()
plt.savefig('img_40_augmentation_demo.png')
plt.show()
# visualize_augmentation('cat.jpg', train_transform)
4.3 文本增强方法
| 方法 | 描述 | 示例 |
|---|---|---|
| 同义词替换 | 随机替换词 | “猫” → “猫咪” |
| 随机删除 | 删除一些词 | “我很喜欢猫” → “我喜欢猫” |
| 随机交换 | 交换词的位置 | “我很喜欢猫” → “我很猫喜欢” |
| 回译 | 翻译再翻译回来 | 中→英→中 |
| 插入 | 随机插入词 | “我喜欢猫” → “我非常喜欢猫” |
# 文本增强示例(使用 nlpaug 库)
# pip install nlpaug
import nlpaug.augmenter.word as naw
text = "我很喜欢这只可爱的小猫咪"
# 同义词替换
aug_synonym = naw.SynonymAug(lang='zh')
print("同义词替换:", aug_synonym.augment(text))
# 回译(需要翻译 API)
# aug_back_translation = naw.BackTranslationAug(
# from_model_name='Helsinki-NLP/opus-mt-zh-en',
# to_model_name='Helsinki-NLP/opus-mt-en-zh'
# )
# print("回译:", aug_back_translation.augment(text))
4.4 数据增强的注意事项
不要过度增强:
- 图片扭曲太严重,可能变得不认识
- 文本改得太离谱,可能语义全变
考虑任务特点:
- 数字识别:不要上下翻转(6 和 9 会混淆)
- 医学图像:谨慎使用(可能改变诊断特征)
- 文本分类:同义词替换比较安全
测试时不用增强:
- 增强是为了增加训练多样性
- 测试时要评估真实表现
- 使用确定性的预处理(如中心裁剪)
五、三剑客对比

5.1 对比表格
| 特性 | Dropout | L2 正则化 | 数据增强 |
|---|---|---|---|
| 原理 | 随机关掉神经元 | 惩罚大权重 | 增加数据多样性 |
| 实现难度 | 简单 | 非常简单 | 中等 |
| 计算成本 | 低 | 极低 | 中等 |
| 适用场景 | 全连接层 | 通用 | 图像、文本 |
| 训练时影响 | 改变网络结构 | 改变损失函数 | 改变输入数据 |
| 推理时影响 | 无(关闭) | 无 | 无 |
| 典型参数 | p=0.1-0.5 | λ=1e-4~1e-2 | 增强强度 |
5.2 何时用哪个?
图像任务:
首选:数据增强(翻转、裁剪、颜色)
配合:L2 正则化
可选:Dropout(全连接层后)
文本任务:
首选:Dropout
配合:L2 正则化
可选:数据增强(回译、同义词)
表格数据:
首选:L2 正则化
配合:Dropout
数据增强:通常不适用
大模型(如 Transformer):
Dropout:0.1 左右(注意力后)
L2:weight_decay=0.01
数据增强:根据任务选择
5.3 三者配合使用
import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import transforms, datasets
from torch.utils.data import DataLoader
class NetWithAllRegularization(nn.Module):
"""集大成:三种正则化都用"""
def __init__(self):
super().__init__()
self.conv1 = nn.Conv2d(3, 32, 3, padding=1)
self.conv2 = nn.Conv2d(32, 64, 3, padding=1)
self.pool = nn.MaxPool2d(2, 2)
self.fc1 = nn.Linear(64 * 8 * 8, 256)
self.dropout = nn.Dropout(0.5) # Dropout
self.fc2 = nn.Linear(256, 10)
def forward(self, x):
x = self.pool(torch.relu(self.conv1(x)))
x = self.pool(torch.relu(self.conv2(x)))
x = x.view(-1, 64 * 8 * 8)
x = torch.relu(self.fc1(x))
x = self.dropout(x) # Dropout
x = self.fc2(x)
return x
# 数据增强
train_transform = transforms.Compose([
transforms.RandomCrop(32, padding=4),
transforms.RandomHorizontalFlip(),
transforms.ColorJitter(0.2, 0.2, 0.2),
transforms.ToTensor(),
transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))
])
test_transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))
])
# 模型和优化器
model = NetWithAllRegularization()
optimizer = optim.AdamW(model.parameters(), lr=0.001, weight_decay=0.01) # L2
print("✅ 三种正则化都已配置:")
print(" - Dropout: p=0.5")
print(" - L2 正则化: weight_decay=0.01")
print(" - 数据增强: RandomCrop + RandomFlip + ColorJitter")
六、正则化强度选择
6.1 欠拟合 vs 过拟合 vs 刚刚好
| 状态 | 训练准确率 | 测试准确率 | 正则化强度 |
|---|---|---|---|
| 欠拟合 | 70% | 68% | 太强,减弱 |
| 刚好 | 95% | 93% | 合适 |
| 过拟合 | 99% | 80% | 太弱,加强 |
6.2 调整策略
发现过拟合:
- 先加数据增强(如果有图像)
- 再加 L2 正则化(weight_decay=0.01)
- 如果还不够,加 Dropout(p=0.3)
- 逐步调大,直到训练/测试差距缩小
发现欠拟合:
- 减弱正则化强度
- 减小 Dropout 率
- 减小 weight_decay
- 减弱数据增强
- 如果还欠拟合,考虑增加模型容量
监控指标:
# 训练时记录
train_losses = []
test_losses = []
# 绘制学习曲线
plt.plot(train_losses, label='Train')
plt.plot(test_losses, label='Test')
plt.legend()
plt.xlabel('Epoch')
plt.ylabel('Loss')
# 理想状态:两条线接近但不完全重合
⚠️ 常见误区
❌ 误区 1:“正则化越多越好”
真相:
正则化太强会导致欠拟合,模型学不到东西。要在过拟合和欠拟合之间找到平衡。目标是测试集表现最好,不是训练集表现最差。
❌ 误区 2:“Dropout 和 L2 效果一样,用一种就行”
真相:
Dropout 和 L2 的原理不同,效果互补。Dropout 破坏神经元间的共适应,L2 惩罚大权重。通常两者一起用效果更好。
❌ 误区 3:“数据增强只适用于图像”
真相:
文本、音频、视频都可以做数据增强。文本可以回译、同义词替换;音频可以加噪声、变速;视频可以抽帧、裁剪。
❌ 误区 4:“测试时也要用 Dropout”
真相:
Dropout 只在训练时使用!测试时要关闭(model.eval() 会自动关闭 Dropout)。测试时使用 Dropout 会导致结果不稳定。
# 正确做法
model.train() # 训练模式,Dropout 生效
for data, target in train_loader:
output = model(data)
...
model.eval() # 评估模式,Dropout 关闭
with torch.no_grad():
for data, target in test_loader:
output = model(data)
...
💡 一句话总结
正则化三剑客,防止模型死记硬背
Dropout 随机关神经元,L2 惩罚大权重,数据增强变数据。
三者配合使用,让模型学会举一反三。
记忆口诀:
正则化防过拟合,三剑客各有神通。
Dropout 关神经元,随机关掉学更通。
L2 惩罚大权重,模型变得更简单。
数据增强变变变,一张图片变多变。
三者配合效果佳,泛化能力顶呱呱。
🔬 动手实验
实验:对比有无正则化的效果
import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import transforms, datasets
from torch.utils.data import DataLoader
import matplotlib.pyplot as plt
# 构建容易过拟合的小数据集
transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.1307,), (0.3081,))
])
train_data = datasets.MNIST('./data', train=True, download=True,
transform=transform)
test_data = datasets.MNIST('./data', train=False, transform=transform)
# 只用前 1000 个样本训练(容易过拟合)
train_subset = torch.utils.data.Subset(train_data, range(1000))
train_loader = DataLoader(train_subset, batch_size=32, shuffle=True)
test_loader = DataLoader(test_data, batch_size=1000)
# 无正则化模型
class NetNoReg(nn.Module):
def __init__(self):
super().__init__()
self.fc = nn.Sequential(
nn.Flatten(),
nn.Linear(784, 512),
nn.ReLU(),
nn.Linear(512, 256),
nn.ReLU(),
nn.Linear(256, 10)
)
def forward(self, x):
return self.fc(x)
# 有正则化模型
class NetWithReg(nn.Module):
def __init__(self):
super().__init__()
self.fc = nn.Sequential(
nn.Flatten(),
nn.Linear(784, 512),
nn.ReLU(),
nn.Dropout(0.5), # Dropout
nn.Linear(512, 256),
nn.ReLU(),
nn.Dropout(0.5),
nn.Linear(256, 10)
)
def forward(self, x):
return self.fc(x)
def train_model(model, use_l2=False, epochs=50):
"""训练模型"""
if use_l2:
optimizer = optim.Adam(model.parameters(), lr=0.001, weight_decay=0.01)
else:
optimizer = optim.Adam(model.parameters(), lr=0.001)
criterion = nn.CrossEntropyLoss()
history = {'train_acc': [], 'test_acc': []}
for epoch in range(epochs):
# 训练
model.train()
correct = 0
for data, target in train_loader:
optimizer.zero_grad()
output = model(data)
loss = criterion(output, target)
loss.backward()
optimizer.step()
pred = output.argmax(dim=1)
correct += (pred == target).sum().item()
train_acc = correct / len(train_subset)
# 测试
model.eval()
correct = 0
with torch.no_grad():
for data, target in test_loader:
output = model(data)
pred = output.argmax(dim=1)
correct += (pred == target).sum().item()
test_acc = correct / len(test_data)
history['train_acc'].append(train_acc)
history['test_acc'].append(test_acc)
if (epoch + 1) % 10 == 0:
print(f"Epoch {epoch+1}: Train={train_acc:.4f}, Test={test_acc:.4f}")
return history
# 运行实验
print("=== 无正则化 ===")
model_no_reg = NetNoReg()
history_no_reg = train_model(model_no_reg, use_l2=False)
print("\n=== 有正则化 (Dropout + L2) ===")
model_with_reg = NetWithReg()
history_with_reg = train_model(model_with_reg, use_l2=True)
# 可视化
plt.figure(figsize=(12, 5))
plt.subplot(1, 2, 1)
plt.plot(history_no_reg['train_acc'], label='Train (无正则化)')
plt.plot(history_no_reg['test_acc'], label='Test (无正则化)')
plt.xlabel('Epoch')
plt.ylabel('Accuracy')
plt.title('无正则化:明显过拟合')
plt.legend()
plt.ylim(0.8, 1.0)
plt.subplot(1, 2, 2)
plt.plot(history_with_reg['train_acc'], label='Train (有正则化)')
plt.plot(history_with_reg['test_acc'], label='Test (有正则化)')
plt.xlabel('Epoch')
plt.ylabel('Accuracy')
plt.title('有正则化:泛化更好')
plt.legend()
plt.ylim(0.8, 1.0)
plt.tight_layout()
plt.savefig('img_40_regularization_comparison.png')
plt.show()
📚 延伸阅读
- 论文:《Dropout: A Simple Way to Prevent Neural Networks from Overfitting》——Dropout 的原始论文
- 论文:《Decoupled Weight Decay Regularization》——AdamW 的论文,解释为什么 AdamW 比 Adam + L2 更好
- 论文:《mixup: Beyond Empirical Risk Minimization》——一种有趣的数据增强方法
- 博客:Data Augmentation——数据增强综述
✍️ 课后作业
选择题(每题 10 分)
1. Dropout 在训练时和测试时的行为是?
A. 都随机失活神经元
B. 都不随机失活神经元
C. 训练时随机失活,测试时全部激活 ✅
D. 测试时随机失活,训练时全部激活
2. L2 正则化在 PyTorch 中通过哪个参数实现?
A. dropout
B. weight_decay ✅
C. momentum
D. lambda
3. 以下哪种数据增强方法不适合数字识别任务?
A. 随机水平翻转 ✅
B. 随机裁剪
C. 颜色抖动
D. 随机旋转小角度
思考题(20 分)
**实践:在一个分类任务上,分别尝试:
- 无正则化
- 只用 Dropout
- 只用 L2
- Dropout + L2
对比四种方案在训练集和测试集上的表现,分析哪种组合效果最好,为什么?**
📝 下一篇预告
题目:学习率调度——让学习"先快后慢"
我们会学到:
- 为什么需要学习率调度
- 常见的调度策略(Step、Cosine、Warmup)
- 不同调度策略的对比
- 如何选择合适的调度策略
作者:NeuroConscious Research Team
更新时间:2026 年 4 月
版本号:V1.0(图文并茂版)
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)