Cet article est un article qui implémente, ajuste et considère Auto Encoder.
Nous proposons un modèle recommandé pour ceux qui remplissent les conditions ci-dessus.
Tout d'abord, ce qu'est la détection d'anomalies sans enseignant sera expliqué à l'aide d'un exemple. Lorsque vous fabriquez un produit, vous vous retrouvez avec un produit défectueux. Si des rides sont visibles lorsque l'image du produit défectueux est prise, il est très difficile pour une personne de la séparer, de sorte que le réseau neuronal le détecte automatiquement. Cependant, lorsqu'il ne suffit pas de classer l'image froissée comme anormale ou normale, il est possible de trouver la valeur anormale de l'image en utilisant uniquement l'image normale pour l'apprentissage.
Une fonction qui prend une image normale en entrée et renvoie une image normale: Apprenez $ f $ avec un réseau neuronal tel que $ f (x) = x $ ($ x $ est une image normale).
Outlier
Il est nécessaire de faire un modèle qui est stupide dans une certaine mesure avec le modèle écrit ci-dessus et prédit que c'est normal, mais échoue s'il est anormal. Par conséquent, il est assez courant pour le modèle d'être aussi intelligent que possible et d'annuler le bruit ajouté à l'entrée (débruitage), c'est-à-dire d'apprendre $ x = f (x + z) $ ($ z $ est du bruit). Cela semble fonctionner.
Quand j'ai deviné que l'utilisation de la super-résolution au lieu du débruitage fonctionnerait bien pour rendre la prédiction d'image difficile, les performances étaient plutôt bonnes dans le problème de la détection des rides et des rayures. Nous comparerons les trois approches introduites jusqu'à présent et montrerons à quel point elles diffèrent.
Il n'est pas possible de considérer le résultat en utilisant l'image du produit réel en raison des droits, donc le problème devient assez simple, mais 1 des nombres manuscrits de mnist est une image normale et les nombres autres que 1 sont anormaux. Comparez les trois approches ci-dessus sous forme d'image.
Si vous copiez toute la partie de code, elle sera introduite sous une forme de travail. Mettre en œuvre avec keras. Tout d'abord, importez et téléchargez les données.
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
from tensorflow.keras.datasets import mnist
from keras import layers
from keras import models
from keras import optimizers
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()
Convertissez les données dans un format gérable
train_true = train_images[train_labels==1].reshape(6742,28,28,1)/255#Image de formation(1)6742 feuilles
test_true = test_images[test_labels==1].reshape(1135,28,28,1)/255#Image normale de vérification(1)Soit 1135 feuilles
test_false = test_images[test_labels!=1].reshape(8865,28,28,1)/255#Image anormale de vérification(Autre que 1)Est de 1032 feuilles
Je pensais que le nombre de jeux de données mnist était uniforme de 0 à 9, mais il semble être disjoint. L'image a été normalisée à la plage [0,1].
Définissez model1 comme un simple modèle de décodeur d'encodeur1
ffc = 8#first filter count
model1 = models.Sequential()
model1.add(layers.Conv2D(ffc,(3,3),padding="same",activation="relu",input_shape = (28,28,1)))
model1.add(layers.BatchNormalization())
model1.add(layers.MaxPooling2D((2,2)))
model1.add(layers.Conv2D(ffc,(3,3),padding="same",activation="relu"))
model1.add(layers.BatchNormalization())
model1.add(layers.MaxPooling2D((2,2)))
model1.add(layers.Conv2D(ffc,(3,3),padding="same",activation="relu"))
model1.add(layers.BatchNormalization())
model1.add(layers.UpSampling2D())
model1.add(layers.Conv2D(ffc,(3,3),padding="same",activation="relu"))
model1.add(layers.BatchNormalization())
model1.add(layers.UpSampling2D())
model1.add(layers.Conv2D(ffc,(3,3),padding="same",activation="relu"))
model1.add(layers.BatchNormalization())
model1.add(layers.Conv2D(1,(3,3),padding="same",activation="sigmoid"))
model1.compile(loss = "mae",optimizer="adam")
model1.summary()
Ici, la régularisation des lots a été appliquée entre les pliages. L'activation de la couche de sortie est sigmoïde. (Pour mapper à [0,1]) La fonction de perte a l'avantage qu'il est plus difficile de rendre flou dans la génération d'image si la valeur absolue est utilisée au lieu de l'erreur carrée dans MAE. J'ai défini model2 de la même manière.
ffc = 8#first filter count
model2 = models.Sequential()
model2.add(layers.MaxPooling2D((4,4),input_shape = (28,28,1)))
model2.add(layers.UpSampling2D())
model2.add(layers.Conv2D(ffc,(3,3),padding="same",activation="relu"))
model2.add(layers.BatchNormalization())
model2.add(layers.Conv2D(ffc,(3,3),padding="same",activation="relu"))
model2.add(layers.BatchNormalization())
model2.add(layers.UpSampling2D())
model2.add(layers.Conv2D(ffc,(3,3),padding="same",activation="relu"))
model2.add(layers.BatchNormalization())
model2.add(layers.Conv2D(ffc,(3,3),padding="same",activation="relu"))
model2.add(layers.BatchNormalization())
model2.add(layers.Conv2D(1,(3,3),padding="same",activation="sigmoid"))
model2.compile(loss = "mae",optimizer="adam")
model2.summary()
Le matériel de calcul est utilisé pour le décodage en n'effectuant que le maxpool et le codage.
Entraînons-nous réellement.
t_acc = np.zeros(50)
f_acc = np.zeros(50)
for i in range(50):
hist = model1.fit(train_true,train_true,steps_per_epoch=10,epochs = 1,verbose=0)
true_d = ((test_true - model1.predict(test_true))**2).reshape(1135,28*28).mean(axis=-1)
false_d = ((test_false- model1.predict(test_false))**2).reshape(8865,28*28).mean(axis=-1)
t_acc[i] = (true_d<=true_d.mean()+3*true_d.std()).sum()/len(true_d)
f_acc[i] = (false_d>true_d.mean()+3*true_d.std()).sum()/len(false_d)
print("{}Le pourcentage de réponses correctes pour les images d'apprentissage normales dans la semaine est{:.2f}%Ainsi, le taux de réponse correct des images anormales est{:.2f}%est".format(i+1,t_acc[i]*100,f_acc[i]*100))
plt.plot(t_acc)
plt.plot(f_acc)
plt.show()
Contrairement à la fonction de perte, la dérivation des valeurs aberrantes a utilisé une erreur quadratique. Lorsque cela est fait, le modèle 1, c'est-à-dire un graphique montrant la transition de la probabilité de la façon dont chacune de l'image normale et de l'image anormale peut être correctement jugée pendant l'apprentissage par un codeur / décodeur ordinaire est sorti. Le seuil est défini comme $ \ mu (moyenne) + 3 \ sigma (écart type) $ de l'image normale.
Exemple de sortie ci-dessous Le bleu est la transition de la probabilité qu'une image normale soit jugée normale, et l'orange est la transition de la probabilité qu'une image anormale soit jugée comme une image anormale. Puisqu'il y a toujours un seuil au-dessus de la moyenne des images normales de trois écarts types, la probabilité de juger une image normale comme une image normale est toujours d'environ 98%. Il semble qu'une cinquantaine d'époques suffisait à apprendre. (La valeur finale est que le taux de réponse correct pour les images normales est de 98,68% et le taux de réponse correct pour les images anormales est de 97,13).
Le modèle est entraîné à l'aide de model1 en ajoutant du bruit de même taille que la taille entraînée à l'échelle 0,1 au centre de 0 à l'entrée. Le code spécifique est le suivant.
t_acc = np.zeros(50)
f_acc = np.zeros(50)
for i in range(50):
hist = model1.fit(train_true,train_true+0.1*np.random.normal(size=train_true.shape),steps_per_epoch=10,epochs = 1,verbose=0)
true_d = ((test_true - model1.predict(test_true))**2).reshape(1135,28*28).mean(axis=-1)
false_d = ((test_false- model1.predict(test_false))**2).reshape(8865,28*28).mean(axis=-1)
t_acc[i] = (true_d<=true_d.mean()+3*true_d.std()).sum()/len(true_d)
f_acc[i] = (false_d>true_d.mean()+3*true_d.std()).sum()/len(false_d)
print("{}Le pourcentage de réponses correctes pour les images d'apprentissage normales dans la semaine est{:.2f}%Ainsi, le taux de réponse correct des images anormales est{:.2f}%est".format(i+1,t_acc[i]*100,f_acc[i]*100))
plt.plot(t_acc)
plt.plot(f_acc)
plt.show()
Si vous faites cela, vous obtiendrez le graphique suivant. Il semble que la convergence soit devenue plus rapide dans une certaine mesure. La valeur finale était de 98,68% pour les images normales et de 97,59% pour les images anormales.
Entraînons model2 et voyons le résultat.
t_acc = np.zeros(50)
f_acc = np.zeros(50)
for i in range(50):
hist = model2.fit(train_true,train_true,steps_per_epoch=10,epochs = 1,verbose=0)
true_d = ((test_true - model2.predict(test_true))**2).reshape(1135,28*28).mean(axis=-1)
false_d = ((test_false- model2.predict(test_false))**2).reshape(8865,28*28).mean(axis=-1)
t_acc[i] = (true_d<=true_d.mean()+3*true_d.std()).sum()/len(true_d)
f_acc[i] = (false_d>true_d.mean()+3*true_d.std()).sum()/len(false_d)
print("{}Le pourcentage de réponses correctes pour les images d'apprentissage normales dans la semaine est{:.2f}%Ainsi, le taux de réponse correct des images anormales est{:.2f}%est".format(i+1,t_acc[i]*100,f_acc[i]*100))
plt.plot(t_acc)
plt.plot(f_acc)
plt.show()
Graphique de résultat C'était un modèle inutile que je n'avais imaginé. Bien que la valeur finale ne semble pas avoir convergé, le taux normal de réponse correcte était de 98,59% et le taux de réponse correcte pour les images anormales était de 84,85%.
J'ai regardé le caractère manuscrit 1 pour faire la distinction entre 1 et les autres, mais dans ce cas, il s'est avéré que l'ajout de bruit était efficace. C'est l'opération d'ajout de ce bruit qui fait que 1 ressemble à 7 ou 9, il est donc assez évident qu'un modèle habitué à le remettre à 1 améliorera la précision. En d'autres termes, si le type d'anomalie est connu, les performances d'Auto Encoder seront extrêmement élevées si un entraînement est ajouté pour ajouter ce type d'anomalie et le renvoyer.
L'approche de super-résolution recommandée pour cet ensemble de données n'était pas très efficace, mais lors de la détection des rides et des rayures sur des produits industriels réels, l'approche consiste à réduire la résolution pour rendre les rides et les rayures invisibles, puis à les restaurer. Cependant, il y a des cas où cela est efficace, c'est donc une bonne idée de changer le modèle à utiliser tout en regardant le problème cible.
Recommended Posts