本記事は、Hugging Face (Transformers) で独自データセットを使用する 方法の備忘録的記事です。CSVファイルやpandas.DataFrameのデータを、Hugging Faceで使用するための方法を紹介します。
ちなみに、Hugging Face (Transformers)は、主に自然言語処理にて広く活用されている、ディープラーニングのライブラリです。Hugging Faceで公開されている訓練済みモデルを簡単に使用できたり、Keras/Pytorchの両方で使用できたり、便利なライブラリです。
概要
Hugging Faceには、Datasetsというパッケージがあります。
そして、その中にdatasets.Dataset
クラスが存在します。
Hugging Face (Transformers) では、データセットを、このdatasets.Dataset
クラスとして読み込んで使用します。
本記事は、独自データセット(csvファイルやpandas.DataFrame形式)を、datasets.Dataset
クラスとして読み込む方法を紹介していく、という内容です。
主な内容:
- datasets.Datasetとして読み込む方法
- csvファイルから
- pandas.DataFrameから
- datasets.Featuresによるクラスラベルの指定
- train_test_split() によるサンプル分割
文章分類タスクを想定しています。
他のタスクでの方法は、今後追記できたらとは思います。
また、本記事の内容は、以下の、Hugging Faceのドキュメントをベースにしています。
より詳細な内容を知りたい方は、こちらをご参照ください。
Hugging Face - Datasets > Load
準備
まず、読み込むダミーデータを用意します。
./my_dataset/
train1.csv
train2.csv
test.csv
id,text,label
0,ようやく目標が達成できそうだ,喜
1,どうしてこんな目に遭うんだ,怒
2,全然上手くいかない……,哀
3,明日から長期休暇だ,楽
... (略)
(train2.csv, test.csvは省略します。ファイル形式はtrain1.csvと同じものとします。)
csvファイルから読み込む
読み込み方法は2パターンあります。
import datasets
# 方法1
dataset_dict = datasets.load_dataset('csv', data_files=['./my_dataset/train1.csv'])
# 方法2
dataset_dict = datasets.load_dataset('./my_dataset', data_files=['train1.csv'])
また、複数ファイルを指定したり、訓練・評価ファイルを指定したりすることも可能です。
# 方法2, 複数ファイル指定
dataset_dict = datasets.load_dataset('./my_dataset', data_files=['train1.csv', 'train2.csv'])
# 方法2, 訓練・評価サンプルをそれぞれ指定
dataset_dict = datasets.load_dataset('./my_dataset', data_files={'train': 'train1.csv', 'test': 'test.csv'})
なお、これらの返値は、datasets.DatasetDict
クラスとなっています。
train
やtest
といったキーに対して、値としてdatasets.Dataset
が格納されています。
DatasetDict({
train: Dataset({
features: ['id', 'text', 'label'],
num_rows: 50
}),
test: Dataset({
features: ['id', 'text', 'label'],
num_rows: 20
})
})
datasets.Dataset
として直接読み込むことも可能です。
# datasets.Datasetとして読み込む
dataset = datasets.Dataset.from_csv(['./my_dataset/train1.csv'])
他にも、csvファイル内の、必要な列だけ読み込むことも可能です。
# 方法2, 読み込む列名を指定
dataset_dict = datasets.load_dataset('./my_dataset', data_files=['train1.csv'], usecols=['text', 'label'])
print(dataset_dict)
DatasetDict({
train: Dataset({
features: ['text', 'label'], # 'id'列が除外されている
num_rows: 50
})
})
pandas.DataFrameから読み込む
続いて、pandas.DataFrame
からの読み込み方法です。
データセットに前処理を加えたり一部を除外したりしたい場合など、csvファイルから直接ではなく、DataFrameで処理をしてから取り込みたい、という場合があるかと思います。
df_train = pd.read_csv('./my_dataset/train1.csv')
dataset = datasets.Dataset.from_pandas(df_train[['text', 'label']])
datasets.Features を指定する
データセットの各値の「意味」を指定することで、データセットを使いやすくします。
本記事の文脈においては、label
が文章分類のクラスラベルであることを指定します。
具体的には、引数features
に、datasets.Features
を指定します。
# datsets.Featuresを定義
my_features = datasets.Features({
'text': datasets.Value('string'),
'label': datasets.ClassLabel(names=['喜', '怒', '哀', '楽'])})
# Dataset生成時に、featuresを指定
dataset_w_feat = datasets.Dataset.from_pandas(
df_train[['text', 'label']], features=my_features)
上記では、Dataset.from_pandas()
で使用していますが、load_dataset()
やDataset.from_csv()
でも同様に使用できます。
features
の指定の有無で、出力を確認してみます。
label
の要素が、クラス名(文字列)から、クラス番号に変換されているのがわかります。
print(dataset.features)
# {'text': Value(dtype='string', id=None),
# 'label': Value(dtype='string', id=None), <--- 文字列として読み込まれている
print(dataset_w_feat.features)
# {'text': Value(dtype='string', id=None),
# 'label': ClassLabel(num_classes=4, names=['喜', '怒', '哀', '楽'], id=None)} <--- クラスラベルとして読み込まれている
print(dataset[0])
# {'text': 'ようやく目標が達成できそうだ', 'label': '喜'}
print(dataset_w_feat[0])
# {'text': 'ようやく目標が達成できそうだ', 'label': 0} <--- クラス番号に変換されている
なお、クラス名とクラス番号は、以下の方法で相互に変換することも可能です。
dataset_w_feat.features['label'].int2str(0) # 喜
dataset_w_feat.features['label'].str2int('怒') # 1
train_test_split()によるサンプル分割
最後に、datasets.Dataset
を、訓練・評価用にサンプルを分割する方法です。
train_test_split()
という関数を使用します
dataset_dict = dataset_w_feat.train_test_split(test_size=0.2, shuffle=True)
print(dataset_dict)
DatasetDict({
train: Dataset({
features: ['text', 'label'],
num_rows: 40
})
test: Dataset({
features: ['text', 'label'],
num_rows: 10
})
})
csvファイルの時点でサンプルが分割されている場合は、前述の方法(「方法2, 訓練・評価サンプルをそれぞれ指定」)を使用します。
おわりに
Hugging Face (Transformers) にて、独自データセットを使用する方法を、一部まとめてみました。
何かしら参考になりましたら嬉しいです。
また、誤った記載やより良い方法がありましたら、ご指摘いただけますと幸いです。
最後までお読みいただきありがとうございました。
それでは!(*ˊᗜˋ)ノシ