LSTM在機器學習上面的應用是很是普遍的,從股票分析,機器翻譯 到 語義分析等等各個方面都有它的用武之地,通過前面的對於LSTM結構的分析,這一節主要介紹一些LSTM的一個小應用,那就是sequence generation。其實sequence generation本事也是對一些應用的統稱,例如: 讓機器學習音樂後而後讓機器根據學習的模型本身創造音樂(製做人快要失業啦。。。。),讓機器學習某種語言而後讓這個學習到的模型本身產生Word來講話,等等。這其實本質是一種one-to-many的LSTM網絡結構。這一節內容主要就是講解這一種網絡結構的應用。網絡
在我們實際實施而且寫代碼以前,我們首要的任務是如何搭建一個sequence generation的網絡結構。一個sequence generation的網絡結構其實也是分爲兩個部分,第一部分是encoding (modeling),也就是我們建模的網絡,它是一個many-to-many的網絡結構;第二部分是decoding的過程,它是一個one-to-many的結構。那麼具體這個網絡結構是什麼樣呢?我們看看下面的圖片app
上面的圖片展現的就是一個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是由兩個部分組成,那麼天然我們代碼也確定得分紅兩部分來實現上圖中的網絡結構,那麼接下來我們來看看第一步,就是如何用Python來實現encoding的結構,代碼以下所示,我們看着代碼來慢慢分析:ide
#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啦,我們仍是看下面的代碼,而後慢慢分析oop
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))this
pred = inference_model.predict([x_initializer, a_initializer, c_initializer])spa
這個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值。code