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

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

ただいまの
回答率

90.84%

  • Python

    5934questions

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

  • Python 3.x

    4464questions

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

  • TensorFlow

    527questions

  • Jupyter

    146questions

  • Keras

    128questions

Tensorflow, kerasで作成したCNNモデルの使い方

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 112

iarik

score 71

 やりたいこと

APIで画像分析を今までやってきましたが、もっと深い画像分析をやりたいと思いtensorflowとkerasを使って勉強をはじめました。まずは、イメージを掴むためkerasでMNIST用のCNNモデルを作成し、作成したモデルに対して自分で用意した画像を当てたときにどういった結果が得られるかやってみようとしたところです。

 動作環境

Mac
Python 3.6.5
tensorflow 1.8.0
keras 2.2.0
jupyternotebook 1.0.0

 わからないこと

Qiitaの記事を読みつつ、jupyter notebook上でkerasで配布されているサンプルコードをmnist_cnn.pyを実行してみました。サンプルコード自体はうまく作成できましたがmodel.predictでエラーが出て進みません。

 やったこと

  • mnist_cnn.pyの実行
    mnist_cnn.pyは問題なく正常実行できました。
# mnist tutorial by keras (train time about 45 minuts)
'''Trains a simple convnet on the MNIST dataset.
Gets to 99.25% test accuracy after 12 epochs
(there is still a lot of margin for parameter tuning).
16 seconds per epoch on a GRID K520 GPU.
'''

from __future__ import print_function
import keras
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Dense, Dropout, Flatten
from keras.layers import Conv2D, MaxPooling2D
from keras import backend as K

batch_size = 128
num_classes = 10
epochs = 12

# input image dimensions
img_rows, img_cols = 28, 28

# the data, split between train and test sets
(x_train, y_train), (x_test, y_test) = mnist.load_data()

if K.image_data_format() == 'channels_first':
    x_train = x_train.reshape(x_train.shape[0], 1, img_rows, img_cols)
    x_test = x_test.reshape(x_test.shape[0], 1, img_rows, img_cols)
    input_shape = (1, img_rows, img_cols)
else:
    x_train = x_train.reshape(x_train.shape[0], img_rows, img_cols, 1)
    x_test = x_test.reshape(x_test.shape[0], img_rows, img_cols, 1)
    input_shape = (img_rows, img_cols, 1)

x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
x_train /= 255
x_test /= 255
print('x_train shape:', x_train.shape)
print(x_train.shape[0], 'train samples')
print(x_test.shape[0], 'test samples')

# convert class vectors to binary class matrices
y_train = keras.utils.to_categorical(y_train, num_classes)
y_test = keras.utils.to_categorical(y_test, num_classes)

model = Sequential()
model.add(Conv2D(32, kernel_size=(3, 3),
                 activation='relu',
                 input_shape=input_shape))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(128, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(num_classes, activation='softmax'))

model.compile(loss=keras.losses.categorical_crossentropy,
              optimizer=keras.optimizers.Adadelta(),
              metrics=['accuracy'])

model.fit(x_train, y_train,
          batch_size=batch_size,
          epochs=epochs,
          verbose=1,
          validation_data=(x_test, y_test))
score = model.evaluate(x_test, y_test, verbose=0)
print('Test loss:', score[0])
print('Test accuracy:', score[1])
  • モデルの保存
    一旦作成したモデルを保存してみました。こちらも正常にできました
# save model
json_string = model.to_json()
open('tutorial_mnist.json', 'w').write(json_string)
model.save_weights('tutorial_mnist.h5')
  • モデルをロードして、用意した画像の分析結果を得る
    画像はkaggleのDatasetより拝借。https://www.kaggle.com/scolianni/mnistasjpgのtestSample.zipからimg_1.jpgを利用して、predictを実行してみましたが、エラーが発生
import keras
from keras.datasets import mnist
from keras.models import model_from_json
from keras.utils import np_utils
from keras.preprocessing import image
from PIL import Image
import matplotlib.pyplot as plt
import numpy

# modelのload
model = model_from_json(open('tutorial_mnist.json').read())
model.load_weights('tutorial_mnist.h5')
model.compile(loss=keras.losses.categorical_crossentropy,
              optimizer=keras.optimizers.Adadelta(),
              metrics=['accuracy'])

# predict
filepath = "/Users/atg/work/python/tensorflow/jupyter/mnist_test_data/img_1.jpg"
img = Image.open(filepath).convert('RGB') ## Gray->L, RGB->RGB
img = img.resize((28, 28))
x = numpy.array(img, dtype=numpy.float32)
x = x / 255.
x = x[None, ...]

pred = model.predict(x, batch_size=1, verbose=0)
score = numpy.max(pred)
pred_label = np.argmax(pred)
print("pred", pred)
print("score", score)
print("pred_label", pred_label)
  • 発生したエラー
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-24-b0c45db13636> in <module>()
     23 x = x[None, ...]
     24 
---> 25 pred = model.predict(x, batch_size=1, verbose=0)
     26 score = numpy.max(pred)
     27 pred_label = np.argmax(pred)

