1. 程式人生 > >螞蟻金融NLP競賽——文字語義相似度賽題總結

螞蟻金融NLP競賽——文字語義相似度賽題總結

1前言

許久沒有更新部落格了,主要是忙於考試周和最近參加的一個螞蟻金融的NLP比賽——文字語義相似度賽題。話不多說,直奔主題。本篇部落格主要記錄的是自己入門NLP以來第一次參加NLP性質的賽題的詳細解題過程。接下來將分成三個部分進行敘述:賽題描述、解題思路及相關程式碼實現、賽題總結.
專案程式碼地址及說明

2賽題描述

說明:問題相似度計算,即給定客服裡使用者描述的兩句話,用演算法來判斷是否表示了相同的語義。若語義相同則判斷為1,不相同則為0.

1 “花唄如何還款” –“花唄怎麼還款”:同義問句
2 “花唄如何還款” – “我怎麼還我的花被呢”:同義問句
3 “花唄分期後逾期瞭如何還款”– “花唄分期後逾期了哪裡還款”:非同義問句

需要思考和解決的問題: 1.句子對中存在錯別字、同義詞、詞序變換等問題。2.兩句話很類似,僅僅有一處細微的差別,最後的語義卻不同。
賽題的評價指標:
賽題評分以F1-score為準,得分相同時,參照accuracy排序。對於F1的計算,需要明白以下幾個概念,True Positive(TP)意思表示做出同義的判定,而且判定是正確的,TP的數值表示正確的同義判定的個數; False Positive(FP)意思表示做出同義的判定,但是判定是錯誤的,數值表示錯誤的同義判定的個數;True Negative(TN)意思表示做出不是同義的判定,而且判定是正確的。數值表示正確的不同義判定個數;False Negative(FN)意思表示做出不是同義的判定,而且判定是錯誤的。數值表示錯誤的不同義判定個數。
計算公式:

精準率(做出為同義的判定中,事實上為同義的比例):precision rate = TP / (TP + FP)
召回率(事實上為同義的語句對中,有多少比例的同義對被預測出來了):
recall rate = TP / (TP + FN)
準確率:accuracy = (TP + TN) / (TP + FP + TN + FN)
F1-score = 2 * precision rate * recall rate / (precision rate + recall rate)

3解題思路及相關程式碼實現

3.1賽題整體分析

分析:本賽題中需要設計一個演算法計算兩個語句的語義相似度,最後表示是否為同義和非同義。對於要設計出一個演算法,首先,需要先明確演算法的輸入和輸出。很容易的判斷出演算法最終的輸出是0或1,而演算法的輸入則是需要思考的地方,如果考慮以神經網路進行建模的話,需要通過表示學習方法將輸入的語句用向量表示(詞向量),如果以機器學習的分類方法進行建模的話,則需要對輸入的語句進行特徵的抽取,特徵的選擇,和特徵的表示。輸入語句的詞向量表示需要思考的問題——訓練詞向量的語料庫和訓練詞向量的模型方法的選擇。

3.2訓練資料的分析

整個賽題相關的資料下載地址,密碼為:5ig5。

1.資料label包含兩類1和0,屬於經典的二分類問題,資料集中類別1和類別0的比例大致為4.5:1,屬於分類不平衡的現象(這點也是後面需要解決的問題也是賽題成績提高的重要點)。
2.需要判斷的每隊語句隊存在著一定的錯別字,如:“花唄”寫成“花被”,“登入”寫成“登陸等,語句中也包含相應的同義詞如:”為啥”:”為什麼”,雖然這些人可以立馬判斷出,但是演算法卻是需要解決的問題點。
3.樣本資料不僅類別分配不平衡,其中正例(同義)的語句隊資料量偏少,模型比較難學習出同義語句隊的特徵。
4.中文句子中存有未登入詞的現象,經過測試像螞蟻花唄,螞蟻借唄…等新詞經jieba分詞是區分不出來的。

3.3整體思路

本次賽題最終的評價指標F1為0.6238,賽題的評價指標F1提升過程0.29——>0.45->0.53->0.5925->0.6159->0.6238。本次賽題純屬是第一次參加NLP的比賽,一步一步慢慢積累解題技能的過程。最終的解題思路為:

