我正在嘗試在 Keras 中實作自定義狀態指標。Keras API網站提供了有關如何執行此操作的簡短演示。但是,該演示僅包括class定義、創建實體和根據某些資料計算指標。他們沒有演示如何在model.fit方法中使用它,這就是我(和大多數人)會使用它的方式。當我使用它時,我得到的結果是 (1) 不改變紀元和 (2) 與內置指標沖突,所以我知道我得到了不正確的結果。我是否使用錯誤提供的代碼或示例代碼不起作用?
我包括以下問題的最小演示:
# libraries
import numpy as np
import random
import tensorflow as tf
from sklearn import datasets
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
from sklearn.model_selection import train_test_split
# setting psuedorandom seeds for reproducibility
np.random.seed(0)
tf.random.set_seed(0)
random.seed(0)
# loads famous Iris dataset
iris = datasets.load_iris()
x = iris.data
y = iris.target
# converts to binary prediction problem
y = np.where(y == 2, 1, 0)
# train/validation split
x_train, x_val, y_train, y_val = train_test_split(x, y, test_size = 0.2)
# reformatting
x_train = tf.constant(x_train)
x_val = tf.constant(x_val)
y_train = tf.constant(y_train)
y_val = tf.constant(y_val)
# stateful metric code from keras website
class BinaryTruePositives(tf.keras.metrics.Metric):
def __init__(self, name='binary_true_positives', **kwargs):
super(BinaryTruePositives, self).__init__(name=name, **kwargs)
self.true_positives = self.add_weight(name='tp', initializer='zeros')
def update_state(self, y_true, y_pred, sample_weight=None):
y_true = tf.cast(y_true, tf.bool)
y_pred = tf.cast(y_pred, tf.bool)
values = tf.logical_and(tf.equal(y_true, True), tf.equal(y_pred, True))
values = tf.cast(values, self.dtype)
if sample_weight is not None:
sample_weight = tf.cast(sample_weight, self.dtype)
values = tf.multiply(values, sample_weight)
self.true_positives.assign_add(tf.reduce_sum(values))
def result(self):
return self.true_positives
def reset_states(self):
self.true_positives.assign(0)
# demonstration from website (correct value is returned)
m = BinaryTruePositives()
m.update_state([0, 1, 1, 1], [0, 1, 0, 0])
print(m.result())
# instantiates metric
true_pos = BinaryTruePositives()
# defines a very simple model
model = Sequential()
model.add(Dense(1, activation = 'sigmoid'))
# compiles model
model.compile(optimizer = 'adam',
loss = 'binary_crossentropy',
metrics = ['Recall', true_pos])
# trains model and prints output
history = model.fit(x_train, y_train,
epochs = 30,
verbose = 1,
validation_data = (x_val, y_val),
batch_size = 10
)
請注意,召回率有所提高,而真正的陽性率保持不變,這是不可能的。
uj5u.com熱心網友回復:
我稍微修改了您的BinaryTruePositives課程,因為在您的模型中,y_pred 是 (0, 1) 中的連續變數,而不是布林值。例如,您需要使用 tf.where(y_pred > 0.5, True, False) 將其轉換為布爾變數。
class BinaryTruePositives(tf.keras.metrics.Metric):
def __init__(self, name='binary_true_positives', **kwargs):
super(BinaryTruePositives, self).__init__(name=name, **kwargs)
self.true_positives = self.add_weight(name='tp', initializer='zeros')
def update_state(self, y_true, y_pred, sample_weight=None):
y_true = tf.cast(y_true, tf.bool)
y_pred = tf.where(y_pred > 0.5, True, False)
values = tf.logical_and(tf.equal(y_true, True), tf.equal(y_pred, True))
values = tf.cast(values, self.dtype)
if sample_weight is not None:
sample_weight = tf.cast(sample_weight, self.dtype)
values = tf.multiply(values, sample_weight)
self.true_positives.assign_add(tf.reduce_sum(values))
def result(self):
return self.true_positives
def reset_states(self):
self.true_positives.assign(0)
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/362371.html
