使用 tf.gather 在 keras 中自定义正则化
Custom regularization in keras with tf.gather
我正在尝试在 keras 中实现自定义正则化器。这个想法是正则化的范围限于数据集中的两列。这是一个玩具数据集:
# dataset
from sklearn.datasets import load_breast_cancer
data = load_breast_cancer()
x = data.data # x.shape() == (569, 30)
y = data.target
这是我编写正则化器的方式:
import tensorflow as tf # tf.__version__ == 2.0.0
class MyRegularizer(tf.keras.regularizers.Regularizer):
def __init__(self, strength):
self.strength = strength
def __call__(self, x):
# print(tf.shape(x))
return self.strength * tf.reduce_sum(tf.subtract(tf.gather(params=x,indices=[29],axis=1),
tf.gather(params=x,indices=[28],axis=1)
)
)
这是一个玩具模型:
# model
inputs = tf.keras.layers.Input(shape=x.shape[1])
dense = tf.keras.layers.Dense(1, kernel_regularizer=MyRegularizer(0.01)
)(inputs)
model = tf.keras.models.Model(inputs = inputs, outputs = dense)
model.compile(loss='binary_crossentropy')
model.summary()
model.fit(x,y)
我得到的错误如下:
InvalidArgumentError: segment_ids[0] = 28 is out of range [0, 1)
我确实尝试在模型外检查正则化器的输出函数
tf.reduce_sum(tf.subtract(tf.gather(x,[29],axis=1),tf.gather(x,[28],axis=1)))
它运行良好。
所以发送到正则化器的张量的形状可能存在问题。我不知道如何解决这个问题(玩过变量名、数据类型、输入形状,都没有运气)。没有正则化器的模型拟合没有任何错误。
互联网上关于上述错误的帖子围绕嵌入维度展开,我未能找到适合我的解决方案。
在您的子类中,'call()' 方法中传递的参数“x”是层内核(权重)。由于您在 Dence 层中有一个单元格,因此“tf.gather”方法无法在内核的第二个轴上找到索引 [28] 的元素。
InvalidArgumentError: segment_ids[0] = 28 is out of range [0, 1)
如果你想获得对应于 [28] 输入的权重;我认为下面的代码可以工作(将轴值更改为零):
import tensorflow as tf # tf.__version__ == 2.0.0
class MyRegularizer(tf.keras.regularizers.Regularizer):
def __init__(self, strength):
self.strength = strength
def __call__(self, x):
# print(tf.shape(x))
return self.strength * tf.reduce_sum(tf.subtract(tf.gather(params=x,indices=[29],axis=0),
tf.gather(params=x,indices=[28],axis=0)
)
)
我正在尝试在 keras 中实现自定义正则化器。这个想法是正则化的范围限于数据集中的两列。这是一个玩具数据集:
# dataset
from sklearn.datasets import load_breast_cancer
data = load_breast_cancer()
x = data.data # x.shape() == (569, 30)
y = data.target
这是我编写正则化器的方式:
import tensorflow as tf # tf.__version__ == 2.0.0
class MyRegularizer(tf.keras.regularizers.Regularizer):
def __init__(self, strength):
self.strength = strength
def __call__(self, x):
# print(tf.shape(x))
return self.strength * tf.reduce_sum(tf.subtract(tf.gather(params=x,indices=[29],axis=1),
tf.gather(params=x,indices=[28],axis=1)
)
)
这是一个玩具模型:
# model
inputs = tf.keras.layers.Input(shape=x.shape[1])
dense = tf.keras.layers.Dense(1, kernel_regularizer=MyRegularizer(0.01)
)(inputs)
model = tf.keras.models.Model(inputs = inputs, outputs = dense)
model.compile(loss='binary_crossentropy')
model.summary()
model.fit(x,y)
我得到的错误如下:
InvalidArgumentError: segment_ids[0] = 28 is out of range [0, 1)
我确实尝试在模型外检查正则化器的输出函数
tf.reduce_sum(tf.subtract(tf.gather(x,[29],axis=1),tf.gather(x,[28],axis=1)))
它运行良好。
所以发送到正则化器的张量的形状可能存在问题。我不知道如何解决这个问题(玩过变量名、数据类型、输入形状,都没有运气)。没有正则化器的模型拟合没有任何错误。
互联网上关于上述错误的帖子围绕嵌入维度展开,我未能找到适合我的解决方案。
在您的子类中,'call()' 方法中传递的参数“x”是层内核(权重)。由于您在 Dence 层中有一个单元格,因此“tf.gather”方法无法在内核的第二个轴上找到索引 [28] 的元素。
InvalidArgumentError: segment_ids[0] = 28 is out of range [0, 1)
如果你想获得对应于 [28] 输入的权重;我认为下面的代码可以工作(将轴值更改为零):
import tensorflow as tf # tf.__version__ == 2.0.0
class MyRegularizer(tf.keras.regularizers.Regularizer):
def __init__(self, strength):
self.strength = strength
def __call__(self, x):
# print(tf.shape(x))
return self.strength * tf.reduce_sum(tf.subtract(tf.gather(params=x,indices=[29],axis=0),
tf.gather(params=x,indices=[28],axis=0)
)
)