ImageDataGenerator.flow_from_directory
メソッドを使用してバッチを生成し、Kerasでバイナリ分類の問題を実行しようとしています。ただし、私のクラスは非常に不均衡であり、1つのクラスが他のクラスよりも約8倍または9倍多いため、すべての例で同じ出力クラスを予測してモデルがスタックします。 flow_from_directory
を、各エポック中に小さなクラスからオーバーサンプリングするか、大きなクラスからアンダーサンプリングするように設定する方法はありますか?今のところ、小さいクラスで各画像の複数のコピーを作成しましたが、もう少し柔軟性を持たせたいと思います。
現在のバージョンの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)-バッチサイズは固定サイズである必要があります)。
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_weights
をclass_weight
パラメータに等しく設定するのと同じくらい簡単になります。
model.fit_generator(..., class_weight=class_weights)
各クラスのファイル数を計算し、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)