~/work/python/tensorflow/lib/python3.6/site-packages/keras/engine/training.py in predict(self, x, batch_size, verbose, steps)
   1150                              'argument.')
   1151         # Validate user data.
-> 1152         x, _, _ = self._standardize_user_data(x)
   1153         if self.stateful:
   1154             if x[0].shape[0] > batch_size and x[0].shape[0] % batch_size != 0:

~/work/python/tensorflow/lib/python3.6/site-packages/keras/engine/training.py in _standardize_user_data(self, x, y, sample_weight, class_weight, check_array_lengths, batch_size)
    752             feed_input_shapes,
    753             check_batch_axis=False,  # Don't enforce the batch size.
--> 754             exception_prefix='input')
    755 
    756         if y is not None:

~/work/python/tensorflow/lib/python3.6/site-packages/keras/engine/training_utils.py in standardize_input_data(data, names, shapes, check_batch_axis, exception_prefix)
    134                             ': expected ' + names[i] + ' to have shape ' +
    135                             str(shape) + ' but got array with shape ' +
--> 136                             str(data_shape))
    137     return data
    138 

ValueError: Error when checking input: expected conv2d_1_input to have shape (28, 28, 1) but got array with shape (28, 28, 3)

期待している次元が違うというエラーということで、reshapeで次元数を変更してみました。

  • 変更したコード
import keras
from keras.datasets import mnist
from keras.models import model_from_json
from keras.utils import np_utils
from keras.preprocessing import image
from PIL import Image
import matplotlib.pyplot as plt
import numpy

# modelのload
model = model_from_json(open('tutorial_mnist.json').read())
model.load_weights('tutorial_mnist.h5')
model.compile(loss=keras.losses.categorical_crossentropy,
              optimizer=keras.optimizers.Adadelta(),
              metrics=['accuracy'])

# predict
filepath = "/Users/atg/work/python/tensorflow/jupyter/mnist_test_data/img_1.jpg"
img = Image.open(filepath).convert('RGB') ## Gray->L, RGB->RGB
img = img.resize((28, 28))
x = numpy.array(img, dtype=numpy.float32)
x = x / 255.
x = x[None, ...]
x = numpy.reshape(x, [28,28,1])

pred = model.predict(x, batch_size=1, verbose=0)
score = numpy.max(pred)
pred_label = np.argmax(pred)
print("pred", pred)
print("score", score)
print("pred_label", pred_label)
  • エラー
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-29-200996341dd9> in <module>()
     22 x = x / 255.
     23 x = x[None, ...]
---> 24 x = numpy.reshape(x, [28,28,1])
     25 
     26 pred = model.predict(x, batch_size=1, verbose=0)

