文字嵌入法(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]



