はじめに
最近、大学の演習でpythonを使ってニューラルネットワークを実装し、それを使用して好きなデータセットの分類を行うといったことをしました(というかさせられた...?)。
その演習では、最終的に、その分類した結果や過程をプレゼンで発表しないといけないので、ある程度良い結果を出したいという願望がありました。
ただ、ニューラルネットワークは演習で実装しており、そこはほとんどいじれなかったです。
なので、他の箇所を工夫しようと色々考えた結果、データ前処理の段階で標準化をしてみようという結論に至りました。そして、それを実装したので今回の記事で紹介したいと思います。
標準化
そもそも標準化とは何かというのは、自分が作った以下のスライドを見てください。
標準化の式は
で表されます。
データ
データ自体はWnie_Qualityというデータを使用しています。
https://archive.ics.uci.edu/ml/datasets/Wine+Quality
このデータはワインの質を、11個の成分から判定するといったものです。
なので、11個(ワインの成分) + 1 個(ワインの質)の12個のカテゴリからこのデータは成り立っています。
ちなみに11個(ワインの成分)を説明変数、1 個(ワインの質)を目的変数とします。
実装(間違った方法)
標準化自体は簡単なので直ぐにできるのですが、問題はデータのどの部分を標準化するのかということです。自分は最初渡されたデータの説明変数をそのまま上の式にぶち込んでました。
大体こんな感じに。
mean_vals = np.mean(xData, axis=0)
std_val = np.std(xData)
xData_cent = (xData - mean_vals) / std_val
xDataは説明変数で、Numpyのarrayで用意しています。
そうすると、上のスライドのグラフのように学習が安定したのでやったねと思ったので発表したら、その方法は厳密には正しくないと先生に指摘されました。
実装(正しい方法)
正しい方法は説明変数そのものを標準化する(1枚目の画像)のではなく、説明変数の各カテゴリごとに標準化する(2枚目の画像)といった方法です。
実装はこんな感じです。
for i in range(xData.shape[1]): mean_vals = np.mean(xData[:,i], axis=0) std_val = np.std(xData[:,i]) xData_cent = ((xData[:,0] - mean_vals) / std_val) xData_cent_list.append(xData_cent) xData_cent_list = np.array(xData_cent_list).reshape([xData.shape[0],xData.shape[1]])
先ほどと同じようにxDataは説明変数です。xDataは1列が1カテゴリに対応しているので、各カテゴリごとに標準化しようと思ったら
- ある1列を抽出
- その抽出した列に標準化を施す
この手順を繰り返し、最終的にそれらを結合してあげればできます。
上のプログラムは今説明したことを処理しているだけです。
結果
実際に間違った方法と正しい方法の両方を実行した結果は以下の画像のようになりました。
ちょっと見にくいかもしれませんが、左が間違った方法、右が正しい方法です。
左の方はAcuuracyが暴走している(?)のに対し、右の方はある程度安定しているのがわかるかと思います。
最後に
今回は標準化といった、データの前処理でよく施される手法について説明しました。
今後というか2019年はデータの前処理についてだけでなく、機械学習について勉強したことを記事にしていきたいなと思います。