多任务高斯过程数学原理和Pytorch实现示例

本文涉及的产品
实时数仓Hologres,5000CU*H 100GB 3个月
实时计算 Flink 版,5000CU*H 3个月
智能开放搜索 OpenSearch行业算法版,1GB 20LCU 1个月
简介: 本文探讨了如何使用高斯过程扩展到多任务场景,强调了多任务高斯过程(MTGP)在处理相关输出时的优势。通过独立多任务GP、内在模型(ICM)和线性模型(LMC)的核心区域化方法,MTGP能够捕捉任务间的依赖关系,提高泛化能力。ICM和LMC通过引入核心区域化矩阵来学习任务间的共享结构。在PyTorch中,使用GPyTorch库展示了如何实现ICM模型,包括噪声建模和训练过程。实验比较了MTGP与独立GP,显示了MTGP在预测性能上的提升。

高斯过程其在回归任务中的应用我们都很熟悉了,但是我们一般介绍的都是针对单个任务的,也就是单个输出。本文我们将讨论扩展到多任务gp,强调它们的好处和实际实现。

本文将介绍如何通过共区域化的内在模型(ICM)和共区域化的线性模型(LMC),使用高斯过程对多个相关输出进行建模。

多任务高斯过程

高斯过程是回归和分类任务中的一个强大工具,提供了一种非参数方式来定义函数的分布。当处理多个相关输出时,多任务高斯过程可以模拟这些任务之间的依赖关系,从而带来更好的泛化和预测效果。

数学上,高斯过程被定义为一组随机变量,其中任何有限数量的变量都具有联合高斯分布。对于一组输入点 X,相应的输出值 f(X) 是联合高斯分布的:

其中 m(X) 是均值函数,k(X, X) 是协方差矩阵。

在多任务环境中,目标是建模函数 f: X → R^T,这样我们就有 T 个输出或任务,f_t(X) 对于 t = 1, …, T。这意味着均值函数是 m: X → R^T,核函数是 k: X × X → R^{T × T}。

我们如何模拟这些任务之间的相关性?

独立多任务高斯过程

一个简单的独立多输出高斯过程模型将每个任务独立建模,不考虑任务之间的任何相关性。在这种情况下,每个任务都有自己的高斯过程,具有自己的均值和协方差函数。数学上可以表达为:

这使得协方差矩阵 k(x, x) 是块对角形的,即 diag(k_1(x, x), …, k_T(x, x))。

这种方法没有利用任务之间的共享信息,可能导致性能不佳,尤其是当某些任务的数据有限时。

Intrinsic model of coregionalization(ICM)

ICM(共区域化的内在模型)方法通过引入核心区域化矩阵 (B) 来推广独立多输出高斯过程,该矩阵模型化任务之间的相关性。ICM方法中的协方差函数定义如下:

其中 k_input是在输入空间上定义的协方差函数(例如,平方指数核),而 B ∈ R^{ T × T} 是捕捉任务特定协方差的核心区域化矩阵。矩阵 (B) 通常参数化为 (B = W W^T),其中W ∈ R^{ T × r} ,且 (r) 是核心区域化矩阵的秩。这确保了核函数是半正定的。

ICM方法可以学习任务之间的共享结构。任务之间的皮尔逊相关系数可以表示为:

Linear model of coregionalization (LMC)

另一种常见的方法是LMC(线性核心区域化模型)模型,它通过允许更多种类的输入核来扩展ICM。在LMC模型中,协方差函数定义为:

其中 (Q) 是基核的数量,k_input^q 是基核,而 (B_q) 是每个基核的核心区域化矩阵。通过结合多个基核,这个模型可以捕捉任务之间更复杂的相关性。

我们可以通过设置 (Q=1) 来恢复ICM模型。或者说ICM是Q=1的LMC模型

噪声建模

在多任务高斯过程中,我们需要考虑一个多输出似然函数,该函数为每个任务模型化噪声。

标准的似然函数通常是多维高斯似然,可以表示为:

其中 (y) 是观测输出,(f(x)) 是潜在函数,Sigma是噪声协方差矩阵。

这里的灵活性在于噪声协方差矩阵的选择,它可以是对角线Σ=diag(σ12,…,σT2)(每个任务独立噪声)或完整(任务间相关噪声)。

