人類其實(shí)從很早以前就開始追求人類和機(jī)器之間的對話,早先科學(xué)家研發(fā)的機(jī)器在和人對話時(shí)都是采用規(guī)則性的回復(fù),比如人提問后,計(jì)算機(jī)從數(shù)據(jù)庫中找出相關(guān)的答案來回復(fù)。這種規(guī)則性的一對一匹配有很多限制。機(jī)器只知道問什么答什么,卻不知道舉一反三,比如你問它:“今天天氣怎么樣?”它會(huì)機(jī)械地把今天的天氣告訴你。這不像人與人之間的對話,人是有各種反應(yīng)的,這類反應(yīng)的產(chǎn)生是基于人的知識(shí)結(jié)構(gòu)和對話場景的。
那么,你覺得這類機(jī)器是否真的具有智能了?圖靈測試是這樣判斷機(jī)器人是否具有智能的:測試中,一個(gè)正常人將嘗試通過一連串的問答,把被試的機(jī)器與人類區(qū)分開來。一般來說,如果正常人無法分辨和自己聊天的是人還是機(jī)器人的時(shí)候,機(jī)器人就算通過測試了。
圖靈測試的關(guān)鍵之處在于,沒有定義“思維/意識(shí)”。只是將機(jī)器人作為黑盒,觀察輸入和輸出是否達(dá)標(biāo)。所以說它從一開始就繞開了“機(jī)器能思考嗎?”這樣的問題,而是把它替換成另外一個(gè)更具操作性的問題——“機(jī)器能做我們這些思考者所做的事嗎?”。大家注意這兩者其實(shí)完全不是一個(gè)層次的問題。
然而,“機(jī)器能思考嗎?”和“機(jī)器能做我們這些思考者所做的事嗎?”這兩個(gè)問題真的可以相互替代嗎?
比如說,機(jī)器能夠?qū)懺姡踔帘仍S多資質(zhì)平庸的人寫出的詩更像樣子。如果我們?nèi)藶閿M定一套標(biāo)準(zhǔn),來為機(jī)器和人寫的詩打分,那么完全有可能設(shè)計(jì)出一臺(tái)能夠贏過絕大多數(shù)詩人的寫詩機(jī)器。但這真的和人類理解并欣賞一首詩是一回事嗎?再比如,人工智能在國際象棋、圍棋領(lǐng)域已經(jīng)比人類更強(qiáng)大,但這真正和人類思考如何下棋是一樣的嗎?
世界上有這么一個(gè)關(guān)于圖靈測試的獎(jiǎng)項(xiàng)——“勒布納獎(jiǎng)”,頒給擅長模仿人類真實(shí)對話場景的機(jī)器人。然而,這個(gè)獎(jiǎng)項(xiàng)大多數(shù)的獲得者都沒有看上去那樣智能。比如一個(gè)人問一臺(tái)機(jī)器“你有多愛我?”,如果它想通過圖靈測試,它就不停地顧左右而言他,比如回答“你覺得呢?”事實(shí)上大多數(shù)問題都可以用反問去替代,說白了這些僅僅是一些對話技巧。而獲勝者并沒有真正理解“你有多愛我?”這樣的問題。
這里有句話,希望大家記住:人工智能的真實(shí)使命是塑造智能,而非去刻意打造為了通過某類隨機(jī)測試的“專業(yè)”程序。
所幸到今天為止,很多學(xué)者都意識(shí)到了圖靈測試的局限性,如果我們要發(fā)明人工智能,就要真正清楚地定義人工智能。同樣如果我們要做智能對話,我們也要清晰地定義智能對話。
在2013年的一次國際會(huì)議上,來自多倫多大學(xué)的計(jì)算機(jī)科學(xué)家發(fā)表了一篇論文,對“圖靈測試”提出了批評。他認(rèn)為類似這樣的人機(jī)博弈其實(shí)并不能真正反映機(jī)器的智能水平。對于人工智能來說,真正構(gòu)成挑戰(zhàn)的是這樣的問題:
鎮(zhèn)上的議員們拒絕給憤怒的游行者提供游行許可——“因?yàn)樗麄儞?dān)心會(huì)發(fā)生暴力行為”——是誰在擔(dān)心暴力行為?
A.鎮(zhèn)上的議員們
B.憤怒的游行者
類似這樣的問題,機(jī)器有沒有可能找到正確的答案?要判斷“他”究指代誰,需要的不是語法書或者百科辭典,而是常識(shí)。人工智能如何能夠理解一個(gè)人會(huì)在什么情況下“擔(dān)心”?這些問題涉及人類語言和社會(huì)交往的本質(zhì),以及對話的前后語境。這些本質(zhì)其實(shí)是一種規(guī)則,而這種規(guī)則是在不停變化的。正是在這些方面,目前人工智能還無法與人類相比。
這意味著,制造一臺(tái)能與人類下棋的機(jī)器人很容易,但想要制造一臺(tái)能理解人類語言的機(jī)器人卻很難。
為了更好地理解機(jī)器對話,英特將現(xiàn)有的對話技術(shù)進(jìn)行總結(jié)并畫出流程圖(見圖3-1),這里面涉及的邏輯和模塊較多,英特是從模擬人類對話的步,即理解人類的語言開始的,當(dāng)然要做到完全理解人類的語言在目前來講也不太可能。對于機(jī)器人來說,無論何種用途的機(jī)器人,首要需要解決的就是理解人類說了些什么,而除了命令句式以外,理解人類說什么就是理解人類提出的各種問題。請移步下一節(jié)來看看如何理解人類的提問。
英特調(diào)查后發(fā)現(xiàn)對于中文問題來說,無非可以分成以下兩類:疑問句和反問句。對于反問句當(dāng)然沒什么好說的,我們來重點(diǎn)看看疑問句。可以分為是非問句、正反問句、特指問句、選擇問句,其中特指問句又可以分為人、原因、地點(diǎn)、時(shí)間、意見、數(shù)量、方式和其余的實(shí)體。
對于問題來說,人類也需要首先對句子做一個(gè)判斷,拿特指問題來說,需要判斷到底是問什么?接著將每個(gè)問題做一個(gè)初步的定位,縮小回答時(shí)的搜索范圍,后從知識(shí)體系和場景中取得答案。
英特團(tuán)隊(duì)按照句式結(jié)構(gòu)找了些例句放進(jìn)去,為后一步的句式分類準(zhǔn)備好訓(xùn)練集。
比如在“特指問句_時(shí)間”里放入了如下例句。
中國部憲法頒布的時(shí)間?
哪天你有空?
演唱會(huì)是哪天?
又比如“特指問句_原因”里放入如下例句。
為什么人的面容千差萬別?
為什么我感覺不到演員演技的好壞?
為什么不要空腹喝牛奶?
用我們在第2章提到的任意特征提取器、分類模型,我們都能得到一個(gè)基本準(zhǔn)確的輸出,比如問題“還有多久輪到我們”。
Enter the sentence you want to test(“quit” to break):還有多久輪到我們
Sentence Type: 疑問句_特指問句_時(shí)間 -- <type ‘str’> How much:
疑問句_特指問句_時(shí)間 --> 0.568171744082 陳述句_轉(zhuǎn)折復(fù)句 --> 0.0833727296382 陳述句_目的復(fù)句 --> 0.0702280010834 陳述句_時(shí)間復(fù)句 --> 0.0467500544003 陳述句_連鎖復(fù)句 --> 0.0389512385469 疑問句_特指問句_地點(diǎn) --> 0.0360868190755 陳述句_因果復(fù)句 --> 0.023920374049 疑問句_選擇問句 --> 0.0149039847156 疑問句_特指問句_意見 --> 2.89120579329e-19 臟話_增強(qiáng)語氣 --> -0.00288297881955 臟話_惡意臟話 --> -0.00377381341484
在答案的提取階段,一般的對話像常見的智能對話助手Siri、小冰等,都是有對應(yīng)的問題答案組(QA)的,這種QA數(shù)量一般都接近百萬級(jí)了。而在現(xiàn)實(shí)工作中,沒有能力和精力人工組建QA怎么辦?這個(gè)時(shí)候我們可以使用互聯(lián)網(wǎng)的信息——利用爬蟲爬取。
大體過程是這樣的:
(1)定義一個(gè)爬蟲,針對某些問題的特點(diǎn)爬取候選答案。
(2)答案的抽取。從離線或在線知識(shí)庫抽取候選答案,候選答案一般有多條。
(3)答案的選擇。從候選答案中提取真正有效的回答。
下面用一個(gè)簡單的例子來做說明。
首先是爬蟲,這里我們以“百度知道”為爬取目標(biāo),爬取相關(guān)問題及答案的前幾名。
def getAnswerfromZhiDao(question): """
Scrap answers from ZhiDao(百度知道 )
:param question:
:return:
""" tic = time.time() global zhidaoHeader
URL = ZHIDAO + "/index?rn=10&word=" + question # print(URL) Answer = []
http = httplib2.Http() # 聲明一個(gè)CookieJar對象實(shí)例來保存cookie cookie = cookielib.CookieJar()
opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookie))
req = urllib2.Request(URL)
response = opener.open(req)
zhidaoHeader['Cookie'] = response.headers.dict['set-cookie']
response, content = http.request(URL, 'GET', headers=zhidaoHeader)
上面的代碼是整個(gè)爬蟲的http請求header頭組裝及爬取url的組裝。
ZHIDAO = 'http://zhidao.baidu.com' URL = ZHIDAO + "/index?rn=10&word=" + question
這里參數(shù)rn=10 也就是要返回10條答案。
比如用戶提問:唐太宗是誰?
組裝后URL = https://zhidao.baidu.com/index?rn=10&word=唐太宗是誰?
利用組裝的URL返回答案條目如下。
search_result_list = etree.HTML(content.lower()).xpath("http://div[@class='slist']/p/a") # time1 = time.time() limit_num = 3 for index in range(min(len(search_result_list), limit_num)):
url = search_result_list[index].attrib['href']
url = ZHIDAO + url # print(url) response, tar_page = http.request(url, 'GET', headers=zhidaoHeader) # 判斷是否做了重定向 301, 302 if response.previous is not None: if response.previous['status'][0] == '3':
url = response.previous['location']
上一段程序先爬取答案的一級(jí)頁面,也就是上面截圖的頁面,然后再分別爬取前三個(gè)答案的詳細(xì)頁面,以得到具體的答案。也可以控制爬取詳細(xì)答案的數(shù)量:limit_num = 3。在爬取“百度知道”內(nèi)容時(shí)需要注意重定向問題,以區(qū)分處理各種網(wǎng)站。
爬取了問題后,需要做答案的提取和選擇,步是找到有一定相關(guān)度的答案候選、縮小范圍;第二步就是選擇并提取答案。因?yàn)槲覀円呀?jīng)做了問題的分類,這里要分情況來考慮。
(1)對于人、地點(diǎn)、時(shí)間等這種知道明確在問什么,也知道明確的提取規(guī)則的,我們可以按照規(guī)則去抽取答案,按出現(xiàn)的頻率來評價(jià)答案。
(2)對于方式、原因等這樣的開放式問題需要用一句話或者一段話回答,可以先選擇一批備選答案,再從備選答案種挑一個(gè)好的。
對于上面提到的問題:唐太宗是誰?這可以歸類到種情況。下面我們來看看這個(gè)問題的處理流程。
步,通過問題分類、問題理解,找到了這個(gè)答案屬于特指問題“人”。
第二步,針對這類問題,英特用了個(gè)小技巧,非常簡單但有效:如果我們確認(rèn)要找的是人、人名等,可以在備選答案中選擇表示人的單詞,比如名詞、代詞,再計(jì)算它出現(xiàn)的頻率,比如“李世民”這個(gè)詞在答案中出現(xiàn)了10多次,就可以將它提取出來反饋給用戶。
if tar == 'who': for i in words: if i.flag == 'nr' and i.word not in question: # 人名 humWord.append(i.word) return getTopWord(humWord, 1)
問數(shù)量的、問時(shí)間的、問地點(diǎn)的都可以照此處理。當(dāng)然如果這里單獨(dú)用了詞頻還是有問題,我們將范圍縮小一些找詞頻就能更準(zhǔn)確:比如將“唐太宗是誰?”這個(gè)問題在答案里做相似性匹配,找到匹配度很高的候選答案,再用以上的小技巧計(jì)算詞頻,當(dāng)然在計(jì)算詞頻時(shí),我們可以看看比如“李世民”這個(gè)詞出現(xiàn)在句中的位置,這能幫助我們進(jìn)一步精確地抽取答案。
做到這一步,英特解決了簡單問句的回答,特別是針對時(shí)間、人物、地點(diǎn)等這種回答只有一個(gè)詞的問句特別有效。但對話中大量出現(xiàn)上文提到的第二種情況,諸如問“如何”“怎么樣”這類開放性問題,該如何處理呢?比如“唐太宗是個(gè)什么樣的皇帝?”這樣的開放問題。對這類問題,來看看英特的解決方法:
步,通過問題分類、問題理解,找到了這個(gè)答案屬于特指問題“意見”。
第二步,求問題和檢索答案段落的文本相似性。相似性有很多種處理方式,思路之一是可以簡單地估計(jì)問題的關(guān)鍵詞占所有問題關(guān)鍵詞的比例(比如:唐太宗、皇帝),或者可以用word2vec、LSI來求相似度。
第三步,判斷答案是否由一個(gè)段落蘊(yùn)含。這里我們假設(shè)已經(jīng)有了識(shí)別文本蘊(yùn)含(RTE)的算法,并能準(zhǔn)確找出“唐太宗勤勉治國,是個(gè)好皇帝。”是被蘊(yùn)含的答案。
我們將答案提取打分的偽代碼總結(jié)如下:
ScoreAnswers(String[] answers, String[] passages, AnalyzedQuestion aq)
scoredAnswers??
foreach answer(answers): //特征1:段落和問題間的文本相似度 textSim?calculateTextSimilarity(answer,passages,aq,question) //特征2:判斷一個(gè)蘊(yùn)含問題 entailed?recognizeEntailment(answer,passages, aq,question) //從特征值估算置信分值 //通過增強(qiáng)置信分值來找到相似答案 return scoredAnswers
通過相似度評分和蘊(yùn)含評分得到答案的總體評分,然后再將答案排序輸出個(gè)答案。
對于相似度評分無需過多描述,但是蘊(yùn)含呢?英特查了很多資料后決定了蘊(yùn)含關(guān)系的研發(fā)方案。
蘊(yùn)含關(guān)系,是為了評價(jià)從一段文字中得到的推論是否符合原文的本意,我們這里用蘊(yùn)含關(guān)系來做答案中是否包含著問題的判斷,其實(shí)就是求某種語義上的相似性或相關(guān)性。
下面舉個(gè)例子。
T:次世界大戰(zhàn)(簡稱一戰(zhàn);英語:World War I、WW I、Great War)是一場于1914年7月28日至1918年11月11日主要發(fā)生在歐洲,然而戰(zhàn)火終延燒至全球的戰(zhàn)爭,當(dāng)時(shí)世界上大多數(shù)國家都被卷入這場戰(zhàn)爭,是人類史上場全球性規(guī)模的大型戰(zhàn)爭,史稱“次世界大戰(zhàn)”。
H:次世界大戰(zhàn)的時(shí)間
label:1 ← 這里標(biāo)簽為1,表示答案中蘊(yùn)含問題。
T:第二十九屆奧林匹克運(yùn)動(dòng)會(huì)(英語:the Games of the XXIX Olympiad;法語:les Jeux de la XXIXe Olympiade),又稱2008年夏季奧運(yùn)會(huì)或北京奧運(yùn)會(huì),于2008年8月8日至24日在中華人民共和國首都北京舉行。
H:東京奧林匹克運(yùn)動(dòng)會(huì)的舉辦時(shí)間
label:0 ← 這里標(biāo)簽為0,表示答案中沒有蘊(yùn)含問題。
從例子可以看出,求蘊(yùn)含關(guān)系就是求一個(gè)相似度,但還不完全像求相似度,蘊(yùn)含關(guān)系中,選擇哪些特征才是這個(gè)算法在問答中應(yīng)用的重點(diǎn),只要把特征選出扔到SVM分類器中就可以做訓(xùn)練了。
一般提取哪些特征出來呢?我們先人工選擇特征并提取。看看代碼,除了詞的頻率和位置還可以提取下面這些特征(規(guī)律):
features['word_overlap'] = len(extractor.overlap('word')) # hyp 與 text 中重復(fù)的 word features['word_hyp_extra'] = len(extractor.hyp_extra('word')) # hyp 有 但 text 中沒有的 word features['ne_overlap'] = len(extractor.overlap('ne')) # hyp 與 text 中重復(fù)的 ne features['ne_hyp_extra'] = len(extractor.hyp_extra('ne')) # hyp 有 但 text 中沒有的 ne features['neg_txt'] = len(extractor.negwords & extractor.text_words) # text 中的 否定詞 features['neg_hyp'] = len(extractor.negwords & extractor.hyp_words) # hyp 中的 否定詞
ne指的是命名實(shí)體(Named Entity),其中hyp指的是問題,大家觀察蘊(yùn)含的示例代碼可以看出,英特在項(xiàng)目進(jìn)行中發(fā)現(xiàn)光是名詞實(shí)體不足以提取到完整特征,于是將時(shí)間名詞、成語、狀態(tài)詞都加入到ne范疇中,提取規(guī)則同上保持不變。
當(dāng)然如果你不想用人工方式提取答案和問題的特征,仍然可以用在第2章我們提到的CNN+RNN方式提取特征,而這種提取方式可以稍作變化,將詞性作為輸入加到Word Embedding層后。
前面的這類方法可以總結(jié)為檢索式方法,其思路是從一個(gè)已知的大知識(shí)數(shù)據(jù)庫 中搜索并組合出相應(yīng)的答案,這種搜索方式可以伴隨一些預(yù)定好的規(guī)則,比如:{who} 想要糖果?回答:我想要{ pronoun }。 這個(gè){ pronoun }可以從數(shù)據(jù)庫找出相應(yīng)的代詞填入。而這種回答的規(guī)則可以用一種通用的XML文件來描述,我們稱它為AIML2.0。
另外還需要擁有初級(jí)的邏輯推理能力,比如IBM Watson ,而對于這類而言,我們除了需要制定相應(yīng)的邏輯規(guī)則庫以外,還需要事實(shí)庫。在Python中我們可以選用pyke框架來管理相應(yīng)的事實(shí)庫與邏輯規(guī)則庫。
以上無論是邏輯推理回答還是一般回答都可以稱作檢索式的或者規(guī)則式的方法。除此之外還有哪些方法可以給出答案呢?英特在調(diào)查中發(fā)現(xiàn)目前學(xué)界在RNN(LSTM)上的突破讓模型擁有了初級(jí)的‘學(xué)習(xí)’能力:基于神經(jīng)網(wǎng)絡(luò)序列的生成式對話模型。
生成式對話模型算法的概念就是讓模型先看一些對話集,然后問它一句話,模型會(huì)通過從對話集學(xué)習(xí)的一些規(guī)律給你一個(gè)回答。簡單來說根據(jù)你的上一句話和學(xué)習(xí)到的所有對話集規(guī)律生成一個(gè)個(gè)單詞,這些單詞如果意義是連貫的那就是一句話!而這正好契合了對話模型。
聽上去很美好,而且一些大公司已做了很多工作,比如圖3-2所示的Google對話集:
Google的這個(gè)結(jié)果建立在訓(xùn)練了3000萬條對話的基礎(chǔ)上,取其中的300萬條對話來做驗(yàn)證集,并且去掉了專業(yè)名詞、數(shù)字和URL等。達(dá)到這種數(shù)據(jù)量級(jí)后,能夠?qū)δ骋淮怪鳖I(lǐng)域類的問題做自由度較高的機(jī)器回復(fù)。
Google所用的生成式對話模型有哪些特點(diǎn)呢?下面來看看基于檢索式模型和生成模型之間的區(qū)別,是不是能找到一些特點(diǎn)。
基于檢索式模型(基于AIML2.0)使用了預(yù)定義回復(fù)庫和一種條件觸發(fā)式方法來根據(jù)輸入和語境做出合適的回復(fù)。這種觸發(fā)式方法一般基于規(guī)則的表達(dá)式匹配,當(dāng)然你也可以用機(jī)器學(xué)習(xí)分類器來處理這類觸發(fā)。檢索式模型的特點(diǎn)是它不會(huì)產(chǎn)生新文本,只是從固定集合中挑選一種回復(fù),套用農(nóng)夫山泉廣告語:“我們不生產(chǎn)文本我們只是集合的搬運(yùn)工”。
生成式對話模型不依賴于預(yù)定義回復(fù)庫,從零開始生成新回復(fù)。生成式對話模型一般基于機(jī)器翻譯中的Seq2Seq技術(shù),但應(yīng)用場景有較大差別;機(jī)器翻譯的目標(biāo)是:把一個(gè)輸入“翻譯”成一個(gè)輸出“回復(fù)”。輸入(翻譯)再輸出(回復(fù))就是編碼器(encoder)經(jīng)信息編碼后再經(jīng)解碼器(decoder)解碼的過程,而在對話中輸入人說的話再輸出機(jī)器的回復(fù)(如圖3-3所示)。
編碼器(encoder)是對于人的提問或?qū)υ挼木幋a,可以看作是機(jī)器對問題的一種理解,而解碼器(decoder)是機(jī)器對問題的一種回復(fù)。
是不是生成式對話模型就遠(yuǎn)比檢索式要好呢?可以說目前為止,還只是各司其職,各自有不同的應(yīng)用場景:
(1)檢索式模型由于采用人工制作的回復(fù)庫,基于檢索式方法不會(huì)有語法錯(cuò)誤,當(dāng)然我們使用搜索引擎作為回復(fù)庫,也很少有語法錯(cuò)誤。然而使用回復(fù)庫不能處理沒出現(xiàn)過的情況,因?yàn)樗鼈儧]有合適的預(yù)定義回復(fù)。同樣,這些模型不能重新利用提上下文中的實(shí)體信息,如先前對話中提到過的名字。綜上,檢索式模型可以用在需要正確回答問題的場合,對答案的語法和準(zhǔn)確性要求比較高。
(2)生成式對話模型從原理上講更“聰明“些。它們可以重新提及輸入中的實(shí)體并帶給你一種正和你對話的感覺。然而,這類模型很可能會(huì)犯語法錯(cuò)誤(特別是輸入一個(gè)長句時(shí)),而且通常要求大量的訓(xùn)練數(shù)據(jù)。綜上,生成式對話模型可以用在要求不那么精確的對話中。比如游戲的NPC交談,比如一般的生活類對話場景。
雖然生成式對話模型有一些缺點(diǎn),但畢是一個(gè)很好的方向,英特選擇使用TensorFlow來實(shí)現(xiàn)這個(gè)結(jié)構(gòu)。
前文提到,生成式對話模型是基于生成式機(jī)器翻譯模型,而機(jī)器翻譯模型用的就是Seq2Seq(Sequece2Sequence)結(jié)構(gòu) 。我們先來理解下Seq2Seq結(jié)構(gòu):Seq2Seq由編碼器和解碼器組成,輸入的單詞以序列化的方式傳入編碼器,終得到表示一句話的上下文特征向量;解碼器接收特征向量以及每次的輸出單詞,做序列化的解碼,輸入和輸出以終止。
對于編碼器來說,為了進(jìn)一步提高生成的準(zhǔn)確性,其輸入部分需要更多的句子特征,除一般的word2vec表示外,我們還可以引入單詞的詞性、句子成分、單詞的重要性(TF-IDF)作為額外的特征。
下面我們看一個(gè)編解碼器的例子(也是Seq2Seq的核心構(gòu)件)。
編碼器代碼如下。
# Encoder encoder_cell = rnn_util.MultiEmbeddingWrapper(
cell,
embedding_classes=num_encoder_symbols,
embedding_size=encoder_embedding_size
)
encoder_outputs, encoder_state = rnn.rnn(
encoder_cell, encoder_inputs, dtype=dtype)
解碼器代碼如下。
# Decoder. output_size = None if output_projection is None:
cell = rnn_cell.OutputProjectionWrapper(cell, num_decoder_symbols)
output_size = num_decoder_symbols
…… def decoder(feed_previous_bool): reuse = None if feed_previous_bool else True with variable_scope.variable_scope(variable_scope.get_variable_scope(), reuse=reuse) as scope:
outputs, state = embedding_attention_decoder(
decoder_inputs,
encoder_state,
attention_states,
cell,
num_decoder_symbols,
embedding_size=decoder_embedding_size,
num_heads=num_heads,
output_size=output_size,
output_projection=output_projection,
feed_previous=feed_previous_bool,
update_embedding_for_previous=False,
initial_state_attention=initial_state_attention)
state_list = [state] if nest.is_sequence(state):
state_list = nest.flatten(state) return outputs + state_list
outputs_and_state = control_flow_ops.cond(feed_previous, lambda: decoder(True), lambda: decoder(False))
這里解釋下解碼器中的Attention層,Attention層的思想也是來自于翻譯領(lǐng)域,即前文出現(xiàn)的單詞也可能出現(xiàn)在后面的回答中,比如說人名、地名等信息。Attention層是在編碼器隱藏層和解碼器之間的網(wǎng)絡(luò)結(jié)構(gòu),在某一時(shí)刻t時(shí),接收解碼器的隱藏層信息,生成當(dāng)前時(shí)刻的加載到編碼器隱藏層上的權(quán)重。
英特訓(xùn)練了10萬條有關(guān)星巴克的微博信息,終取得了不錯(cuò)的結(jié)果,我們先來看看中間的輸出過程(如圖3-4所示)。
圖3-4是英特用和星巴克有關(guān)的微博數(shù)據(jù)訓(xùn)練了5 epoch后得到的結(jié)果。可以看出,在5 epoch時(shí),模型還無法說出一個(gè)完整的句子,甚至都無法表達(dá)通順的短語,但是模型在不停的學(xué)習(xí)中回答越來越準(zhǔn)確,下面的圖3-5是訓(xùn)練了50 epoch后的終結(jié)果。
英特對終結(jié)果分析后發(fā)現(xiàn)仍然會(huì)存在一些問題:就是前文提到的會(huì)有一些語法錯(cuò)誤;第二需要大量的訓(xùn)練數(shù)據(jù)。
個(gè)問題主要受限于現(xiàn)在的模型原理。目前暫時(shí)沒有哪個(gè)模型或者衍生的模型能解決好。
再看第二點(diǎn),如何獲取大量的訓(xùn)練數(shù)據(jù)。憑借英特的經(jīng)驗(yàn),對于普適性的對話模型可以從兩類途徑獲取:一是從電視劇中獲取相關(guān)數(shù)據(jù);二是從微博、QQ聊天記錄中獲取相關(guān)數(shù)據(jù)。
對于一些專業(yè)性比較強(qiáng)的領(lǐng)域,就要求在本專業(yè)領(lǐng)域收集數(shù)據(jù)了,如上文提到的Google將自己IT 服務(wù)部門的所有對話拿來訓(xùn)練。在任何稍微開放領(lǐng)域的應(yīng)用上,比如像回復(fù)一封工作郵件,就超出了該模型現(xiàn)有的能力范圍。但退一步來講,仍舊可以利用模型建議和改正回復(fù)來“輔助”人類工作者;然后在這個(gè)過程中讓模型學(xué)習(xí)人類真實(shí)的回復(fù)語句,不斷更新出一個(gè)符合人類習(xí)慣的對話模型。
英特團(tuán)隊(duì)在做完以上工作后,發(fā)現(xiàn)機(jī)器說的話有些已經(jīng)有成形的答案,還有些不通順、不成句子。這涉及另外一個(gè)問題,我們?nèi)绾卧u價(jià)模型呢?如何判斷哪些模型的哪些調(diào)整有助于提高輸出句子的通順性或準(zhǔn)確度?
英特瀏覽了相關(guān)的論文,發(fā)現(xiàn)針對這類問題有很多評價(jià)辦法,終英特選擇了早出現(xiàn)在翻譯界的方法:BLEU評測方法。
BLEU(Bilingual Evaluation understudy)方法由IBM提出,這種方法認(rèn)為如果機(jī)器翻譯的譯文越接近人工翻譯結(jié)果,那么它的翻譯質(zhì)量越高。所以,評測關(guān)鍵就在于如何定義系統(tǒng)譯文與參考譯文之間的相似度。BLEU采用的方式是比較并統(tǒng)計(jì)共現(xiàn)的n-gram個(gè)數(shù),即統(tǒng)計(jì)同時(shí)出現(xiàn)在系統(tǒng)譯文和參考譯文中的n-gram的個(gè)數(shù),后把匹配到的n-gram的數(shù)目除以系統(tǒng)譯文的單詞數(shù)目,得到評測結(jié)果。
開始提出的BLEU法雖然簡單易行,但是它沒有考慮到翻譯的召回率。后來對BLEU做了修正,即首先計(jì)算出一個(gè)n-gram在一個(gè)句子中大可能出現(xiàn)的次數(shù)MaxRefCount(n-gram),然后再和候選譯文中的這個(gè)n-gram出現(xiàn)的次數(shù)比較,取它們之間小值作為該n-gram的終匹配個(gè)數(shù)。
前面的工作可以總結(jié)為簡單流程圖(如圖3-6所示)。
該流程一共包括4個(gè)主要模塊。正如本章開始時(shí)所分析的那樣,優(yōu)先解決的是問答,與其說這是一個(gè)智能對話機(jī)器人不如說這其實(shí)就是信息檢索和總結(jié)的過程,因?yàn)榱奶飚叢皇且粋€(gè)人的事,它必然是一個(gè)交互的過程(程序與人的交互過程)。而解決交互過程好的方法就是應(yīng)用強(qiáng)化學(xué)習(xí)(reinforcement learning),我們會(huì)在后面的章節(jié)中對該算法做具體的實(shí)驗(yàn)說明,這里僅簡單描述:強(qiáng)化學(xué)習(xí)是用來解決程序與環(huán)境的交互問題的,即讓程序?qū)Ξ?dāng)前所處的環(huán)境做出必要的反應(yīng)。
假定我們站在機(jī)器的角度來考慮問題,所處的環(huán)境為聊天室,看到的全是我與對方的聊天記錄,我們要做的就是在適當(dāng)?shù)臅r(shí)刻給出合適的回復(fù),那么這里就需要做三件事:
(1)看懂聊天記錄(state);
(2)量化回復(fù)所用的語言(action);
(3)針對對話的過程打分(value function)。
件事就是文本特征提取過程(CNN),此處不再贅述。
第二件事有兩種處理思路:
(1)把句子作為動(dòng)作分解成兩個(gè)過程,輸出量化后的動(dòng)作,再根據(jù)量化值生成一句話;
(2)把字作為一個(gè)動(dòng)作,允許連續(xù)輸出多個(gè)動(dòng)作。
第三件事為重要,一個(gè)好的評價(jià)函數(shù)是決定強(qiáng)化學(xué)習(xí)效率的關(guān)鍵,這里也有兩種思路可以考慮:
(1)以對抗的方式訓(xùn)練一個(gè)句子的打分器,但這需要大量的標(biāo)注的對話語料;
(2)新的評價(jià)一個(gè)對話質(zhì)量的觀點(diǎn)是根據(jù)對方是否愿意和你聊天來判斷,即根據(jù)對話的回合數(shù)直接對對話打分。
這樣就把對話過程建模成一個(gè)強(qiáng)化學(xué)習(xí)的過程了。
綜上,對話問題雖然得到了一定的解決,但并沒有在所有領(lǐng)域都取得較好的效果,還需要不斷優(yōu)化,目前好作為輔助功能。另一方面,如果要回答前面提到的常識(shí)性的問題,就需要“規(guī)則”和“常識(shí)”來處理。“規(guī)則常識(shí)”其實(shí)是對實(shí)體的一種映射,這種映射需要不停地存入新的常識(shí)并更新,所以常識(shí)性的問題少不了知識(shí)圖譜 的支持,基于檢索式的方法結(jié)合知識(shí)圖譜的使用,將使問題回答的準(zhǔn)確性有一個(gè)質(zhì)的提高。
這樣就引來了如下思考,如果前面的檢索方式并不能夠解決多輪對話問題,假設(shè)出現(xiàn)這樣的一個(gè)問題“他是做什么的呢?”,那么我們光看這句話明顯不知道“他”指的是誰?此時(shí)就需要使用指代消解來解決。筆者所在的團(tuán)隊(duì)在這方面已經(jīng)有了初步的效果,目前已經(jīng)能實(shí)現(xiàn)5輪 左右的對話。這里簡單例舉幾種指代的處理方式。
(1)原因詢問。
A:她昨天又沒來。B:為什么?
“為什么”就指前一句話的內(nèi)容,這時(shí)候B問的是為什么她昨天又沒來。
(2)同義替換。
A:今天天氣怎么樣。B:今天天氣不錯(cuò)。A:明天呢?
明天呢?替換成明天天氣怎么樣?這里將明天和今天替換,這是同義詞性的替換。
(3)結(jié)構(gòu)補(bǔ)充。
A:周杰倫是干啥的?B:唱歌的。A:出過哪些專輯?
這里“出過哪些專輯?”替換成“周杰倫出過哪些專輯?”這是結(jié)構(gòu)缺失,要去前文找相似結(jié)構(gòu)位置的主題詞并補(bǔ)充。
以上三種情況已經(jīng)可以涵蓋多數(shù)場景,讀者可以根據(jù)這些思路解決更多的指代問題,為多輪對話貢獻(xiàn)自己的力量。
對話的部分講到這里可以告一段落了,人類對于智能機(jī)器人的渴求已越來越迫切,而智能的重要表征就在于對話能力,對話能反映出智能的程度,這方面的研究也只是剛剛開了個(gè)頭,還有很多未知的領(lǐng)域需要我們?nèi)ヌ剿鳌9P者非常慶幸我們能生活在這個(gè)時(shí)代,有信心在有生之年看到真正的智能產(chǎn)生。
本站文章版權(quán)歸原作者及原出處所有 。內(nèi)容為作者個(gè)人觀點(diǎn), 并不代表本站贊同其觀點(diǎn)和對其真實(shí)性負(fù)責(zé),本站只提供參考并不構(gòu)成任何投資及應(yīng)用建議。本站是一個(gè)個(gè)人學(xué)習(xí)交流的平臺(tái),網(wǎng)站上部分文章為轉(zhuǎn)載,并不用于任何商業(yè)目的,我們已經(jīng)盡可能的對作者和來源進(jìn)行了通告,但是能力有限或疏忽,造成漏登,請及時(shí)聯(lián)系我們,我們將根據(jù)著作權(quán)人的要求,立即更正或者刪除有關(guān)內(nèi)容。本站擁有對此聲明的最終解釋權(quán)。