☰
交叉熵损失函数全解析:从信息论原理到工程实践
2026/10/10 3:25:17 网站建设 项目流程

做分类任务这些年,我见过太多人栽在损失函数上。模型结构抄得飞起,数据增强玩得花哨,结果一训练就发现loss曲线诡异:要么不收敛,要么收敛到比随机还差的位置,要么训练集都快过拟合了验证集还在原地打转。大多数人第一反应是调学习率、改batch size,很少有人意识到,问题可能出在你根本没用对损失函数,或者说,你压根没搞懂手里的Cross Entropy Loss到底在算什么。

先说清楚这篇文章是干嘛的。这是"损失函数大汇总"的第四篇,聚焦交叉熵损失函数(Cross Entropy Loss),我会把信息论视角下的公式推导、二分类和多分类的表格差异、NumPy手写实现、PyTorch和TensorFlow的工程写法、以及在YOLO、GAN、蒸馏这类场景里的实际应用全部串起来。适合刚入门深度学习、想彻底搞懂分类损失函数原理的初学者,也适合已经会用nn.CrossEntropyLoss()但想知道它内部到底发生了什么、遇到异常loss时知道去哪排查的进阶选手。看完这篇文章,你再看到[交叉熵、BCE、logits、label_smoothing]这些词,脑子里的画面应该是清晰的数学过程,而不只是一行API调用。

1. 交叉熵到底在“损失”什么:从分类任务本质说起

1.1 为什么分类任务不能用MSE

很多人第一次接触损失函数是从回归任务开始的,MSE(均方误差)顺手就搬到了分类上,结果要么训练极慢,要么直接不收敛。原因不在于"数值大小不合适",而在于这两类任务的数学本质完全不同。

回归任务假设输出是连续值,误差服从高斯分布,MSE恰好是这种假设下的最大似然估计。分类任务输出的是离散的类别标签,模型的最后一层本质上是在估计"输入属于每个类别的概率分布"。既然目标是概率分布,就应该拿衡量分布之间差异的度量,也就是交叉熵,而不是拿衡量两个实数点距离的MSE。

更具体地说,如果把softmax之后的输出当做概率向量,MSE对这时候接近0或1的输出梯度会趋近于0,这就是教科书上常说的"饱和区梯度消失"。交叉熵配合softmax生成的梯度是预测值 - 标签值的形式,当预测错得离谱时梯度幅度也大,预测接近正确时梯度自然变小,这个性质决定了它在分类任务上收敛效率远高于MSE。还有一个经常被忽略的观点:MSE隐式地假设了输出噪声是各向同性的高斯噪声,这在分类任务的0/1标签空间里根本不成立;二分类标签服从伯努利分布,多分类服从类别分布,对应的"自然"损失函数就应该是负对数似然,也就是交叉熵。

1.2 从信息量到熵:不搞懂信息论也能理解交叉熵

要真正理解交叉熵,信息论里三个概念是绕不开的:信息量、熵、KL散度。好消息是你不需要系统学一遍信息论,只需要抓住一条线索。

信息量定义为一个事件发生所带来的"惊讶程度":

[ I(x) = -\log p(x) ]

p(x)是事件发生的概率。概率越小,信息量越大;概率为1的事件信息量为0,因为完全确定的事不带来任何新信息。这个公式的直接推论是:如果用均值编码来表达一个随机变量的平均信息量,就得到熵(Entropy):

[ H(P) = -\sum_{i} p_i \log p_i ]

熵的本质是"按照真实分布P来编码,所需的最短平均码长"。现在换一种情况:真实分布是P,但我手头只有关于这个系统的估计分布Q,我按照Q来编码,那么实际消耗的平均码长就是交叉熵:

[ H(P, Q) = -\sum_{i} p_i \log q_i ]

你发现没有,交叉熵不是凭空造出来的概念,它就是"用Q的视角去度量P的世界"所产生的期望编码代价。当Q完全等于P时,交叉熵等于熵;当Q偏离P时,交叉熵会比熵大。那多出来的部分是什么?就是KL散度。这三个概念的关系可以用一句话概括:交叉熵 = 熵 + KL散度,即:

[ H(P, Q) = H(P) + KL(P | Q) ]

