【问题标题】:Custom Metric for ADR and FAR in KerasKeras 中 ADR 和 FAR 的自定义指标
【发布时间】:2017-01-23 16:09:57
【问题描述】:

我需要在带有 tensorflow 后端的 keras 中定义一个自定义指标,以获取 ADR 和 FAR 指标,其中:

  • ADR 是正确检测到的第 1 类元素数与第 1 类元素总数之比。

  • FAR 是被错误分类为 1 类元素的 0 类元素的数量与 0 类元素的总数之间的比率。

目前,我已经能够计算出每个类的元素总数:

def false_rates(y_true, y_pred):
    total_1 = K.sum(tf.cast(tf.equal(y_true, 1), 'int32'))
    total_0 = K.sum(tf.cast(tf.equal(y_true, 0), 'int32'))
    # [...]

现在,对于张量中的每个索引i,我需要计算有多少:

  • y_true[i] == 1 and y_pred[i] == 1 用于 ADR
  • y_true[i] == 0 and y_pred[i] == 1 代表 FAR

但我不知道如何使用 tensorflow 操作来做到这一点,我得到的最接近的是:

adr = K.sum(
        tf.cast(
            tf.equal(
                tf.add(
                    tf.cast(tf.equal(y_true, 1), 'int32'),
                    tf.cast(tf.equal(y_pred, 1), 'int32')), 2), 'int32'))

# far = ...?

但它似乎只返回 0。

感谢您的帮助!


编辑以包含完整的代码:

# coding: utf-8
import csv
import numpy as np
import os

os.environ["KERAS_BACKEND"] = "tensorflow"

from keras import backend as K
from keras.callbacks import ModelCheckpoint, EarlyStopping, TensorBoard
from keras.layers import Convolution2D
from keras.models import Sequential
from keras.optimizers import RMSprop, SGD
from keras.layers.core import Dense, Dropout
from keras.layers.recurrent import LSTM
from keras.layers.embeddings import Embedding
from keras.preprocessing.sequence import pad_sequences
from keras.preprocessing.text import one_hot

def build_model(input_shape, n1, dropout_p, n_symbols, n_sequence):
    model = Sequential()
    model.add(Embedding(n_symbols+1,
                        output_dim=n1,
                        input_length=n_sequence))
    model.add(LSTM(n1))
    model.add(Dropout(dropout_p))
    model.add(Dense(1))
    return model

def load_sequences(path):
    X, y = [], []
    with open(path,'r') as file:
        reader = csv.reader(file)
        for line in reader:
                X.append(line[0])
                y.append(int(line[1]))
    return np.array(X), np.array(y)

def adr_and_far(y_true, y_pred):
    total_adr = K.sum(K.tf.cast(K.tf.equal(y_true, 1), 'int32'))
    total_far = K.sum(K.tf.cast(K.tf.equal(y_true, 0), 'int32'))

    adr_idx = K.tf.equal(y_true, 1) & K.tf.equal(y_pred, 1)
    adr_idx = K.tf.reshape(K.tf.where(adr_idx), [-1])

    far_idx = K.tf.equal(y_true, 0) & K.tf.equal(y_pred, 1)
    far_idx = K.tf.reshape(K.tf.where(far_idx), [-1])

    num_adr = K.tf.shape(adr_idx)[0]  # 3
    num_far = K.tf.shape(far_idx)[0]  # 2

    return { 'total_adr': total_adr,
             'adr': num_adr / total_adr,
             'total_far': total_far,
             'far': num_far / total_far
           }

simbols = ['1','a','A','r','2','b','B','s','3','c','C','t','4','d','D','u','5','e','E','v','6','f','F','w','7','g','G','x','8','h','H','y','9','i','I','z', ',', '.', '*', '+', '0']
n_symbols = len(simbols) # dimensionality of your word vectors

max_len_sequence = 20
input_shape = (max_len_sequence, n_symbols)
n1 = 128 # From Paper
dropout_p = 0.1
loss_method = 'binary_crossentropy'

