Courses
您训练的每一个机器学习模型,本质上都在求解一个优化问题——而您实际要优化的,就是所谓的目标函数。
简单来说,它是一个衡量“解有多好”的数学函数。它接收一组输入并输出一个分数。目标始终是找到能使该分数最大化或最小化的取值。从线性规划到深度学习,目标函数都是核心。一旦您理解了它的工作方式,就会在各处看到它的影子。
本文将解释什么是目标函数、它与损失函数和成本函数有何不同,以及它们在机器学习与优化中的用法。
想系统学习至 2026 年仍不过时的深度学习?欢迎报名我们的 Deep Learning in Python 课程,打造您的 PyTorch 项目集。
什么是目标函数?
目标函数是用于评估某个解好坏的数学函数。
您向它输入一组值——如模型参数、决策变量——它返回一个数。这个数反映了当前解的表现。数值越高(或越低),解就越好(或越差)。
既然聊到这里,不妨顺带谈谈一般意义上的优化。
优化是寻找能让该数值朝正确方向变化的输入的过程。如果是最小化,您就要找尽可能小的值;如果是最大化,则要找尽可能大的值。无论哪种情况,目标函数都是衡量标准。
通俗地说,把它当作一个打分系统。每个候选解都有一个分数,您的任务是找到得分最高的那个。
目标函数 vs 损失函数 vs 成本函数
这三个术语经常被互换使用——但它们并不完全相同。
最宽泛的是目标函数。凡是您要最大化或最小化的函数,都可称为目标函数。它未必涉及误差或预测——它只是定义了在您的问题中“更好”的含义。
而损失函数用于衡量单个训练样本上的误差——即模型预测与真实值的偏差。例如,单个数据点的均方误差就是一种损失函数。
而成本函数是在整个数据集上汇总损失,通常取平均。因此,训练时实际要最小化的是成本函数——它汇总了模型在所有样本上的表现,而非单个样本。
在实践中,多数机器学习框架与论文会宽泛地使用这些术语。您会看到在应称“成本”的地方用了“损失”,以及用“目标”来指代这三者。
当您阅读论文时,这些区分才更重要。语境往往能告诉您作者实际指的是哪一个。
更直观的比较请参见下表:

目标/损失/成本函数对比表
优化中的目标函数
每个优化问题都有目标和限制条件。
目标函数定义目标——也就是您要最大化或最小化的内容。约束定义限制——解必须遵守的边界。两者共同构成了问题的框架。
以一个简单的资源分配为例。
假设您经营一家生产两种产品的工厂,希望最大化利润。目标函数将总利润表示为两种产品产量的函数。约束则体现限制条件——可用原材料、设备工时、产线人力等。目标函数告诉您要优化什么,约束告诉您手里拥有什么。
线性规划是最常见的适用场景之一。它用于在线性约束下优化线性目标函数。应用广泛,涵盖物流、排产、供应链到金融。其数学基础成熟,求解器可以处理包含成千上万个变量的问题。
需要注意的是,目标函数并不会改变约束的存在——它只是告诉求解器要追求什么。如果您更换了目标函数,即使约束不变,也会得到完全不同的解。
机器学习中的目标函数
在机器学习中,目标函数定义了您的模型到底在学什么。
每次训练模型,您都在运行一种优化算法(如梯度下降、Adam、RMSProp),它会调整模型参数,以最小化或最大化目标函数。模型并不了解您的业务问题。它只知道目标函数给出的分数,并在每次更新中尝试提升这个分数。
这意味着目标函数的选择将决定最终结果。建议多做尝试,看看哪一种最适合您的场景。
均方误差(回归)
均方误差(MSE)是回归问题的默认目标函数。它衡量模型预测与真实目标值之间的平均平方差。

MSE 公式
对误差求平方使所有误差都为正,并对大的误差施加比小误差更重的惩罚。比如预测偏差为 10 的样本对总和的贡献是 100,而非 10。这使得 MSE 对异常值比较敏感,在嘈杂的真实世界数据中需要留意。
import numpy as np
y_true = np.array([3.0, 5.0, 2.5, 7.0])
y_pred = np.array([2.8, 5.2, 2.0, 6.5])
mse = np.mean((y_true - y_pred) ** 2)
print(f"MSE: {mse:.4f}")

MSE 输出
交叉熵损失(分类)
交叉熵损失是分类问题的标准目标函数。它衡量模型预测的概率分布与真实类别分布之间的差异。

