zoukankan      html  css  js  c++  java
  • NLP(十四):Transformer—用BERT,RoBERTa,XLNet,XLM和DistilBERT文本分类

    https://zhuanlan.zhihu.com/p/87760325

    https://zhuanlan.zhihu.com/p/89232880

    一、前言

    Simple Transformers是Hugging Face在的Transformers库的基础上构建的。 Hugging Face Transformers库是供研究人员和其他需要全面控制操作方式的人员使用的库。 当需要偏离常规,做不同的事情或完全做新的事情时,它也是最佳选择。 比如NLP中得多分类任务,下面根据我的简单测试,一起看看。

    二、介绍

    Simple Transformers专为一些特殊得NLP任务设计得。文本分类非常普遍,如今再NLP任务中也不算比较难的任务了。 Simple Transformers就是这么想的,在这里就是要做到这一点!

    所有源代码都可以在Github Repo上找到。

    安装

    1. 这里安装Anaconda或Miniconda Package Manager
    2. 创建一个新的虚拟环境并安装所需的软件包。
    conda create -n transformers python pandas tqdm
    conda activate transformers

    如果使用cuda:

    conda install pytorch cudatoolkit=10.0 -c pytorch

    否则:

    conda install pytorch cpuonly -c pytorch
    conda install -c anaconda scipy
    conda install -c anaconda scikit-learn
    pip install transformers
    pip install tensorboardx

    安装simpletransformers。

    用法

    让我们看看如何对AGNews数据集执行多类分类。

    下载并提取数据

    1. 从Fast.ai下载数据集。(国内用户需要FQ下载)
    2. 提取train.csv和test.csv并将它们放在目录data /中。

    准备数据进行培训

    import pandas as pd
    
    train_df = pd.read_csv('data/train.csv', header=None)
    train_df['text'] = train_df.iloc[:, 1] + " " + train_df.iloc[:, 2]
    train_df = train_df.drop(train_df.columns[[1, 2]], axis=1)
    train_df.columns = ['label', 'text']
    train_df = train_df[['text', 'label']]
    train_df['text'] = train_df['text'].apply(lambda x: x.replace('\', ' '))
    
    eval_df = pd.read_csv('data/test.csv', header=None)
    eval_df['text'] = eval_df.iloc[:, 1] + " " + eval_df.iloc[:, 2]
    eval_df = eval_df.drop(eval_df.columns[[1, 2]], axis=1)
    eval_df.columns = ['label', 'text']
    eval_df = eval_df[['text', 'label']]
    eval_df['text'] = eval_df['text'].apply(lambda x: x.replace('\', ' '))
    eval_df['label'] = eval_df['label'].apply(lambda x:x-1)


    Simple Transformers要求数据必须包含在至少两列的Pandas DataFrames中。 只需为列的文本和标签命名,SimpleTransformers就会处理数据。 或者可以遵循以下约定。
    第一列包含文本,类型为str。
    第二列包含标签,类型为int。
    对于多类分类,标签应该是从0开始的整数。如果数据具有其他标签,则可以使用python dict保留从原始标签到整数标签的映射。

    使用模型:

    from simpletransformers.model import TransformerModel
    
    # Create a TransformerModel
    model = TransformerModel('roberta', 'roberta-base', num_labels=4)

    这将创建一个TransformerModel,用于训练,评估和预测。 第一个参数是model_type,第二个参数是model_name,第三个参数是数据中的标签数。

    model_type可以是['bert','xlnet','xlm','roberta','distilbert']之一。

    有关可用于model_name的预训练模型的完整列表,请参阅“当前预训练模型”。

    要加载以前保存的模型而不是默认模型的模型,可以将model_name更改为包含已保存模型的目录的路径。

    model = TransformerModel('xlnet', 'path_to_model/', num_labels=4)

    TransformerModel具有dict args,其中包含许多属性,这些属性可提供对超参数的控制。 有关每个属性的详细说明, 默认值如下所示。

    self.args = {
        'output_dir': 'outputs/',
        'cache_dir': 'cache_dir',
    
        'fp16': True,
        'fp16_opt_level': 'O1',
        'max_seq_length': 128,
        'train_batch_size': 8,
        'gradient_accumulation_steps': 1,
        'eval_batch_size': 8,
        'num_train_epochs': 1,
        'weight_decay': 0,
        'learning_rate': 4e-5,
        'adam_epsilon': 1e-8,
        'warmup_ratio': 0.06,
        'warmup_steps': 0,
        'max_grad_norm': 1.0,
    
        'logging_steps': 50,
        'save_steps': 2000,
    
        'overwrite_output_dir': False,
        'reprocess_input_data': False,
        'process_count': cpu_count() - 2 if cpu_count() > 2 else 1,
    }

    在创建TransformerModel或调用其train_model方法时,只要简单地传递包含要更新的键值对的字典,就可以修改这些属性中的任何一个。 下面给出一个例子。

    # Create a TransformerModel with modified attributes
    model = TransformerModel('roberta', 'roberta-base', 
    num_labels=4, args={'learning_rate':1e-5, 'num_train_epochs': 2, 'reprocess_input_data': True, 'overwrite_output_dir': True})

    开始训练:

    # Train the model
    model.train_model(train_df)

    train_model方法将在第n个步骤(其中n为self.args ['save_steps'])的第n个步骤创建模型的检查点(保存)。 训练完成后,最终模型将保存到self.args ['output_dir']。

    验证:

    result, model_outputs, wrong_predictions = model.eval_model(eval_df)

    要评估模型,只需调用eval_model。 此方法具有三个返回值。

    结果:dict形式的评估结果。 默认情况下,仅对多类分类计算马修斯相关系数(MCC)。

    model_outputs:评估数据集中每个项目的模型输出列表。 如果需要每个类别的概率而不是单个预测,这很有用。 通过对输出应用softmax函数来计算预测。

    错误的预测:每个错误预测的InputFeature列表。 可以从InputFeature.text_a属性获取文本。 (可以在存储库的utils.py文件中找到InputFeature类)

    还可以包括要在评估中使用的其他指标。 只需将指标函数作为关键字参数传递给eval_model方法。 指标功能应包含两个参数,第一个是真实标签,第二个是预测。 这遵循sklearn标准。

    对于任何需要附加参数的度量标准函数(在sklearn中为f1_score),我们可以在添加了附加参数的情况下将其包装在自己的函数中,然后将函数传递给eval_model。

    from sklearn.metrics import f1_score, accuracy_score
    
    
    def f1_multiclass(labels, preds):
        return f1_score(labels, preds, average='micro')
        
    result, model_outputs, wrong_predictions = model.eval_model(eval_df, f1=f1_multiclass, acc=accuracy_score)
    

    作为参考,我使用这些超参数获得的结果如下:

    {'mcc': 0.937104098029913, 'f1': 0.9527631578947369, 'acc': 0.9527631578947369}

    这个结果是我没有做任务超参的调整。。。。

    预测/测试

    在实际应用中,我们通常不知道什么是真正的标签。 要对任意示例执行预测,可以使用predict方法。 此方法与eval_model方法非常相似,不同之处在于,该方法采用简单的文本列表并返回预测列表和模型输出列表。

    predictions, raw_outputs = model.predict(['Some arbitary sentence'])

    结论

    在许多实际应用中,多类分类是常见的NLP任务。 Simple Transformers是将Transformers的功能应用于现实世界任务的一种轻松方法,建议大家开始尝试。

  • 相关阅读:
    [转]easyui data-options的使用
    HTML5新事物
    jQuery checkbox相关
    mybatis insert前获取要插入的值
    mybatis获得刚刚插入的自增的值
    MySQL 获得当前日期时间(以及时间的转换)
    Linux dirname $0 source if
    CCS
    Linux compress & uncompress
    Programming In Scala Reading Note 8
  • 原文地址:https://www.cnblogs.com/zhangxianrong/p/14773086.html
Copyright © 2011-2022 走看看