我想增加rnn或lstm单元中的循环权重。
如果您看下面的代码,您会发现lsrm单元输入的形状为(2,1),这意味着2个时间步长和1个特征。
%tensorflow_version 2.x
import tensorflow as tf
m = tf.keras.models.Sequential()
lstm = tf.keras.layers.LSTM(1, use_bias=False)
input = tf.keras.Input(shape=(2,1))
m.add(input)
m.add(lstm)
lstm.get_weights()
输出为
[array([[ 0.878217 , 0.89324415, 0.404307 , -1.0542995 ]], dtype=float32),
array([[-0.24181306, -0.341401 , 0.65207034, 0.63227856]], dtype=float32)]
每个功能的权重为4,先前输出的权重为4
现在,如果我这样更改输入形状
input = tf.keras.Input(shape=(2,1))
then the output of get_weights function will be like this:
[array([[-0.9725287 , -0.90078545, 0.97881985, -0.9623983 ],
[-0.9644511 , 0.90705967, 0.05965471, 0.32613564]], dtype=float32),
array([[-0.24867296, -0.22346373, -0.6410606 , 0.69084513]], dtype=float32)]
现在我的问题是:如何增加第二个阵列中的权重以保持(4,1)形状? 我的想法是,我希望RNN或STRM不仅要获取先前的输出(t-1时刻),而且还要获取更多的prevois值,例如(t-2,t-3,t-4)时刻。
在tf后端的喀拉拉邦有办法吗?
答案 0 :(得分:1)
我无法理解更改,我认为您的输入中有错字,但是:
时间步数将永远不会改变权重数。该层是“循环的”,这意味着它将“循环”时间步长。每个步骤的权重不同。
该层的整个目的是对每个时间步骤一遍又一遍地应用相同的操作。
输入要素是输入的最后一个维度。它们定义了权重的一个维度。
输出要素(也是输出的最后一个维度)是权重的另一个维度。
LSTM层有两组内核:
shape=(input_dim, self.units * 4)
shape=(self.units, self.units * 4)
第一组作用于输入数据,它们的形状考虑了输入特征和输出特征。
第二组作用于内部状态并具有仅考虑输出特征(单位)的形状。
从源代码开始:
self.kernel = self.add_weight(shape=(input_dim, self.units * 4),
name='kernel',
initializer=self.kernel_initializer,
regularizer=self.kernel_regularizer,
constraint=self.kernel_constraint)
self.recurrent_kernel = self.add_weight(
shape=(self.units, self.units * 4),
name='recurrent_kernel',
initializer=self.recurrent_initializer,
regularizer=self.recurrent_regularizer,
constraint=self.recurrent_constraint)
权重列表中的最后一个数组是形状为(1, 1)
的4个递归内核,它们被分组为一个。
所以:
您可以使用更多输入功能来增加kernel
。例如,将Input((anything, 1))
转换为Input((anything, more))
。
您可以使用更大的输出功能来增加kernel
和recurrent_kernel
(以及偏差,如果考虑的话)。将LSTM(1, ...)
转换为LSTM(more, ...)
重量与长度无关。甚至有可能使用Input((None, 1))
,这意味着长度可变。
这应该是自动的。 LSTM层设计为具有内存。内存是一种内部状态,它参与所有时间步骤。有一些门(内核)决定新步骤如何参与此内存。由于所有步骤都参与同一个存储器,因此LSTM层从理论上考虑“所有”时间步骤。
因此,您不必为此担心。
但是,如果您确实希望这样做,可能有两种方法。不过,不知道他们是否会带来任何改善。
一种方法是将移位的输入连接为特征:
def pad_and_shift(x):
steps = 3
paddings = tf.constant([[0,0], [steps-1, 0], [0, 0]])
x = tf.pad(x, paddings)
to_concat = [ x[:,i:i - steps + 1] for i in range(steps-1) ]
to_concat += x[:, steps-1:]
return tf.concat(to_concat, axis=-1)
given_inputs = ....
out = Lambda(pad_and_shift)(given_inputs)
out = LSTM(units, ...)(out)
另一个涉及编辑LSTM的源代码,这将非常复杂并且可能不太值得。