4
votes

Plotly: Comment créer une matrice de confusion annotée à l'aide d'une carte thermique?

J'aime utiliser Plotly pour tout visualiser, j'essaye de visualiser une matrice de confusion par Plotly, voici mon code:

def plot_confusion_matrix(y_true, y_pred, class_names):
    confusion_matrix = metrics.confusion_matrix(y_true, y_pred)
    confusion_matrix = confusion_matrix.astype(int)

    layout = {
        "title": "Confusion Matrix", 
        "xaxis": {"title": "Predicted value"}, 
        "yaxis": {"title": "Real value"}
    }

    fig = go.Figure(data=go.Heatmap(z=confusion_matrix,
                                    x=class_names,
                                    y=class_names,
                                    hoverongaps=False),
                    layout=layout)
    fig.show()

et le résultat est

entrez la description de l'image ici

Comment puis-je afficher le numéro dans la cellule correspondante au lieu de survoler, comme ceci entrez la description de l'image ici


1 commentaires

Votre question bénéficierait vraiment d'un échantillon de données et d'un extrait de code complet. Vous manquez vos importations par exemple.


3 Réponses :


6
votes

Vous pouvez utiliser des cartes thermiques annotées avec ff.create_annotated_heatmap() pour obtenir ceci:

entrez la description de l'image ici

Code complet:

import plotly.figure_factory as ff

z = [[0.1, 0.3, 0.5, 0.2],
     [1.0, 0.8, 0.6, 0.1],
     [0.1, 0.3, 0.6, 0.9],
     [0.6, 0.4, 0.2, 0.2]]

x = ['healthy', 'multiple diseases', 'rust', 'scab']
y =  ['healthy', 'multiple diseases', 'rust', 'scab']

# change each element of z to type string for annotations
z_text = [[str(y) for y in x] for x in z]

# set up figure 
fig = ff.create_annotated_heatmap(z, x=x, y=y, annotation_text=z_text, colorscale='Viridis')

# add title
fig.update_layout(title_text='<i><b>Confusion matrix</b></i>',
                  #xaxis = dict(title='x'),
                  #yaxis = dict(title='x')
                 )

# add custom xaxis title
fig.add_annotation(dict(font=dict(color="black",size=14),
                        x=0.5,
                        y=-0.15,
                        showarrow=False,
                        text="Predicted value",
                        xref="paper",
                        yref="paper"))

# add custom yaxis title
fig.add_annotation(dict(font=dict(color="black",size=14),
                        x=-0.35,
                        y=0.5,
                        showarrow=False,
                        text="Real value",
                        textangle=-90,
                        xref="paper",
                        yref="paper"))

# adjust margins to make room for yaxis title
fig.update_layout(margin=dict(t=50, l=200))

# add colorbar
fig['data'][0]['showscale'] = True
fig.show()


5 commentaires

@ClementViricel La fonction est ff.create_annotated_heatmaps() . C'est dans l'extrait de code. Et l'extrait de code est entièrement reproductible. Essayez par vous-même.


D'accord, je l'ai essayé et cela fonctionne. C'est juste une boucle for pour créer une annoation. Ma faute.


Je pense juste qu'il peut être plus clair pour un débutant de proposer un code simple comme: def plot .. et d'expliquer ce qu'il fait réellement


@ClementViricel Ok. J'ai inclus ff.create_annotated_heatmaps () au début de la réponse pour indiquer clairement à quiconque ne lit pas l'extrait de code comment le problème est résolu. Souhaitez-vous retirer votre vote défavorable? Après tout, la suggestion a été marquée comme la réponse acceptée par le PO il y a longtemps


C'est fait: D merci d'avoir pris mon commentaire en compte



2
votes

Comme le dit @vestland, vous pouvez annoter la figure avec complot. La carte thermique fonctionne comme n'importe quel type de figure intrigue. Voici un code pour tracer une carte thermique à partir d'une matrice de confusion (essentiellement juste un vecteur 2D avec des nombres).

def plot_confusion_matrix(cm, labels, title):
# cm : confusion matrix list(list)
# labels : name of the data list(str)
# title : title for the heatmap
data = go.Heatmap(z=cm, y=labels, x=labels)
annotations = []
for i, row in enumerate(cm):
    for j, value in enumerate(row):
        annotations.append(
            {
                "x": labels[i],
                "y": labels[j],
                "font": {"color": "white"},
                "text": str(value),
                "xref": "x1",
                "yref": "y1",
                "showarrow": False
            }
        )
layout = {
    "title": title,
    "xaxis": {"title": "Predicted value"},
    "yaxis": {"title": "Real value"},
    "annotations": annotations
}
fig = go.Figure(data=data, layout=layout)
return fig


1 commentaires

Merci pour cette réponse. Cela fonctionne pour moi, car je souhaite utiliser des objets graphiques plutôt que des figurines. Comment puis-je inclure la mise en page / l'annotation pour chaque sous-tracé? Le go.heatmap ne semble pas avoir d'argument pour les annotations.



0
votes

J'ai trouvé la stratégie de @ vestland la plus utile.

Cependant, contrairement à une matrice de confusion traditionnelle, les prédictions correctes du modèle se situent le long de la diagonale supérieure droite et non de la partie supérieure gauche.

Cela peut facilement être résolu en inversant toutes les valeurs d'index de la matrice de confusion comme indiqué ci-dessous:

import plotly.figure_factory as ff

z = [[0.1, 0.3, 0.5, 0.2],
     [1.0, 0.8, 0.6, 0.1],
     [0.1, 0.3, 0.6, 0.9],
     [0.6, 0.4, 0.2, 0.2]]

# invert z idx values
z = z[::-1]

x = ['healthy', 'multiple diseases', 'rust', 'scab']
y =  x[::-1].copy() # invert idx values of x

# change each element of z to type string for annotations
z_text = [[str(y) for y in x] for x in z]

# set up figure 
fig = ff.create_annotated_heatmap(z, x=x, y=y, annotation_text=z_text, colorscale='Viridis')

# add title
fig.update_layout(title_text='<i><b>Confusion matrix</b></i>',
                  #xaxis = dict(title='x'),
                  #yaxis = dict(title='x')
                 )

# add custom xaxis title
fig.add_annotation(dict(font=dict(color="black",size=14),
                        x=0.5,
                        y=-0.15,
                        showarrow=False,
                        text="Predicted value",
                        xref="paper",
                        yref="paper"))

# add custom yaxis title
fig.add_annotation(dict(font=dict(color="black",size=14),
                        x=-0.35,
                        y=0.5,
                        showarrow=False,
                        text="Real value",
                        textangle=-90,
                        xref="paper",
                        yref="paper"))

# adjust margins to make room for yaxis title
fig.update_layout(margin=dict(t=50, l=200))

# add colorbar
fig['data'][0]['showscale'] = True
fig.show()


0 commentaires