【NLP】使用Google的T5提取文本特征

2021-07-29 14:20:37 浏览数 (1)

作者 | Mike Casale

编译 | VK

来源 | Towards Data Science

下图是文本到文本框架的示意图。每个任务都使用文本作为模型的输入,通过训练生成一些目标文本。

这允许在不同的任务中使用相同的模型、损失函数和超参数,包括翻译(绿色)、语言可接受性(红色)、句子相似性(黄色)和文档摘要(蓝色)。


在本文中,我们将演示如何使用Google T5对表格数据中的文本进行特征化。你可以使用这个存储库中的Jupyter笔记本:

https://github.com/mikewcasale/nlp_primitives

当试图在机器学习管道中利用真实世界的数据时,通常会遇到书面文本—例如,在预测房地产估价时,有许多数字特征,例如:

  • “卧室数量”
  • “浴室数量”
  • “面积(平方英尺)”
  • “纬度”
  • “经度”
  • 等等…

但同时,也有大量的书面文本,比如在Zillow等网站的房地产上市描述中。这些文本数据可以包括许多其他方面没有考虑到的有价值的信息,例如:

  • 开放式厨房/平面图
  • 花岗岩个数
  • 硬木地板
  • 不锈钢电器
  • 最近的装修
  • 等等…

然而,令人惊讶的是,许多AutoML工具完全忽略了这些信息,因为诸如XGBoost之类的流行表格算法不能直接使用书面文本。

这就是Featuretools基本函数的用武之地。Featuretools旨在为不同类型的数据(包括文本)自动创建特征,然后表格机器学习模型可以使用这些数据。

在本文中,我们将展示如何扩展nlp Primitive库,以便与Google最先进的T5模型一起使用,并在此过程中创建最重要的nlp特征,进而提高准确性。

关于T5

对于任何不熟悉T5的读者来说,T5模型出现在谷歌的论文中,题目是Exploring the Limits of Transfer Learning with a Unified Text-to-Text Transformer。

使用Hugging Face T5的一个机器学习demo

在NLP的背景下,Hugging Face Transformers是一个自然语言处理库,对很多ML模型开放,并得到了像Flair、Asteroid、ESPnet、Pyannote等库的支持。

为了扩展NLP库以便与T5一起使用,我们将构建两个自定义TransformPrimitive类。出于实验目的,我们测试了两种方法:

  • 微调Hugging Face T5-base
  • Hugging Face T5-base的情感分析

首先,让我们加载基本模型。

代码语言:javascript复制
from simpletransformers.t5 

import T5Modelmodel_args = {
    "max_seq_length": 196,
    "train_batch_size": 8,
    "eval_batch_size": 8,
    "num_train_epochs": 1,
    "evaluate_during_training": True,
    "evaluate_during_training_steps": 15000,
    "evaluate_during_training_verbose": True,
    "use_multiprocessing": False,
    "fp16": False,
    "save_steps": -1,
    "save_eval_checkpoints": False,
    "save_model_every_epoch": False,
    "reprocess_input_data": True,
    "overwrite_output_dir": True,
    "wandb_project": None,
}

model = T5Model("t5", "t5-base", args=model_args)

第二,让我们加载预训练模型。

代码语言:javascript复制
model_pretuned_sentiment = T5Model('t5',
                                   'mrm8488/t5-base-finetuned-imdb-sentiment',
                                   use_cuda=True)
model_pretuned_sentiment.args

为了对t5模型进行微调,需要对训练数据进行重组和格式化。

从Kaggle数据集,我们将review_text列映射到一个名为input_text的新列,我们将review_rating列映射到一个名为target_text的新列,这意味着review_rating就是我们试图预测的内容。

这些更改符合Simpletransformers库接口,用于微调t5,其中主要的附加要求是指定一个“前缀”,用于帮助进行多任务训练(注意:在本例中,我们将重点放在单个任务上,因此前缀不必使用,但是,我们无论如何都会定义它,以便于使用)。

代码语言:javascript复制
dft5 = df[['review_text','review_rating']
].rename({
'review_text':'input_text',
'review_rating':'target_text'
},axis=1)

dft5['prefix'] = ['t5-encode' for x in range(len(dft5))]dft5['target_text'] = 

dft5['target_text'].astype(str)

dft5

本例中的目标文本是消费者对给定餐厅的评分。我们可以通过以下方法轻松地微调T5模型

代码语言:javascript复制
from sklearn.model_selection import train_test_split

train_df, eval_df = train_test_split(dft5)

model.train_model(train_df, eval_data=eval_df)

接下来,我们加载预训练模型。

代码语言:javascript复制
test = ['Great drinks and food', 
list(np.array(model.predict(test)).astype(float))
 'Good food & beer',

 Generating outputs: 0%| | 0/1 [00:00<?, ?it/s] Generating outputs: 100%|██████████| 1/1 [00:00<00:00, 3.17it/s] Generating outputs: 100%|██████████| 1/1 [00:00<00:00, 3.16it/s] Decoding outputs: 0%| | 0/3 [00:00<?, ?it/s] Decoding outputs: 33%|███▎ | 1/3 [00:00<00:01, 1.14it/s] Decoding outputs: 100%|██████████| 3/3 [00:00<00:00, 3.43it/s] Out[14]: [4.0, 4.0, 4.0] 
 'Pretty good beers']

我们可以看到,微调模型输出了review_rankings列表[4.0,4.0,4.0],这是一个预测结果。

