1. 程式人生 > >三十五、一個lstm單元讓聊天機器人學會甄嬛體

三十五、一個lstm單元讓聊天機器人學會甄嬛體


當今比較流行的seq2seq基本都是用lstm組成的編碼器解碼器模型實現,開源的實現大都基於one-hot的embedding(沒有詞向量表達的資訊量大),因此打算自己實現一個基於word2vec詞向量的強大的seq2seq模型,首先實現了只有一個lstm單元的機器人

下載《甄嬛傳》小說原文

上網隨便百度一個“甄嬛傳 txt”,下載下來,首先要把檔案轉碼成utf-8編碼,然後要把windows的回車符都替換成\n,以便後續處理,最終效果如下:

[root@centos $] head zhenhuanzhuan.txt
序文--不過是「情」

    在鍵盤上敲落一個個文字的時候,窗外有大雨過後的清新。站在十二樓的落地玻璃窗前往外看,有大片大片開闊的深綠蔓延。

  我喜歡這個有山有水的小城,所以在這樣一個煩熱的下午,揹負著窒悶的心情不顧一切逃出暫居的城市,來到這裡,在寫完了一個整整寫了三年多的故事之後。

  終於,寫完了《後宮:甄嬛傳》的最後一本,第七本。七,是我喜歡的一個數字。甄嬛的故事,最後一個字,是我在初夏的某日坐在師大某個小賓館的房間裡寫下的。這個故事,自我在母校時始,又於母校終,像一個有始有終的圓圈,終於完結了。

  這是我的第一部長篇,自己也輕籲一口氣,居然寫了那麼長,那麼久。
  可是完結的那一刻,我心裡一點也不快活。因?是我自己,把我喜愛的清,把我理想中溫潤如玉的男子,寫到玉碎斑駁。

對甄嬛傳切詞

執行

python ./word_segment.py zhenhuanzhuan.txt zhenhuanzhuan.segment

生成的檔案如下:

[root@centos $] head zhenhuanzhuan.segment
  序文 - - 不過 是 「 情 」

 在 鍵盤 上 敲落 一個個 文字 的 時候 , 窗外 有 大雨 過後 的 清新 。 站 在 十二樓 的 落地 玻璃窗 前往 外看 , 有 大片大片 開闊 的 深綠 蔓延 。

     我 喜歡 這個 有山有水 的 小城 , 所以 在 這樣 一個 煩熱 的 下午 , 揹負著 窒悶 的 心情 不顧一切 逃出 暫居 的 城市 , 來到 這裡 , 在 寫 完 了 一個 整整 寫 了 三年 多 的 故事 之後 。

     終於 , 寫 完 了 《 後宮 : 甄 嬛 傳 》 的 最後 一本 , 第七 本 。 七 , 是 我 喜歡 的 一個 數字 。 甄 嬛 的 故事 , 最後 一個 字 , 是 我 在 初夏 的 某日 坐在 師大 某個 小 賓館 的 房間 裡 寫下 的 。 這個 故事 , 自我 在 母校 時始 , 又 於 母校 終 , 像 一個 有始有終 的 圓圈 , 終於 完結 了 。

     這 是 我 的 第一部 長篇 , 自己 也 輕籲 一口氣 , 居然 寫 了 那麼 長 , 那麼 久 。
     可是 完結 的 那一刻 , 我 心裡 一點 也 不 快活 。 因 ? 是 我 自己 , 把 我 喜愛 的 清 , 把 我 理想 中 溫潤 如玉 的 男子 , 寫 到 玉碎 斑駁 。

生成詞向量

執行

./word2vec -train ./zhenhuanzhuan.segment -output vectors.bin -cbow 1 -size 200 -window 8 -negative 25 -hs 0 -sample 1e-4 -threads 20 -binary 1 -iter 15

這樣會生成一個vectors.bin檔案,這就是我們想要的基於甄嬛傳原文生成的詞向量檔案

如果想知道vectors.bin檔案裡如何儲存以及如何載入,可以參考我的另一篇文章《三十二-用三千萬影視劇字幕語料庫生成詞向量

訓練程式碼

下面是我的程式碼原文,僅供參考

