この記事では、ワインのデータ(アルコール度数、pH、酸性度…)を学習して品質を判定するコードを書いてみたいと思います。
「機械学習の使い方を学びたい」
「Pythonで機械学習のコードを書いてみたい」
そんな方に読んでいただければと思います。
目次
使用するデータ
UCI Machine Learning Repositoryという機械学習向けデータセットを無料で公開しているサイトがあります。
このサイトの白ワインのデータセット(winequality-white.csv)を使ってみます。
https://archive.ics.uci.edu/ml/machine-learning-databases/wine-quality/
CSVのカラムをみてみましょう。
import pandas as pd df = pd.read_csv("data/winequality-white.csv",sep=";",encoding="utf-8") print(df.columns)
Index(['fixed acidity', 'volatile acidity', 'citric acid', 'residual sugar', 'chlorides', 'free sulfur dioxide', 'total sulfur dioxide', 'density', 'pH', 'sulphates', 'alcohol', 'quality'], dtype='object')
酸性度(fixed acidity)や揮発性酸度(volatile acidity)などのワインのデータが11個あり、最後のカラムに品質(quality)があることが分かります。
品質は0〜10で評価されており、数字が高いほど良いです。
SVM(サポートベクターマシン)を使う
まずは、データのクラス分類に有効なSVMのLinearSVCを使ってみます。
コードの流れは以下の通り。
- pandasでデータを読み込み、データとラベルに分割する。
- 訓練用とテスト用にデータを分ける
- 学習する
- 予測する
from sklearn.model_selection import train_test_split from sklearn import datasets,svm,metrics from sklearn.metrics import accuracy_score import pandas as pd df = pd.read_csv("data/winequality-white.csv",sep=";",encoding="utf-8") y = df['quality'] x = df.drop(columns='quality') # データを学習用とテスト用に分割する x_train,x_test,y_train,y_test = train_test_split(x,y,test_size=0.2) # データを学習 clf = svm.LinearSVC() clf.fit(x_train, y_train) # 予測して精度を確認する y_pred = clf.predict(x_test) print(accuracy_score(y_test, y_pred))
0.36428571428571427
あまり精度はよくありませんね。
ランダムフォレストを使う
では、複数の分類器を使って精度を向上させるランダムフォレスト(Random Forests)という手法を使ってみます。
コードの流れは全く同じで、学習器の指定の部分だけ違っています。
from sklearn.model_selection import train_test_split from sklearn import metrics from sklearn.ensemble import RandomForestClassifier from sklearn.metrics import accuracy_score,classification_report import pandas as pd df = pd.read_csv("data/winequality-white.csv",sep=";",encoding="utf-8") y = df['quality'] x = df.drop(columns='quality') # データを学習用とテスト用に分割する x_train,x_test,y_train,y_test = train_test_split(x,y,test_size=0.2) # データを学習 clf = RandomForestClassifier() clf.fit(x_train, y_train) # 予測して精度を確認する y_pred = clf.predict(x_test) print(accuracy_score(y_test, y_pred))
0.6428571428571429 /home/matsu/anaconda3/envs/digits/lib/python3.6/site-packages/sklearn/metrics/classification.py:1135: UndefinedMetricWarning: Precision and F-score are ill-defined and being set to 0.0 in labels with no predicted samples.'precision', 'predicted', average, warn_for)
精度は大幅に改善したようです。さすがランダムフォレスト。
ただし、よく見るとワーニング「UndefinedMetricWarning」が出ています。これは全てのラベルにデータが分類されていないという意味です。
pandasのgroupbyを使って、それぞれの品質(quality)の数を数えてみます。
import pandas as pd df = pd.read_csv("data/winequality-white.csv",sep=";",encoding="utf-8") count_data = df.groupby('quality')['quality'].count() print(count_data)
quality 3 20 4 163 5 1457 6 2198 7 880 8 175 9 5
11段階の評価と言いつつ、3から9しかありませんしデータが偏っています。これを不均衡データと言います。
ラベルを振り直す
ラベルを3つにして再度学習してみます。品質が4以下は0(悪い)、5〜7は1(普通)、8以上は2(良い)とラベルを振り直してみます。
import pandas as pd df = pd.read_csv("data/winequality-white.csv",sep=";",encoding="utf-8") y = df['quality'] new_y = [] for d in y: if d <= 4: new_y.append(0) elif d <= 7: new_y.append(1) elif d <= 9: new_y.append(2)
新しいラベルデータ(new_y)を使って、以下のように学習、判定してみます。
# データを学習用とテスト用に分割する x_train,x_test,y_train,y_test = train_test_split(x,new_y,test_size=0.2) # データを学習 clf = RandomForestClassifier() clf.fit(x_train, y_train) # 予測して精度を確認する y_pred = clf.predict(x_test) print(accuracy_score(y_test, y_pred))
0.926530612244898
かなり精度が向上しました。
学習アルゴリズムやパラメータを変更する方法の他に、ラベルを振り直す方法を学びました。かなり有効なので、覚えておきたいですね。