~/work/python/tensorflow/lib/python3.6/site-packages/numpy/core/fromnumeric.py in reshape(a, newshape, order)
    255            [5, 6]])
    256     """
--> 257     return _wrapfunc(a, 'reshape', newshape, order=order)
    258 
    259 

~/work/python/tensorflow/lib/python3.6/site-packages/numpy/core/fromnumeric.py in _wrapfunc(obj, method, *args, **kwds)
     50 def _wrapfunc(obj, method, *args, **kwds):
     51     try:
---> 52         return getattr(obj, method)(*args, **kwds)
     53 
     54     # An AttributeError occurs if the object does not have

ValueError: cannot reshape array of size 2352 into shape (28,28,1)

今度はサイズでエラーが発生しましたが、そもそもpredictを行う前の画像の読み込みからモデルに適した形に変換する処理の考え方が間違っているのではと思い、teratailに質問を記載しました。

モデル作成まではQiitaや海外のフォーラムでも見かけるのですが、実際に作成したモデルで予測させる際は見るサイトで方法が変わり、かつサンプルコードを写経してもうまくいかず、だんだん何が正しい方法なのかがわからなくなってきました。
参考になるサイトや方法がありましたら、ご教授頂きたいです。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

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

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • wakame

    2018/06/08 15:39

    > エラーが出てうまく進みませんでした。 エラーはどちらになりますか

    キャンセル

  • iarik

    2018/06/08 15:40

    申し訳ございませんでした。修正致しました

    キャンセル

回答 1

checkベストアンサー

+1

質問者さんが作られた予測モデルはMNIST(手書き数字0-9)を何が書かれているかを予測する画像分類モデルなんですね。
とするとこのモデルは以下のコードから入力に(28, 28, 1)の画像(width, height, channel)を入力としていますね。

# input image dimensions
img_rows, img_cols = 28, 28

# the data, split between train and test sets
(x_train, y_train), (x_test, y_test) = mnist.load_data()

if K.image_data_format() == 'channels_first':
    x_train = x_train.reshape(x_train.shape[0], 1, img_rows, img_cols)
    x_test = x_test.reshape(x_test.shape[0], 1, img_rows, img_cols)
    input_shape = (1, img_rows, img_cols)
else:
    x_train = x_train.reshape(x_train.shape[0], img_rows, img_cols, 1)
    x_test = x_test.reshape(x_test.shape[0], img_rows, img_cols, 1)
    input_shape = (img_rows, img_cols, 1)


# 一部省略

model = Sequential()

# (28, 28, 1) or (1, 28, 28)の画像を入力層に入れる
# channel first か channel lastによって変わる
# 質問者さんの場合はchannel lastのようですね
model.add(Conv2D(32, kernel_size=(3, 3),
                 activation='relu',
                 input_shape=input_shape))

予測時の画像の前処理のコードにコメントをつけてみました。

# predict
filepath = "/Users/atg/work/python/tensorflow/jupyter/mnist_test_data/img_1.jpg"

# ここはRGBScaleではなくGrayScaleを選択しましょう
# もともとMNISTはGrayScaleですね
img = Image.open(filepath).convert('RGB') ## Gray->L, RGB->RGB
x = numpy.array(img, dtype=numpy.float32)
x = x / 255.
x = x[None, ...]
print(x.shape)
# (1, 28, 28, 3)
# RGBScaleで読み込んだためchannelが3になっていますね
x = numpy.reshape(x, [28,28,1])
# 質問者さんが記述されたエラーコードはここでreshapeできずエラーを出しているみたいですね
# ValueError: cannot reshape array of size 2352 into shape (28,28,1)


とりあえず上の指摘部分を直してみました。

# 上記コード修正版
# predict
filepath = "/Users/atg/work/python/tensorflow/jupyter/mnist_test_data/img_1.jpg"
img = Image.open(filepath).convert('L') ## Gray->L, RGB->RGB
x = numpy.array(img, dtype=numpy.float32)
x = x.reshape((28, 28, 1))
x = x / 255.
x = x[None, ...]
print(x.shape)
# (1, 28, 28, 1)

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

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

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

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/06/08 16:40

    wakameさん、早速の回答ありがとうございます。そもそもGrayScaleだったのですね、出だしから残念なミスを犯しておりました。頂いたコードを実行してエラー解消して正常に実行できました。
    実際に実行した際は以下に修正して実行しております。
    x = img.reshape((28, 28, 1))→x = x.reshape((28, 28, 1))

    キャンセル

  • 2018/06/08 16:46

    失礼しました、掲載したコードも修正しておきました。

    キャンセル

  • 2018/06/08 16:52

    1点質問なのですが、channels_firstとchannels_lastの使い分けが今ひとつわかっていないのですが。単にプログラム作成者の使いやすさで、channels_firstかchannels_lastの何方かで設定する程度の考えでしょうか?

    キャンセル

  • 2018/06/08 17:10

    https://www.tensorflow.org/performance/performance_guide#use_nchw_imag こちらを見るとtensorflowのデフォルトはchannel lastのようですね、またベストプラクティスはどちらも対応することと記述されていますね。

    キャンセル

  • 2018/06/08 17:12

    kerasの場合はhttps://keras.io/ja/backend/ keras.jsonのimage_data_formatにchannel_firstかchannel_lastかを記述することで一意のフォーマットに保つことができます。

    キャンセル

  • 2018/06/08 17:20

    質問の回答としてはおそらく質問者さんの認識で正しいかと、データセットのフォーマットも一意に定まっていないせいかライブラリ側(Keras)がどちらも受け入れられる体制をとっている点からもそのように感じられます。

    キャンセル

  • 2018/06/08 17:31

    wakameさん、参考情報ありがとうございます。大変勉強になります。今回、x = x.reshape((28, 28, 1))のように決め打ちで記述しておりましたが、両方のフォーマットに対応できるようにベストなのはif文で入力フォーマットを確認し、それに合わせてreshapeするほうが良さそうですね。
    ありがとうございます。

    キャンセル

  • 2018/06/08 17:34

    そちらのほうが丁寧ですね、恥ずかしながら私はkeras.jsonのimage_data_formatに記述されているフォーマットでのみ対応できるコードしか書いてないです、勉強になります。

    キャンセル

  • 2018/06/08 18:53

    一般的なフォーマットの場合、shapeだけが問題ではなくて、軸の入れ替えも必要なので、汎化するのは難しいです。
    あらかじめtensorflow/kerasを使うことが決まっているのであれば、channel_lastで揃えた方がいろいろと楽です。
    channelの差が大きくモデルの計算速度を影響するのであれば、その差異を吸収するようにtensorflowの方が書き換わっていくのでユーザは意識する必要がありません。
    計算速度がクリティカルのならpythonではお話にならないのでC++のAPIに移る必要があります。

    キャンセル

  • 2018/06/08 19:13

    mkgreiさんコメントありがとうございます。なんというかシステム上しかたがないのですがコメントのほうが回答より有益な情報になっていきますね。

    キャンセル

  • 2018/06/08 21:37

    最初の質問に対して回答は適切になされているケースが多いですが、技術者の性として派生した疑問を解決して行くうちにコメントの方が重要な話が展開されることがよくありますね。
    私はいつもコメント欄もじっくり楽しみながら読んでいます。

    キャンセル

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

  • ただいまの回答率 90.84%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

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

  • Python

    5934questions

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

  • Python 3.x

    4464questions

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

  • TensorFlow

    527questions

  • Jupyter

    146questions

  • Keras

    128questions