1 加载hf上没有的数据集

对于每种数据格式,只需要在load_dataset()函数中指定加载脚本的类型,以及指定一个或多个文件路径的data_files参数。

以下为加载在github上管理的数据集进行演示,首先下载数据集:

解压数据集:

安装datasets库:

加载数据集:

查看数据集:

也可以使用以下方式加载数据集:

如果数据集很有可能存储在某个远程服务器上,可以使用以下方式进行加载:

1
2
3
4
5
6
url = "https://github.com/crux82/squad-it/raw/master/"
data_files = {
"train": url + "SQuAD_it-train.json.gz",
"test": url + "SQuAD_it-test.json.gz",
}
squad_it_dataset = load_dataset("json", data_files=data_files, field="data")

2 对数据集进行分片和切块

首先加载要处理的数据集,将使用托管在UC Irvine Machine Learning Repository上的药物审查数据集,其中包含患者对各种药物的评论,以及正在治疗的病情和患者满意度的 10 星评级。

1
2
3
4
5
6
7
8
9
!wget "https://archive.ics.uci.edu/ml/machine-learning-databases/00462/drugsCom_raw.zip"
!unzip drugsCom_raw.zip

from datasets import load_dataset

data_files = {"train": "drugsComTrain_raw.tsv", "test": "drugsComTest_raw.tsv"}
# \t is the tab character in Python
drug_dataset = load_dataset("csv", data_files=data_files, delimiter="\t")

创建数据集的一个随机样本进行查看:

Unnamed:0列重命名为更易于解释的名称来稍微清理数据集。可以使用DatasetDict.rename_column()函数一次性重命名两个分片中的列:

删除condition中为None的行:

删除None条目后,可以将condition列转化为小写:

2.1 创建新列

目标删除少于30个单词的评论,首先统计每个评论的字数:

删除较少字数的评论:

添加batched参数会加速很多:

2.2 从Datasets到DataFrame

为了实现各种第三方库之间的转换,🤗 Datasets 提供了Dataset.set_format()函数。此功能仅更改数据集的输出格式,因此您可以轻松切换到另一种格式,而不会影响底层数据格式,即 Apache Arrow。格式设置已就地完成。

将数据集转换为Pandas:

1
drug_dataset.set_format("pandas")

之后可以使用任何Pandas功能:

完成 Pandas 分析后,可以使用Dataset.from_pandas()函数创建新的Dataset对象,如下所示:

2.3 创建验证集

Datasets 提供了一个Dataset.train_test_split()函数,该函数基于scikit-learn中的著名功能。用它来将训练集拆分为trainvalidationsplit(设置seed参数以实现可重复性):

如下表所示,🤗 Datasets 提供了三个主要功能来以不同格式保存数据集:

保存数据集后,可以使用load_from_disk()函数加载它,如下所示:


3 使用FAISS进行语义检索

3.1 加载和准备数据集

GitHub Issues 是一个数据集,由 GitHub 问题和与 Datasets存储库关联的拉取请求组成。它旨在用于教育目的,可用于语义搜索或多标签文本分类。

之后过滤pr以及没有comment的数据,如下:

数据集中有很多列,其中大部分我们不需要构建我们的搜索引擎。从搜索的角度来看,信息量最大的列是titlebodycomments,而html_url提供了一个返回源问题的链接。使用Dataset.remove_columns()函数来删除其余部分:

每条数据中的comments是一个列表,包含多个评论,这里将每个评论都分解出来,增加数据量。首先将数据转换为pandas格式:

之后使用explode方法进行拆分:

第一行代码 comments_df = df.explode("comments", ignore_index=True) 的作用是对 DataFrame (df) 中的某一列(这里是 "comments" 列)进行展开操作。

explode 是 Pandas 提供的一个方法,用于将列表类型的元素拆分成多行。假设 "comments" 列中的每个单元格存储的是一个列表(例如:["评论1", "评论2", "评论3"]),那么 explode 方法会将这个列表中的每个元素变成单独的一行,同时保留其他列的值不变。

假设原始 DataFrame (df) 的结构如下:

1
2
3
4
| index | post_id | comments                  |
|-------|---------|---------------------------|
| 0 | 1 | ["评论1", "评论2"] |
| 1 | 2 | ["评论3", "评论4", "评论5"] |

执行 explode("comments") 后,"comments" 列中的每个列表元素会被拆分成多行,结果如下:

1
2
3
4
5
6
7
| index | post_id | comments |
|-------|---------|----------|
| 0 | 1 | 评论1 |
| 1 | 1 | 评论2 |
| 2 | 2 | 评论3 |
| 3 | 2 | 评论4 |
| 4 | 2 | 评论5 |

如果设置了 ignore_index=True,索引会被重新排列为连续的整数:

