Praxiseinstieg Machine Learning mit Scikit-Learn, Keras und TensorFlow. Aurélien Géron

Praxiseinstieg Machine Learning mit Scikit-Learn, Keras und TensorFlow - Aurélien Géron


Скачать книгу

      plt.matshow(norm_conf_mx, cmap=plt.cm.gray)

      plt.show()

image

      Nun sehen Sie deutlich, welche Arten von Fehler der Klassifikator begeht. Wie gesagt, die Zeilen stehen für die tatsächlichen Kategorien und die Spalten für die vorhergesagten. Die Spalte der Kategorie 8 ist recht hell, es wurden also recht viele Bilder fälschlicherweise als 8 zugeordnet. Aber die Zeile für Kategorie 8 ist gar nicht so schlecht, was Ihnen zeigt, dass echte 8er im Allgemeinen korrekt als 8er klassifiziert werden. Wie Sie sehen, muss die Konfusionsmatrix nicht notwendigerweise symmetrisch sein. Sie können auch erkennen, dass 3er und 5er häufig verwechselt werden (in beide Richtungen).

      Eine Analyse der Konfusionsmatrix gibt Ihnen häufig Aufschluss darüber, wie sich Ihr Klassifikator verbessern lässt. Aus diesem Diagramm sehen Sie, dass sich Ihre Mühe auf das Verbessern der Klassifikation der falschen 8er konzentrieren sollte. Sie könnten also beispielsweise versuchen, zusätzliche Trainingsdaten für Ziffern zu sammeln, die wie 8er aussehen (es aber nicht sind), sodass der Klassifikator lernen kann, sie von den echten 8ern zu unterscheiden. Oder Sie probieren, neue Merkmale ermitteln, die dem Klassifikator helfen können – beispielsweise ein Algorithmus, der die geschlossenen Schleifen zählt (eine 8 hat zwei, eine 6 hat eine, eine 5 keine). Oder Sie könnten die Bilder vorverarbeiten (z.B. mit Scikit-Image, Pillow oder OpenCV), um vorhandene Muster wie die Schleifen besser hervorzuheben.

      Das Analysieren einzelner Fehler hilft auch dabei, zu erkennen, was Ihr Klassifikator eigentlich tut und warum er scheitert. Dies ist aber schwieriger und zeitlich aufwendiger. Wir könnten etwa Beispiele von 3en und 5en plotten:

      cl_a, cl_b = 3, 5

      X_aa = X_train[(y_train == cl_a) & (y_train_pred == cl_a)]

      X_ab = X_train[(y_train == cl_a) & (y_train_pred == cl_b)]

      X_ba = X_train[(y_train == cl_b) & (y_train_pred == cl_a)]

      X_bb = X_train[(y_train == cl_b) & (y_train_pred == cl_b)]

      plt.figure(figsize=(8,8))

      plt.subplot(221); plot_digits(X_aa[:25], images_per_row=5)

      plt.subplot(222); plot_digits(X_ab[:25], images_per_row=5)

      plt.subplot(223); plot_digits(X_ba[:25], images_per_row=5)

      plt.subplot(224); plot_digits(X_bb[:25], images_per_row=5)

      plt.show()

      Die zwei 5 × 5-Blöcke auf der linken Seite zeigen als 3en klassifizierte Ziffern, und die zwei 5 × 5-Blöcke auf der rechten Seite zeigen als 5en klassifizierte Ziffern. Einige der falsch zugeordneten Ziffern (z.B. in den Blöcken links unten und rechts oben) sind so unleserlich, dass sogar ein Mensch bei der Zuordnung Schwierigkeiten hätte (z.B. sieht die 5 in der ersten Zeile und zweiten Spalte wirklich wie eine schlecht geschriebene 3 aus). Es ist schwer nachzuvollziehen, warum der Klassifikator diese Fehler gemacht hat.3 Der Grund ist, dass wir einen einfachen SGDClas sifier verwendet haben, ein lineares Modell. Dieses ordnet in jeder Kategorie ein Gewicht pro Pixel zu und zählt bei einem neuen Bild einfach nur die gewichteten Intensitäten der Pixel zusammen, um einen Score für jede Kategorie zu berechnen. Da sich die 3en und 5en nur um einige Pixel unterscheiden, kommt das Modell bei diesen Ziffern leicht durcheinander.

