运行 Keras 中的反向模型
Run model in reverse in Keras
我目前正在研究 Keras 框架。并做了一些简单的分类测试等。我想找到一种方法 运行 网络反向,使用输出作为输入,反之亦然。有什么办法吗?
没有"running a neural net in reverse"这样的东西,因为神经网络的通用架构没有定义任何非前向数据处理。然而,有一个模型子类可以做到——生成模型,现在还不是 keras 的一部分。您唯一可以做的就是创建一个网络,以某种方式 "simulates" 您感兴趣的生成过程。但这是特定模型的特定方法,没有通用的解决方案。
我不确定这个的用例,但只是添加一个快速修复,就是重新设计一个架构,这样输入就被视为输出,反之亦然。
假设您的输入数据的形状(作为示例):
n_obs, n_feat = 1000, 20
n_labels = 2
n_hidden = 100 # you can make this whatever you want
你通常会像这样设计输入层:
Dense(input_dim = n_feat, output_dim = n_hidden)
输出层如:
Dense(input_dim = n_hidden, output_dim = n_labels)
如果您想要 运行 这个 "in reverse",只需制作另一个模型,具有相反的架构,例如:
新输入层:
Dense(input_dim = n_labels, output_dim = n_hidden)
新输出层:
Dense(input_dim = n_hidden, output_dim = n_feat)
但是和上面lejlot说的类似,这里没有单一模型的解决方案。您不能在输入数据上训练模型,然后在输出数据上对其进行测试。这有意义吗?
基础权重矩阵必须具有正确的数据维度,当您尝试为其提供不同形状的数据(即输出数据代替输入数据)时,它无法执行矩阵乘法,即是每个神经网络的核心。
如果您对这一点感到困惑,您应该回顾一下神经网络的实际工作原理。
我认为您正在寻找的是 "Auto-Associative" 神经网络。它有一个 n 维的输入,几个层,其中一个是 m 维的 "middle layer",然后还有几个层导致一个输出层,该输出层的维数与输入层 n.
这里的关键是m远小于n。
它的工作原理是训练网络在输出时重新创建输入。然后你把网络分成两半。前半部分从 n 到 m 维(将输入编码为更小的 space)。后半部分从 m 维到 n 维(解码,或者 "reverse" 如果你愿意)。
对加密、压缩、无监督学习等非常有用
有一种方法,但你的里程可能会有所不同,它可能只是 return 输入的垃圾,尽管 'rubbish' 仍然会产生你开始的输出。关键词是'treat inputs as weights and train them with the rest of the model fixed'.
也就是说,您可以用一层权重替换输入层,冻结模型的其余部分并在固定输出的同时训练这些权重。
为了适应 Keras 的结构,我创建了一个自定义层并将其命名为 'Recover'。在训练模型时不会触发它,但它用作反向训练步骤的人造输入层。 (我确信该方法可以进一步优化,但这是我能想到的最快的方法)。
class Recover(Layer):
def __init__(self, **kwargs):
super(Recover, self).__init__(**kwargs)
self.reverse = False
def build(self, input_shape):
self.kernel = self.add_weight(name='kernel',
shape=(input_shape[1],),
initializer='uniform',
trainable=True)
super(Recover, self).build(input_shape)
def call(self, x):
if self.reverse:
return K.ones_like(x)*self.kernel
else:
return x
def compute_output_shape(self, input_shape):
return (input_shape[0], input_shape[0])
直接在输入层之后添加该层,在该层上设置trainable
为False
。首先,正常训练网络,这一层应该被忽略并作为传递。
完成后,重置该层内的权重,将reverse
设置为True
,将trainable
设置为True
,将trainable
设置为False
对于所有其他层,重新编译模型并重新开始训练。
大致如下:
for x in model.layers:
x.trainable = False
model.layers[0].trainable = True
model.layers[0].reverse = True
model.compile( ...your compile parameters... )
此时调用 model.fit
时将忽略实际输入,可以只为输入数组指定正确形状的零。
使用这种方法有时会陷入次优解决方案。只需重新初始化 Recover
层的权重并重复。训练完成后,Recover
层的权重可以通过调用 get_weights()
获得,并将对应于原始模型的输入,从而使其产生所需的输出。
结果很可能会像噪声一样,可能需要引入额外的损失(通过在 call
函数中调用 self.add_loss
)来强制模型产生有意义的输入。
我目前正在研究 Keras 框架。并做了一些简单的分类测试等。我想找到一种方法 运行 网络反向,使用输出作为输入,反之亦然。有什么办法吗?
没有"running a neural net in reverse"这样的东西,因为神经网络的通用架构没有定义任何非前向数据处理。然而,有一个模型子类可以做到——生成模型,现在还不是 keras 的一部分。您唯一可以做的就是创建一个网络,以某种方式 "simulates" 您感兴趣的生成过程。但这是特定模型的特定方法,没有通用的解决方案。
我不确定这个的用例,但只是添加一个快速修复,就是重新设计一个架构,这样输入就被视为输出,反之亦然。
假设您的输入数据的形状(作为示例):
n_obs, n_feat = 1000, 20
n_labels = 2
n_hidden = 100 # you can make this whatever you want
你通常会像这样设计输入层:
Dense(input_dim = n_feat, output_dim = n_hidden)
输出层如:
Dense(input_dim = n_hidden, output_dim = n_labels)
如果您想要 运行 这个 "in reverse",只需制作另一个模型,具有相反的架构,例如:
新输入层:
Dense(input_dim = n_labels, output_dim = n_hidden)
新输出层:
Dense(input_dim = n_hidden, output_dim = n_feat)
但是和上面lejlot说的类似,这里没有单一模型的解决方案。您不能在输入数据上训练模型,然后在输出数据上对其进行测试。这有意义吗?
基础权重矩阵必须具有正确的数据维度,当您尝试为其提供不同形状的数据(即输出数据代替输入数据)时,它无法执行矩阵乘法,即是每个神经网络的核心。
如果您对这一点感到困惑,您应该回顾一下神经网络的实际工作原理。
我认为您正在寻找的是 "Auto-Associative" 神经网络。它有一个 n 维的输入,几个层,其中一个是 m 维的 "middle layer",然后还有几个层导致一个输出层,该输出层的维数与输入层 n.
这里的关键是m远小于n。
它的工作原理是训练网络在输出时重新创建输入。然后你把网络分成两半。前半部分从 n 到 m 维(将输入编码为更小的 space)。后半部分从 m 维到 n 维(解码,或者 "reverse" 如果你愿意)。
对加密、压缩、无监督学习等非常有用
有一种方法,但你的里程可能会有所不同,它可能只是 return 输入的垃圾,尽管 'rubbish' 仍然会产生你开始的输出。关键词是'treat inputs as weights and train them with the rest of the model fixed'.
也就是说,您可以用一层权重替换输入层,冻结模型的其余部分并在固定输出的同时训练这些权重。
为了适应 Keras 的结构,我创建了一个自定义层并将其命名为 'Recover'。在训练模型时不会触发它,但它用作反向训练步骤的人造输入层。 (我确信该方法可以进一步优化,但这是我能想到的最快的方法)。
class Recover(Layer):
def __init__(self, **kwargs):
super(Recover, self).__init__(**kwargs)
self.reverse = False
def build(self, input_shape):
self.kernel = self.add_weight(name='kernel',
shape=(input_shape[1],),
initializer='uniform',
trainable=True)
super(Recover, self).build(input_shape)
def call(self, x):
if self.reverse:
return K.ones_like(x)*self.kernel
else:
return x
def compute_output_shape(self, input_shape):
return (input_shape[0], input_shape[0])
直接在输入层之后添加该层,在该层上设置trainable
为False
。首先,正常训练网络,这一层应该被忽略并作为传递。
完成后,重置该层内的权重,将reverse
设置为True
,将trainable
设置为True
,将trainable
设置为False
对于所有其他层,重新编译模型并重新开始训练。
大致如下:
for x in model.layers:
x.trainable = False
model.layers[0].trainable = True
model.layers[0].reverse = True
model.compile( ...your compile parameters... )
此时调用 model.fit
时将忽略实际输入,可以只为输入数组指定正确形状的零。
使用这种方法有时会陷入次优解决方案。只需重新初始化 Recover
层的权重并重复。训练完成后,Recover
层的权重可以通过调用 get_weights()
获得,并将对应于原始模型的输入,从而使其产生所需的输出。
结果很可能会像噪声一样,可能需要引入额外的损失(通过在 call
函数中调用 self.add_loss
)来强制模型产生有意义的输入。