Тонкая настройка последних х слоев BERT - PullRequest
1 голос
/ 07 мая 2019

Я пытаюсь настроить BERT только на определенных последних слоях (скажем, 3 последних слоя). Я хочу использовать Google Colab для обучения на ТПУ. Я использую hub.Module , чтобы загрузить BERT и точно настроить его, а затем использовать точно настроенный вывод для моей задачи классификации.

bert_module = hub.Module(BERT_MODEL_HUB, tags=tags, trainable=True)

hub.Module имеет возможность установить модель как обучаемую или не обучаемую, но не как частично обучаемую (только отдельные слои)

Кто-нибудь знает, как я могу тренировать только последние 1,2 или 3 слоя BERT, используя hub.Module?

Спасибо

Ответы [ 2 ]

1 голос
/ 04 июня 2019

Вы можете установить его вручную в списке обучаемых переменных.Ниже приведена моя реализация слоя Берта в tenorflow-keras-

class BertLayer(tf.keras.layers.Layer):
      def __init__(self, n_fine_tune_layers, **kwargs):
          self.n_fine_tune_layers = n_fine_tune_layers
          self.trainable = True
          self.output_size = 768
          super(BertLayer, self).__init__(**kwargs)

      def build(self, input_shape):
          self.bert = hub.Module(
              bert_path,
              trainable=True,# did this in place of self.trainable
              name="{}_module".format(self.name)
          )

          trainable_vars = self.bert.variables


          trainable_vars = [var for var in trainable_vars if not "/cls/" in var.name]
          #print("--------------------------len=",len(trainable_vars))
          # Select how many layers to fine tune
          trainable_vars = trainable_vars[-self.n_fine_tune_layers:]

          # Add to trainable weights
          for var in trainable_vars:
              self._trainable_weights.append(var)

          for var in self.bert.variables:
              if var not in self._trainable_weights:
                  self._non_trainable_weights.append(var)

          super(BertLayer, self).build(input_shape)

      def call(self, inputs):
          inputs = [K.cast(x, dtype="int32") for x in inputs]
          input_ids, input_mask, segment_ids = inputs
          bert_inputs = dict(
              input_ids=input_ids, input_mask=input_mask, segment_ids=segment_ids
          )
          result = self.bert(inputs=bert_inputs, signature="tokens", as_dict=True)[
              "pooled_output"
          ]
          return result

      def compute_output_shape(self, input_shape):
          return (input_shape[0], self.output_size)

Сосредоточиться на следующей строке в приведенном выше коде -

trainable_vars = trainable_vars[-self.n_fine_tune_layers:]

Вы можете установить аргумент n_fine_tune_layers равным 1/ 2/3 от defalt-

def __init__(self, n_fine_tune_layers=2, **kwargs):
0 голосов
/ 09 июля 2019

Приведенный ниже код взят из этого поста (https://towardsdatascience.com/bert-in-keras-with-tensorflow-hub-76bcbc9417b) и неверен.

trainable_vars = self.bert.variables

trainable_vars = trainable_vars[-self.n_fine_tune_layers:]

Вернет переменные в алфавитном порядке, а не в фактическом порядке слоя. Таким образом, он вернет уровень 11 до уровня 4 и т. Д. Это не то, что вы хотите.

Я точно не определился, как получить фактический порядок, в котором реализованы слои, но обновлю этот ответ, когда я это сделаю!

...