最終採用機器學習的方法對本賽題的分類問題進行建模,對機器學習輸入主要是兩個方面:抽取的NLP統計特徵和經過深度模型訓練輸出的語句的相似度。最終的分類模型採用Stacking的整合學習方式進行訓練。

3.4具體實現過程和步驟

Step1 前期外部資料整理工作
根據前期訓練資料的分析工作,需要使用到的外部資料有,主要部分是人工尋找的:

1.用於語句隊的分詞的停用詞表——stop_words.txt
2.用於jieba分詞的新詞的自定義字典——dict_all.txt
3.用於糾錯及部分同義詞替換規則的檔案——spelling_corrections.json
4.用於語義相似度的深度學習模型的預訓練的詞向量(知乎問答語料庫訓練的300維度)——sgns.zhihu.bigram
5.用於計算兩個語句中的疑問詞的相似度的疑問詞相似的規則檔案——doubt_words.txt

Step2 文字預處理工作
該部分主要的目的是:為最終演算法的輸入提供一個相對較正確的表示,主要的工作是:將尋找的規則檔案的詞語對在語句中進行替換,去除語句中的停用詞,將語句進行分詞處理,並根據預訓練的詞向量的矩陣,構建出詞彙表的詞向量矩陣embedding_matrix.其中構建預訓練的詞向量使用的語料庫為整個訓練集10447對個語句組成,訓練方法是Word2Vec中的CBOW方式,negative sampling技巧。另外一種預訓練的詞向量是外部網上資源知乎問答語料庫經過Word2vec訓練的。詞向量(詞的分佈表示)主要是為了作為神經網路的Embeding層的輸入。
詳細的過程為:

    # step 1 載入原資料
    jieba.load_userdict(project.aux_dir + dict_path)
    data_local_df = pd.read_csv(project.data_dir + train_all, sep='\t', header=None,names=["index", "s1", "s2", "label"])
    data_test_df = pd.read_csv(project.data_dir + test_all, sep='\t', header=None, names=["index", "s1", "s2", "label"])
    data_all_df = pd.read_csv(project.data_dir + train_data_all, sep='\t', header=None, names=["index", "s1", "s2", "label"])
    # 預訓練中文字元向量
    pre_train_char_w2v()
    # 訓練集中的語句的文字處理,去除停用詞,根據規則表替換相應的詞,使用jieba對語句進行分詞處理
    preprocessing(data_local_df,'train_0.6_seg')
    preprocessing(data_test_df,'test_0.4_seg')
    preprocessing(data_all_df,'data_all_seg')

    # 儲存label
    project.save(project.features_dir + 'y_0.4_test.pickle', data_test_df['label'].tolist())
    project.save(project.features_dir + 'y_0.6_train.pickle', data_local_df['label'].tolist())
    project.save(project.features_dir + 'y_train.pickle', data_all_df['label'].tolist())

    # step 2預訓練中文片語向量
    pre_train_w2v()

    # step 3記錄訓練集中的詞彙表中的詞對應的詞向量表示
    process_save_embedding_wv('train_all_w2v_embedding_matrix.pickle',type=2,isStore_ids=True)
    # process_save_embedding_wv('zhihu_w2v_embedding_matrix.pickle',type=2,isStore_ids=False)
    # process_save_embedding_wv('zhihu_w2v_embedding_matrix.pickle',type=3,isStore_ids=False)

    # step 4 char wordembedding
    process_save_char_embedding_wv(isStore_ids=True)

