class_docstr: Description
  -----------
  Boost GNN predictor for semi-supervised node classification or regression problems.
  Publication: https://arxiv.org/abs/2101.08543
  
  Parameters
  ----------
  gnn_model : nn.Module
      DGL implementation of GNN model.
  task: str, optional
      Regression or classification task.
  loss_fn : callable, optional
      Function that takes torch tensors, pred and true, and returns a scalar.
  trees_per_epoch : int, optional
      Number of GBDT trees to build each epoch.
  backprop_per_epoch : int, optional
      Number of backpropagation steps to make each epoch.
  lr : float, optional
      Learning rate of gradient descent optimizer.
  append_gbdt_pred : bool, optional
      Append GBDT predictions or replace original input node features.
  train_input_features : bool, optional
      Train original input node features.
  gbdt_depth : int, optional
      Depth of each tree in GBDT model.
  gbdt_lr : float, optional
      Learning rate of GBDT model.
  gbdt_alpha : int, optional
      Weight to combine previous and new GBDT trees.
  random_seed : int, optional
      random seed for GNN and GBDT models.
  
  Examples
  ----------
  gnn_model = GAT(10, 20, num_heads=5),
  bgnn = BGNNPredictor(gnn_model)
  metrics = bgnn.fit(graph, X, y, train_mask, val_mask, test_mask, cat_features)
code: def init_node_features(self, X):
      node_features = torch.empty(
          X.shape[0],
          self.in_dim,
          requires_grad=True,
          device=self.device,
      )
      if self.append_gbdt_pred:
          node_features.data[:, : -self.out_dim] = torch.from_numpy(
              X.to_numpy(copy=True)
          )
      return node_features
  
imports: import itertools
  import time
  from collections import defaultdict
  import numpy
  import pandas
  import torch
  import torch.nn.functional
  from catboost import CatBoostClassifier, CatBoostRegressor, Pool, sum_models
  from sklearn import preprocessing
  from sklearn.metrics import r2_score
  from tqdm import tqdm
label_desc: Use image node_id 8 for calling the BGNNPredictor obj's underlying member method code with example usage: obj.init_node_features(X) and returns: node_features