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

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

ただいまの
回答率

88.92%

ターゲットサンプルと入力配列の違いの原因

解決済

回答 1

投稿

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

maguro2020

score 21

前提・実現したいこと

GitHub WeaklyAnomalyDetection

上記サイト様を参考に、Pythonと自前のデータセットを用いて異常検知を行いたいと考えております。

発生している問題・エラーメッセージ

発生している問題の詳細は「#試していること」で述べさせていただきますが、x_train,y_train,x_test_y_testの出力結果が全て異なってしまい、頭を悩ませております。

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-11-7bfdc75aa020> in <module>
      1 # 普通の異常検知
      2 for i in range(2):
----> 3     train_and_evaluate(i+1, False)
      4 
      5 # 弱異常検知

<ipython-input-10-6e38c831f860> in train_and_evaluate(number, anomaly)
     50                      batch_size=128,
     51                      epochs=50,
---> 52                      verbose = False)
     53 
     54 

~/.pyenv/versions/3.6.5/lib/python3.6/site-packages/keras/engine/training.py in fit(self, x, y, batch_size, epochs, verbose, callbacks, validation_split, validation_data, shuffle, class_weight, sample_weight, initial_epoch, steps_per_epoch, validation_steps, validation_freq, max_queue_size, workers, use_multiprocessing, **kwargs)
   1152             sample_weight=sample_weight,
   1153             class_weight=class_weight,
-> 1154             batch_size=batch_size)
   1155 
   1156         # Prepare validation data.

~/.pyenv/versions/3.6.5/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)
    635             # Check that all arrays have the same length.
    636             if check_array_lengths:
--> 637                 training_utils.check_array_length_consistency(x, y, sample_weights)
    638             if self._is_graph_network:
    639                 # Additional checks to avoid users mistakenly

~/.pyenv/versions/3.6.5/lib/python3.6/site-packages/keras/engine/training_utils.py in check_array_length_consistency(inputs, targets, weights)
    242                          'the same number of samples as target arrays. '
    243                          'Found ' + str(list(set_x)[0]) + ' input samples '
