nlp-with-transformers系列-02-从头构建文本分类器

文本分类

文本分类是 NLP 中最常见的任务之一, 它可用于广泛的应用或者开发成程序,例如将用户反馈文本标记为某种类别,或者根据客户文本语言自动归类。另外向我们平时见到的邮件垃圾过滤器也是文本分类最熟悉的应用场景之一。

另一种常见的文本分类类型是情感分析,它旨在识别给定文本的极性。 例如,像特斯拉这样的公司可能会分析类似下图中的 Twitter 帖子,以确定人们是否喜欢它的新车天窗。

假设你是一名数据科学算法工程师,现在需要构建一个系统来自动识别人们在 Twitter 上表达的关于你公司产品的情绪极性,例如“愤怒”或“快乐”。在本章中,我们将使用 DistilBERT 模型(BERT 变体)来解决这个任务。PS:[V. Sanh et al., “DistilBERT, a Distilled Version of BERT: Smaller, Faster, Cheaper and Lighter”, (2019).]

这个模型的主要优点是它实现了与 BERT 相当的性能,同时占用内存更小、训练与推理更高效。这使我们能够在几分钟内训练一个分类器,如果你想训练一个更大的 BERT 模型,你可以简单地更改预训练模型的权重, checkpoint 对应于加载到给定Transformer模型中的权重集合。

这也将是我们第一次接触 Hugging Face 生态系统中的三个核心库:Datasets,Tokenizers和Transformers。如下图中所示,这些库将使我们能够快速从原始文本转换为可用于推断新推文的微调模型。因此,本着 Optimus Prime(擎天柱,《变形金刚》) 的精神,让我们深入其中,“改造并启动!”

Dataset

为了构建我们的推文情感分类器,我们将使用一篇论文中的一个非常高质量的数据集,该论文探讨了情绪如何在英语 Twitter 消息中表示。

PS:[E. Saravia 等人,“CARER: Contextualized Affect Representations for Emotion Recognition”,2018 年自然语言处理经验方法会议论文集(2018 年 10 月至 11 月):3687-3697,dx.doi.org/10.18653 /v1/D18-1404.] 。

与大多数仅涉及“正面”和“负面”极性的情绪分析数据集不同,该数据集包含六种基本情绪:愤怒、厌恶、恐惧、喜悦、悲伤和惊讶(anger, disgust, fear, joy, sadness, and surprise)。 给定一条推文,我们的任务将是训练一个可以将其分类为其中一种情绪的模型。

初识 Hugging Face Datasets

我们将使用datasets从 Hugging Face Hub 下载数据。 我们可以使用 list_datasets() 函数来查看 Hub 上有哪些数据集:

from datasets import list_datasets

all_datasets = list_datasets()
print(f"There are {len(all_datasets)} datasets currently available on the Hub")
print(f"The first 10 are: {all_datasets[:10]}")
复制代码
There are 3480 datasets currently available on the Hub
The first 10 are: ['acronym_identification', 'ade_corpus_v2', 'adversarial_qa',
'aeslc', 'afrikaans_ner_corpus', 'ag_news', 'ai2_arc', 'air_dialogue',
'ajgt_twitter_ar', 'allegro_reviews']
复制代码

我们看到每个数据集都有一个名称,所以让我们使用 load_dataset() 函数加载情绪emotion数据集:

# 查看我们本机电脑是否可以连接数据集地址,出于考虑,你能想到办法的
import requests                                                                                                                                                                                                         
requests.head("https://www.dropbox.com/s/1pzkadrvffbqw6o/train.txt?dl=1")
复制代码
<Response [301]>
复制代码
from datasets import load_dataset

emotions = load_dataset("emotion")
复制代码
  0%|          | 0/3 [00:00<?, ?it/s]
复制代码

If we look inside our emotions object:

emotions
复制代码
DatasetDict({
    train: Dataset({
        features: ['text', 'label'],
        num_rows: 16000
    })
    validation: Dataset({
        features: ['text', 'label'],
        num_rows: 2000
    })
    test: Dataset({
        features: ['text', 'label'],
        num_rows: 2000
    })
})
复制代码

我们看到它类似于 Python 字典,每个键值对应一个不同的数据集划分,我们可以按照字典查询的方式访问具体数据集,比如下面是获取训练集:

train_ds = emotions["train"]
train_ds
复制代码
Dataset({
    features: ['text', 'label'],
    num_rows: 16000
})
复制代码

它返回 Dataset 类的实例。 Dataset 对象是 Datasets 中的核心数据结构之一,我们将在本书的整个过程中都会使用它并且你会逐步掌握它许多特性。 对于初学者来说,它的作用就像一个普通的 Python 数组或列表,所以我们可以查看它的长度:

len(train_ds)
复制代码
16000
复制代码

或通过索引访问某个样本:

train_ds[0] # 训练集的的第一条数据
复制代码
{'text': 'i didnt feel humiliated', 'label': 0}
复制代码

在这里,我们看到一条数据格式为字典,其中键对应于列名:

train_ds.column_names
复制代码
['text', 'label']
复制代码
type(train_ds['label'])
复制代码
list
复制代码

我们可以看到数据是推文文本和情感标签,这表明了数据集基于 Apache Arrow 构建(Arrow定义了一种比原生 Python 内存效率更高的类型化列格式)。 我们可以通过访问 Dataset 对象的 features 属性来查看背后使用的数据类型:

