石鳳貴
(馬鞍山師范高等專(zhuān)科學(xué)校軟件工程系,馬鞍山243041)
互聯(lián)網(wǎng)是一個(gè)龐大的知識(shí)庫(kù),在浩瀚的知識(shí)庫(kù)中,我們?nèi)绾嗡魅∷柚R(shí)?搜索引擎完成了這個(gè)任務(wù)。百度搜索是全球最大的中文搜索,擁有全球最大的中文網(wǎng)頁(yè)庫(kù),網(wǎng)頁(yè)數(shù)量每天以萬(wàn)級(jí)的速度增長(zhǎng)。百度提供的服務(wù)包括百度網(wǎng)頁(yè)、百度知道、百度貼吧等。搜索引擎大多以關(guān)鍵詞的方式檢索信息,不能清晰地理解用戶的要表達(dá)的意圖,返回結(jié)果是網(wǎng)頁(yè)的集合,需要用戶進(jìn)行二次篩選。對(duì)于傳統(tǒng)的自動(dòng)問(wèn)答系統(tǒng)需要建立一個(gè)非常龐大的知識(shí)庫(kù),這個(gè)成本相當(dāng)大。我們可以充分發(fā)揮搜索引擎和自動(dòng)問(wèn)答的各自優(yōu)點(diǎn),有機(jī)結(jié)合。
本文結(jié)合自然語(yǔ)言處理技術(shù)和網(wǎng)絡(luò)爬蟲(chóng)技術(shù),利用百度網(wǎng)頁(yè)搜索功能,構(gòu)建自動(dòng)問(wèn)答系統(tǒng)。將互聯(lián)網(wǎng)作為自動(dòng)問(wèn)答系統(tǒng)的知識(shí)庫(kù),通過(guò)爬蟲(chóng)技術(shù)利用百度搜索對(duì)用戶問(wèn)題進(jìn)行檢索,根據(jù)檢索結(jié)果構(gòu)建語(yǔ)料庫(kù),利用自然語(yǔ)言處理技術(shù)對(duì)檢索結(jié)果進(jìn)行答案提取,從而將答案返回給用戶。
自然語(yǔ)言處理(Natural Language Processing,簡(jiǎn)稱(chēng)NLP)是計(jì)算機(jī)科學(xué)領(lǐng)域與人工智能領(lǐng)域中的一個(gè)重要方向,研究人與計(jì)算機(jī)之間用自然語(yǔ)言進(jìn)行有效通信,融語(yǔ)言學(xué)、計(jì)算機(jī)科學(xué)、數(shù)學(xué)于一體的科學(xué)。問(wèn)答系統(tǒng)(Question Answering,簡(jiǎn)稱(chēng)QA)是自然語(yǔ)言處理領(lǐng)域的一個(gè)重要應(yīng)用,具有非常高的使用價(jià)值。
問(wèn)答系統(tǒng)模型[1]分為四層,分別為用戶層、問(wèn)題理解層、檢索層、數(shù)據(jù)層:
用戶層:即UI 層,提供用戶輸入問(wèn)題,顯示系統(tǒng)返回的答案。
問(wèn)題理解層:系統(tǒng)的核心層,負(fù)責(zé)問(wèn)題的理解,包括分詞、停用詞處理、計(jì)算相似度。
檢索層:負(fù)責(zé)內(nèi)容爬取、答案檢索,包括信息檢索、答案抽取。
數(shù)據(jù)層:知識(shí)庫(kù),處理數(shù)據(jù)庫(kù),主要包括專(zhuān)業(yè)詞典庫(kù)、停用詞庫(kù)、同義詞庫(kù)、領(lǐng)域本體庫(kù)、《知網(wǎng)》本體、QA集、互聯(lián)網(wǎng)。
問(wèn)答系統(tǒng)模型如圖1 所示。
(1)分詞
詞是表達(dá)句子意思的最小單位。中文語(yǔ)句結(jié)構(gòu)復(fù)雜,相對(duì)于英文沒(méi)有明顯的標(biāo)記,不像英文具有明顯的分界符。分詞是語(yǔ)句理解的基礎(chǔ)和關(guān)鍵。常用的方法主要有:基于字典分詞算法、向匹配法、基于統(tǒng)計(jì)的分詞算法、基于理解的分詞算法[2]。本文采用jieba 中文分詞工具進(jìn)行分詞。
(2)FAQ
FAQ 庫(kù)(Frequently Asked Question)是把用戶經(jīng)常提出的問(wèn)題和對(duì)應(yīng)的答案預(yù)先保存起來(lái),檢索時(shí)首先從FAQ 中檢索與用戶問(wèn)題相關(guān)的問(wèn)題,從而返回問(wèn)題的答案?;贔AQ 的問(wèn)答系統(tǒng)執(zhí)行效率和準(zhǔn)確度相對(duì)都比較高,同時(shí)也容易實(shí)現(xiàn),比較適合應(yīng)用于針對(duì)特定領(lǐng)域應(yīng)用的問(wèn)答系統(tǒng)。
本文為非特定領(lǐng)域應(yīng)用,借助FAQ 思想,利用爬蟲(chóng)技術(shù)爬取標(biāo)題和摘要,構(gòu)造問(wèn)題答案集。
(3)問(wèn)題分析
問(wèn)題分析是問(wèn)題理解的基礎(chǔ),只有科學(xué)的分析用戶提出的問(wèn)題才能準(zhǔn)確的理解用戶問(wèn)題。問(wèn)題分析需要通過(guò)一定的算法分析,包括問(wèn)題預(yù)處理、分詞、關(guān)鍵詞提取、消除停用詞、詞性標(biāo)注等[3]。
(4)信息檢索
信息檢索方式包括搜索引擎檢索、數(shù)據(jù)庫(kù)檢索。廣泛使用的搜索引擎有百度、Google、360 搜索等。數(shù)據(jù)庫(kù)檢索需要通過(guò)人工整理建立特定數(shù)據(jù)庫(kù),建立索引,選擇排序算法進(jìn)行排序。信息檢索的主要目的是通過(guò)搜索獲取大量文檔,返回與問(wèn)題相關(guān)的數(shù)據(jù)集。
字是構(gòu)成中文句子的最小單位,詞語(yǔ)表達(dá)句子的含義,是句子語(yǔ)義和句法的基本單位。因此,需要通過(guò)計(jì)算詞語(yǔ)的相似度來(lái)計(jì)算句子的相似度,詞語(yǔ)的相似度也應(yīng)結(jié)合其應(yīng)用背景。詞語(yǔ)相似度計(jì)算包含兩類(lèi):一類(lèi)是基于大規(guī)模語(yǔ)料庫(kù);一類(lèi)是基于語(yǔ)義詞典,如《知網(wǎng)》、《同義詞詞林》。
句子相似度由句子間語(yǔ)義上的匹配度反映,句子相似度計(jì)算就是計(jì)算兩個(gè)句子在語(yǔ)義上的吻合度,值的大小決定相似程度,取值為[0,1],值越大說(shuō)明越相似,反之越不相似。句子相似度計(jì)算可以分為:
(1)基于關(guān)鍵詞計(jì)算:提取句子中的關(guān)鍵詞,根據(jù)詞的詞頻和詞性對(duì)句子中的詞進(jìn)行處理。
(2)基于語(yǔ)義依存計(jì)算:深層次分析句子的句法結(jié)構(gòu),根據(jù)依存關(guān)系計(jì)算計(jì)算相似度。
(3)基于語(yǔ)義分析計(jì)算:構(gòu)建語(yǔ)義知識(shí)庫(kù),利用知識(shí)庫(kù)計(jì)算句子中詞的相似度,從而計(jì)算句子的相似度。
(4)編輯距離的相似度計(jì)算:分析兩個(gè)詞語(yǔ)轉(zhuǎn)變成相同詞語(yǔ)需要的最小步驟。
本文根據(jù)句子的詞向量的余弦值來(lái)計(jì)算句子的相似度。
本文分詞采用jieba 分詞,相似度計(jì)算采用Word2Vec 詞向量模型,答案語(yǔ)料庫(kù)采用網(wǎng)絡(luò)爬蟲(chóng)構(gòu)建,系統(tǒng)開(kāi)發(fā)工具采用Python。系統(tǒng)的實(shí)現(xiàn)引入了深度學(xué)習(xí)算法思想。
圖1
大數(shù)據(jù)時(shí)代,人類(lèi)社會(huì)的數(shù)據(jù)正處于急速增長(zhǎng)。數(shù)據(jù)蘊(yùn)含了巨大的價(jià)值,無(wú)論是對(duì)個(gè)人工作和生活還是企業(yè)發(fā)展和創(chuàng)新商業(yè)模式都有著很大的幫助。數(shù)據(jù)從何而來(lái)?需要從網(wǎng)絡(luò)獲取。要獲取全面、有效、準(zhǔn)確的數(shù)據(jù),不可能靠人工獲取,應(yīng)由程序從信息的海洋——互聯(lián)網(wǎng)抓取。這個(gè)從互聯(lián)網(wǎng)抓取數(shù)據(jù)的程序就是網(wǎng)絡(luò)爬蟲(chóng)。爬蟲(chóng)爬取的數(shù)據(jù),根據(jù)需要做進(jìn)一步的分析挖掘[5]。
本文語(yǔ)料庫(kù)直接利用網(wǎng)絡(luò)爬蟲(chóng)通過(guò)百度網(wǎng)頁(yè)搜索獲取,同時(shí)為了有效應(yīng)對(duì)網(wǎng)站反爬蟲(chóng),使用Chrome 瀏覽器的headless 模式實(shí)現(xiàn)。Headless 模式就是在無(wú)界面模式下運(yùn)行瀏覽器。
中文分詞是中文自然語(yǔ)言處理的第一步,一個(gè)優(yōu)秀的分詞系統(tǒng)取決于足夠的語(yǔ)料和完善的模型。很多機(jī)構(gòu)都會(huì)開(kāi)發(fā)和維護(hù)自己的分詞系統(tǒng),本文使用一款完全開(kāi)源、簡(jiǎn)單易用的分詞工具——jieba 中文分詞。
中文分詞的模型主要分為兩大類(lèi):基于規(guī)則和基于統(tǒng)計(jì),jieba 分詞結(jié)合了基于規(guī)則和基于統(tǒng)計(jì)兩類(lèi)方法,同時(shí)jieba 提供了3 中分詞模式。jieba 支持分詞、關(guān)鍵詞提取、詞性標(biāo)注、自定義分詞詞典和停用詞詞典。文本分詞后就可以制作詞向量[4]。
計(jì)算機(jī)只能識(shí)別和計(jì)算數(shù)字,傳入模型計(jì)算的數(shù)據(jù)只能是數(shù)字或向量,處理自然語(yǔ)言時(shí)首先就要進(jìn)行數(shù)據(jù)預(yù)處理即符號(hào)數(shù)學(xué)化。最初一般采用One-Hot 獨(dú)熱編碼,但沒(méi)有考慮詞的含義和詞之間的關(guān)系。最常見(jiàn)、效果比較好的就是詞向量Word2Vec。
(1)語(yǔ)言模型
詞向量是在訓(xùn)練詞語(yǔ)言模型的同時(shí)得到的。要想從自然語(yǔ)言文本中學(xué)習(xí)有效信息,需要從自然語(yǔ)言文本中統(tǒng)計(jì)并建立一個(gè)語(yǔ)言模型。這里介紹的是從大量未標(biāo)注的普通文本數(shù)據(jù)中無(wú)監(jiān)督的學(xué)習(xí)出詞向量。
(2)數(shù)據(jù)格式化處理
分詞完成后,如果文本規(guī)模較大,分詞結(jié)果應(yīng)保存為文件,如果較小可以直接制作詞向量。制作詞向量前,需要將數(shù)據(jù)處理成gensim 可以處理的格式:
方法1:直接處理成列表嵌套的數(shù)據(jù)格式,如[[第一句分詞],[第二句分詞],…]。
方法2:利用gensim.models.word2vec 模塊中Line-Sentence、PathLineSentences、Text8Corpus 類(lèi)讀取分詞結(jié)果文件,生成一個(gè)迭代對(duì)象,封裝的內(nèi)容是分詞后的詞列表。
本文語(yǔ)料為動(dòng)態(tài)語(yǔ)料,同時(shí)規(guī)模較小,因此采用方法1 格式化數(shù)據(jù)。
(3)訓(xùn)練詞向量模型
word2vec.Word2Vec (sentences=None, size=100, window=5,min_count=5)
sentences:就是上面的準(zhǔn)備好的數(shù)據(jù),可以是簡(jiǎn)單的list 或這個(gè)是其他幾個(gè)方法生成的可迭代對(duì)象。size:生成詞向量的大小,也就是特征向量的維數(shù)。window:一個(gè)詞上下文的最大關(guān)聯(lián)距離,即上下文幾個(gè)詞對(duì)這個(gè)詞有影響。
min_count:忽略詞頻小于這個(gè)值的詞;還有一些學(xué)習(xí)率等參數(shù)。
使用jieba 中文分詞工具進(jìn)行分詞。
def tokenizer(sentence):
words_cut=jieba.cut(sentence,cut_all=False)
return list(words_cut)#返回分詞結(jié)果
根據(jù)用戶問(wèn)題爬取相應(yīng)資源,構(gòu)建問(wèn)題-答案語(yǔ)料。
Step1:爬蟲(chóng)打開(kāi)百度首頁(yè),將用戶問(wèn)題輸入到搜索框后執(zhí)行搜索
def spider(driver,keyword_q): #driver:瀏覽器,keyword_q:用戶輸入的問(wèn)題
#打開(kāi)百度首頁(yè)
driver.get("https://www.baidu.com")
time.sleep(2)
#獲取輸入框
inputKeyWord = driver.find_element_by_xpath('//*[@id="kw"]')
inputKeyWord.send_keys(keyword_q)#輸入搜索內(nèi)容
#獲取”百度一下”按鈕
submit_baidu = driver.find_element_by_xpath('//*[@id="su"]')
submit_baidu.click()#單擊按鈕
Step2:解析爬取結(jié)果首頁(yè),構(gòu)建問(wèn)題-答案語(yǔ)料
#driver:瀏覽器,wordlists_question_cut:保存問(wèn)題-答案對(duì)中問(wèn)題分詞
def parse(driver,wordlists_question_cut):
#解析標(biāo)題-摘要代碼段,過(guò)濾搜索結(jié)果中關(guān)于廣告的主題
內(nèi)容
title_abstracts = driver.find_elements_by_xpath('//*[@class="result c-container"]')
title_abstracts.extend (driver.find_elements_by_xpath ('//*[@class="result-op c-container xpath-log"]'))
#解析keyword-abstract 對(duì)
for title_abstract in title_abstracts:
#解析出標(biāo)題代碼塊
#解析出標(biāo)題鏈接
#構(gòu)造含有鏈接的標(biāo)題即Q
#對(duì)標(biāo)題內(nèi)容即Q 進(jìn)行分詞并保存
#解析摘要代碼塊,然后解析文本內(nèi)容
#保存問(wèn)題-答案對(duì)
return 問(wèn)題答案集
def trainModel(modelname,train_corpus_words_cut):
#設(shè)置模型參數(shù)
size=400 #每個(gè)詞的向量維度
window=5 #詞向量訓(xùn)練時(shí)的上下文掃描窗口大小,窗口為5 就是考慮前5 個(gè)詞和后5 個(gè)詞
min_count=1 #設(shè)置最低頻率,默認(rèn)是5,如果一個(gè)詞語(yǔ)在文檔中出現(xiàn)的次數(shù)小于5,那么就會(huì)丟棄
workers = multiprocessing.cpu_count()# 訓(xùn)練的進(jìn)程數(shù),默認(rèn)是當(dāng)前運(yùn)行機(jī)器的處理器核數(shù)。
model=word2vec.Word2Vec()#訓(xùn)練模型
return model
計(jì)算用戶問(wèn)題與問(wèn)答答案集中問(wèn)題的向量夾角余弦值來(lái)計(jì)算他們的相似度。
def calSimilarity_Q(model,wordlist_Qask_cut,wordlists_Q_cut):
similarity_Qs={} #保存Q 的相似度,便于后面檢索答案
for wordlist_Q in wordlists_Q_cut:
similarity = model.n_similarity (wordlist_Qask_cut,wordlist_Q)
Q_text="".join(wordlist_Q)#將Q 分詞結(jié)果還原為Q 內(nèi)容
similarity_Qs[Q_text]=similarity
return similarity_Qs
def search_A(similarity_Qs,Q_As):
#按照字典similarity_Qs 的value 值(相似度)降序,
#取Top5
#遍歷問(wèn)題答案集,如果檢索到就返回檢索結(jié)果
return 檢索結(jié)果
圖2
圖3
本文對(duì)問(wèn)答系統(tǒng)相關(guān)技術(shù)進(jìn)行了分析,構(gòu)建了問(wèn)答系統(tǒng)模型,介紹了系統(tǒng)實(shí)現(xiàn)所使用的網(wǎng)絡(luò)爬蟲(chóng)、jieba中文分詞、Word2Vec 詞向量等關(guān)鍵技術(shù),給出了系統(tǒng)實(shí)現(xiàn)的詳細(xì)算法,最后提供了系統(tǒng)使用效果。從運(yùn)行效果來(lái)看,能很好地滿足用戶的需求。