交叉熵损失函数
如果模型给正确类别分配了高概率,损失就低;如果模型很自信但判断错误,损失就高,并给予惩罚。这会驱使模型既要预测正确类别,也要提高置信度。
import numpy as np
# True labels (one-hot encoded)
y_true = np.array([1, 0, 0])
# Model's predicted probabilities
y_pred = np.array([0.7, 0.2, 0.1])
cross_entropy = -np.sum(y_true * np.log(y_pred))
print(f"Cross-Entropy Loss: {cross_entropy:.4f}")

交叉熵输出
对数似然
对数似然常见于概率与统计模型中。目标是最大化在给定模型参数下观测数据出现的概率。

对数似然公式
之所以使用似然的对数而不是似然本身,是因为它能把概率的乘积变成求和,更易计算与优化。
在实践中,多数框架会最小化负对数似然(NLL),而不是最大化对数似然。两者等价——只是变号以便用梯度下降来优化。
import numpy as np
from scipy.stats import norm
# Observed data
data = np.array([1.2, 2.3, 1.8, 2.1, 1.9])
# Assumed model parameters
mu, sigma = 2.0, 0.5
# Compute negative log-likelihood
nll = -np.sum(norm.logpdf(data, loc=mu, scale=sigma))
print(f"Negative Log-Likelihood: {nll:.4f}")

对数似然输出
训练的本质就是优化。每次前向传播计算目标函数值;每次反向传播计算梯度;每次参数更新都让模型朝着更好的分数方向移动。
凸与非凸目标函数
目标函数并不都是一样的。它们的形状决定了优化难度,以及您能否信任最终的解。
线性目标函数
线性目标函数给出输入与输出的线性关系。当您将任一输入按固定幅度改变时,输出也按固定幅度变化。
线性函数用于线性规划,其中目标与约束均为线性。这是最容易优化的一类目标函数,求解器即便在大规模问题上也能可靠地找到全局最优。
非线性目标函数
非线性目标函数的输入与输出关系更复杂。大多数现实问题——几乎所有机器学习模型——都属于这一类。
MSE 是非线性的,交叉熵是非线性的,神经网络的损失曲面也是非线性的。复杂性提升让这些函数能刻画数据中的复杂关系,但也让优化更困难。
凸函数与非凸函数
这正是有意思的地方。
凸函数形如“碗状”。连接曲线上任意两点的线段都会位于曲线之上或与之重合。这保证了任何局部最小点也是全局最小点——也就是说,优化器一旦找到一个“底”,它就是真正的底。
非凸函数形状更不规则——可能有多个谷底、高原和鞍点。优化器可能陷入局部最小值,即看似到底但并非全局最优的谷底。深度神经网络的损失曲面高度非凸,这就是为什么训练它们需要精心调节学习率、优化器与初始化。
凸问题可以精确求解,非凸问题通常只能近似求解。解的质量取决于您的优化策略。
对于偏视觉的读者,下面是线性、非线性、凸与非凸目标函数的对比:

目标函数类型对比
目标函数如何被优化
有了目标函数,接下来就需要找方法最小化或最大化它。这就是优化算法的用武之地。
最常见的方法是梯度下降。思想是对目标函数关于模型参数求梯度,然后沿着能降低函数值的方向迈出一小步,如此反复,直到值不再改进。
梯度就是目标函数的导数。
它告诉您当前位置的斜率以及“上坡”的方向。要最小化函数,就沿相反方向移动;要最大化,就顺着它移动。
这个过程是迭代的,也就是说,您通过一系列小更新逐步接近最优。每一步的大小由学习率控制。学习率过大会越过最优点,过小则训练变慢。
在实践中,多数机器学习框架采用比基本版本更快、更稳定的梯度下降变体:
- 随机梯度下降(SGD)每步仅用一个随机样本计算梯度,而不是用全量数据
- 小批量梯度下降每步使用一个小批量样本——介于 SGD 与全量之间
- Adam为每个参数自适应学习率,使得调参更宽容
为了使用基于梯度的方法,目标函数必须可导,或至少大部分可导。没有导数就没有梯度,优化器也就无从跟随。这一点务必牢记。
目标函数示例
我们用一个简单的线性回归问题来具体说明。
假设您要基于房屋面积预测房价。手头有一批带真实价格的房屋数据,您希望拟合一条直线,使预测误差最小。您的目标函数是均方误差(MSE),其公式前文已给出。
输入是模型参数——直线的斜率与截距。输出是一个数——所有预测的平均平方误差。在这里,越低越好。
以下是一个可能的 Python 实现:
import numpy as np
np.random.seed(42)
# Generate some fake housing data
square_footage = np.random.uniform(500, 3000, 100)
true_price = 150 * square_footage + 50000 + np.random.normal(0, 15000, 100)
def predict(x, slope, intercept):
return slope * x + intercept
def mse(y_true, y_pred):
return np.mean((y_true - y_pred) ** 2)
# Try two different parameter sets
slope_a, intercept_a = 150, 50000 # good fit
slope_b, intercept_b = 80, 100000 # bad fit
pred_a = predict(square_footage, slope_a, intercept_a)
pred_b = predict(square_footage, slope_b, intercept_b)
print(f"MSE (good fit): {mse(true_price, pred_a):,.2f}")
print(f"MSE (poor fit): {mse(true_price, pred_b):,.2f}")

