質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
86.12%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

解決済

tensprflow.keras のsequentialモデルのSimpleRNNの設定

sigefuji
sigefuji

総合スコア114

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

1回答

0リアクション

0クリップ

239閲覧

投稿2022/09/27 12:15

tensprflow.keras のsequentialモデルのSimpleRNNをテストしています。
下記のコードでこのテストの目的はmodel.fitくらいまで確認したいのですが、最初のSimpleRNNの段階で不整合なエラーとなります。
3次元を期待するが、4次元を検出したとのようです。
公式サイトなどを参照して、色々試行錯誤しましたが、解決には至りません。
正しい設定方法を教えて頂いてもうれしいですが、
このエラーの原因を知りたいです。
・指定したshape(input_shapeのことと推定)が(None, 20, 25, 25)となっていますが、このようにみなされた理由。
・input_shapeの仕様は[batch, timesteps, feature]となっていますが、featurの意味がよくわからない。
conv1d,conv2dでは入力画像のピクセル数となるが、この場合は時間ステップ数となるか?

このRNNネットワークの図的構成図の良いのが見あたりませんが、理解の範囲を言葉で述べておきます。

・隠れ層(unit個)の入力は2要素あって、一つは時系列データのタイムステップ分の入力(ts個)と、一つは隠れ層の出力の一つ前のstep状態(unit個)を合わせた(並べた)ものになる。
・隠れ層の出力は、出力層に全結合する(直前にdropout層をおくこともある)
・今回の場合の出力は複数(3以上)のカテゴリががあり、クロスエントロピー誤差とする。
・クロスエントロピーとするために、fitにはonehotlabelが必要。

他に全体構成を考えるに際し、不明な点があります、あわせてご教示頂ければ幸いです。
・このエラーの直接原因でないが、Denseレイヤーのdense_unitは何か。
SimpleRNNのunitを受け取る全結合のunitで良いか(同じ値を設定)
・出力層のカテゴリー数は、 tf.keras.utils.to_categoricalで生成するshapeに入るカテゴリ数が反映されるとしてよいか。(fitにはカテゴリー数指定が無いので)
・データ生成の別法との比較。1stepづつ与えるのでこの方が良いかとも思う。

参考サイト
・keras公式ページ
https://keras.io/api/layers/recurrent_layers/simple_rnn/
・  RNNの例ですが、数値の値の意味がはっきりしない。
https://www.tensorflow.org/guide/keras/rnn
・以前に教わった日本語サイト
https://note.nkmk.me/python-tensorflow-keras-basics/
・詳解ディープラーニング5章

発生している問題・エラーメッセージ

ValueError: Input 0 of layer "simple_rnn_20" is incompatible with the layer: expected ndim=3, found ndim=4. Full shape received: (None, 20, 25, 25)

該当のソースコード

python

import numpy as np import tensorflow as tf from tensorflow import keras import random from tensorflow.keras.models import Sequential from tensorflow.keras.layers import Dense from tensorflow.keras.layers import Activation from tensorflow.keras.layers import SimpleRNN timesteps = 25 feature = 25 cat_size = 11 bat = 20 unit = 60 dense_unit=cat_size model = Sequential() model.add(SimpleRNN(unit, input_shape=(bat,timesteps,feature), return_sequences=True)) # inputs: A 3D tensor, with shape [batch, timesteps, feature]. # batch = bat # timesteps = timesteps 観測する時間ステップ数 # feature  特徴だが何を意味。conv1d,conv2dでは入力画像のピクセル数となるが、この場合は時間ステップ数となるか? #以下は、この直前でエラーとなるのでコメントにした #model.add(Dense(dense_unit, activation="linear")) # unit:隠れ層の数 #model.compile(loss='binary_crossentropy') #model.compile(loss='categorical_crossentropy') l_x = np.random.random((1000, timesteps))   # l_y = np.random.random((1000, cat_size)) #データ生成の別法   #l_x = np.random.random(1000) #l_y = np.random.random(1000) #l_x = l_x.reshape(-1,1)     #l_y = l_y.reshape(-1,1) print("l_y.shape",l_y.shape) #cl_y = tf.keras.utils.to_categorical(l_y, cat_sz) #model.summary() print("cl_y.shape",cl_y.shape) #history = model.fit(l_x, cl_y, epochs=5, batch_size=bat)

