[PYTHON] Wenn Sie mit der Maus über Matplotlib fahren, wird das entsprechende Bild angezeigt.

Zusammenfassung

Ich habe das getan.

Ein Beispiel ist ein Streudiagramm von MNIST, dessen Dimension durch t-SNE reduziert wurde. Wenn Sie den Mauszeiger über ein Diagramm bewegen, wird die diesem Diagramm entsprechende Abbildung angezeigt.

Figure-1-2020-01-24-21-54-54_Trim.gif

Umgebung

Zunächst die t-SNE-Verarbeitung

Dieser Artikel befasst sich mit der Verwendung von matplotlib. Die Erklärung von MNIST und t-SNE entfällt.

Welche Art von Variablennamen und wie er erstellt wurde, hängt jedoch vom Programm ab. Daher werde ich den Code dort veröffentlichen.

import numpy as np
from sklearn.datasets import fetch_openml
from sklearn.manifold import TSNE

width = 28
nskip = 35

mnist = fetch_openml("mnist_784", version=1)
mnist_img = mnist["data"][::nskip, :]
mnist_label = mnist["target"][::nskip]
mnist_int = np.asarray(mnist_label, dtype=int)

x_embedded = TSNE(n_components=2).fit_transform(mnist_img)

width ist die Breite des Bildes. nskip ist (die Umkehrung von) der Lotteriewahrscheinlichkeit der Probe. Die Stichprobengröße beträgt derzeit 70.000, was für das Plotten zu viel ist. Stellen Sie sie daher auf 1/35 ein und verwenden Sie 2000 Stichproben.

Details anderer Sequenzen sind wie folgt.

Gewöhnliche Handlung

Wahrscheinlich die zweitkomplizierteste Handlung.

    plt.xlim(x_embedded[:, 0].min(), x_embedded[:, 0].max())
    plt.ylim(x_embedded[:, 1].min(), x_embedded[:, 1].max())
    for x, label in zip(x_embedded, mnist_label):
        plt.text(x[0], x[1], label)
    plt.xlabel("component 0")
    plt.ylabel("component 1")
    plt.show()

コメント 2020-01-24 224601.png

Die Idee, Zahlen zu zeichnen https://qiita.com/stfate/items/8988d01aad9596f9d586 Beruhte auf.

Der Bereich der x- und y-Achsen, der mithilfe von "Streuung" automatisch angepasst werden kann, passt "xlim" und "ylim" aufgrund der Methode zum Platzieren von "Text" an jedem Punkt an. Muss sein. Sie sehen jedoch auf einen Blick, dass für jede Zahl Gruppen gebildet werden und manchmal andere Zahlen wie Rauschen gemischt werden.

Schau dir das an

Ich dachte. Lassen Sie uns also zuerst die Beschriftung mit der Maus anzeigen.

Anmerkungsanzeige mit der Maus darüber

Dies fand die Antwort in Stackoverflow.

https://stackoverflow.com/questions/7908636/possible-to-make-labels-appear-when-hovering-over-a-point-in-matplotlib

Ändern Sie diesen Code für diesen MNIST.

    fig, ax = plt.subplots()
    cmap = plt.cm.RdYlGn

    sc = plt.scatter(x_embedded[:, 0], x_embedded[:, 1], c=mnist_int/10.0, cmap=cmap, s=3)
    annot = ax.annotate("", xy=(0,0), xytext=(20,20),textcoords="offset points",
                    bbox=dict(boxstyle="round", fc="w"),
                    arrowprops=dict(arrowstyle="->"))
    annot.set_visible(False)
    def update_annot(ind):
        i = ind["ind"][0]
        pos = sc.get_offsets()[i]
        annot.xy = pos
        text = mnist_label[i]
        annot.set_text(text)
        annot.get_bbox_patch().set_facecolor(cmap(int(text)/10))

    def hover(event):
        vis = annot.get_visible()
        if event.inaxes == ax:
            cont, ind = sc.contains(event)
            if cont:
                update_annot(ind)
                annot.set_visible(True)
                fig.canvas.draw_idle()
            else:
                if vis:
                   annot.set_visible(False)
                   fig.canvas.draw_idle()

    fig.canvas.mpl_connect("motion_notify_event", hover)

    plt.show()

