2019年6月9日 星期日

[自然語言] 文字嵌入(word embedding)法在機器情感判別的實例---IMDB影評分類

文字嵌入法(token embedding):

相較於one-hot encoding的二進位稀疏向量(大部分由0組成)且具有非常高維度特性; token embedding取得的是低維度的浮點數向量,適用於20000個以上的單字處理
有兩種方法建立文字嵌入向量:
  1. 用Embedding layer學習文字嵌入向量
  2. 用其他machine learning已經建立好的文字嵌入向量

實際案例:
下載IMDB的影評的[文字]與[評價(值得看(1)or不值得看(0))],並用Keras建立模型

方法:
  1. 將下載的檔案解壓縮,資料夾分成training, test; training和test資料夾內又有pos和neg資料夾分別儲存正面和負面的文字檔.
  2. 依序打開文字檔,並把它讀入變成陣列
  3. 把文字陣列用keras.preprocessing.text.Tokenizer轉換成數字陣列
  4. 把不足100個元素的陣列補成長度為100的陣列
  5. 建立Keras模型
  6. 視覺化訓練過程
  7. 測試模型的準確度
  8. 儲存模型
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]

三倍槓桿和一倍槓桿的長期定期定額報酬率分析

  以下是中國,美國股票債卷的三倍槓桿和一倍槓桿ETF分析.可以發現,三倍槓桿在下跌時期的跌幅遠比一倍槓桿的多 .且從時間軸來看,三倍槓桿由於下跌力道較強,因此會把之前的漲幅都吃掉,所以對於長期上身的市場,例如美國科技股,由於上升時間遠比下跌時間長,所以持有TQQQ的長期回報率會...