Deep learning 如何在Tensorflow 2/keras自定义层中使用基于numpy的外部库函数?
如果有人能帮助我理解以下问题,我将不胜感激 我试图通过使用keras在tensorflow 2中实现一个自定义层(它是从类层派生的层) 我已经重写了构建和调用函数 当我编写调用函数时,我需要从只接受numpy数组的外部库调用一个方法。这是一个非常复杂的函数,当然它不使用张量流函数。 我的调用函数接收一个张量输入,将其转换为numpy(by.numpy()函数),从另一个库调用外部方法,然后将numpy数组转换回张量 在这里,我遇到了一些问题,并尝试了不同的解决方案Deep learning 如何在Tensorflow 2/keras自定义层中使用基于numpy的外部库函数?,deep-learning,neural-network,pytorch,tensorflow2.0,keras-layer,Deep Learning,Neural Network,Pytorch,Tensorflow2.0,Keras Layer,如果有人能帮助我理解以下问题,我将不胜感激 我试图通过使用keras在tensorflow 2中实现一个自定义层(它是从类层派生的层) 我已经重写了构建和调用函数 当我编写调用函数时,我需要从只接受numpy数组的外部库调用一个方法。这是一个非常复杂的函数,当然它不使用张量流函数。 我的调用函数接收一个张量输入,将其转换为numpy(by.numpy()函数),从另一个库调用外部方法,然后将numpy数组转换回张量 在这里,我遇到了一些问题,并尝试了不同的解决方案 如果我运行代码,它会告诉我…o
class SimpleLayer(tf.keras.layers.Layer):
def __init__(self):
super(SimpleLayer, self).__init__()
def build(self, input_shape):
shape_a = input_shape[0] #batch_size
shape_b = int(input_shape[1]) #height
shape_c = int(input_shape[2]) #width
shape_d = input_shape[3] #channel_number
self.w = self.add_weight(shape=(shape_d*shape_a, 2, shape_b, shape_c),
initializer='random_uniform', dtype='float64',
trainable=True)
def call(self, inputs):
tf_inputs = inputs.numpy()
sft = tr.transform(tf_inputs) # call to the external library
transformed = tf.math.multiply(sft, self.w)
conv = tf.zeros(np.shape(inputs))
conv = tr.inv_transform(inputs, transformed) # another call to a function that also converts to tensor
return conv. # this is a tensor!
.....
model = tf.keras.Sequential([
layers.experimental.preprocessing.Rescaling(1./255),
pl.SimpleLayer(),
layers.Activation('relu'),
layers.MaxPooling2D(),
pl.SimpleLayer(),
layers.Activation('relu'),
layers.Flatten(),
layers.Dense(128, activation='relu'),
layers.Dense(num_classes)
])
model.compile(
optimizer='adam',
loss=tf.losses.SparseCategoricalCrossentropy(from_logits=True),
run_eagerly=True, # adding this to avoid graph building
metrics=['accuracy'])
history = model.fit(train_images, train_labels, epochs=3, batch_size=20,
validation_data=(test_images, test_labels))
有什么解决办法吗?我可以只使用tensorflow 2函数来处理张量吗?或者我遗漏了什么
我也在考虑改用Pytork(我还不知道),但我担心会有同样的问题。您有什么建议吗?梯度不能通过
numpy
函数作为numpy
没有任何自动加载功能
您的自定义函数在tensorflow2.x
或pytorch
中都不起作用,因为未记录对numpy
数组的操作
对于您的调用
代码(在PyTorch中,它将是转发
,否则非常类似),请参阅注释:
def call(self, inputs):
tf_inputs = inputs.numpy() # gradient breaks
sft = tr.transform(tf_inputs) # still numpy
transformed = tf.math.multiply(sft, self.w)
conv = tf.zeros(np.shape(inputs))
conv = tr.inv_transform(inputs, transformed)
return conv # Tensor with no gradient history
这会发生在所有的SimpleLayer
层上
可能的解决方案
- 在
tensorflow
或pytorch
中以可微的方式对这些操作进行编码(假设它们是可微的,并且不使用像argmax
这样的操作)(后者更简单、更直观,您可以更轻松地使用它) - 如果您的复杂函数使用
并且是可微的,那么您可以通过将numpy
重写为np.op
来使用PyTorch对其进行编码,因为它们的API非常相似,并且几乎无缝地互操作torch.op
- 您可以使用而不是
和tf
作为“JAX可以自动区分本地Python和NumPy函数”。根据您的应用程序,可能值得一试pytorch