在训练模型时,P是真实标签分布(固定不变),Q是模型预测分布(可优化)。于是熵H(P)是常数,最小化交叉熵就等价于最小化KL散度,也就是让模型预测分布不断逼近真实分布。这就是交叉熵作为分类损失函数最底层的逻辑。

2. 公式推导全流程:从KL散度到BCE再到多分类CE

2.1 KL散度:交叉熵的亲爹,长得丑但有用

KL散度的定义式是:

[ KL(P | Q) = \sum_{i} p_i \log \frac{p_i}{q_i} = \sum_{i} p_i \log p_i - \sum_{i} p_i \log q_i ]

右边第一项就是-H(P),第二项是H(P, Q)。所以:

[ KL(P | Q) = H(P, Q) - H(P) ]

KL散度不是对称的,KL(P||Q) ≠ KL(Q||P),所以它严格来说不是"距离",而是一个"不相似度度量"。它还有个性质是非负的,等于0当且仅当P和Q一致。这些性质直接支撑了"最小化KL散度来拟合分布"这套训练逻辑。实际做深度学习时没人直接算KL散度做损失,因为真实分布P(尤其是标签的one-hot向量)经常有0值,p_i log(p_i/q_i)在p_i=0时会出NaN。大家直接用交叉熵代替KL,因为最小化它们的解是一样的,而且交叉熵数值上更干净。

2.2 二分类场景:Binary Cross Entropy的最大似然推导

二分类是理解交叉熵最好的切入点,因为它的公式只有一个求和项,看起来非常亲切。假设标签y ∈ {0, 1},模型输出ŷ = σ(z),表示预测样本属于类别1的概率。按照伯努利分布的写法:

[ P(y|x) = \hat{y}^y (1-\hat{y})^{(1-y)} ]

对N个独立样本取对数似然:

[ \log L = \sum_{n=1}^{N} \left[ y_n \log \hat{y}_n + (1 - y_n) \log(1 - \hat{y}_n) \right] ]

取负号并除以N,得到标准的Binary Cross Entropy(BCE):

[ L_{BCE} = -\frac{1}{N} \sum_{n=1}^{N} \left[ y_n \log \hat{y}_n + (1 - y_n) \log(1 - \hat{y}_n) \right] ]

这个推导过程解释了三个细节:为什么要除以N,因为样本量不同时累积损失没有可比性,平均后能让学习率等超参数在不同batch size下相对稳定;为什么是y log ŷ + (1-y) log(1-ŷ)这样的对称结构,因为二分类的类别0和类别1地位对等;为什么ŷ要经过sigmoid而不是直接用原始logits,因为logits是实数域的值,而概率必须限制在(0,1)区间。

2.3 多分类CE:softmax配合one-hot的化简

多分类交叉熵的教科书公式写出来是:

[ L_{CE} = -\frac{1}{N} \sum_{n=1}^{N} \sum_{c=1}^{C} y_{n,c} \log \hat{y}_{n,c} ]

其中y_{n,c}是one-hot标签矩阵,ŷ_{n,c}是softmax输出。很多初学者看到这个双重求和就头大,但一旦理解one-hot的特性,式子可以瞬间简化:对每个样本,只有真实类别那一维y_{n,c}=1,其余全是0,所以内层求和实际上只需要取出真实类别对应的那个预测概率。整个公式化简为:

[ L_{CE} = -\frac{1}{N} \sum_{n=1}^{N} \log \hat{y}_{n, c_n} ]

c_n是第n个样本的真实类别索引。这也就是为什么多分类交叉熵又叫负对数似然(NLL)。如果你用了softmax输出,那ŷ = softmax(z),代入进去就是:

[ L = -\frac{1}{N} \sum_{n=1}^{N} \left( z_{n, c_n} - \log \sum_{j=1}^{C} e^{z_{n,j}} \right) ]

这个形式叫logits版本的交叉熵,也是PyTorch里F.cross_entropy真正在算的东西。它把softmax的除法和log运算合并在一起做了数值优化,所以你们在代码里直接喂logits就行,不要在训练代码里先调softmax再算nll_loss,既多此一举还引入数值误差。

3. 代码实现:从NumPy手写再到一行API

3.1 手写实现与数值稳定技巧

先动手写一个纯NumPy版本,彻底搞清楚内部流程。核心代码如下:

