Deeplearning4j 實戰 (16):FastText在監督學習和無監督學習中的應用

Eclipse Deeplearning4j GitChat課程https://gitbook.cn/gitchat/column/5bfb6741ae0e5f436e35cd9f
Eclipse Deeplearning4j 系列博客https://blog.csdn.net/wangongxi
Eclipse Deeplearning4j Githubhttps://github.com/eclipse/deeplearning4j

Deeplearning4j 1.0.0-beta5的版本中NLP模塊開始支持FastText模型。在這之前的版本中,已經支持的embedding算法有Word2Vec、Glove、Doc2Vec以及Graph Embedding。這些模塊的使用在我的GitChat CSDN達人課中有詳細講解,有需要的開發人員可以參考。
FastText是Word2Vec的作者Tomas Mikolov在Facebook的研究成果,這裏先貼下論文的地址:Link。FastText的模型結構非常簡單,本質是一個三層的神經網絡結構。輸入層是文本的N-gram語言模型特徵,這些詞被embedding後轉化成詞向量並且加權平均形成隱藏層,在輸出層可以使用負採樣(Negative Sampling)、層次SoftMax(Hierarchical Softmax)以及直接Softmax作爲損失函數。以下是論文中模型結構的截圖:
fasttext-model
FastText相對於Word2Vec的創新點其實是在於輸入層引入N-gram語言模型的這一trick。其餘的模型結構包括損失函數都和Word2Vec類似。因此FastText也是可以直接進行無監督的建模,用於提取語義向量。但更多場景下,開發人員將FastText用於諸如文本分類的工作中,作爲對比其他複雜神經網絡模型的baseline。由於其網絡結構相對簡單,因此baseline的工作可以放在CPU上進行,非常快速和方便。
FastText的實現已經開源,開發人員可以去Github託管地址查看相關代碼。另外,官方同樣針對全世界近300種語言提供了預訓練的模型,其中包括歐美語言以及中日韓等常用語言。對於預訓練模型的使用在下面的內容中將會詳細描述,這裏先附上下載說明的地址:預訓練模型

1. 預訓練中文維基百科模型

Deeplearning4j 1.0.0-beta5版本中的FastText模型支持加載Python原生預訓練的模型。在上文的介紹中我們已經給出了預訓練模型的地址,開發人員可以自行下載。需要指出的是,下載頁面上對於每一種語言會放上bin+text和text兩個鏈接。bin+tex的鏈接包含兩個部分,一個是預訓練好的詞向量(以.vec爲擴展名的文件)另一個是模型文件本身(以.bin爲擴展名的文件)。我們直接用文本編輯器打開.vec文件,可以看下類似下面截圖的信息:
在這裏插入圖片描述
可以看到,文件內容的第一行包含了詞表大小和詞向量大小兩個重要信息。從第二行開始是每一個次以及其對應的詞向量。圖中就是包含了5W左右中文詞並且詞向量維度是100的一份數據。
下面我們介紹如何基於Deeplearning4j中的FastText模型加載Facebook官方預訓練的中文詞向量來做預測。Facebook官方提供的詞向量都是基於各大語言的維基百科來進行訓練的。
在這裏插入圖片描述
我們直接點擊bin+text的鏈接下載模型和詞向量文件。下載下來的是個zip文件,解壓後可以得到之前說的兩個文件,其中.vec文件800M左右,.bin文件3G左右。我們可以通過以下邏輯來加載這兩個預訓練好的模型文件。

public void loadPretrained(){
    FastText fastText = new FastText(new File("fasttext/model/wiki.zh.bin"));
    fastText.loadPretrainedVectors(new File("fasttext/model/wiki.zh.vec"));
	//加載預訓練模型結束
	//預測相似詞        
	System.out.println(fastText.wordsNearest("網絡", 3));
	//預測詞向量
    System.out.println(Arrays.toString(fastText.getWordVector("網絡")));
}

在上面這段邏輯中,我們分別加載了模型和詞向量文件,之後我們預測了“網絡”這個詞的Top3相似詞以及該詞本身的詞向量,可以得到以下結果。
在這裏插入圖片描述
需要注意,由於Facebook官方預訓練的模型較大,因此在程序啓動的時候,開發人員可以適當調整下JVM參數。我這邊設置的參數是:-Xms4G -Xmx8G。

2. 監督學習

這部分我們介紹下如何基於FastText進行文本分類的工作。在之前的博客中,我們介紹過基於Embedding+LSTM的結構做文本分類問題,這裏我們使用那篇博客相同的語料。爲了兼容FastText官方的語料格式,我們將原始語料處理成類似下面截圖的這種樣式。
在這裏插入圖片描述
語料中第一列是標註。真正和業務相關的標註是“正面”和“負面”,而且帶有label的前綴是默認的用於定義標註信息的前綴。當然這個在聲明模型實例的時候,可以自定義。語料中以空格隔開標註和語料。同之前的博客一樣,我們用jieba分詞預先將句子進行分詞。下面我們給出FastText的分類建模邏輯。

    public void supervised(File inputFile, File output){
    FastText fastText = FastText.builder()
                                .supervised(true)
                                .learningRate(0.01)
                                .wordNgrams(2)
                                .numThreads(4)
                                .epochs(20)
                                .inputFile(inputFile.getAbsolutePath())
                                .outputFile(output.getAbsolutePath()).build();
    fastText.fit();
    
    //
    FastText _fastText = new FastText(new File("fasttext/supervised/supervised.mod.bin"));
    //
    Pair<String,Float> result = _fastText.predictProbability("鄙視 蒙牛 鄙視 中糧 鄙視 寧高寧");
    System.out.println(result.getFirst() + "\t" + Math.exp(result.getRight()));
}

