【问题标题】:ValueError using tensorflow.metrics.Recall(class_id=1)ValueError 使用 tensorflow.metrics.Recall(class_id=1)
【发布时间】:2022-01-24 21:11:24
【问题描述】:

使用Python 3.8.3tensorflow 版本2.4.1

想在tensorflow.metrics中使用参数class_idRecall(见documentation

这是复制问题的最少代码。 下面的代码因class_id=1而崩溃

from tensorflow.keras.layers import Input, Dense
from tensorflow.keras.models import Model
from tensorflow.keras.layers import SimpleRNN
from sklearn.model_selection import train_test_split
from tensorflow.keras import metrics
import numpy as np
#generate data
max_length  = 200
width = 3
n_samples = 100
data = np.random.rand(n_samples, max_length, width)
label = np.random.randint(0, high =2, size = n_samples)
train_size = 0.8
x_train, x_test, y_train, y_test = train_test_split(data, label, train_size = train_size)

#create a model
rnn_size = 16
sequence_input = Input(shape=(max_length,width,), dtype='float32')
x = SimpleRNN(rnn_size)(sequence_input)
preds = Dense(1, activation='sigmoid')(x)
model = Model(sequence_input, preds)
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=[metrics.Recall(class_id=1)])
#fit
BATCH_SIZE = 32
history = model.fit(x_train, y_train, epochs=1, batch_size=BATCH_SIZE)

抛出ValueError

ValueError: slice index 1 of dimension 1 out of bounds. for '{{node strided_slice_1}} = StridedSlice[Index=DT_INT32, T=DT_FLOAT, begin_mask=0, ellipsis_mask=1, end_mask=0, new_axis_mask=0, shrink_axis_mask=2](Cast_1, strided_slice_1/stack, strided_slice_1/stack_1, strided_slice_1/stack_2)' with input shapes: [?,1], [2], [2], [2] and with computed input tensors: input[1] = <0 1>, input[2] = <0 2>, input[3] = <1 1>.

但它适用于metrics.Recall(class_id=0)

metrics.Precision(class_id=1) 和所有其他使用 class_id 的指标可能出现相同的错误(我还没有全部尝试过)。

我无法解读错误消息的含义,也无法在网上找到任何相关内容来回答我的问题。

【问题讨论】:

    标签: tensorflow machine-learning keras metrics valueerror


    【解决方案1】:

    文档指出:

    class_id(可选):我们想要二进制度量的整数类 ID。 这必须在半开区间 [0, num_classes) 中,其中 num_classes 是预测的最后一个维度。

    当您使用sigmoid 时,您的输出包含导致此错误的形状: (1, )。如果你修改你的网络进行二元分类,输出将是第 1 类的 sigmoid 概率。

    因此,对于二元分类情况,默认情况下您将获得类 1 的精度和召回率,如果您想获得类 0,则需要定义自己的指标。一个例子可以在here找到。

    相对错误来自这里(source code):

    if class_id is not None:
      y_true = y_true[..., class_id]
      y_pred = y_pred[..., class_id]
    

    在您的示例中,标签应该是单热编码的:

    from tensorflow.keras.layers import Input, Dense
    from tensorflow.keras.models import Model
    from tensorflow.keras.layers import SimpleRNN
    from sklearn.model_selection import train_test_split
    from tensorflow.keras import metrics
    from tensorflow.keras.utils import to_categorical
    import numpy as np
    #generate data
    max_length  = 200
    width = 3
    n_samples = 100
    data = np.random.rand(n_samples, max_length, width)
    label = np.random.randint(0, high =2, size = n_samples)
    label = to_categorical(label, 2)
    train_size = 0.8
    x_train, x_test, y_train, y_test = train_test_split(data, label, train_size = train_size)
    
    #create a model
    rnn_size = 16
    sequence_input = Input(shape=(max_length,width), dtype='float32')
    x = SimpleRNN(rnn_size)(sequence_input)
    preds = Dense(2, activation='softmax')(x)
    model = Model(sequence_input, preds)
    model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=[metrics.Precision(class_id=1),
                                                                              metrics.Recall(class_id=1)])
    #fit
    BATCH_SIZE = 32
    history = model.fit(x_train, y_train, epochs=16, batch_size=BATCH_SIZE,
                        validation_data = (x_test, y_test))
    
    Epoch 16/16
    3/3 [==============================] - 0s 86ms/step - loss: 0.6771 - precision: 0.5676 - 
           recall: 0.5250 - val_loss: 0.6419 - val_precision: 0.2222 - val_recall: 0.6667
    

    通过 sklearn 验证结果:

    from sklearn.metrics import classification_report
    print(classification_report(np.argmax(y_test, axis = -1), 
                                np.argmax(model.predict(x_test, batch_size = 1), 
                                          axis= -1), digits = 4))
    
                  precision    recall  f1-score   support
    
               0     0.9091    0.5882    0.7143        17
               1     0.2222    0.6667    0.3333         3
    
        accuracy                         0.6000        20
       macro avg     0.5657    0.6275    0.5238        20
    weighted avg     0.8061    0.6000    0.6571        20
    

    如果您在上一个示例中更改 class_id = 0,它将计算类 0 的指标。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-06-25
      • 2017-12-28
      • 1970-01-01
      • 2018-02-01
      • 2018-12-25
      • 2020-12-29
      相关资源
      最近更新 更多