基於Bert和通用句子編碼的Spark-NLP文本分類

做者|Veysel Kocaman
編譯|VK
來源|Towards Data Sciencepython

天然語言處理(NLP)是許多數據科學系統中必須理解或推理文本的關鍵組成部分。常見的用例包括文本分類、問答、釋義或總結、情感分析、天然語言BI、語言建模和消歧。git

NLP在愈來愈多的人工智能應用中是愈來愈重要。若是你正在構建聊天機器人、搜索專利數據庫、將患者與臨牀試驗相匹配、對客戶服務或銷售電話進行分級、從財務報告中提取摘要,你必須從文本中提取準確的信息。github

文本分類是現代天然語言處理的主要任務之一,它是爲句子或文檔指定一個合適的類別的任務。類別取決於所選的數據集,而且能夠從主題開始。算法

每個文本分類問題都遵循類似的步驟,並用不一樣的算法來解決。更不用說經典和流行的機器學習分類器,如隨機森林或Logistic迴歸,有150多個深度學習框架提出了各類文本分類問題。sql

文本分類問題中使用了幾個基準數據集,能夠在nlpprogress.com上跟蹤最新的基準。如下是關於這些數據集的基本統計數據。數據庫

簡單的文本分類應用程序一般遵循如下步驟:網絡

  • 文本預處理和清理
  • 特徵工程(手動從文本建立特徵)
  • 特徵向量化(TfIDF、頻數、編碼)或嵌入(word2vec、doc2vec、Bert、Elmo、句子嵌入等)
  • 用ML和DL算法訓練模型。

Spark-NLP中的文本分類

在本文中,咱們將使用通用句子嵌入(Universal Sentence Embeddings)在Spark NLP中創建一個文本分類模型。而後咱們將與其餘ML和DL方法以及文本向量化方法進行比較。多線程

Spark NLP中有幾個文本分類選項:框架

  • Spark-NLP中的文本預處理及基於Spark-ML的ML算法
  • Spark-NLP和ML算法中的文本預處理和單詞嵌入(Glove,Bert,Elmo)
  • Spark-NLP和ML算法中的文本預處理和句子嵌入(Universal Sentence Encoders)
  • Spark-NLP中的文本預處理和ClassifierDL模塊(基於TensorFlow)

正如咱們在關於Spark NLP的重要文章中所深刻討論的,在ClassifierDL以前的全部這些文本處理步驟均可以在指定的管道序列中實現,而且每一個階段都是一個轉換器或估計器。這些階段按順序運行,輸入數據幀在經過每一個階段時進行轉換。也就是說,數據按順序經過各個管道。每一個階段的transform()方法更新數據集並將其傳遞到下一個階段。藉助於管道,咱們能夠確保訓練和測試數據通過相同的特徵處理步驟。機器學習

Universal Sentence Encoders

在天然語言處理(NLP)中,在創建任何深度學習模型以前,文本嵌入起着重要的做用。文本嵌入將文本(單詞或句子)轉換爲向量。

基本上,文本嵌入方法在固定長度的向量中對單詞和句子進行編碼,以極大地改進文本數據的處理。這個想法很簡單:出如今相同上下文中的單詞每每有類似的含義。

像Word2vec和Glove這樣的技術是經過將一個單詞轉換成向量來實現的。所以,對應的向量「貓」比「鷹」更接近「狗」。可是,當嵌入一個句子時,整個句子的上下文須要被捕獲到這個向量中。這就是「Universal Sentence Encoders」的功能了。

Universal Sentence Encoders將文本編碼成高維向量,可用於文本分類、語義類似性、聚類和其餘天然語言任務。在Tensorflow hub中能夠公開使用預訓練的Universal Sentence Encoders。它有兩種變體,一種是用Transformer編碼器訓練的,另外一種是用深度平均網絡(DAN)訓練的。

Spark NLP使用Tensorflow hub版本,該版本以一種在Spark環境中運行的方式包裝。也就是說,你只需在Spark NLP中插入並播放此嵌入,而後以分佈式方式訓練模型。

爲句子生成嵌入,無需進一步計算,由於咱們並非平均句子中每一個單詞的單詞嵌入來得到句子嵌入。

Spark-NLP中ClassifierDL和USE在文本分類的應用

在本文中,咱們將使用AGNews數據集(文本分類任務中的基準數據集之一)在Spark NLP中使用USE和ClassifierDL構建文本分類器,後者是Spark NLP 2.4.4版中添加的最新模塊。

ClassifierDL是Spark NLP中第一個多類文本分類器,它使用各類文本嵌入做爲文本分類的輸入。ClassifierDLAnnotator使用了一個在TensorFlow內部構建的深度學習模型(DNN),它最多支持50個類。

也就是說,你能夠用這個classifirdl在Spark NLP中用BertElmoGloveUniversal Sentence Encoders構建一個文本分類器。