# -*- coding: utf-8 -*-
import sys import math import tflearn import chardet import numpy as np import struct seq = [] max_w = 50 float_size = 4 word_vector_dict = {} def load_vectors(input): """從vectors.bin載入詞向量,返回一個word_vector_dict的詞典,key是詞,value是200維的向量 """ print "begin load vectors" input_file = open(input, "rb") # 獲取詞表數目及向量維度 words_and_size = input_file.readline() words_and_size = words_and_size.strip() words = long(words_and_size.split(' ')[0]) size = long(words_and_size.split(' ')[1]) print "words =", words print "size =", size for b in range(0, words): a = 0 word = '' # 讀取一個詞 while True: c = input_file.read(1) word = word + c if False == c or c == ' ': break if a < max_w and c != '\n': a = a + 1 word = word.strip() vector = [] for index in range(0, size): m = input_file.read(float_size) (weight,) = struct.unpack('f', m) vector.append(weight) # 將詞及其對應的向量存到dict中 word_vector_dict[word.decode('utf-8')] = vector input_file.close() print "load vectors finish" def init_seq(): """讀取切好詞的文字檔案,載入全部詞序列 """ file_object = open('zhenhuanzhuan.segment', 'r') vocab_dict = {} while True: line = file_object.readline() if line: for word in line.decode('utf-8').split(' '): if word_vector_dict.has_key(word): seq.append(word_vector_dict[word]) else: break file_object.close() def vector_sqrtlen(vector): len = 0 for item in vector: len += item * item len = math.sqrt(len) return len 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): 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) def main(): load_vectors("./vectors.bin") init_seq() xlist = [] ylist = [] test_X = None #for i in range(len(seq)-100): for i in range(10): sequence = seq[i:i+20] xlist.append(sequence) ylist.append(seq[i+20]) if test_X is None: test_X = np.array(sequence) (match_word, max_cos) = vector2word(seq[i+20]) print "right answer=", match_word, max_cos X = np.array(xlist) Y = np.array(ylist) net = tflearn.input_data([None, 20, 200]) net = tflearn.lstm(net, 200) net = tflearn.fully_connected(net, 200, activation='linear') net = tflearn.regression(net, optimizer='sgd', learning_rate=0.1, loss='mean_square') model = tflearn.DNN(net) model.fit(X, Y, n_epoch=500, batch_size=10,snapshot_epoch=False,show_metric=True) model.save("model") predict = model.predict([test_X]) #print predict #for v in test_X: # print vector2word(v) (match_word, max_cos) = vector2word(predict[0]) print "predict=", match_word, max_cos main()

解釋一下上面的程式碼,load_vectors是從vectors.bin中載入詞向量,init_seq是載入甄嬛傳切詞後的文字並存到一個序列裡,vector2word是求距離某向量最近的詞,模型中只有一個lstm單元

執行效果如下:

[[email protected] $] python one_lstm_sequence_generate.py
begin load vectors
words = 16995
size = 200
load vectors finish
right answer= 站 1.0
---------------------------------
Run id: DQK34Q
Log directory: /tmp/tflearn_logs/
---------------------------------
Training samples: 10
Validation samples: 
--
Training Step: 500  | total loss: 0.33673
| SGD | epoch: 500 | loss: 0.33673 - acc: 0.1748 -- iter: 10/10
--
predict= 站 0.941794432002

可以看出:經過500個epoch的訓練,均方損失降到0.33673,並能以0.941794432002的餘弦相似度預測出下一個字

如果你有強大的gpu,可以調整上述引數,把整篇文章都訓練進去,稍稍修改程式碼中predict的部分,讓他不斷的輸出下一個字,就可以自動吐出甄嬛體

這段程式碼是基於tflearn實現的,在tflearn官方文件的examples中實現的seq2seq是直接呼叫了tensorflow中的tensorflow/python/ops/seq2seq.py,而這部分是基於one-hot的embedding方法,這是一定沒有詞向量效果好的,因此下一步打算基於上面的程式碼繼續改造,實現基於詞向量的seq2seq,相信能夠讓我的聊天機器人問答效果更好,敬請期待

相關推薦

一個lstm單元聊天機器人學會

當今比較流行的seq2seq基本都是用lstm組成的編碼器解碼器模型實現,開源的實現大都基於one-hot的embedding(沒有詞向量表達的資訊量大),因此打算自己實現一個基於word2vec詞向量的強大的seq2seq模型,首先實現了只有一個lstm單元的機器人 下載《甄嬛傳》小說原文 上網隨

rsync工具介紹rsync常用選項rsync通過ssh同步

rsync工具 rsync常用選項 rsync通過ssh同步 三十五、 rsync工具介紹、rsync常用選項、rsync通過ssh同步一、rsync工具數據備份,很重要。rsync工具:數據備份的工具。remote sync(遠程同步)rsync可以遠程同步數據(類似scp),也可以本地同步數據

robotframework中怎麽將100轉化成100.00

bubuko frame 分享圖片 技術 分享 圖片 怎麽 技術分享 http 1.將100轉化成100.00 三十五、robotframework中怎麽將100轉化成100.00

python學習之Flask框架(七)資料庫:Flask對資料庫的基本操作常見關係模板資料庫遷移綜合案例:圖書管理

補充:   使用SQL_Alchemy定義一個模型類,不可以不指定primary_key=True建立表. 一、資料庫基本操作 1. 資料庫的基本操作(CRUD): 在Flask-SQLAlchemy中,插入、修改、刪除操作,均由資料庫會話管理。

懶載入(原生封裝)

