NLP冻手之路(2)——文本数据集的下载与各种操作(Datasets)

时间:2022-10-22 22:51:32

✅ NLP 研 0 选手的学习笔记



上一篇文章链接: NLP冻手之路(1)——中文/英文字典与分词操作(Tokenizer)


一、需要的环境

python 需要 3.6+,pytorch 需要 1.10+

● 本文使用的库基于 Hugging Face Transformer,官网链接:https://huggingface.co/docs/transformers/index 【一个很不错的开源网站,针对于 transformer 框架做了很多大集成,目前 github 72.3k ⭐️】

● 安装 Hugging Face Transformer 的库只需要在终端输入 pip install transformers【这是 pip 安装方法】;如果你用的是 conda,则输入 conda install -c huggingface transformers

● 本文除了要安装上述配置,还要安装名为 datasets 的数据集处理包,只需要在终端输入 pip install datasets【这是 pip 安装方法】;如果你用的是 conda,则输入 conda install -c huggingface -c conda-forge datasets



二、数据集的了解

● 这里我用了 pprint 函数来打印,它比 print 打印出来的内容更整洁。

import datasets
from pprint import pprint

my_datasets_list = datasets.list_datasets()
print("Number of datasets in the Datasets library: ", len(my_datasets_list))
pprint(my_datasets_list[:20], compact=True)  # 打印数据集列表中的前 20 个来看看

输出结果:
Number of datasets in the Datasets library:  12173 
['acronym_identification', 'ade_corpus_v2', 'adversarial_qa', 'aeslc',
 'afrikaans_ner_corpus', 'ag_news', 'ai2_arc', 'air_dialogue',
 'ajgt_twitter_ar', 'allegro_reviews', 'allocine', 'alt', 'amazon_polarity',
 'amazon_reviews_multi', 'amazon_us_reviews', 'ambig_qa', 'americas_nli', 'ami',
 'amttl', 'anli']

● 从结果可以看到,截止目前 2022年10月20日,目前数据库已有 12172 个数据集。

● 接着,我们来了解一下一个 中文情感分析的数据集,即 seamew/ChnSentiCorp注意,后面所有的实验都将基于这个数据集。一般这里面的数据集都有 description,但是这个没有,我大致说一下,就是这个数据集全是一段一段的文本,每一段文本都是用户针对于某件事、某个东西等的评价。

index = my_datasets_list.index('seamew/ChnSentiCorp')  # 获取该数据集在 my_datasets(其 type 为list) 的位置
info = datasets.list_datasets(with_details=True)[index]  # 通过设置 with_details 为 True 来获得数据集的详细信息
pprint(info)

输出:
DatasetInfo: {
	id: seamew/ChnSentiCorp
	sha: 5fad0d07523f9c5fc76b8babaca9ab6fdeb6af2d
	lastModified: 2021-06-22T08:58:53.000Z
	tags: []
	private: False
	author: seamew
	description: None
	citation: None
	cardData: None
	siblings: None
	gated: False
	downloads: 1512
	likes: 8
}


三、数据集的获取

● 数据集的获取有两种方法,第一种是直接调用 load_dataset 函数获取,第二种是从官网下载下来。

● 第一种方法可能需要一下 F墙 的 VPN,需注意的是,这个 VPN 要打开到 “网卡模式”,而不只是 “网页模式”。因为 “网页模式” 只能去看看 Youtube 等外网网页,并不能使得 Python编辑器 访问到外网。

3.1 方法一:直接调用函数获取

● 我们通过设置 cache_dir 来将数据集下载到 ./my_data 中。

import datasets

my_dataset_all = datasets.load_dataset(path='seamew/ChnSentiCorp', cache_dir='./my_data')  # 获取整个数据集
my_dataset_train = my_dataset_all['train']
my_dataset_validation = my_dataset_all['validation']
my_dataset_test = my_dataset_all['test']

print("my_dataset_all:", my_dataset_all)
print("my_dataset_train:", my_dataset_train)
print("my_dataset_validation[0]:", my_dataset_validation[0])  # 打印第一个
print("my_dataset_test[:3]:", my_dataset_test[:3])  # 打印前三个

● 运行结果如下,其中 label1 代表对应的那段评论是 积极 的,反之,若 label0 则代表对应的那段评论是 消极 的。其中训练集有 9600 个样例,验证集和测试集分别有 1200 个样例。
NLP冻手之路(2)——文本数据集的下载与各种操作(Datasets)

