どハマりした内容
scikit-learnに実装されている多層パーセプトロン(MLPClassifer)で予測した内容と、あらかじめ学習して取得していた重み、バイアス行列を使った自作のニューラルネットーワクの予測が全く合わなかった。
先に結論
入力データの標準化をしていなかった...
どハマりした経緯
- 学習モデルの構築にPipelineを使って標準化、トレーニング、テスト(汎化性能)のチェックをしていた。
- 最終的な重みとバイアスだけで、標準化をしていないデータにも対応できると勝手に思い込んでいた(恥)
おまけ:MLPClassifierで取得した重み、バイアスでニューラルネットワークを構築
import numpy as np
import os
import sys
import pandas as pd # dataFrameを扱うライブラリ
from math import exp, expm1
input = [[入力データの配列]]
input = np.array(input)
df = pd.read_csv("入力データの標準化に使うデータ(学習させた時のデータ)")
df_x = pd.get_dummies(ダミー変数を生成したい列)
# 標準化!(ここを忘れていた)
sc = StandardScaler()
sc.fit_transform(df_x)
input = sc.transform(input)
bias0 = pd.read_csv("MLPClassieferから出力されたバイアスcsv", header=None)
bias0 = bias0.iloc[1:,1:].as_matrix()
weight0 = pd.read_csv("MLPClassieferから出力された重みcsv", header=None)
weight0 = weight0.iloc[1:,1:].as_matrix()
# 重み・入力 + バイアス
layer0 = np.dot(weight0.T, dummy.T) + bias0
# 隠れ層の活性化。今回はランプ関数で活性化した。
layer0 = np.clip(layer0, 0, np.finfo(layer0.dtype).max, out=layer0)
隠れ層だけ、入力と重みの線形結合を活性化関数に流して。。。
最後の出力層では、シグモイド関数で活性化
output_layer = np.dot(最後の隠れ層の重み, 最後の隠れ層に入るデータ) + 最後の隠れ層のバイアス
# シグモイド関数で活性化
1 / (1 + exp(-output_layer[0, 0]))
ここで[0, 0]になっているのは、2値問題を扱っているからだと思います。