import numpy as np def softmax(logits): # 减去最大值,防止 exp 溢出 z = logits - np.max(logits, axis=-1, keepdims=True) exp_z = np.exp(z) return exp_z / np.sum(exp_z, axis=-1, keepdims=True) def cross_entropy(logits, labels): # logits: (N, C) # labels: (N,) 类别索引,或 (N, C) one-hot probs = softmax(logits) N = logits.shape[0] if labels.ndim == 1: # 从预测概率中取出真实类别的概率 log_probs = np.log(probs[np.arange(N), labels] + 1e-12) else: # one-hot 形式,只有真实类别那一项非零 log_probs = np.sum(np.log(probs + 1e-12) * labels, axis=-1) return -np.mean(log_probs) def cross_entropy_grad(logits, labels): probs = softmax(logits) grad = probs.copy() if labels.ndim == 1: grad[np.arange(len(labels)), labels] -= 1 else: grad -= labels return grad / len(labels)

这里有两个细节值得解释。第一是softmax里的减去最大值操作:如果不减,当logits里出现大数值(比如100),exp(100)在float32下已经溢出成inf,整个loss变成NaN。减去最大值后,最大的指数项变成exp(0)=1,其余项都在安全范围内,数学上完全等价。第二是np.log(probs)里加的1e-12:probs理论上是正数,但浮点运算可能给出0,log(0)就是负无穷,加一个小epsilon是防御性写法。

梯度函数值得多看一眼:∂L/∂z_i = softmax(z)_i - y_i。这个结果漂亮到让人怀疑是不是巧合——分类损失函数加softmax的梯度,居然就是"预测概率减去真实标签"。正因为有了这个简洁形式,反向传播才不用显式算softmax的雅可比矩阵,训练速度大幅提升。你以后自己写自定义损失函数时,只要保持梯度的形式是这种残差形式,数值上一般不会出问题。

3.2 PyTorch里的交叉熵:一行API背后的三重封装

PyTorch的F.cross_entropy是实际工作中最常用到的写法,但很多人并不知道它内部做了什么。它其实是三合一套装:log_softmax + nll_loss。也就是说:

import torch import torch.nn.functional as F logits = torch.randn(8, 10) # 模拟 batch=8, 10类 target = torch.randint(0, 10, (8,)) # 真实类别索引 # 推荐用法:直接喂 logits loss = F.cross_entropy(logits, target) # 手动等价写法 loss_manual = F.nll_loss(F.log_softmax(logits, dim=-1), target) # 带标签平滑,缓解模型过度自信 loss_smooth = F.cross_entropy(logits, target, label_smoothing=0.1) # 带类别权重,处理训练集类别不均衡 weights = torch.tensor([1.0, 1.0, 2.0, ...]) # 每个类别一个权重 loss_weighted = F.cross_entropy(logits, target, weight=weights) # 忽略某个类别(常用于语义分割的 ignore_index) loss_ignore = F.cross_entropy(logits, target, ignore_index=255)

需要注意的最大坑是:input参数必须是logits,不是softmax后的概率。一旦你手贱先做了F.softmax(logits, dim=-1)再传进去,数值上还算能出结果,但梯度路径已经变了,训练效果会大打折扣。PyTorch官方也专门在文档里提示不要这样做。另外,label_smoothing参数在PyTorch 1.10之后原生支持,它会把one-hot标签变成[0.9, 0.0333, 0.0333, ...]这种平滑分布,防止模型对训练标签过于自信,提升泛化性。

3.3 TensorFlow/Keras的对应写法:全都藏在from_logits里

TensorFlow的写法在表面上和PyTorch差异很大,但底层逻辑一致。关键是from_logits这个参数,它提醒你:如果你的预测值是模型最后一层线性输出(裸logits),设为True;如果你已经过了一层softmax,设为False。强烈建议始终用from_logits=True,因为数值稳定性和梯度路径更优。

import tensorflow as tf # 多分类,标签是整数索引 loss_fn = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True) loss = loss_fn(y_true, y_pred) # y_true: (N,), y_pred: (N, C) logits # 多分类,标签是one-hot loss_fn_oh = tf.keras.losses.CategoricalCrossentropy(from_logits=True) loss_oh = loss_fn_oh(y_true_oh, y_pred) # y_true_oh: (N, C) # 二分类,标签0/1 bce_fn = tf.keras.losses.BinaryCrossentropy(from_logits=True) loss_bce = bce_fn(y_binary, y_logits)

