En utilisant RandomForestClassifier de scikit-learn, vous pouvez résoudre le problème de classification dans une forêt aléatoire. En tant que fonctionnalité de Random Forest, il est possible d'identifier les données aberrantes qui ont une valeur différente de la valeur d'attribut qui représente la classe à partir des données appartenant à la même classe. Puisque le scikit-learn officiel n'a pas de fonction pour calculer les valeurs aberrantes, cette fois j'ai créé un script qui génère des valeurs aberrantes. (Au fait, il peut être calculé avec R)
Pour trouver la valeur aberrante, utilisez apply dans la méthode RandomForestClassifier de scicit-learn. Il s'agit d'une méthode qui renvoie l'index de feuille indiquant dans quelle feuille chaque donnée est contenue lorsque les données d'entrée du lot sont fournies à chaque arbre de décision créé par l'algorithme de forêt aléatoire.
Afin de trouver la valeur de l'écart, il est d'abord nécessaire de trouver le degré de proximité de chaque donnée.
Le degré de proximité de chaque donnée est calculé à l'aide du tableau renvoyé par la méthode apply comme argument. La méthode apply renvoie un tableau bidimensionnel de [nombre d'échantillons, nombre d'arbres de décision].
A proximité, les données $ x_ {k} $ contenues dans la même feuille que les données $ x_ {n} $ sont comptées, et la somme est calculée en l'exécutant sur tous les arbres de détermination qui les ont créées. Enfin, le résultat est divisé par le nombre d'arbres de décision et normalisé pour obtenir le degré d'approximation des données $ x_ {n} $. Le résultat final est renvoyé sous la forme d'un tableau bidimensionnel de [Nombre d'échantillons, Nombre d'échantillons]. (Au fait, le tableau est une matrice diagonale)
def proximity(data):
n_samples = np.zeros((len(data),len(data)))
n_estimators = len(data[0])
for e,est in enumerate(np.transpose(np.array(data))):
for n,n_node in enumerate(est):
for k,k_node in enumerate(est):
if n_node == k_node:
n_samples[n][k] += 1
n_samples = 1.0 * np.array(n_samples) / n_estimators
return n_samples
Après avoir trouvé le degré d'approximation, trouvez la valeur aberrante. Un tableau d'étiquettes correctes est utilisé comme argument pour calculer les valeurs aberrantes dans la même classe. Le flux de traitement est le suivant.
--Calculer la valeur moyenne du degré de proximité dans la classe
--Calculer les valeurs aberrantes de chaque donnée
--Calculer la valeur médiane et l'écart absolu médian (MAD) des valeurs aberrantes de chaque classe
--Normaliser les valeurs aberrantes de chaque donnée avec les écarts absolus médians et médians
C'est tout ce que vous devez faire, et vous pouvez facilement l'écrire en utilisant numpy. Si l'instruction for est également incluse, la vitesse peut être augmentée.
Utilisez également XGBoost en utilisant l'encapsuleur scikit-learn de XGBoost. Il est également possible de spécifier les valeurs aberrantes.
À propos, dans la normalisation des valeurs aberrantes, la valeur médiane et la valeur MAD sont utilisées à la place de la moyenne et de l'écart type, car il s'agit d'une statistique (robuste) qui n'est pas facilement affectée par les valeurs aberrantes.
def outlier(data, label):
N = len(label)
pbar = [0] * N
data = np.square(data)
#Trouvez la valeur moyenne du degré de proximité dans la classe
for n,n_prox2 in enumerate(data):
for k,k_prox2 in enumerate(n_prox2):
if label[n] == label[k]:
pbar[n] += k_prox2
if pbar[n] == 0.0:
pbar[n] = 1.0e-32
#Trouvez la valeur aberrante
out = N / np.array(pbar)
#Trouvez les valeurs aberrantes médianes pour chaque classe
meds = {}
for n,l in enumerate(label):
if l not in meds.keys():
meds[l] = []
meds[l].append(out[n])
label_uniq = list(set(label))
med_uniq = {} #La médiane réelle de chaque classe entre dans cette variable
for l in label_uniq:
med_uniq[l] = np.median(meds[l])
#Écart absolu central des valeurs aberrantes pour chaque classe(MAD)Cherchant
mads = {}
for n,l in enumerate(label):
if l not in mads.keys():
mads[l] = []
mads[l].append(np.abs(out[n] - med_uniq[l]))
mad_uniq = {} #Le MAD réel de chaque classe entre dans cette variable
for l in label_uniq:
mad_uniq[l] = np.median(mads[l])
#Normaliser les valeurs aberrantes de chaque donnée avec la valeur médiane, MAD
outlier = [0] * N
for n,l in enumerate(label):
if mad_uniq[l] == 0.0:
outlier[n] = out[n] - med_uniq[l]
else:
outlier[n] = (out[n] - med_uniq[l]) / mad_uniq[l]
return outlier
En utilisant la fonction ci-dessus, j'ai essayé d'identifier la valeur aberrante de l'iris dans les exemples de données de sklearn. L'exemple de code pour générer l'image de ce résultat est illustré ci-dessous.
outlier.py
from sklearn.datasets import load_iris
from sklearn.ensemble import RandomForestClassifier
import numpy as np
import matplotlib.pyplot as plt
def proximity(data):
n_samples = np.zeros((len(data),len(data)))
n_estimators = len(data[0])
for e,est in enumerate(np.transpose(np.array(data))):
for n,n_node in enumerate(est):
for k,k_node in enumerate(est):
if n_node == k_node:
n_samples[n][k] += 1
n_samples = 1.0 * np.array(n_samples) / n_estimators
return n_samples
def outlier(data, label):
N = len(label)
pbar = [0] * N
data = np.square(data)
#Trouvez la valeur moyenne du degré de proximité dans la classe
for n,n_prox2 in enumerate(data):
for k,k_prox2 in enumerate(n_prox2):
if label[n] == label[k]:
pbar[n] += k_prox2
if pbar[n] == 0.0:
pbar[n] = 1.0e-32
#Trouvez la valeur aberrante
out = N / np.array(pbar)
#Trouvez les valeurs aberrantes médianes pour chaque classe
meds = {}
for n,l in enumerate(label):
if l not in meds.keys():
meds[l] = []
meds[l].append(out[n])
label_uniq = list(set(label))
med_uniq = {} #La médiane réelle de chaque classe entre dans cette variable
for l in label_uniq:
med_uniq[l] = np.median(meds[l])
#Écart absolu central des valeurs aberrantes pour chaque classe(MAD)Cherchant
mads = {}
for n,l in enumerate(label):
if l not in mads.keys():
mads[l] = []
mads[l].append(np.abs(out[n] - med_uniq[l]))
mad_uniq = {} #Le MAD réel de chaque classe entre dans cette variable
for l in label_uniq:
mad_uniq[l] = np.median(mads[l])
#Normaliser les valeurs aberrantes de chaque donnée avec la valeur médiane, MAD
outlier = [0] * N
for n,l in enumerate(label):
if mad_uniq[l] == 0.0:
outlier[n] = out[n] - med_uniq[l]
else:
outlier[n] = (out[n] - med_uniq[l]) / mad_uniq[l]
return outlier
if __name__ == '__main__':
iris = load_iris()
X = iris.data
y = iris.target
div = 50
best_oob = len(y)
for i in range(20):
rf = RandomForestClassifier(max_depth=5,n_estimators=10,oob_score=True)
rf.fit(X, y)
if best_oob > rf.oob_score:
app = rf.apply(X)
prx = proximity(app)
out = outlier(prx,y)
fig = plt.figure(figsize=[7,4])
ax = fig.add_subplot(1,1,1)
ax.scatter(np.arange(div),out[:div], c="r",marker='o', label='class 0')
ax.scatter(np.arange(div,div*2),out[div:div*2], c="b",marker='^', label='class 1')
ax.scatter(np.arange(div*2,div*3),out[div*2:], c="g",marker='s', label='class 2')
ax.set_ylabel('outlier')
ax.legend(loc="best")
fig.savefig("out.png ")
Recommended Posts