Keras模型中的采样Softmax

3

我考虑的一些方法:

继承Model类 TensorFlow Keras中的采样softmax

继承Layers类 如何在Keras模型中使用TensorFlow的采样softmax loss函数?

这两种方法中,Model方法更为简洁,而Layers方法则有些hacky——它将目标作为输入的一部分并将其推入模型中,多输出模型再见了。

我希望在子类化Model类方面获得一些帮助——具体来说: 1)与第一种方法不同——我想像在指定标准Keras模型时那样,使用任意数量的层。例如:

class LanguageModel(tf.keras.Model):
    def __init__(self, **kwargs)

2) 我希望在模型类中加入如下代码 - 但是希望让模型类认识到:

def call(self, y_true, input):
        """ reshaping of y_true and input to make them fit each other """
        input = tf.reshape(input, (-1,self.hidden_size))
        y_true = tf.reshape(y_true, (-1,1))
      weights = tf.Variable(tf.float64))
      biases = tf.Variable(tf.float64)
      loss = tf.nn.sampled_softmax_loss(
      weights=weights,
      biases=biases,
      labels=labels,
      inputs=inputs,
      ...,
      partition_strategy="div")
      logits = tf.matmul(inputs, tf.transpose(weights))
      logits = tf.nn.bias_add(logits, biases)
       y_predis = tf.nn.softmax_cross_entropy_with_logits_v2(
                                labels=inputs[1],
                                logits=logits) 




我想我需要一些指针来了解在函数式API中Model类的哪些部分应该进行更改,因为我必须像上面那样编写自定义损失函数。我猜问题在于访问tf.nn.sampledsoftmax函数中的权重。

1个回答

8
我能想到的最简单的方法是定义一个损失函数,忽略输出层的结果。
完整的Colab在这里: https://colab.research.google.com/drive/1Rp3EUWnBE1eCcaisUju9TwSTswQfZOkS 损失函数。请注意,它假设输出层是Dense(activation ='softmax'),并忽略y_pred。因此,在训练/评估期间使用损失时,密集层的实际输出为NOP。
预测时会使用输出层。
class SampledSoftmaxLoss(object):
  """ The loss function implements the Dense layer matmul and activation
  when in training mode.
  """
  def __init__(self, model):
    self.model = model
    output_layer = model.layers[-1]
    self.input = output_layer.input
    self.weights = output_layer.weights

  def loss(self, y_true, y_pred, **kwargs):
    labels = tf.argmax(y_true, axis=1)
    labels = tf.expand_dims(labels, -1)
    loss = tf.nn.sampled_softmax_loss(
        weights=self.weights[0],
        biases=self.weights[1],
        labels=labels,
        inputs=self.input,
        num_sampled = 3,
        num_classes = 4,
        partition_strategy = "div",
    )
    return loss

模型:

def make_model():
  inp = Input(shape=(10,))
  h1 = Dense(16, activation='relu')(inp)
  h2 = Dense(4, activation='linear')(h1)
  # output layer and last hidden layer must have the same dims
  out = Dense(4, activation='softmax')(h2)
  model = Model(inp, out)
  loss_calculator = SampledSoftmaxLoss(model)
  model.compile('adam', loss_calculator.loss)
  return model

tf.set_random_seed(42)
model = make_model()
model.summary()

注意,SampledSoftmaxLoss要求最后一个模型层的输入维度必须与类别数相同。

1
  1. 正确:损失函数假定最后一层是输出层并使用其权重/偏置;忽略其输出,因为y_pred没有用于损失计算。
  2. 您可以使用任何在输出层上操作的指标,例如准确性;输出层仍然存在,如果将其连接到图节点(例如精度指标),则仍将生成输出。
- Pedro Marques
谢谢,这很方便。所以我只需创建一个层,它从上一层获取权重并计算预测?例如softmax等?但这不会被model.compile编译,对吗? - pythOnometrist
损失函数不是一个层,它控制计算损失和启动反向传播过程的图形部分;您希望模型定义良好,以便可以将其用于推理。理解这个损失函数的方法是忽略输出层(y_pred)的输出,并使用输出层权重和偏差重新计算它,使用sampled_softmax_loss;这最终会导致对输出层进行梯度更新,但不直接使用输出层结果。 - Pedro Marques
还有一个问题 - 为什么不直接使用self.input = output_layer.output,从而避免额外的一层? - pythOnometrist
你提到最后一层的输入必须是与类别数相等的维度。为什么呢?我的架构是180(inputs) - 512 - 256 - 200000(类别数) - softmax。您建议我在256维层之后插入另一层类别数吗?我已经卡在这个问题上一个星期了,非常需要帮助。 - lego king
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接