docstr: Finetuning stage.
  In this stage, we actually trained a combination model with the encoder trained
  during pretraining stage and another projection head with downstream task.
docstr_tok: ["Finetuning","stage",".","In","this","stage",",","we","actually","trained","a","combination","model","with","the","encoder","trained","during","pretraining","stage","and","another","projection","head","with","downstream","task","."]
code: def _train_finetuning_only(self, dataset):
      """
      Finetuning stage.
      In this stage, we actually trained a combination model with the encoder trained
      during pretraining stage and another projection head with downstream task.
      """
      model = self._compose_model()
      fine_train_loader = utils.graph_get_split(
          dataset,
          "train",
          batch_size=self.batch_size,
          num_workers=self.num_workers,
          shuffle=True,
      )
      try:
          fine_val_loader = utils.graph_get_split(
              dataset,
              "val",
              batch_size=self.batch_size,
              num_workers=self.num_workers,
          )
      except ValueError:
          fine_val_loader = fine_train_loader
      except AttributeError:
          fine_val_loader = fine_train_loader
      optimizer = self.f_optimizer(
          model.parameters(),
          lr=self.f_lr,
          weight_decay=self.f_weight_decay,
      )
      scheduler = self._get_scheduler("finetune", optimizer)
      with trange(self.f_epoch) as t:
          epoch_loss = 0.0
          for epoch in t:
              t.set_description(f"Finetuning epoch {epoch + 1}")
              model.train()
              for data in fine_train_loader:
                  optimizer.zero_grad()
                  data = data.to(self.device)
                  out = model(data)
                  loss = self.f_loss(out, data.y)
                  loss.backward()
                  optimizer.step()
                  if self.f_lr_scheduler_type:
                      scheduler.step()
                  epoch_loss += loss.item()
              if fine_val_loader is not None:
                  eval_func = (
                      self.feval
                      if not isinstance(self.feval, list)
                      else self.feval[0]
                  )
                  val_loss = self._evaluate(fine_val_loader, eval_func)
  
                  if eval_func.is_higher_better():
                      val_loss = -val_loss
                  self.f_early_stopping(val_loss, model)
                  if self.f_early_stopping.early_stop:
                      LOGGER.debug("Early stopping at", epoch)
                      break
              else:
                  self.f_early_stopping(epoch_loss, model)
                  if self.f_early_stopping.early_stop:
                      LOGGER.debug("Early stop at", epoch)
                      break
      self.f_early_stopping.load_checkpoint(model)
  
imports: import os
  import torch
  import logging
  import torch.nn.functional
  import torch.utils.data
  import numpy
  import typing
  import torch.multiprocessing
  from typing import Union, Tuple, Sequence, Type, Callable
  from tqdm import trange
  from copy import deepcopy
  from .base import BaseContrastiveTrainer
  from ..None import register_trainer
  from ..base import EarlyStopping, _DummyModel
  from ..evaluation import Evaluation, get_feval, Acc
  from ...model import BaseAutoModel, BaseEncoderMaintainer, BaseDecoderMaintainer, DecoderUniversalRegistry
  from ....datasets import utils
  from ....utils import get_logger
  from torch_geometric.nn.glob import global_add_pool, global_max_pool, global_mean_pool
label_desc: Use image node_id 6 for calling the GraphCLSemisupervisedTrainer obj's underlying member method code with example usage: obj._train_finetuning_only(dataset) without return types