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

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

新規登録して質問してみよう
ただいま回答率
85.48%
Keras

Kerasは、TheanoやTensorFlow/CNTK対応のラッパーライブラリです。DeepLearningの数学的部分を短いコードでネットワークとして表現することが可能。DeepLearningの最新手法を迅速に試すことができます。

CNN (Convolutional Neural Network)

CNN (Convolutional Neural Network)は、全結合層のみではなく畳み込み層とプーリング層で構成されるニューラルネットワークです。画像認識において優れた性能を持ち、畳み込みニューラルネットワークとも呼ばれています。

Model

MVCモデルの一部であるModelはアプリケーションで扱うデータとその動作を管理するために扱います。

Python 3.x

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

Q&A

解決済

1回答

1685閲覧

KerasやTensorflowのmodel.predict()は数値的に何をやっているのか?

mamoru-max

総合スコア2

Keras

Kerasは、TheanoやTensorFlow/CNTK対応のラッパーライブラリです。DeepLearningの数学的部分を短いコードでネットワークとして表現することが可能。DeepLearningの最新手法を迅速に試すことができます。

CNN (Convolutional Neural Network)

CNN (Convolutional Neural Network)は、全結合層のみではなく畳み込み層とプーリング層で構成されるニューラルネットワークです。画像認識において優れた性能を持ち、畳み込みニューラルネットワークとも呼ばれています。

Model

MVCモデルの一部であるModelはアプリケーションで扱うデータとその動作を管理するために扱います。

Python 3.x

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

0グッド

0クリップ

投稿2022/05/20 10:29

編集2022/05/22 10:48

知りたい事:
Keras(またはTensorflow)でCNNのモデルを構築し学習させた後に、model.predict()で予測値をだす際の数値的な処理の詳細を知りたいです。

試したこと:
学習させたモデルのファイルからパラメータを取得し、教科書的な畳み込み演算、全結合演算をコードした自作CNNで予測値を算出したところ、model.predict()とはかなり異なる値ばかり算出されてしまいました。

Kerasで構築したモデルは以下のとおりです。

Python

1model = Sequential() 2mode.add(Conv2D(20,kernel_size=(1,5), strides=(1,1), padding='valid', input_shape=(24,13,1), activation='relu')) 3mode.add(Conv2D(20,kernel_size=(1,9), strides=(1,1), padding='valid', activation='relu')) 4mode.add(Conv2D(20,kernel_size=(24,1), strides=(1,1), padding='valid', activation='relu')) 5mode.add(Flatten()) 6mode.add(Dense(20,activation='relu')) 7mode.add(Dense(2,activation='sigmoid')) 8model.load_weights(model_path / '[model_filename].h5') 9model.summary() 10 11# Prediction 12y = model.predict(x, batch_size=1)

私の自作CNNのコードは下の通りです(畳み込みと全結合のみ記載します)

Python

1def mydense(ind, ker, bia, func): 2 tem_dense = np.dot(ker.T, ind) + bia 3 return func(tem_dense) 4 5def myconv(ind, ker, bia, func): 6 7 # input sample data's shape 8 H = ind.shape[0] 9 W = ind.shape[1] 10 11 # kernel' shape 12 Hf = ker.shape[0] 13 Wf = ker.shape[1] 14 K = ker.shape[3] 15 16 # result of convolution 17 u = np.zeros((H - Hf + 1, W - Wf + 1, K)) 18 # output 19 z = np.zeros((u.shape)) 20 21 for k in range(0,K): 22 for n in range(0,W - Wf + 1): 23 for m in range(0, H - Hf + 1): 24 u[m,n,k] = (ind[m:m+Hf, n:n+Wf, :] * ker[:,:,:,k] + bia[k]).sum() 25 26 z = np.array([func(i) for i in u]) 27 28 return z

KerasまたはTensorflowのソースコード
https://github.com/keras-team/keras/tree/master/keras
などで調べていましたが、私の自作コードの畳み込み演算(上記の myconv)は

Python

1from tensorflow.python.ops.nn_ops import convolution 2from tensorflow.python.ops.gen_nn_ops import conv2d 3tf.nn.conv2d() 4from tensorflow.python.ops.nn_ops import convolution_internal 5from tensorflow.pythonn.ops.nn_ops import convolution_v2

