诱导变量的重塑 - GPflow
Reshape of Inducing Variables - GPflow
我有一个 SGPR
型号:
import numpy as np
import gpflow
X, Y = np.random.randn(50, 2), np.random.randn(50, 1)
Z1 = np.random.randn(13, 2)
k = gpflow.kernels.SquaredExponential()
m = gpflow.models.SGPR(data=(X, Y), kernel=k, inducing_variable=Z1)
我想分配不同形状的诱导变量,例如:
Z2 = np.random.randn(29, 2)
m.inducing_variable.Z.assign(Z2)
但如果我这样做,我得到:
ValueError: Shapes (13, 2) and (29, 2) are incompatible
有没有办法在不重新定义模型的情况下重新分配诱导变量?
上下文:我不想用诱导变量优化模型,而是想在不优化诱导变量的情况下优化模型,在优化的每一步手动重新分配诱导变量。
更新:此问题已由 https://github.com/GPflow/GPflow/pull/1594 解决,它将成为下一个 GPflow 补丁版本 (2.1.4) 的一部分。
通过该修复,您不需要自定义 class。您需要做的就是沿第一个维度使用 None
显式设置静态形状:
inducing_variable = gpflow.inducing_variables.InducingPoints(
tf.Variable(
Z1, # initial value
trainable=False, # True does not work - see Note below
shape=(None, Z1.shape[1]), # or even tf.TensorShape(None)
dtype=gpflow.default_float(), # required due to tf's 32bit default
)
)
m = gpflow.models.SGPR(data=(X, Y), kernel=k, inducing_variable=inducing_variable)
那么 m.inducing_variable.Z.assign(Z2)
应该可以正常工作。
注意 在这种情况下 Z
不能 是可训练的,因为 TensorFlow 优化器需要知道构造时的形状时间,不支持动态形状。
现在(从 GPflow 2.1.2 开始)没有 built-in 方法来改变 SGPR
的诱导变量的形状,尽管原则上是可行的。你可以用你自己的诱导变量class得到你想要的东西:
class VariableInducingPoints(gpflow.inducing_variables.InducingPoints):
def __init__(self, Z, name=None):
super().__init__(Z, name=name)
# overwrite with Variable with None as first element in shape so
# we can assign arrays with arbitrary length along this dimension:
self.Z = tf.Variable(Z, dtype=gpflow.default_float(),
shape=(None, Z.shape[1])
)
def __len__(self):
return tf.shape(self.Z)[0] # dynamic shape
# instead of the static shape returned by the InducingPoints parent class
然后
m = gpflow.models.SGPR(
data=(X, Y), kernel=k, inducing_variable=VariableInducingPoints(Z1)
)
相反。那么你的 m.inducing_variable.Z.assign()
应该会如你所愿。
(对于SVGP
,诱导变量的大小和由q_mu
和q_sqrt
定义的分布必须匹配,并且在构造时已知,所以在这种情况下改变诱导变量的数量就不那么微不足道了。)
我有一个 SGPR
型号:
import numpy as np
import gpflow
X, Y = np.random.randn(50, 2), np.random.randn(50, 1)
Z1 = np.random.randn(13, 2)
k = gpflow.kernels.SquaredExponential()
m = gpflow.models.SGPR(data=(X, Y), kernel=k, inducing_variable=Z1)
我想分配不同形状的诱导变量,例如:
Z2 = np.random.randn(29, 2)
m.inducing_variable.Z.assign(Z2)
但如果我这样做,我得到:
ValueError: Shapes (13, 2) and (29, 2) are incompatible
有没有办法在不重新定义模型的情况下重新分配诱导变量?
上下文:我不想用诱导变量优化模型,而是想在不优化诱导变量的情况下优化模型,在优化的每一步手动重新分配诱导变量。
更新:此问题已由 https://github.com/GPflow/GPflow/pull/1594 解决,它将成为下一个 GPflow 补丁版本 (2.1.4) 的一部分。
通过该修复,您不需要自定义 class。您需要做的就是沿第一个维度使用 None
显式设置静态形状:
inducing_variable = gpflow.inducing_variables.InducingPoints(
tf.Variable(
Z1, # initial value
trainable=False, # True does not work - see Note below
shape=(None, Z1.shape[1]), # or even tf.TensorShape(None)
dtype=gpflow.default_float(), # required due to tf's 32bit default
)
)
m = gpflow.models.SGPR(data=(X, Y), kernel=k, inducing_variable=inducing_variable)
那么 m.inducing_variable.Z.assign(Z2)
应该可以正常工作。
注意 在这种情况下 Z
不能 是可训练的,因为 TensorFlow 优化器需要知道构造时的形状时间,不支持动态形状。
现在(从 GPflow 2.1.2 开始)没有 built-in 方法来改变 SGPR
的诱导变量的形状,尽管原则上是可行的。你可以用你自己的诱导变量class得到你想要的东西:
class VariableInducingPoints(gpflow.inducing_variables.InducingPoints):
def __init__(self, Z, name=None):
super().__init__(Z, name=name)
# overwrite with Variable with None as first element in shape so
# we can assign arrays with arbitrary length along this dimension:
self.Z = tf.Variable(Z, dtype=gpflow.default_float(),
shape=(None, Z.shape[1])
)
def __len__(self):
return tf.shape(self.Z)[0] # dynamic shape
# instead of the static shape returned by the InducingPoints parent class
然后
m = gpflow.models.SGPR(
data=(X, Y), kernel=k, inducing_variable=VariableInducingPoints(Z1)
)
相反。那么你的 m.inducing_variable.Z.assign()
应该会如你所愿。
(对于SVGP
,诱导变量的大小和由q_mu
和q_sqrt
定义的分布必须匹配,并且在构造时已知,所以在这种情况下改变诱导变量的数量就不那么微不足道了。)