【问题标题】:Tensorflow structured data model.predict() returns incorrect probabilitiesTensorflow 结构化数据 model.predict() 返回不正确的概率
【发布时间】:2019-10-03 22:28:04
【问题描述】:

我正在尝试按照 structured data models 的 Tensorflow 教程(我是初学者)进行一些更改。

我的目的是创建一个模型,我向它提供看起来像这样的数据(以 csv 格式)(该示例只有 2 个功能,但我想在弄清楚之后对其进行扩展):

power_0,power_1,result
0.2,0.3,draw
0.8,0.1,win
0.3,0.1,draw
0.7,0.2,win
0.0,0.4,lose

我使用以下代码创建了模型:

def get_labels(df, label, mapping):
    raw_y_true = df.pop(label)
    y_true = np.zeros((len(raw_y_true)))
    for i, raw_label in enumerate(raw_y_true):
        y_true[i] = mapping[raw_label]
    return y_true


tf.compat.v1.enable_eager_execution()

mapping_to_numbers = {'win': 0, 'draw': 1, 'lose': 2}

data_frame = pd.read_csv('data.csv')
data_frame.head()

train, test = train_test_split(data_frame, test_size=0.2)
train, val = train_test_split(train, test_size=0.2)

train_labels = np.array(get_labels(train, label='result', mapping=mapping_to_numbers))
val_labels = np.array(get_labels(val, label='result', mapping=mapping_to_numbers))
test_labels = np.array(get_labels(test, label='result', mapping=mapping_to_numbers))

train_features = np.array(train)
val_features = np.array(val)
test_features = np.array(test)

model = tf.keras.Sequential([
    tf.keras.layers.Dense(128, activation='relu', input_shape=(train_features.shape[-1],)),
    tf.keras.layers.Dense(128, activation='relu'),
    tf.keras.layers.Dropout(0.3),
    tf.keras.layers.Dense(128, activation='relu'),
    tf.keras.layers.Dropout(0.3),
    tf.keras.layers.Dense(3, activation='sigmoid'),
])

model.compile(
    optimizer='adam',
    loss='binary_crossentropy',
    metrics=['accuracy'],
    run_eagerly=True)

epochs = 10
batch_size = 100
history = model.fit(
    train_features,
    train_labels,
    epochs=epochs,
    validation_data=(val_features, val_labels))

input_data_frame = pd.read_csv('input.csv')
input_data_frame.head()

input_data = np.array(input_data_frame)

print(model.predict(input_data))

input.csv 如下所示:

power_0,power_1
0.8,0.1
0.7,0.2

而实际结果是:

[[0.00604381 0.00242573 0.00440606]
 [0.01321151 0.00634229 0.01041476]]

我希望得到每个标签的概率(“赢”、“平”和“输”),谁能帮我解决这个问题?

提前致谢

【问题讨论】:

    标签: python-3.x tensorflow machine-learning


    【解决方案1】:

    在这一行 tf.keras.layers.Dense(3, activation='sigmoid') 中使用 softmax 激活。

    【讨论】:

    • 我试过了,但现在我得到[[0.33328226 0.33350918 0.33320865]] 或类似的每个输入,并且由于从 0.6 到 0.2-0.3 的变化,精度也下降了
    • @AlonYampolski 模型会收敛吗?
    • 不确定模型收敛是什么意思,正如我所说,我对 tensorflow 很陌生☺️
    • 哦,没关系。你训练了多少个epoch?验证损失是否停止减少?
    • 使用 sigmoid 时,验证损失在 -4.08 和 -0.22 之间移动,使用 'softmax' 时,它稳定在 1.1。我将纪元设置为 10
    【解决方案2】:

    你的例子对我很有效:

    model = tf.keras.Sequential([
        tf.keras.layers.Flatten(input_shape=(train_features.shape[-1],)),
        tf.keras.layers.Dense(128, activation='relu'),
        tf.keras.layers.Dense(16, activation='relu'),
        tf.keras.layers.Dense(3, activation='softmax'),
    ])
    
    model.compile(
        optimizer='adam',
        loss='sparse_categorical_crossentropy',
        metrics=['accuracy'],
        run_eagerly=True)
    

    使用扁平化

    【讨论】:

    • 非常感谢!!!!!!您对使用Flatten 层和sparse_categorical_crossentropy 损失函数的建议有所不同。我的模型的准确率现在是 0.97-1(取决于训练数据),predict 函数的结果实际上是场景!
    【解决方案3】:

    我必须在这里写下我的建议,因为我还不能发表评论。 @zihaozhihao 是对的,您必须使用 softmax 而不是 sigmoid,因为您不处理二进制问题。另一个问题可能是您的损失函数:

    model.compile(
    optimizer='adam',
    loss='binary_crossentropy',
    metrics=['accuracy'],
    run_eagerly=True)
    

    尝试使用loss='categorical_crossentropy',,因为您正在使用多标签分类。你可以阅读更多关于多标签分类herehere的信息。

    至于你的概率问题。您将获得两个测试输入的每个类的概率。例如: win draw loss [[0.00604381 0.00242573 0.00440606] [0.01321151 0.00634229 0.01041476]] 问题是您的损失函数和导致奇怪的概率值的激活函数。您可能想在此处查看this 帖子以获取更多信息。

    希望对您有所帮助,欢迎随时提问。

    【讨论】:

    • 我尝试了您建议的更改,但不幸的是我仍然得到了意想不到的结果:[[0.33328226 0.33350918 0.33320865]]
    • 但如果我是正确的,你现在得到一个分布。如果我没记错的话,它说33%赢33%平33%输?也许您可以告诉我您的期望,以便我尝试理解:)
    • 问题是我尝试的每一个输入的分布几乎都是均匀的,我预计如果获胜,我会得到[[0.7, 0.2, 0.1]],概率分布不均匀
    • 请问您使用了多少个训练示例,您的训练准确度/损失与验证准确度/损失是多少?因为可能是您的实现很好,所以您的模型只是欠拟合:) 此外,您可能希望为 epoch 设置更高的数字,以便让您的模型有时间从数据中真正学习。你只训练了 10 个 epoch,这对于学习一些东西来说是一个很低的数字。
    • 将损失更改为categorical_crossentropy后,训练结果为loss: 3.1619 - acc: 0.2797 - val_loss: 3.3370 - val_acc: 0.1500,验证为loss: 3.3287 - acc: 0.1400。我有 1000 个样本,但我可以生成尽可能多的样本
    【解决方案4】:

    由于是多类分类问题,loss functionn请使用categorical_crossentropy代替binary_crossentropy,同时使用softmax 代替 sigmoid 作为激活函数

    此外,您应该增加 epochs 以获得更好的收敛性。

    【讨论】:

      猜你喜欢
      • 2018-07-15
      • 2018-07-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-03
      • 2019-07-17
      • 1970-01-01
      相关资源
      最近更新 更多