概述
LSTM 在机器学习上面的应用是非常广泛的, 从股票分析, 机器翻译 到 语义分析等等各个方面都有它的用武之地, 经过前面的对于 LSTM 结构的分析, 这一节主要介绍一些 LSTM 的一个小应用, 那就是 sequence generation. 其实 sequence generation 本事也是对一些应用的统称, 例如: 让机器学习音乐后然后让机器根据学习的模型自己创造音乐(制作人快要失业啦....), 让机器学习某种语言然后让这个学习到的模型自己产生 Word 来说话, 等等. 这其实本质是一种 one-to-many 的 LSTM 网络结构. 这一节内容主要就是讲解这一种网络结构的应用.
Sequence generation 的网络结构分析
在咱们实际实施并且写代码之前, 咱们首要的任务是如何搭建一个 sequence generation 的网络结构. 一个 sequence generation 的网络结构其实也是分为两个部分, 第一部分是 encoding (modeling), 也就是咱们建模的网络, 它是一个 many-to-many 的网络结构; 第二部分是 decoding 的过程, 它是一个 one-to-many 的结构. 那么具体这个网络结构是什么样呢? 咱们看看下面的图片
上面的图片展示的就是一个 sequence generation 从 encoding 到 decoding 的全过程和结构. 在咱们的这个应用中, 咱们的 encoding 中每一个 time step 的输入是一个文字, 输出则是相应输入的后一个字, 这些数据都来自于咱们的 training data; 等到咱们训练完成后, 咱们将训练得来的 LSTM cell 来构建一个 decoding 网络, 就是咱们只输入一个单词, 它根据咱们的之前学习的 model, 来自动的预测咱们要说什么话, 是不是很 cool?? 当然啦, 在 encoding 阶段, 咱们的 LSTM 具体有多少的 time steps, 是根据咱们的 input data 的 shape 来决定的; 在 decoding 阶段具体有多少的 time step 则是由咱们自己来决定的, 咱们需要用一个 for loop 来决定咱们在 decoding 阶段的 time steps. 从上图, 咱们也可以很明显的看出在 decoding 的时候, 咱们只有一个输入 X, 后面 time step 的输入则都是前一个 time step 的输出. 上面就是怎么 sequence generation 的一个整体的结构. 那么就下来, 咱们就分析一些它的代码, 看看咱们如何用代码来实现上面的网络结构.
Sequence generation 代码分析
从上面的分析, 咱们可以看出 sequence generation 是由两个部分组成, 那么自然咱们代码也肯定得分成两部分来实现上图中的网络结构, 那么接下来咱们来看看第一步, 就是如何用 Python 来实现 encoding 的结构, 代码如下所示, 咱们看着代码来慢慢分析:
- #define shared variables
- n_a=64
- n_values = 78 # dimensions of out single input
- reshapor = keras.layers.Reshape((1, n_values)) # Used in Step 2.B of djmodel(), below
- LSTM_cell = keras.layers.LSTM(n_a, return_state = True) # Used in Step 2.C, return_state muset be set
- densor = keras.layers.Dense(n_values, activation='softmax') # Used in Step 2.D
- #multiple inputs (X, a, c), we have to use functional Keras, other than sequential APIs
- def create_model(Tx, n_a, n_values):
- """
- Implement the model
- Arguments:
- Tx -- length of the sequence in a corpus
- n_a -- the number of activations used in our model
- n_values -- number of unique values in the music data
- Returns:
- model -- a keras instance model with n_a activations
- """
- # Define the input layer and specify the shape
- X = keras.Input(shape=(Tx, n_values))#input omit the batch_size dimension, X is still 3 dimensiones (with batch_size dimension).
- # Define the initial hidden state a0 and initial cell state c0
- a0 = keras.Input(shape=(n_a,), name='a0')
- c0 = keras.Input(shape=(n_a,), name='c0')
- a = a0
- c = c0
- # Step 1: Create empty list to append the outputs while you iterate
- outputs = []
- # Step 2: Loop
- for t in range(Tx):
- # Step 2.A: select the "t"th time step vector from X.
- x = keras.layers.Lambda(lambda x: X[:,t,:])(X)
- # Step 2.B: Use reshapor to reshape x to be (1, n_values) (≈1 line)
- #因为 LSTM layer 默认的输入的 dimension 是 (batch_size, Tx, n_values), 其中 batch_size 是省略的, 即是 (Tx, n_values). 如果是(Tx,n_values) 的话, LSTM()会默认循环 Tx 次, 因而, 咱们将它 reshape 成(1,n_values), 它就不会循环了.
- x = reshapor(x)
- # Step 2.C: Perform one step of the LSTM_cell
- a, _, c = LSTM_cell(x, initial_state=[a,c])
- # Step 2.D: Apply densor to the hidden state output of LSTM_Cell
- out = densor(a) #out's shape is (m,1,n_values)
- # Step 2.E: add the output to "outputs"
- outputs.append(out)
- # Step 3: Create model instance
- model = keras.Model(inputs=[X,a0,c0],outputs=outputs)
- return model
从上面的代码, 咱们可以看出, 首先咱们得定义一些 shared variable, 例如 a, c 的 dimension, LSTM_cell, 等等这些, 这些变量在咱们的 model 中无论是 encoding 还是 decoding 都是公用的, 并不是说一个 LSTM layer 就含有很多个 LSTM_cell, 这是错误的理解 (虽然咱们图片上面是这么画的, 但这是为了方便大家理解才画了很多个 LSTM_cell, 实际是同一个 LSTM_cell, 希望不要误解). 首先咱们构建这个网络需要的参数有, Tx = time_steps; n_a = a,c 的 vector 的 dimension; 以及 n_values = 咱们每一个输入的 vector 的 dimension. 因为咱们的网络有三处输入, 分别是 X, a, c, 所以咱们要先定义这三处输入, 并且设定它们的 shape, 注意在设定它们的 shape 的时候, 是不需要有 batch_size 的; 随后咱们来到 for loop 中, 首先提取每一个 time step 的 input value, 即上面代码中 Lambda layer 所做的事儿, 然后因为咱们提取的是每一个 time step 的值, 每一个 time step, LSTM 只会循环一次, 所以咱们还是得把它 reshape 到(1,n_values); 随后咱们将处理好的 input value 传递给 LSTM_cell, 并且返回 hidden state a, 和 memory cell c, 最后经过一个 dense layer 计算咱们的输出, 并且将每一步的输出装进 outputs 这个 list 中. 这就是构建咱们的 encoding 网络的整个步骤. 那么既然咱们分析了上面 encoding 的阶段, 完成了对咱们 LSTM 的训练过程并且得到了咱们想要的 LSTM, 那么接下来咱们看一看咱们的 decoding 过程, 即如何用训练得到的 LSTM 来 generate(predict) 咱们的 sequence 啦, 咱们还是看下面的代码, 然后慢慢分析
- def sequence_inference_model(LSTM_cell, n_values = 78, n_a = 64, Ty = 100):
- """ Uses the trained"LSTM_cell"and"densor" from model() to generate a sequence of values.
- Arguments:
- LSTM_cell -- the trained "LSTM_cell" from model(), Keras layer object
- densor -- the trained "densor" from model(), Keras layer object
- n_values -- integer, number of unique values
- n_a -- number of units in the LSTM_cell
- Ty -- integer, number of time steps to generate
- Returns:
- inference_model -- Keras model instance
- """
- # Define the input of your model with a shape (it is a one-to-many structure, the input shape is (1,n_values))
- x0 = keras.Input(shape=(1, n_values))
- # Define a0, c0, initial hidden state for the decoder LSTM
- a0 = keras.Input(shape=(n_a,), name='a0')
- c0 = keras.Input(shape=(n_a,), name='c0')
- a = a0
- c = c0
- x = x0
- # Step 1: Create an empty list of "outputs" to later store your predicted values (≈1 line)
- outputs = []
- # Step 2: Loop over Ty and generate a value at every time step
- for t in range(Ty):
- # Step 2.A: Perform one step of LSTM_cell
- a, _, c = LSTM_cell(x, initial_state=[a, c])
- # Step 2.B: Apply Dense layer to the hidden state output of the LSTM_cell
- out = densor(a)
- # Step 2.C: Append the prediction "out" to "outputs". out.shape = (None, 78)
- outputs.append(out)
- # Step 2.D: Select the next value according to "out", and set "x" to be the one-hot representation of the
- # selected value, which will be passed as the input to LSTM_cell on the next step. We have provided
- # the line of code you need to do this.
- x = keras.layers.Lambda(one_hot)(out)
- # Step 3: Create model instance with the correct "inputs" and "outputs"
- inference_model = keras.Model(inputs=[x0, a0, c0], outputs=outputs)
- return inference_model
- inference_model = sequence_inference_model(LSTM_cell, densor, n_values = 78, n_a = 64, Ty = 50)
- inference_model.summary()
- x_initializer = np.zeros((1, 1, 78))
- a_initializer = np.zeros((1, n_a))
- c_initializer = np.zeros((1, n_a))
- pred = inference_model.predict([x_initializer, a_initializer, c_initializer])
这个 inference model 就是根据上面的训练来的 LSTM 来 predict 的, 它共用了上面训练得来的的 LSTM 中的参数 weights 和 bias, 根据输入的一个词 x0 来预测后面来输出哪些值, 具体输出多少个值也是根据用户设定的 Ty 来决定, 当然啦, 咱们还可以更加精细化的管理咱们的输出, 例如如果遇到 EOS, 咱们直接停止输出. 咱们即使有了前面的 LSTM, 但是因为结构的不同, 咱们还是得先去构建一个新的 inference model, 即重新要搭建一个 decoding 的结构. 从 decoding 的结构咱们可以看出来, 咱们的输入还是有三个, 即 x0,a0,c0. 这里有比 encoding 简单的地方就是咱们不需要再去 reshape 那么的输入了, 咱们的输入都是标准的 shape, 即分别是(batch_size, Tx, n_values), (batch_size, n_a), (batch_size, n_a), 咱们直接输入进去并且输入到 Lstm 和 densor 中就可以, 不需要进行一些 shape 方面的配置了, 其次这里有一点个 encoding 不一样的, 就是需要将每一个 time step 的输出当做下个 time step 的输入, 即上面代码中的 x=tf.keras.Lambda(one_hot)(out). 因为这是一个 inference model, 所以咱们也不需要重新 fitting 啦, 可以直接调用它的 predict 方法就可以 predict 啦.
总结
对于 sequence generation 相关的应用呢, 咱们首先要在脑海中找到这个 pattern, 即它是有 2 部分组成的, 一个 encoding, 一个 decoding; 然后用 encoding 来训练模型, 用 decoding 来 predict 模型. 对于输入的 input layer, 一定要注意并且理解他们 input data 的 shape, 一定要一致性; 对于一起 share 的变量一定要理解, 例如 LSTM_cell, densor 等, 他们都是构成这个 LSTM 模型的最基本的但愿, 都是 share 的, 并不是每一个 time step 都有独立的 entity. 如果对于以上的步骤和内容都理解的话, 对于 sequence generation 相关的应用就都可以套用上面的模式进行实现, 唯一需要改动的就是一下 dimension 值.
来源: https://www.cnblogs.com/tangxiaobo199181/p/12459428.html