[PYTHON] Identifizieren Sie Ausreißer mit dem Random Forest Classifier von scikit-learn

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.

Screenshot from 2017-01-22 21-28-40.png

Über den Code

Um den Abweichungswert zu ermitteln, muss zunächst der Grad der Nähe der einzelnen Daten ermittelt werden.

Berechnung des Approximationsgrades

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

Berechnung von Ausreißern

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.

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

Stichprobe

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.

out.png

Code

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 ")
  

Referenz

Recommended Posts

Identifizieren Sie Ausreißer mit dem Random Forest Classifier von scikit-learn
Clustering repräsentativer Schulen im Sommer 2016 mit Scikit-Learn
Füllen Sie fehlende Werte mit Scikit-learn impute aus
Isomap mit Scikit-lernen
DBSCAN mit Scikit-Learn
Clustering mit Scikit-Learn (1)
Clustering mit Scikit-Learn (2)
PCA mit Scikit-Learn
kmeans ++ mit scikit-learn
Kreuzvalidierung mit Scikit-Learn
Mehrklassen-SVM mit Scikit-Learn
Clustering mit scikit-learn + DBSCAN
Scikit-Lernen mit Chemoinfomatik
Füllen Sie Ausreißer mit NaN basierend auf Quadranten in Pandas
DBSCAN (Clustering) mit Scikit-Learn
(Fortsetzung) Probieren Sie andere Entfernungsfunktionen mit kmeans in Scikit-learn aus
Installieren Sie scikit.learn mit pip
Berechnen Sie tf-idf mit scikit-learn
Betreiben Sie LibreOffice mit Python
Schaben mit Chromedriver in Python
Neuronales Netzwerk mit Python (Scikit-Learn)
Umgang mit Sounds in Python
Scraping mit Selen in Python
Parallele Verarbeitung mit Parallel von Scikit-Learn
Scraping mit Tor in Python
Tweet mit Bild in Python
Kombiniert mit Ordnungszahl in Python
[Python] Lineare Regression mit Scicit-Learn
Robuste lineare Regression mit Scikit-Learn