零基础学机器学习:损失函数详解!从公式推导到代码实现,小白轻松掌握核心要点!
一、损失函数的核心分类
根据机器学习任务类型,损失函数可分为三大类:回归损失函数(预测连续值)、分类损失函数(预测离散类别)、其他特殊损失函数(适用于排序、生成等任务)。
二、回归损失函数(Regression Loss)
1. 均方误差(Mean Squared Error, MSE)
数学公式
- 单个样本的损失(平方误差,SE): L S E ( y ^ i , y i ) = ( y ^ i − y i ) 2 L_{SE}(\hat{y}_i, y_i) = (\hat{y}_i - y_i)^2 LSE(y^i,yi)=(y^i−yi)2
- 全样本的损失(均方误差,MSE): L M S E ( y ^ , y ) = 1 n ∑ i = 1 n ( y ^ i − y i ) 2 L_{MSE}(\hat{y}, y) = \frac{1}{n} \sum_{i=1}^n (\hat{y}_i - y_i)^2 LMSE(y^,y)=n1∑i=1n(y^i−yi)2
代码实现
import numpy as np
import tensorflow as tf
from tensorflow.keras.losses import MeanSquaredError
def mse_loss(y_true, y_pred):
n = len(y_true)
return np.sum((y_pred - y_true) ** 2) / n
y_true = tf.constant([[1.2], [2.5], [3.1], [4.7], [5.3],
[6.8], [7.2], [8.5], [9.1], [10.4]], dtype=tf.float32)
y_pred = tf.constant([[1.0], [2.3], [3.5], [4.9], [5.1],
[6.6], [7.5], [8.3], [9.4], [10.2]], dtype=tf.float32)
tf_mse_manual = tf.reduce_mean(tf.square(y_pred - y_true))
tf_mse = MeanSquaredError()(y_true, y_pred)
print("NumPy MSE:", mse_loss(y_true.numpy(), y_pred.numpy()))
print("TensorFlow manual MSE:", tf_mse_manual.numpy())
print("TensorFlow built-in MSE:", tf_mse.numpy())

2. 平均绝对误差(Mean Absolute Error, MAE)
数学公式
- 单个样本的损失(绝对误差,AE): L A E ( y ^ i , y i ) = ∣ y ^ i − y i ∣ L_{AE}(\hat{y}_i, y_i) = |\hat{y}_i - y_i| LAE(y^i,yi)=∣y^i−yi∣
- 全样本的损失(平均绝对误差,MAE): L M A E ( y ^ , y ) = 1 n ∑ i = 1 n ∣ y ^ i − y i ∣ L_{MAE}(\hat{y}, y) = \frac{1}{n} \sum_{i=1}^n |\hat{y}_i - y_i| LMAE(y^,y)=n1∑i=1n∣y^i−yi∣
代码实现
import numpy as np
import tensorflow as tf
from tensorflow.keras.losses import MeanAbsoluteError
def mae_loss(y_true, y_pred):
n = len(y_true)
return np.sum(np.abs(y_pred - y_true)) / n
y_true = tf.constant([[1.2], [2.5], [3.1], [4.7], [5.3],
[6.8], [7.2], [8.5], [9.1], [10.4]], dtype=tf.float32)
y_pred = tf.constant([[1.0], [2.3], [3.5], [4.9], [5.1],
[6.6], [7.5], [8.3], [9.4], [10.2]], dtype=tf.float32)
tf_mae_manual = tf.reduce_mean(tf.abs(y_pred - y_true))
tf_mae = MeanAbsoluteError()(y_true, y_pred)
print("NumPy MAE:", mae_loss(y_true.numpy(), y_pred.numpy()))
print("TensorFlow manual MAE:", tf_mae_manual.numpy())
print("TensorFlow built-in MAE:", tf_mae.numpy())

