Formation des modèles d'arbres
Let's go !

2.2 Le Random Forest from scratch

Je ne le dirais jamais assez, mais implémenter un algorithme from scratch est pour moi la meilleure façon d’être sûr d’avoir bien compris son fonctionnement

Dans cette partie, nous allons implémenter l’algorithme du random forest en Python.

Pour des soucis de simplicité, nous n’allons pas implémenter l’algorithme d’arbre de décision mais utiliser ce qui est proposé par le package Sklearn. 

Si vous voulez avoir plus d’informations sur l’implémentation de l’arbre de décision from scratch, vous pouvez retourner dans la partie précédente.

A/ La classe Random forest

Nous allons coder la classe du modèle qui va nous permettre d’entraîner nos modèles de random forest.

On va commencer par créer la fonction d’initialisation de la classe.

C’est à cette étape que l’on va demander à l’utilisateur de spécifier toutes les informations dont on a besoin pour entraîner notre modèle.

class RandomForestClassifier():
  def __init__(self, n_estimators=100, max_depth=None, min_samples_split=2, 
               min_samples_leaf=1, min_weight_fraction_leaf=0, max_features="auto",
               max_leaf_nodes=None, min_impurity_decrease=0, random_state=None, 
               class_weight=None, max_sample=None, max_columns=4):
    self._n_estimators = n_estimators
    self._max_depth = max_depth
    self._min_samples_split = min_samples_split
    self._min_samples_leaf = min_samples_leaf
    self._min_weight_fraction_leaf = min_weight_fraction_leaf
    self._max_features = max_features
    self._max_leaf_nodes = max_leaf_nodes
    self._min_impurity_decrease = min_impurity_decrease
    self._random_state = random_state
    self._class_weight = class_weight
    self._max_sample = max_sample
    self._max_columns = max_columns
    self._model = dict()
    self._features = dict()

La classe fit, va permettre d’entraîner un nombre d’arbres de notre forêt égal au nombre spécifié dans n_estimators_.

Nous allons aléatoirement choisir un nombre d’exemples et un nombre de colonnes, cet échantillon est assigné à  x_samp.

Nous allons entraîner un arbre en utilisant x_samp comme données d’entraînement. Cet arbre sera sauvé dans le dictionnaire model et les variables à utiliser pour cet arbre seront sauvées dans le dictionnaire features.

  def fit(self, x, y):

    if not(self._max_sample) :
      self._max_sample = x.shape[0]

    for est in range(self._n_estimators) :
      rand_index = np.random.randint(low=0, high=x.shape[0], size=self._max_sample)

      rand_column = np.random.randint(low=0, high=x.shape[1], size=self._max_columns)

      x_samp = x[rand_index, :]
      x_samp = x_samp[:, rand_column]

      y_samp = y[rand_index]

      decision_tree_model = DecisionTreeClassifier(max_depth=self._max_depth, 
                                                   min_samples_split=self._min_samples_split,
                                                   min_samples_leaf=self._min_samples_leaf,
                                                   min_weight_fraction_leaf=self._min_weight_fraction_leaf,
                                                   max_features=self._max_features,
                                                   max_leaf_nodes=self._max_leaf_nodes,
                                                   min_impurity_decrease=self._min_impurity_decrease,
                                                   random_state=self._random_state,
                                                   class_weight=self._class_weight)
      self._model[est] = decision_tree_model.fit(x_samp, y_samp)
      self._features[est] = rand_column

La classe predict utilise les données passées en paramètres dans et boucle sur les arbres de notre forêt pour obtenir une prédiction pour chaque arbre.

  def predict(self, x):

    pred = np.zeros(x.shape[0])

    for i in range(self._n_estimators):
      pred += self._model[i].predict(x[:, self._features[i]])

    pred = pred / self._n_estimators

    pred = np.where(pred >= 0.5, 1, 0)

    return pred