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

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

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

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

Python

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

Q&A

解決済

1回答

2386閲覧

Deep Learningの画像の2クラス分類をしたい

essa

総合スコア81

Keras

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

Python

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

0グッド

0クリップ

投稿2018/10/20 08:23

教師あり学習のDeep Learningを使った画像の2クラス分類をしたいと考えています。

前提条件として、ラベル付き画像と

ざっくりとした処理になりますが、以下のような流れになると理解しております。

1.画像読み込み;
1.1.Train画像データ(正例と負例)の入力
1.2.Test画像データ(正例と負例)の入力
1.3.Train画像のデータ水増し

2.データ処理;
2.1.2クラス分類処理を行うニューラルネットを構築
2.2.Trainデータを使って学習データを作成
2.3.作成した学習データに対し、Testデータを入力し、2クラス分類を実施

3.結果出力;
2.3.Testデータの正例と、2.3.にて出力した結果を比較して精度の算出

成果物;
2クラス分類結果のCSVファイル

そこで、最初の画像データの入力からどのようにコーディングをしたらいいのかが
いまいちわかりません。

参考になるサイト等を教えていただければと思います。

どうぞよろしくお願い致します。

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

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

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

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

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

guest

回答1

0

ベストアンサー

画像を読み込む際、画像の入ったフォルダを指定して

全データを読み込むということをしたいのですが、その場合はどうすればよろしいでしょうか。

以下のようにすればよいです。

  1. glob.glob() でファイル一覧を取得する。
  2. PIL.Image.open() で画像を読み込む。

2クラス分類を Keras でやる手順

サンプルをした使用するデータセット

Kaggle Cats and Dogs Dataset

解凍すると、以下のようになっている。

PetImages ├── Cat: 猫の画像が入っている └── Dog: 犬の画像が入っている

画像を学習用とテスト用に分割する。

''' 以下のようなクラスごとにフォルダ分けされたディレクトリ構造を学習用、テスト用に分割する。 input_dirpath ├── Cat └── Dog ↓ dataset ├── test │   ├── cat │   └── dog └── train ├── cat └── dog ''' import glob import os import shutil from PIL import Image from sklearn.model_selection import train_test_split # dataset/train/dog/11702.jpg input_dirpath = 'PetImages' output_dirpath = 'dataset' for sub_dirpath in glob.glob(os.path.join(input_dirpath, '*')): class_name = os.path.basename(sub_dirpath).lower() # 出力用のディレクトリを作成する。 train_dirpath = os.path.join(output_dirpath, 'train', class_name) test_dirpath = os.path.join(output_dirpath, 'test', class_name) os.makedirs(train_dirpath, exist_ok=True) os.makedirs(test_dirpath, exist_ok=True) # サブディレクトリ配下の画像パスを取得する。 img_paths = glob.glob(os.path.join(sub_dirpath, '*.jpg')) print('class {}: {} images found.'.format(class_name, len(img_paths))) # 画像パスを学習用、テスト用に分割する。 train_paths, test_paths = train_test_split(img_paths, test_size=0.2) for img_paths, to_dirpath in zip([train_paths, test_paths], [train_dirpath, test_dirpath]): for img_path in img_paths: to_filepath = os.path.join(to_dirpath, os.path.basename(img_path)) try: img = Image.open(img_path) img.verify() # 画像が壊れていないかチェック img._getexif() # exif の壊れていないかチェック # 問題ない画像ファイルならコピー shutil.copy(img_path, to_filepath) # print('{} ---> {}'.format(img_path, to_filepath)) except Exception: # 壊れた画像ファイルはスキップ print('Invalid image found. {}'.format(img_path))

学習済みの ResNet-50 でモデルを作成する。

fine-tuning でやりたいので、ImageNet で学習済みの ResNet-50 のモデルのあとに全結合層をくっつけて、モデルを作成する。

