tasksource 0.0.41__tar.gz → 0.0.43__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {tasksource-0.0.41 → tasksource-0.0.43}/PKG-INFO +17 -14
- {tasksource-0.0.41 → tasksource-0.0.43}/README.md +16 -13
- tasksource-0.0.43/src/tasksource/.ipynb_checkpoints/preprocess-checkpoint.py +267 -0
- tasksource-0.0.43/src/tasksource/.ipynb_checkpoints/recast-checkpoint.py +113 -0
- tasksource-0.0.43/src/tasksource/.ipynb_checkpoints/tasks-checkpoint.py +1211 -0
- {tasksource-0.0.41 → tasksource-0.0.43}/src/tasksource/preprocess.py +1 -1
- {tasksource-0.0.41 → tasksource-0.0.43}/src/tasksource/recast.py +3 -2
- {tasksource-0.0.41 → tasksource-0.0.43}/src/tasksource/tasks.py +143 -38
- {tasksource-0.0.41 → tasksource-0.0.43}/src/tasksource.egg-info/PKG-INFO +17 -14
- {tasksource-0.0.41 → tasksource-0.0.43}/src/tasksource.egg-info/SOURCES.txt +3 -0
- {tasksource-0.0.41 → tasksource-0.0.43}/tasks.md +574 -549
- {tasksource-0.0.41 → tasksource-0.0.43}/.github/scripts/release.py +0 -0
- {tasksource-0.0.41 → tasksource-0.0.43}/.github/workflows/python-publish.yml +0 -0
- {tasksource-0.0.41 → tasksource-0.0.43}/.github/workflows/release.yml +0 -0
- {tasksource-0.0.41 → tasksource-0.0.43}/.gitignore +0 -0
- {tasksource-0.0.41 → tasksource-0.0.43}/CITATION.cff +0 -0
- {tasksource-0.0.41 → tasksource-0.0.43}/LICENSE +0 -0
- {tasksource-0.0.41 → tasksource-0.0.43}/mtasks.md +0 -0
- {tasksource-0.0.41 → tasksource-0.0.43}/pyproject.toml +0 -0
- {tasksource-0.0.41 → tasksource-0.0.43}/setup.cfg +0 -0
- {tasksource-0.0.41 → tasksource-0.0.43}/src/tasksource/__init__.py +0 -0
- {tasksource-0.0.41 → tasksource-0.0.43}/src/tasksource/access.py +0 -0
- {tasksource-0.0.41 → tasksource-0.0.43}/src/tasksource/metadata/__init__.py +0 -0
- {tasksource-0.0.41 → tasksource-0.0.43}/src/tasksource/metadata/bigbench_groups.py +0 -0
- {tasksource-0.0.41 → tasksource-0.0.43}/src/tasksource/metadata/blimp_groups.py +0 -0
- {tasksource-0.0.41 → tasksource-0.0.43}/src/tasksource/metadata/original.txt +0 -0
- {tasksource-0.0.41 → tasksource-0.0.43}/src/tasksource/metadata/popularity.py +0 -0
- {tasksource-0.0.41 → tasksource-0.0.43}/src/tasksource/mtasks.py +0 -0
- {tasksource-0.0.41 → tasksource-0.0.43}/src/tasksource.egg-info/dependency_links.txt +0 -0
- {tasksource-0.0.41 → tasksource-0.0.43}/src/tasksource.egg-info/requires.txt +0 -0
- {tasksource-0.0.41 → tasksource-0.0.43}/src/tasksource.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: tasksource
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.43
|
|
4
4
|
Summary: Preprocessings to prepare datasets for a task
|
|
5
5
|
Home-page: https://github.com/sileod/tasksource/
|
|
6
6
|
Classifier: Programming Language :: Python :: 3
|
|
@@ -19,7 +19,7 @@ Requires-Dist: numpy
|
|
|
19
19
|
Requires-Dist: scipy
|
|
20
20
|
Requires-Dist: sorcery
|
|
21
21
|
|
|
22
|
-
## tasksource 
|
|
22
|
+
## tasksource  600+ curated datasets and preprocessings for instant and interchangeable use
|
|
23
23
|
|
|
24
24
|
Huggingface Datasets is an excellent library, but it lacks standardization, and datasets often require preprocessing work to be used interchangeably.
|
|
25
25
|
`tasksource` streamlines interchangeable datasets usage to scale evaluation or multi-task learning.
|
|
@@ -36,7 +36,7 @@ for id in df[df.task_type=="MultipleChoice"].id:
|
|
|
36
36
|
dataset = load_task(id) # all yielded datasets can be used interchangeably
|
|
37
37
|
```
|
|
38
38
|
|
|
39
|
-
Browse the 500+ curated tasks in tasks.md (200+ MultipleChoice tasks, 200+ Classification tasks), and feel free to request a new task. Datasets are downloaded to
|
|
39
|
+
Browse the 500+ curated tasks in tasks.md (200+ MultipleChoice tasks, 200+ Classification tasks), and feel free to request a new task. Datasets are downloaded to `$HF_DATASETS_CACHE` (like any Hugging Face dataset), so ensure you have more than 100GB of space available.
|
|
40
40
|
|
|
41
41
|
You can now also use:
|
|
42
42
|
```python
|
|
@@ -47,9 +47,7 @@ load_dataset("tasksource/data", "glue/rte",max_rows=30_000)
|
|
|
47
47
|
|
|
48
48
|
Text encoder pretrained on tasksource reached state-of-the-art results: [🤗/deberta-v3-base-tasksource-nli](https://hf.co/sileod/deberta-v3-base-tasksource-nli)
|
|
49
49
|
|
|
50
|
-
Tasksource pretraining is notably helpful for RLHF reward modeling or any kind of classification, including zero-shot. You can also find a large
|
|
51
|
-
|
|
52
|
-
[u/conceptofmind](https://github.com/conceptofmind) also trained Llama on tasksource: [🤗/conceptofmind/Tasksource-Open-Llama-13b](https://hf.co/conceptofmind/Tasksource-Open-Llama-13b)
|
|
50
|
+
Tasksource pretraining is notably helpful for RLHF reward modeling or any kind of classification, including zero-shot. You can also find a large and a multilingual version.
|
|
53
51
|
|
|
54
52
|
### tasksource-instruct
|
|
55
53
|
|
|
@@ -78,17 +76,22 @@ winogrande = MultipleChoice('sentence',['option1','option2'],'answer',
|
|
|
78
76
|
tasks = [winogrande.load(), codah.load()]) # Aligned datasets (same columns) can be used interchangably
|
|
79
77
|
```
|
|
80
78
|
|
|
81
|
-
###
|
|
82
|
-
For help integrating tasksource into your experiments, please contact [damien.sileo@inria.fr](mailto:damien.sileo@inria.fr).
|
|
79
|
+
### Citation and contact
|
|
83
80
|
|
|
84
81
|
For more details, refer to this [article:](https://arxiv.org/abs/2301.05948)
|
|
85
82
|
```bib
|
|
86
|
-
@
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
83
|
+
@inproceedings{sileo-2024-tasksource,
|
|
84
|
+
title = "tasksource: A Large Collection of {NLP} tasks with a Structured Dataset Preprocessing Framework",
|
|
85
|
+
author = "Sileo, Damien",
|
|
86
|
+
booktitle = "Proceedings of the 2024 Joint International Conference on Computational Linguistics, Language Resources and Evaluation (LREC-COLING 2024)",
|
|
87
|
+
month = may,
|
|
88
|
+
year = "2024",
|
|
89
|
+
address = "Torino, Italia",
|
|
90
|
+
publisher = "ELRA and ICCL",
|
|
91
|
+
url = "https://aclanthology.org/2024.lrec-main.1361",
|
|
92
|
+
pages = "15655--15684",
|
|
92
93
|
}
|
|
93
94
|
```
|
|
95
|
+
For help integrating tasksource into your experiments, please contact [damien.sileo@inria.fr](mailto:damien.sileo@inria.fr).
|
|
96
|
+
|
|
94
97
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
## tasksource 
|
|
1
|
+
## tasksource  600+ curated datasets and preprocessings for instant and interchangeable use
|
|
2
2
|
|
|
3
3
|
Huggingface Datasets is an excellent library, but it lacks standardization, and datasets often require preprocessing work to be used interchangeably.
|
|
4
4
|
`tasksource` streamlines interchangeable datasets usage to scale evaluation or multi-task learning.
|
|
@@ -15,7 +15,7 @@ for id in df[df.task_type=="MultipleChoice"].id:
|
|
|
15
15
|
dataset = load_task(id) # all yielded datasets can be used interchangeably
|
|
16
16
|
```
|
|
17
17
|
|
|
18
|
-
Browse the 500+ curated tasks in tasks.md (200+ MultipleChoice tasks, 200+ Classification tasks), and feel free to request a new task. Datasets are downloaded to
|
|
18
|
+
Browse the 500+ curated tasks in tasks.md (200+ MultipleChoice tasks, 200+ Classification tasks), and feel free to request a new task. Datasets are downloaded to `$HF_DATASETS_CACHE` (like any Hugging Face dataset), so ensure you have more than 100GB of space available.
|
|
19
19
|
|
|
20
20
|
You can now also use:
|
|
21
21
|
```python
|
|
@@ -26,9 +26,7 @@ load_dataset("tasksource/data", "glue/rte",max_rows=30_000)
|
|
|
26
26
|
|
|
27
27
|
Text encoder pretrained on tasksource reached state-of-the-art results: [🤗/deberta-v3-base-tasksource-nli](https://hf.co/sileod/deberta-v3-base-tasksource-nli)
|
|
28
28
|
|
|
29
|
-
Tasksource pretraining is notably helpful for RLHF reward modeling or any kind of classification, including zero-shot. You can also find a large
|
|
30
|
-
|
|
31
|
-
[u/conceptofmind](https://github.com/conceptofmind) also trained Llama on tasksource: [🤗/conceptofmind/Tasksource-Open-Llama-13b](https://hf.co/conceptofmind/Tasksource-Open-Llama-13b)
|
|
29
|
+
Tasksource pretraining is notably helpful for RLHF reward modeling or any kind of classification, including zero-shot. You can also find a large and a multilingual version.
|
|
32
30
|
|
|
33
31
|
### tasksource-instruct
|
|
34
32
|
|
|
@@ -57,17 +55,22 @@ winogrande = MultipleChoice('sentence',['option1','option2'],'answer',
|
|
|
57
55
|
tasks = [winogrande.load(), codah.load()]) # Aligned datasets (same columns) can be used interchangably
|
|
58
56
|
```
|
|
59
57
|
|
|
60
|
-
###
|
|
61
|
-
For help integrating tasksource into your experiments, please contact [damien.sileo@inria.fr](mailto:damien.sileo@inria.fr).
|
|
58
|
+
### Citation and contact
|
|
62
59
|
|
|
63
60
|
For more details, refer to this [article:](https://arxiv.org/abs/2301.05948)
|
|
64
61
|
```bib
|
|
65
|
-
@
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
62
|
+
@inproceedings{sileo-2024-tasksource,
|
|
63
|
+
title = "tasksource: A Large Collection of {NLP} tasks with a Structured Dataset Preprocessing Framework",
|
|
64
|
+
author = "Sileo, Damien",
|
|
65
|
+
booktitle = "Proceedings of the 2024 Joint International Conference on Computational Linguistics, Language Resources and Evaluation (LREC-COLING 2024)",
|
|
66
|
+
month = may,
|
|
67
|
+
year = "2024",
|
|
68
|
+
address = "Torino, Italia",
|
|
69
|
+
publisher = "ELRA and ICCL",
|
|
70
|
+
url = "https://aclanthology.org/2024.lrec-main.1361",
|
|
71
|
+
pages = "15655--15684",
|
|
71
72
|
}
|
|
72
73
|
```
|
|
74
|
+
For help integrating tasksource into your experiments, please contact [damien.sileo@inria.fr](mailto:damien.sileo@inria.fr).
|
|
75
|
+
|
|
73
76
|
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
from collections.abc import Iterable
|
|
2
|
+
from dotwiz import DotWiz
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from typing import Union
|
|
5
|
+
import itertools
|
|
6
|
+
import funcy as fc
|
|
7
|
+
import exrex
|
|
8
|
+
import magicattr
|
|
9
|
+
import numpy as np
|
|
10
|
+
import copy
|
|
11
|
+
import datasets
|
|
12
|
+
import time
|
|
13
|
+
|
|
14
|
+
def get_column_names(dataset):
|
|
15
|
+
cn = dataset.column_names
|
|
16
|
+
if type(cn)==dict:
|
|
17
|
+
return set(fc.flatten(cn.values()))
|
|
18
|
+
else:
|
|
19
|
+
return set(cn)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def sample_dataset(dataset,n=10000, n_eval=1000,seed=0):
|
|
23
|
+
for k in dataset:
|
|
24
|
+
n_k=(n if k=='train' else n_eval)
|
|
25
|
+
if n_k and len(dataset[k])>n_k:
|
|
26
|
+
dataset[k]=dataset[k].train_test_split(train_size=n_k,seed=seed)['train']
|
|
27
|
+
return dataset
|
|
28
|
+
|
|
29
|
+
class Preprocessing(DotWiz):
|
|
30
|
+
default_splits = ('train','validation','test')
|
|
31
|
+
@staticmethod
|
|
32
|
+
def __map_to_target(x,fn=lambda x:None, target=None):
|
|
33
|
+
x[target]=fn(x)
|
|
34
|
+
return x
|
|
35
|
+
|
|
36
|
+
def load(self):
|
|
37
|
+
return self(datasets.load_dataset(self.dataset_name,self.config_name))
|
|
38
|
+
|
|
39
|
+
def __call__(self,dataset, max_rows=None, max_rows_eval=None,seed=0):
|
|
40
|
+
dataset = self.pre_process(dataset)
|
|
41
|
+
|
|
42
|
+
# manage splits
|
|
43
|
+
for k,v in zip(self.default_splits, self.splits):
|
|
44
|
+
if v and k!=v:
|
|
45
|
+
dataset[k]=dataset[v]
|
|
46
|
+
del dataset[v]
|
|
47
|
+
if k in dataset and not v: # obfuscated label
|
|
48
|
+
del dataset[k]
|
|
49
|
+
dataset = fix_splits(dataset)
|
|
50
|
+
|
|
51
|
+
for k in list(dataset.keys()):
|
|
52
|
+
if k not in self.default_splits:
|
|
53
|
+
del dataset[k]
|
|
54
|
+
dataset = sample_dataset(dataset, max_rows, max_rows_eval,seed=seed)
|
|
55
|
+
|
|
56
|
+
# field annotated with a string
|
|
57
|
+
substitutions = {v:k for k,v in self.to_dict().items()
|
|
58
|
+
if (k and k not in {'splits','dataset_name','config_name'}
|
|
59
|
+
and type(v)==str and k!=v)}
|
|
60
|
+
|
|
61
|
+
dataset=dataset.remove_columns([c for c in substitutions.values() if c in dataset['train'].features and c not in substitutions])
|
|
62
|
+
dataset=dataset.rename_columns(substitutions)
|
|
63
|
+
|
|
64
|
+
# field annotated with a function
|
|
65
|
+
for k in self.to_dict().keys():
|
|
66
|
+
v=getattr(self, k)
|
|
67
|
+
if callable(v) and k not in {"post_process","pre_process","load"}:
|
|
68
|
+
dataset=dataset.map(self.__map_to_target,
|
|
69
|
+
fn_kwargs={'fn':v,'target':k})
|
|
70
|
+
|
|
71
|
+
dataset=dataset.remove_columns(
|
|
72
|
+
get_column_names(dataset)-set(self.to_dict().keys()))
|
|
73
|
+
dataset = fix_labels(dataset)
|
|
74
|
+
dataset = fix_splits(dataset) # again: label mapping changed
|
|
75
|
+
dataset = self.post_process(dataset)
|
|
76
|
+
return dataset
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
@dataclass
|
|
80
|
+
class cat(Preprocessing):
|
|
81
|
+
fields:Union[str,list]=None
|
|
82
|
+
separator:str=' '
|
|
83
|
+
|
|
84
|
+
def __call__(self, example=None):
|
|
85
|
+
y=[np.char.array(example[f]) + sep
|
|
86
|
+
for f,sep in zip(self.fields[::-1],itertools.repeat(self.separator))]
|
|
87
|
+
y=list(sum(*y))
|
|
88
|
+
if len(y)==1:
|
|
89
|
+
y=y[0]
|
|
90
|
+
return y
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def pretty(f):
|
|
94
|
+
class pretty_f(DotWiz):
|
|
95
|
+
def __init__(self,*args):
|
|
96
|
+
self.__f_arg = f(*args)
|
|
97
|
+
for a in args:
|
|
98
|
+
setattr(self,'value',a)
|
|
99
|
+
|
|
100
|
+
def __call__(self, *args,**kwargs):
|
|
101
|
+
return self.__f_arg(*args,**kwargs)
|
|
102
|
+
|
|
103
|
+
def __repr__(self):
|
|
104
|
+
return f"{self.__f_arg.__qualname__ .split('.')[0]}({self.value})"
|
|
105
|
+
return pretty_f
|
|
106
|
+
|
|
107
|
+
class dotgetter:
|
|
108
|
+
def __init__(self, path=''):
|
|
109
|
+
self.path=path
|
|
110
|
+
|
|
111
|
+
def __bool__(self):
|
|
112
|
+
return bool(self.path)
|
|
113
|
+
|
|
114
|
+
def __getattr__(self, k):
|
|
115
|
+
return self.__class__(f'{self.path}.{k}'.lstrip('.'))
|
|
116
|
+
|
|
117
|
+
def __getitem__(self, i):
|
|
118
|
+
return self.__class__(f'{self.path}[{i}]')
|
|
119
|
+
|
|
120
|
+
def __call__(self, example=None):
|
|
121
|
+
return magicattr.get(DotWiz(example), self.path)
|
|
122
|
+
|
|
123
|
+
def __hash__(self):
|
|
124
|
+
return hash(self.path)
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
@dataclass
|
|
128
|
+
class ClassificationFields(Preprocessing):
|
|
129
|
+
sentence1:str='sentence1'
|
|
130
|
+
sentence2:str='sentence2'
|
|
131
|
+
labels:str='labels'
|
|
132
|
+
|
|
133
|
+
@dataclass
|
|
134
|
+
class Seq2SeqLMFields(Preprocessing):
|
|
135
|
+
prompt:str='prompt'
|
|
136
|
+
output:str='output'
|
|
137
|
+
|
|
138
|
+
@dataclass
|
|
139
|
+
class TokenClassificationFields(Preprocessing):
|
|
140
|
+
tokens:str='tokens'
|
|
141
|
+
labels:str='labels'
|
|
142
|
+
|
|
143
|
+
@dataclass
|
|
144
|
+
class MultipleChoiceFields(Preprocessing):
|
|
145
|
+
inputs:str='input'
|
|
146
|
+
choices:Iterable=tuple()
|
|
147
|
+
labels:str='labels'
|
|
148
|
+
choices_list:str=None
|
|
149
|
+
def __post_init__(self):
|
|
150
|
+
for i, c in enumerate(self.choices):
|
|
151
|
+
setattr(self,f'choice{i}',c)
|
|
152
|
+
delattr(self,'choices')
|
|
153
|
+
if not self.choices_list:
|
|
154
|
+
delattr(self,'choices_list')
|
|
155
|
+
|
|
156
|
+
def __call__(self,dataset, *args, **kwargs):
|
|
157
|
+
dataset = super().__call__(dataset, *args, **kwargs)
|
|
158
|
+
if self.choices_list:
|
|
159
|
+
dataset = dataset.filter(lambda x: 1<len(x['choices_list']))
|
|
160
|
+
n_options = min([len(x) for k in dataset for x in dataset[k]['choices_list']])
|
|
161
|
+
n_options = min(5,n_options)
|
|
162
|
+
dataset = dataset.map(self.flatten, fn_kwargs={'n_options':n_options})
|
|
163
|
+
return dataset
|
|
164
|
+
|
|
165
|
+
@staticmethod
|
|
166
|
+
def flatten(x, n_options=None):
|
|
167
|
+
n_neg = n_options-1 if n_options else None
|
|
168
|
+
choices = x['choices_list']
|
|
169
|
+
label=x['labels']
|
|
170
|
+
neg = choices[:label] + choices[label+1:]
|
|
171
|
+
pos = choices[label]
|
|
172
|
+
x['labels']=0
|
|
173
|
+
x['choices_list']=[pos]+neg[:n_neg]
|
|
174
|
+
for i,o in enumerate(x['choices_list']):
|
|
175
|
+
x[f'choice{i}']=o
|
|
176
|
+
del x['choices_list']
|
|
177
|
+
return x
|
|
178
|
+
|
|
179
|
+
@dataclass
|
|
180
|
+
class SharedFields:
|
|
181
|
+
splits:list=Preprocessing.default_splits
|
|
182
|
+
dataset_name:str = None
|
|
183
|
+
config_name:str = None
|
|
184
|
+
pre_process: callable = lambda x:x
|
|
185
|
+
post_process: callable = lambda x:x
|
|
186
|
+
#language:str="en"
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
@dataclass
|
|
190
|
+
class Classification(SharedFields, ClassificationFields): pass
|
|
191
|
+
|
|
192
|
+
@dataclass
|
|
193
|
+
class MultipleChoice(SharedFields, MultipleChoiceFields): pass
|
|
194
|
+
|
|
195
|
+
@dataclass
|
|
196
|
+
class TokenClassification(SharedFields, TokenClassificationFields): pass
|
|
197
|
+
|
|
198
|
+
@dataclass
|
|
199
|
+
class Seq2SeqLM(SharedFields, Seq2SeqLMFields): pass
|
|
200
|
+
|
|
201
|
+
get=dotgetter()
|
|
202
|
+
constant = pretty(fc.constantly)
|
|
203
|
+
regen = lambda x: list(exrex.generate(x))
|
|
204
|
+
|
|
205
|
+
def name(label_name, classes):
|
|
206
|
+
return lambda x:classes[x[label_name]]
|
|
207
|
+
|
|
208
|
+
def fix_splits(dataset):
|
|
209
|
+
|
|
210
|
+
if len(dataset)==1 and "train" not in dataset:
|
|
211
|
+
k = list(dataset)[0]
|
|
212
|
+
dataset['train'] = copy.deepcopy(dataset[k])
|
|
213
|
+
del dataset[k]
|
|
214
|
+
|
|
215
|
+
if 'auxiliary_train' in dataset:
|
|
216
|
+
del dataset['auxiliary_train']
|
|
217
|
+
|
|
218
|
+
if 'test' in dataset: # manage obfuscated labels
|
|
219
|
+
if 'labels' in dataset['test'].features:
|
|
220
|
+
if len(set(fc.flatten(dataset['test'].to_dict()['labels'])))==1:
|
|
221
|
+
del dataset['test']
|
|
222
|
+
|
|
223
|
+
if 'validation' in dataset and 'train' not in dataset:
|
|
224
|
+
train_validation = dataset['validation'].train_test_split(0.5, seed=0)
|
|
225
|
+
dataset['train'] = train_validation['train']
|
|
226
|
+
dataset['validation']=train_validation['test']
|
|
227
|
+
|
|
228
|
+
if 'validation' in dataset and 'test' not in dataset:
|
|
229
|
+
validation_test = dataset['validation'].train_test_split(0.5, seed=0)
|
|
230
|
+
dataset['validation'] = validation_test['train']
|
|
231
|
+
dataset['test']=validation_test['test']
|
|
232
|
+
|
|
233
|
+
if 'train' in dataset and 'validation' not in dataset:
|
|
234
|
+
train_val = dataset['train'].train_test_split(train_size=0.90, seed=0)
|
|
235
|
+
dataset['train'] = train_val['train']
|
|
236
|
+
dataset['validation']=train_val['test']
|
|
237
|
+
|
|
238
|
+
if 'test' in dataset and 'validation' not in dataset:
|
|
239
|
+
validation_test = dataset['test'].train_test_split(0.5, seed=0)
|
|
240
|
+
dataset['validation'] = validation_test['train']
|
|
241
|
+
dataset['test']=validation_test['test']
|
|
242
|
+
|
|
243
|
+
if 'validation' not in dataset and 'test' not in dataset:
|
|
244
|
+
train_val_test = dataset["train"].train_test_split(train_size=0.90, seed=0)
|
|
245
|
+
val_test = train_val_test["test"].train_test_split(0.5, seed=0)
|
|
246
|
+
dataset["train"] = train_val_test["train"]
|
|
247
|
+
dataset["validation"] = val_test["train"]
|
|
248
|
+
dataset["test"] = val_test["test"]
|
|
249
|
+
|
|
250
|
+
return dataset
|
|
251
|
+
|
|
252
|
+
def fix_labels(dataset, label_key='labels'):
|
|
253
|
+
if type(dataset['train'][label_key][0]) in [int,list,float]:
|
|
254
|
+
return dataset
|
|
255
|
+
labels=set(fc.flatten(dataset[k][label_key] for k in {"train"}))
|
|
256
|
+
if set(labels)=={'entailment','neutral','contradiction'}:
|
|
257
|
+
order=lambda x:dict(fc.flip(enumerate(['entailment','neutral','contradiction']))).get(x,x)
|
|
258
|
+
else:
|
|
259
|
+
order=str
|
|
260
|
+
labels=sorted(labels, key=order)
|
|
261
|
+
dataset=dataset.cast_column(label_key, datasets.ClassLabel(names=labels))
|
|
262
|
+
return dataset
|
|
263
|
+
|
|
264
|
+
def concatenate_dataset_dict(l):
|
|
265
|
+
"""Concatenate a list of DatastDict objects sharing same splits and columns."""
|
|
266
|
+
keys=l[0].keys()
|
|
267
|
+
return datasets.DatasetDict({k: datasets.concatenate_datasets([x[k] for x in l]) for k in keys})
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import random
|
|
2
|
+
from datasets import DatasetDict, Dataset
|
|
3
|
+
from sorcery import dict_of
|
|
4
|
+
import string
|
|
5
|
+
|
|
6
|
+
improper_labels =['recast/recast_kg_relations','linguisticprobing',"lex_glue/scotus",'lexical_relation_classification/ROOT09',"pragmeval/squinky","pragmeval/emobank",'pragmeval/persuasiveness']
|
|
7
|
+
improper_labels += ['glue/stsb', 'sick/relatedness', 'joci', 'utilitarianism', 'amazon_counterfactual/en', 'toxic_conversations', 'ethos/multilabel', 'lex_glue/eurlex', 'lex_glue/unfair_tos', 'app_reviews', 'humicroedit/subtask-1', 'stackoverflow-questions', 'go_emotions/simplified', 'google_wellformed_query', 'has_part', 'blog_authorship_corpus/age', 'promptCoherence', 'Sarcasm_News_Headline', 'auditor_review/demo-org--auditor_review', 'Dynasent_Disagreement', 'Politeness_Disagreement', 'SBIC_Disagreement', 'SChem_Disagreement', 'Dilemmas_Disagreement', 'sts-companion', 'acceptability-prediction', 'chaos-mnli-ambiguity', 'headline_cause/en_simple', 'oasst1_dense_flat', 'civil_comments']
|
|
8
|
+
|
|
9
|
+
improper_labels += ['stsb_multi_mt','MLMA_hate_speech','icl-symbol-tuning-instruct','zero-shot-label-nli']
|
|
10
|
+
|
|
11
|
+
def render_options(options):
|
|
12
|
+
options = [f'"{x}"' for x in options]
|
|
13
|
+
return f"{', '.join(options[:-1])} or {options[-1]}"
|
|
14
|
+
|
|
15
|
+
def render_classification(text,options,answer):
|
|
16
|
+
example = 'A→B' if text.startswith('A:') else 'the following'
|
|
17
|
+
inputs = f'With no explanation, label {example} with either {render_options(options)}.\n{text}'
|
|
18
|
+
targets = f"{answer}."
|
|
19
|
+
return dict_of(inputs,targets)
|
|
20
|
+
|
|
21
|
+
def render_token_classification(tokens,options,labels):
|
|
22
|
+
prefix = f'With no explanation, label each line with {render_options(options)} preceded by ":".\n'
|
|
23
|
+
inputs = prefix+"\n".join(tokens)
|
|
24
|
+
targets = "\n".join([':'.join(x) for x in zip(tokens,labels)])
|
|
25
|
+
return dict_of(inputs,targets)
|
|
26
|
+
|
|
27
|
+
def render_multiple_choice(prompt, options, labels):
|
|
28
|
+
inputs=(prompt+'\n' if prompt else '')
|
|
29
|
+
letters = string.ascii_uppercase[:len(options)]
|
|
30
|
+
inputs=f'With no explanation, chose the best option from {render_options(letters)}. {inputs}'
|
|
31
|
+
for letter, option in zip(letters, options):
|
|
32
|
+
inputs+=f'\n{letter}: {option}'
|
|
33
|
+
targets = f'{letters[labels]}.'
|
|
34
|
+
return dict_of(inputs, targets)
|
|
35
|
+
|
|
36
|
+
def negative_sample_options(y, labels,N=4):
|
|
37
|
+
if len(labels)<N:
|
|
38
|
+
return labels
|
|
39
|
+
else:
|
|
40
|
+
return [y]+random.sample([x for x in labels if x!=y], N-1)
|
|
41
|
+
|
|
42
|
+
def shuffle_choices(x):
|
|
43
|
+
choices = sorted([k for k in x if 'choice' in k])
|
|
44
|
+
choices_texts = [x[c] for c in choices]
|
|
45
|
+
correct_choice =choices_texts[x['labels']]
|
|
46
|
+
random.shuffle(choices_texts)
|
|
47
|
+
for c, ct in zip(choices, choices_texts):
|
|
48
|
+
x[c]=ct
|
|
49
|
+
x["labels"]=choices_texts.index(correct_choice)
|
|
50
|
+
return x
|
|
51
|
+
|
|
52
|
+
def recast_dataset_classification_to_mc(dataset,sep="[SEP]",N=4):
|
|
53
|
+
|
|
54
|
+
def recast_split(d,N=N):
|
|
55
|
+
labels = d.features['labels']
|
|
56
|
+
df=d.to_pandas()
|
|
57
|
+
df['inputs'] = df.sentence1
|
|
58
|
+
if "sentence2" in df:
|
|
59
|
+
df['inputs'] +=sep + df.sentence2
|
|
60
|
+
|
|
61
|
+
N=min(N, len(labels.names))
|
|
62
|
+
df['choices']=df.apply(lambda x:negative_sample_options(labels.int2str(x['labels']), labels.names,N),axis=1)
|
|
63
|
+
df['labels']=df.apply(lambda x:x['choices'].index(labels.int2str(x['labels'])),axis=1)
|
|
64
|
+
|
|
65
|
+
for i in range(N):
|
|
66
|
+
df[f'choice{i}']= "This example is " + df.choices.map(lambda x:x[i])
|
|
67
|
+
|
|
68
|
+
choices = [f'choice{i}' for i in range(N)]
|
|
69
|
+
return Dataset.from_pandas(df[['inputs',*choices,'labels']],preserve_index=False)
|
|
70
|
+
|
|
71
|
+
return DatasetDict({k: recast_split(v) for k,v in dataset.items()})
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def recast_instruct(dataset):
|
|
75
|
+
features = dataset['train'].features
|
|
76
|
+
labels = features['labels']
|
|
77
|
+
|
|
78
|
+
if "sentence1" in features:
|
|
79
|
+
task_type='Classification'
|
|
80
|
+
if "choice0" in features:
|
|
81
|
+
task_type = "MultipleChoice"
|
|
82
|
+
if "tokens" in features:
|
|
83
|
+
task_type = "TokenClassification"
|
|
84
|
+
|
|
85
|
+
def recast_MultipleChoice(x):
|
|
86
|
+
x=shuffle_choices(x)
|
|
87
|
+
choices = sorted([k for k in x if 'choice' in k])
|
|
88
|
+
if all([x[c] in x['inputs'] for c in choices]):
|
|
89
|
+
return {"inputs":x['inputs'], 'targets': x[f"choice{x['labels']}"].strip()+"."}
|
|
90
|
+
else:
|
|
91
|
+
return render_multiple_choice(x['inputs'],[x[c] for c in choices],x['labels'])
|
|
92
|
+
|
|
93
|
+
def recast_TokenClassification(x):
|
|
94
|
+
distractors = list(labels.feature.names)
|
|
95
|
+
x_labels = [labels.feature.int2str(y) for y in x['labels']]
|
|
96
|
+
labels_set= list({labels.feature.int2str(y) for y in x['labels']})
|
|
97
|
+
options=list(dict.fromkeys(labels_set+distractors))[:max(len(labels_set),10)]
|
|
98
|
+
return render_token_classification(x['tokens'],options,x_labels)
|
|
99
|
+
|
|
100
|
+
def recast_Classification(x):
|
|
101
|
+
if 'sentence2' in x:
|
|
102
|
+
text=f"A: {x['sentence1']}\nB: {x['sentence2']}"
|
|
103
|
+
else:
|
|
104
|
+
text=x['sentence1']
|
|
105
|
+
|
|
106
|
+
answer=labels.int2str(x['labels']).strip()
|
|
107
|
+
options= negative_sample_options(answer, labels._int2str)
|
|
108
|
+
return render_classification(text, options, answer)
|
|
109
|
+
|
|
110
|
+
dataset = dataset.map(eval(f"recast_{task_type}"))
|
|
111
|
+
dataset = dataset.remove_columns([k for k in features if k not in ['inputs','targets']])
|
|
112
|
+
return dataset
|
|
113
|
+
|