Keras实现seq2seq案例代码:Bi-LSTM
目錄
1. 案例介紹
2. 代碼實現
代碼一:為模型創建輸入
代碼二:構建模型
代碼三:檢驗模型性能
1. 案例介紹
?為便于講解seq2seq模型用例,我們采用一篇研究論文中所使用的注釋預料庫的文本內容。
論文:《Learning Phrase Representations using RNN Encoder–Decoder for Statistical Machine Translation》,即“開發基準語料庫,以支持從醫療病例報告中自動提取與藥物有關的不良反應”
詞向量模型:我們使用開源模型skip-gram,該模型由NLPLab(http://evexdb.org/pmresources/vec-spacemodels/wikipedia-pubmed-and-PMC-w2v.bin)提供,該模型對所有的PubMed摘要和PMC全文(408萬個單詞)進行了訓練。skip-gram模型的輸出是一個具有200維度的字向量集。
語料庫:論文中使用的ADE語料庫包括三個文件,DRUG-AE.rel、DRUG-DOSE.rel、DRUG-NEG.txt,我們將利用文件DRUG-AE.rel,其提供了藥物與不良反應之間的關系。DRUG-AE.rel文件的格式如下,列與列之間由管道分隔符“|”隔開:
列-1:PubMed-ID
列-2:句子
列-3:不良反應
列-4:不良反應在“文檔級別”的起始位移
列-5:不良反應在“文檔級別”的結束位移
列-6:藥物
列-7:藥物在“文檔級別”的起始位移
列-8:藥物在“文檔級別”的結束位移
2. 代碼實現
代碼一:為模型創建輸入
#!/usr/bin/env python3 # -*- coding:utf-8 -*- # Author: Hou-Hou""" 《deep learning for natural language processing creating neural networks with python》"""import re import numpy as npimport nltk from string import punctuation # 找出字符串中的所有的標點(針對英文) from gensim.models import KeyedVectorsimport keras import tensorflow import copy from keras.preprocessing.sequence import pad_sequences# 檢查版本 print(keras.__version__) # 2.2.4 print(tensorflow.__version__) # 1.7.0def create_input():# 加載預訓練的詞向量EMBEDDING_FILE = 'wikipedia-pubmed-and-PMC-w2v.bin'word2vec = KeyedVectors.load_word2vec_format(EMBEDDING_FILE,binary=True)print('Found %s word vectors of word2vec' % len(word2vec.vocab))TEXT_FILE = 'DRUG-AE.rel'# 為模型創建輸入f = open(TEXT_FILE, 'r')input_data_ae = []op_labels_ae = []sentences = []for each_line in f.readlines():sent_list = np.zeros([0, 200])labels = np.zeros([0, 3])tokens = each_line.split('|')sent = tokens[1]if sent in sentences:continuesentences.append(sent)begin_offset = int(tokens[3])end_offset = int(tokens[4])mid_offset = range(begin_offset+1, end_offset)word_tokens = nltk.word_tokenize(sent)offset = 0for each_token in word_tokens:offset = sent.find(each_token, offset)offset1 = copy.deepcopy(offset)offset += len(each_token)if each_token in punctuation or re.search(r'\d', each_token):continue # 若each_token為標點符號或數字,則跳過each_token = each_token.lower()each_token = re.sub("[^A-Za-z\-]+", "", each_token)if each_token in word2vec.wv.vocab:# 獲取訓練好后所有的詞:model.vocab或model.wv.vocabnew_word = word2vec.word_vec(each_token) # 若單詞在詞匯表中,將其轉換為向量if offset1 == begin_offset:sent_list = np.append(sent_list, np.array([new_word]), axis=0)labels = np.append(labels, np.array([[0,0,1]]), axis=0)elif offset == end_offset or offset in mid_offset:sent_list = np.append(sent_list, np.array([new_word]), axis=0)labels = np.append(labels, np.array([[0,1,0]]), axis=0)else:sent_list = np.append(sent_list, np.array([new_word]), axis=0)labels = np.append(labels, np.array([[1,0,0]]), axis=0)input_data_ae.append(sent_list)op_labels_ae.append(labels)input_data_ae = np.array(input_data_ae)op_labels_ae = np.array(op_labels_ae)# 給輸入文本添加填充項:最大長度為30input_data_ae = pad_sequences(input_data_ae, maxlen=30, dtype='float64', padding='post')op_labels_ae = pad_sequences(op_labels_ae, maxlen=30, dtype='float64', padding='post')return input_data_ae, op_labels_ae(1)copy.copy() 淺拷貝:拷貝了最外圍的對象本身,內部的元素都只是拷貝了一個引用而已。也就是,把對象復制一遍,但是該對象中引用的其他對象我不復制
? ? ? ? ?copy.deepcopy() 深拷貝:外圍和內部元素都進行了拷貝對象本身,而不是引用。也就是,把對象復制一遍,并且該對象中引用的其他對象我也復制
(2)find() 方法:檢測字符串中是否包含子字符串 str ,如果指定 beg(開始) 和 end(結束) 范圍,則檢查是否包含在指定范圍內。如果包含子字符串返回開始的索引值,否則返回 - 1。
(3)re.sub(pattern, repl, string, count=0, flags=0)
? ? ? ? ? ? ? ? pattern:表示正則表達式中的模式字符串;
? ? ? ? ? ? ? ? repl:被替換的字符串(既可以是字符串,也可以是函數);
? ? ? ? ? ? ? ? string:要被處理的,要被替換的字符串;
? ? ? ? ? ? ? ? count:匹配的次數, 默認是全部替換
代碼二:構建模型
? ? ? 定義模型體系結構,我們使用雙向LSTM網絡的一個隱藏層,它有300個隱藏單元;除此之外,還使用一個時間分布稠密層,將在每個時間步上應用一個全連接的稠密層,按時間步分別得到輸出。
#!/usr/bin/env python3 # -*- coding:utf-8 -*- # Author: Hou-Houimport datetime import os from keras.layers import Dense, Input, LSTM, Dropout,Bidirectional, TimeDistributed from keras.models import Model from keras.layers.normalization import BatchNormalization from keras.callbacks import EarlyStopping, ModelCheckpointfrom create_input import *input_data_ae, op_labels_ae = create_input()# 創建訓練、驗證數據集:訓練=4000, 驗證=271 x_train = input_data_ae[:4000] x_test = input_data_ae[4000:] y_train = input_data_ae[:4000] y_test = input_data_ae[4000:]batch = 1# 創建網絡結構 def build_model():xin = Input(batch_shape=(None, 30, 200), dtype='float')seq = Bidirectional(LSTM(300, return_state=True), merge_mode='concat')(xin)# 雙向RNN包裝器,merge_mode:前向和后向RNN輸出的結合方式mlp1 = Dropout(0.2)(seq)mlp2 = TimeDistributed(Dense(60, activation='softmax'))(mlp1) # 該包裝器可以把一個層應用到輸入的每一個時間步上mlp3 = Dropout(0.2)(mlp2)mlp4 = TimeDistributed(Dense(3, activation='softmax'))(mlp3)model = Model(inputs=xin, outputs=mlp4)model.compile(optimizer='Adam', loss='categorical_crossentropy')# 訓練model.fit(x_train, y_train,batch_size=batch,epochs=50,validation_data=(x_test, y_test))save_fname = os.path.join('./', '%s-e%s-3.h5' % (datetime.datetime.now().strftime('%Y%m%d-%H%M%S'), str(50)))model.save(save_fname)return modelmodel = build_model()# 預測 val_pred = model.predict(x_test, batch_size=batch) labels = [] for i in range(len(val_pred)):b = np.zeros_like(val_pred[i])b[np.arange(len(val_pred[i])), val_pred[i].argmax(1)]=1labels.append(b) print('val_pred=', val_pred.shape)訓練結果:
?
代碼三:檢驗模型性能
# 檢驗模型性能 from sklearn.metrics import f1_score, precision_score, recall_scorescore = [] f1 = [] precision = [] recall = [] point=[]for i in range(len(y_test)):if(f1_score(labels[i], y_test[i], average='weighted')>0.6):point.append(i)score.append(f1_score(labels[i], y_test[i], average='weighted'))precision.append(precision_score(labels[i], y_test[i], average='weighted'))recall.append(recall_score(labels[i], y_test[i], average='weighted'))print(len(point)/len(labels)*100) print(np.mean(score)) print(np.mean(precision)) print(np.mean(recall))輸出結果:
?
完!?
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結
以上是生活随笔為你收集整理的Keras实现seq2seq案例代码:Bi-LSTM的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Keras学习代码—github官网ex
- 下一篇: tf.name_scope()与tf.v