[PYTHON] Erkennung abnormaler Werte durch unbeaufsichtigtes Lernen: Maharanobis-Distanz (Implementierung)

Übrigens, als Fortsetzung der vorherigen Theorie werde ich dieses Mal tatsächlich Maharanobis Distanz mit Python implementieren. Klicken Sie hier für die vorherige Theorie Erkennung abnormaler Werte durch unbeaufsichtigtes Lernen: Maharanobis-Abstand (Theorie)

Einführung

Die Scikit-Learn-Bibliothek von Python implementiert eine Funktion, die die Maharanobis-Entfernung berechnet. Robust covariance estimation and Mahalanobis distances relevance

Selbst wenn ich einen Artikel schreibe, in dem steht "Ich werde diesen Code ausführen!", Handelt es sich nur um eine englische Übersetzung. Dieses Mal werde ich es selbst implementieren und sehen, wie der Berechnungsprozess im Programm abläuft.

Nachdem Sie alle Codes verbunden haben, besteht das Ziel darin, die Entfernung selbst berechnen zu können.

Umgebung

Nehmen Sie außerdem an, dass die in diesem Experiment behandelte Datei das folgende Format hat. Angenommen, Spalte ist die Maschinennummer und Zeile ist die Maschinenbewertung. (Es scheint, dass Ichamon in die entgegengesetzte Richtung fliegen wird, aber natürlich ist das Gegenteil kein Problem.)

test.csv

1 2 3 4 5 6 7 8 9 10
a 0 6 7 2 3 3 1 0 0 1
b 1 1 11 6 0 2 1 4 1 2
c 2 12 32 5 0 1 3 4 1 1
d 3 3 7 3 2 2 2 1 2 5
e 4 6 6 3 5 1 1 1 1 3
f 5 7 9 5 0 2 2 1 1 2

Bei diesem Format scheint die Punktzahl nur für die dritte Maschinennummer extrem hoch zu sein.

Mit der Maharanobis-Entfernung können Sie selbst einen bestimmten Schwellenwert festlegen und einen Datensatz mit einem Wert, der den Schwellenwert überschreitet, als abnormalen Wert beurteilen. Beachten Sie, dass Sie den -Schwellenwert jedes Mal selbst festlegen müssen. </ b> Dieses Mal werden wir abnormale Daten </ b> visualisieren, indem wir sie als Grafik anzeigen, ohne auf dieser Seite einen Schwellenwert festzulegen.

Implementierung

import Die zu importierende Funktion lautet wie folgt.

  • numpy
  • scipy
  • pandas
  • matplotlib
  • pylab

Diese Installationsverfahren werden diesmal weggelassen. Grundsätzlich ist es für die Installation besser, pip oder easy_install zu verwenden.

# -*- coding: utf-8 -*-
import numpy as np
import scipy as sc
from scipy import linalg
from scipy import spatial
import scipy.spatial.distance
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.font_manager
import pylab

Variablendefinition

Dieses Mal gibt es 6 Zeilen für ROW und 10 Zeilen für COLUMN. Definieren Sie Folgendes. Lesen Sie auch dies, da die zuvor erwähnte test.csv gelesen wird.

ROW = 10
COLUMN = 6
csv = pd.read_csv('test.csv')

Gleichzeitig werden hier auch zuerst die Variablen definiert, die in Zukunft behandelt werden sollen.

# row:Linie,column:Säule,ave:durchschnittlich,vcm:分散共分散LinieSäule
row = []
column = []
ave = [0.0 for i in range(ROW)]
vcm = np.zeros((COLUMN, ROW, ROW))
diff = np.zeros((1, ROW))
mahal = np.zeros(COLUMN)
tmp = np.zeros(ROW)

Fehlende Werte löschen

Im Allgemeinen gibt es nicht viele Fälle, in denen alle Daten wie folgt "test.csv" aufgefüllt werden. In einem solchen Fall lösche ich den fehlenden Wert wie folgt.

#Fehlende Daten löschen
# axis =1 löscht Spalten mit fehlenden Werten
trans_data = csv.dropna(axis=1)
print(trans_data)

Wenn Sie dies drucken,

  Unnamed: 0  1   2   3  4  5  6  7  8  9  10
0          a  0   6   7  2  3  3  1  0  0   1
1          b  1   1  11  6  0  2  1  4  1   2
2          c  2  12  32  5  0  1  3  4  1   1
3          d  3   3   7  3  2  2  2  1  2   5
4          e  4   6   6  3  5  1  1  1  1   3
5          f  5   7   9  5  0  2  2  1  1   2

Es wird so ausgegeben.

Außerdem werden die auf diese Weise formatierten Daten in ein Listenformat konvertiert und in der zuvor deklarierten Zeile und Spalte gespeichert.

#trans zu rudern_Verketten Sie Datenelemente im Listenformat
for i in range(ROW):
    row.append(list(trans_data.ix[i]))
print(row)

#Spalten verketten
for i in range(1, COLUMN+1):
    column.append(list(trans_data.ix[:, i]))
