3

I am trying to train on a colab TPU using data from my GCP account.

When I run the cell that starts the training, the cell just seems to hang, with no progress. I put a very low number of steps, so that the training should complete pretty quickly, about a minute on GPU, but it never finishes on TPU.

I am using a custom model, and I am using files saved on GCP using the solution given in this stackoverflow answer How to connect to private storage bucket using the Google Colab TPU

The model trains/runs just fine on GPU/CPU.

The full code is in this colab notebook here

https://colab.research.google.com/drive/13HgRJru0glOzn7m0b7tmVCO_VrRpa1XS?usp=sharing

And here's a google drive link to the sample data file

https://drive.google.com/file/d/10EFyxau97jLfeGaKugMevIyX-bobsFe5/view?usp=sharing

And below is the code from the colab notebook

!pip install transformers --q
%tensorflow_version 2.x

!gcloud auth login

'''NEED TO RUN THIS CELL TWICE TO AVOID ERROR'''

from google.colab import auth
auth.authenticate_user()

project_id = 'machinelearning-264918'
!gcloud config set project {project_id}

!pip install tfa-nightly
import tensorflow_addons as tfa

from transformers import TFBertModel, AutoModel
import tensorflow as tf
from tensorflow.keras.layers import (Dense,
                                     Dropout)
import os
import tensorflow_addons as tfa

logger = tf.get_logger()
logger.info(tf.__version__)

autotune = tf.data.experimental.AUTOTUNE

try:
    tpu = tf.distribute.cluster_resolver.TPUClusterResolver()
    tf.config.experimental_connect_to_cluster(tpu)
    tf.tpu.experimental.initialize_tpu_system(tpu)
    strategy = tf.distribute.experimental.TPUStrategy(tpu)
    logger.info('Running with TPUStrategy on TPU {} with {} cores '
                .format(tpu.cluster_spec().as_dict()['worker'],
                        strategy.num_replicas_in_sync))
    batch_size = 3 * strategy.num_replicas_in_sync
except Exception:
    # raise ValueError
    strategy = tf.distribute.OneDeviceStrategy(device='/gpu:0')
    logger.warning('Failed initializing TPU! Running on GPU')
    batch_size = 3

from tensorflow.python.keras.mixed_precision.experimental import loss_scale_optimizer as lso
from tensorflow.python.distribute import parameter_server_strategy

def _minimize(strategy, tape, optimizer, loss, trainable_variables):
    with tape:
        if isinstance(optimizer, lso.LossScaleOptimizer):
            loss = optimizer.get_scaled_loss(loss)

    gradients = tape.gradient(loss, trainable_variables)
    # Whether to aggregate gradients outside of optimizer. This requires support
    # of the optimizer and doesn't work with ParameterServerStrategy and
    # CentralStroageStrategy.
    aggregate_grads_outside_optimizer = (
        optimizer._HAS_AGGREGATE_GRAD and  # pylint: disable=protected-access
        not isinstance(strategy.extended,
                        parameter_server_strategy.ParameterServerStrategyExtended))

    if aggregate_grads_outside_optimizer:
        # We aggregate gradients before unscaling them, in case a subclass of
        # LossScaleOptimizer all-reduces in fp16. All-reducing in fp16 can only be
        # done on scaled gradients, not unscaled gradients, for numeric stability.
        gradients = optimizer._aggregate_gradients(zip(gradients,  # pylint: disable=protected-access
                                                    trainable_variables))
    if isinstance(optimizer, lso.LossScaleOptimizer):
        gradients = optimizer.get_unscaled_gradients(gradients)
    gradients = optimizer._clip_gradients(gradients)  # pylint: disable=protected-access
    if trainable_variables:
        if aggregate_grads_outside_optimizer:
            optimizer.apply_gradients(
                zip(gradients, trainable_variables),
                experimental_aggregate_gradients=False)
        else:
            optimizer.apply_gradients(zip(gradients, trainable_variables))

class CustomModel(tf.keras.Model):
    def train_step(self, data):
        # Unpack the data. Its structure depends on your model and
        # on what you pass to `fit()`.
        x, y = data
        batch_label = tf.reshape(y, (tf.size(y)/2, 2), name=None)

        rs = tf.ragged.stack(x, axis=0)
        reg = rs.to_tensor()
        batch_input = tf.reshape(reg, (tf.shape(reg)[0]*tf.shape(reg)[1], tf.shape(reg)[2]))

        with tf.GradientTape() as tape:
            y_pred = self(batch_input, training=True)  # Forward pass
            # Compute the loss value
            # (the loss function is configured in `compile()`)
            loss = self.compiled_loss(batch_label, y_pred, regularization_losses=self.losses)

        # Compute gradients
        _minimize(self.distribute_strategy, tape, self.optimizer, loss,
                self.trainable_variables)
        # Update weights
        # self.optimizer.apply_gradients(zip(gradients, trainable_vars))
        # Update metrics (includes the metric that tracks the loss)
        self.compiled_metrics.update_state(y, y_pred)
        # Return a dict mapping metric names to current value
        return {m.name: m.result() for m in self.metrics}

