データ分析ガチ勉強アドベントカレンダー7日目。 今日からはscikit-learn
を取り扱う。
機械学習の主要ライブラリであるscikit-learn(sklearn)。機械学習のイメージをつかみ練習するにはコレが一番よいのではないかと思われる。
今日はデータを作って、(必要ならば)変形し、モデルに入力するまでをまとめる。
- 既存データへのアクセスの仕方
- ある程度狙ったランダムデータを作る方法
- modelに入力する際、どういう構造でデータを入れるかについて。
基本的にはDataset loading utilitiesを参考にしながら。 いくつかデータセットをピックアップして、実際に扱ってみる。
なお、今回はsklearn.datasets
をふんだんに用いるので、はじめに下記コマンドを読み込んでおく。
from sklearn import datasets
Toy Dataset
datasets.load_hogehoge()
という関数により、データを使うことができる。
感覚をつかむために用意されたデータセット。簡単に使えるが、デー多数は少なく、学習器の性能をテストするには完全な量ではない。
スペック
dataset | どういうデータか | データ数 | 次元 | 特徴量の型 | 正解ラベル |
---|---|---|---|---|---|
load_boston |
ボストンの家賃 | 506 | 13 | 正の実数 | 実数 |
load_iris |
アヤメの分類 | 50×3クラス | 4 | 正の実数 | 3クラス |
load_diabetes |
糖尿病患者の進行状況 | 442 | 10 | -2<x<2 | 25~346の整数 |
load_digits |
8×8ピクセルの数字データ | (約)180×10クラス | 64 | 0~16の整数 | 0から9まで |
load_linnerud |
男性の生理学的特徴と運動能力の関係 | 20 | 3 | 整数 | 整数 |
load_wine |
ワインを3種類に分類 | [59,71,48]=178 | 13 | 正の実数 | 3クラス |
load_breast_canser |
乳がんの陰性/陽性判定 | [212,357]=569 | 30 | 正の実数 | 2クラス |
データの形式
正解ラベルが実数かクラスかによって、正解データの利用の仕方が回帰か分類かに分かれる。
ざっくり回帰は、次の値を予測する、分類は、そのデータがどのクラスに属するかを判定する。正解ラベルが実数ならばその値自身に意味があるが、クラス(1,2,3など)ならば、その値自身には意味がない(カテゴリ変数とも呼ばれる)
先ほどの表で、正解ラベル次第でデータの保持形式が変わる
正解ラベルが実数
下記データを保持している
- data : データに入っているベクトルの値
- feature_names : 各要素の名前
- target : 実数値
(例:boston)
data = datasets.load_boston() print("data shape:", data.data.shape) print("feature name:",data.feature_names) print("target value:", data.target)
出力
data shape: (506, 13) feature name: ['CRIM' 'ZN' 'INDUS' 'CHAS' 'NOX' 'RM' 'AGE' 'DIS' 'RAD' 'TAX' 'PTRATIO' 'B' 'LSTAT'] target value: [ 24. 21.6 34.7 ... 22. 11.9]
正解ラベルがクラス
下記データを保持
- data : データに入っているベクトルの値
- feature_names : 各要素の名前
- target : クラス(カテゴリ変数)
- target_names : クラスの名前
data = datasets.load_iris() print("data shape:",data.data.shape) print("feature name:",data.feature_names) print("target class", data.target) print("class name:",data.target_names)
出力
data shape: (150, 4) feature name: ['sepal length (cm)', 'sepal width (cm)', 'petal length (cm)', 'petal width (cm)'] target class [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2] class name: ['setosa' 'versicolor' 'virginica']
シャッフル
ちなみにこのままだと、データが0,1,2ときれいに並びすぎている。逐次学習のアルゴリズムのときなどは影響を受けてしまうので、sklearn.util.shuffle
を用いるとよい
from sklearn.utils import shuffle X, y = shuffle(data.data,data.target, random_state=0) print("target class", y)
出力
target class: [2 1 0 2 0 2 0 1 1 1 2 1 1 1 1 0 1 1 0 0 2 1 0 0 2 0 0 1 1 0 2 1 0 2 2 1 0 1 1 1 2 0 2 0 0 1 2 2 2 2 1 2 1 1 2 2 2 2 1 2 1 0 2 1 1 1 1 2 0 0 2 1 0 0 1 0 2 1 0 1 2 1 0 2 2 2 2 0 0 2 2 0 2 0 2 2 0 0 2 0 0 0 1 2 2 0 0 0 1 1 0 0 1 0 2 1 2 1 0 2 0 2 0 0 2 0 2 1 1 1 2 2 1 1 0 1 2 2 0 1 1 1 1 0 0 0 2 1 2 0]
狙ったランダムデータを生成する
ラベル付データ生成
make_hoge
を使えば、簡単にデータを生成することができる。hoge
で表内囲まれているところは、パラメータで調節できるところ。
dataset | どういうデータか | データ数 | 次元 | クラス数 | データ分布の調整 |
---|---|---|---|---|---|
make_blobs |
ガウス分布のデータ生成 (重ならない) |
n_samples |
n_features |
centers |
cluster_std center_box |
make_classification |
n-class分類用データ生成 (詳細設計可能) |
n_samples |
n_features |
n_classes |
結構複雑 詳細 |
make_gaussian_quantiles |
同心円状の分布を生成 | n_samples |
n_features |
n_classes |
mean cov |
make_hastie_10_2 |
Hastie Exampleで用いられた分布 | n_samples |
10 | 2 | - |
make_circles |
円の分布 | n_samples |
2 | 2 | factor |
make_moons |
三日月形の分布 | n_samples |
2 | 2 | - |
その他
shuffle
(bool) : サンプルをシャッフルするかどうか。
それぞれのデータの分布(イメージ)はこんな感じ
マルチラベルデータ生成
さっきのが、正解ラベルがひとつのラベルのとき。正解ラベルを複数持つデータについてはmake_multilabel_classification
にて生成が可能(詳細)。重要なパラメータは下記
n_samples
,n_features
: ↑と一緒n_classes
: クラスの数n_labels
: ひとつのデータに対するラベル付けするクラスの平均
ひとつのデータに対して出てくる出力は下記のようになる
data, target = datasets.make_multilabel_classification(n_samples=100, n_features=10, n_classes=5, n_labels=3) print("data:",data[0]) print("label:",target[0])
出力
data: [ 4. 2. 9. 3. 4. 5. 3. 6. 1. 10.] label: [0 1 1 0 0]
1がついているのがそのデータについているラベル。
その他
そのほかにもbiclustering用のデータや、metrics learning用のデータなどもある
make_biclustering
make_s_curve
とmake_swiss_roll
(xz平面に射影)
fetchしてくる
datasets.fetch_hoghoge
で、外部リポジトリにあるデータを保持することも可能。普通にダウンロードに時間がかかるので、必要なときだけ保存するようになっている。下記のようなものがある。
関数 | 説明 |
---|---|
datasets.fetch_20newsgroups() |
自然言語のデータ、20個のニュースカテゴリに分ける。データ数は11314 |
datasets.fetch_20newsgroups_vectorized() |
上記の文章を単語に分けてベクトル化(13万次元くらい) |
datasets.fetch_california_housing() |
カリフォルニアの家の評価(正解値は実数) |
datasets.fetch_kddcup99() |
KDD99の侵入検知のコンペで用いられたデータ。詳細 |
datasets.fetch_lfw_pairs() |
labeld face in the wild の略。同じ人か違う人かの二値分類詳細 |
datasets.fetch_lfw_people() |
人の名前を当てる分類問題 |
datasets.fetch_mldata("hoge") |
"hoge"を変えれば、ここにあるデータを良しなにとってこれる |
datasets.fetch_olivetti_faces() |
AT&Tが作った、CV用データセット |
datasets.fetch_rcv1() |
Reuters Corpus Volumeの略。80万のデータ、約5万のワードベクトル、13のカテゴリ。マルチラベル。 |
datasets.fetch_species_distributions() |
species distributionのデータセット。参考 |
これも基本的には
- data : データに入っているベクトルの値
- feature_names : 各要素の名前
- target : クラス(カテゴリ変数の場合)
- target_names : クラスの名前
がデータとして入っている。自然言語ベクトル化する前とかだったら微妙に違うこともあるが、だいたいはこういう配列なんだと思っていればOK。そんなに難しい構造していないので、ちょっと自分が作った学習器を試したいときに、データだけ呼ぶってのもいいと思う。
学習させる
データを用意できたので、最後にデータを投げるところまでまとめて終わりにする。 処理の仕方とか、まあ種々のデータのいじり方は後に回すとして、どうやって入力するかだけ。
- データをシャッフルして分割する(
sklearn.model_selection.train_test_split
) - 学習させる(
sklearn.ensemble.RandomForestClassifier
) - テストして評価する(accuracy)(
sklearn.metrics.accuracy_score
)
取ってきたデータを いろんな学習器があるけれど、sklearnは入出力の関数/型が決まっている
model.fit(X,y)
: モデルを学習する(教師なしの場合は、ラベルはいらないので、model.fit(X)
)model.predict(X)
: モデルからテストを行う
irisのデータを読み込んで学習を行うところまでをやってみる
from sklearn.model_selection import train_test_split from sklearn.ensemble import RandomForestClassifier from sklearn.metrics import accuracy_score # データの読み込み iris = datasets.load_iris() data, target = iris.data, iris.target # 学習とテストに分ける data_train, data_test, target_train, target_test = train_test_split(data, target, train_size=0.8, random_state=1) # RandomForestを使う model = RandomForestClassifier() # 学習 model.fit(data_train, target_train) # テストと評価 target_pred = model.predict(data_test) print(accuracy_score(target_test, target_pred))
出力
0.966666666667
できた。ランダムフォレスト強い
まとめ
今日はデータについてと、一度学習するところまでをまとめてみた。 sklearnのデータセットの形を知り、をうまく使いこなせれば、いろいろと幅が広がりそう。
今日のコードも、上げているので是非試してみてください。
明日もsklearnの話題!最後に取り扱った学習のところをもうちょっと詳しく書く予定です。お楽しみに~