Python scikit-learn - アヤメの品種分類をクロスバリデーションで行う

アヤメの品種分類をクロスバリデーションで行います。

クロスバリデーションとは、最初に全てのデータを訓練データとテストデータに分割して、訓練データを用いて学習を行い、テストデータを用いて学習の妥当性を検証する手法です。

クロスバリデーションにはいろいろな手法がありますが、今回はK分割交差法をご紹介します。

【例 集合XをA,B,Cと3分割する場合】

(1) 集合Xを、AとBとCに分割します。
(2) Aとテストデータ、残りのB,Cを訓練データとして分類精度s1を求めます。
(3) Bとテストデータ、残りのA,Cを訓練データとして分類精度s1を求めます。
(4) Cとテストデータ、残りのA,Bを訓練データとして分類精度s1を求めます。
(5) 分類精度s1,s2,s3の平均を求め分類精度とします。

クロスバリデーション

実行するコードは下記の通りです。

[コード]

1
2
3
4
5
6
7
8
9
10
11
12
13
import pandas as pd
from sklearn import svm, metrics, model_selection, datasets

# アヤメのCSVデータを読み込む
iris = datasets.load_iris()

# データの学習
clf = svm.SVC()
scores = model_selection.cross_val_score(clf, iris.data, iris.target, cv=5)

# 正答率を求める
print('各正解率:', scores)
print('正解率:', scores.mean())

9行目のcv=5で分割数を5に設定しています。

model_selection.cross_val_score関数1つで、複数回の検証を行えるのは大変便利です。


実行結果は次のようになります。

[実行結果]

各正解率: [0.96666667 0.96666667 0.96666667 0.93333333 1.        ]
正解率: 0.9666666666666666

正答率96%以上と十分な結果となります。

Python scikit-learn - 機械学習でアヤメの品種を分類する

機械学習でアヤメの品種を分類します。

機械学習でアヤメの品種分類

scikit-learn には、機械学習やデータマイニングを試すことができるようデータが同梱されています。

iris.dataには次の4種類のデータが格納されています。

カラム内容
sepal length (cm)がく片の長さ
sepal width (cm)がく片の幅
petal length (cm)花弁の長さ
petal width (cm)花弁の幅

iris.targetには次の3種類の花の種類が格納されています。

花の種類
setosa0
versicolor1
virginica2

実行するコードは下記の通りです。

[コード]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import pandas as pd
from sklearn import svm, metrics, model_selection, datasets

# アヤメのCSVデータを読み込む
iris = datasets.load_iris()

# 学習用とテスト用に分離する
train_data, test_data, train_label, test_label = model_selection.train_test_split(iris.data, iris.target, test_size=0.2, train_size=0.8, shuffle = True)

# データの学習
clf = svm.SVC()
clf.fit(train_data, train_label)

# データを予測
pre = clf.predict(test_data)

# 正答率を求める
ac_score = metrics.accuracy_score(test_label, pre)
print('正解率:', ac_score)

学習用とテスト用にデータを分離し、シャッフルまで行ってくれるmodel_selection.train_test_split(7行目)はとても便利です。


実行結果は次のようになります。

[実行結果]

正解率: 0.9333333333333333

正答率93%以上と十分な結果となりました。

Python scikit-learn - フレームワークで排他的論理和(XOR)演算を学習する

排他的論理和(XOR)に関しての機械学習ですが、次の2点に関してフレームワークを利用する処理に変更します。

  • データとラベルを分割する。
  • 正解率を求める。

フレームワークで排他的論理和(XOR)演算を学習する

「データとラベルの分割」と「正解率を求める」箇所を変更します。

変更前のコードをコメントアウトしているので参考にして下さい。

[コード]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
import pandas as pd                 # 追加
from sklearn import svm, metrics # metrics追加

# XORの演算と結果
xor_data = [
[0, 0, 0],
[0, 1, 1],
[1, 0, 1],
[1, 1, 0]
]

# 学習させるためにデータとラベルに分ける

# [変更前]
#data = []
#label = []
#for row in xor_data:
# data.append([row[0], row[1]])
# label.append(row[2])

# [変更後]
xor_df = pd.DataFrame(xor_data)
data = xor_df.iloc[:,0:2] # データ
label = xor_df.iloc[:,2] # ラベル

# データの学習
clf = svm.SVC()
clf.fit(data, label)

# データを予測
pre = clf.predict(data)
print('予測結果:', pre)

# 正解と合っているか結果を確認

# [変更前]
#cnt_ok = 0
#total = 0
#for idx, ans in enumerate(label):
# if pre[idx] == ans:
# cnt_ok += 1
# total += 1
#print('正解率:{} / {}'.format(cnt_ok, cnt_ok / total))

# [変更後]
ac_score = metrics.accuracy_score(label, pre)
print('正解率:', ac_score)

実行結果は次のようになります。

[実行結果]

予測結果: [0 1 1 0]
正解率: 1.0

変更前に比べてかなり短いコードで同様の結果が得られることが分かります。

Python scikit-learn - 排他的論理和(XOR)演算を学習する

機械学習で排他的論理和(XOR)を学習します。