后者通常表示为 Σ=LLT,其中 L∈RT×r,且 r是噪声协方差矩阵的秩。这允许捕捉不同任务的噪声项之间的相关性。

最终包含噪声的协方巧矩阵则由以下给出:

其中 (K) 是没有噪声的协方差矩阵,(I) 是单位矩阵,⊗表示克罗内克乘积,以便将噪声项添加到协方差矩阵的对角块中。

PyTorch实现

我们上面介绍了多任务的高斯过程的数学原理,下面开使用' GPyTorch '与ICM内核实现多任务GP的示例。

首先需要安装所需的软件包,包括' Torch ', ' GPyTorch ', ' matplotlib '和' seaborn ', ' numpy '。

 %pip install torch gpytorch matplotlib seaborn numpy pandas

 import torch
 import gpytorch
 from matplotlib import pyplot as plt
 import numpy as np
 import seaborn as sns
 import pandas as pd
AI 代码解读

然后,定义多任务GP模型。使用ICM内核(秩r=1)来捕获任务之间的相关性。

我们为两个任务(正弦和移位正弦)生成合成的噪声训练数据,以便有相关的输出。

噪声协方差矩阵为

其中σ²1 = σ²2 = 0.1²,ρ = 0.3。

最后,我们通过绘制每个任务的平均预测和置信区间来训练模型并评估其性能。

 # Define the kernel with coregionalization
 class MultitaskGPModel(gpytorch.models.ExactGP):
     def __init__(self, train_x, train_y, likelihood, num_tasks):
         super(MultitaskGPModel, self).__init__(train_x, train_y, likelihood)
         self.mean_module = gpytorch.means.MultitaskMean(
             gpytorch.means.ConstantMean(), num_tasks=num_tasks
         )
         self.covar_module = gpytorch.kernels.MultitaskKernel(
             gpytorch.kernels.RBFKernel(), num_tasks=num_tasks, rank=1
         )

     def forward(self, x):
         mean_x = self.mean_module(x)
         covar_x = self.covar_module(x)
         return gpytorch.distributions.MultitaskMultivariateNormal(mean_x, covar_x)

 # Training data
 f1 = lambda x:  torch.sin(x * (2 * torch.pi))
 f2 = lambda x: torch.sin((x - 0.1) * (2 * torch.pi))
 train_x = torch.linspace(0, 1, 10)
 train_y = torch.stack([
     f1(train_x),
     f2(train_x)
 ]).T
 # Define the noise covariance matrix with correlation = 0.3
 sigma2 = 0.1**2
 Sigma = torch.tensor([[sigma2, 0.3 * sigma2], [0.3 * sigma2, sigma2]])
 # Add noise to the training data
 train_y += torch.tensor(np.random.multivariate_normal(mean=[0,0], cov=Sigma, size=len(train_x)))

 # Model and likelihood
 num_tasks = 2
 likelihood = gpytorch.likelihoods.MultitaskGaussianLikelihood(num_tasks=num_tasks, rank=1)
 model = MultitaskGPModel(train_x, train_y, likelihood, num_tasks)

 # Training the model
 model.train()
 likelihood.train()

 optimizer = torch.optim.Adam(model.parameters(), lr=0.1)

 mll = gpytorch.mlls.ExactMarginalLogLikelihood(likelihood, model)

 scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=50, gamma=0.5)

 num_iter = 500
 for i in range(num_iter):
     optimizer.zero_grad()
     output = model(train_x)
     loss = -mll(output, train_y)
     loss.backward()
     optimizer.step()
     scheduler.step()

 # Evaluation
 model.eval()
 likelihood.eval()

 test_x = torch.linspace(0, 1, 100)

 with torch.no_grad(), gpytorch.settings.fast_pred_var():
     pred_multi = likelihood(model(test_x))

 # Plot predictions
 fig, ax = plt.subplots()

 colors = ['blue', 'red']
 for i in range(num_tasks):
     ax.plot(test_x, pred_multi.mean[:, i], label=f'Mean prediction (Task {i+1})', color=colors[i])
     ax.plot(test_x, [f1(test_x), f2(test_x)][i], linestyle='--', label=f'True function (Task {i+1})')
     lower = pred_multi.confidence_region()[0][:, i].detach().numpy()
     upper = pred_multi.confidence_region()[1][:, i].detach().numpy()
     ax.fill_between(
         test_x,
         lower,
         upper,
         alpha=0.2,
         label=f'Confidence interval (Task {i+1})',
         color=colors[i]
     )

 ax.scatter(train_x, train_y[:, 0], color='black', label=f'Training data (Task 1)')
 ax.scatter(train_x, train_y[:, 1], color='gray', label=f'Training data (Task 2)')

 ax.set_title('Multitask GP with ICM')
 ax.legend(loc='lower center', bbox_to_anchor=(0.5, -0.2),
           ncol=3, fancybox=True)