def get_model(drop_out):
    sciBert = TFBertModel.from_pretrained('bert-base-uncased', from_pt=True)

    allFinal = tf.keras.Input(shape=(None,), dtype=tf.int32, name='inputN') 

    '''Should posFinal and negFinal be concatenated, so there's only one call to sciBert'''
    allBertOut = sciBert(allFinal, training=True)

    allPoolConcat = tf.concat([
                    allBertOut[0][:, 0], #output of ff layer after last hidden state since it seems to be untrained in roberta
                    tf.reduce_mean(allBertOut[0][:, 1:-1], axis=1)
                    ],axis=1) 

    postLayer = tf.keras.layers.Dense(768, activation='swish', name='postff')
    LayerNorm = tf.keras.layers.LayerNormalization(epsilon=1e-12, name="LayerNormO")
    postLayer2 = tf.keras.layers.Dense(768, activation='swish', name='2postff')
    classifier = tf.keras.layers.Dense(2, name='classifierff')

    postWeights = postLayer(allPoolConcat) 
    postWeights = LayerNorm(postWeights)
    postWeights = Dropout(drop_out)(postWeights)

    postWeights2 = postLayer2(postWeights) 
    allScores = classifier(postWeights2) 

    model = CustomModel(inputs=allFinal, outputs=allScores)
    return model

@tf.function
def _parse_example(example_proto):
    features = {
        'sciBert_SentenceIndex': tf.io.VarLenFeature( dtype=tf.int64),
        'SciBert_IDs': tf.io.VarLenFeature(dtype=tf.int64),
    }

    parsed_example_dict = tf.io.parse_single_example(example_proto, features)
    sentencePositions = parsed_example_dict['sciBert_SentenceIndex']
    passageIds = parsed_example_dict['SciBert_IDs']

    sentencePositions = tf.sparse.to_dense(sentencePositions)
    bertIds = tf.sparse.to_dense(passageIds)

    sentencePositions = tf.cast(sentencePositions, dtype=tf.int32)
    passageIds = tf.cast(passageIds, dtype=tf.int32)
    length = tf.shape(
                        sentencePositions, out_type=tf.dtypes.int32, name='shape'
                    )

    lengthMinusOne = tf.math.subtract(
                            length, 1, name='SubtractOne'
                            )

    # creage random numbers for a sentence index up to 2nd to last index
    # the last index is just the last position of the non-padded bertID
    startRandSentIndex = tf.random.uniform(
            shape=[1], minval=0, maxval=lengthMinusOne[0], dtype=tf.dtypes.int32, seed=None, name=None)
    # Get the end point for that sentence 
    endRandSentIndex = tf.math.add(startRandSentIndex, 1, name=None)
    # last position of the non-padded bertID
    lastPosition = length-1
    # extract BertID positions for sentence start/end and bertID end
    startSentencePosit = tf.gather_nd(sentencePositions, [startRandSentIndex], batch_dims=0)
    endSentencePosit = tf.gather_nd(sentencePositions, [endRandSentIndex], batch_dims=0)
    lastPassagePosit = tf.gather_nd(sentencePositions, [lastPosition], batch_dims=0)
    # Get slices of BertIDs for the query, and the rest
    firstPiece = tf.slice(bertIds, [0], [startSentencePosit[0]] )
    queryPiece = tf.slice(bertIds, [startSentencePosit[0]], [endSentencePosit[0]-startSentencePosit[0]] )
    lastPiece = tf.slice(bertIds, [endSentencePosit[0]], [lastPassagePosit[0]-endSentencePosit[0]] )
    # concat rest of passage
    restPassagePiece = tf.concat( [firstPiece,lastPiece], axis=0 )
    # Clip
    queryPiece = queryPiece[0:256]

    restPassagePiece = restPassagePiece[0:510]
    # add special tokens for proper input into the model 
    return tf.cast(queryPiece, dtype=tf.int32), tf.cast(restPassagePiece, dtype=tf.int32)

@tf.function
def clip_seq_to_len(seq, num_tokens=512):
    seq_len = tf.shape(seq)[0]
    if seq_len > 511:
        return seq[:511]
    return seq[:]

@tf.function
def make_samples(query_a, passage_a, query_b, passage_b):
    CLS_inputID = tf.constant([102])
    SEP_inputID = tf.constant([103])

    positive_sample_a = clip_seq_to_len(tf.concat([CLS_inputID, query_a, SEP_inputID, passage_a], axis=-1))
    positive_sample_b = clip_seq_to_len(tf.concat([CLS_inputID, query_b, SEP_inputID, passage_b], axis=-1))

    negative_sample_a = clip_seq_to_len(tf.concat([CLS_inputID, query_a, SEP_inputID, passage_b], axis=-1))
    negative_sample_b = clip_seq_to_len(tf.concat([CLS_inputID, query_b, SEP_inputID, passage_a], axis=-1))
    
    positive_sample_a = tf.concat([positive_sample_a, SEP_inputID], axis=-1)
    positive_sample_b = tf.concat([positive_sample_b, SEP_inputID], axis=-1)
    negative_sample_a = tf.concat([negative_sample_a, SEP_inputID], axis=-1)
    negative_sample_b = tf.concat([negative_sample_b, SEP_inputID], axis=-1)
    return positive_sample_a, positive_sample_b, negative_sample_a, negative_sample_b

