Python “关于”的区别;“二进制交叉熵”;及;二元“交叉熵”;在tf.keras.loss中?

Python “关于”的区别;“二进制交叉熵”;及;二元“交叉熵”;在tf.keras.loss中?,python,tensorflow,tf.keras,Python,Tensorflow,Tf.keras,我正在使用tf.GradientTape()使用TensorFlow 2.0训练一个模型,但是我发现如果我使用tf.keras.loss.BinaryCrossentropy,模型的准确率是95%,但是如果我使用tf.keras.loss.binary\u crossentropy,则会降低到75%。所以我对同一个度量的差异感到困惑 import pandas as pd import numpy as np import tensorflow as tf from tensorflow.ker

我正在使用tf.GradientTape()使用TensorFlow 2.0训练一个模型,但是我发现如果我使用
tf.keras.loss.BinaryCrossentropy
,模型的准确率是
95%
,但是如果我使用
tf.keras.loss.binary\u crossentropy
,则会降低到
75%
。所以我对同一个度量的差异感到困惑

import pandas as pd
import numpy as np
import tensorflow as tf
from tensorflow.keras import layers

from sklearn.model_selection import train_test_split

def read_data():
    red_wine = pd.read_csv("https://archive.ics.uci.edu/ml/machine-learning-databases/wine-quality/winequality-red.csv", sep=";")
    white_wine = pd.read_csv("https://archive.ics.uci.edu/ml/machine-learning-databases/wine-quality/winequality-white.csv", sep=";")
    red_wine["type"] = 1
    white_wine["type"] = 0
    wines = red_wine.append(white_wine)
    return wines

def get_x_y(df):
    x = df.iloc[:, :-1].values.astype(np.float32)
    y = df.iloc[:, -1].values.astype(np.int32)
    return x, y

def build_model():
    inputs = layers.Input(shape=(12,))
    dense1 = layers.Dense(12, activation="relu", name="dense1")(inputs)
    dense2 = layers.Dense(9, activation="relu", name="dense2")(dense1)
    outputs = layers.Dense(1, activation = "sigmoid", name="outputs")(dense2)
    model = tf.keras.Model(inputs=inputs, outputs=outputs)
    return model

def generate_dataset(df, batch_size=32, shuffle=True, train_or_test = "train"):
    x, y = get_x_y(df)
    ds = tf.data.Dataset.from_tensor_slices((x, y))
    if shuffle:
        ds = ds.shuffle(10000)
    if train_or_test == "train":
        ds = ds.batch(batch_size)
    else:
        ds = ds.batch(len(df))
    return ds

# loss_object = tf.keras.losses.binary_crossentropy
loss_object = tf.keras.losses.BinaryCrossentropy()
optimizer = tf.keras.optimizers.Adam(learning_rate=0.001)

def train_step(model, optimizer, x, y):
    with tf.GradientTape() as tape:
        pred = model(x, training=True)
        loss = loss_object(y, pred)
    grads = tape.gradient(loss, model.trainable_variables)
    optimizer.apply_gradients(zip(grads, model.trainable_variables))


def train_model(model, train_ds, epochs=10):
    for epoch in range(epochs):
        print(epoch)
        for x, y in train_ds:
            train_step(model, optimizer, x, y)

def main():
    data = read_data()
    train, test = train_test_split(data, test_size=0.2, random_state=23)
    train_ds = generate_dataset(train, 32, True, "train")
    test_ds = generate_dataset(test, 32, False, "test")
    model = build_model()
    train_model(model, train_ds, 10)
    model.compile(loss='binary_crossentropy',
                  optimizer='adam',
                  metrics=['accuracy']
                  )
    model.evaluate(test_ds)

main()

它们确实应该起同样的作用;使用,在文档字符串描述上有明显差异;前者用于两个类标签,而后者支持任意类计数。但是,如果以预期的格式传递目标,则两者都会在调用后端之前应用相同的预处理,这将进行实际计算

您观察到的差异可能是再现性问题;确保设置了随机种子-请参阅下面的函数。有关再现性的更完整答案,请参阅


功能

def reset_seeds(reset_graph_,_backend=None):
如果使用\u后端重置\u图形\u不是无:
K=使用\u后端重置\u图形\u
K.清除会话()
tf.compat.v1.reset\u default\u graph()
打印(“KERAS和TENSORFLOW图形重置”)#可选
np.随机种子(1)
随机种子(2)
tf.compat.v1.set\u random\u seed(3)
打印(“随机种子重置”)#可选

用法

将tensorflow导入为tf
将tensorflow.keras.backend作为K导入
重置种子(K)

谢谢,我发现准确性不一致的原因:

  • 模型中的
    输出
    的形状是
    (无,1)
    ,但馈送标签是
    (无,)
    ,这导致python的广播机制具有错误的含义

  • tf.keras.loss.binarycrosentropy()
    的源代码中,在计算损失时,
    y_pred
    y_true
    都通过一个名为
    挤压或扩展维度
    的函数进行处理,该函数在
    tf.keras.loss.binary_crossentropy
    中缺乏

  • 注意:注意输入数据和模型输出之间的形状是否一致


  • 这里的问题是什么?嗨,问题是我将loss_对象从
    tf.keras.loss.BinaryCrossentropy()
    更改为
    tf.keras.loss.binary_crossentropy
    ,精确度从
    95%
    降低到
    75
    谢谢,但我认为这不是问题,我多次运行代码,但是当将
    loss\u对象
    tf.keras.loss.BinaryCrossentropy()
    切换到
    tf.keras.loss.BinaryCrossentropy时,精确度从
    95%
    降低到
    75%
    @JunkaiSun共享您的完整代码;可能的错误源太多,无法猜测。嗨,我把完整的代码粘贴在问题中,你可以在你的计算机上测试这个程序。当将
    tf.keras.loss.BinaryCrossentropy()从
    tf.keras.loss.BinaryCrossentropy()切换到
    tf.keras.loss.binary\u crossentropy
    @OverLordGoldDragon“docstring描述”时,评估指标从95%降低到75%,您能为两者共享这些吗?我刚刚在TF网站上发现:@DrNishaArora检查他们的链接和docstrings下面的代码。对,这就是我所说的“如果以预期的格式传递目标”-通过你的代码,确认你的解决方案。尽管如此,还是要使用随机种子,否则结果仍会相差几个百分点。