● 如果通过这种方法下载的数据集,即可通过 save_to_disk 函数来保存到本地,下一次加载数据集时,就不需要再重复到网上下载,直接加载本地的即可。加载函数详见 “2.2 方法二:官网下载获取” 的 load_from_disk

my_dataset_all.save_to_disk(dataset_dict_path='./save_data')  

3.2 方法二:官网下载获取

● 如果方法一行不通,就用这个方法。首先进入该数据集的网页:https://huggingface.co/datasets/seamew/ChnSentiCorp

NLP冻手之路(2)——文本数据集的下载与各种操作(Datasets)
● 然后,依照上图打开对话框,接着使用 git clone https://huggingface.co/datasets/seamew/ChnSentiCorp 来将数据集下载到本地,如下图所示。
NLP冻手之路(2)——文本数据集的下载与各种操作(Datasets)
● 我们然后还有做一系列文件夹划分操作,以便代码调用:1. 首先,我们在 ChnSentiCorp 文件夹里新建一个 dataset.json 文件,其中写入 { "splits": ["train", "validation", "test"] } 即可。2. 然后,我们需要编辑三个文件夹,分别命名为 trainvalidationtest。然后需要将 dataset_info.json 复制三份,分别放到这三个文件夹中,同时,对应的 *.arrow 数据文件也放入其中。3. 最后,在这三个文件夹内新建一个 state.json 文件,其内容如下(以 train 为例,注意,对于不同的文件夹(train、validation和test),其 filename_split 要做相应的改写):

{
    "_data_files": [
      {
        "filename": "chn_senti_corp-train.arrow"
      }
    ],
    "_fingerprint": "24c4fd9824d8b978",
    "_format_columns": null,
    "_format_kwargs": {},
    "_format_type": null,
    "_indexes": {},
    "_output_all_columns": false,
    "_split": "train"
}

● 最后,ChnSentiCorp 文件夹里面的结构如下:
NLP冻手之路(2)——文本数据集的下载与各种操作(Datasets)
● 我们通过 load_from_disk 函数来将本地保存的数据集加载到内存:

my_dataset_all_git = datasets.load_from_disk('./git_example/ChnSentiCorp')
print(my_dataset_all_git)

输出:
DatasetDict({
    train: Dataset({
        features: ['text', 'label'],
        num_rows: 9600
    })
    validation: Dataset({
        features: ['text', 'label'],
        num_rows: 1200
    })
    test: Dataset({
        features: ['text', 'label'],
        num_rows: 1200
    })
})


四、数据集的操作

4.1 排序与打乱

● 在实际训练的时候,我们常用到 排序(sort) 与 打乱(shuffle),具体操作如下:

my_dataset = datasets.load_from_disk('./git_example/ChnSentiCorp')['train']  # 获取 train 集
print(my_dataset)  # 简单打印 train集 的信息
pprint(my_dataset[:10])  # 未排序的 label 是乱序的

my_dataset_sort = my_dataset.sort('label')  # 排序之后 label 便有序了
print(my_dataset_sort['label'][:10])  # 前十个 label 的值
print(my_dataset_sort['label'][-10:])  # 最后十个 label 的值

shuffled_dataset = my_dataset.shuffle(seed=42)  # 打乱顺序 seed 的值可调
print(shuffled_dataset['label'][:10])

● 运行结果:
NLP冻手之路(2)——文本数据集的下载与各种操作(Datasets)


4.2 选择和过滤

● 再介绍一下常用的选择函数 select 和 过滤函数 filter

my_dataset = datasets.load_from_disk('./git_example/ChnSentiCorp')['train']  # 获取 train 集
x = my_dataset.select([1, 0, 10, 20, 30, 40, 50])  # 选择下标为 1、0、10、...、50 的数据
pprint(x)

def f(data):
    return data['text'].startswith('很差')  # 返回一个 true 或者 false

# 这里的 filter 函数需要用一个 lambda 函数
start_with_ar = my_dataset.filter(f)
print(len(start_with_ar), start_with_ar['text'])  # 打印以 '很差' 开头的句子的数量和内容

输出:
Dataset({
    features: ['label', 'text'],
    num_rows: 7
})
2 ['很差,相当差,搞得我们的外国客人都发大火了!!!服务不符合四星级的酒店标准!', '很差劲的地方。是人都不要住。设施什么都不好还贵。真是晦气']

4.3 切分和分桶

● 如果我们还想对 train集 进行划分,可以用 train_test_split 函数,另外还有一个好用的均分函数 shard