Figure-1-2020-01-24-22-33-54_Trim.gif

Nun, es wird ein allgemeines Ereignis in der GUI verwendet. Erstellen Sie zuerst ein leeres "Annotation" -Objekt "Annot" und erstellen Sie dann eine Funktion "update_annot", die seine Position, ihren Inhalt usw. aktualisiert. Registrieren Sie die Funktion "Schweben" als "fig.canvas.mpl_connect (" motion_notify_event ", hover)" und rufen Sie "update_annot" auf, während Sie "annot" anzeigen, wenn der Cursor auf einen Punkt im "Schwebeflug" zeigt. Verstecke "Annot", wenn es nicht auf einen Punkt zeigt.

Um die Farbe auf "c = mnist_int / 10.0" in "Scatter" zu setzen, habe ich ein "mnist_int" -Array mit einer Ganzzahlbezeichnung vorbereitet.

Jetzt können Sie ein interaktives Streudiagramm wie im obigen Video zeichnen.

Ich habe diesmal übersprungen, aber ich denke, es wäre freundlicher, irgendwo eine Legende von Farben und Zahlen anzuzeigen.

Dadurch wurde ich unzufriedener.

"Wie speziell sieht ein verrauschter Punkt aus, zum Beispiel 7 in einem Cluster von 1s? Vielleicht macht der Algorithmus einen normalen Punkt verrauscht, also nur die Beschriftung Ich möchte auch die Rohdaten überprüfen. "

Um dies zu realisieren, scheint es gut, das Originalbild mit der Maus darüber anzuzeigen.

Bildanzeige mit der Maus über

Es gab offiziell eine Demo, um Bilder mit Anmerkungen anzuzeigen.

https://matplotlib.org/3.1.0/gallery/text_labels_and_annotations/demo_annotation_box.html

Kombinieren Sie dies mit der zuvor erwähnten Event-Registrierung.

Erstens, da die Anmerkung nur Text früher war, war "Anmerkung" in Ordnung, aber wenn es um Bilder geht, ist es ein bisschen mühsam,

Eine zweistufige Operation ist erforderlich. Importieren Sie zunächst die gewünschte Klasse.

from matplotlib.offsetbox import OffsetImage, AnnotationBbox

Vorbereitung der notwendigen Grafikobjekte.

    fig, ax = plt.subplots()
    cmap = plt.cm.RdYlGn

Bereiten Sie danach "OffsetImage" vor, aber verwenden Sie zu diesem Zeitpunkt das 0. Bild als Dummy-Bild.

    img = mnist_img[0, :].reshape((width, width))
    imagebox = OffsetImage(img, zoom=1.0)
    imagebox.image.axes = ax

Erstellen Sie darauf basierend eine "Annotation Bbox".

    annot = AnnotationBbox(imagebox, xy=(0,0), xybox=(width,width),
                        xycoords="data", boxcoords="offset points", pad=0.5,
                        arrowprops=dict( arrowstyle="->", connectionstyle="arc3,rad=-0.3"))
    annot.set_visible(False)
    ax.add_artist(annot)

Beachten Sie, dass "xybox" nicht die Größe von "annot" angibt, sondern die Position relativ zum Annotationspunkt "xy".

Als nächstes werden die Diagramme und Bilder aktualisiert.

    sc = plt.scatter(x_embedded[:, 0], x_embedded[:, 1], c=mnist_int/10.0, cmap=cmap, s=3)

    def update_annot(ind):
        i = ind["ind"][0]
        pos = sc.get_offsets()[i]
        annot.xy = (pos[0], pos[1])
        img = mnist_img[i, :].reshape((width, width))
        imagebox.set_data(img)

Ich aktualisiere die neuen Bilddaten für "imagebox", aber es scheint, dass der Aktualisierungsprozess für "annot" nicht erforderlich ist.

Da ich separat experimentiert habe, reagiert es auch dynamisch, selbst wenn sich die Größe von "img" ändert. Ich denke, es gibt einen Prozess, um es separat hinzuzufügen, selbst wenn es verschiedene Größen gibt.

