Attaques contradictoires contre les modèles sans gradient

DEV - 16/01
Un de mes collègues m'a récemment posé des questions sur les exemples contradictoires (AE) pour les modèles sans gradient tels que...

Un de mes collègues m'a récemment posé des questions sur les exemples contradictoires (AE) pour les modèles sans gradient tels que les arbres de décision. C’est une bonne question : après tout, de nombreuses techniques de génération AE reposent sur des optimisations basées sur le gradient des entrées du modèle. Sans gradients, attaquer ces modèles devient un défi d’optimisation algorithmique plutôt que numérique. Cela peut être plus facile à comprendre pour les programmeurs sans formation avancée en mathématiques.

Remarque : cet article a été initialement publié sur mon site Web.

Section 0 : Configuration

Nous choisirons des arbres de décision car ils sont interprétables et faciles à mettre en œuvre avec sklearn. Commençons par adapter certaines données de jouets avec 4 fonctionnalités f0, f1, f2, f3 à trois classes c0, c1, c2 et visualisons comment elles font des inférences. Notre objectif est de perturber un échantillon juste assez pour qu'il soit mal classé.

importer numpy en tant que np depuis sklearn.tree importer DecisionTreeClassifier np.random.seed(0) # Créer des données de jouets num_samples = 20 num_classes = 3 X = np.random.rand(num_samples, 4) y = np.random.randint(0, num_classes, size=(num_samples,)) clf = DecisionTreeClassifier(random_state=1234) model = clf.fit(X, y)
Entrer en mode plein écran Quitter le mode plein écran

Section 1 : Analyse

Rappelons que les arbres de décision peuvent être considérés comme des arbres binaires dont les nœuds se divisent en fonction de la valeur de la fonctionnalité d'une instance. Pour prédire une étiquette de classe pour une instance donnée, nous commençons au nœud racine et suivons les branches déterminées par les valeurs des caractéristiques jusqu'à atteindre un nœud feuille représentant la prédiction. Par exemple, considérons l'entrée suivante : [.9, .2, .5, .3]. À partir du nœud racine de la figure 1, les divisions suivantes sont parcourues jusqu'à ce que nous atteignions le nœud feuille violet en bas correspondant à la classe c2 : f2 > .45, f1 > 182, f0 <= .97, f2 <= .882. , f2 <= 0,586, f3 <= 0,342.

depuis matplotlib importer pyplot en tant que plt depuis sklearn import tree fig = plt.figure(figsize=(6, 20)) tree.plot_tree( clf, feature_names=[f"f{i}" pour i in range(X.shape[1 ])], class_names=[f"c{i}" pour i dans set(y)], fill=True, ) plt.show() print(clf.predict([[0.9, 0.2, 0.5, 0.3]] ))
Entrer en mode plein écran Quitter le mode plein écran

C’est une bonne idée d’inspecter le modèle et de le vérifier. Heureusement, la documentation de sklearn fournit d'excellentes ressources pour décompresser un arbre de décision dans un nœud d'arbre binaire et tracer le chemin emprunté lors de la passe avant.

class Node : def __init__(self, id) : self.id = id self.left = Aucun self.right = Aucun self.parent = Aucun self.cls = Aucun def unpack_tree(clf) : root = Node(0) children_left = clf.tree_.children_left children_right = clf.tree_.children_right feature = clf.tree_.feature seuil = clf.tree_.threshold stack = [root] while ...
[Courte citation de 8% de l'article original]
Loading...