optimizer = 'adam'
model = build_model(input_shape, n1, dropout_p, n_symbols, max_len_sequence)
model.compile(loss=loss_method, optimizer=optimizer, metrics=['accuracy', adr_and_far])

还有错误:

 Using TensorFlow backend.
Traceback (most recent call last):
  File "1%29+Training+RNN+Single+Model.py", line 68, in <module>
    model.compile(loss=loss_method, optimizer=optimizer, metrics=['accuracy', adr_and_far])
  File "/usr/local/lib/python2.7/site-packages/keras/models.py", line 594, in compile
    **kwargs)
  File "/usr/local/lib/python2.7/site-packages/keras/engine/training.py", line 716, in compile
    metric_result = metric_fn(y_true, y_pred)
  File "1%29+Training+RNN+Single+Model.py", line 43, in adr_and_far
    adr_idx = K.tf.reshape(K.tf.where(adr_idx), [-1])
TypeError: select() takes at least 3 arguments (1 given)

【问题讨论】:

    标签: tensorflow keras


    【解决方案1】:

    你只需要数数吗?

    y_true = tf.constant([1, 1, 1, 0, 0, 0, 1, 1, 1])
    y_pred = tf.constant([1, 1, 0, 1, 1, 0, 1, 0, 0])
    
    adr_idx = tf.equal(y_true, y_pred) & tf.equal(y_true, 1)
    adr_idx = tf.reshape(tf.where(adr_idx), [-1]) # [0, 1, 6]
    
    far_idx = tf.equal(y_true, 0) & tf.equal(y_pred, 1) 
    far_idx = tf.reshape(tf.where(far_idx), [-1])  # [3, 4]
    
    num_adr = tf.shape(adr_idx)[0]  # 3
    num_far = tf.shape(far_idx)[0]  # 2
    
    with tf.Session() as sess:
        sess.run(tf.global_variables_initializer())
        a, b = sess.run([num_adr, num_far])
    

    使用 keras 1.2.1 和 tensorflow 版本 0.11
    我认为原因是形状不同
    y_true 的形状是 (?, ?) 和 y_pred 的形状是 (?, 1) ?

    def adr_and_far(y_true, y_pred):
        total_adr = K.sum(K.tf.cast(K.tf.equal(y_true, 1), 'int32'))
        total_far = K.sum(K.tf.cast(K.tf.equal(y_true, 0), 'int32'))
    
        adr_idx = K.tf.equal(y_true, 1) & K.tf.equal(y_pred, 1)
        adr_idx = K.sum(K.tf.cast(K.reshape(adr_idx, [-1]), 'int32'))
    
        far_idx = K.tf.equal(y_true, 0) & K.tf.equal(y_pred, 1)
        far_idx = K.sum(K.tf.cast(K.reshape(far_idx, [-1]), 'int32'))
    
    
        return { 'total_adr': total_adr,
                 'adr': adr_idx / total_adr,
                 'total_far': total_far,
                 'far': far_idx / total_far
               }
    

    【讨论】:

    • 你的回答似乎很接近我的需要,但每次我尝试使用tf.where 我都得到了这个TypeError: select() takes at least 3 arguments (1 given)
    • 之前的错误只有在导入Keras和Tensorflow时才会出现。
    • 所以如果只是导入 keras 或 tensorflow 可以吗?如果使用tensorflow作为后端,需要同时导入吗?
    • 对不起,我表达得很糟糕。我的意思是,如果我导入 Keras,那么 Tensorflow 会抛出该错误,我使用 tf(来自 tensorflow 模块)或K.tf(来自 Keras 后端模块的 tensorflow)并不重要。我还检查了 Keras 使用的 Tensorflow 版本是否与我在独立模式下使用 Tensorflow 时的版本相同。
    • 或者您可以粘贴您的代码。顺便说一句,如果你使用from keras import backend as K,你会使用k,比如k.where,而不是k.tf.where?
    猜你喜欢
    • 1970-01-01
    • 2018-05-14
    • 2020-03-04
    • 2017-09-20
    • 2019-02-06
    • 2017-10-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多