高斯过程(Gaussian Process, GP)是概率论和统计学中的一个重要概念,它本质上定义了在连续域上的概率分布。想象你面对一个未知函数时,高斯过程提供了一种描述对这个函数"认知不确定性"的数学框架。不同于常规的单点概率分布,GP能够描述整个函数空间上的分布特性。
从技术定义来看,高斯过程是由均值函数m(x)和协方差函数k(x,x')完全确定的随机过程。这里的协方差函数(也称核函数)决定了函数的平滑程度、周期性和其他重要特性。在实际应用中,我们通常将均值函数设为0(通过数据预处理实现),这样整个高斯过程的性质就完全由核函数决定了。
关键提示:高斯过程与高斯分布的关系就像"函数"与"点"的关系。如果说高斯分布描述的是随机变量的分布,那么高斯过程描述的就是随机函数的分布。
高斯过程采样让我们能够从先验分布中抽取具体的函数实例。这个过程的核心在于理解协方差矩阵如何刻画不同输入点之间的相关性。以下是MATLAB实现的关键步骤:
matlab复制x = linspace(-5, 5, 100)'; % 100个均匀分布的点在[-5,5]区间
matlab复制length_scale = 1; % 长度尺度参数
sigma_f = 1; % 信号方差参数
K = zeros(100,100);
for i = 1:100
for j = 1:100
K(i,j) = sigma_f^2 * exp(-0.5*(x(i)-x(j))^2/length_scale^2);
end
end
matlab复制L = chol(K + 1e-6*eye(100), 'lower'); % 添加小量确保正定性
matlab复制rng(1); % 设置随机种子保证可重复性
f_prior = L * randn(100, 5); % 生成5个样本函数
不同的核函数会导致完全不同的采样结果。常用的核函数包括:
平方指数核(RBF):
matlab复制k(x,x') = σ² exp(-||x-x'||²/(2l²))
产生平滑、无限可微的函数样本
Matérn核:
matlab复制k(x,x') = σ² (1 + √3||x-x'||/l) exp(-√3||x-x'||/l)
产生不那么平滑的样本,适用于物理过程建模
周期核:
matlab复制k(x,x') = σ² exp(-2sin²(π||x-x'||/p)/l²)
产生周期性样本,适用于季节性数据
实操心得:在实际采样时,建议先用小规模数据(如20-50个点)测试不同核函数的效果,确定合适后再扩展到大数据集。这样可以节省大量计算时间。
高斯过程回归的核心思想是:在观察到一些训练数据后,如何更新我们对函数的认知。这个过程涉及以下关键方程:
后验均值和方差计算:
matlab复制% 训练数据
x_train = [-4, -3, -2, -1, 1]';
y_train = sin(x_train); % 假设真实函数是sin(x)
% 测试点
x_test = linspace(-5,5,100)';
% 计算各种核矩阵
K_train = kernel(x_train, x_train, length_scale, sigma_f);
K_test = kernel(x_test, x_test, length_scale, sigma_f);
K_cross = kernel(x_test, x_train, length_scale, sigma_f);
% 加入噪声项
noise_level = 0.1;
K_train = K_train + noise_level^2 * eye(size(K_train));
% 计算后验分布参数
L = chol(K_train, 'lower');
alpha = L' \ (L \ y_train);
post_mean = K_cross * alpha;
v = L \ K_cross';
post_var = diag(K_test - v' * v);
高斯过程的性能很大程度上取决于核函数超参数的选择。常用的优化方法是最大化边缘似然:
matlab复制function [nlZ, dnlZ] = neg_log_marginal_likelihood(hyp, x, y)
% hyp = [log(length_scale); log(sigma_f); log(noise_level)]
ell = exp(hyp(1));
sf = exp(hyp(2));
sn = exp(hyp(3));
K = sf^2 * exp(-0.5*pdist2(x,x).^2/ell^2) + sn^2*eye(size(x,1));
L = chol(K, 'lower');
alpha = L' \ (L \ y);
% 负对数边缘似然
nlZ = 0.5*y'*alpha + sum(log(diag(L))) + 0.5*length(y)*log(2*pi);
% 梯度计算(可选)
if nargout > 1
W = L' \ (L \ eye(size(K))) - alpha*alpha';
dK_ell = K .* pdist2(x,x).^2 / ell^3;
dK_sf = 2*K / sf;
dK_sn = 2*sn*eye(size(K));
dnlZ = zeros(3,1);
dnlZ(1) = 0.5*sum(sum(W .* dK_ell));
dnlZ(2) = 0.5*sum(sum(W .* dK_sf));
dnlZ(3) = 0.5*sum(sum(W .* dK_sn));
end
end
使用MATLAB的fminunc进行优化:
matlab复制hyp_init = log([1; 1; 0.1]); % 初始猜测
options = optimoptions('fminunc', 'Display', 'iter', 'GradObj', 'on');
hyp_opt = fminunc(@(h) neg_log_marginal_likelihood(h, x_train, y_train), hyp_init, options);
高斯过程实现中最大的挑战之一是确保数值稳定性。以下是关键技巧:
添加微小对角项:
matlab复制K = K + 1e-8 * eye(size(K)); % 防止矩阵不正定
使用Cholesky分解替代直接求逆:
matlab复制% 不推荐
alpha = inv(K) * y;
% 推荐
L = chol(K, 'lower');
alpha = L' \ (L \ y);
对数空间参数优化:
在优化超参数时,对长度尺度和噪声水平等参数取对数,确保它们保持正值。
当数据点超过几千个时,标准高斯过程的计算复杂度O(N³)会成为瓶颈。可以考虑以下方案:
稀疏近似方法:
matlab复制m = 50; % 诱导点数量
xu = linspace(min(x), max(x), m)'; % 均匀分布的诱导点
% 计算稀疏近似所需的矩阵
Kuu = kernel(xu, xu, ell, sf);
Kuf = kernel(xu, x_train, ell, sf);
L = chol(Kuu, 'lower');
A = L \ Kuf;
Qff = A' * A;
% 稀疏近似协方差矩阵
K_sparse = Qff + diag(diag(K_train - Qff));
使用Kronecker乘积结构:
当输入空间是网格状时,可以利用Kronecker乘积分解协方差矩阵。
GPU加速:
MATLAB的并行计算工具箱可以显著加速矩阵运算:
matlab复制if gpuDeviceCount > 0
K = gpuArray(K);
y = gpuArray(y);
end
将高斯过程扩展到多维输入空间只需修改核函数的距离计算方式:
matlab复制function K = kernel_multi(X, Z, ell, sf)
% X: N x D矩阵
% Z: M x D矩阵
% ell: D维长度尺度向量
N = size(X,1);
M = size(Z,1);
K = zeros(N,M);
for i = 1:N
for j = 1:M
r2 = sum(((X(i,:) - Z(j,:))./ell').^2);
K(i,j) = sf^2 * exp(-0.5 * r2);
end
end
end
在实际应用中,不同维度可能需要不同的长度尺度(自动相关性确定,ARD):
matlab复制ell = [1; 2; 0.5]; % 每个维度有自己的长度尺度
hyp.cov = log([ell; sf]); % 在优化中包含所有参数
当观测噪声不是高斯分布时,需要进行近似处理:
拉普拉斯近似:
期望传播(EP):
MCMC采样:
当有多个相关输出时,可以使用多任务高斯过程:
matlab复制% 核函数现在需要处理任务索引和输入
k({x,i}, {z,j}) = k_x(x,z) * k_t(i,j);
% 其中k_x是输入空间的核,k_t是任务间的核
现代深度高斯过程将GP与神经网络结合:
GP作为神经网络的最后一层:
深度核学习:
matlab复制phi = neural_network(x); % 神经网络特征提取
K = kernel(phi, phi, ell, sf); % 在特征空间计算核
在实际项目中,我发现从简单模型开始逐步增加复杂度是最稳妥的做法。先尝试标准的高斯过程回归,确认基线性能后再考虑更复杂的变体。对于超参数优化,多次随机初始化的策略往往比依赖单一初始化点更可靠。