print(column)
#Ergebnis der Zeilenberechnung

[['a', 0, 6, 7, 2, 3, 3, 1, 0, 0, 1], ['b', 1, 1, 11, 6, 0, 2, 1, 4, 1, 2], ['c', 2, 12, 32, 5, 0, 1, 3, 4, 1, 1], ['d', 3, 3, 7, 3, 2, 2, 2, 1, 2, 5], ['e', 4, 6, 6, 3, 5, 1, 1, 1, 1, 3], ['f', 5, 7, 9, 5, 0, 2, 2, 1, 1, 2]]

#Ergebnis der Spaltenberechnung
[[0, 1, 2, 3, 4, 5], [6, 1, 12, 3, 6, 7], [7, 11, 32, 7, 6, 9], [2, 6, 5, 3, 3, 5], [3, 0, 0, 2, 5, 0], [3, 2, 1, 2, 1, 2], [1, 1, 3, 2, 1, 2], [0, 4, 4, 1, 1, 1], [0, 1, 1, 2, 1, 1], [1, 2, 1, 5, 3, 2]]

Es stellte sich heraus, dass es Zeile für Zeile als mehrdimensionales Array gespeichert wird.

Berechnung des Mittelwertvektors

Ich erklärte, dass der Durchschnittswertvektor durch die folgende Formel ausgedrückt werden kann.

{ 
  μ = \frac{1}{m} \sum_{i=1}^m x_i
}

Wenn dies tatsächlich in Python geschrieben ist, wird es wie folgt sein.

#Berechnung des Durchschnittswertes
for i in range(ROW):
    #Eine Technik namens Schneiden
    ave[i] = np.average(row[i][1:len(row[i])])
print(ave)
  Unnamed: 0  1   2   3  4  5  6  7  8  9  10
0          a  0   6   7  2  3  3  1  0  0   1
1          b  1   1  11  6  0  2  1  4  1   2
2          c  2  12  32  5  0  1  3  4  1   1
3          d  3   3   7  3  2  2  2  1  2   5
4          e  4   6   6  3  5  1  1  1  1   3
5          f  5   7   9  5  0  2  2  1  1   2
[2.2999999999999998, 2.8999999999999999, 6.0999999999999996, 3.0, 3.1000000000000001, 3.3999999999999999]

Für die Zeile werden numerische Werte angezeigt, z. B. der Durchschnitt der Werte in Zeile a und der Durchschnitt der Werte in Zeile b.

Berechnung der verteilten co-verteilten Matrix

Wie ich im vorherigen Artikel erwähnt habe, ist auch die Verteilungs-Co-Verteilungsmatrix

\sum_{} = \frac{1}{m}\sum_{i=1}^m (x_i - μ)(x_i - μ)^{\mathrm{T}}

Es kann auf diese Weise berechnet werden.

#Da es Numpys Methode verwendet, Array()Konvertierte die Liste mit.
column = np.array([column])
ave = np.array(ave)

#Suchen Sie die verteilte, gemeinsam verteilte Matrix
# np.swapaxes()Sie können die Achse mit konvertieren.
for i in range(COLUMN):
    diff = (column[0][i] - ave)
    diff = np.array([diff])
    vcm[i] = (diff * np.swapaxes(diff, 0, 1)) / COLUMN

print(vcm)

Der Diff-Teil ist der Unterschied und mathematisch

 {(x_i - μ)}

Es zeigt auf diesen Teil. Berechnen Sie diese Differenz für jede Spalte und finden Sie die Matrix für jede Spalte.

  Unnamed: 0  1   2   3  4  5  6  7  8  9  10