1
2
3
4
5
6
7
| index | post_id | comments |
|-------|---------|----------|
| 0 | 1 | 评论1 |
| 1 | 1 | 评论2 |
| 2 | 2 | 评论3 |
| 3 | 2 | 评论4 |
| 4 | 2 | 评论5 |

3.2 创建文本嵌入

sentence-transformers的库,专门用于创建嵌入向量。文档中方便的模型概述表表明,multi-qa-mpnet-base-dot-v1检查点在语义搜索方面具有最佳性能。

首先加载模型:

将模型移动到GPU上:

将第一条数据送入模型进行嵌入:

以此类推,将所有数据都使用上述方式进行嵌入:

3.3 使用FAISS进行高效的相似性搜索

FAISS(Facebook AI Similarity Search 的缩写)是一个库,可提供高效的算法来快速搜索和聚类嵌入向量。FAISS 背后的基本思想是创建一种称为索引的特殊数据结构,它允许人们找到哪些嵌入与输入嵌入相似。

在 Datasets 中创建 FAISS 索引很简单,使用Dataset.add_faiss_index()函数并指定要索引的数据集的哪一列。

在构建faiss索引时,要求先安装faiss库,但是明明已经下载了,并且可以成功导入faiss库,但是在添加faiss索引时还是报错显示要安装。

最后找到一个解决方法:重启会话,然后先安装faiss库,之后再构建faiss索引即可成功:

现在,可以通过使用该Dataset.get_nearest_examples()函数执行最近邻查找来对此索引执行查询。首先嵌入一个问题来测试一下,如下所示:

Dataset.get_nearest_examples()函数返回一个分数元组,用于对查询和文档之间的重叠进行排名,以及一组相应的样本(此处为 5 个最佳匹配项)。

第一个匹配结果:

1
2
3
4
5
6
COMMENT: Requiring online connection is a deal breaker in some cases unfortunately so it'd be great if offline mode is added similar to how `transformers` loads models offline fine.

@mandubian's second bullet point suggests that there's a workaround allowing you to use your offline (custom?) dataset with `datasets`. Could you please elaborate on how that should look like?
SCORE: 25.505016326904297
TITLE: Discussion using datasets in offline mode
URL: https://github.com/huggingface/datasets/issues/824

可以发现在上述结果中并没有给出如何在本地加载数据集,而是title字段匹配度较高。

后四个匹配结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
COMMENT: The local dataset builders (csv, text , json and pandas) are now part of the `datasets` package since #1726 :)
You can now use them offline

datasets = load_dataset('text', data_files=data_files)

We'll do a new release soon
SCORE: 24.555538177490234
TITLE: Discussion using datasets in offline mode
URL: https://github.com/huggingface/datasets/issues/824
==================================================

COMMENT: I opened a PR that allows to reload modules that have already been loaded once even if there's no internet.

Let me know if you know other ways that can make the offline mode experience better. I'd be happy to add them :)

I already note the "freeze" modules option, to prevent local modules updates. It would be a cool feature.

----------

> @mandubian's second bullet point suggests that there's a workaround allowing you to use your offline (custom?) dataset with `datasets`. Could you please elaborate on how that should look like?

Indeed `load_dataset` allows to load remote dataset script (squad, glue, etc.) but also you own local ones.
For example if you have a dataset script at `./my_dataset/my_dataset.py` then you can do

load_dataset("./my_dataset")

and the dataset script will generate your dataset once and for all.

----------

About I'm looking into having `csv`, `json`, `text`, `pandas` dataset builders already included in the `datasets` package, so that they are available offline by default, as opposed to the other datasets that require the script to be downloaded.
cf #1724
SCORE: 24.14898681640625
TITLE: Discussion using datasets in offline mode
URL: https://github.com/huggingface/datasets/issues/824
==================================================

COMMENT: > here is my way to load a dataset offline, but it **requires** an online machine
>
> 1. (online machine)
>
>
> import datasets
>
> data = datasets.load_dataset(...)
>
> data.save_to_disk(/YOUR/DATASET/DIR)
>
>
> 2. copy the dir from online to the offline machine
>
> 3. (offline machine)
>
>
> import datasets
>
> data = datasets.load_from_disk(/SAVED/DATA/DIR)
>
> HTH.

SCORE: 22.89400291442871
TITLE: Discussion using datasets in offline mode
URL: https://github.com/huggingface/datasets/issues/824
==================================================

COMMENT: here is my way to load a dataset offline, but it **requires** an online machine
1. (online machine)

import datasets
data = datasets.load_dataset(...)
data.save_to_disk(/YOUR/DATASET/DIR)

2. copy the dir from online to the offline machine

3. (offline machine)

import datasets
data = datasets.load_from_disk(/SAVED/DATA/DIR)

HTH.
SCORE: 22.40665626525879
TITLE: Discussion using datasets in offline mode
URL: https://github.com/huggingface/datasets/issues/824
==================================================

可以发现后面几个结果基本都给出了从本地加载数据集的代码,效果不错。