#やろうとしたこと
mnistのデータをgzから読み込んだ2次元データを、
全結合して出力する2層モデルを試そうとした。
#失敗したこと
なぞのエラーが発生した。今回はこのエラーの解決方法を、自分の戒めのために記事に残しておく。
ValueError: Shapes (None, 10, 10) and (None, 28, 10) are incompatible
#処理の流れ
- gzデータの読み込み
- 正規化
- モデルの作成
- 学習実行
※各処理で参考にしたリンクを付けた
#モデル
入力層:28*28のデータをインプットする。
出力層:全結合してsoftmaxで0~9までの予想値を出力する
loss関数:categorical_crossentropy
最適化アルゴリズム:adam
メトリクス:accuracy(正答率)
#エラー
ValueError: Shapes (None, 10, 10) and (None, 28, 10) are incompatible
メッセージの意味を調べてみると、どうやら特定のレイヤーにおける入出力データの形が期待しているものと異なる
ということのようだ。
#原因の見つけ方と判明した原因
エラーが発生したときに、model.summary()を実行してみると、
現在のモデルの各層における出力データの形式が分かる。
ここで以下のように、全結合層において期待していた出力データのshapeが異なっていた。
(0~9の予想値をonehot表現で出力することを期待していたため、output shapeは当然(10)となると思った)
こちらの期待:(10)
実際:(28,10)
以下model.summary()の実行結果
Model: "sequential_1"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
dense_1 (Dense) (None, 28, 10) 290
=================================================================
Total params: 290
Trainable params: 290
Non-trainable params: 0
_________________________________________________________________
#根本原因(全結合層に関する一時的な勘違い)
全結合層(Dense)は1次元データを1次元データにして出力する。
ここで、2次元データ(28*28)を全結合層へ入力しても1次元データにしてくれると期待してしまった。
(よく考えたら、畳み込みのモデルでは1次元データに直していたなと後で思い出した。)
#解決
全結合層の直前に、Flattenを追加することで正常に動くようになった。
#モデルの構築
model = Sequential()
model.add(InputLayer(input_shape=(28,28)))
model.add(Flatten())
model.add(Dense(10,activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])