1. 程式人生 > 程式設計 >keras 簡單 lstm例項(基於one-hot編碼)

keras 簡單 lstm例項(基於one-hot編碼)

簡單的LSTM問題,能夠預測一句話的下一個字詞是什麼

固定長度的句子,一個句子有3個詞。

使用one-hot編碼

各種引用

import keras
from keras.models import Sequential
from keras.layers import LSTM,Dense,Dropout
import numpy as np

資料預處理

data = 'abcdefghijklmnopqrstuvwxyz'
data_set = set(data)
 
word_2_int = {b:a for a,b in enumerate(data_set)}
int_2_word = {a:b for a,b in enumerate(data_set)}
 
word_len = len(data_set)
print(word_2_int)
print(int_2_word)

一些輔助函式

def words_2_ints(words):
 ints = []
 for itmp in words:
  ints.append(word_2_int[itmp])
 return ints
 
print(words_2_ints('ab'))
 
def words_2_one_hot(words,num_classes=word_len):
 return keras.utils.to_categorical(words_2_ints(words),num_classes=num_classes)
print(words_2_one_hot('a'))
def get_one_hot_max_idx(one_hot):
 idx_ = 0
 max_ = 0
 for i in range(len(one_hot)):
  if max_ < one_hot[i]:
   max_ = one_hot[i]
   idx_ = i
 return idx_
 
def one_hot_2_words(one_hot):
 tmp = []
 for itmp in one_hot:
  tmp.append(int_2_word[get_one_hot_max_idx(itmp)])
 return "".join(tmp)
 
print( one_hot_2_words(words_2_one_hot('adhjlkw')) )

構造樣本

time_step = 3 #一個句子有3個詞
 
def genarate_data(batch_size=5,genarate_num=100):
 #genarate_num = -1 表示一直迴圈下去,genarate_num=1表示生成一個batch的資料,以此類推
 #這裡,我也不知道資料有多少,就這麼迴圈的生成下去吧。
 #入參batch_size 控制一個batch 有多少資料,也就是一次要yield進多少個batch_size的資料
 '''
 例如,一個batch有batch_size=5個樣本,那麼對於這個例子,需要yield進的資料為:
 abc->d
 bcd->e
 cde->f
 def->g
 efg->h
 然後把這些資料都轉換成one-hot形式,最終資料,輸入x的形式為:
 
 [第1個batch]
 [第2個batch]
 ...
 [第genarate_num個batch]
 
 每個batch的形式為:
 
 [第1句話(如abc)]
 [第2句話(如bcd)]
 ...
 每一句話的形式為:
 
 [第1個詞的one-hot表示]
 [第2個詞的one-hot表示]
 ...
 '''
 cnt = 0
 batch_x = []
 batch_y = []
 sample_num = 0
 while(True):
  for i in range(len(data) - time_step):
   batch_x.append(words_2_one_hot(data[i : i+time_step]))
   batch_y.append(words_2_one_hot(data[i+time_step])[0]) #這裡資料加[0],是為了符合keras的輸出資料格式。 因為不加[0],表示是3維的資料。 你可以自己嘗試不加0,看下面的test打印出來是什麼
   sample_num += 1
   #print('sample num is :',sample_num)
   if len(batch_x) == batch_size:
    yield (np.array(batch_x),np.array(batch_y))
    batch_x = []
    batch_y = []
    if genarate_num != -1:
     cnt += 1
 
    if cnt == genarate_num:
     return
   
for test in genarate_data(batch_size=3,genarate_num=1):
 print('--------x:')
 print(test[0])
 print('--------y:')
 print(test[1])

搭建模型並訓練

model = Sequential()
 
# LSTM輸出維度為 128
# input_shape控制輸入資料的形態
# time_stemp表示一句話有多少個單詞
# word_len 表示一個單詞用多少維度表示,這裡是26維
 
model.add(LSTM(128,input_shape=(time_step,word_len)))
model.add(Dense(word_len,activation='softmax')) #輸出用一個softmax,來分類,維度就是26,預測是哪一個字母
 
model.compile(loss='categorical_crossentropy',optimizer='rmsprop',metrics=['accuracy'])
 
model.fit_generator(generator=genarate_data(batch_size=5,genarate_num=-1),epochs=50,steps_per_epoch=10)
#steps_per_epoch的意思是,一個epoch中,執行多少個batch
#batch_size是一個batch中,有多少個樣本。
#所以,batch_size*steps_per_epoch就等於一個epoch中,訓練的樣本數量。(這個說法不對!再觀察看看吧)
#可以將epochs設定成1,或者2,然後在genarate_data中列印樣本序號,觀察到樣本總數。

使用訓練後的模型進行預測:

result = model.predict(np.array([words_2_one_hot('bcd')]))

print(one_hot_2_words(result))

可以看到,預測結果為

e

補充知識:訓練集產生的onehot編碼特徵如何在測試集、預測集復現

資料處理中有時要用到onehot編碼,如果使用pandas自帶的get_dummies方法,訓練集產生的onehot編碼特徵會跟測試集、預測集不一樣,正確的方式是使用sklearn自帶的OneHotEncoder。

程式碼

import pandas as pd
from sklearn.preprocessing import OneHotEncoder
ohe = OneHotEncoder(handle_unknown='ignore')
data_train=pd.DataFrame({'職業':['資料探勘工程師','資料庫開發工程師','資料分析師','資料分析師'],'籍貫':['福州','廈門','泉州','龍巖']})
ohe.fit(data_train)#訓練規則
feature_names=ohe.get_feature_names(data_train.columns)#獲取編碼後的特徵名
data_train_onehot=pd.DataFrame(ohe.transform(data_train).toarray(),columns=feature_names)#應用規則在訓練集上
 
data_new=pd.DataFrame({'職業':['資料探勘工程師','jave工程師'],'莆田']})
data_new_onehot=pd.DataFrame(ohe.transform(data_new).toarray(),columns=feature_names)#應用規則在預測集上

以上這篇keras 簡單 lstm例項(基於one-hot編碼)就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支援我們。