MSE 优劣拟合对比
第一组参数得到的 MSE 更低,说明拟合效果更好。这正是优化器据以决定前进方向的依据。
对于偏视觉的读者,请看下图:

MSE 示例
图中可见两种参数的拟合效果,以及在不同斜率范围上的 MSE 曲面,从而看到目标函数本身。
左图展示两组参数对数据的拟合;右图展示不同斜率下的 MSE 曲面——目标函数作为一条曲线,具有清晰的最小值,优化器正试图找到它。梯度下降的每一步都沿着这条曲线朝该最小值移动。
约束与目标函数
目标函数告诉您要优化什么;约束告诉您能做什么。
在大多数实际问题中,您不可能随心所欲地极大化或极小化。您需要在预算、时间窗口或物理产能等限制内工作。这些限制称为约束,它们定义了优化器可选择的合法解空间。
以制造业为例。
假设您要在两条产品线间最大化利润。若无约束,答案就是无限制生产。但您只有 500 小时的设备时间和 1000 单位原材料可用。这些就是约束。目标函数仍然是(最大化利润),但优化器只能在约束允许的区域内搜索。
当您改变约束时,即使目标函数不变,最优解也会随之变化。
目标函数与一组约束共同构成了约束优化的基础。线性规划、投资组合优化以及许多现实中的规划问题都是这样表述的。
结语
每个优化问题——无论是训练神经网络、分配资源,还是拟合回归模型——归根结底都是在最小化或最大化某个函数。
这个函数就是目标函数。它定义了“更好”的含义,引导每一次参数更新,并决定模型实际学到什么。若您选对了,它就能帮助模型解决手头问题;若选错了,模型会解决另一个完全不同的问题——而且常常不会给出明显的错误提示。
选择合适的目标函数是数据科学中的一种设计决策,它会影响之后的一切。作为实践者,请尽管尝试——可选的目标函数很多。
不知道从哪里开始?我们的 Model Validation in Python 与 Hyperparameter Tuning in Python 课程都是初中级数据科学家的理想起点。
FAQs
什么是目标函数?
目标函数是一个用于衡量解好坏的数学函数。您为它提供一组输入,例如模型参数和决策变量,它会返回一个数值。目标始终是找到能让这个数尽可能高或尽可能低的输入。
目标函数与损失函数有什么区别?
损失函数是机器学习中用于衡量单个训练样本预测误差的特定类型目标函数。目标函数是更宽泛的术语——它可以指任何您要最小化或最大化的函数,而不仅仅是预测误差。在实践中,两者常被交替使用,但阅读论文时这种区分很重要。
目标函数应用于哪些场景?
只要涉及优化的问题都会出现目标函数——机器学习、线性规划、资源分配、金融、物流等。在机器学习中,目标函数定义了模型在训练期间所学的内容。在机器学习之外,它定义了任何有无约束优化问题中的目标。
为什么在机器学习中选择目标函数如此重要?
目标函数决定模型在训练中究竟在优化什么。如果选错了,模型会极其认真地去最小化错误的东西——这反而更难察觉。比如在分类问题中使用 MSE,不仅结果差,而且会“自信地差”,更糟糕。
目标函数会有多个极小值吗?
会——这也是训练深度学习模型的核心挑战之一。非凸目标函数存在多个局部最小值,优化器可能会困在并非全局最优的谷底。这就是为何权重初始化、学习率调度和优化器选择都很关键——它们会影响优化器最终能否找到一个好的解。