Otomatik Kodlayıcılara Giriş

TensorFlow.org'da görüntüleyin Google Colab'da çalıştırın Kaynağı GitHub'da görüntüleyin Not defterini indir

Bu öğretici, otomatik kodlayıcıları üç örnekle tanıtır: temel bilgiler, görüntü gürültü giderme ve anormallik algılama.

Otomatik kodlayıcı, girdisini çıktısına kopyalamak üzere eğitilmiş özel bir sinir ağı türüdür. Örneğin, elle yazılmış bir rakamın görüntüsü verildiğinde, bir otomatik kodlayıcı önce görüntüyü daha düşük boyutlu bir gizli gösterime kodlar, ardından gizli gösterimin kodunu tekrar bir görüntüye dönüştürür. Bir otomatik kodlayıcı, yeniden yapılandırma hatasını en aza indirirken verileri sıkıştırmayı öğrenir.

Otomatik kodlayıcılar hakkında daha fazla bilgi edinmek için lütfen Ian Goodfellow, Yoshua Bengio ve Aaron Courville tarafından yazılan Derin Öğrenme'nin 14. bölümünü okuyun.

TensorFlow ve diğer kitaplıkları içe aktarın

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import tensorflow as tf

from sklearn.metrics import accuracy_score, precision_score, recall_score
from sklearn.model_selection import train_test_split
from tensorflow.keras import layers, losses
from tensorflow.keras.datasets import fashion_mnist
from tensorflow.keras.models import Model

Veri kümesini yükleyin

Başlamak için, Fashion MNIST veri setini kullanarak temel otomatik kodlayıcıyı eğiteceksiniz. Bu veri kümesindeki her görüntü 28x28 pikseldir.

(x_train, _), (x_test, _) = fashion_mnist.load_data()

x_train = x_train.astype('float32') / 255.
x_test = x_test.astype('float32') / 255.

print (x_train.shape)
print (x_test.shape)
tutucu2 l10n-yer
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/train-labels-idx1-ubyte.gz
32768/29515 [=================================] - 0s 0us/step
40960/29515 [=========================================] - 0s 0us/step
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/train-images-idx3-ubyte.gz
26427392/26421880 [==============================] - 0s 0us/step
26435584/26421880 [==============================] - 0s 0us/step
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/t10k-labels-idx1-ubyte.gz
16384/5148 [===============================================================================================] - 0s 0us/step
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/t10k-images-idx3-ubyte.gz
4423680/4422102 [==============================] - 0s 0us/step
4431872/4422102 [==============================] - 0s 0us/step
(60000, 28, 28)
(10000, 28, 28)

İlk örnek: Temel otomatik kodlayıcı

Temel otomatik kodlayıcı sonuçları

İki Yoğun katmana sahip bir otomatik kodlayıcı tanımlayın: görüntüleri 64 boyutlu bir gizli vektöre sıkıştıran bir encoder ve gizli alandan orijinal görüntüyü yeniden oluşturan bir decoder .

Modelinizi tanımlamak için Keras Model Alt Sınıflandırma API'sini kullanın.

latent_dim = 64 

class Autoencoder(Model):
  def __init__(self, latent_dim):
    super(Autoencoder, self).__init__()
    self.latent_dim = latent_dim   
    self.encoder = tf.keras.Sequential([
      layers.Flatten(),
      layers.Dense(latent_dim, activation='relu'),
    ])
    self.decoder = tf.keras.Sequential([
      layers.Dense(784, activation='sigmoid'),
      layers.Reshape((28, 28))
    ])

  def call(self, x):
    encoded = self.encoder(x)
    decoded = self.decoder(encoded)
    return decoded

autoencoder = Autoencoder(latent_dim)
tutucu4 l10n-yer
autoencoder.compile(optimizer='adam', loss=losses.MeanSquaredError())

Modeli hem girdi hem de hedef olarak x_train kullanarak eğitin. encoder , veri kümesini 784 boyuttan gizli alana sıkıştırmayı öğrenecek ve decoder , orijinal görüntüleri yeniden yapılandırmayı öğrenecek. .

