Mit RandomForestClassifier von scikit-learn können Sie das Klassifizierungsproblem in einer zufälligen Gesamtstruktur lösen. Als Merkmal von Random Forest ist es möglich, Ausreißerdaten zu identifizieren, deren Wert sich vom Attributwert, der die Klasse darstellt, von den Daten unterscheidet, die zu derselben Klasse gehören. Da das offizielle Scikit-Learn keine Funktion zum Berechnen von Ausreißern hat, habe ich dieses Mal ein Skript erstellt, das Ausreißer ausgibt. (Übrigens kann es mit R berechnet werden)
Um den Ausreißer zu finden, verwenden Sie apply in der RandomForestClassifier-Methode von scicit-learn. Dies ist eine Methode, die den Blattindex zurückgibt, in welchem Blatt die einzelnen Daten enthalten sind, wenn die Eingabedaten des Stapels an jeden vom zufälligen Gesamtstrukturalgorithmus erstellten Entscheidungsbaum übergeben werden.
Um den Abweichungswert zu ermitteln, muss zunächst der Grad der Nähe der einzelnen Daten ermittelt werden.
Der Grad der Nähe der einzelnen Daten wird anhand des von der Methode apply als Argument zurückgegebenen Arrays berechnet. Die Methode apply gibt ein zweidimensionales Array von [Anzahl der Stichproben, Anzahl der Entscheidungsbäume] zurück.
In der Nähe werden die Daten $ x_ {k} $ gezählt, die im selben Blatt wie die Daten $ x_ {n} $ enthalten sind, und die Summe wird berechnet, indem sie für alle Bestimmungsbäume ausgeführt wird, die sie erstellt haben. Schließlich wird das Ergebnis durch die Anzahl der Entscheidungsbäume geteilt und normalisiert, um den Approximationsgrad der Daten $ x_ {n} $ zu erhalten. Das Endergebnis wird als zweidimensionales Array von [Anzahl der Proben, Anzahl der Proben] zurückgegeben. (Das Array ist übrigens eine Diagonalmatrix)
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
Nachdem Sie den Grad der Annäherung gefunden haben, suchen Sie den Ausreißer. Um die Ausreißer in derselben Klasse zu berechnen, nehmen Sie ein Array korrekter Beschriftungen als Argument. Der Verarbeitungsablauf ist wie folgt.
Berechnen Sie den Durchschnittswert des Grads der Nähe in der Klasse
Berechnen Sie die Ausreißer der einzelnen Daten
Berechnen Sie den Medianwert und die mediane absolute Abweichung (MAD) der Ausreißer jeder Klasse
Normalisieren Sie die Ausreißer der einzelnen Daten mit dem Median und dem Median der absoluten Abweichungen
Dies ist alles, was Sie tun müssen, und Sie können es einfach mit numpy schreiben. Wenn die for-Anweisung ebenfalls enthalten ist, kann die Geschwindigkeit erhöht werden.
Verwenden Sie XGBoost auch mit XGBoosts Scikit-Learn-Wrapper. Es ist auch möglich, die Ausreißer anzugeben.
Übrigens werden bei der Normalisierung von Ausreißern der Medianwert und MAD anstelle des Mittelwerts und der Standardabweichung verwendet, da die Statistiken (robust) von den Ausreißern nicht leicht beeinflusst werden.
def outlier(data, label):
N = len(label)
pbar = [0] * N
data = np.square(data)
#Finden Sie den Durchschnittswert des Grads der Nähe in der Klasse
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
#Finde den Ausreißer
out = N / np.array(pbar)
#Finden Sie die mittleren Ausreißer für jede Klasse
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 = {} #Der tatsächliche Median jeder Klasse geht in diese Variable
for l in label_uniq:
med_uniq[l] = np.median(meds[l])
#Zentrale absolute Abweichung der Ausreißer für jede Klasse(MAD)Ich suche
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 = {} #Der tatsächliche MAD jeder Klasse geht in diese Variable
for l in label_uniq:
mad_uniq[l] = np.median(mads[l])
#Normalisieren Sie die Ausreißer der einzelnen Daten mit dem Medianwert 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
Mit der obigen Funktion habe ich versucht, den Ausreißer der Iris in den Beispieldaten von sklearn zu identifizieren. Der Beispielcode zur Ausgabe des Bildes dieses Ergebnisses ist unten dargestellt.
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)
#Finden Sie den Durchschnittswert des Grads der Nähe in der Klasse
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
#Finde den Ausreißer
out = N / np.array(pbar)
#Finden Sie die mittleren Ausreißer für jede Klasse
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 = {} #Der tatsächliche Median jeder Klasse geht in diese Variable
for l in label_uniq:
med_uniq[l] = np.median(meds[l])
#Zentrale absolute Abweichung der Ausreißer für jede Klasse(MAD)Ich suche
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 = {} #Der tatsächliche MAD jeder Klasse geht in diese Variable
for l in label_uniq:
mad_uniq[l] = np.median(mads[l])
#Normalisieren Sie die Ausreißer der einzelnen Daten mit dem Medianwert 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