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

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

ただいまの
回答率

87.34%

lossがマイナスになる

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 1,532

score 20

tensorflowのチュートリアルで犬と猫を学習させるプログラムがあったので、それを書き換えて自分と妹を学習させようと思ったのですが、学習するたびにlossの値がマイナスになります。以下が実行したプログラムと結果とtensorflowのチュートリアルのURLです。
ほぼチュートリアル、マルパクリでファイルの場所だけ変更しました。
犬、猫で実行した場合lossがマイナスになることはないのですが、自分と妹の顔切り取り写真ではlossがマイナスになります。

顔切り取りした画像を明度を変更したり傾けたりして水増しし、5000枚くらいまでふやしました。また、画像の大きさは統一にしなければならないと思っていたので、顔の画像を200×200に統一しました。

まだ、tensorflowを触り始めたばかりということもあり、何をどういう動作をしているのか、どう調べればよいのかよくわかっていません。
投げやりの質問になったしまったのですが、本当にどうすればよいのかわからないため、ご教授お願い致します。

行ったこと

画像のサイズが200×200にしたため、おかしいデータになったのかのとおもい、IMG_HEIGHT = 200,IMG_WIDTH = 200に変更しました。
が、結果は変わりませんでした。
そもそも、IMG_HEIGHTが何を示しているのかも調べてみましたがよくわかりませんでした。

tensorflowのチュートリアル

import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Conv2D, Flatten, Dropout, MaxPooling2D
from tensorflow.keras.preprocessing.image import ImageDataGenerator

import os
import numpy as np
import matplotlib.pyplot as plt

PATH = 'C:/GraduationResearch/annotation/data'

train_dir = os.path.join(PATH, 'train')
validation_dir = os.path.join(PATH, 'validation')

train_me_dir = os.path.join(train_dir, 'me')  
train_sister2_dir = os.path.join(train_dir, 'sister2')  
validation_me_dir = os.path.join(validation_dir, 'me')  
validation_sister2_dir = os.path.join(validation_dir, 'sister2')

num_me_tr = len(os.listdir(train_me_dir))
num_sister2_tr = len(os.listdir(train_sister2_dir))

num_me_val = len(os.listdir(validation_me_dir))
num_sister2_val = len(os.listdir(validation_sister2_dir))
# num_father_val = len(os.listdir(validation_father_dir))

total_train = num_me_tr + num_sister2_tr
total_val = num_me_val  + num_sister2_val

print(total_train)
print(total_val)

batch_size = 128
epochs = 1
IMG_HEIGHT = 150
IMG_WIDTH = 150

train_image_generator = ImageDataGenerator(rescale=1./255) 
validation_image_generator = ImageDataGenerator(rescale=1./255)
print(train_image_generator)
print(validation_image_generator)
print("-------------------------------")


train_data_gen = train_image_generator.flow_from_directory(batch_size=batch_size,
                                                           directory=train_dir,
                                                           shuffle=True,
                                                           target_size=(IMG_HEIGHT, IMG_WIDTH),
                                                           class_mode='binary')

val_data_gen = validation_image_generator.flow_from_directory(batch_size=batch_size,
                                                              directory=validation_dir,
                                                              target_size=(IMG_HEIGHT, IMG_WIDTH),
                                                              class_mode='binary')

sample_training_images, _ = next(train_data_gen)

def plotImages(images_arr):
    fig, axes = plt.subplots(1, 5, figsize=(20,20))
    axes = axes.flatten()
    for img, ax in zip( images_arr, axes):
        ax.imshow(img)
        ax.axis('off')
    plt.tight_layout()
    plt.show()

model = Sequential([
    Conv2D(16, 3, padding='same', activation='relu', input_shape=(IMG_HEIGHT, IMG_WIDTH ,3)),
    MaxPooling2D(),
    Conv2D(32, 3, padding='same', activation='relu'),
    MaxPooling2D(),
    Conv2D(64, 3, padding='same', activation='relu'),
    MaxPooling2D(),
    Flatten(),
    Dense(512, activation='relu'),
    Dense(1, activation='sigmoid')
])

model.compile(optimizer='adam',
              loss='binary_crossentropy',
              metrics=['accuracy'])

history = model.fit_generator(
    train_data_gen,
    steps_per_epoch=total_train // batch_size,
    epochs=epochs,
    validation_data=val_data_gen,
    validation_steps=total_val // batch_size
)

acc = history.history['accuracy']
val_acc = history.history['val_accuracy']

loss = history.history['loss']
val_loss = history.history['val_loss']

epochs_range = range(epochs)

plt.figure(figsize=(8, 8))
plt.subplot(1, 2, 1)
plt.plot(epochs_range, acc, label='Training Accuracy')
plt.plot(epochs_range, val_acc, label='Validation Accuracy')
plt.legend(loc='lower right')
plt.title('Training and Validation Accuracy')

