実践型AIプログラミング特講 #11

実践型AIプログラミング特講 #11

本A Iシリーズもおかげさまでとうとう十一回を迎えることができました。ご愛読いただいている方々に感謝いたします。では今回はpythonのAIパッケージを用いてサンプルプログラムでよく耳にすることもあるであろうワイン判定アルゴリズムの構築を実践を通して皆様にご紹介いたします。

AIで美味しいワインを判定しよう

ワインは本当に美味しいものですが、その美味しさはワインの成分を調べることで判別できると言われています。そこで、機械学習を利用して、ワインの成分データからグレードを判別するプログラムを作ってみましょう。

ワインの品質を機械学習で分析しよう

以前より、降水量や気温などの情報から、その年のワインの品質を予測できると言われていました。しかし、ワインの成分を分析すれば、より的確にワインの品質を予測することができます。本節では、ワインの成分を元にして、ワインの品質を予測してみます。ワインを題材にして機械学習を実践しましょう。

ワインデータをダウンロードしよう

それでは、今回利用するワインデータをダウンロードしてみましょう。機械学習の練習で使えるたくさんのサンプルが「UCI Machine Learning Repository(機械学習リポジトリー)」で公開されています。ワインの品質データもそこに登録されています。

UCI 機械学習リポジトリーのワインの品質データ

UCI Machine Learning Repository > Wine Quality Data Set[URL] https://archive.ics.uci.edu/ml/datasets/wine+quality

このワインの品質データには、白ワインと赤ワインの2種類があります。今回は、白ワインを対象にしてみたいと思います。Jupyter Notebook を利用して、白ワインデータをダウンロードしてみましょう。Jupyter Notebook を起動したら、新規ノートブックを作成し、以下のプログラムを記入して実行します。このプログラムを実行すると、ワインデータをダウンロードします。

from urllib.request import urlretrieve

“https://archive.ics.uci.edu” + \url”/ml/machine-learning-databases/wine-quality” +/winequality-white.csv”

savepath = “winequality-white.csv”

urlretrieve(url, savepath)

無事ダウンロードが完了したら、Jupyter Notebook のファイル一覧に、「winequality-white.csv」という名前のファイルが表示されます(ファイル一覧をリロードするには、画面右上の更新ボタンを押すか、ブラウザーでページをリロードしましょう)。ダウンロードできると、CSVファイルが表示されます。

ワインデータを読み込んでみよう

Jupyter Notebook で下記のように記述して、実行してみましょう。少し変わった形式の CSVですが、Pandas を使えば、カンマ「」以外の区切り記号を持った CSVファイルも楽々読み込むことができます。

import pandas as pd

df = pd.read_csv(“winequality-white.csv”, sep=”;”, encoding=”utf-8″)

セミコロン「」のように、カンマ以外の区切り文字を持つCSV ファイルを読み込む場合、read_csv0)の引数に、sep=”,”のようなパラメーターを指定します。

ワインデータの内容について

ワインデータの説明によれば、このワインデータは、11種類のワインの成分データに続いて、12番目(末尾)がワイン専門家によるワインの品質データとなっています。ワイン専門家による品質評価は、3回以上の評価を行い、その中央値を採用したものです。そして、その品質データ評価ですが、0がもっとも悪く、数値が上がるごとに評価が高くなり 10が最良です。

ワインの品質を判定してみよう

機械学習の基本手順に沿ってプログラムを作ってみましょう。機械学習では、データを学習用とテスト用に分割し、学習用データでモデルを訓練し、テストデータでモデルを評価するという手順で行います。

ワイン判定のためのアルゴリズムを決定しよう

ここでは、ランダムフォレストというアルゴリズムを利用して機械学習をしてみます。どのようにして、アルゴリズムを選定できるでしょうか。今回は、アンサンブル学習より、ランダムフォレストを選んでみました。

ワインの品質判定を行うプログラム

以下は、ワインデータを読み込んで、ワイン成分からどの程度、品質を判定できるかを確かめるプログラムです。

import pandas as pd

from sklearn.model_selection import train_test_split

from sklearn.ensemble import RandomForestClassifier

from sklearn.metrics import accuracy_score

from sklearn.metrics import classification_report

# データを読み込む

wine =pd.read_csv(“winequality-white.csv”, sep=”;”, encoding=”utf-8″)

# データをラベルとデータに分離*1

y = wine [“quality”]x=wine.drop(“quality”, axis=1)

# 学習用とテスト用に分割する*2

x_train, x_test, y_train, y_test =train_test_split(x, y, test_size=0.2)

# 学習する*3

model = RandomForestClassifier ()model.fit(x_train, y-train)

# 評価する*4

y-pred =model.predict (x_test)

print (classification_report (y_test, y_pred))

print (” EM =”, accuracy_score(y_test, y-pred))

