做代理模型的朋友应该都有过这种体验:测试函数维度一上10维,原本乖乖听话的Kriging模型突然就疯了——训练时间从几秒变成几小时,预测结果全部变成NaN,或者误差大得离谱。前段时间我调一个20维的工艺优化问题,500个样本点喂进去,协方差矩阵的条件数直接飙到10的17次方,优化器反复迭代却输出一堆无效结果。这篇文章就把我踩过的高维Kriging的坑集中说一下,把核心代码掰开揉碎,重点解释维度超过10维后传统实现方式到底崩在哪、怎么用特殊手段把它救回来。
这篇文章适合正在用Kriging做代理模型、响应面拟合,或者做贝叶斯优化但发现高维场景下模型频繁失效的读者。不管你是用现成库还是自己手写实现,理解这些数值层面的崩溃点,比换一个库要管用得多。
1. 维度诅咒在Kriging里的两个元凶:样本爆炸与距离集中
1.1 空间填充的指数爆炸:1000个样本在高维里只是沧海一粟
很多人对Kriging的第一印象是"插值精度高、能给出不确定性估计",这在低维空间完全正确。比如一维问题,均匀取10个点就能把区间填得差不多;二维问题,10×10的网格是100个点;但到了10维,如果想保持同样的填充密度,理论上需要10的10次方个点。这就是维度诅咒的第一重体现:空间体积随维度指数增长,而我们的样本量往往只有几百个。
实际工程里,高维样本点的总量通常卡在几百到几千这个量级。拿上面说的20维工艺优化来讲,500个样本散布在20维超立方体里,每个维度方向实际上只有大约2到3个有效切分点,这连捕捉变量之间的非线性交互都勉强,更别说支撑Kriging对协方差结构做准确估计。
维度升高后,超参数估计会退化成"矮子里面拔将军":长度尺度的最大似然估计缺乏足够信息,优化器只能在多个等价的局部最优之间反复摇摆。普通Kriging模型假设所有方向共用一个长度尺度,这在低维还能凑合,高维下不同变量的敏感度往往差异极大,单一尺度参数必然顾此失彼。
1.2 距离集中效应:所有点都"差不多远"
第二个元凶更隐蔽,也更容易被忽视:高维空间中,随机样本点之间的欧氏距离会趋向一致。我做过一个简单测试——在20维空间里随机生成200个点,计算两两之间的欧氏距离,距离的变异系数不到5%。换句话说,在高维空间里,几乎所有样本点之间的距离都挤在同一个很窄的区间内。
这对Kriging是个致命的数值问题。因为Kriging的相关性矩阵是基于距离构造的,距离分布越集中,相关性矩阵中各个元素的值就越接近,矩阵就趋近于"所有元素都相等"的病态状态。相关性矩阵一旦接近奇异,求逆结果就会剧烈震荡,稍微一个浮点误差都会被无限放大,最终输出要么是天文数字,要么直接NaN。
这两个效应叠加在一起,导致传统Kriging在维度超过10之后,误差和数值不稳定几乎是必然的。理解这一点,再看后面的代码走查和各种补救手段,就会清楚每个方案的针对性在哪里。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 核心代码走查:传统实现从建矩阵到求逆的崩溃点
2.1 先看最基础的Kriging实现长什么样
为了把问题讲透,我们先写一个最朴素的普通Kriging实现。这里故意用的是最直观的写法,和很多教材、论文里的伪代码基本一致,方便对照崩溃点。
python复制import numpy as np
from scipy.spatial.distance import cdist
def gaussian_correlation(X, Y, theta):
# theta: 长度尺度参数,控制相关性随距离衰减的速度
d = cdist(X / theta, Y / theta, metric='euclidean')
return np.exp(-0.5 * d ** 2)
class SimpleKriging:
def __init__(self, theta):
self.theta = theta
def fit(self, X, y):
self.X_ = X
self.y_ = y
n = X.shape[0]
# 构建相关矩阵,这是Kriging的核心
self.R_ = gaussian_correlation(X, X, self.theta)
self.R_inv_ = np.linalg.inv(self.R_) # 关键崩溃点
ones = np.ones((n, 1))
self.mu_ = (ones.T @ self.R_inv_ @ y) / (ones.T @ self.R_in