Step3 文字特徵抽取工作
描述:賽題的重點部分,賽題成績的好壞主要取決於特徵的選取工作。由於不像很多大佬一樣一開始便能設計出針對語句對進行語義相似度判斷的神經網路模型,此部分是一點一點調研和摸索出來的。因為最終的分類模型是通過機器學習的方法進行建立,所以需要以多維度的特徵作為計算語句對語義相似度演算法的輸入。最終我們選取的特徵包括兩個方面,一方面是計算語句對語義相似度的神經網路的輸出作為特徵之一,另一方面是統計語句對的NLP資料的特徵。
a.兩個語句的長度上的差距.
b.兩個語句的編輯距離.
c.兩個語句的n-gram相似性的特徵.
d.兩個語句的詞的統計特徵.包括相同詞的個數,不同詞的個數,Jaccard相似度。
e.兩個語句中的疑問詞的相似度.主要是根據疑問詞相似度規則檔案進行計算。
f.兩個語句是否同時包括螞蟻花唄和螞蟻借唄相關的主題.,觀測到訓練資料中的語句對基本全都是關於螞蟻花唄和螞蟻借唄相關的問題。
g.兩個語句的詞向量組合的相似度.主要是根據全部訓練集做語料庫使用word2vec訓練的詞向量計算的兩個語句的詞向量的組合相似度。
h.兩個語句神經網路編碼的曼哈頓距離相似度和餘弦相似度主要是根據兩個語句的預訓練詞向量輸入經過LSTM進行編碼計算出兩個語句的語義向量的曼哈頓距離和餘弦相似度作為最後的機器學習的分類模型特徵之一。
i.兩個語句的神經網路編碼的match vector形式計算的相似度.
j.兩個語句的神經網路編碼的改進的Compare-Aggregate模型的相似度
神經網路模型說明
此處相似度特徵表現最好的神經網路模型是改進的Compare-Aggregate模型,其次是兩個語句神經網路編碼的曼哈頓距離相似度和餘弦相似度的模型。所以接下來對這兩個神經網路模型做詳細的介紹。接下來將詳細介紹這三種神經網路模型,這也是自己在賽題中的使用模型的嘗試改進和理解性的構建模型的過程。
模型一:基於LSTM進行語義編碼的曼哈頓距離相似度和餘弦相似度的模型
圖1
提交結果後的平臺測試的F1結果為0.456,該模型主要是簡單對輸入的語句序列進行LSTM的編碼獲取得到句子的語義表示向量,再經過語義向量的曼哈頓計算和餘弦距離計算,最後依據這兩項訓練出模型引數。
具體實現為:

class ManDist(Layer):
    def call(self, inputs, **kwargs):
        """This is where the layer's logic lives."""
        self.res  = K.exp(- K.sum(K.abs(inputs[0]-inputs[1]),axis = 1,keepdims = True))
        return self.res
class ConsDist(Layer):
    def call(self, inputs, **kwargs):
        self.res = K.sum(inputs[0] * inputs[1],axis=1,keepdims=True)/(K.sum(inputs[0]**2,axis=1,keepdims=True) * K.sum(inputs[1]**2,axis=1,keepdims=True))
        return self.res

模型二:基於LSTM進行語義編碼的match vector形式計算的相似度的模型
該模型是在模型一的基礎上進行了改進,提交結果後的平臺測試的F1結果為0.53.改進的地方是在使用LSTM進行對語句詞向量編碼後將兩個語句的語義編碼向量進行點乘和減法計算後再進行接下來的相似度計算。提升的原因是:語句的語義向量除了LSTM編碼形成的語義向量還附加了兩個語句的語義向量的點乘和減法形成的語義互動。
具體實現為:

    def call(self, inputs, **kwargs):
        encode_s1 = inputs[0]
        encode_s2 = inputs[1]
        sentence_differerce = encode_s1 - encode_s2
        sentece_product = encode_s1 * encode_s2
        self.match_vector = K.concatenate([encode_s1,sentence_differerce,sentece_product,encode_s2],1)
        return self.match_vector

模型三:改進的Compare-Aggregate的模型
模型三做出的改進:第一部分,該模型是基於論文《A Decomposable Attention Model for Natural Language Inference》中的Attention機制,在語句中的詞級別上添加了注意力機制,讓經過LSTM編碼後的語義向量在語句中的詞上更有了重心,主要體現在語句中各個詞的詞向量經過attention機制後的權重分配不一樣了。此外,還藉助了該論文中的Compare部分,將attention機制表示的語句詞向量與雙向LSTM語義編碼的向量進行Concatenate連線。第二部分,模型三除了以兩個語句的片語級別的向量做為輸入外,還增加了兩個語句的字級別的向量作為輸入。增加字元級的輸入,主要是為了解決out-of-vocabulary片語級別的問題。第三部分,在語句的詞向量的語義向量上添加了基於CNN的互動式處理思想,這種方式考慮了句子之間的所有互動屬性。
根據模型三提交結果後的平臺測試的F1結果提升到0.59.
圖2
最終的程式碼實現

    # 提取深度學習特徵
    extract_feature_siamese_lstm_manDist()
    extract_feature_siamese_lstm_attention()
    extract_feature_siamese_lstm_dssm()
    # 提取NLP特徵
    extract_sentece_length_diff()
    extract_edit_distance()
    extract_ngram()
    extract_sentence_diff_same()
    extract_doubt_sim()
    extract_sentence_exist_topic()
    extract_word_embedding_sim()

