1. 程式人生 > >用 TensorFlow 做個聊天機器人

用 TensorFlow 做個聊天機器人

上一次提到了不錯的學習聊天機器人的資源,不知道小夥伴們有沒有去學習呢。
自己動手做聊天機器人教程
我最近每天都會學一點,拿出解讀來和大家分享一下。

本文結構:

    1. 聊天機器人的架構簡圖
    1. 用 TensorFlow 實現 Chatbot 的模型
    1. 如何準備 chatbot 的訓練資料
    1. Chatbot 原始碼解讀

1. 聊天機器人的架構簡圖

聊天機器人的工作流程大體為:提問-檢索-答案抽取。

提問:就是要分析主人的問句中關鍵詞,提問型別,還有真正想知道的東西。

檢索:根據前一步的分析,去找答案。

答案抽取:找到的答案,並不能直接應用,還要整理成真正有用的,可以作為答案的回答。

涉及到的關鍵技術如圖中所示。

看不清圖的話,就是醬紫:

問句解析:
中文分詞、詞性標註、實體標註、概念類別標註、句法分析、語義分析、邏輯結構標註、指代消解、關聯關係標註、問句分類、答案類別確定;

海量文字知識表示:
網路文字資源獲取、機器學習方法、大規模語義計算和推理、知識表示體系、知識庫構建

答案生成與過濾:
候選答案抽取、關係推演、吻合程度判斷、噪聲過濾

2. 用 TensorFlow 實現 Chatbot 的模型

之前有根據 Siraj 的視訊寫過一篇《自己動手寫個聊天機器人吧》
文章裡只寫了主函式的簡單過程:Data-Model-Training,是用 Lua 實現的,詳細的程式碼可以去他的

github 上學習

下面這篇文章是用 TensorFlow + tflearn 庫 實現,在 建模, 訓練 和 預測 等環節可以學到更多細節:

兩篇的共同點是都用了 Seq2Seq 來實現。

LSTM的模型結構為:

細節的話可以直接去看上面那篇原文,這裡 po 出建立模型階段簡要的流程圖和過程描述:

  • 先將原始資料 300w chat 做一下預處理,即 切詞,分為 問答對。

  • 然後用 word2vec 訓練出詞向量,生成二進位制的詞向量檔案。

作為 Input data X 傳入下面流程:

  • question 進入 LSTM 的 encoder 環節,answer 進入 decoder 環節,

  • 分別生成 output tensor。

  • 其中 decoder 是一個詞一個詞的生成結果,將所有結果加入到一個 list 中。

  • 最後和 encoder 的輸出,一起做為下一環節 Regression 的輸入,並傳入 DNN 網路。

3. 如何準備 chatbot 的訓練資料

訓練資料的生成過程如下:

  • 首先在 input file 裡讀取每一行,並根據 ‘|’ 拆分成 question 和 answer 句子。
  • 每個句子,都將 word 通過 word2vec 轉化成詞向量。
  • 每一句的向量序列都轉化成相同維度的形式:self.word_vec_dim * self.max_seq_len
  • 最後 answer 構成了 y 資料,question+answer 構成了 xy 資料,再被投入到 model 中去訓練:
model.fit(trainXY, trainY, n_epoch=1000, snapshot_epoch=False, batch_size=1)

程式碼如下:

def init_seq(input_file):
    """讀取切好詞的文字檔案,載入全部詞序列
    """
    file_object = open(input_file, 'r')
    vocab_dict = {}
    while True:
        question_seq = []
        answer_seq = []
        line = file_object.readline()
        if line:
            line_pair = line.split('|')
            line_question = line_pair[0]
            line_answer = line_pair[1]
            for word in line_question.decode('utf-8').split(' '):
                if word_vector_dict.has_key(word):
                    question_seq.append(word_vector_dict[word])
            for word in line_answer.decode('utf-8').split(' '):
                if word_vector_dict.has_key(word):
                    answer_seq.append(word_vector_dict[word])
        else:
            break
        question_seqs.append(question_seq)
        answer_seqs.append(answer_seq)
    file_object.close()