image

      Der Hauptunterschied zwischen 3en und 5en ist die Stellung der kurzen Linie, die die obere Linie mit dem unteren Bogen verbindet. Wenn Sie eine 3 zeichnen und diese Verbindungslinie ein Stück weiter links platzieren, könnte der Klassifikator das Bild leicht für eine 5 halten und umgekehrt. Anders gesagt, reagiert unser Klassifikator sehr sensibel auf Verschiebungen und Rotationen des Bilds. Ein Möglichkeit, der Verwechslung von 3 und 5 entgegenzuwirken, wäre daher, die Bilder so vorzuverarbeiten, dass sie alle zentriert und wenig gedreht sind. Vermutlich ließen sich auf diese Weise auch weitere Fehler vermeiden.

       Klassifikation mit mehreren Labels

      Bisher wurde jeder Datenpunkt stets genau einer Kategorie zugeordnet. In einigen Fällen kann es sein, dass Sie Ihren Klassifikator mehrere Kategorien für jeden Datenpunkt ausgeben lassen möchten. Betrachten Sie beispielsweise einen Klassifikator zur Gesichtserkennung: Was sollte dieser tun, wenn er mehrere Personen im gleichen Bild findet? Natürlich sollte er jeder erkannten Person ein Tag zuordnen. Sagen wir einmal, der Klassifikator sei auf drei Gesichtern trainiert worden: Alice, Bob und Charlie. Wenn er anschließend ein Bild von Alice und Bob gezeigt bekommt, sollte er [1, 0, 1] ausgeben (was bedeutet: »Alice ja, Bob nein, Charlie ja«). Solch einen Klassifikator, der mehrere binäre Tags ausgibt, nennt man ein Klassifikationssystem mit mehreren Labels.

      Wir beschäftigen uns an dieser Stelle noch nicht mit Gesichtserkennung. Stattdessen betrachten wir zur Veranschaulichung ein einfacheres Beispiel:

      from sklearn.neighbors import KNeighborsClassifier

      y_train_large = (y_train >= 7)

      y_train_odd = (y_train % 2 == 1)

      y_multilabel = np.c_[y_train_large, y_train_odd]

      knn_clf = KNeighborsClassifier()

      knn_clf.fit(X_train, y_multilabel)

      Dieses Codebeispiel erstellt das Array y_multilabel mit zwei Labels als Ziel für jedes Ziffernbild: Das erste besagt, ob die Ziffer groß ist (7, 8 oder 9), und das zweite, ob sie ungerade ist. Die folgenden Zeilen erstellen eine Instanz von KNeighborsClassifier (diese unterstützt die Klassifikation mehrerer Labels, was nicht alle Klassifikatoren tun). Wir trainieren diesen mit dem Array mit mehreren Zielwerten. Nun können Sie eine Vorhersage vornehmen und bemerken, dass zwei Labels ausgegeben werden:

      >>> knn_clf.predict([some_digit])

      array([[False, True]])

      Und das Ergebnis ist richtig! Die Ziffer 5 ist tatsächlich nicht groß (False) und ungerade (True).

      Es gibt viele Möglichkeiten, einen Klassifikator mit mehreren Labels auszuwerten, und die Wahl der richtigen Metrik hängt von Ihrem Projekt ab. Ein Ansatz ist beispielsweise, den F1-Score für jedes Label einzeln zu bestimmen (oder eine andere der oben besprochenen binären Klassifikationsmetriken) und anschließend einfach deren Mittelwert zu berechnen. Der folgende Code berechnet den mittleren F1-Score über sämtliche Labels:

      >>> y_train_knn_pred = cross_val_predict(knn_clf, X_train, y_multilabel, cv=3)

      >>> f1_score(y_multilabel, y_train_knn_pred, average="macro")

      0.976410265560605

      Dabei nehmen wir an, dass alle Labels gleich wichtig sind, was nicht der Fall sein muss. Wenn Sie zum Beispiel viel mehr Bilder von Alice als von Bob oder Charlie haben, sollten Sie dem Score eines Klassifikators bei Alice ein höheres Gewicht verleihen. Eine einfache Möglichkeit ist dabei, jedem Label ein Gewicht entsprechend der Anzahl Datenpunkte mit diesem Label (dem Support) zu verleihen. Um das zu erreichen, setzen Sie im obigen Codebeispiel average="weighted".4

       Klassifikation mit mehreren Ausgaben

      Die letzte Art hier betrachteter Klassifikationsaufgaben nennt man Klassifikation mit mehreren Kategorien und mehreren Ausgaben (oder einfach Klassifikation mit mehreren Ausgaben). Sie ist eine Verallgemeinerung der Klassifikation mit mehreren Labels, wobei jedes Label mehrere Kategorien beinhalten kann (also mehr als zwei mögliche Werte haben kann).

      Um dies zu veranschaulichen, erstellen wir ein System, das Rauschen aus Bildern entfernt. Als Eingabe erhält es ein verrauschtes Bild einer Ziffer und wird (hoffentlich) ein sauberes Bild einer Ziffer


Скачать книгу