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

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

ただいまの
回答率

89.10%

mnist手書き数字画像データ学習モデル活用でjpeg画像の予測ができません。

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 2,422

hmgien1469

score 11

本を見ながらKerasよりデータを取得して Deep Learningを試しています。
mnistからのデータを使い、モデルを作成して実際に手書き画像ファイルを読ませて試したのですが、
ValueError: Error when checking input: expected dense_1_input to have 2 dimensions, but got array with shape (28, 28, 3)
と出ます。
えっ、(28, 28)ではないの?最終的に(784,)にしないとモデルに入れられないのに。といったところで、なぜ(28, 28, 3)という三次元になるのか、それを(784,)の一次元でモデルに入れるための方法をご教示願います。

%matplotlib inline
from __future__ import division, print_function

from keras import backend as K
from keras.datasets import mnist
from keras.layers import Activation, Dense, Dropout
from keras.layers.normalization import BatchNormalization
from keras.models import Sequential
from keras.utils.np_utils import to_categorical
import numpy as np
from sklearn.metrics import classification_report, confusion_matrix

# Kerasに付属の手書き数字画像データをダウンロード
np.random.seed(0)
(X_train, labels_train), (X_test, labels_test) = mnist.load_data()

# 各画像は行列なのでベクトルに変換→X_trainとX_testを作成
n_samples_train = X_train.shape[0]
X_train = X_train.reshape(n_samples_train, -1)
n_samples_test = X_test.shape[0]
X_test = X_test.reshape(n_samples_test, -1)
X_train.shape

# ラベルをone-hotベクトル(値がひとつだけ1で他が0のベクトル)に変換→Y_trainとY_testを作成
Y_train = to_categorical(labels_train)
Y_test = to_categorical(labels_test)

#Deep Learningモデルコード
model = Sequential()
model.add(Dense(10, input_dim = 784))
model.add(BatchNormalization())
model.add(Activation('relu'))
model.add(Dense(10))
model.add(BatchNormalization())
model.add(Activation('relu'))
model.add(Dense(10))
model.add(BatchNormalization())
model.add(Activation('softmax'))
model.compile(optimizer='adam',loss='categorical_crossentropy',
              metrics=['accuracy'])
# Trainingの実施
model.fit(X_train ,Y_train ,epochs = 10 ,batch_size = 128,
          validation_data=(X_test, Y_test))
# Test dataを用いてモデルを評価(accuracyを算出)
_,acc = model.evaluate(X_test ,Y_test ,verbose = 0)
print('accuracy:{:.2f}'.format(acc))

**#以下データ読み込み、予測コード**
import numpy as image_np
from PIL import Image, ImageOps
import os

#取得画像answer
image_ans = (8,9,5,0)

#'number_file'フォルダ内ファイル取得
images = os.listdir('number_file')
for i in images:
    if i == 'Thumbs.db':
        continue
    #imagesの中にある全ての画像をopen
    image = Image.open('number_file/'+i)
    #画素値を逆転
    image = ImageOps.invert(image)
    #配列変換
    image = np.array(image)
    #データをモデルに入れて予測
    image_data_pred = model.predict_classes(image, verbose = 0)


読み込んだデータをimage.shape()でかくにんしたところ、
エラー内容と同様に(28, 28, 3)となっていました。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

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

  • coco_bauer

    2018/09/19 14:57

    ディレクトリ 'number_file' には、どのようなファイル(形式、データ数等)が入っているのですか? 変数imageは、そうしたファイルから読みだした(open)データに基づいているので、元のファイルに原因を求めるべきかと思われます。

    キャンセル

  • hmgien1469

    2018/09/19 16:04

    回答いただいていた人のコメント通り、RGB 形式でした。.convert('L')により白黒変換したらうまくいきました。ありがとうございます。

    キャンセル

回答 2

+1

えっ、(28, 28)ではないの?最終的に(784,)にしないとモデルに入れられないのに。といったところで、なぜ(28, 28, 3)という三次元になるのか、それを(784,)の一次元でモデルに入れるための方法をご教示願います。
  • MNIST はグレースケールなので、各画像は (28, 28) の numpy 配列です。
  • ネットワークは (784,) の numpy 配列を期待しているので、1次元配列に潰します。
  • 読み込んだ画像が RGB 形式であったため、(28, 28, 3) となっています。
  • これをネットワークに入れるには、まずグレースケール形式に変換し、 (28, 28) の numpy 配列にします。その後、1次元配列に潰し (784,) の numpy 配列にします。

 MNIST の学習コード