プログラムを実行するには、Jupyter Notebook のセルに上記のプログラムを貼り付けて実行します。すると、以下のような値が表示されます。

正解率= 0.6673469387755102

これは、ワインの品質分類の精度を表す値です。実行するたびに値は異なりますが、だいたい、061(619%) から 0.68(68%) までの値が表示されます。それにしても、なぜデータの実行結果が異なるのでしょうか。それは、データを学習用とテスト用にランダムに分割するために、どのデータを学習したかによって、多少の誤差が生じるからです。それでは、プログラムを確認してみましょう。プログラムの(※1)の部分では、読み込んだワインのデータをラベル部分(目的変数)とデータ部分(説明変数)に分離します。ここでは、ワイン専門家による評価(quality)がラベルに相当し、11種類のワイン成分がデータに相当します。Pandas のDataFrame では、drop() メソッドを使うと任意のデータを削除できるので便利です。(※2)の部分では、データを学習用とテスト用に分割します。データをすべて学習し、そのデータ(アストするなら、正しい精度を得ることはできません。必ず、学習用とテスト用でデータを分けておく必要があります。その際、train_test_split() メソッドを使うと、手軽に学習用とテスト用を分割できて便利です。(※3)の部分では、RandomForestClassifier を利用してクラス分けを行う分類器を作成します。そし(、fht メソッドで学習用データを学習します。(※4)の部分では、テストデータを用いて予測を行って、実際の正解ラベルと比べてスコアを計算し結果を画面に出力します。ここで、accuracy_score()関数を使っていますが、それが正解ラベルと予測結果のラベルを比較して正解率を求める機能を提供しています。先ほども紹介した通り、ここでは、0.65前後の値が表示されるはずです。また、classification_report() 関数を利用することで、各分類ラベルごとのレポートも表示します。ここで出力される値は、各ラベル(ワインの品質)への分類がどの程度正確に行われたかを表すものです。precision が精度(適合率)、recall が再現率、f1-score が精度と再現率の調和平均で、support が正解ラベルのデータの数です。precision (精度)は正と予測したデータのうち実際に正であるものの割合で、recall (再現率)は実際に正であるもののうち正であると予測されたものの割合、つまり、実際に正解した割合です。加えて下には、accuracy、macro avg、weighted avg が表示されています。これは、accuracy が正解率、macro avg が算術平均(マクロ平均)、weighted avg が加重平均(Support のデータ数で重み付けされた平均)を意味しています。

精度向上を目指そう

ところで、0.667(約67%)程度の正解率では、あまり精度が高いとは言えません。そこでもう少し、今回のワインデータの精度向上を目指しましょう。加えて、classification_reportの実行結果にTUndefinedMetricWarning(未定義メトリックの警告)が表示されます。これは、すべてのラベルにデータが分類されていないことを表しています。そこで、今回のデータについて、改めて確認してみましょう。このワインデータは、ワインの品質を0から 10までの11段階に分類するというものでした。しかし、ワインデータの説明を見てみると、1段階のワインがそれぞれ同数あるというわけではなさそうです。それでは、各品質(quality)のデータがいくつずつあるのか調べてみましょう。

import matplotlib.py plot as plt

import pandas as pd

# ワインデータの読み込み

wine =pd.read_csv(“winequality-white.csv”, sep=”;”, encoding=”utf-8″)

# 品質データこでとにグループ分けして、その数を数える

count_data = wine.groupby(‘quality’) [“quality”].count ()

print (count_data)

# 数えたデータをグラフに描画

count_data. plot ()

plt.savefig(“wine-count-plt.png”)

plt.show ()

Jupyter Notebook で実行してみましょう。このプログラムでは、データをよりわかりやすくするために、視覚化しています。count_data.plot()と書くと、データ数の分布をグラフに描画します。そして、その後の plt.savefig() は、表示したグラフをファイルに保存します。このプログラムを見るとわかりますが、Pandas モジュールは、保持しているデータをグラフにプロットするのが非常に簡単です。また、groupby メソッドを使うと、データをまとめて集計できます。次に、実行結果に注目してみましょう。このワインデータの品質の大半は5から7であり、その他のデータは、わずかであることがわかります。また、2以下と 10は存在すらしていないということもわかりました。このように、データ数の分布数の差があるデータを「不均衡データ」と呼びます。そこで、11段階のデータを、4以下、5-7、8以上と、ラベルを3段階 (0, 1, 2) に分けてみます。上記のプログラムで、(※2)の処理以前の部分に、次のコードを追加してみましょう。

import pandas as pd

from sklearn.model_selection import train_test_split

from sklearn.ensemble import RandomForestClassifier

from sklearn.metrics import accuracy_score

from sklearn.metrics import classification_report

# データを読み込む*1

wine = pd.read_csv(“winequality-white.csv”, sep=”;”, encoding=”utf-8″)

# データをラベルとデータに分離

y = wine [“quality”]x = wine.drop(“quality”, axis=1)

# yのラベルをつけ直す*2

newlist=[]

for v in list (y):

if v <= 4:

newlist += [0]

elif v <= 7:

newlist += [1]

else:

newlist += [2]

y = newlist

# 学習用とテスト用に分割する*3

x_train, x_test, y_train, y_test = train_test_split (x, y, test_size=0.2)

# 学習する*4

model = RandomForestClassifier ()model.fit(x_train, y_train)

# 評価する*5

y-pred= model.predict (x_test)

print (classification_report(y_test, y_pred))

print (” E =”, accuracy_score(y_test, y_pred))

このプログラムを、Jupyter Notebook に記述して実行してみましょう。

正解率= 0.9459183673469388

どうでしょうか。0.945..(約 95%)と、正解率をぐっと向上させることができました!プログラムを確認してみましょう。 (※1)の部分で、Pandas を利用してデータを読み込みます。 そして、データをラベルとデータに分離します。(※2)の部分で、ラベルデータの分類を変更します。そして、(※3)の部分でデータを学習用とテスト用に分割し、(※ 4) の部分で、 RandomForestClassifer を利用してデータを学習します。(※5)の部分では、predict() メソッドでテストデータを評価し、 結果を表示します。

機械学習の奥深いところ

今回のワイン分類では、 データの分布グラフを確認しつつ、 ラベルを3段階につけ直してみました。ラベルに名前をつけるとしたら、「0:品質の悪いワイン」 「1:普通のワイン」 「2: 極上のワイン」と考えることができるでしょう。 もちろん、 どのような目的で機械学習のシステムを構築するのかにもよりますが、元のデータに少し手を加えることで、 精度をぐっと向上させることができます。scikit-learn では、手軽にアルゴリズムを変えたり、 パラメーターをチューニングできます。 しかし、最初のプログラム 「wine_simple.py」 のアルゴリズムを SVMに変更したりしても、それほど精度を向上させることはできませんでした。 そこで、 少し視点を変えて、 学習前のデータに手を加えてみました。 それにより、ぐっと精度を向上させることができました。大量のデータを投入することで、 より望ましい答えを出す機械学習ですが、 やはり魔法の箱ではありません。どんなデータをどのように分類しようとしているのかを調べて、 データを変形整形してみると、 精度を向上させることができます。

応用のヒント

ここでは、ワインの品質分類に挑戦してみましたが、何かしらの成分から製品の品質を自動でチェックするという場面は意外に多いと思います。正常なデータと異常データを用意できれば、機械学習によって、自動で製品の異常を検知することが可能になります。

Column

機械学習アルゴリズム「ランダムフォレスト」について「ランダムフォレスト (random forests)」とは、複数の分類木を用いて性能を向上させるアンサンブル学習法の1つです。精度が良いため、機械学習でよく使われるアルゴリズムです。そもそも、ランダムフォレストは、2001年に Leo Breiman によって提案された機械学習のアルゴリズムです。集団学習によって、高精度の分類、回帰、クラスタリングなどを実現します。これは、学習用のデータをサンプリングして多数の決定木を作成し、作成した決定木をもとに多数決で結果を決める手法です。また、「ランダムフォレスト」という名前の由来ですが、学習用の多数の決定木を作成することに由来しています。ちなみに、決定木というのは、ツリー構造のグラフであり、予測·分類を行う機械学習のアルゴリズムです。これは精度の低い学習器である弱学習器に分類されています。ですが、集団学習(アンサンブル学習)させることで、決定木の精度を高めることができます。

ランダムフォレストの構造

ランダムフォレストは処理も高速で、また分類精度も良いことから、機械学習でよく使われます。scikit-learn を使う場合、RandomForestClassifier を指定します。

この節のまとめ

ワインの品質データなど、ユニークな機械学習の練習問題が、UCI 機械学習リポジトリーにたくさん登録されている

・ランダムフォレストを利用してワインの品質分類に挑戦した

・機械学習で分類精度を向上させるためには、アルゴリズムを変えてみたり、元データの特性に注目して、データを変形してみることもできる

 

いかがでしたでしょうか。少し発展的な内容も盛り込まれているので初学者には少しハードルが高たったかもしれません。余談になりますが、学習というものは常に自分のスキルより少し上のもの理解しようとすることでモチベーションが生まれ学習効率が上がる学術的データがあるそうです。少し難しくてもトライする習慣が身につけば今後の学習プロセスを最適化する自分なりの学習方法が見つけられるかもしれませんね。逐一申し上げますがプログラミングは地道な一つ一つの積み重ねが大切です。是非気負わず自分のペースでゆっくり学習を継続していただけたら幸いです。

次の記事のリンクはこちら

プログラミングカテゴリの最新記事