@tf.function
def get_samples(example_a, example_b):
    samples = make_samples(*_parse_example(example_a), *_parse_example(example_b))
    return samples

config = {
  'drop_out':0.1
}

loss_fn = tf.keras.losses.CategoricalCrossentropy(from_logits=True)

with strategy.scope():
    model = get_model(**config)
    model.compile(loss=loss_fn,
                  optimizer=tfa.optimizers.AdamW(weight_decay=1e-5, learning_rate=3e-4, epsilon=1e-07), run_eagerly=False)

config_name = 'model_b'
base_dir = 'gs://bdora-semanticscholar'
model_dir = os.path.join(base_dir, config_name)
# tensorboard_dir = os.path.join(model_dir, 'logs_' + str(time()))
tfrecords_pattern_train = os.path.join(base_dir, 'VersionB_00022*')
tfrecords_pattern_train2 = os.path.join(base_dir, 'VersionB_00022*')

@tf.function
def gen():
    while True:
        yield ([1, 0], [1, 0], [0, 1], [0, 1] )

batchNumber = batch_size
run_eagerly = False

with strategy.scope():
    filenames = tf.io.gfile.glob(tfrecords_pattern_train)
    train_dataset = tf.data.TFRecordDataset(filenames, num_parallel_reads=autotune)

    filenames = tf.io.gfile.glob(tfrecords_pattern_train)
    neg_dataset = tf.data.TFRecordDataset(filenames, num_parallel_reads=autotune)
    
    train_dataset = train_dataset.shuffle(150_000, seed=1000, reshuffle_each_iteration=True)
    neg_dataset = neg_dataset.shuffle(150_000, seed=2000, reshuffle_each_iteration=True)

    train_datasetC = tf.data.Dataset.zip((train_dataset, neg_dataset))
    train_datasetC = train_datasetC.map(get_samples, num_parallel_calls=autotune)
    
    train_datasetC = train_datasetC.shuffle(1024, seed=1000, reshuffle_each_iteration=True)
    train_datasetC = train_datasetC.padded_batch(batchNumber, padding_values=(0, 0, 0, 0))

    datasetLabels = tf.data.Dataset.from_generator(
        gen,
        (tf.int32, tf.int32, tf.int32, tf.int32),
        (tf.TensorShape([None]), tf.TensorShape([None]), tf.TensorShape([None]), tf.TensorShape([None])))
    
    datasetLabels = datasetLabels.batch(batchNumber)

    train_datasetFinal = tf.data.Dataset.zip((train_datasetC, datasetLabels))
    train_datasetFinal = train_datasetFinal.prefetch(autotune)
    train_datasetFinal = train_datasetFinal.repeat()
    train_datasetFinal = train_datasetFinal.apply(tf.data.experimental.ignore_errors())

model.fit(train_datasetFinal, steps_per_epoch=100, epochs=3)

And this is the only output I get

Epoch 1/3
WARNING:tensorflow:Gradients do not exist for variables ['tf_bert_model/bert/pooler/dense/kernel:0', 'tf_bert_model/bert/pooler/dense/bias:0'] when minimizing the loss.
WARNING:tensorflow:Gradients do not exist for variables ['tf_bert_model/bert/pooler/dense/kernel:0', 'tf_bert_model/bert/pooler/dense/bias:0'] when minimizing the loss.
WARNING:tensorflow:Gradients do not exist for variables ['tf_bert_model/bert/pooler/dense/kernel:0', 'tf_bert_model/bert/pooler/dense/bias:0'] when minimizing the loss.
WARNING:tensorflow:Gradients do not exist for variables ['tf_bert_model/bert/pooler/dense/kernel:0', 'tf_bert_model/bert/pooler/dense/bias:0'] when minimizing the loss.
WARNING:tensorflow:Gradients do not exist for variables ['tf_bert_model/bert/pooler/dense/kernel:0', 'tf_bert_model/bert/pooler/dense/bias:0'] when minimizing the loss.
WARNING:tensorflow:Gradients do not exist for variables ['tf_bert_model/bert/pooler/dense/kernel:0', 'tf_bert_model/bert/pooler/dense/bias:0'] when minimizing the loss.
WARNING:tensorflow:Gradients do not exist for variables ['tf_bert_model/bert/pooler/dense/kernel:0', 'tf_bert_model/bert/pooler/dense/bias:0'] when minimizing the loss.
WARNING:tensorflow:Gradients do not exist for variables ['tf_bert_model/bert/pooler/dense/kernel:0', 'tf_bert_model/bert/pooler/dense/bias:0'] when minimizing the loss.
SantoshGupta7
  • 5,607
  • 14
  • 58
  • 116

1 Answers1

0

I found this GitHub issue discussion [1] that you can refer to. It's not an error, it just means it's not updating those variables. Those variables (pooler) are not used when doing sequence classification.

[1] https://github.com/tensorflow/tensorflow/issues/37501