مشاهده در TensorFlow.org | در Google Colab اجرا شود | مشاهده منبع در GitHub | دانلود دفترچه یادداشت |
این آموزش رمزگذارهای خودکار را با سه مثال معرفی می کند: اصول اولیه، حذف نویز تصویر و تشخیص ناهنجاری.
رمزگذار خودکار نوع خاصی از شبکه عصبی است که برای کپی کردن ورودی خود در خروجی آموزش دیده است. به عنوان مثال، با توجه به تصویری از یک رقم دستنویس، یک رمزگذار خودکار ابتدا تصویر را در یک نمایش نهفته با ابعاد پایینتر رمزگذاری میکند، سپس نمایش نهفته را به یک تصویر رمزگشایی میکند. رمزگذار خودکار یاد می گیرد که داده ها را فشرده کند در حالی که خطای بازسازی را به حداقل می رساند.
برای کسب اطلاعات بیشتر در مورد رمزگذارهای خودکار، لطفاً فصل 14 از یادگیری عمیق توسط یان گودفلو، یوشوا بنژیو و آرون کورویل را مطالعه کنید.
TensorFlow و کتابخانه های دیگر را وارد کنید
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
مجموعه داده را بارگیری کنید
برای شروع، رمزگذار خودکار اصلی را با استفاده از مجموعه داده Fashion MNIST آموزش خواهید داد. هر تصویر در این مجموعه داده 28x28 پیکسل است.
(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)
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)
مثال اول: رمزگذار خودکار پایه
یک رمزگذار خودکار با دو لایه متراکم تعریف کنید: یک encoder
که تصاویر را در یک بردار نهفته 64 بعدی فشرده می کند و یک decoder
که تصویر اصلی را از فضای پنهان بازسازی می کند.
برای تعریف مدل خود، از Keras Model Subclassing API استفاده کنید.
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)
autoencoder.compile(optimizer='adam', loss=losses.MeanSquaredError())
مدل را با استفاده از x_train
به عنوان ورودی و هدف آموزش دهید. encoder
یاد می گیرد که مجموعه داده را از 784 بعد به فضای پنهان فشرده کند و decoder
یاد می گیرد که تصاویر اصلی را بازسازی کند. .
autoencoder.fit(x_train, x_train,
epochs=10,
shuffle=True,
validation_data=(x_test, x_test))
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>
اکنون که مدل آموزش داده شده است، بیایید آن را با رمزگذاری و رمزگشایی تصاویر از مجموعه آزمایشی آزمایش کنیم.
encoded_imgs = autoencoder.encoder(x_test).numpy()
decoded_imgs = autoencoder.decoder(encoded_imgs).numpy()
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()
مثال دوم: حذف نویز تصویر
همچنین میتوان یک رمزگذار خودکار برای حذف نویز از تصاویر آموزش داد. در بخش زیر، با اعمال نویز تصادفی برای هر تصویر، یک نسخه نویز از مجموعه داده Fashion MNIST ایجاد خواهید کرد. سپس یک رمزگذار خودکار را با استفاده از تصویر نویزدار به عنوان ورودی و تصویر اصلی به عنوان هدف آموزش خواهید داد.
بیایید مجموعه داده را مجدداً وارد کنیم تا تغییراتی که قبلا انجام شده را حذف کنیم.
(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)
(60000, 28, 28, 1)
اضافه کردن نویز تصادفی به تصاویر
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.)
تصاویر پر سر و صدا را ترسیم کنید.
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()
رمزگذار خودکار کانولوشنال را تعریف کنید
در این مثال، شما یک رمزگذار خودکار کانولوشنال را با استفاده از لایههای Conv2D در encoder
و لایههای Conv2DTranspose در decoder
آموزش میدهید.
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())
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>
بیایید نگاهی به خلاصه ای از رمزگذار بیندازیم. توجه داشته باشید که چگونه تصاویر از 28x28 به 7x7 کوچک می شوند.
autoencoder.encoder.summary()
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 _________________________________________________________________
رمزگشا تصاویر را از 7*7 به 28*28 نمونه برداری می کند.
autoencoder.decoder.summary()
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 _________________________________________________________________
ترسیم تصاویر پر سر و صدا و تصاویر حذف شده توسط رمزگذار خودکار.
encoded_imgs = autoencoder.encoder(x_test).numpy()
decoded_imgs = autoencoder.decoder(encoded_imgs).numpy()
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()
مثال سوم: تشخیص ناهنجاری
بررسی اجمالی
در این مثال، شما یک رمزگذار خودکار را برای تشخیص ناهنجاری ها در مجموعه داده ECG5000 آموزش می دهید. این مجموعه داده شامل 5000 الکتروکاردیوگرام است که هر کدام دارای 140 نقطه داده است. شما از یک نسخه ساده شده از مجموعه داده استفاده خواهید کرد، که در آن هر نمونه دارای برچسب 0
(مرتبط با یک ریتم غیرعادی) یا 1
(مرتبط با یک ریتم عادی) است. شما علاقه مند به شناسایی ریتم های غیر طبیعی هستید.
چگونه می توانید ناهنجاری ها را با استفاده از رمزگذار خودکار تشخیص دهید؟ به یاد بیاورید که رمزگذار خودکار برای به حداقل رساندن خطای بازسازی آموزش داده شده است. شما یک رمزگذار خودکار را فقط با ریتم های معمولی آموزش می دهید، سپس از آن برای بازسازی تمام داده ها استفاده می کنید. فرضیه ما این است که ریتم های غیرعادی خطای بازسازی بیشتری خواهند داشت. اگر خطای بازسازی از یک آستانه ثابت فراتر رود، یک ریتم را به عنوان یک ناهنجاری طبقه بندی می کنید.
بارگذاری اطلاعات ECG
مجموعه داده ای که استفاده خواهید کرد بر اساس یکی از داده های timeseriesclassification.com است.
# 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
)
داده ها را به [0,1]
عادی کنید.
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)
رمزگذار خودکار را فقط با استفاده از ریتم های معمولی که در این مجموعه داده با 1
برچسب گذاری شده اند، آموزش خواهید داد. ریتم های عادی را از ریتم های غیرعادی جدا کنید.
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]
یک نوار قلب معمولی ترسیم کنید.
plt.grid()
plt.plot(np.arange(140), normal_train_data[0])
plt.title("A Normal ECG")
plt.show()
یک نوار قلب غیرعادی را ترسیم کنید.
plt.grid()
plt.plot(np.arange(140), anomalous_train_data[0])
plt.title("An Anomalous ECG")
plt.show()
مدل را بسازید
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()
autoencoder.compile(optimizer='adam', loss='mae')
توجه داشته باشید که رمزگذار خودکار فقط با استفاده از ECG های معمولی آموزش داده می شود، اما با استفاده از مجموعه آزمایش کامل ارزیابی می شود.
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
plt.plot(history.history["loss"], label="Training Loss")
plt.plot(history.history["val_loss"], label="Validation Loss")
plt.legend()
<matplotlib.legend.Legend at 0x7ff1d339b790>
اگر خطای بازسازی بیشتر از یک انحراف استاندارد از نمونه های تمرینی معمولی باشد، به زودی ECG را به عنوان غیرعادی طبقه بندی خواهید کرد. ابتدا، بیایید یک ECG معمولی را از مجموعه آموزشی، بازسازی پس از کدگذاری و رمزگشایی توسط رمزگذار خودکار، و خطای بازسازی ترسیم کنیم.
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()
یک طرح مشابه ایجاد کنید، این بار برای یک نمونه آزمایشی غیرعادی.
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()
تشخیص ناهنجاری ها
با محاسبه اینکه آیا تلفات بازسازی بیشتر از یک آستانه ثابت است، ناهنجاری ها را تشخیص دهید. در این آموزش میانگین خطای مثالهای معمولی را از مجموعه آموزشی محاسبه میکنید، سپس اگر خطای بازسازی بیشتر از یک انحراف استاندارد از مجموعه آموزشی باشد، نمونههای آینده را به عنوان غیرعادی طبقهبندی میکنید.
خطای بازسازی را در ECGهای معمولی از مجموعه آموزشی ترسیم کنید
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()
مقدار آستانه ای را انتخاب کنید که یک انحراف استاندارد بالاتر از میانگین باشد.
threshold = np.mean(train_loss) + np.std(train_loss)
print("Threshold: ", threshold)
Threshold: 0.03241627
اگر خطای بازسازی را برای مثالهای غیرعادی در مجموعه آزمایشی بررسی کنید، متوجه خواهید شد که بیشتر آنها خطای بازسازی بیشتری نسبت به آستانه دارند. با تغییر آستانه، می توانید دقت و فراخوانی طبقه بندی کننده خود را تنظیم کنید.
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()
اگر خطای بازسازی بیشتر از آستانه باشد، ECG را به عنوان یک ناهنجاری طبقه بندی کنید.
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)
Accuracy = 0.944 Precision = 0.9921875 Recall = 0.9071428571428571
مراحل بعدی
برای کسب اطلاعات بیشتر در مورد تشخیص ناهنجاری با رمزگذارهای خودکار، این مثال تعاملی عالی ساخته شده با TensorFlow.js توسط ویکتور دیبیا را بررسی کنید. برای استفاده در دنیای واقعی، میتوانید یاد بگیرید که ایرباس چگونه ناهنجاریها را در دادههای تله متری ISS با استفاده از TensorFlow تشخیص میدهد. برای کسب اطلاعات بیشتر در مورد اصول اولیه، این پست وبلاگ فرانسوا شوله را بخوانید. برای جزئیات بیشتر، فصل 14 از یادگیری عمیق توسط ایان گودفلو، یوشوا بنجیو و آرون کورویل را بررسی کنید.