import numpy as np from keras.applications.resnet50 import ResNet50, preprocess_input, decode_predictions from keras.layers import Dense, Flatten from keras.models import Model from keras.preprocessing import image num_classes = 2 # モデルを作成する。 # ---------------------------------- base_model = ResNet50(weights='imagenet', include_top=False, input_shape=(224, 224, 3)) # ベースモデルのあとに分類用の全結合層を追加する。 x = base_model.output x = Flatten()(x) x = Dense(1000, activation='relu')(x) output = Dense(num_classes, activation='softmax')(x) model = Model(inputs=base_model.input, outputs=output) # fine-tuning なので追加した層以外はフリーズする。(パラメータ更新しない) for layer in base_model.layers: layer.trainable = False # モデルを可視化 from keras.utils import plot_model # plot_model(model, to_file='model.png') # モデルをコンパイルする。 model.compile(optimizer='rmsprop', loss='categorical_crossentropy', metrics = ['accuracy'])

ディレクトリからデータを読み込み、水増しするジェネレーターを作成する。

以下のディレクトリ構造を想定している。

dataset ├── test │   ├── cat │   └── dog └── train ├── cat └── dog

ImageDataGenerator でディレクトリから画像を読み込みつつ、水増しするジェネレーターを作成する。

train_dirpath = 'dataset/train' test_dirpath = 'dataset/test' batch_size = 32 epochs = 10 # 学習用の画像生成器を作成する。 params = {'vertical_flip': True, 'horizontal_flip': True, 'brightness_range': [0.7, 1.0]} # 学習用のジェネレーターを作成する。 train_datagen = image.ImageDataGenerator( preprocessing_function=preprocess_input, **params) train_gen = train_datagen.flow_from_directory( train_dirpath, target_size=model.input_shape[1:3], batch_size=batch_size) # テスト用の画像生成器を作成する。(テスト用は水増ししない) test_datagen = image.ImageDataGenerator(preprocessing_function=preprocess_input) # テスト用のジェネレーターを作成する。 test_gen = test_datagen.flow_from_directory( test_dirpath, target_size=model.input_shape[1:3], batch_size=batch_size)

学習する。

python

1# 学習する。 2history = model.fit_generator( 3 train_gen, 4 steps_per_epoch=len(train_gen) / batch_size, 5 epochs=epochs, 6 validation_data=test_gen, 7 validation_steps=len(test_gen) / batch_size)
Found 24331 images belonging to 2 classes. Found 8925 images belonging to 2 classes. Epoch 1/10 24/23 [==============================] - 10s 413ms/step - loss: 7.4179 - acc: 0.5208 - val_loss: 7.8353 - val_acc: 0.5139 Epoch 2/10 24/23 [==============================] - 5s 188ms/step - loss: 6.2514 - acc: 0.6094 - val_loss: 4.3866 - val_acc: 0.7222 Epoch 3/10 24/23 [==============================] - 5s 190ms/step - loss: 4.0494 - acc: 0.7435 - val_loss: 1.0163 - val_acc: 0.9340 Epoch 4/10 24/23 [==============================] - 5s 219ms/step - loss: 3.1330 - acc: 0.7995 - val_loss: 1.2144 - val_acc: 0.9201 Epoch 5/10 24/23 [==============================] - 5s 227ms/step - loss: 4.0351 - acc: 0.7487 - val_loss: 1.1573 - val_acc: 0.9236 Epoch 6/10 24/23 [==============================] - 5s 215ms/step - loss: 3.3249 - acc: 0.7930 - val_loss: 1.0633 - val_acc: 0.9340 Epoch 7/10 24/23 [==============================] - 5s 228ms/step - loss: 2.6396 - acc: 0.8346 - val_loss: 0.8395 - val_acc: 0.9479 Epoch 8/10 24/23 [==============================] - 5s 225ms/step - loss: 2.5717 - acc: 0.8372 - val_loss: 1.1193 - val_acc: 0.9306 Epoch 9/10 24/23 [==============================] - 5s 217ms/step - loss: 2.9105 - acc: 0.8190 - val_loss: 1.0074 - val_acc: 0.9375 Epoch 10/10 24/23 [==============================] - 5s 216ms/step - loss: 2.5275 - acc: 0.8424 - val_loss: 1.3991 - val_acc: 0.9132

学習過程を可視化する。

import matplotlib.pyplot as plt fig, [ax1, ax2] = plt.subplots(1, 2, figsize=(8, 4)) epochs = np.arange(1, len(history.history['loss']) + 1) # 各エポックの誤差の推移 ax1.set_title('loss') ax1.plot(epochs, history.history['loss'], label='train') ax1.plot(epochs, history.history['val_loss'], label='validation') ax1.set_xticks(epochs) ax1.legend() # 各エポックの精度の推移 ax2.set_title('accuracy') ax2.plot(epochs, history.history['acc'], label='train') ax2.plot(epochs, history.history['val_acc'], label='validation') ax2.set_xticks(epochs) ax2.legend() plt.show()

