AIプログラミング(Pythonサンプル):工数見積りする学習・予測プログラムを自作してみた【ラズパイ・機械学習・ディープラーニング】 | 9が好きな人のブログ
自作の拙作AIですが使えそうでしょうかね?(苦笑)
今回は、サンプルプログラムのあるポイントについて、補足説明します。これは地味に重要なポイントで、ちょっと苦労した点でもあります。
それは「データ前処理・標準化」です。
データ前処理とは
AI(ディープラーニング)などの機械学習においては、学習データに対して予め「前処理」というものがしばしば行われます。前処理とは、何らかの方法で、学習データ(説明変数、目的変数)の値を、機械学習上の計算で扱いやすいように変形しておくことです。前処理で代表的なのが、学習データの値の範囲(スケール)を小さくしておくことです。
身長[cm]などでいえば、
[160,165,170,175,180]
のようなデータが5つあったとき、これらを最大値の180で割り算して
[0.888888889,0.916666667,0.944444444,0.972222222,1.0]
のように、1.0以下の値に収めるようなことです。
AIの学習データ(説明変数、目的変数)に対し、これを行うことで、以下の効果が得られ、学習スピードが向上します。
・説明変数の値が小さくなることで、ニューラルネットワークの重み更新の振れ幅が抑えられ、重みが収束しやすくなる
・目的変数の値が小さくなることで、損失関数の値も小さくなり、誤差が収束しやすくなる
たとえていえば、プラモデルがいい例かもしれません。現物そのままのサイズで、プラモを作ったり修繕しようとするのはとても大変で、手間も時間もコストもすごくかかります。
実際に1/1スケールのガンプラなど出回ってませんよねw(お台場のガンダムくらい?)出回っているプラモデルは、扱いやすいよう100分の1程度のスケールに小さくされています。AIの学習データの前処理を行う目的もそれと似たような理由です。
データの標準化とは
さて、前処理の手法としてよく用いられるのがデータの「正規化」とよばれるものです。正規化とは、計算・解析において扱いやすいように、データをある規則に従って整形することをいいます。例えば、画像認識AIにおいては、学習データに使用する画素値を最大値(255)で割っておくことで、データ値を[0,1]の範囲に収めるという手法が用いられます。正規化の手法の中でも、特に以下のような特性を持つデータセットに変形することを「標準化」といいます。
・平均値=0
・標準偏差=1
標準偏差など、いきなり数学的な用語が出てきましたが、これらは統計学で使用される重要な概念です。また、上記の特性を満たすものは、「正規分布」と呼ばれる自然界でよくみられる形のデータ群です。
これらの概念については、以下のサイトなどが参考になります。
14-3. 標準化したデータの使い方 | 統計学の時間 | 統計WEB
6-2. データを標準化してみよう | 統計学の時間 | 統計WEB
標準化の計算は、それほど複雑ではありません。
・データ値:x
・データセットの平均値:u
・データセットの標準偏差:σ
・標準化データ値:X
とすると、以下の式で定義されます。
X = (x-u)/σ
試しに先ほどの身長のデータセット [160,165,170,175,180] に対し、標準化を行ってみると以下のようになります。
[-1.414213562, -0.707106781, 0, 0.707106781, 1.414213562]
かなり小さい値になりましたね。
AIにおけるデータ標準化のメリットの一つは、データのスケールを小さくして、学習速度を上げることです。それ以外にも、スケールの異なる複数の説明変数(身長、体重など)を正規化する場合にも使用されます。各説明変数間のスケールが大きく異なる場合、スケールの大きい変数が学習に影響を与えてしまうため、標準化を用いてこれを是正できます。
機械学習における標準化の目的、メリットについては、以下のサイトなども参考になります。
Feature Scalingはなぜ必要? - Qiita
以下のディープラーニング本でも正規化、標準化について言及されており、参考になります。
SBクリエイティブ (2018-08-28)
売り上げランキング: 76,394
売り上げランキング: 76,394
秀和システム (2019-06-05)
売り上げランキング: 169,082
売り上げランキング: 169,082
学習時の標準化
前回のAIサンプルプログラムにおいて、標準化によるデータ前処理は、学習プログラム、予測プログラム、プロットプログラムいずれにも実装されています。予測、プロットにおいては、標準化された出力データを、元のスケールに戻す標準化の逆変換も実装しています。サンプルプログラムは↓のGitHub上にあります。
https://github.com/kotetsu99/deep_regression
学習のサンプルコード「deep_regression_train.py」では、学習用のcsvファイル読み込んだ後、学習データセットの標準化を実装しています。データセット(ベクトル)の標準化はPythonの計算ライブラリである、scipyを使用することで、簡単に実装できます。
x = scipy.stats.zscore(x)
これを利用して、データセットの標準化を行っているのが以下のサブルーチンです。
66 def load_csv(csvfile): 67 # csvをロードし、変数に格納 68 df = pd.read_csv(csvfile) 69 dfv = df.values.astype(np.float64) 70 n_dfv = dfv.shape[1] 71 72 # 学習データをシャッフル 73 np.random.shuffle(dfv) 74 75 # 特徴量のセットを変数xに、ターゲットを変数yに格納 76 x = dfv[:, np.array(range(0, (n_dfv-1)))] 77 y = dfv[:, np.array([(n_dfv-1)])] 78 79 # データの標準化 80 x = scipy.stats.zscore(x) 81 y = scipy.stats.zscore(y) 82 83 return x, y
説明変数x(テスト項目数)、目的変数y(消化日数)をcsvから読み込み、1列目=x、2列目=yとなる行列を生成。これを行をランダムに入れ替えてシャッフルした後、x,yを別々のベクトルとして格納、最後にそれぞれに対して標準化処理を行っています。標準化処理自体は、scipyを使えば簡単にできます。
余談になりますが、学習データセットをシャッフルしているのは、モデルの学習に使用するデータに偏りを持たせないためです。モデルの学習には、KerasのModel クラスのfit関数を使用しています。
53 # モデルの学習 54 history = dnn_model.fit(X, y, epochs=nb_epochs, validation_split=0.1, batch_size=n _bs, verbose=2)
ここで学習に使うデータは最初の9割で、残りの1割は学習に使わずモデルの精度(損失関数の大きさ)を評価するデータとして使用されます。
validation_split=0.1
という設定がそれです。
学習データをシャッフルせずに学習させた場合、データセットの後尾部分(x:テスト項目数 が大きい値の箇所)が学習に使われないため、そのレンジに対する予測精度が落ちてしまいます。このため、学習データをシャッフルで対処しています。
# そもそも評価用にデータを割かないのであればシャッフルは不要ですが……
予測・プロット時の標準化および逆変換
予測のサンプルコード「deep_regression_predict.py」においては、標準化および標準化されたデータを元のスケールに戻す逆変換を実装しています。使用する学習済モデルは標準化された変数(x:テスト項目数)を、入力として使用します。このため予測プログラムに引数として渡すxに対し、標準化を行う必要があります。標準化に用いる、平均値と標準偏差ですが、これは学習データのものを用います。これを実施しているのが以下のサブルーチンです。
68 def input_normalization(X, x): 69 # 入力ベクトルの各要素値を、対応する学習データの各列ベクトルで標準化 70 n = X.shape[1] 71 for i in range(n): 72 t = x[:,i] 73 X[:,i] = (X[:,i] - t.mean()) / t.std() 74 return X
↑のサブルーチンを用いて、入力データ(テスト項目数)を標準化し、学習モデルに入力して予測値(消化日数)を得ます。
40 # 入力データ標準化 41 X = input_normalization(X, x) 42 43 # 予測結果の取得 44 result = dnn_model.predict_on_batch(X) 45 46 # 予測結果に対し標準化の逆変換 47 Y = result * y.std() + y.mean()
ここで予測に使用している学習済モデルは、学習時に標準化された正解値(消化日数)を用いて訓練しています。そのため出力「result」が標準化されたスケールで出てきます。
予測したいのは、標準化されたスケールの予測値(消化日数)ではないため、これを元のスケールに戻す必要があります。そのため、予測結果に対し標準化の逆変換を行います。これは標準化の式を変形すれば簡単に計算できます。
標準化の式;X = (x-u)/σ
逆変換の式:x = X*σ + u
・データ値:x
・データセットの平均値:u
・データセットの標準偏差:σ
・標準化データ値:X
平均値uと標準偏差σは、学習データ(消化日数)のものを用います。これにより、元のスケールで予測値を得ることができます。
プロットサンプルコード「deep_regression_plot.py」についても、標準化・逆変換処理の要領は、予測プログラムとほぼ同じです。標準化・逆変換処理をかける入力値・出力値がスカラーからベクトルに変わっただけですね。
AI(ディープラーニング)をはじめとする機械学習において、標準化等の正規化によるデータ前処理は頻繁に利用されます。その実装方法について、本記事が参考になれば幸いです。