バイアスの付与は

Python

1from tensorflow.python.ops.gen_nn_ops import bias_add

と活性化関数(reluとsigmoid)の処理(省略)は結果が一致していましたが、

Python

1from keras.layers.convolutional import Conv2D 2from keras.layers.convolutional import Conv

とは一致していませんでしたので、ここで何かしら教科書的な数式以外の処理が組まれていると推測しています。

▼Kerasのmodel.predict() の数値的な厳密な処理はどのようになっているのか?
▼ソースコードなどの、どのあたりを調べれば分かりそうか?
▼ほかに質問した方が良さそうな、おすすめのサイトは?(英語版のstackoverflowには投稿していますが今のところ返答がありません、、)

この3点について、もしご存じの方いらっしゃいましたら助けて頂けますと大変ありがたいです。

長すぎないようにするためにだいぶ省略しましたので、上記でご不明点等ありましたら遠慮なく仰ってください。
何卒よろしくお願いいたします。

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2022/05/20 21:47 編集

全体を通して結果を見てどこかが違う、では追跡しにくいので、関数1つ単位で純正の関数と自作関数とで同じ値を入れた時に何が出るか比較してはどうでしょうか?同じインプットをしたら同じ出力であってほしい、というのを関数単位で見ていくイメージです。ネットワーク単位で比較するのはその後がよいです。 「おそらく」その何かあるのがCONV部分だと思うのですが、そうであれば質問の流れを、 ・ ゼロから自力でCNNを作った ・ Keras等の純正ツールと結果を比較したが一致しなかった ・ 関数を一個一個追跡していったところ、CONVの部分が違いそうだった ・ その違う部分の処理を比較すると○○(実際のソースコードを並べる) ・ どこが違うか分からない みたいな感じにした方がよいです。
mamoru-max

2022/05/22 10:35

fourteenlength さん ご指摘ありがとうございます。 分かりにくい投稿で申し訳ございません。
mamoru-max

2022/05/23 00:04 編集

jbpb0 さん ご提案ありがとうございます。 こちらも結果が > from keras.layers.convolutional import Conv2D > from keras.layers.convolutional import Conv と同様に、結果が自作myconvとは異なり、実行毎に異なる値が出力されています。 ご不明点ありましたら、また何かご存じでしたら引き続きご教授頂けますと幸いです。 よろしくお願いいたします。
jbpb0

2022/05/23 13:53

tensorflow.keras.layers.Conv2D の演算に付いて、下記を実行して確認しました import numpy as np import tensorflow as tf from tensorflow.keras.layers import Conv2D from tensorflow.keras import initializers input_size = 7 kernel_size = 3 input_value = 0.5 kernel_value = 1.0 input_np = np.ones((input_size, input_size)) * input_value input_tensor = tf.convert_to_tensor(input_np.reshape(1, input_size, input_size, 1)) kernel = np.ones((kernel_size, kernel_size)) * kernel_value conv_2d = Conv2D(filters=1, kernel_size=(kernel_size, kernel_size), input_shape=(input_size, input_size, 1), kernel_initializer=initializers.Constant(kernel)) output_tensor = conv_2d(input_tensor) output_np = np.squeeze(output_tensor.numpy()) print(input_np) print(kernel) print(output_np) 結果は下記の通りとなり、問題ありませんでした [[0.5 0.5 0.5 0.5 0.5 0.5 0.5] [0.5 0.5 0.5 0.5 0.5 0.5 0.5] [0.5 0.5 0.5 0.5 0.5 0.5 0.5] [0.5 0.5 0.5 0.5 0.5 0.5 0.5] [0.5 0.5 0.5 0.5 0.5 0.5 0.5] [0.5 0.5 0.5 0.5 0.5 0.5 0.5] [0.5 0.5 0.5 0.5 0.5 0.5 0.5]] [[1. 1. 1.] [1. 1. 1.] [1. 1. 1.]] [[4.5 4.5 4.5 4.5 4.5] [4.5 4.5 4.5 4.5 4.5] [4.5 4.5 4.5 4.5 4.5] [4.5 4.5 4.5 4.5 4.5] [4.5 4.5 4.5 4.5 4.5]]
jbpb0

2022/05/23 23:54

