Суть этого вопроса:
Я бы хотел найти правильный способ вычисления Fscore для данных проверки и обучения после каждой эпохи (не пакетно)
Для задачи двоичной классификации я хотел бы вычислить Fscore
после каждой эпохи, используя простую модель keras
. Но вопрос о том, как вычислить Fscore
, кажется довольно обсуждаемым.
Я знаю, что keras
работает пакетно, и один из способов вычисления fscore для каждой партии будет { ссылка } (Расчет Fscore: f1
).
Пакетный расчет может быть довольно запутанным, и я предпочитаю рассчитывать Fscore после каждой эпохи . Поэтому простой вызов history.history['f1']
или history.history['val_f1']
делает трюк , а не , потому что он показывает пакетные fscores.
Я решил, что один из способов - сохранить каждую модель с помощью
from keras.callbacks import ModelCheckpoint
функция:
- Сохранение веса каждой модели после каждой эпохи
- Повторная загрузка модели и использование
model.evaluate
или model.predict
Редактировать:
Используя бэкэнд тензорного потока, я решил отслеживать TruePositives
, FalsePositives
и FalseNegatives
(как предложил зонтик29). Но теперь самое интересное: Результаты при перезагрузке модели отличаются для обучающих данных (TP, FP, FN разные) но не для набора проверки!
Итак, простая модель, хранящая веса для восстановления каждой модели и пересчета TP, FN, TP (и, наконец, Fscore), выглядит так:
from keras.metrics import TruePositives, TrueNegatives, FalseNegatives, FalsePositives
## simple keras model
sequence_input = Input(shape=(input_dim,), dtype='float32')
preds = Dense(1, activation='sigmoid',name='output')(sequence_input)
model = Model(sequence_input, preds)
model.compile(loss='binary_crossentropy',
optimizer='adam',
metrics=[TruePositives(name='true_positives'),
TrueNegatives(name='true_negatives'),
FalseNegatives(name='false_negatives'),
FalsePositives(name='false_positives'),
f1])
# model checkpoints
filepath="weights-improvement-{epoch:02d}-{val_f1:.2f}.hdf5"
checkpoint = ModelCheckpoint(os.path.join(savemodel,filepath), monitor='val_f1', verbose=1, save_best_only=False, save_weights_only=True, mode='auto')
callbacks_list = [checkpoint]
history = model.fit(x_train, y_train, validation_data=(x_val, y_val), epochs=epoch, batch_size=batch,
callbacks=[callbacks_list])
## Saving TP, FN, FP to calculate Fscore
tp.append(history.history['true_positives'])
fp.append(history.history['false_positives'])
fn.append(history.history['false_negatives'])
arr_train = np.stack((tp, fp, fn), axis=1)
## doing the same for tp_val, fp_val, fn_val
[...]
arr_val = np.stack((tp_val, fp_val, fn_val), axis=1)
## following method just showes batch-wise fscores and shouldnt be used:
## f1_sc.append(history.history['f1'])
Перезагрузка модели после каждой эпохи для вычисления Fscore (Метод predict
с sklearn fscore metri c from sklearn.metrics import f1_score
эквивалентен вычислению fscore metri c из TP, FP, FN):
Fscore_val = []
fscorepredict_val_sklearn = []
Fscore_train = []
fscorepredict_train = []
## model_loads contains list of model-paths
for i in model_loads:
## rebuilding the model each time since only weights are stored
sequence_input = Input(shape=(input_dim,), dtype='float32')
preds = Dense(1, activation='sigmoid',name='output')(sequence_input)
model = Model(sequence_input, preds)
model.load_weights(i)
# Compile model (required to make predictions)
model.compile(loss='binary_crossentropy',
optimizer='adam',
metrics=[TruePositives(name='true_positives'),
TrueNegatives(name='true_negatives'),
FalseNegatives(name='false_negatives'),
FalsePositives(name='false_positives'),
f1
])
### For Validation data
## using evaluate
y_pred = model.evaluate(x_val, y_val, verbose=0)
Fscore_val.append(y_pred) ## contains (loss,tp,fp,fn, f1-batchwise)
## using predict
y_pred = model.predict(x_val)
val_preds = [1 if x > 0.5 else 0 for x in y_pred]
cm = f1_score(y_val, val_preds)
fscorepredict_val_sklearn.append(cm) ## equivalent to Fscore calculated from Fscore_vals tp,fp, fn
### For the training data
y_pred = model.evaluate(x_train, y_train, verbose=0)
Fscore_train.append(y_pred) ## also contains (loss,tp,fp,fn, f1-batchwise)
y_pred = model.predict(x_train, verbose=0) # gives probabilities
train_preds = [1 if x > 0.5 else 0 for x in y_pred]
cm = f1_score(y_train, train_preds)
fscorepredict_train.append(cm)
Расчет Fscore из tp, fn и fp с использованием Fscore_val
tp, fn, fp и сравнение его с fscorepredict_val_sklearn
эквивалентно и идентично вычислению его из arr_val
.
Однако, количество tp, fn и fp отличается при сравнении Fscore_train
и arr_train
. Таким образом, я получаю разные оценки. Количество tp, fn, fp должно быть одинаковым, но их нет .. Это ошибка?
Кому из них мне доверять? На самом деле fscorepredict_train
кажутся более заслуживающими доверия, поскольку они начинаются выше «всегда угадывает класс 1» -Fscore (при отзыве = 1). (fscorepredict_train[0]=0.6784
vs f_hist[0]=0.5736
vs always-guessing-class-1-fscore = 0,6751)
[ Примечание: Fscore_train[0] = [0.6853608025386962, 2220.0, 250.0, 111.0, 1993.0, 0.6730511784553528]
(loss, tp, tn, fp, fn) приводит к fscore = 0,6784, поэтому Fscore от Fscore_train = fscorepredict_train]