autoencoder.fit(x_train, x_train,
                epochs=10,
                shuffle=True,
                validation_data=(x_test, x_test))
tutucu6 l10n-yer
Epoch 1/10
1875/1875 [==============================] - 4s 2ms/step - loss: 0.0243 - val_loss: 0.0140
Epoch 2/10
1875/1875 [==============================] - 3s 2ms/step - loss: 0.0116 - val_loss: 0.0106
Epoch 3/10
1875/1875 [==============================] - 3s 2ms/step - loss: 0.0100 - val_loss: 0.0098
Epoch 4/10
1875/1875 [==============================] - 3s 2ms/step - loss: 0.0094 - val_loss: 0.0094
Epoch 5/10
1875/1875 [==============================] - 3s 2ms/step - loss: 0.0092 - val_loss: 0.0092
Epoch 6/10
1875/1875 [==============================] - 3s 2ms/step - loss: 0.0090 - val_loss: 0.0091
Epoch 7/10
1875/1875 [==============================] - 3s 2ms/step - loss: 0.0090 - val_loss: 0.0090
Epoch 8/10
1875/1875 [==============================] - 3s 2ms/step - loss: 0.0089 - val_loss: 0.0090
Epoch 9/10
1875/1875 [==============================] - 3s 2ms/step - loss: 0.0088 - val_loss: 0.0089
Epoch 10/10
1875/1875 [==============================] - 3s 2ms/step - loss: 0.0088 - val_loss: 0.0089
<keras.callbacks.History at 0x7ff1d35df550>

Artık model eğitildiğine göre, test setinden görüntüleri kodlayarak ve kodunu çözerek test edelim.

encoded_imgs = autoencoder.encoder(x_test).numpy()
decoded_imgs = autoencoder.decoder(encoded_imgs).numpy()
tutucu8 l10n-yer
n = 10
plt.figure(figsize=(20, 4))
for i in range(n):
  # display original
  ax = plt.subplot(2, n, i + 1)
  plt.imshow(x_test[i])
  plt.title("original")
  plt.gray()
  ax.get_xaxis().set_visible(False)
  ax.get_yaxis().set_visible(False)

  # display reconstruction
  ax = plt.subplot(2, n, i + 1 + n)
  plt.imshow(decoded_imgs[i])
  plt.title("reconstructed")
  plt.gray()
  ax.get_xaxis().set_visible(False)
  ax.get_yaxis().set_visible(False)
plt.show()

png

İkinci örnek: Görüntü gürültü giderme

Görüntü gürültü giderme sonuçları

Bir otomatik kodlayıcı, görüntülerden paraziti çıkarmak için de eğitilebilir. Aşağıdaki bölümde, her bir görüntüye rastgele gürültü uygulayarak Fashion MNIST veri setinin gürültülü bir versiyonunu oluşturacaksınız. Ardından, giriş olarak gürültülü görüntüyü ve hedef olarak orijinal görüntüyü kullanarak bir otomatik kodlayıcı eğiteceksiniz.

Daha önce yapılan değişiklikleri atlamak için veri kümesini yeniden içe aktaralım.

(x_train, _), (x_test, _) = fashion_mnist.load_data()
x_train = x_train.astype('float32') / 255.
x_test = x_test.astype('float32') / 255.

x_train = x_train[..., tf.newaxis]
x_test = x_test[..., tf.newaxis]

print(x_train.shape)
-yer tutucu11 l10n-yer
(60000, 28, 28, 1)

Resimlere rastgele gürültü ekleme

noise_factor = 0.2
x_train_noisy = x_train + noise_factor * tf.random.normal(shape=x_train.shape) 
x_test_noisy = x_test + noise_factor * tf.random.normal(shape=x_test.shape) 

x_train_noisy = tf.clip_by_value(x_train_noisy, clip_value_min=0., clip_value_max=1.)
x_test_noisy = tf.clip_by_value(x_test_noisy, clip_value_min=0., clip_value_max=1.)

Gürültülü görüntüleri çizin.

n = 10
plt.figure(figsize=(20, 2))
for i in range(n):
    ax = plt.subplot(1, n, i + 1)
    plt.title("original + noise")
    plt.imshow(tf.squeeze(x_test_noisy[i]))
    plt.gray()
