1

我正在尝试将自定义均值函数传递给 GPflow 2.0。我有一些 (x,y,z) 数据,每个 x,y 点都有几个观察值。我想将每个 (x,y) 对的平均 z 值作为均值函数传递。我的自定义均值函数代码train_xy位于训练数据中 (x,y,z) 元组的位置(x 和 y 是输入,z 是输出)。

下面是我设置均值函数并将其传递给简单 GPR 模型的代码。


class CustomMean(gpflow.mean_functions.MeanFunction):
    """
    means = mean(grouped by unique tuples of input1 & input2)
    """

    def __init__(self, X):
        # MeanFunction.__init__(self)
        self.X = Parameter(X)

    def __call__(self, X):
        mean_arr = []
        X = np.unique(X, axis=0)
        for i in range(len(X)):
            y_list = train_xy[(train_xy['input1'] == X[i, 0]) & (train_xy['input2'] == X[i, 1])]['output']
            mean_arr.append(y_list.mean())
        mean_arr = np.asarray(mean_arr, dtype=np.float64)
        mean_arr[np.isnan(mean_arr)] = 0
        means = tf.convert_to_tensor(mean_arr)
        return means
    
    
k = gpflow.kernels.Linear()
mean_func = CustomMean(X_train.values.astype('float64'))
m = gpflow.models.GPR(data=(X_train, y_train), kernel=k, mean_function=mean_func)

pred_mean, pred_var = m.predict_f(X_test.values.astype('float64'))

我在调用predict_f函数时遇到了问题:


InvalidArgumentError                      Traceback (most recent call last)
<ipython-input-140-c7b24d06c38e> in <module>()
----> 1 pred_mean, pred_var = m.predict_f(X_test.values.astype('float64'))

~/anaconda3/envs/tensorflow_p36/lib/python3.6/site-packages/gpflow/models/gpr.py in predict_f(self, Xnew, full_cov, full_output_cov)
    103             kmn, kmm + s, knn, err, full_cov=full_cov, white=False
    104         )  # [N, P], [N, P] or [P, N, N]
--> 105         f_mean = f_mean_zero + self.mean_function(Xnew)
    106         return f_mean, f_var

...

InvalidArgumentError: Incompatible shapes: [1250,2596] vs. [1104] [Op:AddV2]

看起来该错误与名为f_mean = f_mean_zero + self.mean_function(Xnew). 当我看这个的形状时,尺寸非常大。我的训练数据中有 2596 个唯一 (x,y) 对(总共 3750 行)和测试中有 1104 个唯一 (x,y) 对(总共 1250 行)。 f_mean_zero是 (1250, 2596),而self.mean_function(Xnew)返回均值的一维张量(如预期的那样)。我不了解 的维度f_mean_zero,特别是因为我的测试数据中的 (x,y) 对在我的训练数据中。这似乎与这张票类似的问题,但没有解决方案。谢谢!

4

2 回答 2

0

您是否考虑过从数据中减去平均值并使用零均值 GPR 对其进行建模,然后再将平均值加回去?这将达到相同的效果,而无需创建自定义类。

于 2020-07-10T16:03:34.360 回答
0

我有几个建议可以帮助您解决问题:

  1. 重要的是要记住 GPflow 的大部分计算都使用 TensorFlow。许多操作的输入和输出(如__call__均值函数)被假定为tf.Tensors 而不是np.ndarrays ,就像您的代码段中的情况一样。s不支持 、 等操作len(),必须将其正确转换为 TensorFlow 操作。话虽这么说,您想要实现的任务并不容易在 TensorFlow 中使用 Tensor 逻辑来实现。我相信你将不得不使用像tf.where这样的操作。np.uniquetf.Tensor

  2. 您提供的堆栈跟踪显示不匹配的形状。mean 函数调用的输出应与输入具有相同的前导维度(X在您的情况下)。示例:如果X有 shape [N, D],则调用的输出应该有 shape [N, 1]

  3. 我不清楚为什么您将X作为参数存储在平均函数的 init 中。你能详细说明一下吗?

希望这对您有所帮助。

于 2020-07-09T08:25:50.770 回答