var Lazy = { $:function(arg,context){ var tagAll,n,eles=[],i,sub = arg.substring(1); context = context|| document;

JAVA泛型實現原理

1. 概述 泛型在java中有很重要的地位,在面向物件程式設計及各種設計模式中有非常廣泛的應用。 什麼是泛型?為什麼要使用泛型? 泛型,即“引數化型別”。一提到引數,最熟悉的就是定義方法時有形參,然後呼叫此方法時傳遞實參。那麼引數化型別怎麼理解呢?顧名思義,就是將型別由原來的具體

HDFS的FileSystem常用操作

package com.yang.hdfs; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import org.apache.had

jquery動畫 無縫滾動兩種方式

無縫輪播有兩種方式,一種可以讓ul中的每個li進行移動,另外一種時令整個ul進行移動。無縫輪播效果之前用js寫過一次,以下是用jQuery分別實現這兩種方式;   一、第一種 控制每個li標籤移動實現無縫輪播 1.基本佈局樣式 2.實現自動向左輪播 採用列舉物件封裝函式的方法,封

minishell(3)

35.1 內容   在當前的 minishell 中,如果執行 date clear 命令等,minishell 會停止:      這是因為引入程序組的時候,mshell 放置在前臺程序組,同時之後在子程序中又建立了一個程序組,在程式碼中,第二個程序組在沒有將其設定為前臺程序組之前,一直是後臺程序組。

java學習--多執行緒程式設計

Java 多執行緒程式設計 Java 給多執行緒程式設計提供了內建的支援。 一條執行緒指的是程序中一個單一順序的控制流,一個程序中可以併發多個執行緒,每條執行緒並行執行不同的任務。 多執行緒是多工的一種特別的形式,但多執行緒使用了更小的資源開銷。 這裡定義和執行緒相關的

python學習之Flask框架: 藍圖和單元測試

一、藍圖和單元測試: 1.藍圖: 隨著flask程式越來越複雜,我們需要對程式進行模組化的處理,之前學習過python的模組化管理,於是針對一個簡單的flask程式進行模組化處理 名詞解釋: 高內聚,低耦合:   所謂高內聚是指一個軟體模組是由相關性很強的程式碼組成,

演算法題():二叉樹的下一個結點

題目描述 給定一個二叉樹和其中的一個結點,請找出中序遍歷順序的下一個結點並且返回。注意,樹中的結點不僅包含左右子結點,同時包含指向父結點的指標。 分析 分情況討論: 1.如果結點有右孩子,則返回右子樹中最後一個左孩子; 2.如果結點沒有右孩子,且該結點是父結點的左孩子,則返回

javaSE ()多執行緒 ( 多執行緒實現方法和區別同步程式碼塊和方法(執行緒安全))

主要還是熟悉api,熟悉方法,簡單,需要多實踐 1、 多執行緒實現方法和區別: 多執行緒實現的兩種方法: 1)類繼承Thread類或實現Runnable介面,重寫run()方法 2)建立Thread的子類物件(需要開幾個執行緒就建立幾個物件,可建立匿名內部類) 3)子類

一個完美的管理後臺側邊欄

在sonata管理後臺除了我們常用的部分之外,還有側欄的內容我們沒有涉及過,這一節講幾個簡單的配置來讓我們管理後臺內容更豐富更易用 把管理後臺據為己有 我們的管理後臺左上角logo部分顯示的內容是這樣的: 是不是有點low了?我想改個名字叫做“後臺管理系統”怎麼辦呢?非常簡單,開啟app/co

IT 移動端:足跡第步:靜態自適應流式響應式四種HTML網頁佈局的區別(哪種佈局在移動端最好用)

1)靜態佈局:在PC端與移動端用2個佈局;一個元素的位置和大小都不變化;2)自適應佈局:在PC端與移動端用2個佈局;一個元素的位置會變化。3)流式佈局:在PC端與移動端1個佈局;元素的位置會變化,元素的

# Unity 遊戲框架搭建 2019 () 9 ~ 10 示例整理

## 第九個示例 目前程式碼如下: ```cs using UnityEngine; #if UNITY_EDITOR using UnityEditor; #endif namespace QFramework { public class ResolutionCheck { #if UNITY_E

AGG第課 gsv_text 渲染ASCII字符

agg gsv_text代碼 agg::rendering_buffer &rbuf = rbuf_window(); agg::pixfmt_bgr24 pixf(rbuf); typedef agg::renderer_base<agg::pixfmt_bgr24>

Spring Boot 環境變量讀取 和 屬性對象的綁定

bean database 環境 autoconf lac autowire 屬性 boot title 凡是被spring管理的類,實現接口 EnvironmentAware 重寫方法 setEnvironment 可以在工程啟動時,獲取到系統環境變量和applicati

Linux 入門記錄:Linux 網絡基本配置

包含 mac地址 圖像 鏈接 ifcfg 修改主機名 www. 永久生效 expr 一、以太網(Ethernet) 以太網(Ethernet)是一種計算機局域網技術。IEEE 組織的 IEEE 802.3 標準制定了以太網的技術標準,它規定了包括物理層的連線、電子信號和介

愛創課堂每日一題第天- 說說你對閉包的理解?

前端 前端學習 前端入門使用閉包主要是為了設計私有的方法和變量。閉包的優點是可以避免全局變量的汙染,缺點是閉包會常駐內存,會增大內存使用量,使用不當很容易造成內存泄露。在js中,函數即閉包,只有函數才會產生作用域的概念閉包有三個特性:1.函數嵌套函數2.函數內部可以引用外部的參數和變量3.參數和變量不會