每種抽取方法對應一個函式,抽取特徵的步驟:
step1 定義抽取特徵的方法名
step2 載入需要抽取特徵的資料
step3 定義抽取特徵的方法(如果是深度學習需要呼叫./final_demo/train_model.py檔案中構建模型的方法)
step4 逐行讀取資料,並進行特徵的抽取,儲存到相應的np.array陣列中
step5 特徵的儲存
呼叫方法:
project.save_features(feature_train, feature_test, col_names, feature_name)
引數說明:訓練集的抽取出的特徵feature_train,測試集的抽取特徵feature_test,抽取特徵的方法的多列特徵的列名col_names,抽取特徵的方式名feature_name

Step4 Stacking分類模型的建立工作
通過上述的特徵提取方法將會提取出19個特徵,通過對提取出的特徵使用機器學習建立分類模型。一開始選擇使用了基本的sklearn中的LogisticRegression分類方法。後來提出使用整合學習中的Stacking模式將Sklearn中的多個分類學習方法進行融合,最終提交結果後的平臺測試的F1結果提升到0.61.
圖3
本次賽題使用的兩層Stacking方式,選用了GussianNBClassifier、RandomForestClassifier、LogisticRegression、DecisionTreeClassifier四個基分類器作為第一層Stacking基模型。第二層Stacking選用的是RandomForestClassifier分類器進行訓練的。具體實現的方式為:

    # stacking 第一層模型訓練,分別使用基分類器對訓練集X_train進行5折交叉驗證,在使用訓練的模型預測X_test取均值。作為第二層Stacking模型的輸入。
    gnb_cls = GussianNBClassifier()
    gnb_oop_train,gnb_oofp_val = gnb_cls.get_model_out(,y_train,X_test)

    rf_cls = RFClassifer()
    rf_oop_train, rf_oofp_val = rf_cls.get_model_out(X_train, y_train, X_test)

    lg_cls = LogisicClassifier()
    lg_oop_train, lg_oofp_val = lg_cls.get_model_out(X_train, y_train, X_test)

    dt_cls = DecisionClassifier()
    dt_oop_train, dt_oofp_val = dt_cls.get_model_out(X_train, y_train, X_test)
     # 構造第二層Stacking模型的輸入
    input_train = [gnb_oop_train,rf_oop_train,lg_oop_train,dt_oop_train]
    input_test = [gnb_oofp_val,rf_oofp_val,lg_oofp_val,dt_oofp_val]

    stacked_train = np.concatenate([data.reshape(-1,1) for data in input_train],axis=1)
    stacked_test = np.concatenate([data.reshape(-1,1) for data in input_test],axis=1)

    # stacking 第二層模型訓練
    second_model = DecisionTreeClassifier(max_depth=3,class_weight={0: 1, 1: 4})
    second_model.fit(stacked_train,y_train)

Step5 整個專案的執行

1.選出抽取特徵的方法名組合成需要特徵輸入list
2.載入多個抽取方法抽取出的特徵資料和訓練集的label資料
呼叫方法:project.load_feature_lists(feature_names_list)
引數說明:feature_names_list為你的抽取特徵的方法名組合成list
返回引數說明:你的訓練集經過多種抽取方法組合成的多個列,你的測試集經過多種抽取方法組合成的多個列,每種抽取方法對應的列的index。
注意:一種抽取方法可能對應著多種特徵列
3.構建最終的分類模型,交叉驗證的方式