def generate_trainig_data(self):
        xy_data = []
        y_data = []
        for i in range(len(question_seqs)):
            question_seq = question_seqs[i]
            answer_seq = answer_seqs[i]
            if len(question_seq) < self.max_seq_len and len(answer_seq) < self.max_seq_len:
                sequence_xy = [np.zeros(self.word_vec_dim)] * (self.max_seq_len-len(question_seq)) + list(reversed(question_seq))
                sequence_y = answer_seq + [np.zeros(self.word_vec_dim)] * (self.max_seq_len-len(answer_seq))
                sequence_xy = sequence_xy + sequence_y
                sequence_y = [np.ones(self.word_vec_dim)] + sequence_y
                xy_data.append(sequence_xy)
                y_data.append(sequence_y)
        return np.array(xy_data), np.array(y_data)

4. Chatbot 原始碼解讀

提煉出步驟如下:

其中 2. 準備資料, 3. 建立模型 就是上文著重說的部分。

    1. 引入包
    1. 準備資料
    1. 建立模型
    1. 訓練
    1. 預測

1. 引入包

import sys
import math
import tflearn
import tensorflow as tf
from tensorflow.python.ops import rnn_cell
from tensorflow.python.ops import rnn
import chardet
import numpy as np
import struct

2. 準備資料

def load_word_set()
將 3000 萬語料,分成 Question 和 Answer 部分,提取出 word。

def load_word_set():
    file_object = open('./segment_result_lined.3000000.pair.less', 'r')
    while True:
        line = file_object.readline()
        if line:
            line_pair = line.split('|')
            line_question = line_pair[0]
            line_answer = line_pair[1]
            for word in line_question.decode('utf-8').split(' '):
                word_set[word] = 1
            for word in line_answer.decode('utf-8').split(' '):
                word_set[word] = 1
        else:
            break
    file_object.close()

def load_vectors(input)
從 vectors.bin 載入詞向量,返回一個 word_vector_dict 的詞典,key 是詞,value 是200維的向量。

def init_seq(input_file)
將 Question 和 Answer 中單詞對應的詞向量放在詞向量序列中 question_seqs, answer_seqs

def init_seq(input_file):
    """讀取切好詞的文字檔案,載入全部詞序列
    """
    file_object = open(input_file, 'r')
    vocab_dict = {}
    while True:
        question_seq = []
        answer_seq = []
        line = file_object.readline()
        if line:
            line_pair = line.split('|')
            line_question = line_pair[0]
            line_answer = line_pair[1]
            for word in line_question.decode('utf-8').split(' '):
                if word_vector_dict.has_key(word):
                    question_seq.append(word_vector_dict[word])
            for word in line_answer.decode('utf-8').split(' '):
                if word_vector_dict.has_key(word):
                    answer_seq.append(word_vector_dict[word])
        else:
            break
        question_seqs.append(question_seq)
        answer_seqs.append(answer_seq)
    file_object.close()

def vector_sqrtlen(vector)
用來求向量的長度。

def vector_sqrtlen(vector):
    len = 0
    for item in vector:
        len += item * item
    len = math.sqrt(len)
    return len

def vector_cosine(v1, v2)
用來求兩個向量間的距離。

def vector_cosine(v1, v2):
    if len(v1) != len(v2):
        sys.exit(1)
    sqrtlen1 = vector_sqrtlen(v1)
    sqrtlen2 = vector_sqrtlen(v2)
    value = 0
    for item1, item2 in zip(v1, v2):
        value += item1 * item2
    return value / (sqrtlen1*sqrtlen2)

def vector2word(vector)
給定一個詞向量,去 word-vector 字典中查詢與此向量距離最近的向量,並記憶相應的單詞,返回單詞和 cosine 值。

def vector2word(vector):
    max_cos = -10000
    match_word = ''
    for word in word_vector_dict:
        v = word_vector_dict[word]
        cosine = vector_cosine(vector, v)
        if cosine > max_cos:
            max_cos = cosine
            match_word = word
    return (match_word, max_cos)

3. 建立模型

class MySeq2Seq(object)
在前兩篇筆記中單獨寫了這兩塊。

def generate_trainig_data(self)
question_seqs, answer_seqs 得到 xy_data 和 y_data 的形式。

def model(self, feed_previous=False)
用 input data 生成 encoder_inputs 和帶GO頭的 decoder_inputs
將 encoder_inputs 傳遞給編碼器,返回一個輸出(預測序列的第一個值)和一個狀態(傳給解碼器)。
在解碼器中,用編碼器的最後一個輸出作為第一個輸入,預測過程用前一個時間序的輸出作為下一個時間序的輸入。

