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

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

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

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

Model

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

OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

390閲覧

kerasで学習させたモデルをロードし、画像で認識させる

python01

総合スコア11

Keras

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

Model

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

OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2024/02/11 16:08

編集2024/02/15 15:28

実現したいこと

ねじの画像をkerasで学習させ、学習済みモデルをロードしました。

このモデルを用いて、テスト画像でねじを認識できるか試しています。

↓実現したいテスト画像図
イメージ説明

発生している問題・分からないこと

expected shape=(None, 300, 300, 1)とのエラーが発生している為、
ロードした配列が正しくないと推測しておりますが、対応方法がわかりません。

エラーメッセージ

error

1--------------------------------------------------------------------------- 2ValueError Traceback (most recent call last) 3<ipython-input-160-df9f9fcb6594> in <module> 4 9 5 10 #test = best_model.predict(test_img, verbose=1) 6---> 11 test = best_model.predict(test_img) 7 12 print(test) 8 9~\anaconda3\lib\site-packages\keras\src\utils\traceback_utils.py in error_handler(*args, **kwargs) 10 68 # To get the full stack trace, call: 11 69 # `tf.debugging.disable_traceback_filtering()` 12---> 70 raise e.with_traceback(filtered_tb) from None 13 71 finally: 14 72 del filtered_tb 15 16~\anaconda3\lib\site-packages\keras\src\engine\training.py in tf__predict_function(iterator) 17 13 try: 18 14 do_return = True 19---> 15 retval_ = ag__.converted_call(ag__.ld(step_function), (ag__.ld(self), ag__.ld(iterator)), None, fscope) 20 16 except: 21 17 do_return = False 22 23ValueError: in user code: 24 25 File "C:\Users\user\anaconda3\lib\site-packages\keras\src\engine\training.py", line 2341, in predict_function * 26 return step_function(self, iterator) 27 File "C:\Users\user\anaconda3\lib\site-packages\keras\src\engine\training.py", line 2327, in step_function ** 28 outputs = model.distribute_strategy.run(run_step, args=(data,)) 29 File "C:\Users\user\anaconda3\lib\site-packages\keras\src\engine\training.py", line 2315, in run_step ** 30 outputs = model.predict_step(data) 31 File "C:\Users\user\anaconda3\lib\site-packages\keras\src\engine\training.py", line 2283, in predict_step 32 return self(x, training=False) 33 File "C:\Users\user\anaconda3\lib\site-packages\keras\src\utils\traceback_utils.py", line 70, in error_handler 34 raise e.with_traceback(filtered_tb) from None 35 File "C:\Users\user\anaconda3\lib\site-packages\keras\src\engine\input_spec.py", line 298, in assert_input_compatibility 36 raise ValueError( 37 38 ValueError: Input 0 of layer "sequential_11" is incompatible with the layer: expected shape=(None, 300, 300, 1), found shape=(None, 300, 3)

該当のソースコード

python

1from tensorflow.python.keras.models import load_model 2import cv2 3 4#モデルを読み込み 5loaded_model = models.load_model('./model/model-40.h5') 6model.summary() #モデル情報を出力 7 8#画像の読み取り 9test_img = cv2.imread("img00.jpg") 10 11test = best_model.predict(test_img) 12print(test)

_ソースコード(最新)

1import cv2 2import numpy as np 3 4#モデルを読み込み 5loaded_model = models.load_model('./model/model-40.h5') 6 7# 画像の読み込み 8test_img = cv2.imread("img01.jpg") 9 10# 画像のリサイズと前処理 11resized_img = cv2.resize(test_img, (300, 300)) 12gray_img = cv2.cvtColor(resized_img, cv2.COLOR_BGR2GRAY) 13normalized_img = gray_img / 255 # 正規化 14 15input_img = np.expand_dims(normalized_img, axis=-1) # チャンネルの次元を追加 16 17# モデルの予測 18prediction = loaded_model.predict(np.array([input_img])) 19 20#結果を出力 21threshold = 0.5 22y_pred = prediction >= threshold 23print(y_pred) 24print(prediction)

試したこと・調べたこと

  • teratailやGoogle等で検索した
  • ソースコードを自分なりに変更した
  • 知人に聞いた
  • その他
上記の詳細・結果

1.テスト用画像(img00.jpg)を300*300のサイズに変更。

2.model.summary()でモデルの情報を確認しました。

