Write your own training loop in PyTorch. In this video, we will look at how we can do the same fine-tuning as in the Trainer video, but without relying on that class. This way you will be able to easily customize each step of 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 on its own, but is used to compute the gradients 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 is unclear, don't hesitate to take a refresher on your favorite deep learning course. We will use the GLUE MRPC dataset here again, and we have seen how to preprocess the data using the Datasets library with dynamic padding. Checkout the videos linked 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 batches. We use our DataCollatorForPadding as the collate function, and shuffle the training set. To check that everything works as intended, we try to grab a batch of data and inspect it. Like our dataset elements, it's a dictionary, but this time 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 will need to create our 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 dataset, 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 return the 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 afterward, or at the next step they will get added to the gradients you compute! 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 colab 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! 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, 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!