--> 244                          'and ' + str(list(set_y)[0]) + ' target samples.')
    245     if len(set_w) > 1:
    246         raise ValueError('All sample_weight arrays should have '

ValueError: Input arrays should have the same number of samples as target arrays. Found 520 input samples and 1010 target samples.

コード

(自前のコードは文字数制限のため、省略いたしました)
異常検知のコード

import matplotlib.pyplot as plt
import os
import cv2
import random
import numpy as np
from keras.utils import to_categorical
from keras.preprocessing.image import ImageDataGenerator

from b_c_dataset import BCN_Dataset

bell = 0#bellは0
call = 1#callは1

# dataset
(x_train, y_train), (x_test, y_test) = BCN_Dataset.create_bcn()

x_train = x_train.reshape(x_train.shape[0], 583, 438, 3)
x_test = x_test.reshape(x_test.shape[0], 583, 438, 3)

x_train = x_train.astype('float32') / 255
x_test = x_test.astype('float32') / 255

#学習データ
x_train_sum, x_train_c, x_train_b, x_test_c, x_test_b = [], [], [], [], []
y_train_sum = []

for i in range(len(x_train)):
    if y_train[i] == bell:
        x_train_b.append(x_train[i])
    elif y_train[i] == call:
        x_train_c.append(x_train[i])
    else:
        x_train_sum.append(x_train[i])
        y_train_sum.append(y_train[i])

x_train_sum = np.array(x_train_sum)
x_train_b = np.array(x_train_b)
x_train_c = np.array(x_train_c)

#trainデータからランダムに10個抽出
number = np.random.choice(np.arange(0,x_train_sum.shape[0]),10,replace=False)

x, y = [], []

for i in number:
    x.append(x_train_sum[i])
    y.append(y_train_sum[i])

x_train_sum = np.array(x)
y_train_sum = np.array(y)

#callデータからランダムに10個抽出
number = np.random.choice(np.arange(0,x_train_c.shape[0]),10,replace=False)

x, y = [], []

for i in number:
    x.append(x_train_c[i])

#データ結合
x_train_sum = np.vstack((x_train_sum, np.array(x)))
y_train_sum = np.hstack((y_train_sum, call*np.ones(500)))

#bellデータからランダムに10個抽出
number = np.random.choice(np.arange(0,x_train_b.shape[0]),10,replace=False)

x, y = [], []

for i in number:
    x.append(x_train_b[i])

# Data Augmentation
datagen = ImageDataGenerator(rotation_range=10,
                             width_shift_range=0.1,
                             height_shift_range=0.1,
                             horizontal_flip=False)
img = []

for d in datagen.flow(np.array(x), batch_size=1):
    # このあと画像を表示するためにndarrayをPIL形式に変換して保存する
    img.append(d[0])
    # datagen.flowは無限ループするため必要な枚数取得できたらループを抜ける
    if len(img) == 500:
        print("finish")
        break

#データ結合
x_train_sum = np.vstack((x_train_sum, np.array(img)))
y_train_sum = np.hstack((y_train_sum, bell*np.ones(500)))
y_train_sum = to_categorical(y_train_sum)

#テストデータ
for i in range(len(x_test)):
    if y_test[i] == 1:#callは1
        x_test_c.append(x_test[i])

    if y_test[i] == 0:#bellは0
        x_test_b.append(x_test[i])

x_test_c = np.array(x_test_c)
x_test_b = np.array(x_test_b)

**#こちらの出力結果が元のサイト様と異なります(※1)**
print(x_train_sum.shape)
print(y_train_sum.shape)
print(x_test_c.shape)
print(x_test_b.shape)


#96 * 96 ** 3にリサイズ
import cv2
from PIL import Image

def resize(x):
    x_out = []

    for i in range(len(x)):
        img = cv2.cvtColor(x[i], cv2.COLOR_RGB2BGR)
        img = cv2.resize(img,dsize=(96,96))
        x_out.append(img)

    return np.array(x_out)

X_train_sum = resize(x_train_sum)
X_test_c = resize(x_test_c)
X_test_b = resize(x_test_b)


#metric learning
import keras
from keras.applications import MobileNetV2
from keras.optimizers import Adam, SGD
from keras.models import Model
from keras.layers import GlobalAveragePooling2D, Dense
from keras import backend as K

from sklearn.neighbors import LocalOutlierFactor
from sklearn import metrics
from sklearn.preprocessing import MinMaxScaler


input_shape = (96, 96, 3)
classes = 3
batchsize = 128
alpha = 0.5

def train_and_evaluate(number, anomaly=True):
    # mobile net読み込み
    print("Model build...")

    mobile = MobileNetV2(include_top=True, input_shape=input_shape, alpha=alpha,
                     weights='imagenet')

    # 最終層削除
    mobile.layers.pop()
    model = Model(inputs=mobile.input,outputs=mobile.layers[-1].output)

    # L2層と全結合層を付ける
    c = keras.layers.Lambda(lambda xx: 5*(xx)/K.sqrt(K.sum(xx**2)))(model.output) #metric learning
    c = Dense(classes, activation='softmax')(c)
    model = Model(inputs=model.input,outputs=c)

    #model.summary()

    model.compile(loss='categorical_crossentropy',
                  optimizer=Adam(amsgrad=True),
                  metrics=['accuracy'])

    print(number,"training...")

    #cnnの学習
    if anomaly == True:
        train_NO = 5000
    else:
        train_NO = 4500

    hist = model.fit(X_train_sum[:train_NO],
                     y_train_sum[:train_NO],
                     batch_size=128,
                     epochs=50,
                     verbose = False)


    # 最終層削除
    model.layers.pop()
    model = Model(inputs=model.input,outputs=model.layers[-1].output)

    train = model.predict(X_train_sum[4000:4500], batch_size=1)#スニーカー
    test_c = model.predict(X_test_c, batch_size=1)
    test_b = model.predict(X_test_b, batch_size=1)

    train = train.reshape((len(train),-1))
    test_c = test_s.reshape((len(X_test_c),-1))
    test_b = test_b.reshape((len(X_test_b),-1))

    #0-1変換
    ms = MinMaxScaler()
    train = ms.fit_transform(train)
    test_c = ms.transform(test_c)
    test_b = ms.transform(test_b)

    # LOF
    clf = LocalOutlierFactor(n_neighbors=5)
    y_pred = clf.fit(train)

    # plot the level sets of the decision function
    Z1 = -clf._decision_function(test_c)
    Z2 = -clf._decision_function(test_b)

    #ROC曲線の描画
    y_true = np.zeros(len(test_c)+len(test_b))
    y_true[len(test_c):] = 1#0:正常、1:異常

    # FPR, TPR(, しきい値) を算出
    fpr, tpr, _ = metrics.roc_curve(y_true, np.hstack((Z1, Z2)))

    # AUC
    auc = metrics.auc(fpr, tpr)

    # ROC曲線をプロット
    plt.plot(fpr, tpr, label='metric learning(AUC = %.2f)'%auc)
    plt.legend()
    plt.title(str(number)+'ROC curve')
    plt.xlabel('False Positive Rate')
    plt.ylabel('True Positive Rate')
    plt.grid(True)
    plt.show()

#ここより下のコードを実行した際に、上記のエラーメッセージが発生いたしました。
# 普通の異常検知
for i in range(2):
    train_and_evaluate(i+1, False)

# 弱異常検知
for i in range(2):
    train_and_evaluate(i+1)


異常検知のコードはまだ続きがありますが、エラーが発生してしまったため省略させていただきます。
※1:「#試していること」で出力結果の違いについて述べさせていただきます。

試していること

コードの途中に記載させていただいた(※1)の出力結果は以下のようになっておりました。
自前のデータセットで実行した際の出力結果

#異常検知の途中のコード
print(x_train_sum.shape)
print(y_train_sum.shape)
print(x_test_c.shape)
print(x_test_b.shape)

#出力結果
finish
(520, 583, 438, 3)
(1010, 3)
(24, 583, 438, 3)
(56, 583, 438, 3)

元のサイト様のコードの出力結果

print(x_train_sum.shape)
print(y_train_sum.shape)
print(x_test_c.shape)
print(x_test_b.shape)

# 出力結果
finish
(5000, 28, 28, 1)
(5000, 10)
(1000, 28, 28, 1)
(1000, 28, 28, 1)


注)画像サイズの違いは当方も把握しております。(サイト様は28,28の画像データ。自分は583,438の画像データです。)
エラーメッセージの原因は、上記に記載したx_train_sum.shape、y_train_sum.shape、x_test_c.shape、x_test_b.shapeの数が一致していないことではないかと考えております。また、元のサイト様の画像サイズは確かに、当初、使用する予定だった自前のデータセットのbellとcallのtrainデータの数は一致しておりませんでした。そこでデータ数を揃えるため、bell、callの元のトレーニング画像データを60枚にいたしました。(ちなみにnoiseのトレーニング画像データは11枚です)しかし、出力結果は変わらず、上記と同じになってしまい頭を悩ませております。