print(train_ds.features)
复制代码
{'text': Value(dtype='string', id=None), 'label': ClassLabel(num_classes=6,
names=['sadness', 'joy', 'love', 'anger', 'fear', 'surprise'], names_file=None,
id=None)}
复制代码

在这种情况下,text列的数据类型是字符串,而label列是一个特殊的 ClassLabel 对象,其中包含有关类名及其到整数的映射的信息。 我们还可以使用切片访问多行:

print(train_ds[:5])
复制代码
{'text': ['i didnt feel humiliated', 'i can go from feeling so hopeless to so
damned hopeful just from being around someone who cares and is awake', 'im
grabbing a minute to post i feel greedy wrong', 'i am ever feeling nostalgic
about the fireplace i will know that it is still on the property', 'i am feeling
grouchy'], 'label': [0, 0, 3, 2, 3]}
复制代码

请注意,在这种情况下,字典值现在是列表而不是单个元素。我们还可以按名称获取完整列:

print(train_ds["text"][:5])
复制代码
['i didnt feel humiliated', 'i can go from feeling so hopeless to so damned
hopeful just from being around someone who cares and is awake', 'im grabbing a
minute to post i feel greedy wrong', 'i am ever feeling nostalgic about the
fireplace i will know that it is still on the property', 'i am feeling grouchy']
复制代码

现在我们已经了解了如何使用 数Datasets加载和检查数据,让我们对推文的内容进行一些完整性检查。

自定义Huggingface Datatsets

假如我们的数据集没有在Huggingface Datasets怎么办?

我们将使用 Hugging Face Hub 下载本书中大多数示例的数据集。 但在许多情况下,我们会经常遇到自己在处理存储在笔记本电脑或公司远程服务器上的数据的情况。 Datasets 提供了几个加载脚本来处理本地和远程数据集。 dataset-loading 中显示了最常见数据格式的示例。

[[dataset-loading]]
.How to load datasets in various formats
[options="header"]
|======
| Data format | Loading script | Example
| CSV | `csv` | `load_dataset("csv", data_files="my_file.csv")` 
| Text | `text` | `load_dataset("text", data_files="my_file.txt")` 
| JSON | `json` | `load_dataset("json", data_files="my_file.jsonl")`
|======
复制代码

如我们所看见的,对于每种数据格式,我们只需将相关的加载脚本传递给 load_dataset() 函数,以及指定一个或多个文件的路径或 URL 的 data_files 参数。 例如,情感数据集的源文件实际上托管在 Dropbox 上,因此加载数据集的另一种方法是首先下载其中一个子集,比如我们可以把训练集下载到本地:

dataset_url = "https://www.dropbox.com/s/1pzkadrvffbqw6o/train.txt" # 没有wget命令,这里可以手动下载
!wget {dataset_url}
复制代码
--2022-03-14 11:46:13--  https://www.dropbox.com/s/1pzkadrvffbqw6o/train.txt
Connecting to 127.0.0.1:7890... connected.
ERROR: cannot verify www.dropbox.com's certificate, issued by `/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert SHA2 High Assurance Server CA':
  Unable to locally verify the issuer's authority.
To connect to www.dropbox.com insecurely, use `--no-check-certificate'.
Unable to establish SSL connection.
复制代码
!head -n 1 train.txt
复制代码
'head' 不是内部或外部命令,也不是可运行的程序
或批处理文件。
复制代码

我们可以看到这里没有列标题,每条推文和情感都用分号分隔。 尽管如此,这与 CSV 文件非常相似,因此我们可以通过使用 csv 脚本并将 data_files 参数指向 train.txt 文件来在本地加载数据集:

#hide_output
emotions_local = load_dataset("csv", data_files="data/train.txt", sep=";", 
                              names=["text", "label"])
复制代码
  0%|          | 0/1 [00:00<?, ?it/s]
复制代码

在这里,我们还指定了分隔符的类型和列的名称。更简单的方法是将 data_files 参数指向 URL 本身

#hide_output
dataset_url = "https://www.dropbox.com/s/1pzkadrvffbqw6o/train.txt?dl=1"
emotions_remote = load_dataset("csv", data_files=dataset_url, sep=";", 
                               names=["text", "label"])
复制代码
  0%|          | 0/1 [00:00<?, ?it/s]
复制代码

它将自动为您下载和缓存数据集。 如您所见,load_dataset() 函数用途广泛。 我们建议查看 Datastesdocumentation以获得完整的概述

将Datasets对象转为DataFrame

尽管Datasets 提供了许多基础功能来对我们的数据进行切片和切块,但将 Dataset 对象转换为 Pandas DataFrame 通常很方便,因此我们可以访问高级 用于数据可视化的级别 API。 为了启用转换 Datasets 提供了一个 set_format() 方法,允许我们更改 Dataset 的输出格式。 请注意,这不会更改底层数据格式(这是一个箭头表),如果需要,您可以稍后切换到另一种格式:

import pandas as pd

emotions.set_format(type="pandas")
df = emotions["train"][:]
df.head()
复制代码

.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}
.dataframe tbody tr th {
vertical-align: top;
}

.dataframe thead th {
text-align: right;
}

text label
0 i didnt feel humiliated 0
1 i can go from feeling so hopeless to so damned… 0
2 im grabbing a minute to post i feel greedy wrong 3
3 i am ever feeling nostalgic about the fireplac… 2
4 i am feeling grouchy 3
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享