Model: "sequential_13" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= conv2d_55 (Conv2D) (None, 150, 150, 16) 800 max_pooling2d_55 (MaxPooli (None, 75, 75, 16) 0 ng2D) conv2d_56 (Conv2D) (None, 75, 75, 32) 4640 max_pooling2d_56 (MaxPooli (None, 37, 37, 32) 0 ng2D) conv2d_57 (Conv2D) (None, 37, 37, 64) 18496 max_pooling2d_57 (MaxPooli (None, 18, 18, 64) 0 ng2D) conv2d_58 (Conv2D) (None, 18, 18, 128) 73856 max_pooling2d_58 (MaxPooli (None, 9, 9, 128) 0 ng2D) conv2d_59 (Conv2D) (None, 9, 9, 256) 295168 max_pooling2d_59 (MaxPooli (None, 4, 4, 256) 0 ng2D) flatten_11 (Flatten) (None, 4096) 0 dense_22 (Dense) (None, 64) 262208 dropout_11 (Dropout) (None, 64) 0 dense_23 (Dense) (None, 1) 65 ================================================================= Total params: 655233 (2.50 MB) Trainable params: 655233 (2.50 MB) Non-trainable params: 0 (0.00 Byte) _________________________________________________________________

3.ご教示頂いたコードで試した結果
エラーの発生はなくなりました。

しかし、学習させたねじ画像と、何もない画像の2種類で
試したところ、どちらも同じ出力であった為、
正しく判断できていないようです。
→正規化でうまく数値の出力はできるようになりました。

尚、学習させたモデルを混同行列で検証した結果は下記通りで、
学習自体は問題なくできてそうです。

イメージ説明

_画像前処理・正規化追加

1import cv2 2import numpy as np 3 4#モデルを読み込み 5loaded_model = models.load_model('./model/model-40.h5') 6 7# 画像の読み込み 8test_img = cv2.imread("img00.jpg") 9 10# 画像のリサイズと前処理 11resized_img = cv2.resize(test_img, (300, 300)) 12gray_img = cv2.cvtColor(resized_img, cv2.COLOR_BGR2GRAY) 13normalized_img = gray_img / 255 # 正規化 14input_img = np.expand_dims(normalized_img, axis=-1) # チャンネルの次元を追加 15 16# モデルの予測 17prediction = loaded_model.predict(np.array([input_img])) 18print(prediction)

4.出力された数値に関して
予測させた画像と出力された数値の一覧は下表の通りです。

イメージ説明

正しく予測できていれば、「True」が出力されると思っていましたが
数値での出力なので、解釈に困っています。
出力値はねじの個数に反応してそうなのですが、
これがねじの個数を認識している数値なのか、そもそもねじを正しく認識できているのか不明です。
⇒学習時の検証画像のみでの結果を確認しました(試した事5に記載しています)

CNNの出力層

1#畳み込み層~プーリング層 2model.add(Conv2D(filters=16,kernel_size=(7,7),strides=(2,2),padding='same',activation='relu',input_shape=(300,300,1))) 3model.add(MaxPooling2D(pool_size=(2,2),strides=(2,2))) 4 5model.add(Conv2D(filters=32,kernel_size=(3,3),activation='relu',padding='same')) 6model.add(MaxPooling2D(pool_size=(2,2),strides=(2,2))) 7 8model.add(Conv2D(filters=64, kernel_size=(3,3), activation="relu", padding="same")) 9model.add(MaxPooling2D(pool_size = (2,2), strides =(2,2))) 10 11model.add(Conv2D(filters=128, kernel_size=(3,3), activation="relu", padding="same")) 12model.add(MaxPooling2D(pool_size = (2,2), strides =(2,2))) 13 14model.add(Conv2D(filters=256, kernel_size=(3,3), activation="relu", padding="same")) 15model.add(MaxPooling2D(pool_size = (2,2), strides =(2,2))) 16 17#全結合層 18model.add(Flatten()) 19 20model.add(Dense(units=64,activation='relu')) 21model.add(Dropout(rate=0.2)) 22model.add(Dense(units=1,activation='sigmoid')) 23 24#コンパイル→ニューラルネットワークモデルの生成終了 25model.compile(optimizer='adam',loss='binary_crossentropy',metrics=['accuracy'])

5.学習終了後、学習時に用いた検証画像で予測させた結果
検証画像を一つずつ予測させた結果は下表の通りです。
学習時の前処理と検証時の前処理が異なる?

