乐趣区

关于人工智能:基于Bert和通用句子编码的SparkNLP文本分类

作者 |Veysel Kocaman
编译 |VK
起源 |Towards Data Science

自然语言解决 (NLP) 是许多数据迷信零碎中必须了解或推理文本的要害组成部分。常见的用例包含文本分类、问答、释义或总结、情感剖析、自然语言 BI、语言建模和消歧。

NLP 在越来越多的人工智能利用中是越来越重要。如果你正在构建聊天机器人、搜寻专利数据库、将患者与临床试验相匹配、对客户服务或销售电话进行分级、从财务报告中提取摘要,你必须从文本中提取精确的信息。

文本分类 是古代自然语言解决的次要工作之一,它是为句子或文档指定一个适合的类别的工作。类别取决于所选的数据集,并且能够从主题开始。

每一个文本分类问题都遵循类似的步骤,并用不同的算法来解决。更不用说经典和风行的机器学习分类器,如随机森林或 Logistic 回归,有 150 多个深度学习框架提出了各种文本分类问题。

文本分类问题中应用了几个基准数据集,能够在 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/JohnSnowLa…。

! 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/JohnSnowLa…。

那咱们就能够训练了。

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/JohnSnowLa…。咱们还筹备了另一个 Notebook,简直涵盖了 Spark NLP 和 Spark ML 中所有可能的文本分类组合(CV、TfIdf、Glove、Bert、Elmo、USE、LR、RF、ClassifierDL、DocClassifier):https://github.com/JohnSnowLa…。

咱们还开始为公共和企业 (医疗) 版本提供在线 Spark NLP 训练。这里是所有公共 Colab Notebook 的链接(https://github.com/JohnSnowLa…

John Snow 实验室将组织虚构 Spark NLP 训练,以下是下一次训练的链接:

https://events.johnsnowlabs.c…

以上代码截图

原文链接:https://towardsdatascience.co…

欢送关注磐创 AI 博客站:
http://panchuang.net/

sklearn 机器学习中文官网文档:
http://sklearn123.com/

欢送关注磐创博客资源汇总站:
http://docs.panchuang.net/

退出移动版