何艷,張寧
西安郵電大學(xué) 通信與信息工程學(xué)院,陜西 西安 710121
通過(guò)互聯(lián)網(wǎng)得到科學(xué)準(zhǔn)確的醫(yī)療服務(wù)與人們的幸福生活密切相關(guān),智能問(wèn)答平臺(tái)有助于快速篩選搜索信息。自動(dòng)聊天機(jī)器人可分為以信息提取為基礎(chǔ)的專(zhuān)家系統(tǒng)和自主生產(chǎn)學(xué)習(xí)式的開(kāi)放領(lǐng)域問(wèn)答平臺(tái)系統(tǒng)[1]。垂直領(lǐng)域的專(zhuān)家系統(tǒng)大大壓縮了數(shù)據(jù)規(guī)模,適用于醫(yī)療領(lǐng)域的應(yīng)用開(kāi)發(fā)[2]。語(yǔ)義分析是實(shí)現(xiàn)智能問(wèn)答的基本途徑。在傳統(tǒng)TextRank算法和Word2Vec基礎(chǔ)上,Python以MySQL+Flask web +vue分級(jí)架構(gòu)實(shí)現(xiàn)了知識(shí)自動(dòng)問(wèn)答[3]。醫(yī)療數(shù)據(jù)包含大量冗余文本數(shù)據(jù)。聯(lián)合標(biāo)注策略的實(shí)體關(guān)系抽取模型使用NoSQL數(shù)據(jù)庫(kù)Neo4j存儲(chǔ)知識(shí)數(shù)據(jù),獲得較高檢索效率[4]。Java語(yǔ)言的MVC(Model、View、Controller)架構(gòu)將后臺(tái)運(yùn)算與前端顯示分離[5-6]。利用多源異構(gòu)數(shù)據(jù)構(gòu)建醫(yī)療相關(guān)知識(shí)庫(kù),聯(lián)合中文分詞和醫(yī)療詞典,準(zhǔn)確識(shí)別醫(yī)療相關(guān)領(lǐng)域詞匯[7]。不同數(shù)據(jù)庫(kù)的知識(shí)存儲(chǔ)會(huì)影響問(wèn)答效率。MySQL體積小、速度快,在靈活性上遠(yuǎn)超SQL Sever和Oracle數(shù)據(jù)庫(kù)[8]。利用Redis數(shù)據(jù)庫(kù)緩存,可提高系統(tǒng)處理高并發(fā)場(chǎng)景時(shí)的效率[9]。ANSJ實(shí)現(xiàn)分詞,且標(biāo)注分詞后詞性,在內(nèi)存中分詞速率100萬(wàn)字/s,準(zhǔn)確度達(dá)96%以上[10-11]。Spring作為JavaWeb框架,集成了控制翻轉(zhuǎn)和面向切面編程的特點(diǎn)[12-13]。布隆過(guò)濾器利用錯(cuò)誤率換取更小的空間占用,其操作時(shí)間復(fù)雜度為O(1)[14-15]。本文旨在設(shè)計(jì)實(shí)現(xiàn)一款智能問(wèn)答系統(tǒng),通過(guò)用戶(hù)對(duì)自身病情癥狀的描述,系統(tǒng)通過(guò)語(yǔ)義解析得到合理準(zhǔn)確的醫(yī)療指導(dǎo),進(jìn)而給人們提供日常的健康醫(yī)療咨詢(xún)。
本醫(yī)療問(wèn)答系統(tǒng)設(shè)計(jì)框圖如圖1所示,系統(tǒng)采用分級(jí)架構(gòu),使得數(shù)據(jù)庫(kù)、邏輯層、展示層分開(kāi),便于分層開(kāi)發(fā)維護(hù)。
圖1 系統(tǒng)設(shè)計(jì)框圖
后端代碼結(jié)構(gòu)大致分為Controller、Dao、Pojo、Service、Test五部分。其中Controller層負(fù)責(zé)與前端代碼的交互,接收或發(fā)送數(shù)據(jù)到前端。Pojo層存儲(chǔ)項(xiàng)目對(duì)應(yīng)的數(shù)據(jù)模型類(lèi)。Service層負(fù)責(zé)處理項(xiàng)目的主要邏輯。Test負(fù)責(zé)代碼的調(diào)試與測(cè)試功能。圖2展示了后端項(xiàng)目代碼結(jié)構(gòu)。
圖2 后端項(xiàng)目代碼結(jié)構(gòu)
在數(shù)據(jù)庫(kù)連接的部分,采用基于JDBC的Java數(shù)據(jù)庫(kù)連接工具M(jìn)ybatis進(jìn)行Java程序與MySQL數(shù)據(jù)庫(kù)的連接。使用注解的方式完成連接,并將SQL語(yǔ)句卸載至xml文件中,便于維護(hù)管理[16]。同時(shí)項(xiàng)目采用了Mybatis自帶的SQL預(yù)處理方式,避免了SQL注入的風(fēng)險(xiǎn)。
醫(yī)療問(wèn)答系統(tǒng)的數(shù)據(jù)模型包括用戶(hù)集合、疾病集合和用戶(hù)患病集合。用戶(hù)集合用于存儲(chǔ)普通用戶(hù)在平臺(tái)進(jìn)行登錄、注冊(cè)、問(wèn)答咨詢(xún)所需的基本信息;疾病集合用于存儲(chǔ)爬取的醫(yī)療相關(guān)信息;用戶(hù)患病集合用于存儲(chǔ)疾病與用戶(hù)之間的對(duì)應(yīng)關(guān)系,形成用戶(hù)表與疾病表之間多對(duì)多的表間關(guān)系。各表間關(guān)系繪制成實(shí)體聯(lián)系圖如圖3所示。
圖3 系統(tǒng)數(shù)據(jù)庫(kù)實(shí)體聯(lián)系圖
由于項(xiàng)目前后端分離的設(shè)計(jì),在本機(jī)測(cè)試時(shí)兩端會(huì)分別占用不同端口,前端Vue部分占用8080端口,后端占用8081端口。前后端的數(shù)據(jù)交互采用JSON(JavaScript Object Notation)數(shù)據(jù)格式。依照J(rèn)SON將后端Java實(shí)體類(lèi)序列化成字符串的格式發(fā)送至前端解析,同時(shí)前端也能發(fā)送JSON至后端,經(jīng)由后端轉(zhuǎn)換為實(shí)體類(lèi)。在Java中,可以將JSON還原為HashMap結(jié)構(gòu)或者一個(gè)基本對(duì)象。
本系統(tǒng)在多個(gè)角度進(jìn)行了并發(fā)設(shè)計(jì),確保了程序的穩(wěn)定性(圖4)。系統(tǒng)設(shè)計(jì)將Tomcat服務(wù)器默認(rèn)提供的BIO模式改配置為NIO模式。BIO模式下,每次請(qǐng)求會(huì)新建一個(gè)線程去處理,線程的創(chuàng)建與銷(xiāo)毀極大地浪費(fèi)了系統(tǒng)資源,改為NIO模式后不用每次阻塞線程,提高了系統(tǒng)效率。在編寫(xiě)Java代碼時(shí),內(nèi)部使用了HashMap作為緩存暫時(shí)存儲(chǔ)數(shù)據(jù)庫(kù)查詢(xún)結(jié)果,避免每次處理時(shí)對(duì)數(shù)據(jù)庫(kù)的反復(fù)查詢(xún)。利用WebMagic的多線程爬蟲(chóng)特性爬取醫(yī)療數(shù)據(jù),開(kāi)啟5個(gè)線程同時(shí)爬取,提高了系統(tǒng)速度。
圖4 醫(yī)療問(wèn)答系統(tǒng)的并發(fā)設(shè)計(jì)圖
考慮到系統(tǒng)各模塊間耦合度高,本系統(tǒng)在架構(gòu)設(shè)計(jì)上采用MVC模式解耦合。將系統(tǒng)拆分為View(前端視圖層)、Controller(邏輯控制層)、Model(中間數(shù)據(jù)邏輯層),分別對(duì)應(yīng)后端代碼中的Controller、Service、Pojo三個(gè)文件夾。其中Controller文件夾中主要編寫(xiě)基于SpringMVC的相關(guān)代碼,負(fù)責(zé)通過(guò)http協(xié)議完成前后端數(shù)據(jù)交互。Service文件夾中主要編寫(xiě)問(wèn)答系統(tǒng)的主要邏輯,即接收到問(wèn)題后對(duì)問(wèn)題處理并回復(fù)的過(guò)程。Pojo文件夾中則存放系統(tǒng)用到的實(shí)體類(lèi),包括用戶(hù)類(lèi)、醫(yī)療信息類(lèi)。三層分離編寫(xiě),互不干擾。三層間通過(guò)數(shù)據(jù)接口交互,方便分模塊糾錯(cuò)。
問(wèn)答模塊是系統(tǒng)的主要邏輯模塊,具體流程是前端接收用戶(hù)輸入的語(yǔ)句傳輸至后端,隨后進(jìn)入Service層。通過(guò)Ansj對(duì)語(yǔ)句進(jìn)行分詞處理,并按照詞性摘取出語(yǔ)句中的動(dòng)詞、名詞等作重點(diǎn)處理,并將其存入HashMap標(biāo)記為InfoMap。依次遍歷InfoMap中的所有詞,并在MySQL數(shù)據(jù)庫(kù)中查找相關(guān)疾病的癥狀,并記錄疾病名稱(chēng)和出現(xiàn)次數(shù)至Disease Map中,最后通過(guò)SpringMVC反饋給前端。
用戶(hù)信息處理模塊包含對(duì)用戶(hù)注冊(cè)信息的數(shù)據(jù)庫(kù)寫(xiě)入以及對(duì)登錄用戶(hù)信息的查庫(kù)校驗(yàn)。項(xiàng)目中的User類(lèi)對(duì)應(yīng)MySQL中的User表,分別設(shè)置Uid、UName、Password三個(gè)字段,簡(jiǎn)單地實(shí)現(xiàn)了登錄注冊(cè)功能所需要的所有信息。用戶(hù)通過(guò)/login進(jìn)入登錄模塊前端頁(yè)面,輸入用戶(hù)名密碼后發(fā)送至后端,在通過(guò)MySQL查詢(xún)登錄信息完成校驗(yàn),校驗(yàn)成功后自動(dòng)轉(zhuǎn)入問(wèn)答模塊。注冊(cè)功能則是在數(shù)據(jù)庫(kù)中存入用戶(hù)的注冊(cè)信息,注冊(cè)完成后返回登錄頁(yè)面。
信息獲取模塊負(fù)責(zé)自動(dòng)獲取醫(yī)療網(wǎng)站內(nèi)醫(yī)療相關(guān)的信息,醫(yī)療數(shù)據(jù)內(nèi)容爬取后重新存儲(chǔ),見(jiàn)圖5。借助WebMagic提供的爬蟲(chóng)接口,使用Java線程池技術(shù)配置多個(gè)線程同時(shí)爬蟲(chóng),考慮到本電腦使用四核CPU,確定開(kāi)啟五個(gè)線程,理論上獲得了五倍速度的爬蟲(chóng)效率。通過(guò)爬蟲(chóng)獲取疾病名稱(chēng)、疾病描述、病因、癥狀、治療手段、診斷鑒別等多種信息,對(duì)應(yīng)創(chuàng)建其Java類(lèi)用于存儲(chǔ),最后通過(guò)Mybatis的持久化技術(shù)將醫(yī)療數(shù)據(jù)存儲(chǔ)至MySQL數(shù)據(jù)庫(kù)中。
圖5 爬取獲得的醫(yī)療數(shù)據(jù)內(nèi)容
網(wǎng)絡(luò)爬蟲(chóng)策略包括借助棧結(jié)構(gòu)實(shí)現(xiàn)的深度優(yōu)先搜索、借助隊(duì)列實(shí)現(xiàn)的廣度優(yōu)先搜索以及最佳優(yōu)先搜索。
最佳優(yōu)先搜索比深度優(yōu)先策略和廣度優(yōu)先搜索策略更加復(fù)雜,但在面對(duì)大量網(wǎng)頁(yè)爬取的任務(wù)時(shí),能更好地過(guò)濾掉30%以上的無(wú)關(guān)網(wǎng)頁(yè)。它的邏輯是在爬取之前先對(duì)候選URL進(jìn)行一系列的相似度分析,并最終選擇爬取與主題相關(guān)度更高的網(wǎng)頁(yè),節(jié)省計(jì)算機(jī)資源。
WebMagic是一個(gè)基于Java的開(kāi)源爬蟲(chóng)框架,其整體 結(jié) 構(gòu) 包 括 Downloader、PageProcessor、Scheduler和Pipeline四個(gè)組件,分別對(duì)應(yīng)爬蟲(chóng)生命周期中的下載、清洗、時(shí)間管理和持久化。需要將這些組件結(jié)合并完成多線程任務(wù)以提高爬蟲(chóng)效率,同時(shí)使用容器spider將組件組織起來(lái)協(xié)作完成任務(wù)。圖6展示了Web Magic各模塊協(xié)作工作流程。
圖6 WebMagic運(yùn)行流程圖
數(shù)據(jù)庫(kù)技術(shù)主要研究目標(biāo)是數(shù)據(jù),實(shí)現(xiàn)數(shù)據(jù)高效存儲(chǔ)與快速獲取。目前的主流數(shù)據(jù)庫(kù)分為關(guān)系型數(shù)據(jù)庫(kù)與非關(guān)系型數(shù)據(jù)庫(kù)兩種。關(guān)系型數(shù)據(jù)庫(kù)指采用行列表格形式組織數(shù)據(jù),其主要模塊是二維的表格。如圖7所示分為表頭和內(nèi)容,多個(gè)數(shù)據(jù)表組成了數(shù)據(jù)庫(kù)。為了避免數(shù)據(jù)重復(fù)存儲(chǔ),按照最小關(guān)系表的形式存儲(chǔ),采用SQL對(duì)數(shù)據(jù)庫(kù)進(jìn)行增刪改查等操作。
圖7 關(guān)系型數(shù)據(jù)庫(kù)的數(shù)據(jù)表
非關(guān)系型數(shù)據(jù)庫(kù)也被叫作NoSQL(不適于SQL語(yǔ)句的意思),其速度優(yōu)勢(shì)得益于Hash數(shù)據(jù)結(jié)構(gòu),其預(yù)先準(zhǔn)備適當(dāng)長(zhǎng)度的存儲(chǔ)空間,并做線性標(biāo)記。當(dāng)有數(shù)據(jù)存入空間時(shí),采用特定哈希算法計(jì)算數(shù)據(jù)位置后存入,在后續(xù)查詢(xún)過(guò)程中,只需要將查詢(xún)?cè)~再次進(jìn)行哈希計(jì)算,就能在01的復(fù)雜度內(nèi)完成查詢(xún)操作,同比使用了B+樹(shù)的MySQL數(shù)據(jù)庫(kù),查詢(xún)的時(shí)間復(fù)雜度遠(yuǎn)遠(yuǎn)超過(guò)01。
分詞技術(shù)將連續(xù)詞語(yǔ)組成的句子重新分割成各個(gè)詞語(yǔ),便于計(jì)算機(jī)分治處理。中文分詞算法大致分為基于詞典的分詞算法與基于人工智能統(tǒng)計(jì)的分詞算法。Java語(yǔ)言提供了盤(pán)古分詞、NLPIR、IKAnalyzer、PaodingAnalyzer等分詞工具。由于AnsjSeg提供便捷的分詞接口,分詞處理后,框架將會(huì)返回句子中所有詞語(yǔ)與其所對(duì)應(yīng)的詞性,因此本文將采用AnsjSeg分詞工具。
Mybatis是源于Apache的一個(gè)開(kāi)源項(xiàng)目,完成了對(duì)底層JDBC的封裝,簡(jiǎn)化了后端連接數(shù)據(jù)庫(kù)的步驟,對(duì)外提供簡(jiǎn)便的接口。其解除了SQL語(yǔ)句與程序代碼的耦合,將業(yè)務(wù)層與數(shù)據(jù)訪問(wèn)分離使系統(tǒng)結(jié)構(gòu)更加清晰。
用戶(hù)自主輸入隨意用戶(hù)名密碼即可完成注冊(cè),注冊(cè)成功后系統(tǒng)自動(dòng)跳轉(zhuǎn)到登錄頁(yè)。用戶(hù)在輸入自身癥狀后,系統(tǒng)會(huì)反饋可能性病癥以及其可能性權(quán)值。用戶(hù)登錄成功后,頁(yè)面將自動(dòng)跳轉(zhuǎn)到/work路徑展示問(wèn)答頁(yè)面,用戶(hù)向第一個(gè)輸入框內(nèi)輸入疾病癥狀(不需要特殊格式),點(diǎn)擊提交按鈕后,前端自動(dòng)將內(nèi)容提交至后臺(tái)分析,隨后Java后臺(tái)經(jīng)過(guò)分詞處理后向數(shù)據(jù)庫(kù)查詢(xún)結(jié)果,結(jié)果集將封裝在TreeMap中暫存,由于TreeMap可以將key值排序,所以得到疾病可能性權(quán)值將從小到大展示。
數(shù)據(jù)庫(kù)中的醫(yī)療數(shù)據(jù)均由數(shù)據(jù)獲取模塊提供,首先對(duì)被爬取網(wǎng)頁(yè)進(jìn)行分析,確保其Robot協(xié)議允許用戶(hù)爬蟲(chóng)。隨后分析其頁(yè)面結(jié)構(gòu)尋找需要爬取的頁(yè)面特性,通過(guò)WebMagic對(duì)頁(yè)面進(jìn)行解析,獲取其中關(guān)鍵標(biāo)簽所包含的有用信息,在遇到多種冗余信息存儲(chǔ)于同一標(biāo)簽下時(shí),則采用CSS選擇器篩選出符合條件的數(shù)據(jù)。并將其保存至Java的Static靜態(tài)類(lèi)中(靜態(tài)類(lèi)保證了在類(lèi)中字段填滿(mǎn)之前,爬蟲(chóng)的重復(fù)執(zhí)行并不會(huì)刷新對(duì)象中內(nèi)容),等到類(lèi)的其他字段通過(guò)爬蟲(chóng)填滿(mǎn)后統(tǒng)一寫(xiě)入數(shù)據(jù)庫(kù),完成一組數(shù)據(jù)的爬取。
項(xiàng)目測(cè)試環(huán)境為Windows 10 PC一臺(tái),Java8編譯環(huán)境,F(xiàn)irefox瀏覽器。使用Java首先啟動(dòng)graduationdesign項(xiàng)目,查看SpringBoot啟動(dòng)日志,確定8081端口打開(kāi)無(wú)誤后再啟動(dòng)前端VUE代碼。項(xiàng)目啟動(dòng)效果如圖8~9所示。
圖8 后端項(xiàng)目啟動(dòng)頁(yè)面
圖9 前端項(xiàng)目啟動(dòng)頁(yè)面
問(wèn)答模塊測(cè)試使用用戶(hù)組織的語(yǔ)言對(duì)系統(tǒng)進(jìn)行提問(wèn),系統(tǒng)將自動(dòng)反饋可能性病癥,并以JASON的數(shù)據(jù)格式發(fā)送至前端,包括疾病的名稱(chēng)及可能性權(quán)值,癥狀描述越多越準(zhǔn)確??梢栽跒g覽器中查詢(xún)到前后端數(shù)據(jù)交互的情況如圖10所示。在數(shù)據(jù)爬蟲(chóng)測(cè)試中,后端提前綁定MySQL服務(wù)器,啟動(dòng)后自動(dòng)查找尋醫(yī)問(wèn)藥網(wǎng)中關(guān)于呼吸科的疾病信息,同一疾病分別爬取疾病的名稱(chēng)、癥狀、治療方法、病因、簡(jiǎn)介五個(gè)信息后,進(jìn)行數(shù)據(jù)庫(kù)查詢(xún)校驗(yàn),如果與庫(kù)中數(shù)據(jù)不重復(fù),統(tǒng)一存入數(shù)據(jù)庫(kù)。
圖10 問(wèn)答功能數(shù)據(jù)交互詳情
醫(yī)學(xué)領(lǐng)域的信息化和智慧化建設(shè)是當(dāng)前迫切需要解決的難題。在信息技術(shù)發(fā)展的同時(shí),人們也逐步由初始的單純對(duì)速度與信息量的追求,進(jìn)而發(fā)展為對(duì)信息準(zhǔn)確性和高效性的追求。目前市面上的各類(lèi)搜索引擎所提供的信息檢索服務(wù)大都趨向于百科全書(shū)式的大雜燴,用戶(hù)搜索關(guān)鍵知識(shí)時(shí),往往會(huì)檢索出許多冗余的“垃圾”數(shù)據(jù),浪費(fèi)人們的時(shí)間。還有一些搜索引擎在返回正常搜索數(shù)據(jù)的同時(shí)還會(huì)夾雜一些廣告,使得用戶(hù)的搜索效率大幅降低。傳統(tǒng)搜索引擎在醫(yī)療領(lǐng)域的使用,有助于獲取互聯(lián)網(wǎng)上全面的信息資源,但如何篩選信息成為難題。
本文開(kāi)發(fā)設(shè)計(jì)的基于JavaEE的醫(yī)療問(wèn)答系統(tǒng),通過(guò)網(wǎng)絡(luò)爬蟲(chóng)爬取醫(yī)療相關(guān)數(shù)據(jù),并將其存儲(chǔ)至MySQL數(shù)據(jù)庫(kù)中。用戶(hù)注冊(cè)系統(tǒng)后,后臺(tái)數(shù)據(jù)庫(kù)保存其個(gè)人信息,登錄系統(tǒng)后顯示提問(wèn)頁(yè)面。用戶(hù)發(fā)問(wèn)后利用分詞技術(shù)分析問(wèn)題,快速將反饋結(jié)果發(fā)送至前端,實(shí)現(xiàn)用戶(hù)注冊(cè)、登錄、注銷(xiāo)、查詢(xún)等基本功能。
由于醫(yī)療領(lǐng)域的專(zhuān)業(yè)性和需求迫切性,各種不同形式的醫(yī)療問(wèn)答系統(tǒng)被推向市場(chǎng),如騰訊醫(yī)典、平安好醫(yī)生以及丁香醫(yī)生等。區(qū)別于傳統(tǒng)搜索引擎,本文開(kāi)發(fā)的醫(yī)療問(wèn)答系統(tǒng)將目標(biāo)聚焦于垂直醫(yī)療領(lǐng)域,通過(guò)對(duì)用戶(hù)語(yǔ)句的語(yǔ)義分析進(jìn)行模糊匹配,確保搜索的結(jié)果信息控制在一個(gè)較小的維度,為患者提供準(zhǔn)確、高效的醫(yī)療咨詢(xún)服務(wù)。利用基于JavaEE的醫(yī)療問(wèn)答系統(tǒng)可以實(shí)現(xiàn)用戶(hù)對(duì)于自身癥狀的初步判斷,系統(tǒng)通過(guò)分析用戶(hù)提供的癥狀描述,取得用戶(hù)描述內(nèi)容的關(guān)鍵詞,將關(guān)鍵詞與醫(yī)療數(shù)據(jù)庫(kù)中內(nèi)容匹配,通過(guò)規(guī)則推理和本體描述實(shí)現(xiàn)問(wèn)答功能。本文開(kāi)發(fā)實(shí)現(xiàn)的基于Java的醫(yī)療問(wèn)答系統(tǒng),其注冊(cè)登錄流程簡(jiǎn)潔,界面層級(jí)清晰,通過(guò)分詞技術(shù)和關(guān)系型數(shù)據(jù)庫(kù)的聯(lián)合使用,結(jié)合爬蟲(chóng)策略,實(shí)現(xiàn)了醫(yī)療垂直領(lǐng)域的問(wèn)答,能便捷、及時(shí)解決用戶(hù)健康需求。本系統(tǒng)采用了高擴(kuò)展性系統(tǒng)架構(gòu),未來(lái)可以進(jìn)一步擴(kuò)充性能,以提供更智慧快捷的醫(yī)療服務(wù)。
與此同時(shí),本系統(tǒng)也有許多需要優(yōu)化改進(jìn)的地方。前端頁(yè)面的UI以功能實(shí)用為主,沒(méi)有考慮到美學(xué)設(shè)計(jì)理念。此外,目前系統(tǒng)只是爬取了呼吸內(nèi)科相關(guān)疾病,后臺(tái)數(shù)據(jù)庫(kù)中醫(yī)療數(shù)據(jù)的爬取不夠全面。在問(wèn)答過(guò)程中問(wèn)答信息偏學(xué)術(shù)化,略顯機(jī)械,后續(xù)需改進(jìn)該系統(tǒng)的人性化。