排他的論理和(XOR)とは、2つの入力のどちらか片方が真で、もう片方が偽の時には結果が真となり、両方とも真あるいは両方とも偽のときには偽となる演算です。

排他的論理和(XOR)演算を学習する

scikit-learnという機械学習用のライブラリを使います。

[コード]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
from sklearn import svm

# XORの演算と結果
xor_data = [
[0, 0, 0],
[0, 1, 1],
[1, 0, 1],
[1, 1, 0]
]

# 学習させるためにデータとラベルに分ける
data = []
label = []

for row in xor_data:
data.append([row[0], row[1]])
label.append(row[2])

# データの学習
clf = svm.SVC()
clf.fit(data, label)

# データを予測
pre = clf.predict(data)
print('予測結果:', pre)

# 正解と合っているか結果を確認
cnt_ok = 0
total = 0

for idx, ans in enumerate(label):
if pre[idx] == ans:
cnt_ok += 1
total += 1

print('正解率:{} / {}'.format(cnt_ok, cnt_ok / total))

実行結果は次のようになります。

[実行結果]

予測結果: [0 1 1 0]
正解率:4 / 1.0

4つのデータにおいて4つ正解しており、正解率は100%であることが分かります。

教師あり学習でBMI肥満度分類

BMI値の算出式で導き出された肥満度分類を、算出式を使わずSVM(サポートベクターマシン)で分類してみます。

手順としては下記の通りです。
①乱数を使って10000万件の身長・体重データを生成し、BMI値を算出し肥満度分類を行う。
②身長・体重データと肥満度分類のデータを8割の学習データと2割のテストデータに分ける。
③8割のデータを学習させる。
④学習データをもとに2割のテストデータでデータ予測を行う。
⑤データ予測がどれだけ正しかったかの結果を表示する。

[データ作成]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import random

# BMIを算出し、体型を3パターンで返す
def calc_bmi(height, weight):
bmi = weight / (height / 100) ** 2
if bmi < 18.5:
return '痩せ'
elif bmi < 25:
return '普通'
else:
return '肥満'

# データ作成 ← 手順①
lst_label = []
lst_height_weight = []
for i in range(10000):
height = random.randint(100, 200) # 100cm~200cmの身長を生成
weight = random.randint(30, 100) # 30kg~60kgの体重を生成
label = calc_bmi(height, weight)

lst_height_weight.append([height, weight])
lst_label.append(label)

[SVMを使っての学習と予測]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from sklearn import model_selection, svm, metrics
import matplotlib.pyplot as plt
import pandas as pd

# 学習データとテストデータに分ける ← 手順②
# テストデータの割合はtest_sizeで指定(0.0~1.0)
data_train, data_test, label_train, label_test = \
model_selection.train_test_split(lst_height_weight, lst_label, test_size=0.2)

# データを学習 ← 手順③
clf = svm.SVC()
clf.fit(data_train, label_train)

# データを予測 ← 手順④
predict = clf.predict(data_test)

[結果表示]

1
2
3
# 結果確認 ← 手順⑤
print('正解率=', metrics.accuracy_score(label_test, predict))
print('レポート=\n', metrics.classification_report(label_test, predict))

[出力結果]

1
2
3
4
5
6
7
8
9
10
11
正解率= 0.994
レポート=
precision recall f1-score support

普通 0.99 0.98 0.98 391
痩せ 0.99 1.00 0.99 430
肥満 1.00 1.00 1.00 1179

accuracy 0.99 2000
macro avg 0.99 0.99 0.99 2000
weighted avg 0.99 0.99 0.99 2000

正解率は99.4%と十分に納得いく結果となりました。
レポートの見方は下記の通りです。

名称 内容
precision 予測が正だった中で、予測通り正答分類できた割合
recall 実際に正だった中で、予測も正答だった割合
f1-score precisionとrecallの調和平均
support データ数

(Google Colaboratoryで動作確認しています。)

クロスバリデーション(交差検証)

分類の検証を行う場合に、データ全体を何分割かして分割した回数分検証を行う方法です。
例えば5分割の場合、学習データを8割、検証データを2割に分割して検証し、さらに検証データをかえて実行・・・・といった感じに5回検証を行います。

[アヤメのデータをダウンロード]

1
!wget https://raw.githubusercontent.com/pandas-dev/pandas/master/pandas/tests/data/iris.csv

[5分割でクロスバリデーション実行]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import pandas as pd
from sklearn import svm, metrics, model_selection

# アヤメデータを読み込む
csv = pd.read_csv('iris.csv')

# データとラベルに分割
data = csv[['SepalLength', 'SepalWidth', 'PetalLength', 'PetalWidth']]
label = csv['Name']

# クロスバリデーション(交差検証)を行う
clf = svm.SVC()
score = model_selection.cross_val_score(clf, data, label, cv=5) # cv=5は5分割の意
print('各正解率', score)
print('正解率', score.mean())

[出力結果]

1
2
各正解率 [0.96666667 1.         0.96666667 0.96666667 1.        ]
正解率 0.9800000000000001

5回分の検証結果が96%~100%、平均正解率も98%以上なので十分実用性がある・・・ということになると思います。。

(Google Colaboratoryで動作確認しています。)


Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×