from keras import backend as K
from keras.datasets import mnist
from keras.layers import Activation, BatchNormalization, Dense, Dropout
from keras.models import Sequential
from keras.utils.np_utils import to_categorical
import numpy as np

# MNIST データを取得する。
(x_train, y_train), (x_test, y_test) = mnist.load_data()
print('x_train.shape', x_train.shape)  # x_train.shape (60000, 28, 28)
print('y_train.shape', y_train.shape)  # y_train.shape (60000,)
print('x_test.shape', x_test.shape)  # x_test.shape (10000, 28, 28)
print('y_test.shape', y_test.shape)  # y_test.shape (10000,)

# 1次元配列にする。 (28, 28) -> (784,) にする
x_train = x_train.reshape(len(x_train), -1)
x_test = x_test.reshape(len(x_test), -1)

# one-hot 表現に変換する。
y_train = to_categorical(y_train)
y_test = to_categorical(y_test)

# モデルを作成する。
model = Sequential()
model.add(Dense(10, input_dim=784))
model.add(BatchNormalization())
model.add(Activation('relu'))
model.add(Dense(10))
model.add(BatchNormalization())
model.add(Activation('relu'))
model.add(Dense(10))
model.add(BatchNormalization())
model.add(Activation('softmax'))
model.compile(optimizer='adam',
              loss='categorical_crossentropy',
              metrics=['accuracy'])

# 学習する。
model.fit(x_train, y_train, epochs=10, batch_size=128,
          validation_data=(x_test, y_test))

# 評価する。
_, acc = model.evaluate(x_test, y_test, verbose=0)
print('accuracy:{:.2f}'.format(acc))

 本題のコード

テスト用にフォルダに MNIST の画像をRGB、グレースケール形式で保存する。

# MNIST の画像をファイルに保存する。
import glob
import os
from PIL import Image

(x_train, y_train), (x_test, y_test) = mnist.load_data()

img_dir = 'number_file'
os.makedirs(img_dir, exist_ok=True)
for data, label in zip(x_test[:10], y_test[:10]):
    img = Image.fromarray(data)
    # グレースケール形式で保存する。
    img.save(os.path.join(img_dir,
             'gray_{}.png'.format(label)))

    # RGB 形式で保存する。
    img = img.convert('RGB')
    img.save(os.path.join(img_dir,
             'color_{}.png'.format(label)))

画像を読み込んで、推論する。
RGB 形式の場合はグレースケール形式に変換する。

# フォルダ内の画像を読み込み、予測する。
for img_path in glob.glob(os.path.join(img_dir, '*.png')):
    # 画像を読み込む。
    img = Image.open(img_path)

    # 画像が RGB ならグレースケールに変換する。(28, 28, 3) -> (28, 28)
    if img.mode == 'RGB':
        img = img.convert("L")
    # (28, 28) -> (1, 784) にする。
    data = np.array(img).reshape(1, -1)

    # 推論する。
    pred_y = model.predict_classes(data, verbose=0)
    print(img_path, pred_y)

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/09/19 16:14

    ・MNIST はグレースケール
    ・読み込んだ画像が RGB 形式であったため、(28, 28, 3) となっています。
    ご教示いただきましてありがとうございました。
    書き込んでいただいた中の後半のコードを参考に自コードを修正できました。

    キャンセル

  • 2018/09/19 16:50

    コード内容もすべて読んでなるほどと思いました。
    今後の参考ともなる素晴らしい回答ありがとうございました。

    キャンセル

check解決した方法

0

データをグレースケール変換するように
image = Image.open('number_file/'+i)
に対して.convert('L')
書き加えたら解決しました。
参考URL
https://qiita.com/takus69/items/dd904dfc62372310c46f

学習後のコードは以下の通りです。
今回得られた予測結果についてはノーコメントです。

皆さまありがとうございました。

#取得画像answer
image_ans = [8,9,5,0]

#'number_file'フォルダ内ファイル取得
images = os.listdir('number_file')
pred_list = []

for i in images:
    if i == 'Thumbs.db':
        continue
    #imagesの中にある全ての画像をopen,白黒変換
    image = Image.open('number_file/'+i).convert('L')
    #画素値を逆転
    image = ImageOps.invert(image)
    #配列変換
    image = np.array(image)
    #1次元変換,リストに一旦収納
    image = image.reshape((28*28))
    pred_list.append(image)

#データをモデルに入れて予測
image_pred = model.predict_classes(np.array(pred_list))
print(classification_report(image_ans, image_pred))

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

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