SparseCategoricalCrossentropy和CategoricalCrossentropy的区别只在标签格式:前者接收整数索引,后者接收one-hot向量。别在数据准备阶段多此一举把整数标签又转成one-hot,直接用Sparse版本能省不少内存,ES索引也不会报错。

3.4 多标签任务:这不是多分类,别用CategoricalCrossentropy

多标签分类(一个样本同时属于多个类别)是最容易误用交叉熵的场景。比如一张图片同时有"猫"和"狗"两个标签,这时候每个类别是独立的二分类问题,应该用sigmoid + BCE,而不是softmax + CE。softmax强制所有类别概率之和为1,天然假设每个样本只能属于一个类别;sigmoid对每个类别独立输出0~1的概率,允许同时多个类别为高概率。

PyTorch里对应的API是F.binary_cross_entropy_with_logits,它内置了sigmoid,同样直接吃logits:

# logits: (N, C),targets: (N, C) 多标签0/1矩阵 loss_ml = F.binary_cross_entropy_with_logits(logits, targets)

这个函数有pos_weight参数,专门处理正样本极其罕见的多标签场景:pos_weight > 1会让模型更重视正样本的召回率。我做过一个多标签项目,正样本占比只有1%,用了pos_weight=10之后F1直接从0.2涨到0.65,效果立竿见影。

4. 真实项目里的交叉熵:从YOLO到GAN再到蒸馏

4.1 分类网络训练时交叉熵的调参经验

用交叉熵训练ResNet、MobileNet这类分类网络时,有几个经验你很难在文档里查到。第一个是初始学习率敏感度:因为交叉熵梯度本身就是残差形式,训练初期预测接近均匀分布(1/C),梯度不会太大,所以初始学习率可以比MSE场景大胆一些。但softmax输出接近0/1后梯度趋近于0,如果学习率太大,后期loss会像锯齿一样来回跳,建议配合CosineAnnealing或CosineWarmup。第二个是过拟合的早期信号:训练集CE一直降、验证集CE不降只升的时候,往往不是模型容量问题,而是模型开始过度自信。这时候盲目加dropout不如先加label_smoothing,因为label_smoothing直接限制置信度上限,效果更可控。第三个是和MixUp/CutMix的配合:这两种增强产生的标签是平滑的软标签,必须用交叉熵而不是硬标签版NLL才能正确反映软标签的误差。很多复现代码在这里写错,导致MixUp之后精度反而下降。

4.2 YOLO损失函数里的交叉熵:分类分支居然是BCE

用户问YOLO系列损失函数时,最容易被忽略的一点是:YOLOv5和YOLOv8的分类分支用的都是BCE,而不是多分类CE。原因在于目标检测的标签天然是多标签的——一个预测框可能同时包含"人"和"自行车"两个类别(骑自行车的人这种场景很常见),用softmax会强制类别互斥,反而造成误检。YOLOv8把每个类别当成独立的二分类问题,输出维度仍是(N, C),但激活函数是sigmoid,损失函数是逐类别的BCE。

具体到YOLO损失函数结构,通常是三部分相加:

  • 分类分支:BCE,衡量每个类别预测概率和真实标签(0/1)的差异
  • 目标框分支:CIoU或SIoU,衡量预测框和真实框的位置尺寸误差
  • 置信度分支:BCE,衡量该位置是否真的有目标的概率

这三部分的相对权重是超参数,YOLOv5默认cls: 0.5, box: 0.05, obj: 1.0这种量级。如果你自己复现YOLO,一定别把分类分支换成CategoricalCrossentropy,否则在某些遮挡场景下mAP会明显下降。另外YOLOv5源码里还给每个预测层设计了obj权重随尺度变化,小目标层的置信度损失加权更高,这些细节本质上是类别不平衡的变体处理。

4.3 GAN里玩转BCE:同一公式,两个视角

生成对抗网络的标准损失函数就是BCE,但它用在了两个方向完全不同的网络里。判别器D的目标是区分真实样本和生成样本,它的损失是标准的BCE:

[ L_D = -\mathbb{E}{x \sim p{data}}[\log D(x)] - \mathbb{E}_{z \sim p_z}[\log(1 - D(G(z)))] ]

生成器G的目标是骗过判别器,它要最小化"生成样本被判别为真"的负对数概率。在非饱和版GAN里,G的损失是:

