ניקוי תמונות מרעשים באמצעות למידת מכונה
אוטואנקודר autoencoder היא רשת נוירונית שמשחזרת את הקלט שהיא מקבלת בשכבת הפלט. לדוגמה, נזין לתוכה תמונות של ספרות והרשת תפיק תמונות של ספרות דומות כמה שניתן למקור. בעוד רשת רגילה מנסה להכליל. לדוגמה, לסדר תמונות של 70,000 ספרות ב-10 קטגוריות של מספרים, ה-autoencoder מנסה ליצור שחזור כמה שיותר אמין של המידע שהוזן לתוכו. ההבדל הזה מרשת רגילה גורם לשינוי משמעותי בארכיטקטורה. כי בעוד ברשת רגילה שכבת הקלט מכילה יותר נאורונים מאשר שכבת הפלט ב-autoencoder מספר הנוירונים בשכבת הפלט יהיה זהה לזה שבשכבת הקלט.
תרשים סכמטי של רשת autoencoder יראה כך:
- מספר הנוירונים בשכבת הקלט input הוא גדול יותר מבשכבה החבויה, ומספר הנוירונים חוזר וגדל עד לגודל המקורי בשכבת הפלט.
- בסכמה מתוארת שכבה חבויה אחת ובמודל שנפתח במדריך נראה מספר גדול יותר של שכבות חבויות.
הרשת מורכבת משני חלקים:
- Encoder - החלק שבין הקלט לבין השכבה החבויה המרכזית. בחלק זה של הרשת המידע נדחס לייצוג מצומצם.
- Decoder - החלק שבין השכבה החבויה המרכזית לבין הפלט שבו המידע חוזר לממדים המקוריים.
השכבה החבויה כוללת מספר נמוך יותר של נוירונים מאשר השכבות שעוטפות אותה משני הצדדים. מכיוון שהרשת לומדת לשחזר את המידע, המשמעות היא שהשכבה החבויה לומדת להחזיק את המידע בייצוג דחוס המסתפק במספר קטן יותר של ממדים.
Autoencoders יכולים לשמש לניקוי מרעשים וגם לאנליזת PCA. במדריך הנוכחי נלמד לנקות תמונות של ספרות הכתובות בכתב יד מרעשים.
לחץ כאן כדי להוריד את קובץ קוד המלא שנפתח במדריך
ייבוא הספריות הבסיסיות
import numpy as np
import matplotlib.pyplot as plt
ייבוא מסד הנתונים
מסד הנתונים הוא MNIST שכולל 70,000 תמונות של ספרות הכתובות בכתב יד.
# import the mnist dataset
from keras.datasets import mnist
(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train = x_train.reshape(x_train.shape[0], 28, 28, 1).astype('float32')
x_test = x_test.reshape(x_test.shape[0], 28, 28, 1).astype('float32')
נוסיף לתמונות רעש
הקוד הבא מוסיף רעש אקראי לתמונות.
# add random noise
noise_factor = 0.5
x_train_noisy = x_train + noise_factor * np.random.normal(loc=0.0, scale=1.0, size=x_train.shape)
x_test_noisy = x_test + noise_factor * np.random.normal(loc=0.0, scale=1.0, size=x_test.shape)
x_train_noisy = np.clip(x_train_noisy, 0., 1.)
x_test_noisy = np.clip(x_test_noisy, 0., 1.)
# show the first 10 noisy images
rows = 1
cols = 10
fig, ax = plt.subplots(rows,cols)
for i in range(cols):
ax[i].imshow(x_test_noisy[i].reshape(28,28))
בניית המודל autoencoder
נייבא מ-Keras את הספריות שישמשו לבניית המודל.
from keras.models import Sequential
from keras.engine.input_layer import Input
from keras.layers import Conv2D
from keras.layers import MaxPooling2D
from keras.layers import UpSampling2D
from keras.optimizers import adadelta
נבנה את המודל בשכבות:
# the autoencoder model
model = Sequential()
# encoder
model.add(Conv2D(32, (3, 3), activation='relu', padding='same'))
model.add(MaxPooling2D((2, 2), padding='same'))
model.add(Conv2D(32, (3, 3), activation='relu', padding='same'))
model.add(MaxPooling2D((2, 2), padding='same'))
# decoder
model.add(Conv2D(32, (3, 3), activation='relu', padding='same'))
model.add(UpSampling2D((2, 2)))
model.add(Conv2D(32, (3, 3), activation='relu', padding='same'))
model.add(UpSampling2D((2, 2)))
model.add(Conv2D(1, (3, 3), activation='sigmoid', padding='same'))
model.compile(optimizer='adadelta', loss='binary_crossentropy')
המודל מבוסס על קונבולוציה בדומה למדריך קודם על זיהוי ספרות שכתובות בכתב יד לקריאת המדריך.
למודל יש שני חלקים. ה-encoder משתמש בשתי שכבות קונבולוציה ו-2 שכבות MaxPooling כדי לדחוס את המידע. ה-decoder משתמש גם הוא בשתי שכבות קונבולוציה ובנוסף בשתי שכבות UpSampling שמרחיבות את המידע לצורתו המקורית.
זה מבנה המודל:
Layer (type) Output Shape Param # ====================================================== conv2d_1 (Conv2D) (None, 28, 28, 32) 320 ______________________________________________________ max_pooling2d_1 (MaxPooling2 (None, 14, 14, 32) 0 ______________________________________________________ conv2d_2 (Conv2D) (None, 14, 14, 32) 9248 ______________________________________________________ max_pooling2d_2 (MaxPooling2 (None, 7, 7, 32) 0 ______________________________________________________ conv2d_3 (Conv2D) (None, 7, 7, 32) 9248 ______________________________________________________ up_sampling2d_1 (UpSampling2 (None, 14, 14, 32) 0 ______________________________________________________ conv2d_4 (Conv2D) (None, 14, 14, 32) 9248 ______________________________________________________ up_sampling2d_2 (UpSampling2 (None, 28, 28, 32) 0 ______________________________________________________ conv2d_5 (Conv2D) (None, 28, 28, 1) 289 ====================================================== Total params: 28,353 Trainable params: 28,353 Non-trainable params: 0
אנחנו מתחילים עם 28*28 נוירונים בקלט, שה-encoder מכווץ ל-14*14 ואח"כ ל-7*7. ה-decoder מרחיב ל-14*14 ומסיים עם מבנה של 28*28.
נריץ את המודל:
model.fit(x_train_noisy, x_train,
epochs=10,
batch_size=128,
shuffle=True,
validation_data=(x_test_noisy, x_test))
הערכת המודל
נעריך עד כמה המודל מצליח בניקוי התמונות בקבוצת הביקורת מרעשים.
x_pred = model.predict(x_test_noisy)
ככה זה נראה עבור 10 הספרות הראשונות:
rows = 3
fig, ax = plt.subplots(rows,cols)
for c in range(cols):
ax[0][c].imshow(x_test[c].reshape(28,28))
ax[1][c].imshow(x_test_noisy[c].reshape(28,28))
ax[2][c].imshow(x_pred[c].reshape(28,28))
בשורה הראשונה, התמונות המקוריות. בשורה השנייה, התמונות עם הרעש, ובשורה השלישית השחזור באמצעות הרשת שפיתחנו במדריך.
השחזור נראה אמין עם כי בקווים גסים יותר מהמקור. בסך הכול תוצאה טובה בשביל 10 מחזורים בלבד.
סיכום
למדנו שמודל autoencoder מסוגל לשחזר את המידע שהוא קולט. זו תכונה שימושית כשרוצים לנקות תמונות מרעשים. אפשר גם קטעי קול. צריך לשים לב, ש-autoencoder יודע לשחזר רק את המידע שהוא קולט, והוא לא יודע להכליל. זאת אומרת, שהמודל שפתחנו במדריך כדי לנקות תמונות של ספרות מרעשים לא יצליח בניקוי תמונות של כלבים מרעשים.
פה המקום לעצור לרגע ולהבין משהו מאוד חשוב על הרשת שפתחנו במדריך והוא שהרשת הזו מעולם לא ראתה תמונות שאינן רועשות, ולמרות הכול היא מסוגלת לנקות את התמונות מרעשים. אם עד עכשיו לימדנו את הרשתות שפיתחנו מה הם צריכות להפיק. פה הרשת לומדת בעצמה. זה מרחיק אותנו מהרעיון של למידת מכונה מפוקחת supervised שבה אנחנו מגדירים לרשת את היעדים שהיא צריכה להגיע אליהם (להבדיל בין כלבים וחתולים) ומקרב לסוג של למידה בלתי מפוקחת (unsupervised) שבו הרשת מסווגת בעצמה על סמך דפוסים שאנחנו לא בהכרח מבינים והתוצאה יכולה להיות מפתיעה ואפקטיבית. אפקטיביות משמעותית במיוחד בעולם שבו אנחנו אוגרים כמויות עצומות של מידע כמעט בלא יכולת לסווג לא כל שכן להפיק תובנות משמעותיות.
במדריך הבא נשתמש ב-autoencoder כדי להפיק מידע דחוס במסגרת אנליזת PCA.
לכל המדריכים בנושא של למידת מכונה
אהבתם? לא אהבתם? דרגו!
0 הצבעות, ממוצע 0 מתוך 5 כוכבים