Я попытался определить пользовательскую метрическую функцию (F1-Score) в Keras (бэкэнд Tensorflow) согласно следующему:
def f1_score(tags, predicted):
tags = set(tags)
predicted = set(predicted)
tp = len(tags & predicted)
fp = len(predicted) - tp
fn = len(tags) - tp
if tp>0:
precision=float(tp)/(tp+fp)
recall=float(tp)/(tp+fn)
return 2*((precision*recall)/(precision+recall))
else:
return 0
Пока все хорошо, но когда я пытаюсь применить его при компиляции модели:
model1.compile(loss="binary_crossentropy", optimizer=Adam(), metrics=[f1_score])
это дает ошибку:
TypeError Traceback (most recent call last)
<ipython-input-85-4eca4def003f> in <module>()
5 model1.add(Dense(output_dim=10, activation="sigmoid"))
6
----> 7 model1.compile(loss="binary_crossentropy", optimizer=Adam(), metrics=[f1_score])
8
9 h=model1.fit(X_train, Y_train, batch_size=500, nb_epoch=5, verbose=True, validation_split=0.1)
/home/buda/anaconda2/lib/python2.7/site-packages/keras/models.pyc in compile(self, optimizer, loss, metrics, sample_weight_mode, **kwargs)
522 metrics=metrics,
523 sample_weight_mode=sample_weight_mode,
--> 524 **kwargs)
525 self.optimizer = self.model.optimizer
526 self.loss = self.model.loss
/home/buda/anaconda2/lib/python2.7/site-packages/keras/engine/training.pyc in compile(self, optimizer, loss, metrics, loss_weights, sample_weight_mode, **kwargs)
664 else:
665 metric_fn = metrics_module.get(metric)
--> 666 self.metrics_tensors.append(metric_fn(y_true, y_pred))
667 if len(self.output_names) == 1:
668 self.metrics_names.append(metric_fn.__name__)
<ipython-input-84-b8a5752b6d55> in f1_score(tags, predicted)
4 #tf.convert_to_tensor(img.eval())
5
----> 6 tags = set(tags)
7 predicted = set(predicted)
8
/home/buda/anaconda2/lib/python2.7/site-packages/tensorflow/python/framework/ops.pyc in __iter__(self)
493 TypeError: when invoked.
494 """
--> 495 raise TypeError("'Tensor' object is not iterable.")
496
497 def __bool__(self):
TypeError: 'Tensor' object is not iterable.
В чем здесь проблема? Тот факт, что мои функциональные входы f1_score не Tensorflow массивов? Если да, то где / как я могу их правильно конвертировать?
tensorflow
keras
evaluation
Хендрик
источник
источник
eval
когда вы имеете в видуeval()
Ответы:
Вы должны использовать бэкэнд-функции Keras . К сожалению, они не поддерживают
&
-оператор, поэтому вам нужно создать обходной путь: мы генерируем матрицы измеренияbatch_size x 3
, где (например, для истинного положительного) первый столбец - это вектор истинности основания, второй - фактическое предсказание, а третий - вид столбца метки-помощника, который содержит в случае истинно положительных только единицы. Затем мы проверяем, какие экземпляры являются положительными, прогнозируются как положительные, а метка-помощник также положительна. Это настоящие плюсы.Мы можем сделать этот аналог с ложными срабатываниями, ложными отрицаниями и истинными отрицаниями с некоторыми обратными вычислениями меток.
Ваша метрика f1 может выглядеть следующим образом:
Так как калькулятор Keras-backend возвращает nan для деления на ноль, нам не нужен оператор if-else для оператора return.
Редактировать: я нашел довольно хорошую идею для точной реализации. Проблема с нашим первым подходом состоит в том, что он является только «аппроксимированным», поскольку он вычисляется по частям и впоследствии усредняется. Можно также рассчитать это после каждой эпохи с
keras.callback
s. Пожалуйста, найдите идею здесь: https://github.com/fchollet/keras/issues/5794Примером реализации будет:
Чтобы заставить сеть вызывать эту функцию, вы просто добавляете ее к своим обратным вызовам, таким как
Тогда вы можете просто получить доступ к членам
metrics
переменной.источник