【云駐共創】M-SQL,一種超強的多任務表示學習方法,你值得擁有
本篇文章將硬核講解M-SQL:一種將自然語言轉換為SQL語句的多任務表示學習方法的相關論文。

數據集整體介紹
定義介紹
國際慣例,先來一段定(bai)義(du)介(bai)紹(ke):Text to SQL,顧名思義,就是在給定數據庫(或表)的前提下,根據用戶的提問,產生SQL語句。其數學描述如下:
令X表示用戶的自然語言提問,D表示與提問相關的數據庫(或表),Y表示其對應的SQL語句。
SQL語句生成任務可以表述為:對于每一組獨立的(X,D,Y),將(X,D)映射到對應的Y。
用一個大家熟悉的場景為例。假設我們有一張學生信息表,我們可以用自然語言提問:大于18歲的學生都有誰,模型需要返回一個與之相關的SQL語句,那么就是:
SELECT 姓名 FROM 學生信息 WHERE 年齡 > 18
場景分類
Text to SQL有很多種分類,其中一種是按問題分類:
一種是上下文無關的(提問之間不存在關聯):Spider
一種是上下文相關的(兩個提問之間存在一定關聯):SparC
“上下文無關”是指提問之間沒有任何的關聯,而“上下文相關”是前后兩個提問之間,存在一些指代關系或者說存在一定的關聯。
同樣,我們舉一個簡單的例子來說明:
提問1:有預約的醫生ID是什么?
SELECT physician FROM appointment
提問2:他們的名字是什么?
SELECT T2.name FROM appointment AS T1 JOIN physician AS T2 ON T1.Physician = T2.EmpoyeeID
以上就是一個上下文相關的例子,第一句的確定醫生ID,第二句根據醫生ID確定醫生名字。
另一種是按領域分類:單領域 or 多領域
如果所有的提問都是有關于航空方面的,這就是一個單領域的數據集。而跨領域數據集,則是在訓練集當中可能有很多種領域,在測試集當中也有很多種領域,但是訓練集中的領域和測試集中的領域不重合,這就要求我們的模型具有一定的泛化能力。
第三種是按照數據庫進行分類:
單表數據庫:WikiSQL,其提問只針對一個表,或者是它所針對數據庫當中只有一個表
多表數據庫:Spider,其提問針對的數據庫當中有許多個表,它所產生的 SQL語句可能涉及到多個表之間的連接。
第四種種分類是按照標注類型進行分類:
最終結果:WikiTableQuestion
SQL語句:WikiSQL、Spider
有一些數據集沒有給出相關的SQL語句,而是直接給出了一個結果。以前面的例子為例,“大于18歲的學生都有誰”,輸出有可能是給出SQL語句,也有可能是最終結果:把這些人名都給列出來,而沒有給出SQL語句,這其中涉及到的“弱監督學習”,本次不做具體講解。
TableQA 數據集
本次要講解的論文所采用的是一個TableQA數據集,它也是一個單表數據。也就是每一個提問都只針對一個表進行提問。TableQA和WikiSQL有有很多相似之處,但是也有一定的差異,如下圖所示:
數據集
語種
數量
難易
Select字段數量
Where條件數量
Where條件操作
Value標準度
WikiSQL
英文
8w+
簡單
1
以單個為主
AND
存在于數據庫表中
TableQA
中文
5w+
較難
[1,2]
以多個為主
[AND, OR]
形式多樣
論文概述
介紹完數據集之后,我們來對論文中所提出的模型進行一個簡單的介紹。
首先來思考這樣一個問題:通過自然語言生成SQL語可以有什么方法?其實一個最簡單的思路:輸入端是自然語言句子,輸出端是與之對應的SQL語句(按照SQL語句按照一個token一個token進行生成)。
比如說我們前面那個例子,Encoder是“大于18歲的學生都有誰“,輸出端是SELECT?name FROM XX表?Y條件。
這個方法很簡單,但是也伴隨著一些問題:SQL語句是結構化的查詢語言,它是具備一定的結構的,這和一般的語言生成任務是有一定差別的。
對于一般的語言生成任務來說,如果變更其中的一兩個詞,可能它的語義不會發生太大變化。但是對于 SQL語句來說,如果某個詞不一樣了,那么其就可能就沒有辦法繼續執行。所以我們需要利用好SQL語句內部的一些語法信息,也就是結構信息。按照它的結構來進行生成,這就是論文當中所提出來的,按照 SQL的框架來進行生成。
M-SQL
因為TableQA數據集只針對單表,相當于From字句可以省略。大體可以分成兩個部分,一部分是 Select子句,一部分是 Where子句。
其中Select的子句當中有兩個部分:一個是所選取的表的名稱,另一個是聚合操作。比如說我們要求某一列的最大值、最小值或者是對某一列進行求和,就需要聚合操作來進行。
對于Where子句這一部分,我們詳細介紹一下:
$WOP:where 條件連接符(and /or / Null)
$COLUMN:數據庫中的列名
$AGG:對選取列的操作(Null, AVG, MAX, MIN, COUNT, SUM)
$OP:where子句中的列值
根據對TableQA數據集進行統計,限定select中最多出現2列、where中最多有3個條件:
SELECT ($AGG $COLUMN)*
WHERE $WOP ($COLUMN $OP $VALUE)*
M-SQL模型
此模型大致可從下往上可以分成三塊。
Encoder:對輸入進行一個編碼;采用了一個簡單的bert模型,版本是wwwm-ext。wwm意味著其使用的是一個全詞覆蓋的方式,而ext則擴充了它的訓練集并使它的訓練部署有所增加。
其輸入部分包括:問題、列名。同樣以前面“大于18歲的學生都有誰”為例,可以看到上圖所示,T1至TL,后面跟著的是所提問的表當中所出現的每一列它的列名,比如說這個表當中可能有姓名、學號或者年齡。另外,與bert輸入不同的是它用 [XLS]去替換了[CLS]。
列表示:對于列的表示進行增強;由于每一列當中它可能會由多個token構成,比如說,一列的名字叫“姓名”,其可能是兩個字,這兩個字分別有兩個embeding,那么如何把這兩個embeding給它合并成一個embeding作為列的表示呢?我們可以用前面的 XLS的表示來對列的表示進行增強,具體的做法如下:
先通過前面 XLS的表示,對這一列當中所有的token表示進行計算attention,attention計算出來之后再加上前面 XLS表示的 embeding,這兩個之和就構成了這一列的增強的表示。
經過上述步驟之后,我們就得到了問題當中,每一個token的表示,以及表格當中每一列的表示。
子模型:8個子模型及對這8個子模型進行1個多任務的學習。
前面提到,我們可以將SQL語句分割成不同的部分,然后每一部分分別進行生成,于是可以得出8個子任務,分別是:
Select列數
Where列數和連接符
Select列
Select列操作
Where列
Where每列的運算
值抽取
值匹配
接下來,我們對這8個子任務分別介紹一下它們的做法。
任務一:S-num:Select中出現的列數。[1、2](2分類)
首先是Select當中出現的列數。對于TableQA數據集,Select當中出現列數只可能是一列或者是兩列,因此我們可以當做是一個二分類的問題:利用 XLS的 embeding做線性變換,然后過sigmoid的得到它的概率。
任務二:w-num-op:Where中的連接符和條件數。[null-1、and-1、or-1、and-2、or-2、and-3、or-3](7分類)
第二個任務是Where當中出現的連接符和條件數。所謂“連接符”,指的是“And”還是“or”等;條件的個數,指的是Where當中所出現的“>”、“<”、“=”等等條件的個數。我們可以將他們分成了7個類別,“-”前面的就是連接符,“-”后面的這些就是條件的個數。當然也可以把這兩個任務進行分開,但是如果把這兩個任務進行分開的話,效果與兩個任務一起做相比,會大打折扣。
那么總共是有7個類型,就可以看成是7分類的問題,因此還是 XLS表示過一個線性變換,然后再經過softmax,就可以得到這7個類別上的概率分布。
第三個和第四個子任務是Select字句和Where字句當中出現的列。我們前面已經預測了Select當中的例數,以及Where當中的例數,那么在這一部分我們分別預測每一例所出現的概率即可。
任務三:S-col:Select 中出現的列
Select中出現的列:利用我們之前每一列得到增強的表示,經過一個線性變換,再過一個softmax就可以得到這一列所出現的概率。
任務四:W-col:Where 條件中出現的列
對Where條件當中出現的列:同樣,利用不同的線性變化來進行得到這一列它所出現的概率。
任務五:S-col-agg:Select 中出現的列的操作符
[Null, AVG, MAX, MIN, COUNT, SUM](6分類)
第五個任務是Select當中出現的這些操作符,這些操作符也被稱為是聚合操作。比如說,我們可以求這一列當中所有數據的最大值、最小值或者求平均、求和等等。
在TableQA當中,5種操作符加上NULL一共是6種,我們可以將其看到是一個6分類的問題。同樣,我們對每一列的增強的表示做一個線性變換,然后再經過softmax就可以得到每一類的概率分布。
任務六:W-col-op:Where 條件中出現的列對應的條件運算符
[> / < / == / !=](4分類)
對于Where條件當中出現的這些運算符也是一樣。這些運算符,包括這一類大于一個數或者小于一個數,或者是等于某個值,或者不等于某個值,一共是4類,我們可以看作是一個4分類的問題。做法和之前的Select當中的運算符一致,也是給列的增強表示過一個線性映射再經過softmax得到4類的每一類的概率分布,從中的選取最大的作為這一列的運算符。
任務七:從問題中抽取可能是值的短語
使用0/1對問題中的Token進行標記(1表示值,0表示非值),每一組連續的
1標記的token作為一個整體
第一步就是從問題當中抽取出有可能是值的短語。比如說“大于18歲的學生都有誰”這個問題,那么這個子任務就是把“18”從問題當中進行抽出來。我們可以采用的方法是使用0和1對問題當中所出現的token進行標記,比如說“大于18歲都有誰”中的“18”,我們就把它標記成1,然后其他所有的token就把它標注上0,并對于問題當中我們一個token的表述過一個線性變換,使用sigmoid的來預測它到底是1還是0。
任務八:將抽取出的短語和Where中出現的列進行匹配
在任務七的基礎上,我們需要將抽取出來的短語與where當中所出現的列進行匹配。
在前一個步驟,我們已經把“18”給它打上1的標簽了,因此也就生成了“18”這個token序列。它是一個可能會出現在某一個條件當中的value,但是它會出現到哪一列之后,是這一步所要確定的事。
將取出來的短語與Where當中出現的列進行匹配,如果短語當中它是由多個token構成的,就把所有的token的text表示求一個平均。如下圖,此公式相當于是對短語與where當中出現的列求一個相似度,然后再過一個sigmoid。前面這個u是一個可學習的參數,過一個sigmoid就可以得到短語與列是否匹配:如果匹配就把短語作為列的值,比如說18就跟age匹配了,然后我們就可以寫age > 18。
Execution-Guided Decoding
我們已經對上述8個子任務做了簡單的介紹。通過這8個子任務,我們就可以得到一條SQL語句,并且保證它是符合了語法規則的。但是它所產生的SQL語句有可能還是不能被執行。
因為SQL語句的內部可能還存在一些限制條件:
SELECT子句中如果出現string類型的列,則對應的操作不能是’sum’, ‘min’, ‘max’
WHERE子句中如果出現string類型的列,則對應的操作不能是‘<’, ‘>’
SELECT子句和WHERE子句中出現的列互不相同(分析數據集得知)
在這些限制下,我們可以采用Execution-Guided Decoding的方法:在decode的過程當中,去掉那些不能被執行的SQL語句,比如說SQL語句執行出來的結果是空,或者壓根就不能被執行,從而被會報錯,這些SQL語句我們就可以直接被拋棄,而選取符合上述條件的概率最大的SQL語句。
實驗結果
接下來是實驗結果。
首先簡單介紹一下其所采用的評價指標,分別是LX、X還有MX。
LX,就是它的邏輯形式的準確率。如果所生成的SQL語句和標準答案的SQL語句完全一致,那么上面這兩個操作正確;如果有一點不一樣,比如說“>”寫錯了,或者是這一列選錯了,那么這個例子即錯誤。
X,就是它的執行結果的準確率。如果兩條SQL語句,可能它的邏輯形式不一樣(這兩個SQL可能存在一些差別),但它的執行結果是一致的,那么也算預測正確。
MX,是前面LX和X的一個平均。它有兩個模型,一個是單個模型,一個是集成模型(后面的Ens)。通過Ensemble對多次訓練的結果進行集成,最終得到一個更好的結果。從圖中我們可以看到它比之前幾種模型的結果都要好。
因為之前的模型都是基于WikiSQL進行實現的。我們所采用的TableQA與WikiSQL有一些不同,并且比WikiSQL要更難一些,所以之前的這些模型在TableQA對數據集上的效果并不是很好。
子任務的性能
下圖對8個不同的子模型的性能做了對比:
我們可以看到在每一個子模型上,它的效果都是非常不錯的,現在經過Ensemble之后就可以達到更好的效果。
消融實驗
在實驗的最后一部分我們做了一系列的消融實驗。
從實驗結果我們可以看出,使用BERT-wwm-ext的版本比 BERT-base效果要好,使用XLS作為前置比CLS作為前置的效果要好。圖中更下面部分是所使用的一些值的抽取的方法,以及一些值匹配的方法,我們在下面給大家作更詳細的介紹。
復現中的細節處理
接下來,我們將介紹在復現過程當中的一些細節處理。
首先是數據預處理的部分。對于這個數據集來說,它的數據是不太規范的,有可能會出現以下情況(括號中表示歧義部分):
數字:哪些城市上一周成交一手房超十五萬平? (十五,15)
年份:你知道10年的土地成交面積嗎? (10年,2010)
單位:哪些城市最近一周新盤庫存超過5萬套? (5萬,50000)
日期:哪個公司于18年12月28號成立? ( 18年12月28號,2018/12/28 )
同義:你能幫我算算芒果這些劇的播放量之和是多少嗎?(芒果,芒果TV)
前面幾個問題,可以直接按照一定的規則來進行轉換;而后面這些可以通過到數據庫當中去找相關的品類詞做一個替換。
值的抽取
在“值抽取”這一部分的,我們嘗試了很多種方法,比如說bert+crf的方法,bert+bilstm+crf,以及bert+半指針的方法。最終所采用的還是0/1標記的方法,因為它的效果是最好的。
bert + crf,val_acc: 0.8785
bert + bilstm + crf,val_acc: 0.8801
bert + 半指針,val_acc: 0.8891
bert + 0/1 標記,val_acc: 0.8922
0/1的方式是如何實現的呢?我們以問題是“青秀南城百貨有限公司在哪?”為例來詳細講解一下。
query:青秀南城百貨有限公司在哪?
bert_tokenizer:[‘[XLS]’, ‘青’, ‘秀’, ‘南’, ‘城’, ‘百’, ‘貨’, ‘有’, ‘限’, ‘公’, ‘司’, ‘在’, ‘哪’, ‘?’, ‘[SEP]’]
value:青秀南城百貨有限公司
tag:[0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0]
首先對此問題進行Tokenizer,然后得到token序列,如果值“青秀南城百貨有限公司”出現在SQL語句中,就把這些token給標記成1;對于其他的沒有在SQL語句當中出現的,就標記成0。
細節處理
Value檢索
由于在value抽取的時候,抽取出來的value可能不太規范,或者是問題當中和數據庫當中出現的不太一致。比如說下圖中的“人人”與“人人網”:
Query1:人人周漲跌幅是多少?
Value:人人
在這種情況下,我們就需要將 value與 SQL這一列當中出現的所有的值做一個檢索,選出與之最接近的一個詞作為最終的 value。那么如果檢索,我們可以選的方法也很多,比如說rouge-L的匹配方式,以及幾種機器學習的方法:邏輯回歸、SVR以及貝葉斯。通過效果對比,我們可以發現,邏輯回歸是最好的方式,其準確度是97%。
Table-Column 信息增強:
最后一部分,使用表的內容來對列的表示進行增強。
如上圖,比如說地區這一類,從中隨機選取一個列值,比如說“廣西”,我們這一列就表示成“地區, 廣西”這一個整體就作為這一列的一個表示,并把它送到input端,然后再進一步的獲得列的表示。通過這種方式對于列進行增強,最終可以獲得0.4的效果提升。
復現中的問題及建議
1、數據集不規范,建議抽取選取部分規范的數據進行訓練和預測;
2、不要從0開始復現,可以基于現有的模型,參考現有的代碼。
M-SQL:一種將自然語言轉換為SQL語句的多任務表示學習方法
查看本期論文解讀視頻、算法鏈接,請點擊:
https://marketplace.huaweicloud.com/markets/aihub/article/detail/?content_id=d5f27a62-fc93-43cb-813b-6bb5c5eec068
查看活動詳情:
https://bbs.huaweicloud.com/blogs/298594
SQL 數據庫
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。