0          a  0   6   7  2  3  3  1  0  0   1
1          b  1   1  11  6  0  2  1  4  1   2
2          c  2  12  32  5  0  1  3  4  1   1
3          d  3   3   7  3  2  2  2  1  2   5
4          e  4   6   6  3  5  1  1  1  1   3
5          f  5   7   9  5  0  2  2  1  1   2
#vcm Spalte 1. Spaltenmatrix
[[[  5.29000000e-01   4.37000000e-01   9.43000000e-01  -0.00000000e+00
    -2.07000000e-01  -3.68000000e-01]
  [  4.37000000e-01   3.61000000e-01   7.79000000e-01  -0.00000000e+00
    -1.71000000e-01  -3.04000000e-01]
  [  9.43000000e-01   7.79000000e-01   1.68100000e+00  -0.00000000e+00
    -3.69000000e-01  -6.56000000e-01]
  [ -0.00000000e+00  -0.00000000e+00  -0.00000000e+00   0.00000000e+00
     0.00000000e+00   0.00000000e+00]
  [ -2.07000000e-01  -1.71000000e-01  -3.69000000e-01   0.00000000e+00
     8.10000000e-02   1.44000000e-01]
  [ -3.68000000e-01  -3.04000000e-01  -6.56000000e-01   0.00000000e+00
     1.44000000e-01   2.56000000e-01]]

#vcm zweite Reihe
 [[  1.36900000e+00  -7.03000000e-01   2.18300000e+00   0.00000000e+00
     1.07300000e+00   1.33200000e+00]
  [ -7.03000000e-01   3.61000000e-01  -1.12100000e+00  -0.00000000e+00
    -5.51000000e-01  -6.84000000e-01]
  [  2.18300000e+00  -1.12100000e+00   3.48100000e+00   0.00000000e+00
     1.71100000e+00   2.12400000e+00]
  [  0.00000000e+00  -0.00000000e+00   0.00000000e+00   0.00000000e+00
     0.00000000e+00   0.00000000e+00]
  [  1.07300000e+00  -5.51000000e-01   1.71100000e+00   0.00000000e+00
     8.41000000e-01   1.04400000e+00]
  [  1.33200000e+00  -6.84000000e-01   2.12400000e+00   0.00000000e+00
     1.04400000e+00   1.29600000e+00]]

…

#vcm 10. Reihe
[[  1.69000000e-01   1.17000000e-01   6.63000000e-01  -2.60000000e-01
     1.30000000e-02   1.82000000e-01]
  [  1.17000000e-01   8.10000000e-02   4.59000000e-01  -1.80000000e-01
     9.00000000e-03   1.26000000e-01]
  [  6.63000000e-01   4.59000000e-01   2.60100000e+00  -1.02000000e+00
     5.10000000e-02   7.14000000e-01]
  [ -2.60000000e-01  -1.80000000e-01  -1.02000000e+00   4.00000000e-01
    -2.00000000e-02  -2.80000000e-01]
  [  1.30000000e-02   9.00000000e-03   5.10000000e-02  -2.00000000e-02
     1.00000000e-03   1.40000000e-02]
  [  1.82000000e-01   1.26000000e-01   7.14000000e-01  -2.80000000e-01
     1.40000000e-02   1.96000000e-01]]]

Finde die Maharanobis-Entfernung

Die Maharanobis-Entfernung kann mit der folgenden Formel berechnet werden.

  θ < \sqrt{(x_i - μ) ^{\mathrm{T}}\sum{}^{-1} (x_i - μ) }
#Finde Mahalanobis Entfernung
for i in range(COLUMN):
    #Generieren Sie eine allgemeine inverse Matrix und multiplizieren Sie sie zur Vereinfachung der Berechnung mit einem Wendepreis.
    vcm[i] = sc.linalg.pinv(vcm[i])
    vcm[i] = vcm[i].transpose()
    vcm[i] = np.identity(ROW)
    #Erzeugung eines Differenzvektors
    diff = (column[0][i] - ave)
    for j in range(ROW):
        tmp[j] = np.dot(diff, vcm[i][j])
    mahal[i] = np.dot(tmp, diff)
#Maharanobis Entfernung
[  5.39258751   8.5720476   28.53559181   3.67151195   7.89176786
   5.88897275   4.72016949   5.00799361   6.7882251    5.8719673 ]

Jetzt können Sie die Entfernung für jede Datensatzspalte berechnen!

Eigentlich Handlung

Zeichnen wir die auf diese Weise erhaltene Maharanobis-Entfernung in einem Diagramm.

plot = pylab.arange(0.0, ROW, 1.0)
mahal = np.sqrt(mahal)

print("Maharanobis Entfernung")
print(mahal)
plt.bar(range(COLUMN),mahal)
plt.title("")
plt.xlabel("x")
plt.ylabel("y")
plt.savefig("plot1.png ")

plot1.png

  Unnamed: 0  1   2   3  4  5  6  7  8  9  10
0          a  0   6   7  2  3  3  1  0  0   1
1          b  1   1  11  6  0  2  1  4  1   2
2          c  2  12  32  5  0  1  3  4  1   1
3          d  3   3   7  3  2  2  2  1  2   5
4          e  4   6   6  3  5  1  1  1  1   3
5          f  5   7   9  5  0  2  2  1  1   2
#Maharanobis Entfernung
[  5.39258751   8.5720476   28.53559181   3.67151195   7.89176786
   5.88897275   4.72016949   5.00799361   6.7882251    5.8719673 ]

Als ich es zeichnete, stellte ich fest, dass die Datensätze in der dritten Spalte im Vergleich zu den anderen Elementen weit voneinander entfernt waren. Jetzt können Sie sehen, dass die Daten visuell nicht in Ordnung sind.

abschließend

Was haben Sie gedacht. Dieses Mal habe ich basierend auf Theorie die Maharanobis-Entfernung tatsächlich mit Python berechnet. Das diesmal verwendete Programm wurde für GitHub gist veröffentlicht.

Da der Code vollständig implementiert wurde, liegt möglicherweise ein Fehler im Code vor. Wenn Sie also genaue Berechnungen benötigen, Robuste Kovarianzschätzung und Relevanz der Mahalanobis-Entfernungen covariance / plot_mahalanobis_distances.html) Wir empfehlen dringend, dass Sie die Bibliothek mit Bezug auf dieses Dokument verwenden.

Wir würden uns freuen, wenn Sie uns kontaktieren könnten, wenn Sie Mängel oder Fehler haben.

Recommended Posts