質問のコードの「myconv」を、 def myconv(ind, ker, bia, func): ↓ def myconv(ind, ker, bia): z = np.array([func(i) for i in u]) return z ↓ return u と変更して、下記を実行 import numpy as np input_size = 7 kernel_size = 3 input_value = 0.5 kernel_value = 1.0 input_np = np.ones((input_size, input_size, 1)) * input_value kernel = np.ones((kernel_size, kernel_size, 1, 1)) * kernel_value output_np = myconv(input_np, kernel, [0.0]) print(np.squeeze(input_np)) print(np.squeeze(kernel)) print(np.squeeze(output_np)) 結果は下記の通り、 tensorflow.keras.layers.Conv2D の結果と同じでした [[0.5 0.5 0.5 0.5 0.5 0.5 0.5] [0.5 0.5 0.5 0.5 0.5 0.5 0.5] [0.5 0.5 0.5 0.5 0.5 0.5 0.5] [0.5 0.5 0.5 0.5 0.5 0.5 0.5] [0.5 0.5 0.5 0.5 0.5 0.5 0.5] [0.5 0.5 0.5 0.5 0.5 0.5 0.5] [0.5 0.5 0.5 0.5 0.5 0.5 0.5]] [[1. 1. 1.] [1. 1. 1.] [1. 1. 1.]] [[4.5 4.5 4.5 4.5 4.5] [4.5 4.5 4.5 4.5 4.5] [4.5 4.5 4.5 4.5 4.5] [4.5 4.5 4.5 4.5 4.5] [4.5 4.5 4.5 4.5 4.5]]
mamoru-max

2022/05/24 13:28 編集

jbpb0 さん 私の方でも確認できました、誠にありがとうございます。 また条件をjbpb0 さんのものに合わせて、(当然かもしれませんが)from keras.layers.convolutional import Conv2Dの方でも同じ結果が得られました。 私が質問の箇所で、convolutionalクラスのConv2Dでは毎回異なる結果が出力される(恐らく乱数がきいている)と申し上げましたが、今回のものとの違いは「kernel_initializer=initializers.Constant(kernel)」であり、defaultが 'glorot_uniform' であるため私が単純にConv2Dを使用して毎回ある種の一様乱数が発生していました、こちらをご教示頂いた通りConstantにしたところ、教科書通りの畳み込み計算と同じ結果結果になりました。 しかし、依然としてmodel.predict()とは異なる値になっており、また学習時にconv2Dの引数にkernel_initializerがConstantに指定されていなくても、(常識的に、な推測にはなりますが)predict()では重みに一様乱数を加えたら最適化で算出した重みが変わることになるので、kernel_initializerはpredict()には関係ないのかもしれない、と考えていますが断定もできず、、 続けてpredict()では何が起きているのか、 predict_step https://github.com/keras-team/keras/blob/2a703470e18354c7c4b4c27a2c3846e4471ec54c/keras/engine/training.py#L1785 等の処理の理解を続けてみますので、何か見つかりましたらまた投稿いたします。 またご不明点等ありましたら、または何かご存じでしたら引き続きご教授頂けますと幸いです。
jbpb0

2022/08/01 01:34 編集

> predict()では重みに一様乱数を加えたら最適化で算出した重みが変わることになるので、kernel_initializerはpredict()には関係ないのかもしれない 「kernel_initializer」を指定してない場合に、どのタイミングで重みが乱数で初期化されるのかは、下記が参考になると思います 一番下の「コメント」も見てください https://qiita.com/neptunium/items/a3a4e111c4049a6e1acf 【追記】 > model.load_weights(model_path / '[model_filename].h5') の直前と直後にそれぞれ下記を実行して、表示される結果(重み)を比べてみてください model.get_weights() 「kernel_initializer」を指定してない場合は重みが乱数で初期化されていて、「model.load_weights(...」で重みが上書きされて変わってますよね 「model.predict(...」では、その上書きされた重みが使われてるはずです
mamoru-max

2022/08/01 01:24

ありがとうございます。こちら知りませんでしたので大変助かります。
guest

回答1

0

ベストアンサー

「tensorflow.keras.layers.Conv2D」の演算に付いて、下記を実行して確認しました

python

