我最近一直在调查高斯过程。概率多输出的观点在我的领域是有希望的。特别是空间统计。但我遇到了三个问题:
让我使用meuse
数据集(来自R包sp
)运行一个简单的案例研究。
更新:用于此问题且根据Grr's answer更新的Jupyter笔记本为here。
import pandas as pd
import numpy as np
import matplotlib.pylab as plt
%matplotlib inline
meuse = pd.read_csv(filepath_or_buffer='https://gist.githubusercontent.com/essicolo/91a2666f7c5972a91bca763daecdc5ff/raw/056bda04114d55b793469b2ab0097ec01a6d66c6/meuse.csv', sep=',')
例如,我们将专注于铜和铅。
fig = plt.figure(figsize=(12,8))
ax1 = fig.add_subplot(121, aspect=1)
ax1.set_title('Lead')
ax1.scatter(x=meuse.x, y=meuse.y, s=meuse.lead, alpha=0.5, color='grey')
ax2 = fig.add_subplot(122, aspect=1)
ax2.set_title('Copper')
ax2.scatter(x=meuse.x, y=meuse.y, s=meuse.copper, alpha=0.5, color='orange')
事实上,铜和铅的浓度是相关的。
plt.plot(meuse['lead'], meuse['copper'], '.')
plt.xlabel('Lead')
plt.ylabel('Copper')
因此,这是一个多输出问题。
from sklearn.gaussian_process.kernels import RBF
from sklearn.gaussian_process import GaussianProcessRegressor as GPR
reg = GPR(kernel=RBF())
reg.fit(X=meuse[['x', 'y']], y=meuse[['lead', 'copper']])
predicted = reg.predict(meuse[['x', 'y']])
第一个问题:当y有多个维时,是否为相关多输出构建了内核?如果没有,我该如何指定内核?
我继续进行分析,以显示第二个问题,过度拟合:
fig = plt.figure(figsize=(12,4))
ax1 = fig.add_subplot(121)
ax1.set_title('Lead')
ax1.set_xlabel('Measured')
ax1.set_ylabel('Predicted')
ax1.plot(meuse.lead, predicted[:,0], '.')
ax2 = fig.add_subplot(122)
ax2.set_title('Copper')
ax2.set_xlabel('Measured')
ax2.set_ylabel('Predicted')
ax2.plot(meuse.copper, predicted[:,1], '.')
我创建了一个x和y坐标网格,并且该网格上的所有浓度都被预测为零。
最后,最后一个问题特别出现在土壤的3D中:我如何在这些模型中指定各向异性?
答案 0 :(得分:4)
首先,您需要拆分数据。训练模型然后预测相同的训练数据看起来就像你观察到的过度拟合,但你没有在任何保持数据上测试你的模型,所以你不知道它是如何在野外表现的。尝试将数据与sklearn.model_selection.train_test_split
分开,如下所示:
X_train, X_test, y_train, y_test = train_test_split(meuse[['x', 'y']], meuse[['lead', 'copper']])
然后你可以训练你的模型。但是,你也有一个问题。当您按照自己的方式训练模型时,最终会得到一个length_scale=1e-05
的内核。基本上你的模型中没有噪音。使用此设置进行的预测将围绕输入点(X_train
)紧密居中,以至于您无法对其周围的站点进行任何预测。您需要更改alpha
的{{1}}参数才能解决此问题。这是您可能需要进行网格搜索的内容,因为默认值为1e-10。例如,我使用了GaussianProcessRegressor
。
alpha=0.1
结果如下图所示:
正如你所看到的,这里没有过度拟合的问题,事实上这可能是不合适的。就像我说的那样,你需要在这个模型上做一些GridSearchCV,以便根据你的数据提出最佳设置。
所以回答你的问题:
模型可以很好地处理多输出。
过度拟合可以通过正确拆分数据或在不同的保留集上进行测试来解决。
请看一下高斯过程指南的Radial Basis Function RBF Kernel部分,了解应用各向异性内核的一些见解,而不是我们上面应用的各向同性内核。
评论中的问题更新
当你写“模型按原样处理多输出”时,你是说“按原样”模型是为相关目标构建的,还是模型作为独立的集合处理得很好模型?
好问题。根据我对GaussianProcessRegressor的理解,我不相信它能够在内部存储多个模型。所以这是一个单一的模型。这就是说你的问题有趣的是“为相关目标建立”的陈述。在这种情况下,我们的两个目标看起来相当相关(Pearson Correlation Coefficient = 0.818,p = 1.25e-38),所以我在这里看到两个问题:
对于相关数据,如果我们为两个目标以及各个目标建立模型,结果会如何比较?
对于非相关数据,上述情况是否成立?
不幸的是,我们无法在不创建新的“假”数据集的情况下测试第二个问题,这有点超出了我们在这里所做的范围。但是,我们可以很容易地回答第一个问题。使用我们相同的列车/测试分割,我们可以训练两个具有相同超参数的新模型,用于单独预测铅和铜。然后我们可以使用这两个类来训练MultiOutputRegressor
。最后将它们全部与原始模型进行比较。像这样:
reg = GPR(RBF(), alpha=0.1)
reg.fit(X_train, y_train)
predicted = reg.predict(X_test)
fig = plt.figure(figsize=(12,4))
ax1 = fig.add_subplot(121)
ax1.set_title('Lead')
ax1.set_xlabel('Measured')
ax1.set_ylabel('Predicted')
ax1.plot(y_test.lead, predicted[:,0], '.')
ax2 = fig.add_subplot(122)
ax2.set_title('Copper')
ax2.set_xlabel('Measured')
ax2.set_ylabel('Predicted')
ax2.plot(y_test.copper, predicted[:,1], '.')
现在我们有几个可以比较的模型。让我们绘制预测并看看我们得到了什么。
有趣的是,领先预测没有明显差异,但铜预测中有一些。这些只存在于原点GPR模型和我们的其他模型之间。继续进行更多量化的误差测量,我们可以看到,对于解释的方差,原始模型的表现比我们的MultiOutputRegressor略好。有趣的是,铜模型的解释方差明显低于主导模型(这实际上也对应于其他两个模型的各个组件的行为)。这一切都非常有趣,并将引导我们进入我们的最终模型的许多不同的发展路线。
我认为这里重要的一点就是所有的模型迭代看起来都在同一个球场,并且在这种情况下没有明显的优胜者。在这种情况下,您将需要进行一些重要的网格搜索,并且可能实现各向异性内核以及任何其他领域特定知识都会有所帮助,但因为我们的示例与有用的模型相差甚远。