在上述邏輯中,我們首先聲明瞭一個FastText模型的實例並配置一些參數。這裏涉及的主要是學習率、語言模型等。由於實際可設置的參數衆多,這裏不一一列舉。具體我們可以參考Facebook官方給出的參數列表,以下是截圖。
在這裏插入圖片描述
每一行的參數給出了一些物理含義的解釋,最後方括號中的是默認取值。例如,-loss參數的默認取值是softmax,同時也支持ns(negative sampling,負採樣),hs(hierarchical softmax,分層softmax)的損失函數。在上面代碼中,我們沒有對損失函數做特別設置,因此就是默認的softmax。
我們直接調用fit接口來進行模型的訓練。在訓練結束後,我們重新加載這一模型到內存,並且嘗試預測單條語料的分類結果。我們調用predictProbability接口可以得到一個二元組的返回值。其中key是預測標註,value是對數概率。爲了更加直觀的展示原始分類概率,我們將對數概率結果取自然指數值就可以還原成原始概率值。訓練過程中的日誌和預測結果可以參考下圖。
在這裏插入圖片描述
從日誌中我們可以看到,訓練語料中一共包含50920個詞,2個標註。我們最後預測了單條語料的標註,獲得了預測結果以及概率大小。

3. 無監督學習

FastText的無監督學習主要用於生成詞向量,使用的方法和訓練Word2Vec以及Glove等模型類似。首先我們看下語料的構建。
在這裏插入圖片描述
無監督訓練語料的構建只需要在之前帶標註語料的基礎上將標註信息刪去即可。換言之,語料中的每一行其實是分詞後的單條語料。我們同樣使用jieba分詞,並且詞間用空格進行分隔。我們來看下建模的邏輯。

    public void unsupervised(File inputFile,  File output){
    FastText fastText = FastText.builder()
                                .supervised(false)	//無監督建模
                                .skipgram(true)
                                .minCount(1)
                                .bucket(10)
                                .numThreads(4)
                                .lossName("ns")
                                .epochs(10)
                                .inputFile(inputFile.getAbsolutePath())
                                .outputFile(output.getAbsolutePath()).build();
    fastText.fit();
    //
    FastText _fastText = new FastText(new File("fasttext/unsupervised/unsupervised.mod.bin"));
    //
	//        VocabCache vocab = _fastText.vocab();
	//        System.out.println(vocab.vocabWords());
    _fastText.loadPretrainedVectors(new File("fasttext/unsupervised/unsupervised.mod.vec"));
    System.out.println(_fastText.wordsNearest("內存", 3));
    System.out.println(Arrays.toString(_fastText.getWordVector("內存")));
}

同第二部分監督學習的建模邏輯類似,我們聲明一個FastText實例,但是需要在supervised方法設置爲false,即設置無監督學習。我們通過skipgram或者cbow設置需要用的算法,包括在lossName方法中設置損失函數爲ns,即負採樣。我們調用fit方法進行模型訓練並且將模型文件保存到指定磁盤位置。之後,類似在第一部分加載預訓練模型的那種操作,我們分別加載模型和詞向量文件到內存,並且使用“內存”這個詞進行相似詞的推理測試以及打印該詞的詞向量。結果如下圖。
在這裏插入圖片描述
從截圖中我們看到紅色字體的是訓練部分的日誌。主要記錄了建模期間主要參數的變化。最後兩行信息是我們在代碼中通過控制檯輸出的,可以看到和“內存”這個詞相似的Top3的詞是“1G”,“2G”,“標配”這幾個詞以及最後一行詞向量本身。詞向量本身會保存在.vec的文件中,格式在上面的部分已經介紹過,這裏不展開講了。詞向量本身可以直接通過計算某種相似度來作爲一些應用場景的召回,當然也可以作爲下一階段神經網絡的輸入。

4. 小結

這次我們主要介紹了Deeplearning4j 1.0.0-beta5版本中新增的FastText模型的使用。我們分別介紹了在監督學習、無監督學習以及加載官方預訓練模型三個主要場景下的使用方法。Deeplearning4j中的FastText底層實際是依賴JFastText這個項目。JFastText是通過JavaCPP的JNI方式調用Facebook原生接口來實現的,因此可以完全兼容原始項目的接口和文件格式。
FastText模型本身使用了N-gram語言模型來優化輸入的特徵。對於一些經典的NLP問題,如:文本分類,語言模型的引入會較大程度地提升模型指標。FastText正是借鑑了這樣的思想,將其與之前Word2Vec中使用過的網絡結構相結合從而產生了一種快速高效可以用於監督學習的模型。在上文中我們提到,FastText的分類結果往往會作爲baseline的指標,這樣源於其模型較爲簡單,建模快速的特點。上述的這些工作,作者都是在本地CPU機器上完成,有興趣的朋友也可以自己嘗試下。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章