イメージ説明

テストデータを読み込む。

python

1import glob 2import os 3from PIL import Image 4from keras.preprocessing import image 5from keras.utils import to_categorical 6 7label_to_id = test_gen.class_indices 8print(label_to_id) # {'cat': 0, 'dog': 1} 9 10x = [] 11y = [] 12for path in glob.glob(os.path.join(test_dirpath, '*', '*.jpg')): 13 label = os.path.basename(os.path.dirname(path)) 14 img = image.load_img(path, target_size=model.input_shape[1:3]) 15 img = np.array(img) 16 img = preprocess_input(img) 17 18 x.append(img) 19 y.append(label_to_id[label]) 20 21x = np.array(x) 22y = np.array(y) 23print('x.shape', x.shape) # x.shape (8925, 224, 224, 3) 24print('y.shape', y.shape) # y.shape (8925,)

学習したモデルでテストデータを推論し、精度を算出する。

y_prob = model.predict(x) y_classes = y_prob.argmax(axis=-1) from sklearn.metrics import accuracy_score accuracy = accuracy_score(y, y_classes) print('accuracy: {:.2%}'.format(accuracy)) # accuracy: 92.45%

92% の精度が出ました。

投稿2018/10/20 08:33

編集2018/10/20 12:34
tiitoi

総合スコア21956

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

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

essa

2018/10/20 08:41

tiitoi様 早速の回答ありがとうございます。 画像を読み込む際、画像の入ったフォルダを指定して 全データを読み込むということをしたいのですが、その場合はどうすればよろしいでしょうか。 ご存知でしたら教えていただけると幸いです。 どうぞよろしくお願い致します。
tiitoi

2018/10/20 12:35

回答を追記しました。 glob.glob() でファイル一覧を取得する。 PIL.Image.open() で画像を読み込む。 であるディレクトリ以下の画像ファイルを全部読み込めます。
essa

2018/10/21 05:24

とても丁寧に回答していただき、大変ありがとうございます。 参考にさせていただきます。
essa

2018/10/21 08:41

参考に教えていただきたいのですが、tiitoi様はどのように学習しているのでしょうか。差し支えなければ教えていただければ幸いです。 どうぞよろしくお願い致します。
tiitoi

2018/10/21 09:29

理論的な話は書籍「深層学習 (岡谷貴之)」「ゼロから作る Deep Leraning」や Web 上の解説記事、Qiita とかですね。 Keras の使い方は、公式ドキュメントや Stack Overflow がメインです。 公式ドキュメントに書かれてない挙動とか知りたい場合だけ Keras の Github のソースを参照しています。
essa

2018/10/21 11:27

tiitoi様 回答ありがとうございます。 まずは上記コードを写生して理解に努めました。 上記のコードで動かしたところ、Epoch 1/10の23/24で止まってしまいました。 Found 24573 images belonging to 2 classes. Found 12017 images belonging to 2 classes. Epoch 1/10 23/24 [===========================>..] - ETA: 3s - loss: 4.6534 - acc: 0.6807 おそらく使用しているkeras等のバージョンによるものと考えています。 差し支えなければ、tiitoi様のPythonの使用しているkerasのバージョンを教えていただければと思います。 お手数おかけしますが、よろしくお願い致します。
essa

2018/10/21 11:43 編集

すみません。コードの方は解決しました。 1Epochに1300秒もかかっていたおり、止まったと勘違いしていました。 23/24からの処理がかなり時間かかるのですね。
tiitoi

2018/10/21 13:38 編集

> 23/24からの処理がかなり時間かかるのですね。 こちらではそのような現象は確認できませんでした。 CPU で実行されているのでしょうか?メモリ使用量がバッチサイズ32で8Gぐらいでしたので、もしかしたら、メモリに乗り切らなくてスワップして遅くなっている可能性もありますね。 とりあえずバッチサイズを 32 から 16、8などに落とせばメモリ使用量は抑えられます。 こちらで試した環境は GPU (GTX 1080) ですが、1 epoch 5秒ぐらいでした。学習するのであれば、GPU がないと時間がかかりますね。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問