(air whooshing)
(smiley face popping)
(air whooshing)
- Write your own training loop with PyTorch.
In this video, we'll look at
how we can do the same fine-tuning as in the Trainer video,
but without relying on that class.
This way, you'll be able to easily customize each step
to the training loop to your needs.
This is also very useful
to manually debug something
that went wrong with the Trainer API.
Before we dive into the code,
here is a sketch of a training loop.
We take a batch of training data and feed it to the model.
With the labels, we can then compute a loss.
That number is not useful in its own,
that is used to compute
the ingredients of our model weights,
that is the derivative of the loss
with respect to each model weight.
Those gradients are then used by the optimizer
to update the model weights,
and make them a little bit better.
We then repeat the process
with a new batch of training data.
If any of this isn't clear,
don't hesitate to take a refresher
on your favorite deep learning course.
We'll use the GLUE MRPC data set here again,
and we've seen how to prepropose the data
using the Datasets library with dynamic padding.
Check out the videos link below
if you haven't seen them already.
With this done, we only have to define PyTorch DataLoaders
which will be responsible to convert
the elements of our dataset into patches.
We use our DataColletorForPadding as a collate function,
and shuffle the training set
to make sure we don't go over the samples
in the same order at a epoch*.
To check that everything works as intended,
we try to grab a batch of data, and inspect it.
Like our data set elements, it's a dictionary,
but these times the values are not a single list of integers
but a tensor of shape batch size by sequence length.
The next step is to send the training data in our model.
For that, we'll need to actually create a model.
As seen in the Model API video,
we use the from_pretrained method,
and adjust the number of labels to the number of classes
we have on this data set, here two.
Again to be sure everything is going well,
we pass the batch we grabbed to our model,
and check there is no error.
If the labels are provided,
the models of the Transformers library
always returns a loss directly.
We will be able to do loss.backward()
to compute all the gradients,
and will then need an optimizer to do the training step.
We use the AdamW optimizer here,
which is a variant of Adam with proper weight decay,
but you can pick any PyTorch optimizer you like.
Using the previous loss,
and computing the gradients with loss.backward(),
we check that we can do the optimizer step
without any error.
Don't forget to zero your gradient afterwards,
or at the next step,
they will get added to the gradients you computed.
We could already write our training loop,
but we will add two more things
to make it as good as it can be.
The first one is a learning rate scheduler,
to progressively decay our learning rate to zero.
The get_scheduler function from the Transformers library
is just a convenience function
to easily build such a scheduler.
You can again use
any PyTorch learning rate scheduler instead.
Finally, if we want our training
to take a couple of minutes instead of a few hours,
we will need to use a GPU.
The first step is to get one,
for instance by using a collab notebook.
Then you need to actually send your model,
and training data on it by using a torch device.
Double-check the following lines
print a CUDA device for you.
or be prepared for your training to less, more than an hour.
We can now put everything together.
First, we put our model in training mode
which will activate the training behavior
for some layers, like Dropout.
Then go through the number of epochs we picked,
and all the data in our training dataloader.
Then we go through all the steps we have seen already;
send the data to the GPU,
compute the model outputs,
and in particular the loss.
Use the loss to compute gradients,
then make a training step with the optimizer.
Update the learning rate in our scheduler
for the next iteration,
and zero the gradients of the optimizer.
Once this is finished,
we can evaluate our model very easily
with a metric from the Datasets library.
First, we put our model in evaluation mode,
to deactivate layers like Dropout,
then go through all the data in the evaluation data loader.
As we have seen in the Trainer video,
the model outputs logits,
and we need to apply the argmax function
to convert them into predictions.
The metric object then has an add_batch method,
we can use to send it those intermediate predictions.
Once the evaluation loop is finished,
we just have to call the compute method
to get our final results.
Congratulations, you have now fine-tuned a model
all by yourself.
(air whooshing)