AI 代码解读

在使用

GPyTorch
AI 代码解读

时,通过使用

MultitaskMean
AI 代码解读

MultitaskKernel
AI 代码解读

MultitaskGaussianLikelihood
AI 代码解读

类,ICM模型的实现非常简单。这些类可以处理多任务结构、噪声和核心区域化矩阵,允许我们专注于模型定义和训练。

训练的循环也与标准高斯过程类似,以负边际对数似然作为损失函数,并使用优化器来更新模型参数。

在训练过程中添加了一个调度器来降低学习率,这可以帮助稳定优化过程。

 W = model.covar_module.task_covar_module.covar_factor
 B = W @ W.T

 fig, ax = plt.subplots()
 sns.heatmap(B.detach().numpy(), annot=True, ax=ax, cbar=False, square=True)
 ax.set_xticklabels(['Task 1', 'Task 2'])
 ax.set_yticklabels(['Task 1', 'Task 2'])
 ax.set_title('Coregionalization matrix B')
 fig.show()


 L = model.likelihood.task_noise_covar_factor.detach().numpy()
 Sigma = L @ L.T

 fig, ax = plt.subplots()
 sns.heatmap(Sigma, annot=True, ax=ax, cbar=False, square=True)
 ax.set_xticklabels(['Task 1', 'Task 2'])
 ax.set_yticklabels(['Task 1', 'Task 2'])
 ax.set_title('Noise covariance matrix')
 fig.show()
AI 代码解读

下面的图展示了模型学习的核心区域化矩阵 B 以及噪声协方差矩阵 Σ。

这张图捕捉了任务之间的相关性。如我们所见,B 的非对角线元素是正的。

这个图代表每个任务的噪声水平。注意到模型已经正确学习了噪声相关性。

比较

为了突出使用ICM方法对相关输出建模的优势,我们可以将其与独立处理每个任务、忽略任务之间任何潜在相关性的模型进行比较。

为每个任务定义一个单独的GP,训练它们,并在测试数据上评估它们的性能。

 class IndependentGPModel(gpytorch.models.ExactGP):
     def __init__(self, train_x, train_y, likelihood):
         super(IndependentGPModel, self).__init__(train_x, train_y, likelihood)
         self.mean_module = gpytorch.means.ConstantMean()
         self.covar_module = gpytorch.kernels.ScaleKernel(gpytorch.kernels.RBFKernel())

     def forward(self, x):
         mean_x = self.mean_module(x)
         covar_x = self.covar_module(x)
         return gpytorch.distributions.MultivariateNormal(mean_x, covar_x)

 # Create models and likelihoods for each task
 likelihoods = [gpytorch.likelihoods.GaussianLikelihood() for _ in range(num_tasks)]
 models = [IndependentGPModel(train_x, train_y[:, i], likelihoods[i]) for i in range(num_tasks)]

 # Training the independent models
 for i, (model, likelihood) in enumerate(zip(models, likelihoods)):
     model.train()
     likelihood.train()
     optimizer = torch.optim.Adam(model.parameters(), lr=0.1)
     mll = gpytorch.mlls.ExactMarginalLogLikelihood(likelihood, model)
     scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=50, gamma=0.5)

     for _ in range(num_iter):
         optimizer.zero_grad()
         output = model(train_x)
         loss = -mll(output, train_y[:, i])
         loss.backward()
         optimizer.step()
         scheduler.step()

 # Evaluation
 for model, likelihood in zip(models, likelihoods):
     model.eval()
     likelihood.eval()

 with torch.no_grad(), gpytorch.settings.fast_pred_var():
     pred_inde = [likelihood(model(test_x)) for model, likelihood in zip(models, likelihoods)]

 # Plot predictions
 fig, ax = plt.subplots()

 for i in range(num_tasks):
     ax.plot(test_x, pred_inde[i].mean, label=f'Mean prediction (Task {i+1})', color=colors[i])
     ax.plot(test_x, [f1(test_x), f2(test_x)][i], linestyle='--', label=f'True function (Task {i+1})')
     lower = pred_inde[i].confidence_region()[0]
     upper = pred_inde[i].confidence_region()[1]
     ax.fill_between(
         test_x,
         lower,
         upper,
         alpha=0.2,
         label=f'Confidence interval (Task {i+1})',
         color=colors[i]
     )

 ax.scatter(train_x, train_y[:, 0], color='black', label='Training data (Task 1)')
 ax.scatter(train_x, train_y[:, 1], color='gray', label='Training data (Task 2)')

 ax.set_title('Independent GPs')
 ax.legend(loc='lower center', bbox_to_anchor=(0.5, -0.2),
           ncol=3, fancybox=True)
