文字嵌入法(token embedding):
相較於one-hot encoding的二進位稀疏向量(大部分由0組成)且具有非常高維度特性; token embedding取得的是低維度的浮點數向量,適用於20000個以上的單字處理
有兩種方法建立文字嵌入向量:
- 用Embedding layer學習文字嵌入向量
- 用其他machine learning已經建立好的文字嵌入向量
實際案例:
下載IMDB的影評的[文字]與[評價(值得看(1)or不值得看(0))],並用Keras建立模型
方法:
- 將下載的檔案解壓縮,資料夾分成training, test; training和test資料夾內又有pos和neg資料夾分別儲存正面和負面的文字檔.
- 依序打開文字檔,並把它讀入變成陣列
- 把文字陣列用keras.preprocessing.text.Tokenizer轉換成數字陣列
- 把不足100個元素的陣列補成長度為100的陣列
- 建立Keras模型
- 視覺化訓練過程
- 測試模型的準確度
- 儲存模型
import urllib.request import os import tarfile import numpy as np url='http://ai.stanford.edu/~amaas/data/sentiment/aclImdb_v1.tar.gz' filepath='data/aclImdb_v1.tar.gz' #下載壓縮檔案 if not os.path.isfile(filepath): result=urllib.request.urlretrieve(url,filepath) print('download',result) #解壓檔案 if not os.path.exists('data/aclImdb'): tfile=tarfile.open(filepath,'r:gz') result=tfile.extractall('data/') from keras.preprocessing import sequence #匯入把陣列補齊的module from keras.preprocessing.text import Tokenizer #匯入建立字典的module import re #匯入處理文字的module def rm_tags(text): re_tag=re.compile(r'<[^>]+>') return re_tag.sub('',text) #整理資料夾的檔案文字成陣列輸出 import os def read_files(filetype): path='data/aclImdb/' file_list=[] positive_path=path+filetype+'/pos/' for f in os.listdir(positive_path): file_list+=[positive_path+f] negative_path=path+filetype+'/neg/' for f in os.listdir(negative_path): file_list+=[negative_path+f] print('read',filetype,'files:',len(file_list)) all_labels=[1]*12500+[0]*12500 all_texts=[] for fi in file_list: with open(fi,encoding='utf8') as file_input: all_texts += [rm_tags(''.join(file_input.readlines()))] return all_labels,all_texts y_train,train_text=read_files('train') y_test,test_text=read_files('test') #建立字典Token token=Tokenizer(num_words=2000) token.fit_on_texts(train_text) print(token.word_index) #把影評轉換成數字 x_train_seq=token.texts_to_sequences(train_text) x_test_seq=token.texts_to_sequences(test_text) #把每一筆數字list的長度都設成100,不足100的補0 x_train=sequence.pad_sequences(x_train_seq,maxlen=100) x_test=sequence.pad_sequences(x_test_seq,maxlen=100) #建立模型 #使用Embedding把數字list轉乘向量list from keras.models import Sequential from keras.layers import Dense, Dropout, Activation, Flatten,SimpleRNN from keras.layers.embeddings import Embedding model=Sequential() model.add(Embedding(output_dim=32,input_dim=2000,input_length=100)) #output_dim: 輸出維度; input_dim: 字典數; input_length: 輸入每陣列長度 model.add(Dropout(0.2)) #embedding嵌入向量是3D向量,需要用Flatten轉換為2D向量 (第0軸不變,第1軸為其他維度相乘) model.add(Flatten()) model.add(Dense(units=256,activation='relu')) model.add(Dropout(0.25)) model.add(Dense(units=1,activation='sigmoid')) model.summary()
model.compile(loss='binary_crossentropy', optimizer='adam',metrics=['accuracy']) train_history=model.fit(x_train,y_train, validation_split=0.1, epochs=30,batch_size=30,verbose=2) #視覺化訓練過程 import matplotlib.pyplot as plt def show_train_history(train_history,train,validation): plt.plot(train_history.history[train]) plt.plot(train_history.history[validation]) plt.title('Train History') plt.ylabel(train) plt.xlabel('Epoch') plt.legend(['train','validation'],loc='upper left') plt.show() show_train_history(train_history,'acc','val_acc') #若訓練(train)的準確度一直增加而驗證(validation)的準確度沒有一直增加則可能是overfit
#儲存keras model model.save('my_model.h5') #刪除載入的keras model del model from keras.models import load_model model = load_model('my_model.h5') model.summary()
#測試keras模型的準確度 y_test=np.transpose(y_test) scores=model.evaluate(x_test,y_test,verbose=1) #取得測試準確度 scores[1] #Add RNN model insize #建立模型 #使用Embedding把數字list轉乘向量list from keras.models import Sequential from keras.layers import Dense, Dropout, Activation, Flatten from keras.layers.embeddings import Embedding model=Sequential() model.add(Embedding(output_dim=32,input_dim=2000,input_length=100)) model.add(Dropout(0.2)) model.add(SimpleRNN(units=16)) #model.add(Flatten()) model.add(Dense(units=256,activation='relu')) model.add(Dropout(0.25)) model.add(Dense(units=1,activation='sigmoid')) model.compile(loss='binary_crossentropy', optimizer='adam',metrics=['accuracy']) train_history=model.fit(x_train,y_train, validation_split=0.1, epochs=30,batch_size=30,verbose=2) (train_history,'acc','val_acc') #若訓練(train)的準確度一直增加而驗證(validation)的準確度沒有一直增加則可能是overfit
#儲存keras model model.save('my_model_RNN.h5') scores=model.evaluate(x_test,y_test,verbose=1) scores[1]