plt.show()

png

Bir evrişimli otomatik kodlayıcı tanımlayın

Bu örnekte, encoder Conv2D katmanlarını ve decoder Conv2DTranspose katmanlarını kullanarak bir evrişimli otomatik kodlayıcıyı eğiteceksiniz.

class Denoise(Model):
  def __init__(self):
    super(Denoise, self).__init__()
    self.encoder = tf.keras.Sequential([
      layers.Input(shape=(28, 28, 1)),
      layers.Conv2D(16, (3, 3), activation='relu', padding='same', strides=2),
      layers.Conv2D(8, (3, 3), activation='relu', padding='same', strides=2)])

    self.decoder = tf.keras.Sequential([
      layers.Conv2DTranspose(8, kernel_size=3, strides=2, activation='relu', padding='same'),
      layers.Conv2DTranspose(16, kernel_size=3, strides=2, activation='relu', padding='same'),
      layers.Conv2D(1, kernel_size=(3, 3), activation='sigmoid', padding='same')])

  def call(self, x):
    encoded = self.encoder(x)
    decoded = self.decoder(encoded)
    return decoded

autoencoder = Denoise()
autoencoder.compile(optimizer='adam', loss=losses.MeanSquaredError())
yer tutucu16 l10n-yer
autoencoder.fit(x_train_noisy, x_train,
                epochs=10,
                shuffle=True,
                validation_data=(x_test_noisy, x_test))
Epoch 1/10
1875/1875 [==============================] - 8s 3ms/step - loss: 0.0169 - val_loss: 0.0107
Epoch 2/10
1875/1875 [==============================] - 6s 3ms/step - loss: 0.0095 - val_loss: 0.0086
Epoch 3/10
1875/1875 [==============================] - 6s 3ms/step - loss: 0.0082 - val_loss: 0.0080
Epoch 4/10
1875/1875 [==============================] - 6s 3ms/step - loss: 0.0078 - val_loss: 0.0077
Epoch 5/10
1875/1875 [==============================] - 6s 3ms/step - loss: 0.0076 - val_loss: 0.0075
Epoch 6/10
1875/1875 [==============================] - 6s 3ms/step - loss: 0.0074 - val_loss: 0.0074
Epoch 7/10
1875/1875 [==============================] - 6s 3ms/step - loss: 0.0073 - val_loss: 0.0073
Epoch 8/10
1875/1875 [==============================] - 6s 3ms/step - loss: 0.0072 - val_loss: 0.0072
Epoch 9/10
1875/1875 [==============================] - 6s 3ms/step - loss: 0.0071 - val_loss: 0.0071
Epoch 10/10
1875/1875 [==============================] - 6s 3ms/step - loss: 0.0070 - val_loss: 0.0071
<keras.callbacks.History at 0x7ff1c45a31d0>

Kodlayıcının bir özetine bir göz atalım. Görüntülerin 28x28'den 7x7'ye nasıl altörneklendiğine dikkat edin.

autoencoder.encoder.summary()
tutucu19 l10n-yer
Model: "sequential_2"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 conv2d (Conv2D)             (None, 14, 14, 16)        160       
                                                                 
 conv2d_1 (Conv2D)           (None, 7, 7, 8)           1160      
                                                                 
=================================================================
Total params: 1,320
Trainable params: 1,320
Non-trainable params: 0
_________________________________________________________________

Kod çözücü, görüntüleri 7x7'den 28x28'e yükseltir.

autoencoder.decoder.summary()
tutucu21 l10n-yer
Model: "sequential_3"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 conv2d_transpose (Conv2DTra  (None, 14, 14, 8)        584       
 nspose)                                                         
                                                                 
 conv2d_transpose_1 (Conv2DT  (None, 28, 28, 16)       1168      
 ranspose)                                                       
                                                                 
 conv2d_2 (Conv2D)           (None, 28, 28, 1)         145       
                                                                 
=================================================================
Total params: 1,897
Trainable params: 1,897
Non-trainable params: 0
_________________________________________________________________

Otomatik kodlayıcı tarafından üretilen hem gürültülü görüntülerin hem de gürültü giderilmiş görüntülerin çizilmesi.