4. 訓練

def train(self)
generate_trainig_data() 生成 X y 資料,傳遞給 上面定義的 model,並訓練 model.fit,再儲存。

    def train(self):
        trainXY, trainY = self.generate_trainig_data()
        model = self.model(feed_previous=False)
        model.fit(trainXY, trainY, n_epoch=1000, snapshot_epoch=False, batch_size=1)
        model.save('./model/model')
        return model

5. 預測

generate_trainig_data() 生成資料,用 model.predict 進行預測,predict 結果的每一個 sample 相當於一句話的詞向量序列,每個 sample 中的每個 vector 在 word-vector 字典中找到與其最近的向量,並返回對應的 word,及二者間的 cosine。

if __name__ == '__main__':
    phrase = sys.argv[1]
    if 3 == len(sys.argv):
        my_seq2seq = MySeq2Seq(word_vec_dim=word_vec_dim, max_seq_len=max_seq_len, input_file=sys.argv[2])
    else:
        my_seq2seq = MySeq2Seq(word_vec_dim=word_vec_dim, max_seq_len=max_seq_len)
    if phrase == 'train':
        my_seq2seq.train()
    else:
        model = my_seq2seq.load()
        trainXY, trainY = my_seq2seq.generate_trainig_data()
        predict = model.predict(trainXY)
        for sample in predict:
            print "predict answer"
            for w in sample[1:]:
                (match_word, max_cos) = vector2word(w)
                #if vector_sqrtlen(w) < 1:
                #    break
                print match_word, max_cos, vector_sqrtlen(w)

相關推薦

TensorFlow 聊天機器人

上一次提到了不錯的學習聊天機器人的資源,不知道小夥伴們有沒有去學習呢。 自己動手做聊天機器人教程 我最近每天都會學一點,拿出解讀來和大家分享一下。 本文結構: 聊天機器人的架構簡圖 用 TensorFlow 實現 Chatbot 的模型 如何準備 ch

Python一個聊天機器人

最近在使用騰訊語音合成時發現了一個有趣的東西:智慧閒聊 好奇之下點了進去,發現是一個智慧聊天的功能。然後就順勢根據這個api寫了一個簡單的聊天機器人。 好了,廢話不多說,下面來一步一步實現聊天機器人 1:在騰訊ai開放平臺建立一個應用。 2:獲得該應用的app_id

10行程式碼讓你秒變撩妹達人:Python一個聊天機器人

導讀:用Python做一個聊天機器人,這樣你就可以邊寫程式碼邊撩妹了~作者:大鄧來源:大鄧和他的

Avaya將在GITEX 2018上展示全球首聊天機器人社交平臺

阿聯酋迪拜--(美國商業資訊)--Avaya Holdings Corp.今天宣佈,該公司將在2018年海灣資訊科技展(GITEX)技術週上展示全球首個聊天機器人社交平臺,幫助實現客戶自助服務的巨大飛躍。與傳統社交媒體相似,Avaya的創新在於為機器人之間的安全互動提供一個結構化平臺,以擴充套件

(30)進階: jQuery 輪播吧

內容樣式行為分離 輪播初實現  谷歌    蘋果風格的輪播    dog small  CSS屬性     display: flex;   align-items:flex-start;

教你TensorFlow影象識別

弱者用淚水安慰自己,強者用汗水磨練自己。 上一篇文章裡面講了使用TensorFlow做手寫數字影象識別,這篇文章算是它的進階篇吧,在本篇文章中將會講解如何使用TensorFlow識別多種類圖片。本次使用的資料集是CIFAR-10,這是一個比較經典的資料集,可以去百度一下它的官網

室友玩掃雷通關炫耀?我Python十秒通關的程式迴應他!

  起因是這樣的,室友和我一起玩掃雷高難度,今天他來告訴我他的通關了! 各種炫耀,如下圖! 學習Python中有不明白推薦加入交流群                 號:96041

Python小遊戲:環境篇

一、安裝Python和pygame 1、在Windows環境下,安裝Python 略 2、安裝pygame,網址: http://pygame.org 使用Python自帶pip工具即可快速安裝pygame: python3 -m pip install -U py