[ L_G = -\mathbb{E}_{z \sim p_z}[\log D(G(z))] ]

这看起来就是BCE翻转了标签:把生成样本的目标标签从0改成1。理解了BCE的公式,你就知道D(G(z))要尽量接近1,log(D(G(z)))才接近0,损失才小。GAN训练不稳定的一个重要原因就是BCE的梯度在sigmoid饱和区消失——当判别器太强时,D(G(z))趋近0,log(1 - D(G(z)))的梯度也趋近0,生成器收不到有效梯度。这就催生了WGAN、LSGAN等一系列替代损失函数,本质上都是在改这个饱和区特性。

4.4 知识蒸馏里的交叉熵:软标签的CE细节

知识蒸馏是另一个交叉熵大显身手的场景。学生模型除了要和真实标签算CE,还要和教师模型的软输出算CE(或KL散度),蒸馏目标一般是两部分的加权和:

[ L = \alpha \cdot CE(y_{true}, p_{student}) + (1-\alpha) \cdot CE(p_{teacher}^\tau, p_{student}^\tau) ]

教师模型的输出经过了温度系数τ的软化:softmax(z / τ),τ越大分布越平滑,携带的"类别间相似度"信息越多。蒸馏用CE而不是MSE,是因为软标签本质上还是概率分布,CE能更好地匹配分布的形状。我在实际蒸馏项目里发现,温度τ通常在3~8之间效果最好,太低软标签太硬丢失信息,太高软标签太平滑学生学不到细节。

5. 常见问题与避坑实录:交叉熵实战排查清单

这部分内容全部来自真实项目里的踩坑记录,按问题严重程度排个序。

5.1 问题速查表

现象常见原因排查建议
loss直接变NaN学习率太大、logits溢出、标签中有非法值先降学习率一个量级;检查输入是否含NaN;检查标签是否超出类别数
loss一直是负数或远小于预期混入了其他损失项、某层归一化失效打印每个loss分量;检查BatchNorm是否在eval模式下统计异常
预测准确率还行但loss比别人高用了softmax概率再算CE,数值精度丢失改回logits版本,观察是否立即下降
训练loss降了但测试很高模型过度自信、数据分布偏移加label_smoothing;检查验证集清洗
二分类任务调用多分类CE标签处理混乱确认任务性质,换BCE并用sigmoid
类别严重不均衡时模型全预测多数类训练集中负样本占绝对多数用weight参数或Focal Loss
使用混合精度训练后loss轻微变化fp16舍入误差开启loss scaler;对梯度clip

5.2 三个容易被忽略的细节

第一个细节与类权重和batch size的关系有关。F.cross_entropy(weight=...)是在每个batch内先算逐样本loss再乘权重后平均,注意不是除以N,而是除以weight.sum()或有效样本数,具体取决于实现。如果你的weight设置得极端(比如1:100),实际损失数值会偏大,需要相应调低学习率。

第二个细节是label_smoothing与类别权重同时使用时的交互。标度平滑后的"伪标签"不再是0/1,weight参数仍会生效,但平滑后每个类别的有效贡献被重新分配,如果你的权重本身已经强烈不均匀,平滑会削弱权重的效果。我的建议是先用weight处理严重不均衡,再用小的平滑系数(0.05~0.1)提升泛化,不要两个都拉满。

第三个细节非常实在:不要迷信训练集CE降得越低越好。交叉熵没有上界,如果模型把训练样本的置信度推到1,CE会趋近0,但这往往是过拟合的信号。理想情况下,训练集的CE应该在一个不高不低的区间——略高于验证集,差距越小越好。我习惯在训练时同时打印准确率和平均置信度,如果平均置信度超过0.95且验证集CE在回升,多半是过度自信了,立刻检查是否该上正则化。

5.3 从loss曲线上读懂训练状态

交叉熵的loss曲线能告诉你很多信息。训练前几百步,loss从log(C)附近(均匀分布的交叉熵)下降到log(C) - 某个值,这是正常开局。如果loss一开始就低于log(2)(二分类时约0.693),说明模型已经开始学到信号了。如果loss曲线在某个点后长期平坦,别急着降学习率,先看准确率是不是也在平台期——如果准确率还在涨而loss不动,可能是模型在修正边界样本的置信度,这个阶段交叉熵对"已是正确分类但置信度不高"的样本仍有持续优化作用,曲线平坦不一定代表没在学习。