Der Rest der Eventregistrierung ist der gleiche.

    def hover(event):
        vis = annot.get_visible()
        if event.inaxes == ax:
            cont, ind = sc.contains(event)
            if cont:
                update_annot(ind)
                annot.set_visible(True)
                fig.canvas.draw_idle()
            else:
                if vis:
                    annot.set_visible(False)
                    fig.canvas.draw_idle()

    fig.canvas.mpl_connect("motion_notify_event", hover)

    plt.show()

Figure-1-2020-01-24-21-54-54_Trim.gif

Es tut mir leid, dass es nur für einen Moment angezeigt wird, aber ich habe festgestellt, dass die Form des Rauschens sicherlich nahe an einer anderen Zahl liegt und wahrscheinlich falsch verstanden wird.

das Ende

Nun, es ist eine bedeutungslose Technik, die mit der Bildausgabe zu tun hat, aber ich denke, sie kann während des Versuchs und Irrtums recht gut verwendet werden.

In diesem Vortrag erfuhr ich von der Existenz der abstrakten Stammklasse "Artist", die Objekte in matplotlib beschreibt.

Bonuscode als Ganzes

Ändern Sie den Teil des Diagramms, den Sie anzeigen möchten, von "if False:" in "if True:". Wir haben den Vorgang nicht bestätigt, wenn mehrere auf "True" gesetzt sind.

Klicken Sie hier, um
zu erweitern / zu falten
import numpy as np
from sklearn.datasets import fetch_openml
from sklearn.manifold import TSNE
import matplotlib.pyplot as plt
from matplotlib.offsetbox import OffsetImage, AnnotationBbox

width = 28
nskip = 35

mnist = fetch_openml("mnist_784", version=1)
mnist_img = mnist["data"][::nskip, :]
mnist_label = mnist["target"][::nskip]
mnist_int = np.asarray(mnist_label, dtype=int)
print(type(mnist_img))
print(mnist_img.max())
print(mnist_img.dtype)
exit()

x_embedded = TSNE(n_components=2).fit_transform(mnist_img)

if True: 
    plt.xlim(x_embedded[:, 0].min(), x_embedded[:, 0].max())
    plt.ylim(x_embedded[:, 1].min(), x_embedded[:, 1].max())
    for x, label in zip(x_embedded, mnist_label):
        plt.text(x[0], x[1], label)
    plt.xlabel("component 0")
    plt.ylabel("component 1")
    plt.show()
    exit()


fig, ax = plt.subplots()
cmap = plt.cm.RdYlGn

if False: 
    sc = plt.scatter(x_embedded[:, 0], x_embedded[:, 1], c=mnist_int/10.0, cmap=cmap, s=3)
    annot = ax.annotate("", xy=(0,0), xytext=(20,20),textcoords="offset points",
                    bbox=dict(boxstyle="round", fc="w"),
                    arrowprops=dict(arrowstyle="->"))
    annot.set_visible(False)
    def update_annot(ind):
        i = ind["ind"][0]
        pos = sc.get_offsets()[i]
        annot.xy = pos
        text = mnist_label[i]
        annot.set_text(text)
        annot.get_bbox_patch().set_facecolor(cmap(int(text)/10))

    def hover(event):
        vis = annot.get_visible()
        if event.inaxes == ax:
            cont, ind = sc.contains(event)
            if cont:
                update_annot(ind)
                annot.set_visible(True)
                fig.canvas.draw_idle()
            else:
                if vis:
                   annot.set_visible(False)
                   fig.canvas.draw_idle()

    fig.canvas.mpl_connect("motion_notify_event", hover)

    plt.show()