補足情報(FW/ツールのバージョンなど)

コンソールリスト
runfile('C:/book/rnn1/test3.py', wdir='C:/book/rnn1')
Traceback (most recent call last):

File "C:\Users\qhtsi.conda\envs\py38tfkr\lib\site-packages\spyder_kernels\py3compat.py", line 356, in compat_exec
exec(code, globals, locals)

File "c:\book\rnn1\test3.py", line 18, in <module>
model.add(SimpleRNN(unit, input_shape=(bat,timesteps,feature), return_sequences=True))

File "C:\Users\qhtsi.conda\envs\py38tfkr\lib\site-packages\tensorflow\python\training\tracking\base.py", line 587, in _method_wrapper
result = method(self, *args, **kwargs)

File "C:\Users\qhtsi.conda\envs\py38tfkr\lib\site-packages\keras\utils\traceback_utils.py", line 67, in error_handler
raise e.with_traceback(filtered_tb) from None

File "C:\Users\qhtsi.conda\envs\py38tfkr\lib\site-packages\keras\engine\input_spec.py", line 214, in assert_input_compatibility
raise ValueError(f'Input {input_index} of layer "{layer_name}" '

ValueError: Input 0 of layer "simple_rnn_20" is incompatible with the layer: expected ndim=3, found ndim=4. Full shape received: (None, 20, 25, 25)

以下のような質問にはリアクションをつけましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

リアクションが多い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

気になる質問をクリップする

クリップした質問は、後からいつでもマイページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

下記のような質問は推奨されていません。

  • 間違っている
  • 質問になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

適切な質問に修正を依頼しましょう。

jbpb0

2022/09/28 00:20

> 指定したshape(input_shapeのことと推定)が(None, 20, 25, 25)となっていますが、このようにみなされた理由。 「bat = 20」がバッチサイズのことなら、kerasの「input_shape=」の指定にはバッチサイズは入れません model.add(SimpleRNN(unit, input_shape=(bat,timesteps,feature), return_sequences=True)) ↓ 修正 model.add(SimpleRNN(unit, input_shape=(timesteps,feature), return_sequences=True)) 参考 https://keras.io/ja/getting-started/sequential-model-guide/ の「入力のshapeを指定する」
jbpb0

2022/09/28 00:32

> input_shapeの仕様は[batch, timesteps, feature]となっていますが、featurの意味がよくわからない。 たとえば、将来の雲量を予測する場合、過去の雲量だけから予測する場合はfeatureは1です 過去の湿度だけから予測する場合もfeatureは1です 過去の雲量・気温・湿度から予測する場合はfeatureは3です 参考 https://qiita.com/ell/items/34f069651b551709d127
jbpb0

2022/09/28 01:30

> Denseレイヤーのdense_unitは何か。 SimpleRNNのunitを受け取る全結合のunitで良いか(同じ値を設定) 入力ではなく出力です 入力ではないので、「SimpleRNN」とは関係ありません 入力は、前の層の出力に合うように自動的に設定されます 参考 https://keras.io/ja/layers/core/ の「Dense」の「引数」の「units」
jbpb0

2022/09/30 06:28 編集

> 出力層のカテゴリー数は、 tf.keras.utils.to_categoricalで生成するshapeに入るカテゴリ数が反映されるとしてよいか。(fitにはカテゴリー数指定が無いので) ネットワークの定義では最終層の出力なので、質問のコードの場合は最終層の > Denseレイヤーのdense_unitは何か。 がそれです ただし、質問のコードの「input_shape=」を直してから「model.summary()」で確認したら分かりますが、出力に「SimpleRNN」の「timesteps」も反映されるので、それを直す必要があると思います 教師データでは、質問のコードの > history = model.fit(l_x, cl_y, epochs=5, batch_size=bat) で使ってる「cl_y」の「cl_y.shape[1]」がそれです ただし、「print("cl_y.shape",cl_y.shape)」で確認したら分かりますが、「cl_y」は2次元の「l_y」を「to_categorical」で3次元にしたものなので、そのままでは「model.fit」がうまくいかないと思います
jbpb0

2022/09/28 01:55

> クロスエントロピーとするために、fitにはonehotlabelが必要。 上にも書いたように、「l_y」は既にカテゴリー数(cat_size)個の数値が並んでる2次元データなので、それをさらに「to_categorical」で処理したら、次元がおかしくなります 下記のようにして、「l_y」を0〜10の整数が格納されてる1次元データにしたら、「to_categorical」で処理しても大丈夫です l_y = np.random.random((1000, cat_size)) ↓ 修正 l_y = np.random.randint(0, cat_size, (1000)) 上記のように変えてから、「print("cl_y.shape",cl_y.shape)」で確認してみてください
jbpb0

2022/09/28 02:04

「l_x」に「feature」が反映されてないので、ネットワークの定義の「input_shape=」と合ってません l_x = np.random.random((1000, timesteps)) ↓ 修正 l_x = np.random.random((1000, timesteps, feature)) もし、実際の教師データが、「feature = 25」ではなく「feature = 1」の場合でも、同様に3次元データにする必要があります
sigefuji

2022/09/28 02:39

ご返事ありがとうございます。 引用記事中の”1D Convolutionを用いた系列データ分類の場合”において model.add(Conv1D(64, 3, activation='relu', input_shape=(seq_length, 100))) このinput_shapeはbatが無しで、100はfeature数にあたりますが、正しいですか。 bat_sizeについて、conv1d、conv2dなどのバッチサイズはメモリサイズ削減だけでなく汎化性能にも寄与する効果があるとのされていますが、 一方RNNではサンプル数が非常に大きく分けて流す必要がある場合があるとの記事をみたことがありますが、このよう場合のサイズですか。(この理解を忘れていました) そうしますと、bat_sizeが指定されるかされないかは、単に省略されるだけでは、第1引数がbat_sizeかseq_lengthであるか区別できないように思うのですが。 このばあい、このような指定方法に関して公式ページ(英文も)に記載があるでしょうか? たしかに、その後試しにfeatuesを削除しますと、この部分のエラーがなくなることに気が付いています。 (他でエラーとなりますが) featuresは例示のような雲量・気温・湿度などから予想する場合は3個とする、つまり多変量予測の多変量数にあたることはわかりました。 質問ではfeatures=1にあたります。そして1の場合でも指定しなければならないと理解します(省略不可)。
sigefuji

2022/09/28 02:40

randomのfeatureの指定:わかりました。
jbpb0

2022/09/28 02:53

> bat_sizeが指定されるかされないかは、単に省略されるだけでは、第1引数がbat_sizeかseq_lengthであるか区別できないように思うのですが。 kerasは、「input_shape=」の最初の数値をバッチサイズと解釈することはありません ネットワークの定義でバッチサイズを指定する必要がある場合には、下記のようにします ・「batch_size=」で指定する ・「input_shape=」ではなく、「batch_input_shape=」を使う model.add(SimpleRNN(unit, input_shape=(timesteps,feature), batch_size=bat, return_sequences=True)) または model.add(SimpleRNN(unit, batch_input_shape=(bat,timesteps,feature), return_sequences=True))
jbpb0

2022/09/30 06:29 編集

> 質問のコードの「input_shape=」を直してから「model.summary()」で確認したら分かりますが、出力に「SimpleRNN」の「timesteps」も反映されるので、それを直す必要があると思います model.add(SimpleRNN(unit, input_shape=(timesteps,feature), return_sequences=True)) ↓ 変更 model.add(SimpleRNN(unit, input_shape=(timesteps,feature))) とすれば、ネットワークの出力に「SimpleRNN」の「timesteps」が反映されなくなり、ネットワークの出力がカテゴリー数である > Denseレイヤーのdense_unitは何か。 だけになります timesteps個(x feature個)の数値(l_x)から、結果(11カテゴリーのどれか、cl_y)が分かればいいので、途中経過は要りませんよね? 参考 https://qiita.com/everylittle/items/b6f08891c1da41f30b24
sigefuji

2022/09/28 05:38

>bat = 20」がバッチサイズのことなら、kerasの「input_shape=」の指定にはバッチサイズは入れません >model.add(SimpleRNN(unit, input_shape=(bat,timesteps,feature), return_sequences=True)) ↓ 修正 >model.add(SimpleRNN(unit, input_shape=(timesteps,feature), return_sequences=True)) こだわるようですが、最初の部分ですので、納得しておきたいと思います。 次の公式サイトによれば(tensorflow.kerasであるかが不明確でありますが) https://keras.io/api/layers/recurrent_layers/simple_rnn/ Call arguments inputs: A 3D tensor, with shape [batch, timesteps, feature]. とありますので、一組の3Dtensorとしています。 これから省略不可と見えるのですが。 この3Dtensorとはshape(a,b,c)の形のはずで、エラーの(None, 25, 1, 1)は正しく、expected ndim=3,となってしまう設定の違いがあるのではとも思います(想像にすぎない)。
jbpb0

2022/09/28 06:50 編集

> https://keras.io/api/layers/recurrent_layers/simple_rnn/ Call arguments inputs: A 3D tensor, with shape [batch, timesteps, feature]. は、SimpleRNN層に入力されるデータの実際のshapeに付いての記述です 質問のコードでは、「l_x.shape」を各バッチに分割したものが、それに該当します 「l_x.shape」が (データ数, timesteps, feature) となるように「l_x」を作れば、それを各バッチに分割したもののshapeは (バッチサイズ, timesteps, feature) になりますよね 上記と、「input_shape=」として指定する形式を、混同してはいけません
jbpb0

2022/09/28 06:51 編集

https://www.tensorflow.org/tutorials/images/intro_to_cnns?hl=ja を見てください 「MNISTデータセットのダウンロードと準備」で train_images = train_images.reshape((60000, 28, 28, 1)) を実行してるので、「train_images.shape」は (60000, 28, 28, 1) となり、4次元です 学習時には60000個のデータが同時に入力されるのではなく、各バッチに分割されるので、実際にネットワークに入力されるデータのshapeは (バッチサイズ, 28, 28, 1) ですが、やはり4次元です 一方、「畳み込みの基礎部分の作成」の model.add(layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1))) での「input_shape=」の指定は (28, 28, 1) で、3次元です バッチサイズは指定してません 層の種類がSimpleRNNだろうがConv2Dだろうが、そこは同じです https://keras.io/api/layers/convolution_layers/convolution2d/ の「Input shape」に batch_shape + (channels, rows, cols) or batch_shape + (rows, cols, channels) と書いてありますが、上記Webページのコード例のように、「input_shape=」の指定にはバッチサイズは入れません
sigefuji

2022/09/28 06:48

>各バッチに分割したもののshapeは (バッチ数, timesteps, feature) になりますよね これはわかります。conv1d,con2dなどと同じ。 >上記と、「input_shape=」として指定する形式を、混同してはいけません ここはわかりません。 あくまでinput=の仕様は3Dtensorとなっているので、[batch, timesteps, feature]と指定すべきではありませんか?(batchの意味を取り違えていましたが) 何と何を混同しているのだろう? 仕様はinput=[batch, timesteps, feature]とあるので、 少なくともそれぞれの要素を明示して指定すべきとおもいました。(省略形式があるなら別ですが) ライブラリーの仕様を誤りなく理解するのは難しい。
jbpb0

2022/09/30 06:30 編集

だいぶ上の方にも書きましたけど、「input_shape=」とは別に「batch_input_shape=」というものがあり、これの最初の数値はバッチサイズです どうしてもバッチサイズを書かないと気持ち悪いのなら、「batch_input_shape=」を使ってください model.add(SimpleRNN(unit, batch_input_shape=(bat,timesteps,feature), return_sequences=True)) とすれば、 > ValueError: Input 0 of layer "simple_rnn_20" is incompatible with the layer: expected ndim=3, found ndim=4. Full shape received: (None, 20, 25, 25) は出ません > あくまでinput=の仕様は3Dtensorとなっているので、[batch, timesteps, feature]と指定すべきではありませんか? とは、 https://www.tensorflow.org/tutorials/images/intro_to_cnns?hl=ja の「畳み込みの基礎部分の作成」のコードの model.add(layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1))) は間違いで、たとえばバッチサイズが32なら model.add(layers.Conv2D(32, (3, 3), activation='relu', input_shape=(32, 28, 28, 1))) とすべきである、という意味ですか?
sigefuji

2022/09/28 07:02

>2022/09/28 15:46のコメント >層の種類がSimpleRNNだろうがConv2Dだろうが、そこは同じです でもなぜ、前掲の https://keras.io/api/layers/recurrent_layers/simple_rnn/ 仕様と異なるのですか。keras全体の流儀思想と言うことはあるかと思いますが、 やはり今参照している仕様に従いたくなります。
jbpb0

2022/09/28 07:23 編集

> なぜ、前掲の https://keras.io/api/layers/recurrent_layers/simple_rnn/ 仕様と異なるのですか。 上記Webページのどこにも、「input_shape=」の指定の方法に付いては書かれてません https://keras.io/ja/getting-started/sequential-model-guide/ の「入力のshapeを指定する」に、 「バッチサイズを指定したい場合, batch_size引数を指定することができます.」 と書かれてます バッチサイズの指定方法は、「input_shape=」での指定とは「別に」用意されてるのです
sigefuji

2022/09/28 07:22

>2022/09/28 15:48のコメント たしかに上の方で ネットワークの定義でバッチサイズを指定する必要がある場合には、下記のようにします ・「batch_size=」で指定する ・「input_shape=」ではなく、「batch_input_shape=」を使う は見ました。 これは公式サイトに記載があるのですか? どこかにあっても、 https://keras.io/api/layers/recurrent_layers/simple_rnn/ のページに記載がないのでしょうか? Call arguments inputs: A 3D tensor, with shape [batch, timesteps, feature]. これはどう解釈、取り扱いすればよいのでしょうか。 batch,timesteps,featurとはなんぞやと、定義している個所を見ていないのが小生にとっては難題です。
jbpb0

2022/09/28 07:49 編集

> ・「batch_size=」で指定する https://keras.io/getting_started/faq/#how-can-i-use-stateful-rnns の「How can I use stateful RNNs?」に、 「explicitly specify the batch size you are using, by passing a batch_size argument to the first layer in your model. 」 と書かれてます 「Example:」のコード例も見てください > ・「input_shape=」ではなく、「batch_input_shape=」を使う https://keras.io/ja/getting-started/sequential-model-guide/ の一番下の「同じようなStacked LSTMを"stateful"にする」のコード例を見てください > どこかにあっても、 https://keras.io/api/layers/recurrent_layers/simple_rnn/ のページに記載がないのでしょうか? 「input_shape=」や「batch_size=」や「batch_input_shape=」は、ネットワークの最初の層で指定するもので、 https://keras.io/api/layers/ に書かれてるたくさんの種類の層が最初の層になり得るため、それら全部に個別に書いたらたいへんなので、「層の種類に関わらず、最初の層では指定してね」って、まとめて https://keras.io/ja/getting-started/sequential-model-guide/ の「入力のshapeを指定する」とかに書いて済ませてるのではないですかね
sigefuji

2022/09/28 09:16

>上記Webページのどこにも、「input_shape=」の指定の方法に付いては書かれてません 私の誤解の原因は、 Call arguments inputs: A 3D tensor, with shape [batch, timesteps, feature]. の記載を input_shape=[batch, timesteps, feature] と記述すべきと間違えていたことでした。いまやっとわかりました。 これをもとに種々のアドバイスをみなおしてみます。
sigefuji

2022/09/28 10:09

見直した結果次のようにすればfitまで通りました。 疑似訓練データは多少実データに近い形にしました。 頂いたアドバイスで効いたのは ・bat_sizeはinput_shapeには不要 ・featureの意味 ・kerasRNNのページにinput_shape=()の記載はないこと ・input_shapeの指定はkerasに共通で最初に一回指定すればよい。 などです。 沢山のご丁寧なアドバイス、ありがとうございました。 timesteps = 25 feature = 1 cat_size = 11 bat = 1000 unit = 50 dense_unit=cat_size model = Sequential() model.add(SimpleRNN(unit, input_shape=(timesteps,feature), return_sequences=True)) model.add(Dense(dense_unit, activation="linear")) model.compile(loss='categorical_crossentropy') l_x = ((1.0 - (-1.0))*np.random.randn(bat)+1.0)/2.0 l_y = np.random.randint(0,cat_size,bat) l_x = l_x.reshape(-1,timesteps) l_y = l_y.reshape(-1,timesteps) cl_y = tf.keras.utils.to_categorical(l_y, cat_size) model.summary() history = model.fit(l_x, cl_y, epochs=5, batch_size=bat) 参考までに実行結果。 Layer (type) Output Shape Param # ================================================================= simple_rnn_4 (SimpleRNN) (None, 25, 50) 2600 dense_4 (Dense) (None, 25, 11) 561 ================================================================= Total params: 3,161 Trainable params: 3,161 Non-trainable params: 0 _____________________________ Epoch 1/5 1/1 [==============================] - 1s 946ms/step - loss: 7.1064 Epoch 2/5 1/1 [==============================] - 0s 3ms/step - loss: 6.9764 Epoch 3/5 1/1 [==============================] - 0s 4ms/step - loss: 6.6976 Epoch 4/5 1/1 [==============================] - 0s 4ms/step - loss: 6.8238 Epoch 5/5 1/1 [==============================] - 0s 3ms/step - loss: 6.7392 ランダムデータでも多少のアノマリーがありそう。
jbpb0

2022/09/28 11:56

あれ? 「l_x.shape」が (40, 25) で2次元なのに?? と思って実行して確認したら、 > feature = 1 だと2次元でも大丈夫でした 知らなかった feature = 2 だと、当然ですが「l_x」を3次元にしないと、エラー出ました
jbpb0

2022/09/28 12:05

「l_y.shape」が (40, 25) なので、教師データの目的変数(l_y)もtimesteps(25)個並んでる時系列データの想定なのですね (25個のそれぞれが11カテゴリーのどれか) 以前のコメントで > model.add(SimpleRNN(unit, input_shape=(timesteps,feature), return_sequences=True)) ↓ 変更 model.add(SimpleRNN(unit, input_shape=(timesteps,feature))) と書いたのは、目的変数(l_y)は時系列データではない(11カテゴリーのどれかが1個だけ)と思ったからです
jbpb0

2022/09/28 12:16 編集

「SimpleRNN」とは関係無いですが、「to_categorical」でone-hotにしてるので、ネットワークの最終を「softmax」にした方がいいかも model.add(Dense(dense_unit, activation="linear")) ↓ 変更 model.add(Dense(dense_unit, activation="softmax")) (カテゴリー)分類ではなく回帰(目的変数が数値)の場合は、「linear」でいいのですけど
sigefuji

2022/09/30 11:30

その後にもアドバイスを頂いていたのですね。 >「SimpleRNN」とは関係無いですが、「to_categorical」でone-hotにしてるので、ネットワークの最終を「softmax」にした方がいいかも エラーばかりに注目していたので、このあたりはあまり検討していませんでした。 たしかに仰せの通りですね。(サンプルコードのままで、なにか変かなとは思っていた) この質問は実際的でない疑似データでもあり、他で検討しますので、あまり深く検討しないようにします。

まだ回答がついていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
86.12%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問

同じタグがついた質問を見る

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。