encoded_imgs = autoencoder.encoder(x_test).numpy()
decoded_imgs = autoencoder.decoder(encoded_imgs).numpy()
tutucu23 l10n-yer
n = 10
plt.figure(figsize=(20, 4))
for i in range(n):

    # display original + noise
    ax = plt.subplot(2, n, i + 1)
    plt.title("original + noise")
    plt.imshow(tf.squeeze(x_test_noisy[i]))
    plt.gray()
    ax.get_xaxis().set_visible(False)
    ax.get_yaxis().set_visible(False)

    # display reconstruction
    bx = plt.subplot(2, n, i + n + 1)
    plt.title("reconstructed")
    plt.imshow(tf.squeeze(decoded_imgs[i]))
    plt.gray()
    bx.get_xaxis().set_visible(False)
    bx.get_yaxis().set_visible(False)
plt.show()

png

Üçüncü örnek: Anormallik algılama

genel bakış

Bu örnekte, ECG5000 veri kümesindeki anormallikleri algılamak için bir otomatik kodlayıcı eğiteceksiniz. Bu veri seti, her biri 140 veri noktasına sahip 5.000 Elektrokardiyogram içerir. Her örneğin 0 (anormal bir ritme karşılık gelir) veya 1 (normal bir ritme karşılık gelir) olarak etiketlendiği, veri kümesinin basitleştirilmiş bir sürümünü kullanacaksınız. Anormal ritimleri tanımlamakla ilgileniyorsunuz.

Bir otomatik kodlayıcı kullanarak anormallikleri nasıl tespit edeceksiniz? Bir otomatik kodlayıcının yeniden yapılandırma hatasını en aza indirecek şekilde eğitildiğini hatırlayın. Bir otomatik kodlayıcıyı yalnızca normal ritimler üzerinde eğitecek, ardından tüm verileri yeniden oluşturmak için kullanacaksınız. Hipotezimiz, anormal ritimlerin daha yüksek yeniden yapılandırma hatasına sahip olacağıdır. Daha sonra, yeniden yapılandırma hatası sabit bir eşiği aşarsa, bir ritmi anormallik olarak sınıflandırırsınız.

EKG verilerini yükle

Kullanacağınız veri kümesi, timeseriesclassification.com'dan bir veri kümesine dayanmaktadır.

# Download the dataset
dataframe = pd.read_csv('http://storage.googleapis.com/download.tensorflow.org/data/ecg.csv', header=None)
raw_data = dataframe.values
dataframe.head()
# The last element contains the labels
labels = raw_data[:, -1]

# The other data points are the electrocadriogram data
data = raw_data[:, 0:-1]

train_data, test_data, train_labels, test_labels = train_test_split(
    data, labels, test_size=0.2, random_state=21
)

Verileri [0,1] olarak normalleştirin.

min_val = tf.reduce_min(train_data)
max_val = tf.reduce_max(train_data)

train_data = (train_data - min_val) / (max_val - min_val)
test_data = (test_data - min_val) / (max_val - min_val)

train_data = tf.cast(train_data, tf.float32)
test_data = tf.cast(test_data, tf.float32)

Otomatik kodlayıcıyı yalnızca bu veri kümesinde 1 olarak etiketlenen normal ritimleri kullanarak eğiteceksiniz. Normal ritimleri anormal ritimlerden ayırın.

train_labels = train_labels.astype(bool)
test_labels = test_labels.astype(bool)

normal_train_data = train_data[train_labels]
normal_test_data = test_data[test_labels]

anomalous_train_data = train_data[~train_labels]
anomalous_test_data = test_data[~test_labels]

Normal bir EKG çizin.

plt.grid()
plt.plot(np.arange(140), normal_train_data[0])
plt.title("A Normal ECG")
plt.show()

png

Anormal bir EKG çizin.

plt.grid()
plt.plot(np.arange(140), anomalous_train_data[0])
plt.title("An Anomalous ECG")
plt.show()

png

Modeli oluşturun