3. Huber损失(Huber Loss)
数学公式
L H u b e r ( y ^ i , y i ) = { 1 2 ( y ^ i − y i ) 2 if ∣ y ^ i − y i ∣ ≤ δ δ ( ∣ y ^ i − y i ∣ − 1 2 δ ) if ∣ y ^ i − y i ∣ > δ L_{Huber}(\hat{y}_i, y_i) = \begin{cases} \frac{1}{2}(\hat{y}_i - y_i)^2 & \text{if } |\hat{y}_i - y_i| \leq \delta \\ \delta(|\hat{y}_i - y_i| - \frac{1}{2}\delta) & \text{if } |\hat{y}_i - y_i| > \delta \end{cases} LHuber(y^i,yi)={21(y^i−yi)2δ(∣y^i−yi∣−21δ)if ∣y^i−yi∣≤δif ∣y^i−yi∣>δ
全样本损失: L H u b e r ( y ^ , y ) = 1 n ∑ i = 1 n L H u b e r ( y ^ i , y i ) L_{Huber}(\hat{y}, y) = \frac{1}{n} \sum_{i=1}^n L_{Huber}(\hat{y}_i, y_i) LHuber(y^,y)=n1∑i=1nLHuber(y^i,yi)
代码实现
import tensorflow as tf
def huber_loss(y_true, y_pred, delta=1.0):
error = y_pred - y_true
abs_error = tf.abs(error)
huber_term = tf.where(abs_error <= delta,
0.5 * tf.square(error),
delta * (abs_error - 0.5 * delta))
return tf.reduce_mean(huber_term)
y_true = tf.constant([[1.2], [2.5], [3.1], [4.7], [20.0],
[6.8], [7.2], [8.5], [9.1], [10.4]], dtype=tf.float32)
y_pred = tf.constant([[1.0], [2.3], [3.5], [4.9], [5.1],
[6.6], [7.5], [8.3], [9.4], [10.2]], dtype=tf.float32)
huber = huber_loss(y_true, y_pred, delta=2.0)
mse = tf.reduce_mean(tf.square(y_pred - y_true))
print("Huber loss (delta=2.0):", huber.numpy())
print("MSE loss:", mse.numpy())
三、分类损失函数(Classification Loss)
1. 二元交叉熵(Binary Cross-Entropy, BCE)
数学公式
- 单个样本的损失: L B C E ( p ^ i , y i ) = − [ y i ⋅ log ( p ^ i ) + ( 1 − y i ) ⋅ log ( 1 − p ^ i ) ] L_{BCE}(\hat{p}_i, y_i) = -[y_i \cdot \log(\hat{p}_i) + (1 - y_i) \cdot \log(1 - \hat{p}_i)] LBCE(p^i,yi)=−[yi⋅log(p^i)+(1−yi)⋅log(1−p^i)]
- 全样本的损失: L B C E ( p ^ , y ) = − 1 n ∑ i = 1 n [ y i ⋅ log ( p ^ i ) + ( 1 − y i ) ⋅ log ( 1 − p ^ i ) ] L_{BCE}(\hat{p}, y) = -\frac{1}{n} \sum_{i=1}^n [y_i \cdot \log(\hat{p}_i) + (1 - y_i) \cdot \log(1 - \hat{p}_i)] LBCE(p^,y)=−n1∑i=1n[yi⋅log(p^i)+(1−yi)⋅log(1−p^i)]
代码实现
import tensorflow as tf
from tensorflow.keras.losses import BinaryCrossentropy
y_true = tf.constant([[1], [0], [1], [0], [1], [0], [1], [0], [1], [0]], dtype=tf.float32)
y_pred_logits = tf.constant([[2.3], [-1.2], [3.1], [-2.5], [1.8],
[-0.9], [4.2], [-3.7], [2.9], [-1.5]], dtype=tf.float32)
bce_with_logits = BinaryCrossentropy(from_logits=True)(y_true, y_pred_logits)
y_pred_prob = tf.sigmoid(y_pred_logits)
bce_with_prob = BinaryCrossentropy(from_logits=False)(y_true, y_pred_prob)
print("BCE (with logits):", bce_with_logits.numpy())
print("BCE (with probabilities):", bce_with_prob.numpy())
2. Categorical交叉熵(Categorical Cross-Entropy, CCE)
数学公式
- 单个样本的损失: L C C E ( p ^ i , y i ) = − ∑ c = 1 C y i , c ⋅ log ( p ^ i , c ) L_{CCE}(\hat{p}_i, y_i) = -\sum_{c=1}^C y_{i,c} \cdot \log(\hat{p}_{i,c}) LCCE(p^i,yi)=−∑c=1Cyi,c⋅log(p^i,c)
- 全样本的损失: L C C E ( p ^ , y ) = − 1 n ∑ i = 1 n ∑ c = 1 C y i , c ⋅ log ( p ^ i , c ) L_{CCE}(\hat{p}, y) = -\frac{1}{n} \sum_{i=1}^n \sum_{c=1}^C y_{i,c} \cdot \log(\hat{p}_{i,c}) LCCE(p^,y)=−n1∑i=1n∑c=1Cyi,c⋅log(p^i,c)
代码实现
import tensorflow as tf
from tensorflow.keras.losses import CategoricalCrossentropy
y_true = tf.constant([[1,0,0], [0,1,0], [0,0,1], [1,0,0], [0,1,0],
[0,0,1], [1,0,0], [0,1,0], [0,0,1], [1,0,0]], dtype=tf.float32)
y_pred_logits = tf.constant([[3.2, 1.5, 0.8], [2.1, 4.3, 1.2], [0.5, 1.8, 5.1],
[4.7, 0.9, 2.3], [1.8, 3.9, 0.7], [2.2, 1.5, 4.8],
[3.5, 2.1, 1.0], [0.9, 5.2, 1.5], [1.2, 2.3, 3.8],
[4.1, 1.3, 0.6]], dtype=tf.float32)
cce_with_logits = CategoricalCrossentropy(from_logits=True)(y_true, y_pred_logits)
y_pred_prob = tf.nn.softmax(y_pred_logits)
cce_with_prob = CategoricalCrossentropy(from_logits=False)(y_true, y_pred_prob)
print("CCE (with logits):", cce_with_logits.numpy())
print("CCE (with probabilities):", cce_with_prob.numpy())
3. Sparse Categorical交叉熵(Sparse CCE)
数学公式
与CCE相同,仅真实标签为类别索引: y i ∈ { 0 , 1 , . . . , C − 1 } y_i \in \{0,1,...,C-1\} yi∈{0,1,...,C−1}
代码实现
import tensorflow as tf
from tensorflow.keras.losses import SparseCategoricalCrossentropy
y_true = tf.constant([0, 1, 2, 0, 1, 2, 0, 1, 2, 0], dtype=tf.int32)
y_pred_logits = tf.constant([[3.2, 1.5, 0.8], [2.1, 4.3, 1.2], [0.5, 1.8, 5.1],
[4.7, 0.9, 2.3], [1.8, 3.9, 0.7], [2.2, 1.5, 4.8],
[3.5, 2.1, 1.0], [0.9, 5.2, 1.5], [1.2, 2.3, 3.8],
[4.1, 1.3, 0.6]], dtype=tf.float32)
sparse_cce = SparseCategoricalCrossentropy(from_logits=True)(y_true, y_pred_logits)
print("Sparse CCE:", sparse_cce.numpy())
4. 铰链损失(Hinge Loss)
数学公式
L H i n g e ( y i , y ^ i ) = max ( 0 , 1 − y i ⋅ y ^ i ) L_{Hinge}(y_i, \hat{y}_i) = \max(0, 1 - y_i \cdot \hat{y}_i) LHinge(yi,y^i)=max(0,1−yi⋅y^i),其中 y i ∈ { − 1 , 1 } y_i \in \{-1, 1\} yi∈{−1,1}为真实标签, y ^ i \hat{y}_i y^i为模型未归一化的输出
代码实现
import tensorflow as tf
from tensorflow.keras.losses import Hinge
y_true = tf.constant([[1], [-1], [1], [-1], [1]], dtype=tf.float32)
y_pred = tf.constant([[0.8], [-0.9], [1.2], [-0.7], [0.3]], dtype=tf.float32)
hinge_loss = Hinge()(y_true, y_pred)
print("Hinge loss:", hinge_loss.numpy())
四、损失函数的选择原则
- 回归任务优先考虑MSE(无异常值)或MAE(有异常值),Huber损失为折中方案
- 二分类任务使用二元交叉熵(BCE)
- 多分类任务:
- 标签为独热编码 → Categorical交叉熵
- 标签为类别索引 → Sparse Categorical交叉熵
- 支持向量机等间隔最大化模型 → 铰链损失
选择时需结合数据特性(是否有异常值)、任务类型(分类/回归)和模型输出形式综合判断。
另外我整理了损失函数相关资料,感兴趣的dd!
更多推荐


所有评论(0)