プロクラシスト

今日の寄り道 明日の近道

【Day-7】sklearnで機械学習用データの作り方/使い方をまとめる(sklearn.datasets)


スポンサーリンク

f:id:imslotter:20171206182003p:plain データ分析ガチ勉強アドベントカレンダー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) : サンプルをシャッフルするかどうか。

それぞれのデータの分布(イメージ)はこんな感じ

f:id:imslotter:20171206190749p:plain

マルチラベルデータ生成

さっきのが、正解ラベルがひとつのラベルのとき。正解ラベルを複数持つデータについては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_curvemake_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。そんなに難しい構造していないので、ちょっと自分が作った学習器を試したいときに、データだけ呼ぶってのもいいと思う。

学習させる

データを用意できたので、最後にデータを投げるところまでまとめて終わりにする。 処理の仕方とか、まあ種々のデータのいじり方は後に回すとして、どうやって入力するかだけ。

  1. データをシャッフルして分割する(sklearn.model_selection.train_test_split)
  2. 学習させる(sklearn.ensemble.RandomForestClassifier)
  3. テストして評価する(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のデータセットの形を知り、をうまく使いこなせれば、いろいろと幅が広がりそう。

今日のコードも、上げているので是非試してみてください。

github.com

明日もsklearnの話題!最後に取り扱った学習のところをもうちょっと詳しく書く予定です。お楽しみに~

PROCRASIST