接下来,让我们使用预训练的模型进行测试。

代码语言:javascript复制
test = ['Great drinks and food', 
     'Good food &amp; beer', 
     'Pretty good beers']

list(np.where(np.array(model_pretuned_sentiment.predict(test))=='positive', 1.0, 0.0))

Generating outputs:   0%|          | 0/1 [00:00<?, ?it/s] Generating outputs: 100%|██████████| 1/1 [00:00<00:00,  7.57it/s] Generating outputs: 100%|██████████| 1/1 [00:00<00:00,  7.56it/s]  Decoding outputs:   0%|          | 0/3 [00:00<?, ?it/s] Decoding outputs:  33%|███▎      | 1/3 [00:00<00:01,  1.17it/s] Decoding outputs: 100%|██████████| 3/3 [00:00<00:00,  3.50it/s] Out[15]: [1.0, 1.0, 1.0]

注意,预训练模型输出一个布尔真/假值列表,该列表指示语句是正还是负-我们将它们转换为浮点值,以便更好地与表格建模集成。在这种情况下,所有值都为true,因此输出变为[1.0、1.0、1.0]。

既然我们已经加载了两个版本的T5,我们可以构建TransformPrimitive类,这些类将与NLP和Featuretools库集成。

代码语言:javascript复制
from featuretools.primitives.base import TransformPrimitive
from featuretools.variable_types import Numeric, Text


class T5Encoder(TransformPrimitive):

    name = "t5_encoder"
    input_types = [Text]
    return_type = Numeric
    default_value = 0

    def __init__(self, model=model):
      self.model = model    
    def get_function(self): 

      def t5_encoder(x):
            model.args.use_multiprocessing = True
            return list(np.array(model.predict(x.tolist())).astype(float))
      return t5_encoder

以上代码创建了一个名为T5编码器的新类,该类将使用微调的T5模型,下面的代码创建了一个名为T5SentimentEncoder的新类,该类将使用预训练的T5模型。

代码语言:javascript复制
class T5SentimentEncoder(TransformPrimitive):

    name = "t5_sentiment_encoder"
    input_types = [Text]
    return_type = Numeric
    default_value = 0

    def __init__(self, model=model_pretuned_sentiment):
      self.model = model

    def get_function(self):
      def t5_sentiment_encoder(x):
          model.args.use_multiprocessing = True
            return list(np.where(np.array(model_pretuned_sentiment.predict(x.tolist()))=='positive',1.0,0.0))
        return t5_sentiment_encoder

Featuretools现在知道如何使用T5来为文本列提供特征,它甚至会使用T5输出计算聚合

定义了这些新类之后,我们只需将它们与默认类一起以所需的Featuretools格式包起来,这将使它们可用于自动化特征工程

代码语言:javascript复制
trans = [
           T5Encoder,
           T5SentimentEncoder,
           DiversityScore,
           LSA,
           MeanCharactersPerWord,
           PartOfSpeechCount,
           PolarityScore, 
           PunctuationCount,
           StopwordCount,
           TitleWordCount,
           UniversalSentenceEncoder,
           UpperCaseCount
        ]

ignore = {'restaurants': ['rating'],
          'reviews': ['review_rating']}

drop_contains = ['(reviews.UNIVERSAL']

features = ft.dfs(entityset=es,
                  target_entity='reviews',
                  trans_primitives=trans,
                  verbose=True,
                  features_only=True,
                  ignore_variables=ignore,
                  drop_contains=drop_contains,
                  max_depth=4)

正如你在下面的输出中看到的,Featuretools库非常强大!事实上,除了这里显示的T5特征之外,它还使用指定的所有其他NLP Primitive创建了数百个特征,非常酷!

代码语言:javascript复制
feature_matrix = ft.calculate_feature_matrix(features=features,
                                             entityset=es,
                                             verbose=True)

features

机器学习

现在我们使用包含新创建的T5 Primitive的特征矩阵从sklearn创建和测试各种机器学习模型。

作为提醒,我们将比较T5增强的精确度和Alteryx博客《自动特征工程的自然语言处理》中演示的精确度:https://innovation.alteryx.com/natural-language-processing-featuretools/

使用逻辑回归:

请注意,上面的0.64逻辑回归分数显示了比Featuretools原生逻辑回归分数0.63有0.01的改进。

使用随机林分类器:

请注意,上面T5增强的0.65随机林分类器分数显示了比Featuretools本机随机林分类器分数0.64有0.01的改进。

随机森林分类器特征重要性

我们可以查看sklearn随机森林分类器的特征重要性,可以看到改进的分数归于新的T5特征。

从上表中我们可以看到,随机林模型的最高特征重要性是新创建的特征

T5情感编码器(标题)!

关键特征
  1. T5模型是一个健壮、灵活的文本到文本转换器,它可以增强几乎任何NLP任务的结果,包括处理文本数据时NLP Primitive库的结果。虽然额外的准确度在这里微不足道,但几乎可以肯定的是,除了情绪分析之外,通过实施额外的预训练模型,可以提高准确度。 此外,在这个例子中,我们微调的T5版本只在review_text上训练,而不是在review_title数据上训练,这似乎与Featuretools创建的特征不一致。纠正这个问题很可能意味着更高的整体性能。
  2. 扩展Featuretools框架非常简单,可以使用Hugging Face transformersSimpletransformers库。再加上几行代码,精确度就提高了,代码的复杂度也保持不变。

0 人点赞