Keras 中 ADR 和 FAR 的自定义指标
Custom Metric for ADR and FAR in Keras
我需要在带有 tensorflow 后端的 keras 中定义自定义指标,以获取 ADR 和 FAR 指标,其中:
ADR是Class1中正确检测到的元素数与Class1中元素总数的比值。
FAR 是 Class 0 个元素被错误地 class 化为 Class 1 个元素的数量与 [=50 个元素的总数之间的比率=] 0 个元素。
目前,我已经能够计算每个 class:
上的元素总数
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
远
但我不知道如何使用 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 = ...?
但它似乎 return 除了 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)
你只需要数数吗?
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
}
我需要在带有 tensorflow 后端的 keras 中定义自定义指标,以获取 ADR 和 FAR 指标,其中:
ADR是Class1中正确检测到的元素数与Class1中元素总数的比值。
FAR 是 Class 0 个元素被错误地 class 化为 Class 1 个元素的数量与 [=50 个元素的总数之间的比率=] 0 个元素。
目前,我已经能够计算每个 class:
上的元素总数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
为 ADRy_true[i] == 0 and y_pred[i] == 1
远
但我不知道如何使用 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 = ...?
但它似乎 return 除了 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)
你只需要数数吗?
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
}