class AnomalyDetector(Model):
  def __init__(self):
    super(AnomalyDetector, self).__init__()
    self.encoder = tf.keras.Sequential([
      layers.Dense(32, activation="relu"),
      layers.Dense(16, activation="relu"),
      layers.Dense(8, activation="relu")])

    self.decoder = tf.keras.Sequential([
      layers.Dense(16, activation="relu"),
      layers.Dense(32, activation="relu"),
      layers.Dense(140, activation="sigmoid")])

  def call(self, x):
    encoded = self.encoder(x)
    decoded = self.decoder(encoded)
    return decoded

autoencoder = AnomalyDetector()
tutucu31 l10n-yer
autoencoder.compile(optimizer='adam', loss='mae')

Otomatik kodlayıcının yalnızca normal EKG'ler kullanılarak eğitildiğine, ancak tam test seti kullanılarak değerlendirildiğine dikkat edin.

history = autoencoder.fit(normal_train_data, normal_train_data, 
          epochs=20, 
          batch_size=512,
          validation_data=(test_data, test_data),
          shuffle=True)
Epoch 1/20
5/5 [==============================] - 1s 33ms/step - loss: 0.0576 - val_loss: 0.0531
Epoch 2/20
5/5 [==============================] - 0s 8ms/step - loss: 0.0552 - val_loss: 0.0514
Epoch 3/20
5/5 [==============================] - 0s 8ms/step - loss: 0.0519 - val_loss: 0.0499
Epoch 4/20
5/5 [==============================] - 0s 8ms/step - loss: 0.0483 - val_loss: 0.0475
Epoch 5/20
5/5 [==============================] - 0s 8ms/step - loss: 0.0445 - val_loss: 0.0451
Epoch 6/20
5/5 [==============================] - 0s 8ms/step - loss: 0.0409 - val_loss: 0.0432
Epoch 7/20
5/5 [==============================] - 0s 8ms/step - loss: 0.0377 - val_loss: 0.0415
Epoch 8/20
5/5 [==============================] - 0s 8ms/step - loss: 0.0348 - val_loss: 0.0401
Epoch 9/20
5/5 [==============================] - 0s 8ms/step - loss: 0.0319 - val_loss: 0.0388
Epoch 10/20
5/5 [==============================] - 0s 8ms/step - loss: 0.0293 - val_loss: 0.0378
Epoch 11/20
5/5 [==============================] - 0s 8ms/step - loss: 0.0273 - val_loss: 0.0369
Epoch 12/20
5/5 [==============================] - 0s 8ms/step - loss: 0.0259 - val_loss: 0.0361
Epoch 13/20
5/5 [==============================] - 0s 8ms/step - loss: 0.0249 - val_loss: 0.0354
Epoch 14/20
5/5 [==============================] - 0s 8ms/step - loss: 0.0239 - val_loss: 0.0346
Epoch 15/20
5/5 [==============================] - 0s 8ms/step - loss: 0.0230 - val_loss: 0.0340
Epoch 16/20
5/5 [==============================] - 0s 8ms/step - loss: 0.0222 - val_loss: 0.0335
Epoch 17/20
5/5 [==============================] - 0s 8ms/step - loss: 0.0215 - val_loss: 0.0331
Epoch 18/20
5/5 [==============================] - 0s 9ms/step - loss: 0.0211 - val_loss: 0.0331
Epoch 19/20
5/5 [==============================] - 0s 8ms/step - loss: 0.0208 - val_loss: 0.0329
Epoch 20/20
5/5 [==============================] - 0s 8ms/step - loss: 0.0206 - val_loss: 0.0327
yer tutucu34 l10n-yer
plt.plot(history.history["loss"], label="Training Loss")
plt.plot(history.history["val_loss"], label="Validation Loss")
plt.legend()
<matplotlib.legend.Legend at 0x7ff1d339b790>

png

Yeniden yapılandırma hatası normal eğitim örneklerinden bir standart sapmadan büyükse, yakında bir EKG'yi anormal olarak sınıflandıracaksınız. İlk olarak, eğitim setinden normal bir EKG çizelim, otomatik kodlayıcı tarafından kodlanıp kodu çözüldükten sonra yeniden yapılandırma ve yeniden oluşturma hatası.