plt.subplot(1, 2, 2)
plt.plot(epochs_range, loss, label='Training Loss')
plt.plot(epochs_range, val_loss, label='Validation Loss')
plt.legend(loc='upper right')
plt.title('Training and Validation Loss')
plt.show()

model.save('catdig.h5') 

![イメージ説明

解決法

dataファイルの中にme,sister2,fatherの3つが存在したため、labelが0,1,2と増えた。その結果、lossがマイナスになった。
me,sister2で学習させた場合0<loss<1の間に収まった。
多分学習できていると思う。

イメージ説明

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

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

  • miyabi_takatsuk

    2021/02/18 21:10

    質問タグに、Pythonと機械学習、画像解析などを入れた方がいいかと。
    質問は編集できますので

    キャンセル

  • nyanryou

    2021/02/18 21:23

    アドバイスありがとうございます!!

    キャンセル

  • toast-uz

    2021/02/20 08:43

    事象としては正解ラベルに0〜1以外のものが入っているということですが、データ作成に間違いはなさそうなので、謎ですね。

    キャンセル

回答 1

checkベストアンサー

0

binary_crossentropyのlossがマイナスになるのは、モデルの出力またはラベルに0〜1以外の値が含まれている時です。モデルの出力にはsigmoidが入っていますので、ラベルの方に問題があると思います。

おそらくですが、画像ディレクトリに、犬猫など他のサブフォルダが含まれているままなのでないでしょうか?3つ以上のサブディレクトリがあると、flow_from_directoryclass_mode='binary'としていても、エラーにならずに、2以上のラベルがジェネレートされるようです(動かして確認しました)。

なお以下のコードを実行すると、どのようなラベルになっているか、具体的にわかります。

images, labels = next(train_data_gen)
print(labels)

上記の推測が的中していた場合、サブディレクトリを2つだけにするか、classes=['me', 'sister2']というオプションを加えて明示的にサブディレクトリを指定するか、で問題解消すると思います。

なお、元のイメージサイズは揃えなくてよいです。target_sizeオプションで自動的に揃ったサイズに変換してくれますので。もちろん、アスペクト比が違いすぎる画像が混在すると、変換後が歪むので、学習効率が悪くなってしまいますが。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2021/02/20 15:21

    詳しく教えていただきありがとうございます!!
    dataファイルの中にme,sister2,fatherを入れていたのが原因でした。
    labelも犬猫は0,1でしたが、me,sister2,fatherだと0,1,2が含まれていました。ファイルでラベル付けしているとはわかりませんでした。大変勉強になりました。
    また、予想的中すごすぎです…。
    fatherのファイルを消し学習してみたところlossがマイナスになることなく学習が出来ました!
    target_sizeのオプションも知らなかったので本当に助かりました!!
    ありがとうございます!

    キャンセル

  • 2021/02/20 15:30

    すみません。何点かお聞きしたいことがあるのですがよろしいでしょうか…
    ・どの部分でファイルにラベル付けをしているのか
    ・今回はme,sister2で学習が成功しました。しかし、me,sister2,fatherの3つを学習させる場合どうすればよいのか。train_me_dir,train_sister_dir,train_father_dirのようにfatherファイルも指定されるように変更しましたが、labelが0,1,2となるせいか、やはりマイナスになります。複数ファイルでの学習がどこなのか知りたいです。
    ・関係ないのですが、最近機械学習の勉強をしているのですが、どのように学んだのですか?解説などを見ても理解ができなくてわからない状態のままになってしまいます…。

    お手数でなければご教授いただけたら幸いです。

    キャンセル

  • 2021/02/20 16:03

    今回の例では、flow_from_directoryというメソッドが自動的にサブディレクトリをもとにラベルに変換しています。また3つのサブディレクトリを学習させるには、多クラス分類問題にする必要があります。
    https://qiita.com/Phoeboooo/items/cfe8560fe8a285855340 など参考になると思います。

    機械学習を学ぶには、現実に解きたい問題を解くのが一番です。まさに、今回の問題を多クラス分類になおしてみるのもその1つです。示したリンクのコードはやや古いので、それをコピペするのではなく参考にとどめて、今回のコードを自分で変更して多クラス分類に変えてみましょう。変更した部分の意味をよく確認しながら進めるとよいと思います。そういう一歩一歩で、機械学習がわかるようになります。勉強していけば、例えば、GANという手法を使ってあなたの顔写真に別の人の表情(笑い顔とか)を合成する、といったこともできますよ。興味にままにいろいろ試してみてください。

    キャンセル

  • 2021/02/20 16:30

    返信ありがとうございます!
    多クラス分類がんばってみます!
    何でも少しずつ理解ですよね…
    ありがとうございました。大変助かりました!

    キャンセル

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

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

関連した質問

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