1import numpy as np 2import tensorflow as tf 3from tensorflow.keras.layers import Conv2D 4from tensorflow.keras import initializers 5 6input_size = 7 7kernel_size = 3 8input_value = 0.5 9kernel_value = 1.0 10 11input_np = np.ones((input_size, input_size)) * input_value 12input_tensor = tf.convert_to_tensor(input_np.reshape(1, input_size, input_size, 1)) 13 14kernel = np.ones((kernel_size, kernel_size)) * kernel_value 15conv_2d = Conv2D(filters=1, kernel_size=(kernel_size, kernel_size), input_shape=(input_size, input_size, 1), kernel_initializer=initializers.Constant(kernel)) 16 17output_tensor = conv_2d(input_tensor) 18output_np = np.squeeze(output_tensor.numpy()) 19 20print(input_np) 21print(kernel) 22print(output_np)

 
結果は下記の通りとなり、問題ありませんでした

[[0.5 0.5 0.5 0.5 0.5 0.5 0.5]
[0.5 0.5 0.5 0.5 0.5 0.5 0.5]
[0.5 0.5 0.5 0.5 0.5 0.5 0.5]
[0.5 0.5 0.5 0.5 0.5 0.5 0.5]
[0.5 0.5 0.5 0.5 0.5 0.5 0.5]
[0.5 0.5 0.5 0.5 0.5 0.5 0.5]
[0.5 0.5 0.5 0.5 0.5 0.5 0.5]]
[[1. 1. 1.]
[1. 1. 1.]
[1. 1. 1.]]
[[4.5 4.5 4.5 4.5 4.5]
[4.5 4.5 4.5 4.5 4.5]
[4.5 4.5 4.5 4.5 4.5]
[4.5 4.5 4.5 4.5 4.5]
[4.5 4.5 4.5 4.5 4.5]]

 

質問のコードの「myconv」を、

python

1def myconv(ind, ker, bia, func):

python

1def myconv(ind, ker, bia):

と、

python

1 z = np.array([func(i) for i in u]) 2 return z

python

1 return u

を変更して、下記を実行

python

1 2import numpy as np 3 4input_size = 7 5kernel_size = 3 6input_value = 0.5 7kernel_value = 1.0 8 9input_np = np.ones((input_size, input_size, 1)) * input_value 10kernel = np.ones((kernel_size, kernel_size, 1, 1)) * kernel_value 11output_np = myconv(input_np, kernel, [0.0]) 12 13print(np.squeeze(input_np)) 14print(np.squeeze(kernel)) 15print(np.squeeze(output_np))

 
結果は下記の通り、「tensorflow.keras.layers.Conv2D」の結果と同じでした

[[0.5 0.5 0.5 0.5 0.5 0.5 0.5]
[0.5 0.5 0.5 0.5 0.5 0.5 0.5]
[0.5 0.5 0.5 0.5 0.5 0.5 0.5]
[0.5 0.5 0.5 0.5 0.5 0.5 0.5]
[0.5 0.5 0.5 0.5 0.5 0.5 0.5]
[0.5 0.5 0.5 0.5 0.5 0.5 0.5]
[0.5 0.5 0.5 0.5 0.5 0.5 0.5]]
[[1. 1. 1.]
[1. 1. 1.]
[1. 1. 1.]]
[[4.5 4.5 4.5 4.5 4.5]
[4.5 4.5 4.5 4.5 4.5]
[4.5 4.5 4.5 4.5 4.5]
[4.5 4.5 4.5 4.5 4.5]
[4.5 4.5 4.5 4.5 4.5]]

 

以上より、

何かしら教科書的な数式以外の処理が組まれている

ということは無いと思います

投稿2022/07/29 10:06

編集2022/07/29 10:19
jbpb0

総合スコア7651

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mamoru-max

2022/08/01 00:40

誠にありがとうございます。 仰る通り、教科書の数式以外の処理はなさそうです。 私のコードですと def myconv の >u[m,n,k] = (ind[m:m+Hf, n:n+Wf, :] * ker[:,:,:,k] + bia[k]).sum() でバイアスの部分が間違っております。 u[m,n,k] = (ind[m:m+Hf, n:n+Wf, :] * ker[:,:,:,k]).sum() + bia[k] が正しいかもしれません。 ミスで大変お手数おかけしてすみませんでした、、
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問