0

特定のバッチ内で発生するインスタンスに応じて、条件付き損失 (2 つの異なる損失) を計算できるようにしたいと考えています。これにより、私が考えていることを実装する柔軟性が得られると信じているため、カスタムのtrain_stepをゼロから作成しています。ただし、これを実装する方法を理解するのに少し行き詰まっています。

各トレーニング ステップで、バッチ内の各インスタンスの真のラベルと予測されたラベルの間の分類 (カテゴリカル クロスエントロピー) 損失を計算しています。これは標準です。さらに、バッチ内のすべてのインスタンスに対して計算されるのではなく、インスタンスのサブセットのみに対して計算される正則化損失を含めています。これが、条件付き損失または 2 つの損失目標について言及する理由です。

トレーニングの前に、トレーニング インスタンス ID のリストを指定しました (各トレーニング インスタンスには一意の ID が与えられます)。これらのインスタンスのいずれかが現在のバッチにある場合は常に、これらの特定のインスタンスのみを使用して正則化項を計算します。これらのインスタンスのいずれも発生しない場合は、標準の分類損失のみを計算します。正則化項の目的は、特定のトレーニング インスタンス (インスタンス ID で指定) と一連の追加インスタンス (ここでは単一のインスタンスのみを仮定できます) の間の機能の類似性を促進することです (距離の 2 乗で測定)。

これが私がこれまでに持っているものです。これは実用的な実装ではありませんが、うまくいけば、私が説明したことと達成したいことを示しています。モデルは画像テンソルを取り込み、特徴表現 (正則化項の場合) と予測ベクトル (分類損失の場合) の両方を出力します。私が使用しているアプローチを無視して、代替案を提案してください。たとえば、代わりにカスタム損失関数を作成するか、使用tf.condすると役立つ場合があります。注: tensorflow 2/ を使用していtf.GradientTape()ます。

class MNIST_Classifier(tf.keras.Model):
    def __init__(self, model, train_sub_ids, reg_example, lmbda, **kwargs):
        super(MNIST_Classifier, self).__init__(**kwargs)
        self.model = model
        self.train_sub_ids = train_sub_ids
        self.reg_example = reg_examples
        self.lmbda = lmbda
        self.total_loss_tracker = keras.metrics.Mean(name="total_loss")
        self.classification_loss_tracker = keras.metrics.Mean(
            name="classification_loss"
        )
        self.reg_loss_tracker = keras.metrics.Mean(name="reg_loss")

    @property
    def metrics(self):
        return [
            self.total_loss_tracker,
            self.classification_loss_tracker,
            self.reg_loss_tracker,
        ]

    def train_step(self, data):
        with tf.GradientTape() as tape:
            ids, x, y = data # batch includes id, image, label
            _, y_pred = self.model(x) # get predictions, features don't matter for classification loss
            
            # compute classification loss for all instances 
            classification_loss = tf.reduce_mean(
              tf.keras.losses.categorical_crossentropy(y, y_pred)
            )

            # compute reg loss for subset of instances (could be none)
            # step 1: obtain instances from batch where id is in self.train_sub_id
            # TODO: this won't work because it's not using tensor operations...need to replace 
            x_sub = [img for id, img in zip(ids,x) if any(id==i for i in self.train_sub_id)]
            if x_sub:
              features_sub, _  = self.model(x_sub)
              # step 2: compute features and predictions for reg example
              features_reg, _  = self.model(x_reg)
              # should still work if features_sub and features_reg are different shapes in batch (left most) dim
              reg_loss = tf.reduce_mean(tf.math.squared_difference(features_sub, features_reg))
            else:
              reg_loss = 0
            
            total_loss = classification_loss + self.lmbda*reg_loss

        variables = self.trainable_weights
        grads = tape.gradient(total_loss, variables)
        self.optimizer.apply_gradients(zip(grads, self.trainable_weights))
        self.total_loss_tracker.update_state(total_loss)
        self.classification_loss_tracker.update_state(classification_loss)
        self.reg_loss_tracker.update_state(reg_loss)

        return {
            "total_loss": self.total_loss_tracker.result(),
            "classification_loss": self.classification_loss_tracker.result(),
            "reg_loss": self.reg_loss_tracker.result(),
        }
4

0 に答える 0