Dataset

DatasetはLoaderとSchemaの組合せで構成されます。Loaderで読み込んだレコードに対して、Schemaにより定義されたデータ型情報に基づいてDatum型に変換して保持します。

from jubakit.classifier import Schema, Dataset

loader = ...
schema = Schema( ... )

dataset = Dataset(loader, schema)

いくつかのServiceは、上記の方法以外にもDatasetの作成方法が実装されています。例えば、 jubakit.classifier.Dataset は scikit-learn など利用して生成したデータセットを読み込むために、 from_arrayfrom_matrix といった関数が提供されています。その他、本章で説明する機能は jubakit.base.BaseDataset に実装されており、全てのServiceで利用することができます。

静的、非静的なDataset

デフォルトでは、全てのレコードはDatasetインスタンスが作成された際にLoaderからメモリ上へ全て読み出されます。上記の方法で読み出したデータセットを 静的なDataset と呼んでいます。Loaderから逐次的にレコードを読み出したい場合には、 static オプションを指定することで、 非静的なDataset を生成することができます

dataset = Dataset(loader, schema, static=False)

注意点としては、非静的なDatasetを利用した場合、インデックスを利用したレコードアクセスなど、いくつかの機能が利用できなくなります。

Twitterデータなど読み込み上限なしLoaderから作成されたDatasetは非静的になります。上限なしLoaderを利用する際には static=True とすることはできません。

スキーマ推定

Datasetを作成する際にSchemaを指定しない場合には、データセットの一番上のレコードを利用してスキーマの自動推定を行います。

>>> dataset = Dataset(loader)
>>> print(dataset.get_schema())
{'types': {'k1': 's', 'k2': 'n'}, 'fallback_type': None, 'keys': {'k1': 'k1', 'k2': 'k2'}}

types には自動推定されたスキーマ情報が格納されています。上記の例では、k1k2 がそれぞれ 文字列型数値型 と推定されています。

レコードアクセス

get 関数を利用することでLoaderから読み込まれて変換される前の生データにアクセスすることができます。

>>> dataset.get(1)
{'k1': 'hello world', 'k2': 5}

Datumなどに変換されたレコードへはインデックスアクセスすることができます。ただ、殆どのケースで上記のこのような操作は不要でしょう。

>>> dataset[1]
(None, None, <jubatus.common.datum.Datum object at 0xdeadbeef>)
>>> print(dataset[1][2])
datum{string_values: [['k1', 'hello world'], num_values: [['k2', 5.0]], binary_values: []}

スライス操作によってデータを分割したり、データセットの長さを計算することもできます。

>>> dataset2 = dataset[1:3]
>>> type(dataset2)
<class 'jubakit.anomaly.Dataset'>
>>> len(dataset2)
2

scikit-learnの交差検証機能 を利用してデータをN分割することも簡単にできます。以下のコードでは、 KFold を利用してデータセットを学習用データ( ds_train ) と検証用データ( ds_test )に分割しています。

>>> from sklearn.cross_validation import KFold
>>> for train, test in KFold(4, n_folds=2):
...   (ds_train, ds_test) = (dataset[train], dataset[test])

非静的Datasetはランダムアクセスができないため、生データへアクセスするにはイテレーションを回し、インデックスを利用して``get`` 関数を呼ぶ必要がある点に注意してください。

変換処理

静的Datasetは convert 関数を利用することで、ユーザ定義のラムダ関数により一括して変換をかけることができます。

>>> shuffled_dataset = dataset.convert(lambda x: random.sample(x, len(x)))

ラムダ関数は必ず1つの引数を取る必要があり、各生レコードに対して変換処理を施します。ラムダ関数は入力として与えられたリスト構造自体を変更してはいけません。変換処理を行った結果として、新たなDatasetが生成されます。

利便性のため、Datasetにはレコードの順番をランダムに入れ替える``shuffle `` 関数が実装されています。

永続化

Datasetを永続化するために、pickle モジュールを利用することができます。異なるバージョンで生成されたDatasetをUnpickleすることはできません。