[Kaggle]Santander Customer Transaction Prediction（その２）

#Santander Customer Transaction Prediction に挑戦してみた。（その２）
この記事は「Santander Customer Transaction Prediction に挑戦してみた。（その１）」の続きです。

- [Santander Customer Transaction Prediction に挑戦してみた。（その１)](https://qiita.com/pappapa/items/aaddde9c731a154c512b)
- [Santander Customer Transaction Prediction に挑戦してみた。（その３)](https://qiita.com/pappapa/items/683ed1cc648267a3da69)

##（５）正規化
###平均０・標準偏差１に正規化
今回は「平均０・標準偏差１」となるように正規化しました。
**（テストデータは訓練データを使って正規化されています。テストデータを使って計算された値は使用するべきではありません。）**

```python:5-1
#正規化
stdsc = StandardScaler()
x_train_ss = stdsc.fit_transform(x_train)#訓練データを正規化

#テストデータは、訓練データを使って正規化
train_mean = np.mean(x_train, axis=0)#訓練データの平均
train_std = np.std(x_train, axis=0)#訓練データの標準偏差

y_train_ss = (y_train - train_mean) / train_std#テストデータを正規化
```

##（６）検証開始
###モデル作成
様々なモデルを作り検証しここにたどり着きました。（後ほど、学習率の修正やコールバックを組み込む）
何割訓練データとして使うのかや、使うデータを簡単に変えられるように組んであります。

```python:6-1
now_list = high_feature_list + medium_feature_list#使うデータ
print(len(now_list))

x_train_in_model = x_train_ss[:, now_list]#モデルに入れる訓練データ
y_train_in_model = y_train_ss[:, now_list]#モデルに入れるテストデータ

percent_train = 80#訓練データに使う割合（残りは検証データ）[%]
train_num = round(200000*(percent_train/100))#訓練データに使うデータ数（残りは検証データ）

par_train = x_train_in_model[:train_num, :]
par_targets = train_targets[:train_num]
val_train = x_train_in_model[train_num:, :]
val_targets = train_targets[train_num:]

b_size = 1024#色々変更してみる
epoch = 12#色々変更してみる


model = Sequential()
#層の数や変数の数は調整
model.add(Dense(64, input_shape = (len(now_list), ), activation = "relu"))
model.add(Dense(32, activation = "relu"))
#model.add(Dropout(0.5))#過学習を抑えることができる
model.add(Dense(32, activation = "relu"))
#model.add(Dropout(0.5))
model.add(Dense(1, activation = "sigmoid"))

#学習率は後ほど・・・
model.compile(optimizer = optimizers.Adam(), loss = "binary_crossentropy", metrics = ["acc"])

history = model.fit(par_train, par_targets, 
                    epochs = epoch, 
                    batch_size = b_size, 
                    validation_data = (val_train, val_targets))
```

###検証結果をグラフにする
下記のコードを実行するとグラフが現れます。この後、学習率の調整を行いますが、上のモデルのハイパラメータを調整することで、そこそこの結果は得られました。

```python:6-2
plt.plot(range(len(history.history["acc"])), history.history["acc"], color = "red", label="acc")
plt.plot(range(len(history.history["val_acc"])), history.history["val_acc"], color = "blue", label="val_acc")
plt.legend()
plt.grid(True)
plt.show()

plt.plot(range(len(history.history["loss"])), history.history["loss"], color = "red", label="loss")
plt.plot(range(len(history.history["val_loss"])), history.history["val_loss"], color = "blue", label="val_loss")
plt.legend()
plt.grid(True)
plt.show()
```

##（７）学習率
###最適な学習率を探す
[参考にした記事はこちら](https://qiita.com/keng000/items/c50794fb7f029062bd0d)

```python:7-1
now_list = high_feature_list + medium_feature_list
print(len(now_list))

x_train_in_model = x_train_ss[:, now_list]#モデルに入れる訓練データ
y_train_in_model = y_train_ss[:, now_list]#モデルに入れるテストデータ

percent_train = 80#訓練データに使う割合（残りは検証データ）[%]
train_num = round(200000*(percent_train/100))#訓練データに使うデータ数（残りは検証データ）

par_train = x_train_in_model[:train_num, :]
par_targets = train_targets[:train_num]
val_train = x_train_in_model[train_num:, :]
val_targets = train_targets[train_num:]

b_size = 512
epoch = 80

lr_loss_list = []#それぞれの学習率に対して、"loss"を記録する
lr_list = [10**x for x in range(-7, 0)]#学習率のリスト

for i in lr_list:
    print("学習率「"+str(i)+"」の検証開始")
    model = Sequential()
    model.add(Dense(16, input_shape = (len(now_list), ), activation = "relu"))
    model.add(Dense(8, activation = "relu"))
    model.add(Dense(4, activation = "relu"))
    model.add(Dense(1, activation = "sigmoid"))

    model.compile(optimizer = optimizers.Adam(lr = i), loss = "binary_crossentropy", metrics = ["acc"])

    history = model.fit(par_train, par_targets, epochs = epoch, batch_size = b_size, validation_data = (val_train, val_targets), verbose = 0)

    lr_loss_list.append(history.history["loss"])
    print("学習率「"+str(i)+"」の検証終了")
```
###グラフに示す

```python:7-2
#学習率を調査

mean_loss_lr = [np.mean(x) for x in lr_loss_list]
print(len(mean_loss_lr))

plt.plot(lr_list, mean_loss_lr)
plt.xscale('log')#対数軸にする
plt.xlabel("lr")
plt.ylabel("loss")
plt.grid(True)
plt.show()
```

![スクリーンショット 2019-06-07 午後14.23.56 午後.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/427946/71a77cc2-9126-5547-1580-98022e3f7cb7.png)
参考にした記事によると、"loss"が最小になっている時の学習率を採用するのではないとのことです。今回、初めて学習率の設定を試みてみましたが、いくつに設定していいかわからなかったのでとても参考になりました。
本で勉強していたときは、学習率を0.001にとっている場合が多かった印象ですが、今回はそれよりも小さな値がいいようです。

続きはこちらから
[Santander Customer Transaction Prediction に挑戦してみた。（その３)](https://qiita.com/pappapa/items/683ed1cc648267a3da69)