6. 交叉熵的进阶变体:从Label Smoothing到Focal Loss

6.1 Label Smoothing:给标签掺点水分,模型更抗揍

Label Smoothing在公式层面就是把one-hot标签从y_c=1, y_j=0改成y_c=1-ε, y_j=ε/(C-1)。它对应到损失函数就是:

[ L_{LS} = (1 - \varepsilon) \cdot CE(y_{onehot}, p) + \varepsilon \cdot CE(u, p) ]

其中u是均匀分布。这个改动的作用是给模型设一个置信度上限,不让它把训练样本学到100%确信。早期很多人把它当玄学,但它在ImageNet这种大规模数据集上确实稳定涨点,尤其配合较大的模型和较长的训练周期。PyTorch传入label_smoothing=0.1即可,注意它和weight参数要分开用,别混在一起调参。

6.2 Focal Loss:交叉熵解决不了的正负样本失衡

Focal Loss是交叉熵的直接改造,当年为密集目标检测提出(RetinaNet)。它长这样:

[ L_{focal} = -\alpha (1 - p_t)^\gamma \log p_t ]

其中p_t是真实类别对应的预测概率,γ称为聚焦参数,α是类别权重。(1-p_t)^\gamma这个调制系数让模型"专注于难分样本":当p_t接近1(易分样本)时,调制系数接近0,损失被压低;当p_t很小(难分样本)时,调制系数接近1,损失几乎不衰减。这正好治交叉熵的"毛病"——交叉熵对易分样本也给了不小的梯度,而这些易分样本在目标检测里占了绝大多数,模型学了半天全在学"已经会的",难分样本被淹没。你在自己的不平衡分类任务里也可以直接用这个思路,γ=2、α=0.25是常用起点。

6.3 交叉熵和KL散度在实践中的取舍

蒸馏场景、对比学习场景、生成模型里,KL散度有时会直接作为损失函数出现,而交叉熵则出现在分类头。两者理论上只差一个H(P)常数,实际使用上有细微差异:KL散度在teacher和student都是软标签分布时更自然(蒸馏),因为它直接度量分布间的散度;交叉熵在真实标签是0/1时更自然,因为log(0)的问题可以被one-hot结构规避。如果你需要在代码里算KL散度,PyTorch里有F.kl_div,注意它默认输入是log-probabilities,输出方向和直觉相反,容易搞混,传参时F.kl_div(log_y_pred, y_true, reduction='batchmean')才对。

6.4 自定义损失的稳健写法

如果你要在自己的模型里把交叉熵和别的损失(比如对比损失、正则项)组合,建议这样写:

class CombinedLoss(torch.nn.Module): def __init__(self, ce_weight=1.0, contrastive_weight=0.1): super().__init__() self.ce_weight = ce_weight self.contrastive_weight = contrastive_weight def forward(self, logits, targets, embeddings, labels): ce = F.cross_entropy(logits, targets) # 自定义对比损失,注意数值稳定性 cos_sim = torch.mm(F.normalize(embeddings), F.normalize(embeddings).t()) contrastive = ... total = self.ce_weight * ce + self.contrastive_weight * contrastive return total

组合损失项目里最容易翻车的点:一是多个loss数值尺度不一致,CE在log量级,对比损失可能在0~1量级,直接相加后需要显式调权;二是梯度尺度不一致导致一个loss主导,建议打印每个loss分量和它们的梯度范数来定权;三是在reduction选择上要统一,别一个用mean一个用sum,量纲直接乱了。

最后再多说一句经验之谈。我做了这么多年分类任务,从普通CNN到Transformer再到检测分割模型,交叉熵始终是箱底最稳的那个损失函数,但真正用好它的人不多。很多人只知道调API,不知道它随softmax而来的梯度形式为什么是残差式的,也就不知道为什么它会和这个优化器、那个学习率调度器配合良好,更不知道什么时候该换Focal Loss、什么时候该做Label Smoothing、什么时候该上多标签BCE。把这些底层逻辑吃透了,你对"模型训练"这件事的判断力会直接上一个台阶——以后看到奇怪的loss曲线,或者换了一个新任务需要选损失函数时,心里会有一条清晰的决策线,而不是靠瞎试。这就是我想在这篇文章里真正传给你的东西。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询