encoded_data = autoencoder.encoder(normal_test_data).numpy()
decoded_data = autoencoder.decoder(encoded_data).numpy()

plt.plot(normal_test_data[0], 'b')
plt.plot(decoded_data[0], 'r')
plt.fill_between(np.arange(140), decoded_data[0], normal_test_data[0], color='lightcoral')
plt.legend(labels=["Input", "Reconstruction", "Error"])
plt.show()

png

Bu sefer anormal bir test örneği için benzer bir arsa oluşturun.

encoded_data = autoencoder.encoder(anomalous_test_data).numpy()
decoded_data = autoencoder.decoder(encoded_data).numpy()

plt.plot(anomalous_test_data[0], 'b')
plt.plot(decoded_data[0], 'r')
plt.fill_between(np.arange(140), decoded_data[0], anomalous_test_data[0], color='lightcoral')
plt.legend(labels=["Input", "Reconstruction", "Error"])
plt.show()

png

Anormallikleri tespit edin

Yeniden yapılandırma kaybının sabit bir eşikten büyük olup olmadığını hesaplayarak anormallikleri tespit edin. Bu öğreticide, eğitim kümesinden normal örnekler için ortalama hatayı hesaplayacak, ardından yeniden yapılandırma hatası eğitim kümesinden bir standart sapmadan yüksekse gelecekteki örnekleri anormal olarak sınıflandıracaksınız.

Eğitim setinden normal EKG'lerde yeniden yapılandırma hatasını çizin

reconstructions = autoencoder.predict(normal_train_data)
train_loss = tf.keras.losses.mae(reconstructions, normal_train_data)

plt.hist(train_loss[None,:], bins=50)
plt.xlabel("Train loss")
plt.ylabel("No of examples")
plt.show()

png

Ortalamanın bir standart sapma üzerinde olan bir eşik değeri seçin.

threshold = np.mean(train_loss) + np.std(train_loss)
print("Threshold: ", threshold)
tutucu40 l10n-yer
Threshold:  0.03241627

Test setindeki anormal örnekler için yeniden oluşturma hatasını incelerseniz, çoğunun eşikten daha büyük yeniden yapılandırma hatası olduğunu fark edeceksiniz. Eşiği değiştirerek, sınıflandırıcınızın kesinliğini ve geri çağrılmasını ayarlayabilirsiniz.

reconstructions = autoencoder.predict(anomalous_test_data)
test_loss = tf.keras.losses.mae(reconstructions, anomalous_test_data)

plt.hist(test_loss[None, :], bins=50)
plt.xlabel("Test loss")
plt.ylabel("No of examples")
plt.show()

png

Yeniden yapılandırma hatası eşikten büyükse bir EKG'yi anomali olarak sınıflandırın.

def predict(model, data, threshold):
  reconstructions = model(data)
  loss = tf.keras.losses.mae(reconstructions, data)
  return tf.math.less(loss, threshold)

def print_stats(predictions, labels):
  print("Accuracy = {}".format(accuracy_score(labels, predictions)))
  print("Precision = {}".format(precision_score(labels, predictions)))
  print("Recall = {}".format(recall_score(labels, predictions)))
preds = predict(autoencoder, test_data, threshold)
print_stats(preds, test_labels)
-yer tutucu44 l10n-yer
Accuracy = 0.944
Precision = 0.9921875
Recall = 0.9071428571428571

Sonraki adımlar

Otomatik kodlayıcılarla anormallik algılama hakkında daha fazla bilgi edinmek için Victor Dibia tarafından TensorFlow.js ile oluşturulmuş bu mükemmel etkileşimli örneğe göz atın. Gerçek dünyadaki bir kullanım örneği için, Airbus'ın TensorFlow kullanarak ISS Telemetri Verilerindeki Anomalileri nasıl Algıladığını öğrenebilirsiniz. Temel bilgiler hakkında daha fazla bilgi edinmek için François Chollet'in bu blog gönderisini okumayı düşünün. Daha fazla ayrıntı için Ian Goodfellow, Yoshua Bengio ve Aaron Courville tarafından yazılan Derin Öğrenme'nin 14. bölümüne bakın.