Python微信秒回器,再也不怕捱罵啦!

在每次你玩遊戲玩的正嗨的時候,你女票突然發訊息給你怎麼辦?到底是該拋棄對於去回女票的訊息,還是選擇遊戲不理女票呢?假如你選擇了第二種,估計不是搓衣板,就是口紅、包包、衣服伺候了,所以在這種時候,你需要一個幫你秒回信息的神器了。   有想學Python或者對Python感興趣的老

PythonQQ郵箱定時傳送天氣預報給女神,教你呵護心愛的她!

  天氣突然降溫了,還下了雪,今天溫度更是到了零下2度。由於說什麼暖心的話不是我的特長,所以我就琢磨著給女神來點實際的!例如說提醒她哪天下雨阿、哪天會突然降溫阿,這樣她也能提前做點防範。於是我就利用Python寫了個小程式,由於技術有限,希望大佬勿噴!  

PythonQQ郵箱定時發送天氣預報給女神,教你呵護心愛的她!

pytho cap 預報 apt bfd atp 今天 身邊 朋友 天氣突然降溫了,還下了雪,今天溫度更是到了零下2度。由於說什麽暖心的話不是我的特長,所以我就琢磨著給女神來點實際的!例如說提醒她哪天下雨阿、哪天會突然降溫阿,這樣她也能提前做點防範。於是我就利用Py

動手JAVA小遊戲--貪吃蛇

轉眼在大學蹲了快三個春秋,在這幾年裡我可謂是經歷過了大學的“風風雨雨”,逃課、泡女、通宵打機......種種的種種!還有一年就畢業了,回首過去,說實在的還真有點後悔,畢竟看到別人被大公司提前錄用而自己還在碌碌無為在此我想給那些剛進大學的朋友一個忠告:大學真的真的不是給你來玩

TensorFlow過哪些有趣的嘗試?

TensorFlow等AI工具包的出現,讓程式設計師不掌握原理也能迅速學會機器學習或人工智慧技術的使用。 我曾經用TensorFlow分析A股上億條交易資料,嘗試在A股市場尋找一些確定性的規律知乎上的一名產品經理,使用TensorFlow和OpenCV通過人工神

通過攝像頭捕獲影象tensorflow手寫數字識別

花了一晚上搞好了攝像頭捕獲影象做手寫數字識別,程式碼基於tensorflow的mnist程式碼實現,作為學習tensorflow的一個過程。 先在mnist資料集上訓練好網路,並儲存模型。 import numpy as np import tensorflow as tf

python彈球遊戲(一)

用python  tkinter模組做一個擊打反彈球和球拍的遊戲。球在螢幕上飛,玩家需要把它擊打回去,只要球落到螢幕底部,遊戲就結束。 首先我們做一個在螢幕上到處移動的小球: #coding:utf-8 from tkinter import * import ra

Python小網站(MVC架構)

1. 基本結構,採用 MVC 模式。 控制器(controller)負責轉發請求,對請求進行處理檢視 (View): 介面設計人員進行圖形介面設計。模型 (Model): 程式設計師編寫程式應有的功能(

socket.io+angular.js+express.js聊天應用(三)

track xtran styles javascrip lin 應用 nag ive oct 版權聲明:本文為博主原創

socket.io+angular.js+express.js聊天應用(二)

text vertica cer htm javascrip right detail 轉載 fill 版權聲明:本文為

機器學習打造聊天機器人(三) 設計篇

本文是用機器學習打造聊天機器人系列的第三篇,通過閱讀本文你將對聊天機器人的實現有一個大致的思路。 我們的聊天機器人將具備什麼樣的特性? 使用者可以使用人類自然語言的方式來表達自己的意圖。 可以依據使用者的反饋進行線上增量學習,使用的越久,能回答得問題越多。 採用非侵入式設計,通過幾個簡單的API就可以接

機器學習打造聊天機器人(六) 原理篇

本文是用機器學習打造聊天機器人系列的第六篇,主要介紹程式碼中用到的相關演算法的原理。瞭解演算法原理,可以讓我們知道程式背後都做了些什麼,為什麼有時候會出現錯誤以及什麼場景下選擇哪種演算法會更合適。 word2vec 我們使用的詞向量模型就是基於word2vec訓練的,word2vec 是 Google