my_dataset = datasets.load_from_disk('./git_example/ChnSentiCorp')['train']  # 获取 train 集
x = my_dataset.train_test_split(test_size=0.1)  # 按照 9:1 的比例对 train集 再划分为新的 'train集' 和 'test集'
print("原始 train集: ", my_dataset)
print("切分过后的 train集: ", x)

t = my_dataset.shard(num_shards=4, index=0)  # 把数据均匀分配到 4 个桶中. 然后取下标为 0 的桶里的数据
print("均匀(4)分桶过后且取下标为 0 的桶里的数据: ", t)

● 运行结果:
NLP冻手之路(2)——文本数据集的下载与各种操作(Datasets)


4.4 列的新增、删除和重命名

● 如果我们想对数据集里面的每一个样例都多加一个标签,即列的新增,那就要用到 add_column,具体方法如下。另外还有常用的,列的删除 remove_columns 和列的重命名 rename_column

my_dataset = datasets.load_from_disk('./git_example/ChnSentiCorp')['train']  # 获取 train 集
new_column = ["null"] * len(my_dataset)
my_dataset_add = my_dataset.add_column("info", new_column)
print("原始 train集: ", my_dataset)
print("新增了一列的 train集: ", my_dataset_add)
print("原始 train集 的一个例子: ", my_dataset[1])
print("新增了一列的 train集 的一个例子: ", my_dataset_add[1])

my_dataset_newName = my_dataset_add.rename_column('info', 'likes')
print("重命名后的 train集: ", my_dataset_newName)

my_dataset_remove = my_dataset_newName.remove_columns(['likes'])
print("删除了一列的 train集: ", my_dataset_remove)

● 运行结果:
NLP冻手之路(2)——文本数据集的下载与各种操作(Datasets)


4.5 map 函数

● 这个 map 函数是比较重要的,说白了,可以用这个函数对数据集里面的内容进行了人为的修改。

my_dataset = datasets.load_from_disk('./git_example/ChnSentiCorp')['train']  # 获取 train 集
def m(data):
    data['text'] = 'My sentence: ' + data['text']
    return data

my_datatset_map = my_dataset.map(m)  # 也是通过一个 lambda 函数来处理
pprint(my_datatset_map['text'][:5], width=300)  # 打印前五个
print("原始 train集: ", my_dataset)
print("经过 map 后的 train集: ", my_datatset_map)

● 运行结果:

NLP冻手之路(2)——文本数据集的下载与各种操作(Datasets)


4.6 保存与加载

● 其实在 “3.1 方法一:直接调用函数获取” 中已经讲了一个保存的函数 save_to_disk,下面运行结果图中,文件夹里的 save_data 即为函数 my_dataset.save_to_disk(dataset_dict_path='./save_data') 运行后的结果。另外,如果保存为 .csv.json 格式的文件,就要用到 to_csvto_json 函数,加载的话,除了本地加载的 load_from_disk 函数,还有一个就是 load_dataset

my_dataset = datasets.load_from_disk('./git_example/ChnSentiCorp')['train']  # 获取 train 集
print("原始的数据:", my_dataset[1:3], end='\n')  # 打印 2 个例子看看
my_dataset.to_csv(path_or_buf='./save_csv_data.csv')  # 导出为 csv 格式
csv_dataset = datasets.load_dataset(path='csv', data_files='./save_csv_data.csv', split='train')  # 加载 csv 格式数据
print("csv 格式的数据:", csv_dataset[1:3], end='\n')  # 打印 2 个例子看看

csv_dataset.to_json(path_or_buf='./save_json_data.json')  # 导出为 json 格式
json_dataset = datasets.load_dataset(path='json', data_files='./save_json_data.json', split='train')  # 加载 json 格式数据
print("json 格式的数据:", json_dataset[1:3], end='\n')  # 打印 2 个例子看看

● 运行结果:

NLP冻手之路(2)——文本数据集的下载与各种操作(Datasets)



五、小结

● 关于数据集的操作不难,但是很重要,大致看一遍,过一遍即可。


六、补充说明

上一篇文章链接: NLP冻手之路(1)——中文/英文字典与分词操作(Tokenizer)

● 若有写得不对的地方,或有疑问,欢迎评论交流。

● 参考视频:HuggingFace简明教程,BERT中文模型实战示例.NLP预训练模型,Transformers类库,datasets类库快速入门.

● 参考资料:使用Hugging Face的数据集库


⭐️ ⭐️