曹金超,黃 滔,陳 剛,3,吳曉凡,陳 珂,3+
1.浙江大學(xué) 計(jì)算機(jī)科學(xué)與技術(shù)學(xué)院,杭州310027
2.浙江邦盛科技有限公司,杭州310012
3.浙江大學(xué) 浙江省大數(shù)據(jù)智能計(jì)算重點(diǎn)實(shí)驗(yàn)室,杭州310027
4.網(wǎng)易(杭州)網(wǎng)絡(luò)有限公司,杭州310051
隨著信息技術(shù)的快速變革,如何通過(guò)自然語(yǔ)言直接與傳統(tǒng)關(guān)系數(shù)據(jù)庫(kù)交互,也就是如何將人的自然問(wèn)句轉(zhuǎn)化成數(shù)據(jù)庫(kù)可以執(zhí)行的SQL(structured query language)語(yǔ)句已經(jīng)成為人工智能領(lǐng)域的研究熱點(diǎn)之一。為方便管理,可以利用關(guān)系型數(shù)據(jù)庫(kù)來(lái)存儲(chǔ)數(shù)據(jù),然而通過(guò)關(guān)系型數(shù)據(jù)庫(kù)來(lái)查詢數(shù)據(jù)需要預(yù)先學(xué)習(xí)數(shù)據(jù)庫(kù)系統(tǒng)以及數(shù)據(jù)庫(kù)查詢語(yǔ)句SQL上的專業(yè)知識(shí),這對(duì)一個(gè)普通用戶來(lái)說(shuō)顯然很難實(shí)現(xiàn)。為了解決這個(gè)問(wèn)題,許多研究工作都采用了相似的解決思路,通過(guò)實(shí)現(xiàn)一個(gè)自然語(yǔ)言查詢接口(natural language interface,NLI)來(lái)完成用戶通過(guò)日常使用的自然語(yǔ)言與數(shù)據(jù)庫(kù)進(jìn)行交互從而獲取想要查詢的數(shù)據(jù)[1]。
如今,自然語(yǔ)言查詢接口也產(chǎn)生了很多商業(yè)上的應(yīng)用,例如智能語(yǔ)音助手、智能搜索引擎和對(duì)話系統(tǒng)等。同時(shí),該問(wèn)題亦是新型供電軌道交通系統(tǒng)混合時(shí)態(tài)大數(shù)據(jù)個(gè)性化運(yùn)維的最棘手的難點(diǎn)之一。
NLI 最重要的一個(gè)部分就是將自然語(yǔ)言查詢描述轉(zhuǎn)化為標(biāo)準(zhǔn)的SQL 查詢語(yǔ)句(NL2SQL)。針對(duì)這個(gè)問(wèn)題,目前有兩個(gè)不同的解決思路:(1)流水線方法,將自然語(yǔ)言查詢轉(zhuǎn)化為一種中間表達(dá),再將其映射為SQL 語(yǔ)句;(2)深度學(xué)習(xí)方法,使用端到端的神經(jīng)網(wǎng)絡(luò)來(lái)完成轉(zhuǎn)化[1]。
流水線方法將自然語(yǔ)言轉(zhuǎn)化為中間表達(dá)的過(guò)程依賴于自然語(yǔ)言查詢的規(guī)則化描述,因此無(wú)法處理一些復(fù)雜多變的自然語(yǔ)言描述。而近年來(lái),隨著深度學(xué)習(xí)技術(shù)的不斷發(fā)展,使用神經(jīng)網(wǎng)絡(luò)模型來(lái)處理NL2SQL 的工作也越發(fā)普遍。其優(yōu)勢(shì)較前者在于不受自然語(yǔ)言描述多樣性的限制,也能從復(fù)雜的表達(dá)中提取出關(guān)注的語(yǔ)義信息。但現(xiàn)有NL2SQL 的深度學(xué)習(xí)方法存在著一定的局限性,需指定當(dāng)前自然語(yǔ)言查詢對(duì)應(yīng)數(shù)據(jù)庫(kù)中的哪一張表,也就忽略了自然語(yǔ)言查詢到對(duì)應(yīng)查詢表的映射,同時(shí)也無(wú)法支持如圖1中所示例的多表查詢。
從這個(gè)局限性出發(fā),本文針對(duì)自然語(yǔ)言生成多表SQL查詢的問(wèn)題提出了一種解決方法。本文主要的工作和貢獻(xiàn)如下:
(1)相比于現(xiàn)有工作基于模板的深度學(xué)習(xí)模型,本文的深度學(xué)習(xí)模型能處理更復(fù)雜的自然語(yǔ)言查詢,因此能生成更為復(fù)雜的SQL 語(yǔ)句,包括GROUP BY、ORDER BY等關(guān)鍵詞;
(2)利用深度學(xué)習(xí)模型生成的部分SQL 子句提及的表和數(shù)據(jù)庫(kù)模式圖,采用了一種全局最優(yōu)的算法來(lái)生成FROM子句中多表的JOIN路徑;
(3)通過(guò)在一個(gè)開(kāi)放的復(fù)雜自然語(yǔ)言生成SQL的數(shù)據(jù)集Spider上與其他多種模型的對(duì)比,本文方法具有更高的準(zhǔn)確率。
盡管自然語(yǔ)言查詢接口已經(jīng)發(fā)展了很長(zhǎng)一段時(shí)間,但要準(zhǔn)確地理解自然語(yǔ)言查詢中的語(yǔ)義依舊是一個(gè)具有挑戰(zhàn)性的問(wèn)題。早期的NL2SQL 需要針對(duì)不同的數(shù)據(jù)庫(kù)來(lái)人工制定相應(yīng)的語(yǔ)法和語(yǔ)義規(guī)則,但此方法缺乏遷移性和擴(kuò)展性[2]。更傾向于構(gòu)建與數(shù)據(jù)庫(kù)結(jié)構(gòu)和內(nèi)容無(wú)關(guān),能夠自適應(yīng)的NL2SQL接口。
其中一種就是流水線的方法,這種方法通常利用一些中間表達(dá)來(lái)把自然語(yǔ)言查詢轉(zhuǎn)化為SQL。Unger等人[3]在2012年提出了將自然語(yǔ)言查詢轉(zhuǎn)化為一種名為SPARQL的查詢模板,通過(guò)WordNet來(lái)填充這個(gè)查詢模板中的槽。Jagadish 等人[4]在2014 年提出了NaLIR 系統(tǒng),該系統(tǒng)利用一種“解析樹(shù)”的中間表達(dá),將其反饋給用戶后讓用戶選擇與自己理想查詢最匹配的“解析樹(shù)”,最終通過(guò)譯碼器將用戶選擇的“解析樹(shù)”轉(zhuǎn)化為SQL。整個(gè)過(guò)程需要用戶與系統(tǒng)交互才能確定最終的結(jié)果,自動(dòng)化程度不高。上述基于流水線的方法[3-4]需要提前清晰地定義它們語(yǔ)義的覆蓋范圍,以及對(duì)自然語(yǔ)言查詢描述也存在一些規(guī)則限制,因此不能靈活地處理用戶不同方式的提問(wèn),具有一定的局限性。
而隨著深度學(xué)習(xí)技術(shù)的不斷發(fā)展,通過(guò)應(yīng)用神經(jīng)網(wǎng)絡(luò)模型就能較好地解決自然語(yǔ)言描述復(fù)雜多變的問(wèn)題。早期的研究把NL2SQL 處理成一個(gè)序列生成的問(wèn)題,利用Seq2Seq 模型[5]來(lái)完成這個(gè)任務(wù)。Li等人使用Seq2Seq+Attention模型[6],通過(guò)注意力增強(qiáng)的方法來(lái)提升SQL 生成的準(zhǔn)確率。Wang 等人使用Seq2Seq+Copying 模型[7],通過(guò)復(fù)制機(jī)制定位到輸入自然語(yǔ)言描述的其中一部分,將其直接作為輸出SQL 語(yǔ)句的對(duì)應(yīng)的部分,復(fù)制的部分主要包括自然語(yǔ)言描述中數(shù)據(jù)表的列名和一些字符串或數(shù)值。然而,一般的Seq2Seq模型沒(méi)有考慮到SQL語(yǔ)句的格式和語(yǔ)法上還存在一定的規(guī)則,因此生成的SQL 可能會(huì)產(chǎn)生語(yǔ)法上的錯(cuò)誤。因此,Xu 等人[8]在2017 年提出了一個(gè)SQLNet模型,利用預(yù)先定義好SQL查詢的模板,如圖2 所示,然后對(duì)其各個(gè)部分進(jìn)行預(yù)測(cè)和填充。這種方式相對(duì)于Seq2Seq 模型來(lái)說(shuō)能大幅度減少輸出SQL查詢的語(yǔ)法錯(cuò)誤,從而提高準(zhǔn)確率。
Fig.2 SQL sketch in SQLNet圖2 SQLNet中的SQL模板
然而針對(duì)深度學(xué)習(xí)模型,需要大量的自然語(yǔ)言查詢與SQL 查詢的配對(duì)標(biāo)注來(lái)作為訓(xùn)練數(shù)據(jù),而標(biāo)注數(shù)據(jù)的獲取通常代價(jià)昂貴。針對(duì)這個(gè)問(wèn)題,一些最新的自然語(yǔ)言處理研究工作提出了使用大規(guī)模語(yǔ)料來(lái)產(chǎn)生預(yù)訓(xùn)練模型的方法,預(yù)訓(xùn)練模型在許多自然語(yǔ)言處理(NLP)相關(guān)的下游任務(wù)中取得了不錯(cuò)的效果,例如BERT[9](bidirectional encoder representation from transformers)、MT-DNN(multi-task deep neural network)[10]。He等人[11]提出了X-SQL模型,該模型利用MT-DNN預(yù)訓(xùn)練模型對(duì)自然語(yǔ)言查詢和數(shù)據(jù)庫(kù)模式進(jìn)行特征提取來(lái)提升效果。
現(xiàn)有的深度學(xué)習(xí)模型[5,8,11]都局限于在數(shù)據(jù)庫(kù)的單表中查詢,生成結(jié)果不包含多表的JOIN路徑,適用的范圍較窄,無(wú)法進(jìn)行多表SQL 查詢生成。本文提出的模型架構(gòu)能夠解決這個(gè)問(wèn)題,從而實(shí)現(xiàn)包含JOIN路徑的多表SQL查詢的生成。
自然語(yǔ)言查詢轉(zhuǎn)化為標(biāo)準(zhǔn)SQL 查詢語(yǔ)句,其形式化定義為:
輸入:
由n個(gè)詞語(yǔ)組成的自然語(yǔ)言祈使句或疑問(wèn)句:
數(shù)據(jù)庫(kù)模式集合:
其中,k表示該數(shù)據(jù)庫(kù)中表的個(gè)數(shù)。
其中,Ti表示當(dāng)前表的表名,m表示表i列名的個(gè)數(shù),Aj表示表i的第j個(gè)列名。
數(shù)據(jù)庫(kù)模式圖(schema graph):
其中,V表示節(jié)點(diǎn),對(duì)應(yīng)于數(shù)據(jù)庫(kù)中的表;E表示邊,對(duì)應(yīng)表之間的主外鍵關(guān)聯(lián)關(guān)系;w表示邊的權(quán)重值,默認(rèn)為1。
輸出:
與自然語(yǔ)言查詢Q對(duì)應(yīng)的SQL 查詢語(yǔ)句R,格式如圖3所示。
Fig.3 Generated SQL sketch in proposed model圖3 本文生成SQL的模板
其中$VAL來(lái)自于自然語(yǔ)言查詢Q中,本文模型暫不進(jìn)行預(yù)測(cè)。$TAB和$COL分別來(lái)自數(shù)據(jù)庫(kù)模式S的表名和列名。$AGG 的取值集合為{‘NONE’,‘MAX’,‘MIN’,‘COUNT’,‘SUM’,‘AVG’},$OP 的取值集合為{‘=’,‘>’,‘<’,‘>=’,‘<=’,‘!=’},$ORD 的取值集合為{‘DESC’,‘ASC’}。(…)*代表是零個(gè)或者多個(gè),若為零個(gè),則括號(hào)前對(duì)應(yīng)的SQL 關(guān)鍵詞也需省略,[…]*代表至少有一個(gè)。
為解決自然語(yǔ)言查詢生成多表SQL查詢語(yǔ)句的問(wèn)題,本文將分為兩個(gè)階段,分別為SQL子句生成和JOIN路徑生成。通過(guò)充分利用SQL查詢語(yǔ)句特定的語(yǔ)法,將SQL 生成結(jié)果定義為圖3 的格式模板,將序列生成轉(zhuǎn)化為多個(gè)分類問(wèn)題,只需要對(duì)帶“$”的部分進(jìn)行填充即可獲得標(biāo)準(zhǔn)的SQL查詢語(yǔ)句。本文的整體模型架構(gòu)如圖4所示。
輸入的編碼包括兩部分,自然語(yǔ)言查詢和數(shù)據(jù)庫(kù)模式。本文通過(guò)使用處理文本序列常用的雙向長(zhǎng)短時(shí)記憶(bidirectional long short term memory,Bi-LSTM)網(wǎng)絡(luò)模型[12]來(lái)對(duì)自然語(yǔ)言查詢和數(shù)據(jù)庫(kù)模式中的列名進(jìn)行編碼,產(chǎn)生對(duì)應(yīng)的特征向量。
Fig.4 Overall architecture of proposed model圖4 本文模型的整體架構(gòu)
4.1.1 帶表名信息的列名特征向量
SQL 子句的構(gòu)成包含許多數(shù)據(jù)表中的列名信息,因此通過(guò)模型來(lái)獲取數(shù)據(jù)庫(kù)模式信息也是很有必要的。針對(duì)相關(guān)工作中提到的單表查詢,在SQL生成前已經(jīng)給定當(dāng)前自然語(yǔ)言查詢對(duì)應(yīng)的表,因此不必再將表的信息嵌入到列名的特征向量中。但多表查詢沒(méi)有指定對(duì)應(yīng)的表,查詢范圍為對(duì)應(yīng)的整個(gè)數(shù)據(jù)庫(kù)。為了解決這個(gè)問(wèn)題,在做列名信息的特征表達(dá)時(shí),同時(shí)利用表名和列名的配對(duì)來(lái)獲取列名的特征向量。
具體說(shuō)來(lái),就是給定一個(gè)數(shù)據(jù)庫(kù)模式S,首先列出表名和列名的配對(duì)作為Bi-LSTM 編碼模型的輸入。接下來(lái),通過(guò)Bi-LSTM模型的編碼,選擇它最后的隱藏狀態(tài)來(lái)代表當(dāng)前列名的特征向量Ecol。通過(guò)這樣編碼的方式,獲取的列名特征向量Ecol既包含了全局的表名信息,也包含了局部的列名信息,充分地利用了數(shù)據(jù)庫(kù)模式的信息,更有利于后續(xù)的模型理解自然語(yǔ)言查詢中的語(yǔ)義信息。
4.1.2 基于列名的注意力機(jī)制
在獲取自然語(yǔ)言查詢Q的特征表達(dá)時(shí),如果只使用Q經(jīng)過(guò)Bi-LSTM 模型編碼的最后隱藏狀態(tài)EQ作為特征向量,那么在預(yù)測(cè)各個(gè)子句所包含的列名信息時(shí),就不能突出不同列名在自然語(yǔ)言查詢Q中的重要程度。因此,為凸顯不同列名在自然語(yǔ)言查詢Q中信息側(cè)重的不同,本文采用了一種基于列名的注意力機(jī)制[13],意在提醒之后的模型,在當(dāng)前的列名Ecol下,應(yīng)該更加注意自然語(yǔ)言查詢Q中的哪些部分,從而獲得當(dāng)前列名對(duì)應(yīng)Q的特征向量EQ|col。
首先,計(jì)算針對(duì)自然語(yǔ)言查詢Q中每個(gè)詞的權(quán)重值ω,從而獲得一個(gè)長(zhǎng)度為句長(zhǎng)n的向量:
其中,vi表示向量v的第i維,表示自然語(yǔ)言查詢Q的第i個(gè)詞的編碼隱藏狀態(tài),取值范圍從1到n,n是自然語(yǔ)言查詢的長(zhǎng)度,W是可訓(xùn)練的參數(shù)矩陣,其維度為d×d,d表示編碼模型隱藏狀態(tài)輸出的維度。
計(jì)算了權(quán)重值ω之后,就能將自然語(yǔ)言查詢Q中通過(guò)Bi-LSTM模型編碼的每個(gè)詞的隱藏狀態(tài)進(jìn)行加權(quán)乘積后再求和,來(lái)獲得當(dāng)前列名對(duì)應(yīng)Q的特征向量:
其中,HQ表示自然語(yǔ)言查詢Q中所有詞的編碼隱藏狀態(tài)矩陣,其矩陣維度為d×n。
本文將SQL 子句的生成分為4 個(gè)子任務(wù),包括SELECT、WHERE、GROUP BY 和ORDER BY 子句的預(yù)測(cè),每個(gè)子任務(wù)都是SQL語(yǔ)句的一個(gè)部分,各子句中預(yù)測(cè)填充部分之間相互依賴關(guān)系如圖4所示。
4.2.1 模型細(xì)節(jié)
將模板中各子句中的填充內(nèi)容處理成多個(gè)多分類問(wèn)題,采用softmax 函數(shù)為每個(gè)類別計(jì)算概率來(lái)進(jìn)行分類。為后續(xù)公式表達(dá)簡(jiǎn)潔清晰,先對(duì)矩陣M定義概率分布Pc,計(jì)算公式為:
其中,V是可訓(xùn)練參數(shù)。
在接下來(lái)各子句預(yù)測(cè)模塊的公式中,Ecol和EQ|col分別代表了所有列名編碼和其做注意力機(jī)制后對(duì)應(yīng)自然語(yǔ)言查詢Q的矩陣集合,其矩陣維度均為m×d,m表示數(shù)據(jù)庫(kù)列名的數(shù)量,d為編碼隱藏狀態(tài)輸出維度。還有其中所有的W都表示為可訓(xùn)練的模型參數(shù),且各子句預(yù)測(cè)不共享參數(shù)。
(1)SELECT子句
首先預(yù)測(cè)子句中列名COL 的數(shù)量,再預(yù)測(cè)使用哪些列名,取值范圍為對(duì)應(yīng)數(shù)據(jù)庫(kù)中所有表名列名配對(duì)的集合,公式如下:
在選定使用的列名之后,接下來(lái)需要對(duì)列名預(yù)測(cè)其AGG 的數(shù)量和具體是集合{‘NONE’,‘MAX’,‘MIN’,‘COUNT’,‘SUM’,‘AVG’}中的哪些聚合操作,假設(shè)當(dāng)前列名的編號(hào)為i,那么公式如下:
(2)WHERE子句
同樣,首先預(yù)測(cè)子句中列名COL的數(shù)量,再預(yù)測(cè)使用哪些列名,公式如下:
在選定列名之后,需要對(duì)列名預(yù)測(cè)其OP 操作,取值集合為{‘=’,‘>’,‘<’,‘>=’,‘<=’,‘!=’},假設(shè)當(dāng)前列名的編號(hào)為i,公式如下:
(3)GROUP BY子句
該子句的預(yù)測(cè)模型相對(duì)來(lái)說(shuō)更簡(jiǎn)單一些,只需預(yù)測(cè)出子句中列名COL 的數(shù)量和對(duì)應(yīng)哪些列名即可,公式如下:
(4)ORDER BY子句
與SELECT子句預(yù)測(cè)模型結(jié)構(gòu)類似,首先預(yù)測(cè)子句中列名COL的數(shù)量,再預(yù)測(cè)對(duì)應(yīng)使用的列名,公式如下:
在確定使用的列名之后,就需要對(duì)列名的升降序操作ORD進(jìn)行預(yù)測(cè),取值集合為{‘DESC’,‘ASC’},假設(shè)當(dāng)前列名的編號(hào)為i,公式如下:
4.2.2 訓(xùn)練和推理
在訓(xùn)練的過(guò)程中,其目標(biāo)函數(shù)是所有子任務(wù)損失函數(shù)的總和,通過(guò)最小化目標(biāo)函數(shù)值的方式來(lái)進(jìn)行參數(shù)更新。針對(duì)各子句中對(duì)列名COL 的預(yù)測(cè),一個(gè)數(shù)據(jù)庫(kù)中往往有很多列名,而只有少數(shù)幾個(gè)列名是選中的正例,其他未出現(xiàn)在SQL 語(yǔ)句中的列名即為負(fù)例。為解決樣本不均衡這個(gè)問(wèn)題,針對(duì)各子句列名預(yù)測(cè)部分Pcol,本文使用帶權(quán)值的對(duì)數(shù)似然損失函數(shù)來(lái)表示其損失(loss),公式如下:
其中,α是用來(lái)平衡正負(fù)樣例的超參數(shù),在本文的實(shí)驗(yàn)中根據(jù)經(jīng)驗(yàn)取值為3,N表示樣本的數(shù)量,x表示訓(xùn)練數(shù)據(jù),y表示真值。
其他非列名預(yù)測(cè)子任務(wù)的損失采用傳統(tǒng)標(biāo)準(zhǔn)的交叉熵?fù)p失函數(shù)。在模型的訓(xùn)練過(guò)程中,由于已知子句中各部分預(yù)測(cè)的真實(shí)結(jié)果,因此各子任務(wù)之間互不影響,可并行訓(xùn)練。
但在預(yù)測(cè)推理階段,根據(jù)圖4 所示,以SELECT子句為例,在預(yù)測(cè)列名COL 對(duì)應(yīng)的操作AGG 之前,需要先預(yù)測(cè)COL的數(shù)量和取值。因此在預(yù)測(cè)階段模型是不可并行的,并且在預(yù)測(cè)推理的過(guò)程中,一旦某個(gè)部分預(yù)測(cè)出錯(cuò),那這個(gè)錯(cuò)誤一直傳遞下去,對(duì)后續(xù)的預(yù)測(cè)造成影響。
在4.2節(jié)的深度學(xué)習(xí)模型中,已經(jīng)完成了SQL語(yǔ)句中除FROM 子句部分的預(yù)測(cè)。接下來(lái),需要根據(jù)之前各子句中生成結(jié)果中列名所包含的表,通過(guò)選擇表與表之間的關(guān)系和產(chǎn)生JOIN路徑的條件來(lái)生成SQL查詢語(yǔ)句中的FROM子句。
生成FROM 子句中的JOIN 路徑,首先需要獲得已生成的SQL其他子句中列名所包含的表集合St和對(duì)應(yīng)數(shù)據(jù)庫(kù)的數(shù)據(jù)庫(kù)模式圖G,數(shù)據(jù)庫(kù)模式圖描述了數(shù)據(jù)庫(kù)中各個(gè)表之間的主外鍵關(guān)聯(lián)關(guān)系,圖5所示為一個(gè)數(shù)據(jù)庫(kù)的數(shù)據(jù)庫(kù)模式圖[1]。
Fig.5 Example of database schema graph圖5 一個(gè)數(shù)據(jù)庫(kù)模式圖的例子
目前已有的做法[14]是將St中所有的表,選定其中一個(gè)節(jié)點(diǎn)為基準(zhǔn)點(diǎn),通過(guò)在G上使用廣度優(yōu)先遍歷(breadth first search,BFS)算法來(lái)獲取到其他節(jié)點(diǎn)的JOIN 路徑。這個(gè)算法依賴于基準(zhǔn)點(diǎn)的選擇,是一種局部最優(yōu)化的算法,基準(zhǔn)點(diǎn)不同會(huì)導(dǎo)致最終生成JOIN路徑結(jié)果的不同。
本文將通過(guò)表集合St={tab1,tab2,…,tabm}和數(shù)據(jù)庫(kù)模式圖G=(V,E,w)來(lái)獲取最優(yōu)的JOIN路徑的問(wèn)題建模成斯坦納樹(shù)(Steiner tree)問(wèn)題[15],目標(biāo)是從圖G中尋找一棵包括集合St中所有節(jié)點(diǎn)且開(kāi)銷最小的樹(shù),同時(shí)是JOIN路徑的最優(yōu)解。其中St表示表名集合,m為表的數(shù)量。本文采用如下的算法[15]來(lái)獲取最優(yōu)的JOIN路徑:
算法1斯坦納樹(shù)生成算法
輸入:表集合St={tab1,tab2,…,tabm}和數(shù)據(jù)庫(kù)模式圖G=(V,E,w)。
輸出:JOIN路徑,即斯坦納樹(shù)Th。
步驟1由G和St構(gòu)建一個(gè)完全圖G1=(V1,E1,w1),其中V1=St;
步驟2由G1獲得其最小生成樹(shù)T1(若有多棵最小生成樹(shù),隨機(jī)選擇一棵);
步驟3將T1中的邊替換為G中對(duì)應(yīng)的最短路徑(若有多條最短路徑,隨機(jī)選擇一條),得到G的子圖Gs;
步驟4由Gs獲得其最小生成樹(shù)Ts(若有多棵最小生成樹(shù),隨機(jī)選擇一棵);
步驟5刪除Ts中不必要的節(jié)點(diǎn),得到斯坦納樹(shù)Th,其中Th的葉子節(jié)點(diǎn)全部來(lái)自St。
通過(guò)算法1,得到JOIN 路徑之后,再根據(jù)其路徑上的表之間的主外鍵關(guān)聯(lián)關(guān)系產(chǎn)生JOIN 條件,最終生成FROM 子句。相比于BFS 算法,此算法求解的路徑是全局最優(yōu)解,因此理論上生成FROM 子句的準(zhǔn)確率會(huì)更高。
本文的實(shí)驗(yàn)環(huán)境為一臺(tái)小型服務(wù)器,其操作系統(tǒng)為Ubuntu 16.04.6 LTS,處理器型號(hào)為Intel?Xeon?Silver 4110 CPU@2.10 GHz,內(nèi)存為192 GB,GPU 型號(hào)為NVIDIA Quadro P5000,16 GB。本文實(shí)驗(yàn)使用的編程語(yǔ)言為Python,所有的模型訓(xùn)練都在深度學(xué)習(xí)框架PyTorch下進(jìn)行。
本文使用的數(shù)據(jù)集是2018年發(fā)表的Spider數(shù)據(jù)集[16],是一個(gè)包含復(fù)雜SQL查詢和跨領(lǐng)域數(shù)據(jù)庫(kù)的大規(guī)模人工標(biāo)注英文文本生成SQL數(shù)據(jù)集。該數(shù)據(jù)集中包含206 個(gè)數(shù)據(jù)庫(kù),在去除一些嵌套的SQL 查詢后,獲得的訓(xùn)練集3 917條配對(duì)數(shù)據(jù),測(cè)試集數(shù)據(jù)993條配對(duì)數(shù)據(jù)。
本文對(duì)實(shí)驗(yàn)結(jié)果采用的評(píng)價(jià)方式是文獻(xiàn)[8]的匹配準(zhǔn)確率(query-match accuracy),通過(guò)將生成的SQL查詢和真值轉(zhuǎn)化成一種標(biāo)準(zhǔn)化的表達(dá),再來(lái)比較兩者之間是否匹配,這種衡量標(biāo)準(zhǔn)能減少因子句中多列名出現(xiàn)順序不同而導(dǎo)致不匹配的錯(cuò)誤。
根據(jù)圖3 中SQL 語(yǔ)句模板,還有針對(duì)單獨(dú)一個(gè)SQL 子句生成結(jié)果的評(píng)價(jià)指標(biāo)——子句匹配分值(keyword match score),包括了精確率p、召回率r和F1值。以FROM子句為例,F(xiàn)ROM$TAB JOIN($TAB)*,其中的TAB 對(duì)應(yīng)的表就是一個(gè)需要預(yù)測(cè)的值單元,若預(yù)測(cè)結(jié)果為表集合pred={pt1,pt2,…,ptm},子句中表的真值為集合gold={gt1,gt2,…,gtn},那么精確率p、召回率r和F1值定義如下:
在實(shí)驗(yàn)過(guò)程中,本文采用了固定的預(yù)訓(xùn)練好的詞向量GloVe[17]來(lái)對(duì)自然語(yǔ)言查詢和數(shù)據(jù)庫(kù)模式進(jìn)行特征表達(dá),使用Bi-LSTM模型進(jìn)行文本特征提取,隱藏層維度設(shè)置為100維,使用Adam優(yōu)化器[18],學(xué)習(xí)率設(shè)置為1E-3,訓(xùn)練迭代次數(shù)300 次,批量大?。╞atch size)為64,每次迭代都隨機(jī)打亂訓(xùn)練數(shù)據(jù)的順序。
表1 中給出了不同模型在測(cè)試集上對(duì)SQL 中4個(gè)子句預(yù)測(cè)的效果,可以觀察到本文模型相較于Seq2Seq 模型以及其改進(jìn)方法在各個(gè)子句上都有明顯提升,且Seq2Seq 模型預(yù)測(cè)WHERE 子句的效果極差。而針對(duì)SQLNet模型來(lái)說(shuō),其定義SQL語(yǔ)句的模板如圖2 所示,只能對(duì)SELECT 和WHERE 子句進(jìn)行預(yù)測(cè)。本文對(duì)WHERE子句的預(yù)測(cè)模型和SQLNet中的相同,因此在實(shí)驗(yàn)效果上能保持一致。在SELECT子句預(yù)測(cè)時(shí),本文模型能預(yù)測(cè)多個(gè)列名,以及一個(gè)列名對(duì)應(yīng)的多個(gè)聚合操作,SQLNet 模型只支持預(yù)測(cè)一個(gè)列名和其對(duì)應(yīng)的聚合操作,而實(shí)驗(yàn)數(shù)據(jù)中有的SELECT 子句中不止一個(gè)列名,因此本文方法在SELECT子句上的預(yù)測(cè)效果提升較大。
Table 1 F1 of matching 4 clauses in SQL queries on test set表1 測(cè)試集上SQL查詢中4個(gè)子句匹配的F1 值 %
為更準(zhǔn)確地測(cè)試算法1與BFS算法在JOIN路徑生成結(jié)果的對(duì)比,不受SQL 子句生成實(shí)驗(yàn)效果的影響,實(shí)驗(yàn)將訓(xùn)練集和測(cè)試集中除去FROM 子句的SQL 查詢中的表名構(gòu)建出真實(shí)的表集合S,以及通過(guò)數(shù)據(jù)庫(kù)主外鍵關(guān)聯(lián)關(guān)系構(gòu)建數(shù)據(jù)庫(kù)模式圖G,兩者同時(shí)構(gòu)成JOIN路徑生成算法的輸入。
通過(guò)表2實(shí)驗(yàn)結(jié)果分析,可以看出算法1在JOIN路徑的生成上相比于BFS算法在精確率p和召回率r上都有所提升。因此,利用算法1在5.1節(jié)實(shí)驗(yàn)結(jié)果的基礎(chǔ)上生成FROM子句以構(gòu)成完整的SQL語(yǔ)句更為可靠。
Table 2 Experiment result comparison of FROM clause generation表2 FROM子句生成的實(shí)驗(yàn)結(jié)果對(duì)比 %
為生成結(jié)構(gòu)如圖3所示的SQL查詢語(yǔ)句,實(shí)驗(yàn)過(guò)程分為兩個(gè)階段,第一階段使用5.1節(jié)中的SQL子句生成結(jié)果,第二階段需要將SQL 子句中除FROM 子句的表名構(gòu)成JOIN路徑生成的表名集合輸入St,然后將算法的輸出轉(zhuǎn)化為FROM 子句,最終生成SQL查詢的結(jié)果。本文的實(shí)驗(yàn)中第二階段的JOIN路徑生成均采用算法1。
從表3 中的實(shí)驗(yàn)結(jié)果可以得出,Seq2Seq 模型在表1 中WHERE 子句結(jié)果不理想的情況下,在完整SQL 語(yǔ)句的查詢匹配準(zhǔn)確率還能達(dá)到19%~23%之間,說(shuō)明數(shù)據(jù)中一部分的SQL 查詢語(yǔ)句中不包含WHERE 子句。SQLNet 模型由于其局限性,不能用于生成多表查詢SQL,因此無(wú)法統(tǒng)計(jì)其實(shí)驗(yàn)效果。結(jié)果表明使用本文兩個(gè)階段的模型和算法在多表SQL查詢語(yǔ)句生成上能有效地提升準(zhǔn)確率。
Table 3 Query-match accuracy comparison of full pipeline表3 完整流程的查詢匹配準(zhǔn)確率對(duì)比
本文針對(duì)自然語(yǔ)言生成多表SQL 查詢問(wèn)題,提出了SQL 子句生成和JOIN 路徑生成兩個(gè)階段的改進(jìn)模型和方法。在SQL子句生成階段使用深度學(xué)習(xí)模型對(duì)SQL 語(yǔ)句模板進(jìn)行填充,將序列生成處理為多個(gè)多分類問(wèn)題,在JOIN 路徑生成階段將其建模為斯坦納樹(shù)問(wèn)題求解。實(shí)驗(yàn)結(jié)果表明,本文方法的實(shí)驗(yàn)效果相比于之前的模型和方法上都有明顯的提升,但查詢匹配的準(zhǔn)確率仍然不高。由于本文實(shí)驗(yàn)數(shù)據(jù)集Spider的特性,WHERE子句中的VAL不一定出現(xiàn)在自然語(yǔ)言中,對(duì)其預(yù)測(cè)帶來(lái)困難,因此本文對(duì)VAL暫未進(jìn)行預(yù)測(cè)。接下來(lái)的工作可以考慮完成對(duì)VAL的預(yù)測(cè)來(lái)生成完整的SQL 語(yǔ)句。除此之外,由于缺乏中文自然語(yǔ)言生成SQL 查詢語(yǔ)句相關(guān)的數(shù)據(jù)集,因此無(wú)法驗(yàn)證本文模型在中文語(yǔ)料上的實(shí)驗(yàn)效果。