自前のデータセットの詳細です。
トレーニングデータ(train)
bell:60枚
call:60枚
noise:11枚

テストデータ(test)
bell:28枚
call:12枚
noise:10枚

クラス数はbell、call、noiseの3クラスです。

補足

使っているPCはmacOS Catalina バージョン10.15.5
Pythonのバージョンは3.6.5です
Jupiter notebookを使用しています

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

checkベストアンサー

+1

元サイトのコードを見ますと

4000枚⁺スニーカー500枚⁺ブーツ500枚で5000

ですが例示いただきましたコードを見ますと

callは60枚とのことですが元サイトのコードのまま500枚分追加している

y_train_sum = np.hstack((y_train_sum, call*np.ones(500)))

bellは60枚とのことですが元サイトのコードのまま500枚分追加している

y_train_sum = np.hstack((y_train_sum, bell*np.ones(500)))

など元サイトのコードと例示いただいたコードを比較しますと
データ件数が異なるのに、数値を投入した件数に合わせず元サイトのコードのままの数字としている
からだと思います。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2020/07/20 13:42

    ご回答いただきありがとうございます。aokikenichi様。
    aokikenichi様のおかげで、エラーを解消することができました。本当にありがとうございました。

    キャンセル

  • 2020/07/20 18:08

    お役に立てたようでよかったです

    たぶんそこらへんの可変な数値は関数内に直接書かずに冒頭辺りに設定値としてまとめた方が
    美しい書き方ですね

    キャンセル

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

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

関連した質問

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