AI 代码解读

在性能方面,比较多任务GP与ICM和独立GP在测试数据上预测的均方误差(MSE)。

 mean_multi = pred_multi.mean.numpy()
 mean_inde = np.stack([pred.mean.numpy() for pred in pred_inde]).T

 test_y = torch.stack([f1(test_x), f2(test_x)]).T.numpy()
 MSE_multi = np.mean((mean_multi - test_y) ** 2)
 MSE_inde = np.mean((mean_inde - test_y) ** 2)

 df = pd.DataFrame({
     'Model': ['ICM', 'Independent'],
     'MSE': [MSE_multi, MSE_inde]
   })
 df
AI 代码解读

可以看到由于共区域化矩阵学习到的共享结构,ICM在MSE方面略优于独立gp。当处理更复杂的任务或有限的数据时,这种改进可能更为显著。

在独立GP的场景中,每个GP从一个较小的10个点的数据集中学习,这可能会导致过拟合或次优泛化。具有ICM的多任务GP使用所有20个点来学习指数核参数的平方。这种共享信息有助于改进对这两个任务的预测。

https://avoid.overfit.cn/post/f804e93bd5dd4c4ab9ede5bf1bc9b6c8

作者:Andrea Ruglioni

相关实践学习
基于MSE实现微服务的全链路灰度
通过本场景的实验操作,您将了解并实现在线业务的微服务全链路灰度能力。
目录
打赏
0
7
7
2
538
分享
相关文章
基于PyTorch的大语言模型微调指南:Torchtune完整教程与代码示例
**Torchtune**是由PyTorch团队开发的一个专门用于LLM微调的库。它旨在简化LLM的微调流程,提供了一系列高级API和预置的最佳实践
353 59
基于PyTorch的大语言模型微调指南:Torchtune完整教程与代码示例
9个主流GAN损失函数的数学原理和Pytorch代码实现:从经典模型到现代变体
生成对抗网络(GAN)的训练效果高度依赖于损失函数的选择。本文介绍了经典GAN损失函数理论,并用PyTorch实现多种变体,包括原始GAN、LS-GAN、WGAN及WGAN-GP等。通过分析其原理与优劣,如LS-GAN提升训练稳定性、WGAN-GP改善图像质量,展示了不同场景下损失函数的设计思路。代码实现覆盖生成器与判别器的核心逻辑,为实际应用提供了重要参考。未来可探索组合优化与自适应设计以提升性能。
28 7
9个主流GAN损失函数的数学原理和Pytorch代码实现:从经典模型到现代变体
PyTorch Profiler 性能优化示例:定位 TorchMetrics 收集瓶颈,提高 GPU 利用率
本文探讨了机器学习项目中指标收集对训练性能的影响,特别是如何通过简单实现引入不必要的CPU-GPU同步事件,导致训练时间增加约10%。使用TorchMetrics库和PyTorch Profiler工具,文章详细分析了性能瓶颈的根源,并提出了多项优化措施
74 1
PyTorch Profiler 性能优化示例:定位 TorchMetrics 收集瓶颈,提高 GPU 利用率
深度强化学习中SAC算法:数学原理、网络架构及其PyTorch实现
软演员-评论家算法(Soft Actor-Critic, SAC)是深度强化学习领域的重要进展,基于最大熵框架优化策略,在探索与利用之间实现动态平衡。SAC通过双Q网络设计和自适应温度参数,提升了训练稳定性和样本效率。本文详细解析了SAC的数学原理、网络架构及PyTorch实现,涵盖演员网络的动作采样与对数概率计算、评论家网络的Q值估计及其损失函数,并介绍了完整的SAC智能体实现流程。SAC在连续动作空间中表现出色,具有高样本效率和稳定的训练过程,适合实际应用场景。
538 7
深度强化学习中SAC算法:数学原理、网络架构及其PyTorch实现
通过pin_memory 优化 PyTorch 数据加载和传输:工作原理、使用场景与性能分析
在 PyTorch 中,`pin_memory` 是一个重要的设置,可以显著提高 CPU 与 GPU 之间的数据传输速度。当 `pin_memory=True` 时,数据会被固定在 CPU 的 RAM 中,从而加快传输到 GPU 的速度。这对于处理大规模数据集、实时推理和多 GPU 训练等任务尤为重要。本文详细探讨了 `pin_memory` 的作用、工作原理及最佳实践,帮助你优化数据加载和传输,提升模型性能。
346 4
通过pin_memory 优化 PyTorch 数据加载和传输:工作原理、使用场景与性能分析
Pytorch的编译新特性TorchDynamo的工作原理和使用示例
PyTorch的TorchDynamo是一个即时编译器,用于优化动态图执行,提高运行效率。它在运行时分析和转换代码,应用优化技术,如操作符融合,然后编译成高效机器码。通过一个包含特征工程、超参数调整、交叉验证的合成数据集示例,展示了TorchDynamo如何减少训练时间并提高模型性能。它易于集成,只需对现有PyTorch代码进行小改动,即可利用其性能提升。TorchDynamo的优化包括动态捕获计算图、应用优化和编译,适用于实时应用和需要快速响应的场景。
129 11
图神经网络入门示例:使用PyTorch Geometric 进行节点分类
本文介绍了如何使用PyTorch处理同构图数据进行节点分类。首先,数据集来自Facebook Large Page-Page Network,包含22,470个页面,分为四类,具有不同大小的特征向量。为训练神经网络,需创建PyTorch Data对象,涉及读取CSV和JSON文件,处理不一致的特征向量大小并进行归一化。接着,加载边数据以构建图。通过`Data`对象创建同构图,之后数据被分为70%训练集和30%测试集。训练了两种模型:MLP和GCN。GCN在测试集上实现了80%的准确率,优于MLP的46%,展示了利用图信息的优势。
187 1
PyTorch实战:图像分类任务的实现与优化
【4月更文挑战第17天】本文介绍了使用PyTorch实现图像分类任务的步骤,包括数据集准备(如使用CIFAR-10数据集)、构建简单的CNN模型、训练与优化模型以及测试模型性能。在训练过程中,使用了交叉熵损失和SGD优化器。此外,文章还讨论了提升模型性能的策略,如调整模型结构、数据增强、正则化和利用预训练模型。通过本文,读者可掌握基础的PyTorch图像分类实践。
深入理解PyTorch自动微分:反向传播原理与实现
【4月更文挑战第17天】本文深入解析PyTorch的自动微分机制,重点讨论反向传播的原理和实现。反向传播利用链式法则计算神经网络的梯度,包括前向传播、梯度计算、反向传播及参数更新。PyTorch通过`autograd`模块实现自动微分,使用`Tensor`和计算图记录操作历史以自动计算梯度。通过示例展示了如何在PyTorch中创建张量、定义计算过程及求梯度。掌握这些有助于提升深度学习模型的训练效率。
PyTorch在NLP任务中的应用:文本分类、序列生成等
【4月更文挑战第18天】PyTorch在NLP中应用于文本分类和序列生成,支持RNN、CNN、Transformer等模型构建。其动态计算图、丰富API及强大社区使其在NLP研究中备受欢迎。预训练模型和多模态学习的发展将进一步拓宽PyTorch在NLP的应用前景。
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等