Step6 前期訓練資料的分析出現的問題的處理
1.對於樣本分類不平衡的問題,通過最終的樣本類別權重調整實現樣本不平衡問題的解決,在Sklearn中的分類模型用設定class_weight引數即可,檢視Sklearn的原理設定class_weight就是改變sample_weight。
2.對於正例的語句對樣本數量少的問題,通過將正例的樣本語句對進行順序調換,形成新的正例樣本對。
通過解決上述兩個問題,最終提交結果後的平臺測試的F1結果提升到0.6238.

4賽後總結

1.首先需要自己定義演算法的賽題,首先需要考慮好演算法的輸入的形式和輸出的展示。對於演算法的輸入,需要考慮好對輸入要做什麼預處理,以什麼形式輸入演算法中進行計算,也就是怎麼表示輸入。對於演算法的輸出,這是重點,它決定演算法的結構選型。
2.其次對於資料的分析,設計演算法的結構之前,一定需要對給出的賽題資料進行統計方面,演算法方面的分析,對潛在的可能需要解決的問題,或者存在的統計特徵進行記錄下來,這很可能是後期賽題成績提高的關鍵。
3.設計演算法的結構的時候,如果完全沒有想法,可以查詢相關的論文,從論文中提出的方法模型進行改進這是一種很好的方法。針對前期提出的潛在問題有針對性的查詢解決該些問題的論文。所以說平時有空多閱讀自己領域相關論文還是很有好處的。
4.訓練模型時,要儘量打印出每次演算法迭代過程中的val_loss,val_f1,val_acc,val_precision,val_recall.學會觀察這些資料,根據經驗來處理和分析出現列印的結果的原因。這很可能是檢視模型是否擬合訓練資料或者過擬合數據的基礎。
5.就是細節問題,最後成績的提高除了比拼演算法架構外,還比拼處理問題的細節,比如說詞向量的訓練的過程,中文預處理的過程,Embeding 矩陣是否當做引數進行微調的過程。

5參考文獻及連結

相關推薦

螞蟻金融NLP競賽——文字語義相似總結

1前言 許久沒有更新部落格了,主要是忙於考試周和最近參加的一個螞蟻金融的NLP比賽——文字語義相似度賽題。話不多說,直奔主題。本篇部落格主要記錄的是自己入門NLP以來第一次參加NLP性質的賽題的詳細解題過程。接下來將分成三個部分進行敘述:賽題描述、解題思路及相

文字匹配(語義相似/行為相關性)技術綜述

NLP 中,文字匹配技術,不像 MT、MRC、QA 等屬於 end-to-end 型任務,通常以文字相似度計算、文字相關性計算的形式,在某應用系統中起核心支撐作用,比如搜尋引擎、智慧問答、知識檢索、資訊流推薦等。本篇將縱覽文字匹配的技術發展,並重點介紹文字語義相似度計算技術,以及多輪對話

【python 走進NLP】標籤別名語義相似匹配演算法

標籤別名語義相似度匹配演算法: # -*- encoding=utf-8 -*- import pandas as pd import numpy as np import time time1

