正解データは0~9の数字10個なのでランダムに選択すると、正解率は10%になります。
つまり全く学習していないモデルであると言えます。
実際こちらでモデルを作成しても正解率は10%程度でした。
これはデータが正規化されていないことによってネットワークが学習できないことが原因です。
mnistのデータにはグレースケールされた0255の範囲でデータ登録されています。
今回の場合、outputは10次元のone-hotベクトルで回答を得ようとしています。
この2つの値は01の値と0~255の値というように範囲が大きく異なます。
python
1from keras.datasets import mnist
2import numpy as np
3from keras.utils import to_categorical
4
5(x_train, t_train), (x_test, t_test) = mnist.load_data()
6
7t_train = to_categorical(t_train)
8
9print("min: %d , max: %d , mean %f ." % (np.min(x_train),np.max(x_train),np.mean(x_train)))
10print("min: %d , max: %d , mean %f ." % (np.min(t_train),np.max(t_train),np.mean(t_train)))
11
12// min: 0 , max: 255 , mean 33.318421 .
13// min: 0 , max: 1 , mean 0.100000 .
このような場合に学習が上手くいくことは少ないです。
そのためmnistのinputのデータを255で割り0~1の範囲に収まるように加工(正規化)してあげます。
python
1from keras.datasets import mnist
2import numpy as np
3from keras.utils import to_categorical
4
5(x_train, t_train), (x_test, t_test) = mnist.load_data()
6
7x_train = x_train.reshape((60000,784))
8x_train = x_train.astype('float32') / 255
9
10t_train = to_categorical(t_train)
11
12print("min: %d , max: %d , mean %f ." % (np.min(x_train),np.max(x_train),np.mean(x_train)))
13print("min: %d , max: %d , mean %f ." % (np.min(t_train),np.max(t_train),np.mean(t_train)))
14
15// min: 0 , max: 1 , mean 0.130661 .
16// min: 0 , max: 1 , mean 0.100000 .
このような状態であれば質問のネットワークでも十分に学習されます。
python
1from keras.datasets import mnist
2
3from keras.models import Sequential
4from keras.layers.core import Dense
5from keras.utils import to_categorical
6from keras.optimizers import Adam
7import matplotlib.pyplot as plt
8
9(x_train, t_train), (x_test, t_test) = mnist.load_data()
10
11x_train = x_train.reshape((60000,784))
12x_train = x_train.astype('float32') / 255
13
14x_test = x_test.reshape((10000,784))
15x_test = x_test.astype('float32') / 255
16
17t_train_ = to_categorical(t_train)
18t_test_ = to_categorical(t_test)
19
20model = Sequential()
21model.add(Dense(input_dim=784, output_dim=600, bias=True, activation='relu'))
22model.add(Dense(input_dim=600, output_dim=500, bias=True, activation='relu'))
23model.add(Dense(input_dim=500, output_dim=10, bias=True, activation='softmax'))
24model.summary()
25model.compile(loss='categorical_crossentropy', optimizer=Adam(), metrics=['accuracy'])
26
27epoch_num = 10
28history = model.fit(x_train, t_train_,
29 batch_size=1000, epochs=epoch_num,
30 validation_data=(x_test, t_test_))
正答率は98%くらいですね。
しかし過学習が発生しているのが少し気になります。
実際にはネットワークが小さく学習も早く終わる下記のネットワークにするほうが良いかもしれません。
python
1model.add(Dense(input_dim=784, output_dim=64, bias=True, activation='relu'))
2model.add(Dense(input_dim=64, output_dim=64, bias=True, activation='relu'))
3model.add(Dense(input_dim=64, output_dim=10, bias=True, activation='softmax'))
4model.compile(loss='categorical_crossentropy', optimizer=Adam(), metrics=['accuracy'])
このネットワークでも正答率は97%くらいなのでこちらのほうが使い勝手が良いと思います。
また、なぜうまくいくのかさらに精度を上げるにはどうすればよいのかなど詳しく知りたい場合は、
書籍などで数学的な側面も合わせて体系的に学ぶことをオススメします。
PythonとKerasによるディープラーニング
ここまで説明して申し訳ないですが、質問のコードにあるload_mnistのnormalizeというオプションは画素値を0~1の間に正規化してくれるオプションと思われるので、そこをTrueにするだけで上手くいく可能性が高いです。
(x_train, t_train), (x_test, t_test) = load_mnist(flatten=True, normalize=True)