人工知能に関する断創録

人工知能、認知科学、心理学、ロボティクス、生物学などに興味を持っています。このブログでは人工知能のさまざまな分野について調査したことをまとめています。最近は、機械学習、Deep Learning、Kerasに関する記事が多いです。



Kerasによる2クラス分類(Pima Indians Diabetes)

Kerasのプログラミングは

  1. データのロード
  2. モデルの定義
  3. モデルのコンパイル
  4. モデルの学習
  5. モデルの評価
  6. 新データに対する予測

という手順が一般的。今回はもう少し実践的なデータを使ってこの流れをつかみたい。

ソースコード:pima.py

1. データのロード

参考文献で挙げた記事と同じようにUCI Machine Learning repositoryにあるPima Indians Diabetes Data Setを使おう。 医療系のデータでPimaインディアンが糖尿病にかかったかどうかを表すデータのようだ。

Attribute Information:
1. Number of times pregnant
2. Plasma glucose concentration a 2 hours in an oral glucose tolerance test
3. Diastolic blood pressure (mm Hg)
4. Triceps skin fold thickness (mm)
5. 2-Hour serum insulin (mu U/ml)
6. Body mass index (weight in kg/(height in m)^2)
7. Diabetes pedigree function
8. Age (years)
9. Class variable (0 or 1)

データの説明によると最初の8列が患者の属性情報で9列目が糖尿病を発症しない(0)または糖尿病を発症した(1)というラベルとなっている。つまり、患者の属性情報から糖尿病を発症するかを予測するモデルを学習するのがここでの目的。

このデータはCSV形式でダウンロードできる。データをロードするコードは、

# load pima indians dataset
dataset = np.loadtxt(os.path.join("data", "pima-indians-diabetes.data"), delimiter=',')

# split into input (X) and output (Y) variables
X = dataset[:, 0:8]
Y = dataset[:, 8]

ここで、二次元データならグラフで可視化してみるところだけれど、8次元データはそのままでは可視化できない。分析するなら属性間の相関図や次元圧縮してみるのがセオリーか?今回はKerasの使い方の習得がメインなので飛ばそう。

2. モデルの定義

ここはニューラルネットの構造を組み立てるところ。今回は、隠れ層が2つ、出力層が1つの多層パーセプトロン を構築する。

f:id:aidiary:20161103212842p:plain:w400

# create model
model = Sequential()
model.add(Dense(12, input_dim=8, init='uniform', activation='relu'))
model.add(Dense(8, init='uniform', activation='relu'))
model.add(Dense(1, init='uniform', activation='sigmoid'))
  • initで層の重みの初期化方法を指定できる
  • uniformだと0~0.05の一様乱数。normalだと正規乱数。Deep Learning Tutorialの初期値重みで使われていたglorot_uniformもある
  • 層の活性化関数は、独立した層ではなくDenseactivation引数でも指定できる
  • 隠れ層の活性化関数にはrelu、出力層の活性化関数にはsigmoidを指定
  • 出力層にsigmoidを使うと0.0から1.0の値が出力されるため入力データのクラスが1である確率とみなせる。0.5を閾値として0.5未満ならクラス0、0.5以上ならクラス1として分類する

3. モデルのコンパイル

損失関数、最適化関数、評価指標を指定してモデルをコンパイルする。2クラス分類なのでbinary_crossentropyを使う。ここら辺は前回と同じ。

# compile model
model.compile(loss='binary_crossentropy',
              optimizer='adam',
              metrics=['accuracy'])

4. モデルの学習

# fit the model
model.fit(X, Y, nb_epoch=150, batch_size=10)
  • 訓練データXとラベルYを指定して学習
  • エポックは固定で150回ループを回す
  • 学習はいわゆるミニバッチ学習でバッチサイズは10とした。データを10個ずつ取り出して誤差を蓄積し、その誤差で1回重みを更新する。

5. モデルの評価

# evaluate the model
scores = model.evaluate(X, Y)
print("%s: %.2f%%" % (model.metrics_names[1], scores[1] * 100))
  • モデルの評価にはmodel.evaluate()を使う。
  • 戻り値は評価指標のリスト。デフォルトでは損失(loss)のみ。compile()metricsに評価指標を追加すると、別の評価指標が追加される。今回は、精度(acc)を追加してある。model.metrics_namesで、評価尺度の名前リストが得られる。
> print(model.metrics_names)
['loss', 'acc']
> print(scores)
[0.45379118372996646, 0.7890625]

ここでは、訓練データを使って評価しているが、実際は訓練データとは独立したテストデータを用意するべき。ただ、モデルにバグがないか確認するために最初は訓練データで評価してみるのもありだと思う。訓練データでさえ精度がものすごく低かったらそもそも学習できないかプログラムにバグがある。今回は、訓練データの予測で精度79%なのでそこそこうまくいっている?次回は訓練データとテストデータを分ける例を取り上げたい。

6. 新データに対する予測

predictions = np.round(model.predict(X))
correct = Y[:, np.newaxis]
  • モデルに新しいデータを入力してクラスラベルを予測するにはmodel.predict()
  • 今回は簡単のため訓練データXをそのまま入力
  • 出力層はsigmoidなので下のように0.0から1.0の値が出力される
  • 出力をクラスラベルにするためにround()を使う。0.5以上なら1に切り上げ、未満なら0に切り下げ
> print(predictions)
[[ 0.82117373]
 [ 0.10473501]
 [ 0.90901828]
 [ 0.10512047]
 [ 0.78090101]
 ...
> print(correct)
[[ 1.]
 [ 0.]
 [ 1.]
 [ 0.]
 [ 1.]
 ...

今回は実践的なデータセットを用いてKerasによる実験の流れを一通りまとめた。

参考