<結果>
・予測は8割程度合っている。
→学習の検証で用いた画像をそのまま使っているので、結果が異なる事はおかしい?
・逆さ画像は学習させても認識できない。
→学習画像数が不足している?それともこの段階で認識できないのはおかしい?

 <前処理>
・学習時の前処理は正規化、リサイズ、グレースケール化を実施。
モデルロード後の前処理も同じ処理を実施。
※コードは次のURLに記載:https://teratail.com/questions/ohu1ivc9a3j5ah

イメージ説明

補足

Python 3.8.3

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

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

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

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

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

meg_

2024/02/11 16:18

> 1.テスト用画像(img00.jpg)を300*300のサイズに変更。 本当にそのサイズになっていますか?
python01

2024/02/12 06:44

img00.jpgは300*300のサイズです。 shapeに関する記事があったので、ここを参考に進めています。 https://qiita.com/kuroneko-hornet/items/7737b71c3854c06fcb49 また、shapeについて、「None」と「3」は何を意味しているのでしょうか? エラーコード:expected shape=(None, 300, 300, 1), found shape=(None, 300, 3)
meg_

2024/02/12 09:01

> img00.jpgは300*300のサイズです。 どうやって確かめましたか? ファイルのプロパティでもピクセル数を確認できるかと思いますが「300 × 300」になっているということで良いですね? エラーメッセージは「300 × 3」と言っているようです。
python01

2024/02/12 10:52

画像のプロパティを「試した事」に貼っておきました
meg_

2024/02/12 11:42

loaded_model.predict(test_img) ではなくて best_model.predict(test_img) なのは何故でしょうか?
meg_

2024/02/12 11:48

エラーの原因については4次元の入力が期待されているためかと思います。(Noneはデータ数を表しているため)テスト画像が1枚であれば(1, 300, 300, 1)になるように調整してください。 あともしかして訓練はモノクロ画像で行っていてテスト画像はカラーでしょうか?
python01

2024/02/12 22:47

あともしかして訓練はモノクロ画像で行っていてテスト画像はカラーでしょうか? →テスト画像はカラーであったので、モノクロ画像に変換しました。 (1, 300, 300, 1)になるように調整 →この部分を試してみます
jbpb0

2024/02/13 11:45

> 正しく判断できていない input_img = np.expand_dims(gray_img, axis=-1) # チャンネルの次元を追加 ↓ 変更 normalized_img = gray_img / 255 # 正規化 input_img = np.expand_dims(normalized_img, axis=-1) # チャンネルの次元を追加 が必要かも
python01

2024/02/13 13:11

ご教示頂いた正規化を追加すると、0以外の出力ができました! しかし、出力された数値をどう解釈していいか困っております。 予測させた画像と出力された数値を下記にまとめましたので、 「4.出力された数値に関して」 ご確認頂ければ幸いです。
meg_

2024/02/13 14:35

> 正しく予測できていれば、「True」が出力されると思っていましたが数値での出力なので、解釈に困っています。 そういう風にモデルを学習させたのでしょうか?モデルの出力層はどうなっているんでしょうか?
python01

2024/02/13 23:45

出力層ですね。もう少しでわかりそうな気がします! シグモイド関数で出力されていました。 という事は全て0に近いから、単純にねじと認識できていない。 と考えてもよさそうですが、それだと混同行列での結果と大きく乖離しているので つじつまが合いません。
jbpb0

2024/02/14 01:34 編集

> 正しく予測できていれば、「True」が出力されると思っていましたが 数値での出力なので、解釈に困っています。 https://teratail.com/questions/ohu1ivc9a3j5ah では、「該当のソースコード」の178〜180行目で > y_pred_proba = best_model.predict(test_generator, verbose=1) threshold = 0.5 y_pred = y_pred_proba >= threshold として、その結果が > y_predの中身を確認すると、下記のような配列になっているので、 array([[False], [False], [ True],....) となりましたが、上記に print(y_pred_proba) を追加して「y_pred_proba」の内容を調べたら、こちらの質問の > prediction = loaded_model.predict(np.array([input_img])) の結果の「prediction」と同様に、数値が入ってたはずです https://teratail.com/questions/ohu1ivc9a3j5ah と同様に、 print(prediction) ↓ 変更 threshold = 0.5 print(prediction >= threshold) とすれば、数値ではなく「True」か「False」と表示されると思います
jbpb0

2024/02/14 04:40 編集

