Random Forest est un algorithme d'apprentissage en groupe qui utilise un arbre de décision comme une machine d'apprentissage faible et qui est l'une des méthodes d'apprentissage automatique typiques. La quantité d'entités et les données d'observation sont échantillonnées pour créer un arbre de décision. Si vous le recherchez, vous en trouverez beaucoup, je vais donc omettre les algorithmes ici.
Par exemple, si vous essayez de classer les données de 1 000 cas positifs et de 50 cas négatifs par Random Forest, vous ne pouvez pas l'utiliser comme classificateur à moins que vous ne preniez certaines mesures. Il peut également être géré en pondérant les données déséquilibrées (ajustable en tant que paramètre class_weight pour RandomForest dans scikit-learn) Cependant, il est possible que le poids d'une donnée soit trop important et qu'un surentraînement puisse se produire.
Par conséquent, il existe une méthode pour traiter des données déséquilibrées en ajustant le nombre d'échantillons pour chaque arbre de décision. (Dans l'exemple précédent, par exemple, pour chaque arbre de décision, 50 exemples positifs et 50 exemples négatifs sont créés. Cet échantillonnage est effectué sans pondération pour traiter des données déséquilibrées.) Il semble que cela s'appelle Balanced Random Forest. Dans R, il peut être facilement exécuté avec des paramètres, mais dans scikit-learn, il n'y en avait pas de correspondant, alors je l'ai essayé moi-même. (Si vous faites une erreur, veuillez commenter)
balanced_random_forest.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from collections import Counter
from random import sample
from math import sqrt
import numpy as np
import pandas as pd
from sklearn.tree import DecisionTreeClassifier
from sklearn.externals.joblib import Parallel, delayed
from sklearn.utils import resample
def _build_tree(train: np.ndarray, label: np.ndarray):
tree = DecisionTreeClassifier()
tree.fit(train, label)
return tree
def _sampling_equal(y_values: np.ndarray, n_samples: int, bootstrap: bool = True):
"""
:param y_values: label data
:param n_samples: number of samples
:param bootstrap: whether bootstrap or not
:return: sampling index
"""
if bootstrap:
return [i for v in [resample(pd.Series(y_values)[pd.Series(y_values) == uq].index,
n_samples=n_samples) for uq in np.unique(y_values)] for i in v]
else:
return [i for v in [sample(list(pd.Series(y_values)[pd.Series(y_values) == uq].index),
n_samples) for uq in np.unique(y_values)] for i in v]
class BalancedRandomForestClassifier():
"""Prend en charge les données déséquilibrées en créant un arbre avec un nombre constant d'échantillons pour chaque classe"""
def __init__(self, n_estimator: int, n_samples: int, bootstrap: bool = True, max_features: int = 0):
"""
:param n_estimator: number of tree
:param n_samples: number of sampling data
:param bootstrap: how to resample
:param max_features: number of feature
"""
self.n_estimator = n_estimator
self.n_samples = n_samples
self.bootstrap = bootstrap
self.max_features = max_features
def fit(self, x_values: np.ndarray, y_values: np.ndarray):
"""
:param x_values: train data
:param y_values: label data
"""
if self.max_features == 0:
self.max_features = round(sqrt(x_values.shape[1]))
#Sélectionnez les données à entraîner par l'arborescence avec bootstrap etc.
index_list = [_sampling_equal(y_values, self.n_samples, self.bootstrap) for i in range(0, self.n_estimator)]
#Sélectionnez le montant de la fonctionnalité pour chaque arbre
self.feature_list = [sample(range(0, x_values.shape[1]), self.max_features) for i in range(0, self.n_estimator)]
#Construisez un arbre basé sur ce qui précède
self.forest = Parallel(n_jobs=-1, backend="threading")(
delayed(_build_tree)(x_values[np.ix_(index, feature)], y_values[index])
for index, feature in zip(index_list, self.feature_list))
#Déterminé par la majorité des prédictions pour chaque arbre
self.predict = lambda x: [Counter(item).most_common(1)[0][0]
for item in np.array([tree.predict(x[:, feature])
for tree, feature in zip(self.forest, self.feature_list)]).T]
#De là, le calcul de l'importance
count = np.zeros(x_values.shape[1])
feature_importances = np.zeros(x_values.shape[1])
for tree, feature in zip(self.forest, self.feature_list):
count[feature] += 1
feature_importances[feature] += tree.feature_importances_
self.feature_importances_ = feature_importances / count
def _build_tree(train: np.ndarray, label: np.ndarray):
tree = DecisionTreeClassifier()
tree.fit(train, label)
return tree
Il s'agit de l'arbre de décision scikit-learn tel quel. Balanced Random Forest ne modifie que la méthode d'échantillonnage, donc Il ne fait aucun doute que vous devriez en utiliser (ma puissance de montage est de 53)
def _sampling_equal(y_values: np.ndarray, n_samples: int, bootstrap: bool = True):
"""
:param y_values: label data
:param n_samples: number of samples
:param bootstrap: whether bootstrap or not
:return: sampling index
"""
if bootstrap:
return [i for v in [resample(pd.Series(y_values)[pd.Series(y_values) == uq].index,
n_samples=n_samples) for uq in np.unique(y_values)] for i in v]
else:
return [i for v in [sample(list(pd.Series(y_values)[pd.Series(y_values) == uq].index),
n_samples) for uq in np.unique(y_values)] for i in v]
Il obtient le même nombre d'étiquettes pour chaque étiquette avec un bootstrap (éventuellement échantillonnage sans duplication, mais généralement non utilisé). La raison pour laquelle cette inclusion est si ennuyeuse est que si vous échantillonnez chaque étiquette, ce sera un tableau multidimensionnel, donc pour le convertir en un tableau unidimensionnel
def fit(self, x_values: np.ndarray, y_values: np.ndarray):
"""
:param x_values: train data
:param y_values: label data
"""
if self.max_features == 0:
self.max_features = round(sqrt(x_values.shape[1]))
#Sélectionnez les données à entraîner par l'arborescence avec bootstrap etc.
index_list = [_sampling_equal(y_values, self.n_samples, self.bootstrap) for i in range(0, self.n_estimator)]
#Sélectionnez le montant de la fonctionnalité pour chaque arbre
self.feature_list = [sample(range(0, x_values.shape[1]), self.max_features) for i in range(0, self.n_estimator)]
#Construisez un arbre basé sur ce qui précède
self.forest = Parallel(n_jobs=-1, backend="threading")(
delayed(_build_tree)(x_values[np.ix_(index, feature)], y_values[index])
for index, feature in zip(index_list, self.feature_list))
#Déterminé par la majorité des prédictions pour chaque arbre
self.predict = lambda x: [Counter(item).most_common(1)[0][0]
for item in np.array([tree.predict(x[:, feature])
for tree, feature in zip(self.forest, self.feature_list)]).T]
#De là, le calcul de l'importance
count = np.zeros(x_values.shape[1])
feature_importances = np.zeros(x_values.shape[1])
for tree, feature in zip(self.forest, self.feature_list):
count[feature] += 1
feature_importances[feature] += tree.feature_importances_
self.feature_importances_ = feature_importances / count
―― Tout d'abord, décidez du nombre de fonctionnalités à utiliser pour chaque arbre de décision
Puisque la valeur prédite est déterminée par la majorité des arbres créés, la prédiction est faite en fonction de la quantité de caractéristiques ( self.feature_list '') utilisée pour chaque arbre, et la majorité est prise (
Counter (item) .most_common. (1) [0] [0] `` a acquis les étiquettes les plus nombreuses.)
Puisque l'importance est calculée comme la valeur moyenne du taux de contribution du montant de la caractéristique pour chaque arbre déterminé, La valeur totale d'importance de chaque entité est divisée par le nombre d'occurrences.
Recommended Posts