if False:
    img = mnist_img[0, :].reshape((width, width))
    imagebox = OffsetImage(img, zoom=1.0)
    imagebox.image.axes = ax

    sc = plt.scatter(x_embedded[:, 0], x_embedded[:, 1], c=mnist_int/10.0, cmap=cmap, s=3)
    annot = AnnotationBbox(imagebox, xy=(0,0), xybox=(width,width),
                        xycoords="data", boxcoords="offset points", pad=0.5,
                        arrowprops=dict( arrowstyle="->", connectionstyle="arc3,rad=-0.3"))
    annot.set_visible(False)
    ax.add_artist(annot)

    def update_annot(ind):
        i = ind["ind"][0]
        pos = sc.get_offsets()[i]
        annot.xy = (pos[0], pos[1])
        img = mnist_img[i, :].reshape((width, width))
        imagebox.set_data(img)

    def hover(event):
        vis = annot.get_visible()
        if event.inaxes == ax:
            cont, ind = sc.contains(event)
            if cont:
                update_annot(ind)
                annot.set_visible(True)
                fig.canvas.draw_idle()
            else:
                if vis:
                    annot.set_visible(False)
                    fig.canvas.draw_idle()

    fig.canvas.mpl_connect("motion_notify_event", hover)

    plt.show()

Recommended Posts

Wenn Sie mit der Maus über Matplotlib fahren, wird das entsprechende Bild angezeigt.
Wenden wir die Markenbildfarbe auf die Farbkarte von matplotlib an!
Python Open CV hat versucht, das Bild im Text anzuzeigen.
Punkt entsprechend dem Bild
Der Weg zum Herunterladen von Matplotlib
Zeigen Sie das Bild der an den PC angeschlossenen Kamera auf der GUI an.
Zwei Möglichkeiten, mit matplotlib mehrere Grafiken in einem Bild anzuzeigen
So zeigen Sie den Fortschrittsbalken an (tqdm)
So unterdrücken Sie Anzeigefehler in matplotlib
[Python] So legen Sie die Position und Größe der Fensteranzeige von matplotlib fest
Bildanzeige mit dem eingebauten ISIGHT
Bereiten Sie eine URL vor, um das von Active Storage hochgeladene Bild selbst anzuzeigen
Ich möchte den Fortschrittsbalken anzeigen
Zeigen Sie Markierungen über dem Rand mit matplotlib an
Richten Sie die Farbleiste mit matplotlib an der Figur aus
So schalten Sie die Skalenwertanzeige aus, während Sie das Raster mit matplotlib verlassen
So zeigen Sie im gesamten Fenster an, wenn Sie das Hintergrundbild mit tkinter einstellen
So weisen Sie der Matplotlib-Farbleiste mehrere Werte zu
Versuchen Sie, dem Bild die Verzerrung des Fischaugenobjektivs hinzuzufügen
Schneiden Sie das Bild mit Pythonista auf abgerundete Ecken
[Python] So ändern Sie das Datumsformat (Anzeigeformat)
Ich möchte mehrere Bilder mit matplotlib anzeigen.
Ich habe versucht, die Trapezform des Bildes zu korrigieren
So zeigen Sie Bilder kontinuierlich mit matplotlib Memo an
Ich möchte den Fortschritt in Python anzeigen!
Zeigen Sie das Bild nach der Datenerweiterung mit Pytorch an
Zeigen Sie das 邊 an
Laden Sie das durch Anfragen heruntergeladene Bild direkt in S3 hoch
Ich habe versucht, Iris aus dem Kamerabild zu erkennen
Fügen Sie mit Matplotlib Informationen am unteren Rand der Abbildung hinzu
[Python] Geben Sie den Bereich des Bildes durch Ziehen der Maus an
Speichern Sie das von pyqtgraph gezeichnete Diagramm in einem Bild
Konvertieren Sie das Bild in .zip mit Python in PDF
So entfernen Sie verstümmelte Zeichen im Matplotlib-Ausgabebild
Verbinden Sie die Maus mit dem Kreisel des Nintendo Switch Procon
Zeigen Sie das Diagramm an, während Sie die Parameter mit PySimpleGUI + Matplotlib ändern
[Einführung in Python] Grundlegende Verwendung der Bibliothek matplotlib
Ändern Sie die Größe des Bildes auf die angegebene Größe und schwärzen Sie die Ränder
Ich habe versucht, das Bild mithilfe von maschinellem Lernen zu komprimieren
Was tun, wenn das Bild nicht mit matplotlib usw. im Docker-Container angezeigt wird?