向量(文字相似(或點的距離)的計算方案彙總

       鑑於日常學習中常遇到將文字資料等轉為向量,然後計算向量相似度的問題,現將常用方案進行初步彙總,如統計不足敬請留言提示補充:1、餘弦相似度(cosine)        公式:                                即:以向量的夾角為考量角

基於《知網》的詞彙語義相似計算(上)(作者:劉群 李素建)

基於《知網》的詞彙語義相似度計算 劉群 李素建 {liuqun,lisujian}@ict.ac.cn † 中國科學院計算技術研究所   ‡ 北京大學計算語言學研究所 摘要: 《知網》是一部比較詳盡的語義知識詞典。在基於例項的機器翻譯中,詞語相似度計算是一個重要的環節。不過

【python + word2vec】計算語義相似

本方法是使用python語言使用word2vec 的方法來進行語義相似度的計算、 1、首先配置python27下的word2vec的環境(gensim),如下所示: 2、訓練文字 # -*- cod

NLP計算文件相似之doc2vec

import gensim outp1 = 'D:\python_noweightpathway\TIA\docmodel' file = open(u'D:\python_noweightpathway\TIA\TIAxmmc.txt', encoding=

如何比較兩個文字相似 .

目標 嘗試了一下把PageRank演算法結合了文字相似度計算。直覺上是想把一個list裡,和大家都比較靠攏的文字可能最後的PageRank值會比較大。因為如果最後計算的PageRank值大,說明有比較多的文字和他的相似度值比較高,或者有更多的文字向他靠攏。這樣是不是就可以得到一些相對核心的文字,或者相對代表

矩陣式比較兩文字字串相似(包含漢字)方法兩則(java程式碼)

package com.gsww.ctyxy.util; import java.text.NumberFormat;   import java.util.Locale;    /**  * 比較兩個字串的相似度  */   public class AutomaticRating {   /*    pu

NLP計算文件相似之TF-IDF

#!/usr/bin/python # -*- coding: utf-8 -*- import numpy import os from sklearn import feature_extraction from sklearn.feature_extr

Java進行語義相似分析

這是發的第二篇部落格,之前那篇還沒有通過稽核呢,無所謂。 想說說這個題目,還在上大四,自然語言處理和資訊檢索的知識在我們學校是研究生的課程,而且這個實驗室很NB哦,老那我不能保研,只能遠遠看著實驗室門牌號拿著紙巾……擦眼淚了。好在是良心學院,大四沒有什麼基礎課程了,卻開了還

計算兩張圖片相似的方法總結

title rac 相似度 無法 tween hive any 明顯 embed python工具包-pyssim 簡介 python工具包,用來計算圖像之間的結構相似性 (Structural Similarity Image Metric: SSIM)。結構相似性介紹

相似/距離方法總結

假設兩個向量 歐式距離:                                      

螞蟻金服金融大腦的挑戰賽的實現程式碼 NLP文字相似計算

近期做了一些NLP的研究,並基於6月份螞蟻金服金融大腦的挑戰賽,完成了文字相似度計算的驗證。主要思路是基於word2vec來進行訓練,並實現文字相似度的計算。所使用的語料,包括了公開的wiki語料,網友收集的微信語料,以及此大賽中的語料。其中微信語料的位置在https://s

NLP文字相似(TF-IDF)

 我們在比較事物時,往往會用到“不同”,“一樣”,“相似”等詞語,這些詞語背後都涉及到一個動作——雙方的比較。只有通過比較才能得出結論,究竟是相同還是不同。但是萬物真的有這麼極端的區分嗎?在我看來不是的,生活中通過“相似度”這詞來描述可能會更加準確。比如男人和女人,雖然生理器官和可能思想有

nlp文字相似計算問題

文章的目的:文字相似度計算一直是nlp中常見的問題,本文的目標是總結並對比文字相似度計算方法。當然文字的相似度計算會有進一步的應用,比如文字的分類、聚類等。 文章結構:本文先介紹最直接的字面距離相似度度量,而後介紹語義主題層面的度量,最後介紹目前一些新的相似度計算方法。 一、字面距

學習筆記--NLP文字相似之LCS(最長公共子序列)

最長公共子序列 一個序列S任意刪除若干個字元得到的新序列T,則T叫做S的子序列 兩個序列X和Y的公共子序列中,長度最長的那個,定義為X和Y的最長公共子序列  例如:      --字串12455與245576的最長公共子序列為2455      --字串acd

NLP】Python例項:基於文字相似對申報專案進行查重設計

作者:白寧超 2017年5月18日17:51:37 摘要:關於查重系統很多人並不陌生,無論本科還是碩博畢業都不可避免涉及論文查重問題,這也對學術不正之風起到一定糾正作用。單位主要針對科技專案申報稽核,傳統的方式人力物力比較大,且伴隨季度性的繁重工作,效率不高。基於此,單位覺得開發一款可以達到實用的

NLP點滴——文字相似,計算文字間的距離

前言 在自然語言處理過程中,經常會涉及到如何度量兩個文字之間的相似性,我們都知道文字是一種高維的語義空間,如何對其進行抽象分解,從而能夠站在數學角度去量化其相似性。而有了文字之間相似性的度量方式,我們便可以利用劃分法的K-means、基於密度的DBSCAN或者是基於模型的概率方法進行文字之間的聚類分析;另

從0到1,瞭解NLP中的文字相似

本文由雲+社群發表 作者:netkiddy 導語 AI在2018年應該是網