建立網(wǎng)站如何推廣東莞優(yōu)化疫情防控措施
文章目錄
- 0 簡(jiǎn)介
- 1 項(xiàng)目架構(gòu)
- 2 項(xiàng)目的主要過程
- 2.1 數(shù)據(jù)清洗、預(yù)處理
- 2.2 分桶
- 2.3 訓(xùn)練
- 3 項(xiàng)目的整體結(jié)構(gòu)
- 4 重要的API
- 4.1 LSTM cells部分:
- 4.2 損失函數(shù):
- 4.3 搭建seq2seq框架:
- 4.4 測(cè)試部分:
- 4.5 評(píng)價(jià)NLP測(cè)試效果:
- 4.6 梯度截?cái)?#xff0c;防止梯度爆炸
- 4.7 模型保存
- 5 重點(diǎn)和難點(diǎn)
- 5.1 函數(shù)
- 5.2 變量
- 6 相關(guān)參數(shù)
- 7 桶機(jī)制
- 7.1 處理數(shù)據(jù)集
- 7.2 詞向量處理seq2seq
- 7.3 處理問答及答案權(quán)重
- 7.4 訓(xùn)練&保存模型
- 7.5 載入模型&測(cè)試
- 8 最后
0 簡(jiǎn)介
🔥 優(yōu)質(zhì)競(jìng)賽項(xiàng)目系列,今天要分享的是
基于深度學(xué)習(xí)的中文對(duì)話問答機(jī)器人
該項(xiàng)目較為新穎,適合作為競(jìng)賽課題方向,學(xué)長(zhǎng)非常推薦!
🧿 更多資料, 項(xiàng)目分享:
https://gitee.com/dancheng-senior/postgraduate
1 項(xiàng)目架構(gòu)
整個(gè)項(xiàng)目分為 數(shù)據(jù)清洗 和 建立模型兩個(gè)部分。
(1)主要定義了seq2seq這樣一個(gè)模型。
首先是一個(gè)構(gòu)造函數(shù),在構(gòu)造函數(shù)中定義了這個(gè)模型的參數(shù)。
以及構(gòu)成seq2seq的基本單元的LSTM單元是怎么構(gòu)建的。
(2)接著在把這個(gè)LSTM間單元構(gòu)建好之后,加入模型的損失函數(shù)。
我們這邊用的損失函數(shù)叫sampled_softmax_loss,這個(gè)實(shí)際上就是我們的采樣損失。做softmax的時(shí)候,我們是從這個(gè)6000多維里邊找512個(gè)出來做采樣。
損失函數(shù)做訓(xùn)練的時(shí)候需要,測(cè)試的時(shí)候不需要。訓(xùn)練的時(shí)候,y值是one_hot向量
(3)然后再把你定義好的整個(gè)的w[512*6000]、b[6000多維],還有我們的這個(gè)cell本身,以及我們的這個(gè)損失函數(shù)一同代到我們這個(gè)seq2seq模型里邊。然后呢,這樣的話就構(gòu)成了我們這樣一個(gè)seq2seq模型。
函數(shù)是tf.contrib.legacy_seq2seq.embedding_attention_seq2seq()
(4)最后再將我們傳入的實(shí)參,也就是三個(gè)序列,經(jīng)過這個(gè)桶的篩選。然后放到這個(gè)模型去訓(xùn)練啊,那么這個(gè)模型就會(huì)被訓(xùn)練好。到后面,我們可以把我們這個(gè)模型保存在model里面去。模型參數(shù)195M。做桶的目的就是節(jié)約計(jì)算資源。
2 項(xiàng)目的主要過程
前提是一問一答,情景對(duì)話,不是多輪對(duì)話(比較難,但是熱門領(lǐng)域)
整個(gè)框架第一步:做語(yǔ)料
先拿到一個(gè)文件,命名為.conv(只要不命名那幾個(gè)特殊的,word等)。輸入目錄是db,輸出目錄是bucket_dbs,不存在則新建目錄。
測(cè)試的時(shí)候,先在控制臺(tái)輸入一句話,然后將這句話通過正反向字典Ids化,然后去桶里面找對(duì)應(yīng)的回答的每一個(gè)字,然后將輸出通過反向字典轉(zhuǎn)化為漢字。
2.1 數(shù)據(jù)清洗、預(yù)處理
讀取整個(gè)語(yǔ)料庫(kù),去掉E、M和空格,還原成原始文本。創(chuàng)建conversion.db,conversion表,兩個(gè)字段。每取完1000組對(duì)話,插入依次數(shù)據(jù)庫(kù),批量提交,通過cursor.commit.
2.2 分桶
從總的conversion.db中分桶,指定輸入目錄db, 輸出目錄bucket_dbs.
檢測(cè)文字有效性,循環(huán)遍歷,依次記錄問題答案,每積累到1000次,就寫入數(shù)據(jù)庫(kù)。
?
for ask, answer in tqdm(ret, total=total):if is_valid(ask) and is_valid(answer):for i in range(len(buckets)):encoder_size, decoder_size = buckets[i]if len(ask) <= encoder_size and len(answer) < decoder_size:word_count.update(list(ask))word_count.update(list(answer))wait_insert.append((encoder_size, decoder_size, ask, answer))if len(wait_insert) > 10000000:wait_insert = _insert(wait_insert)break
將字典維度6865未,投影到100維,也就是每個(gè)字是由100維的向量組成的。后面的隱藏層的神經(jīng)元的個(gè)數(shù)是512,也就是維度。
句子長(zhǎng)度超過桶長(zhǎng),就截?cái)嗷蛑苯觼G棄。
四個(gè)桶是在read_bucket_dbs()讀取的方法中創(chuàng)建的,讀桶文件的時(shí)候,實(shí)例化四個(gè)桶對(duì)象。
2.3 訓(xùn)練
先讀取json字典,加上pad等四個(gè)標(biāo)記。
lstm有兩層,attention在解碼器的第二層,因?yàn)榈诙硬攀莑stm的輸出,用兩層提取到的特征越好。
num_sampled=512, 分批softmax的樣本量(
訓(xùn)練和測(cè)試差不多,測(cè)試只前向傳播,不反向更新
3 項(xiàng)目的整體結(jié)構(gòu)
s2s.py:相當(dāng)于main函數(shù),讓代碼運(yùn)行起來
里面有train()、test()、test_bleu()和create_model()四個(gè)方法,還有FLAGS成員變量,
相當(dāng)于靜態(tài)成員變量 public static final string
decode_conv.py和data_utils.py:是數(shù)據(jù)處理
s2s_model.py:
里面放的是模型
里面有init()、step()、get_batch_data()和get_batch()四個(gè)方法。構(gòu)造方法傳入構(gòu)造方法的參數(shù),搭建S2SModel框架,然后sampled_loss()和seq2seq_f()兩個(gè)方法
data_utils.py:
讀取數(shù)據(jù)庫(kù)中的文件,并且構(gòu)造正反向字典。把語(yǔ)料分成四個(gè)桶,目的是節(jié)約計(jì)算資源。先轉(zhuǎn)換為db\conversation.db大的桶,再分成四個(gè)小的桶。buckets
= [ (5, 15), (10, 20), (15, 25), (20, 30)]
比如buckets[1]指的就是(10, 20),buckets[1][0]指的就是10。
bucket_id指的就是0,1,2,3
dictionary.json:
是所有數(shù)字、字母、標(biāo)點(diǎn)符號(hào)、漢字的字典,加上生僻字,以及PAD、EOS、GO、UNK 共6865維度,輸入的時(shí)候會(huì)進(jìn)行詞嵌入word
embedding成512維,輸出時(shí),再轉(zhuǎn)化為6865維。
model:
文件夾下裝的是訓(xùn)練好的模型。
也就是model3.data-00000-of-00001,這個(gè)里面裝的就是模型的參數(shù)
執(zhí)行model.saver.restore(sess, os.path.join(FLAGS.model_dir,
FLAGS.model_name))的時(shí)候,才是加載目錄本地的保存的模型參數(shù)的過程,上面建立的模型是個(gè)架子,
model = create_model(sess, True),這里加載模型比較耗時(shí),時(shí)間復(fù)雜度最高
dgk_shooter_min.conv:
是語(yǔ)料,形如: E
M 畹/華/吾/侄/
M 你/接/到/這/封/信/的/時(shí)/候/
decode_conv.py: 對(duì)語(yǔ)料數(shù)據(jù)進(jìn)行預(yù)處理
config.json:是配置文件,自動(dòng)生成的
4 重要的API
4.1 LSTM cells部分:
?
cell = tf.contrib.rnn.BasicLSTMCell(size)cell = tf.contrib.rnn.DropoutWrapper(cell, output_keep_prob=dropout)cell = tf.contrib.rnn.MultiRNNCell([cell] * num_layers)對(duì)上一行的cell去做Dropout的,在外面裹一層DropoutWrapper
構(gòu)建雙層lstm網(wǎng)絡(luò),只是一個(gè)雙層的lstm,不是雙層的seq2seq
4.2 損失函數(shù):
?
tf.nn.sampled_softmax_loss( weights=local_w_t,
b labels=labels, #真實(shí)序列值,每次一個(gè)
inputs=loiases=local_b,
cal_inputs, #預(yù)測(cè)出來的值,y^,每次一個(gè)
num_sampled=num_samples, #512
num_classes=self.target_vocab_size # 原始字典維度6865)
4.3 搭建seq2seq框架:
tf.contrib.legacy_seq2seq.embedding_attention_seq2seq(encoder_inputs, # tensor of input seq 30decoder_inputs, # tensor of decoder seq 30tmp_cell, #自定義的cell,可以是GRU/LSTM, 設(shè)置multilayer等num_encoder_symbols=source_vocab_size,# 編碼階段字典的維度6865num_decoder_symbols=target_vocab_size, # 解碼階段字典的維度 6865embedding_size=size, # embedding 維度,512num_heads=20, #選20個(gè)也可以,精確度會(huì)高點(diǎn),num_heads就是attention機(jī)制,選一個(gè)就是一個(gè)head去連,5個(gè)就是5個(gè)頭去連output_projection=output_projection,# 輸出層。不設(shè)定的話輸出維數(shù)可能很大(取決于詞表大小),設(shè)定的話投影到一個(gè)低維向量feed_previous=do_decode,# 是否執(zhí)行的EOS,是否允許輸入中間cdtype=dtype)
4.4 測(cè)試部分:
?
self.outputs, self.losses = tf.contrib.legacy_seq2seq.model_with_buckets(
self.encoder_inputs,
self.decoder_inputs,
targets,
self.decoder_weights,
buckets,
lambda x, y: seq2seq_f(x, y, True),
softmax_loss_function=softmax_loss_function
)
4.5 評(píng)價(jià)NLP測(cè)試效果:
在nltk包里,有個(gè)接口叫bleu,可以評(píng)估測(cè)試結(jié)果,NITK是個(gè)框架
?
from nltk.translate.bleu_score import sentence_bleu
score = sentence_bleu(
references,#y值
list(ret),#y^
weights=(1.0,)#權(quán)重為1
)
4.6 梯度截?cái)?#xff0c;防止梯度爆炸
?
clipped_gradients, norm = tf.clip_by_global_norm(gradients,max_gradient_norm)
tf.clip_by_global_norm(t_list, clip_norm, use_norm=None, name=None)
通過權(quán)重梯度的總和的比率來截取多個(gè)張量的值。t_list是梯度張量, clip_norm是截取的比率,這個(gè)函數(shù)返回截取過的梯度張量和一個(gè)所有張量的全局范數(shù)
4.7 模型保存
?
tf.train.Saver(tf.global_variables(), write_version=tf.train.SaverDef.V2)
5 重點(diǎn)和難點(diǎn)
5.1 函數(shù)
?
def get_batch_data(self, bucket_dbs, bucket_id):
def get_batch(self, bucket_dbs, bucket_id, data):
def step(self,session,encoder_inputs,decoder_inputs,decoder_weights,bucket_id):
5.2 變量
?
batch_encoder_inputs, batch_decoder_inputs, batch_weights = [], [], []
6 相關(guān)參數(shù)
?
model = s2s_model.S2SModel(data_utils.dim, # 6865,編碼器輸入的語(yǔ)料長(zhǎng)度data_utils.dim, # 6865,解碼器輸出的語(yǔ)料長(zhǎng)度buckets, # buckets就是那四個(gè)桶,data_utils.buckets,直接在data_utils寫的一個(gè)變量,就能直接被點(diǎn)出來FLAGS.size, # 隱層神經(jīng)元的個(gè)數(shù)512FLAGS.dropout, # 隱層dropout率,dropout不是lstm中的,lstm的幾個(gè)門里面不需要dropout,沒有那么復(fù)雜。是隱層的dropoutFLAGS.num_layers, # lstm的層數(shù),這里寫的是2FLAGS.max_gradient_norm, # 5,截?cái)嗵荻?#xff0c;防止梯度爆炸FLAGS.batch_size, # 64,等下要重新賦值,預(yù)測(cè)就是1,訓(xùn)練就是64FLAGS.learning_rate, # 0.003FLAGS.num_samples, # 512,用作負(fù)采樣forward_only, #只傳一次dtype){"__author__": "qhduan@memect.co","buckets": [[5, 15],[10, 20],[20, 30],[40, 50]],"size": 512,/*s2s lstm單元出來之后的,連的隱層的number unit是512*/"depth": 4,"dropout": 0.8,"batch_size": 512,/*每次往里面放多少組對(duì)話對(duì),這個(gè)是比較靈活的。如果找一句話之間的相關(guān)性,batch_size就是這句話里面的字有多少個(gè),如果要找上下文之間的對(duì)話,batch_size就是多少組對(duì)話*/"random_state": 0,"learning_rate": 0.0003,/*總共循環(huán)20次*/"epoch": 20,"train_device": "/gpu:0","test_device": "/cpu:0"}
7 桶機(jī)制
7.1 處理數(shù)據(jù)集
語(yǔ)料庫(kù)長(zhǎng)度桶結(jié)構(gòu)
(5, 10): 5問題長(zhǎng)度,10回答長(zhǎng)度
每個(gè)桶中對(duì)話數(shù)量,一問一答為一次完整對(duì)話
Analysis
(1) 設(shè)定4個(gè)桶結(jié)構(gòu),即將問答分成4個(gè)部分,每個(gè)同種存放對(duì)應(yīng)的問答數(shù)據(jù)集[87, 69, 36,
8]四個(gè)桶中分別有87組對(duì)話,69組對(duì)話,36組對(duì)話,8組對(duì)話;
(2) 訓(xùn)練詞數(shù)據(jù)集符合桶長(zhǎng)度則輸入對(duì)應(yīng)值,不符合桶長(zhǎng)度,則為空;
(3) 對(duì)話數(shù)量占比:[0.435, 0.78, 0.96, 1.0];
7.2 詞向量處理seq2seq
獲取問答及答案權(quán)重
參數(shù):
- data: 詞向量列表,如[[[4,4],[5,6,8]]]
- bucket_id: 桶編號(hào),值取自桶對(duì)話占比
步驟:
- 問題和答案的數(shù)據(jù)量:桶的話數(shù)buckets = [(5, 10), (10, 15), (20, 25), (40, 50)]
- 生成問題和答案的存儲(chǔ)器
- 從問答數(shù)據(jù)集中隨機(jī)選取問答
- 問題末尾添加PAD_ID并反向排序
- 答案添加GO_ID和PAD_ID
- 問題,答案,權(quán)重批量數(shù)據(jù)
- 批量問題
- 批量答案
- 答案權(quán)重即Attention機(jī)制
- 若答案為PAD則權(quán)重設(shè)置為0,因?yàn)槭翘砑拥腎D,其他的設(shè)置為1
Analysis
-
(1) 對(duì)問題和答案的向量重新整理,符合桶尺寸則保持對(duì)話尺寸,若不符合桶設(shè)定尺寸,則進(jìn)行填充處理,
問題使用PAD_ID填充,答案使用GO_ID和PAD_ID填充; -
(2) 對(duì)問題和答案向量填充整理后,使用Attention機(jī)制,對(duì)答案進(jìn)行權(quán)重分配,答案中的PAD_ID權(quán)重為0,其他對(duì)應(yīng)的為1;
-
(3) get_batch()處理詞向量;返回問題、答案、答案權(quán)重?cái)?shù)據(jù);
返回結(jié)果如上結(jié)果:encoder_inputs, decoder_inputs, answer_weights.
7.3 處理問答及答案權(quán)重
?
參數(shù):session: tensorflow 會(huì)話.encoder_inputs: 問題向量列表decoder_inputs: 回答向量列表answer_weights: 答案權(quán)重列表bucket_id: 桶編號(hào)which bucket of the model to use.forward_only: 前向或反向運(yùn)算標(biāo)志位
返回:一個(gè)由梯度范數(shù)組成的三重范數(shù)(如果不使用反向傳播,則為無)。平均困惑度和輸出
Analysis
-
(1) 根據(jù)輸入的問答向量列表,分配語(yǔ)料桶,處理問答向量列表,并生成新的輸入字典(dict), input_feed = {};
-
(2) 輸出字典(dict), ouput_feed = {},根據(jù)是否使用反向傳播獲得參數(shù),使用反向傳播,
output_feed存儲(chǔ)更新的梯度范數(shù),損失,不使用反向傳播,則只存儲(chǔ)損失; -
(3) 最終的輸出為分兩種情況,使用反向傳播,返回梯度范數(shù),損失,如反向傳播不使用反向傳播,
返回?fù)p失和輸出的向量(用于加載模型,測(cè)試效果),如前向傳播;
7.4 訓(xùn)練&保存模型
步驟:
-
檢查是否有已存在的訓(xùn)練模型
-
有模型則獲取模型輪數(shù),接著訓(xùn)練
-
沒有模型則從開始訓(xùn)練
-
一直訓(xùn)練,每過一段時(shí)間保存一次模型
-
如果模型沒有得到提升,減小learning rate
-
保存模型
-
使用測(cè)試數(shù)據(jù)評(píng)估模型
global step: 500, learning rate: 0.5, loss: 2.574068747580052 bucket id: 0, eval ppx: 14176.588030763274 bucket id: 1, eval ppx: 3650.0026667220773 bucket id: 2, eval ppx: 4458.454110999805 bucket id: 3, eval ppx: 5290.083583183104
7.5 載入模型&測(cè)試
(1) 該聊天機(jī)器人使用bucket桶結(jié)構(gòu),即指定問答數(shù)據(jù)的長(zhǎng)度,匹配符合的桶,在桶中進(jìn)行存取數(shù)據(jù);
(2) 該seq2seq模型使用Tensorflow時(shí),未能建立獨(dú)立標(biāo)識(shí)的圖結(jié)構(gòu),在進(jìn)行后臺(tái)封裝過程中出現(xiàn)圖為空的現(xiàn)象;
?
從main函數(shù)進(jìn)入test()方法。先去內(nèi)存中加載訓(xùn)練好的模型model,這部分最耗時(shí),改batch_size為1,傳入相關(guān)的參數(shù)。開始輸入一個(gè)句子,并將它讀進(jìn)來,讀進(jìn)來之后,按照桶將句子分,按照模型輸出,然后去查字典。接著在循環(huán)中輸入上句話,找對(duì)應(yīng)的桶。然后拿到的下句話的每個(gè)字,找概率最大的那個(gè)字的index的id輸出。get_batch_data(),獲取data [('天氣\n', '')],也就是問答對(duì),但是現(xiàn)在只有問,沒有答get_batch()獲取encoder_inputs=1*10,decoder_inputs=1*20 decoder_weights=1*20step()獲取預(yù)測(cè)值output_logits,
8 最后
🧿 更多資料, 項(xiàng)目分享:
https://gitee.com/dancheng-senior/postgraduate