AutoEncoder ist eine Art unbeaufsichtigtes Lernen beim maschinellen Lernen. Die Erkennung von Abnormalitäten ist als Anwendungsbeispiel bekannt. Dieses Mal möchte ich AutoEncoedr für mnist mit CNN (Convolutional Neural Network) ausprobieren. Ich weiß nicht, welche Zahl ich brauen soll, aber es ist ein Memorandum über das Studium von Pytorch. Diesmal habe ich auf [hier] verwiesen (https://github.com/udacity/deep-learning-v2-pytorch/blob/master/autoencoder/convolutional-autoencoder/Convolutional_Autoencoder_Solution.ipynb)
Hier ist ein grobes Verständnis von AutoEncoder:
Stellen Sie den Codierer und Decodierer so ein, dass der Inhalt der Eingangs- und Ausgangsdaten gleich ist.
Wenn sich die Eingabedaten von den üblichen unterscheiden, können keine Ausgabedaten erstellt werden, die den Eingabedaten entsprechen.
Wenn daher ein großer Unterschied zwischen den Eingabedaten und den Ausgabedaten besteht, kann dies als abnormal beurteilt werden (wie es scheint).
Die Umwelt ist python ver3.6.9 pytorch ver1.3.1 numpy ver1.17.4
Laden Sie zuerst mnist. Im Code (als persönliches Hobby) wird Scicit Learn verwendet, um Daten im Ndarray-Format zu lesen, aber Torch Vision wird verwendet, um sie im Tensor-Format zu lesen. 7.000 Bilder mit 0-Bilddaten werden extrahiert und 6000 davon zum Lernen verwendet.
import numpy as np
import matplotlib.pyplot as plt
import torch
from torch import nn, optim
from torch.utils.data import DataLoader, TensorDataset
from sklearn.datasets import fetch_openml
#Laden Sie die wichtigsten Daten herunter
mnist = fetch_openml('mnist_784', version=1, data_home='data/src/download/')
X, y = mnist["data"], mnist["target"]
X_0 = X[np.int32(y) == 0] #Nur extrahieren, wenn die Zieldaten 0 sind
X_0 = (2 *X_0) / 255.0 - 1.0 #max 1.0 min -1.In 0 konvertieren
X_0 = X_0.reshape([X_0.shape[0], 1, 28, 28])
X_0 = torch.tensor(X_0, dtype = torch.float32)
X_0_train, X_0_test = X_0[:6000, :, :, :], X_0[6000:, :, :, :]
train_loader = DataLoader(X_0_train, batch_size = 50)
Erstellen Sie als Nächstes ein Netzwerk mit Pytorch. Der Encoder verwendet nn.Conv2d für die normale Faltung. Das Eingabebild war 1x28x28 mit 784 Dimensionen, aber nach dem Durchlaufen des Encoders wird es mit 196 Dimensionen auf 4x7x7 komprimiert. Der Decoder verwendet nn.ConvTranspose2d, was die Umkehrung der normalen Faltung (?) Ist. Dann kehrt es schließlich zu 784 Dimensionen von 1x28x28 zurück.
class ConvAutoencoder(nn.Module):
def __init__(self):
super(ConvAutoencoder, self).__init__()
#Encoder Layers
self.conv1 = nn.Conv2d(in_channels = 1, out_channels = 16,
kernel_size = 3, padding = 1)
self.conv2 = nn.Conv2d(in_channels = 16, out_channels = 4,
kernel_size = 3, padding = 1)
#Decoder Layers
self.t_conv1 = nn.ConvTranspose2d(in_channels = 4, out_channels = 16,
kernel_size = 2, stride = 2)
self.t_conv2 = nn.ConvTranspose2d(in_channels = 16, out_channels = 1,
kernel_size = 2, stride = 2)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(2, 2)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
#Zeigt die Dimension an, wenn i Blätter mit 28 x 28 Schwarzweißbildern in den Kommentar eingegeben werden
#encode# #in [i, 1, 28, 28]
x = self.relu(self.conv1(x)) #out [i, 16, 28, 28]
x = self.pool(x) #out [i, 16, 14, 14]
x = self.relu(self.conv2(x)) #out [i, 4, 14, 14]
x = self.pool(x) #out [i ,4, 7, 7]
#decode#
x = self.relu(self.t_conv1(x)) #out [i, 16, 14, 14]
x = self.sigmoid(self.t_conv2(x)) #out [i, 1, 28, 28]
return x
Jetzt, wo wir ein Netzwerk haben, lernen wir. Die Berechnung loss_fn vergleicht das Eingabebild mit dem Ausgabebild des Netzwerks.
def train_net(n_epochs, train_loader, net, optimizer_cls = optim.Adam,
loss_fn = nn.MSELoss(), device = "cpu"):
"""
n_Epochen… Anzahl der Trainingseinheiten
net… Netzwerk
device … "cpu" or "cuda:0"
"""
losses = [] #loss_Notieren Sie den Funktionsübergang
optimizer = optimizer_cls(net.parameters(), lr = 0.001)
net.to(device)
for epoch in range(n_epochs):
running_loss = 0.0
net.train() #Netzwerkmodus trainieren
for i, XX in enumerate(train_loader):
XX.to(device)
optimizer.zero_grad()
XX_pred = net(XX) #Vorhersage im Netzwerk
loss = loss_fn(XX, XX_pred) #Vorhersagedaten und Vorhersage von Originaldaten
loss.backward()
optimizer.step() #Verlaufsaktualisierung
running_loss += loss.item()
losses.append(running_loss / i)
print("epoch", epoch, ": ", running_loss / i)
return losses
losses = train_net(n_epochs = 30,
train_loader = train_loader,
net = net)
Stellen Sie den Ausgabeverlust mit matplotlib grafisch dar.
Vorhersage im Internet anhand von Daten, die nicht für das Training verwendet werden. Wenn 0 Bilder in das Netz eingegeben werden
img_num = 4
pred = net(X_0_test[img_num:(img_num + 1)])
pred = pred.detach().numpy()
pred = pred[0, 0, :, :]
origin = X_0_test[img_num:(img_num + 1)].numpy()
origin = origin[0, 0, :, :]
plt.subplot(211)
plt.imshow(origin, cmap = "gray")
plt.xticks([])
plt.yticks([])
plt.text(x = 3, y = 2, s = "original image", c = "red")
plt.subplot(212)
plt.imshow(pred, cmap = "gray")
plt.text(x = 3, y = 2, s = "output image", c = "red")
plt.xticks([])
plt.yticks([])
plt.savefig("0_auto_encoder")
plt.show()
Das obere ist das Eingabebild und das untere ist das Ausgabebild. 0 wird gut wiedergegeben.
Wenn ich das Bild 6 eingebe, kann ich 6 nicht gut reproduzieren. Wenn Sie die Daten nicht gut reproduzieren konnten, können Sie beurteilen, dass sie (wahrscheinlich) abnormal sind.
Übrigens konnte dieses Modell auch auf einem Notebook-PC relativ schnell lernen, daher würde ich es gerne noch in einer tieferen Ebene ausprobieren.
Recommended Posts