web-dev-qa-db-ja.com

kerasflow_from_directoryクラスのオーバーサンプリングまたはアンダーサンプリング

ImageDataGenerator.flow_from_directoryメソッドを使用してバッチを生成し、Kerasでバイナリ分類の問題を実行しようとしています。ただし、私のクラスは非常に不均衡であり、1つのクラスが他のクラスよりも約8倍または9倍多いため、すべての例で同じ出力クラスを予測してモデルがスタックします。 flow_from_directoryを、各エポック中に小さなクラスからオーバーサンプリングするか、大きなクラスからアンダーサンプリングするように設定する方法はありますか?今のところ、小さいクラスで各画像の複数のコピーを作成しましたが、もう少し柔軟性を持たせたいと思います。

12
George

現在のバージョンのKerasでは、Kerasの組み込みメソッドのみを使用してデータセットのバランスを取ることはできません。 flow_from_directoryは、すべてのファイルとそのクラスのリストを作成し、(必要に応じて)シャッフルしてから、それを繰り返し処理するだけです。

しかし、別のトリックを行うことができます-python内でバランスをとる独自のジェネレーターを作成することによって:

def balanced_flow_from_directory(flow_from_directory, options):
    for x, y in flow_from_directory:
         yield custom_balance(x, y, options)

ここに custom_balanceはバッチを与える関数でなければなりません(x, y)はそれをバランスさせ、バランスの取れたバッチを返します(x', y')。ほとんどのアプリケーションでは、バッチのサイズは同じである必要はありませんが、いくつかの奇妙なユースケースがあります(たとえば、 ステートフル RNN)-バッチサイズは固定サイズである必要があります)。

9
Marcin Możejko

model.fit()またはmodel.fit_generator()を呼び出すときにclass_weightパラメーターを設定することができます。

また、次のようにsklearnおよびnumpyライブラリを使用してclass_weightsを簡単に計算できることもあります。

from sklearn.utils import class_weight
import numpy as np

class_weights = class_weight.compute_class_weight(
           'balanced',
            np.unique(train_generator.classes), 
            train_generator.classes)

その後、class_weightsclass_weightパラメータに等しく設定するのと同じくらい簡単になります。

model.fit_generator(..., class_weight=class_weights) 
4
Pasha Dembo

各クラスのファイル数を計算し、class_weightsを正規化することもできます

files_per_class = []
for folder in os.listdir(input_foldr):
    if not os.path.isfile(folder):
            files_per_class.append(len(os.listdir(input_foldr + '/' + folder)))
total_files = sum(files_per_class)
class_weights = {}
for i in xrange(len(files_per_class)):
    class_weights[i] = 1 - (float(files_per_class[i]) / total_files)
print (class_weights)
...
...
...
model.fit_generator(... ,class_weight=class_weights)
1
Michael