咱們開始寫代碼吧!

聲明加載必要的包並啓動一個Spark會話。

import sparknlp
spark = sparknlp.start() 
# sparknlp.start(gpu=True) >> 在GPU上訓練
from sparknlp.base import *
from sparknlp.annotator import *
from pyspark.ml import Pipeline
import pandas as pd
print("Spark NLP version", sparknlp.version())
print("Apache Spark version:", spark.version)
>> Spark NLP version 2.4.5
>> Apache Spark version: 2.4.4

而後咱們能夠從Github repo下載AGNews數據集(https://github.com/JohnSnowLabs/spark-nlp-workshop/tree/master/tutorials/Certification_Trainings/Public)。

! wget https://raw.githubusercontent.com/JohnSnowLabs/spark-nlp-workshop/master/tutorials/Certification_Trainings/Public/data/news_category_train.csv
! wget https://raw.githubusercontent.com/JohnSnowLabs/spark-nlp-workshop/master/tutorials/Certification_Trainings/Public/data/news_category_test.csv
trainDataset = spark.read \
      .option("header", True) \
      .csv("news_category_train.csv")
trainDataset.show(10, truncate=50)
>> 
+--------+--------------------------------------------------+
|category|                                       description|
+--------+--------------------------------------------------+
|Business| Short sellers, Wall Street's dwindling band of...|
|Business| Private investment firm Carlyle Group, which h...|
|Business| Soaring crude prices plus worries about the ec...|
|Business| Authorities have halted oil export flows from ...|
|Business| Tearaway world oil prices, toppling records an...|
|Business| Stocks ended slightly higher on Friday but sta...|
|Business| Assets of the nation's retail money market mut...|
|Business| Retail sales bounced back a bit in July, and n...|
|Business|" After earning a PH.D. in Sociology, Danny Baz...|
|Business| Short sellers, Wall Street's dwindling  band o...|
+--------+--------------------------------------------------+
only showing top 10 rows

AGNews數據集有4個類:World、Sci/Tech、Sports、Business

from pyspark.sql.functions import col
trainDataset.groupBy("category") \
    .count() \
    .orderBy(col("count").desc()) \
    .show()
>>
+--------+-----+
|category|count|
+--------+-----+
|   World|30000|
|Sci/Tech|30000|
|  Sports|30000|
|Business|30000|
+--------+-----+
testDataset = spark.read \
      .option("header", True) \
      .csv("news_category_test.csv")
testDataset.groupBy("category") \
    .count() \
    .orderBy(col("count").desc()) \
    .show()
>>
+--------+-----+
|category|count|
+--------+-----+
|Sci/Tech| 1900|
|  Sports| 1900|
|   World| 1900|
|Business| 1900|
+--------+-----+

如今,咱們能夠將這個數據提供給Spark NLP DocumentAssembler,它是任何Spark datagram的Spark NLP的入口點。

# 實際內容在description列
document = DocumentAssembler()\
    .setInputCol("description")\
    .setOutputCol("document")
    
#咱們能夠下載預先訓練好的嵌入
use = UniversalSentenceEncoder.pretrained()\
 .setInputCols(["document"])\
 .setOutputCol("sentence_embeddings")
# classes/labels/categories 在category列
classsifierdl = ClassifierDLApproach()\
  .setInputCols(["sentence_embeddings"])\
  .setOutputCol("class")\
  .setLabelColumn("category")\
  .setMaxEpochs(5)\
  .setEnableOutputLogs(True)
use_clf_pipeline = Pipeline(
    stages = [
        document,
        use,
        classsifierdl
    ])

以上,咱們獲取數據集,輸入,而後從使用中獲取句子嵌入,而後在ClassifierDL中進行訓練

如今咱們開始訓練。咱們將使用ClassiferDL中的.setMaxEpochs()訓練5個epoch。在Colab環境下,這大約須要10分鐘才能完成。

use_pipelineModel = use_clf_pipeline.fit(trainDataset)

運行此命令時,Spark NLP會將訓練日誌寫入主目錄中的annotator_logs文件夾。下面是獲得的日誌。

如你所見,咱們在不到10分鐘的時間內就實現了90%以上的驗證精度,而無需進行文本預處理,這一般是任何NLP建模中最耗時、最費力的一步。

如今讓咱們在最先的時候獲得預測。咱們將使用上面下載的測試集。

下面是經過sklearn庫中的classification_report得到測試結果。

咱們達到了89.3%的測試集精度!看起來不錯!

基於Bert和globe嵌入的Spark-NLP文本預處理分類

與任何文本分類問題同樣,有不少有用的文本預處理技術,包括詞幹、詞幹分析、拼寫檢查和停用詞刪除,並且除了拼寫檢查以外,Python中幾乎全部的NLP庫都有應用這些技術的工具。目前,Spark NLP庫是惟一一個具有拼寫檢查功能的可用NLP庫。

讓咱們在Spark NLP管道中應用這些步驟,而後使用glove嵌入來訓練文本分類器。咱們將首先應用幾個文本預處理步驟(僅經過保留字母順序進行標準化,刪除停用詞字和詞幹化),而後獲取每一個標記的單詞嵌入(標記的詞幹),而後平均每一個句子中的單詞嵌入以得到每行的句子嵌入。

關於Spark NLP中的全部這些文本預處理工具以及更多內容,你能夠在這個Colab筆記本中找到詳細的說明和代碼示例(https://github.com/JohnSnowLabs/spark-nlp-workshop/blob/master/tutorials/Certification_Trainings/Public/2.Text_Preprocessing_with_SparkNLP_Annotators_Transformers.ipynb)。

那咱們就能夠訓練了。

clf_pipelineModel = clf_pipeline.fit(trainDataset)

獲得測試結果。

如今咱們有88%的測試集精度!即便在全部這些文本清理步驟以後,咱們仍然沒法擊敗Universal Sentence Embeddings+ClassifierDL,這主要是由於USE相對於數據清理後的版本,它在原始文本上執行得更好。

爲了訓練與BERT相同的分類器,咱們能夠在上面構建的同一管道中用BERT_embedding替換glove_embeddings。

word_embeddings = BertEmbeddings\
    .pretrained('bert_base_cased', 'en') \
    .setInputCols(["document",'lemma'])\
    .setOutputCol("embeddings")\
    .setPoolingLayer(-2) # default 0

咱們也可使用Elmo嵌入。

word_embeddings = ElmoEmbeddings\
      .pretrained('elmo', 'en')\
      .setInputCols(["document",'lemma'])\
      .setOutputCol("embeddings")

使用LightPipeline進行快速推理

正如咱們在前面的一篇文章中深刻討論的,LightPipelines是Spark NLP特有的管道,至關於Spark ML管道,但其目的是處理少許的數據。它們在處理小數據集、調試結果或從服務一次性請求的API運行訓練或預測時很是有用。

Spark NLP LightPipelines是Spark ML管道轉換成在單獨的機器上,變成多線程的任務,對於較小的數據量(較小的是相對的,但5萬個句子大體最大值)來講,速度快了10倍以上。要使用它們,咱們只需插入一個通過訓練的管道,咱們甚至不須要將輸入文本轉換爲DataFrame,就能夠將其輸入到一個管道中,該管道首先接受DataFrame做爲輸入。當須要從通過訓練的ML模型中得到幾行文本的預測時,這個功能將很是有用。

LightPipelines很容易建立,並且能夠避免處理Spark數據集。它們的速度也很是快,當只在驅動節點上工做時,它們執行並行計算。讓咱們看看它是如何適用於咱們上面描述的案例的:

light_model = LightPipeline(clf_pipelineModel)
text="Euro 2020 and the Copa America have both been moved to the summer of 2021 due to the coronavirus outbreak."
light_model.annotate(text)['class'][0]
>> "Sports"

你還能夠將這個通過訓練的模型保存到磁盤中,而後稍後在另外一個Spark管道中與ClassifierDLModel.load()一塊兒使用。

結論

本文在Spark-NLP中利用詞嵌入和Universal Sentence Encoders,訓練了一個多類文本分類模型,在不到10min的訓練時間內得到了較好的模型精度。整個代碼均可以在這個Github repo中找到(Colab兼容,https://github.com/JohnSnowLabs/spark-nlp-workshop/blob/master/tutorials/Certification_Trainings/Public/5.Text_Classification_with_ClassifierDL.ipynb)。咱們還準備了另外一個Notebook,幾乎涵蓋了Spark NLP和Spark ML中全部可能的文本分類組合(CV、TfIdf、Glove、Bert、Elmo、USE、LR、RF、ClassifierDL、DocClassifier):https://github.com/JohnSnowLabs/spark-nlp-workshop/blob/master/tutorials/Certification_Trainings/Public/5.1_Text_classification_examples_in_SparkML_SparkNLP.ipynb。

咱們還開始爲公共和企業(醫療)版本提供在線Spark NLP訓練。這裏是全部公共Colab Notebook的連接(https://github.com/JohnSnowLabs/spark-nlp-workshop/tree/master/tutorials/Certification_Trainings/Public)

John Snow實驗室將組織虛擬Spark NLP訓練,如下是下一次訓練的連接:

https://events.johnsnowlabs.com/online-training-spark-nlp

以上代碼截圖

原文連接:https://towardsdatascience.com/text-classification-in-spark-nlp-with-bert-and-universal-sentence-encoders-e644d618ca32

歡迎關注磐創AI博客站:
http://panchuang.net/

sklearn機器學習中文官方文檔:
http://sklearn123.com/

歡迎關注磐創博客資源彙總站:
http://docs.panchuang.net/

相關文章
相關標籤/搜索