Dans toutes les tâches d'enseignement de l'intelligence artificielle, il y a un phénomène désagréable - des erreurs dans le balisage de la séquence d'entraînement. Ces erreurs sont inévitables, car tout le balisage est fait manuellement, car s'il existe un moyen de marquer les données réelles par programme, alors pourquoi avons-nous besoin de quelqu'un d'autre pour leur apprendre à baliser et à dépenser du temps et de l'argent pour créer un design absolument inutile!
La tâche de trouver et de supprimer de faux masques dans une grande séquence d'entraînement est assez compliquée. Vous pouvez tous les afficher manuellement, mais cela ne vous évitera pas d'erreurs répétées. Mais si vous regardez attentivement les outils d'étude des réseaux de neurones proposés dans
les articles précédents , il s'avère qu'il existe un moyen simple et efficace de détecter et d'extraire tous les artefacts de la séquence d'entraînement.
Et dans ce post, il y a un exemple concret, il est évident qu'un simple, sur des ellipses et des polygones, pour un U-net ordinaire, est à nouveau un tel lego dans le bac à sable, mais il est inhabituellement concret, utile et efficace. Nous montrerons comment une méthode simple identifie et trouve presque tous les artefacts, tous les mensonges de la séquence d'apprentissage.
Commençons donc!
Comme précédemment, nous étudierons la séquence des paires image / masque. Dans l'image dans différents quartiers, choisis au hasard, nous placerons également une ellipse de taille aléatoire et un quadrilatère de taille arbitraire, et les deux couleurs de la même couleur, également sélectionnées au hasard parmi deux d'entre elles. Dans la deuxième couleur restante, nous colorons l'arrière-plan. Les dimensions de l'ellipse et du quadrilatère sont bien sûr limitées.
Mais dans ce cas, nous allons apporter des modifications au programme de génération de paires et préparer, avec un masque complètement correct, un masque incorrect, empoisonné par un mensonge - dans environ un pour cent des cas, remplacer le quadrilatère par une ellipse dans le masque, c'est-à-dire le véritable objet de segmentation est désigné par de faux masques comme une ellipse, et non comme un quadrilatère.
Exemples aléatoires 10
Exemples de 10 aléatoires, mais à partir d'un balisage erroné. Le masque supérieur est vrai, le masque inférieur est faux et les chiffres de la séquence d'entraînement sont indiqués sur les images.
pour la segmentation, nous prenons les mêmes programmes de calcul de métrique et de perte et le même U-net simple, mais nous n'utiliserons pas Dropout.
Bibliothèquesimport numpy as np import matplotlib.pyplot as plt from matplotlib.colors import NoNorm %matplotlib inline import math from tqdm import tqdm
Fonctions métriques et de perte def dice_coef(y_true, y_pred): y_true_f = K.flatten(y_true) y_pred = K.cast(y_pred, 'float32') y_pred_f = K.cast(K.greater(K.flatten(y_pred), 0.5), 'float32') intersection = y_true_f * y_pred_f score = 2. * K.sum(intersection) / (K.sum(y_true_f) + K.sum(y_pred_f)) return score def dice_loss(y_true, y_pred): smooth = 1. y_true_f = K.flatten(y_true) y_pred_f = K.flatten(y_pred) intersection = y_true_f * y_pred_f score = (2. * K.sum(intersection) + smooth) / (K.sum(y_true_f) + K.sum(y_pred_f) + smooth) return 1. - score def bce_dice_loss(y_true, y_pred): return binary_crossentropy(y_true, y_pred) + dice_loss(y_true, y_pred) def get_iou_vector(A, B):
U-net normal def build_model(input_layer, start_neurons):
Le programme pour générer des images et des masques - vrai et faux. La première couche de l'image est placée dans le tableau, la seconde est le vrai masque et la troisième couche est le faux masque.
def next_pair_f(idx): img_l = np.ones((w_size, w_size, 1), dtype='float')*0.45 img_h = np.ones((w_size, w_size, 1), dtype='float')*0.55 img = np.zeros((w_size, w_size, 3), dtype='float') i0_qua = math.trunc(np.random.sample()*4.) i1_qua = math.trunc(np.random.sample()*4.) while i0_qua == i1_qua: i1_qua = math.trunc(np.random.sample()*4.) _qua = np.int(w_size/4) qua = np.array([[_qua,_qua],[_qua,_qua*3],[_qua*3,_qua*3],[_qua*3,_qua]]) p = np.random.sample() - 0.5 r = qua[i0_qua,0] c = qua[i0_qua,1] r_radius = np.random.sample()*(radius_max-radius_min) + radius_min c_radius = np.random.sample()*(radius_max-radius_min) + radius_min rot = np.random.sample()*360 rr, cc = ellipse( r, c, r_radius, c_radius, rotation=np.deg2rad(rot), shape=img_l.shape ) p0 = np.rint(np.random.sample()*(radius_max-radius_min) + radius_min) p1 = qua[i1_qua,0] - (radius_max-radius_min) p2 = qua[i1_qua,1] - (radius_max-radius_min) p3 = np.rint(np.random.sample()*radius_min) p4 = np.rint(np.random.sample()*radius_min) p5 = np.rint(np.random.sample()*radius_min) p6 = np.rint(np.random.sample()*radius_min) p7 = np.rint(np.random.sample()*radius_min) p8 = np.rint(np.random.sample()*radius_min) poly = np.array(( (p1, p2), (p1+p3, p2+p4+p0), (p1+p5+p0, p2+p6+p0), (p1+p7+p0, p2+p8), (p1, p2), )) rr_p, cc_p = polygon(poly[:, 0], poly[:, 1], img_l.shape) if p > 0: img[:,:,:1] = img_l.copy() img[rr, cc,:1] = img_h[rr, cc] img[rr_p, cc_p,:1] = img_h[rr_p, cc_p] else: img[:,:,:1] = img_h.copy() img[rr, cc,:1] = img_l[rr, cc] img[rr_p, cc_p,:1] = img_l[rr_p, cc_p] img[:,:,1] = 0. img[:,:,1] = 0. img[rr_p, cc_p,1] = 1. img[:,:,2] = 0. p_f = np.random.sample()*1000. if p_f > 10: img[rr_p, cc_p,2] = 1. else: img[rr, cc,2] = 1. i_false[idx] = 1 return img
Programme de calcul de feuille de triche def make_sh(f_imgs, f_msks, val_len): precision = 0.85 batch_size = 50 t = tqdm() t_batch_size = 50 raw_len = val_len id_train = 1
Le programme principal de calculs. Nous avons apporté de petites modifications au même programme dans le post précédent et certaines variables nécessitent des explications et des commentaires.
i_false = np.zeros((train_num), dtype='int')
Il y a un faux indicateur de masque. Si 1, le masque de F_msks ne correspond pas au masque de f_msks. Ceci est un indicateur de ce que nous recherchons réellement - de faux masques.
m2_select = np.zeros((train_num), dtype='int')
Indicateur que cette image est sélectionnée dans la feuille de triche.
batch_size = 50 val_len = batch_size + 1
Nous créons des séquences de paires image / masque pour la formation et une autre séquence pour les tests. C'est-à-dire Nous allons vérifier une nouvelle séquence indépendante de 10 000 paires. Nous affichons et vérifions visuellement de manière aléatoire des images aléatoires avec des masques vrais et faux. Les images ci-dessus sont montrées.
Dans ce cas particulier, 93 faux masques ont été obtenus, sur lesquels une ellipse, plutôt qu'un quadrilatère, était marquée comme vrai positif.
Nous commençons la formation sur l'ensemble correct, utilisons f_msks comme masque
input_layer = Input((w_size, w_size, 1)) output_layer = build_model(input_layer, 25) model = Model(input_layer, output_layer) model.compile(loss=bce_dice_loss, optimizer=Adam(lr=1e-4), metrics=[my_iou_metric]) v_false = make_sh(f_imgs, f_msks, val_len) t_pred = model.predict(t_imgs,batch_size=batch_size) print (get_iou_vector(t_msks,t_pred.reshape(-1,w_size ,w_size ,1)))
Accuracy 0.9807 loss 0.0092 selected img 404 tested img 10000 : : 1801it [08:13, 3.65it/s] 0.9895299999999841
La feuille de triche s'est avérée en seulement 404 images et a obtenu une précision acceptable sur une séquence de test indépendante.
Maintenant, nous recompilons le réseau et nous nous entraînons sur la même séquence d'entraînement, mais en tant que masques, nous alimentons F_msks avec 1% de faux masques à l'entrée
input_layer = Input((w_size, w_size, 1)) output_layer = build_model(input_layer, 25) model = Model(input_layer, output_layer) model.compile(loss=bce_dice_loss, optimizer=Adam(lr=1e-4), metrics=[my_iou_metric]) v_false = make_sh(f_imgs, F_msks, val_len) t_pred = model.predict(t_imgs,batch_size=batch_size) print (get_iou_vector(t_msks,t_pred.reshape(-1,w_size ,w_size ,1)))
Accuracy 0.9821 loss 0.0324 selected img 727 tested img 10000 : : 1679it [25:44, 1.09it/s] 0.9524099999999959
Nous avons obtenu une feuille de triche de 727 images, ce qui est beaucoup plus grand et la précision des prédictions de test, la même que dans la séquence de test précédente, est passée de 0,98953 à 0,9525. Nous avons ajouté des mensonges à la séquence d'entraînement de moins de 1%, seulement 93 des 10 000 masques étaient faux, mais le résultat a empiré de 3,7%. Et ce n'est pas seulement un mensonge, c'est une vraie ruse! Et la feuille de triche est passée de 404 à 727 images.
Apaisant et plaisant une seule chose
print (len(set(np.arange(train_num)[m2_select>0]).intersection(set(np.arange(train_num)[i_false>0])))) 93
Permettez-moi d'expliquer cette longue formule, nous prenons l'intersection de l'ensemble d'images sélectionnées dans la feuille de triche avec l'ensemble de fausses images et voyons que l'algorithme a sélectionné les 93 fausses images dans la feuille de triche.
La tâche est considérablement simplifiée, ce ne sont pas 10 000 photos à parcourir manuellement, ce ne sont que 727 et tous les mensonges sont concentrés ici.
Mais il existe un moyen encore plus intéressant et utile. Lorsque nous avons compilé la feuille de triche, nous avons inclus uniquement les paires image / masque dont la prédiction est inférieure au seuil, et dans notre cas particulier, nous avons enregistré la valeur de la précision de la prédiction dans le tableau
v_false . Regardons les paires de la séquence d'entraînement qui ont une très petite valeur de prédiction, par exemple, moins de 0,1 et voyons combien de mensonges s'y trouvent.
print (len(set(np.arange(train_num)[v_false<0.01]).intersection(set(np.arange(train_num)[i_false>0])))) 89
Comme vous pouvez le voir, la partie principale des faux masques, 89 sur 93, est tombée dans ces masques.
np.arange(train_num)[v_false<0.01].shape (382,)
Ainsi, si nous ne vérifions que 382 masques manuellement, et c'est sur 10 000 pièces, nous identifierons et détruirons la plupart des faux masques sans aucune pitié.
S'il est possible de visualiser des images et des masques lors de la décision de les inclure dans la feuille de triche, puis à partir d'une certaine étape, tous les faux masques, tous les mensonges seront déterminés par le niveau minimum de prédiction d'un réseau légèrement formé, et les bons masques auront une prédiction supérieure à ce niveau .
Pour résumer
Si dans un monde imaginaire la vérité est toujours quadrangulaire, et le mensonge ovale et une entité inconnue ont décidé de déformer la vérité et ont appelé certaines ellipses la vérité, et les quadrangles sont faux, alors, en utilisant l'intelligence artificielle et la capacité naturelle de faire des tricheurs, l'Inquisition locale trouvera rapidement et facilement et éradique complètement et complètement les mensonges et les tromperies.
PS La capacité de détecter des ovales, des triangles, des polygones simples est une condition préalable à la création de toute IA qui contrôle la voiture. Si vous ne savez pas comment chercher des ovales et des triangles, vous ne trouverez pas tous les panneaux routiers et votre IA partira dans la mauvaise voiture.