【问题标题】:Keras - how to get unnormalized logits instead of probabilitiesKeras - 如何获得非标准化的logits而不是概率
【发布时间】:2018-04-12 16:21:34
【问题描述】:

我正在 Keras 中创建一个模型,并想计算我自己的指标(困惑度)。这需要使用非标准化的概率/logits。但是,keras 模型只返回 softmax 概率:

model = Sequential()
model.add(embedding_layer)
model.add(LSTM(n_hidden, return_sequences=False))
model.add(Dropout(dropout_keep_prob))
model.add(Dense(vocab_size))
model.add(Activation('softmax'))
optimizer = RMSprop(lr=self.lr)

model.compile(optimizer=optimizer, 
loss='sparse_categorical_crossentropy')

Keras FAQ 有一个解决方案来获取中间层的输出here。另一个解决方案是here。但是,这些答案将中间输出存储在不同的模型中,这不是我需要的。 我想将 logits 用于我的自定义指标。自定义指标应包含在 model.compile() 函数中,以便在训练期间对其进行评估和显示。所以我不需要将Dense 层的输出分隔在不同的模型中,而是作为我原始模型的一部分。

简而言之,我的问题是:

  • 使用def custom_metric(y_true, y_pred) 定义here 概述的自定义指标时,y_pred 是否包含logits 或归一化概率?

  • 如果它包含归一化的概率,我怎样才能得到非归一化的概率,即Dense层输出的logits?

【问题讨论】:

  • 所以你想保留这个模型或者你可以改变它?你想保持 sparse_categorical_crossentropy 作为损失吗?
  • 产生相同最终结果的替代方案是什么?

标签: python machine-learning keras neural-network nlp


【解决方案1】:

尝试将上次激活从 softmax 更改为线性

model = Sequential()
model.add(embedding_layer)
model.add(LSTM(n_hidden, return_sequences=False))
model.add(Dropout(dropout_keep_prob))
model.add(Dense(vocab_size))
model.add(Activation('linear'))
optimizer = RMSprop(lr=self.lr)

model.compile(optimizer=optimizer, loss='sparse_categorical_crossentropy')

【讨论】:

  • 但我最后确实需要softmax概率,所以最终模型输出必须是概率
  • 为什么将激活更改为线性会得到对数而不是概率?
  • @Goldname 因为线性激活意味着只传递值而不应用任何激活。 ML 中的 Logits 仅指非标准化的对数概率。如果将激活更改为 softmax,它会获取 logits 并将它们传递给 softmax 函数,该函数返回归一化的概率。 [更多信息] (stackoverflow.com/questions/41455101/…)
  • 我认为这行不通。优化器不会自动发现激活是线性的而不是 softmax。
【解决方案2】:

您可以创建一个模型用于训练,另一个模型用于预测。

对于训练,您可以使用函数式 API 模型,只需提取现有模型的一部分,将 Activation 放在一边:

model = yourExistingModelWithSoftmax 
modelForTraining = Model(model.input,model.layers[-2].output)

#use your loss function in this model:
modelForTraining.compile(optimizer=optimizer,loss=my_sparse_categorical_crossentropy, metrics=[my_custom_metric])

由于您将一个模型作为另一个模型的一部分,因此它们将共享相同的权重。

  • 当你想训练时,使用modelForTraining.fit()
  • 要预测概率时,请使用model.predict()

【讨论】:

  • 我认为我在上面找到的解决方案更加简单。但是,在创建自定义构建指标时,我仍然不知道 Keras 中的 y_pred 是什么。总是最后一个网络层的输出吗?
  • 是的,y_pred 是模型的输出,而y_true 是你传递给fit 的真实数据。 --- 我的解决方案认为您稍后将需要 softmax 概率。
  • 只要我总是添加一个softmax,我以后就不能继续使用softmax probabiltites吗?例如,当调用 model.predict(input) 时,输出将是非标准化概率(=logits)。添加 probs = K.nn.softmax(model.predict(input)) 时,我会得到所需的 softmax 概率。对吗?
  • 关于您的回答:我必须在训练期间使用 sparse_categorical_cross_entropy 作为损失函数。当只训练模型的第一部分时,它使用未归一化的概率作为损失函数的输入,这会产生错误的结果
  • 您只能从输出中获取指标,因此您需要非标准化输出。如果需要,您可以在自定义损失函数中对它们进行标准化。在所有情况下,您稍后都会发现您需要一个模型来执行 softmax。你最终会得到这个答案的变体加上你的答案。
【解决方案3】:

我想我找到了解决办法

首先,我将激活层更改为线性,以便我收到@loannis Nasios 概述的 logits。

其次,为了仍将sparse_categorical_crossentropy 作为损失函数,我定义了自己的损失函数,将 from_logits 参数设置为 true。

model.add(embedding_layer)
model.add(LSTM(n_hidden, return_sequences=False))
model.add(Dropout(dropout_keep_prob))
model.add(Dense(vocab_size))
model.add(Activation('linear'))
optimizer = RMSprop(lr=self.lr)


def my_sparse_categorical_crossentropy(y_true, y_pred):
    return K.sparse_categorical_crossentropy(y_true, y_pred, from_logits=True)

model.compile(optimizer=optimizer,loss=my_sparse_categorical_crossentropy)

【讨论】:

  • 所以,您明确承认了一个有帮助的答案,但甚至都不在乎投票??
  • 不知道你为什么错误地指责另一个用户。我马上就给了loannis Naosis 的答案。但是,肯定是其他人投了反对票,所以我的赞成票没有显示出来。
  • 最后怎么得到softmax概率?
猜你喜欢
  • 2019-10-28
  • 2019-05-19
  • 2019-10-25
  • 2018-07-15
  • 2016-12-04
  • 2018-06-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多