> 混同行列での結果と大きく乖離しているので つじつまが合いません。 混同行列を作る際に使ったデータのそれぞれは、画像ファイルでしょうか? もし画像ファイルなら、「True label」と「Predicted label」がどちらも「0」になってる画像ファイルから1枚と、どちらも「1」になってる画像ファイルから1枚をそれぞれ選んで、この質問のコードで処理したら、結果はどうなりますでしょうか? 片方は「False」で、もう片方は「True」と、混同行列と矛盾無く正しく予測できますでしょうか? 混同行列を作る際に使った画像でも、この質問のコードでは正しく予測できないなら、学習時のコードとこの質問のコードで、まだ何か(画像の前処理?)相違点があるのだと思います あるいは、混同行列を作る際に使った画像ならば、この質問のコードで正しく予測できるのなら、混同行列を作る際に使った画像と、この質問に掲載してるネジ数が1〜12個の画像が、かなり異なってることが考えられます
python01

2024/02/14 07:43

ご教授ありがとうございます! 出力のところは「True」or「False」で出力できるよう修正できました。 sigmoid関数を用いていて、閾値以上でTrueを出力する。という事ですね。 また、混同行列を作る際に使ったデータは画像を用いており、 アドバイス頂いた内容を後で検証してみます。 混同行列でTP・TNの数値が高かったので、 学習自体は問題ないと思っていましたが、これでもまだ検証が必要な時があるんですね。 大変勉強になります。ありがとうございます。
jbpb0

2024/02/15 09:23 編集

> 学習の検証で用いた画像をそのまま使っているので、結果が異なる事はおかしい? 「*.h5」ファイルと画像ファイルが同じなら、結果も同じになるはずです 当方で確認したところ、この質問のコードで問題無いようでした https://qiita.com/tmengine/items/4eeb6770a9a69baf9439 を、データセットも含めて基本そのまま(細かい間違いは直しながら)実行しました その際の「2. 混同行列」のコードで計算した「y_pred_proba」の先頭の五つは、下記の通りでした [[0.00041848] [0.00181046] [0.00030711] [0.0036839 ] [0.0006335 ]] 次に、上記の数値に該当する画像をそれぞれ、この質問のコードで処理した結果の「prediction」は下記の通り、上記数値とほとんど同じでした [[0.00041848]] [[0.00181046]] [[0.00030711]] [[0.00368386]] [[0.0006335]]
python01

2024/02/15 15:31

同じように出力できているんですね! 私のやり方が間違ってそうです。 「ソースコード(最新)」を追加したので、 ここでの質問のコードとjbpb0様が検証で用いられたコードが同じが見て頂く事は 可能でしょうか? お手数お掛けします。
python01

2024/02/21 13:38

jbpb0様 学習させる画像サイズがバラバラであったので、 300×300に近いサイズにリサイズしました。 上記作業の後、再度学習させ、 テスト画像でスコアを確認したところ、 ほぼ全て合っていました! ありがとうございました
guest

回答1

0

ベストアンサー

エラーメッセージから推測すると、best_model.predict()メソッドに渡されるテスト画像の形状が予想されている形状と一致していないようです。エラーメッセージによれば、期待されている形状は (None, 300, 300, 1) であるのに対して、実際の形状は (None, 300, 3) です。
これは、テスト画像の形状が期待される形状と異なっていることを示しています。予測のためにモデルに渡す入力テンソルの形状が (None, 300, 300, 1) のように、チャンネル数が1であることが期待されているようです。
解決策として
・テスト画像を読み込む前に、画像のサイズを (300, 300) にリサイズし、チャンネルを1に変換(画像の前処理)
・モデルを再構築

これは1つ目の画像の前処理のコードです。一度、トライしてみてください。

import cv2 import numpy as np # 画像の読み込み test_img = cv2.imread("img00.jpg") # 画像のリサイズと前処理 resized_img = cv2.resize(test_img, (300, 300)) gray_img = cv2.cvtColor(resized_img, cv2.COLOR_BGR2GRAY) input_img = np.expand_dims(gray_img, axis=-1) # チャンネルの次元を追加 # モデルの予測 prediction = loaded_model.predict(np.array([input_img])) print(prediction)

投稿2024/02/13 00:54

shoshinsha123

総合スコア213

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

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

python01

2024/02/13 01:57

頂いたコードでエラーの発生はなくなりましたが、 学習に用いた「ねじ」があり画像とねじがない画像のどちらも 同じ出力結果となるため、正しく判断ができていないように思われます。 「3.ご教示頂いたコードで試した結果」 に情報をついかしたので、ご確認頂けないでしょうか?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問