인코더의 출력층을 sigmoid 함수로 해놓고 출력층 바로 뒤에 가우시안 잡음 층을 놓으면, 가우시안 잡음 층 바로 뒤에 있는 층의 출력이 커집니다. 잡음에 입력이 묻히지 않도록 하기 위해서 모델이 그렇게 학습합니다. 아마 이렇게 하면 이미지의 특성을 명확하게 표현하려고 하려나?
인코더의 출력층을 16개의 뉴런으로 하고, 출력값을 0과 1로 반올림하면 16비트의 '시맨틱 해시'를 얻습니다. 모든 것이 잘 수행되면 비슷한 이미지는 같은 해시를 가지게 됩니다. 이는 검색 엔진에 매우 유용합니다. 이미지의 시맨틱 해시에 따라 서버에 이미지를 저장하면 같은 서버에는 모두 비슷한 이미지가 저장될 것이고, 사용자가 탐색할 이미지를 전달하면 검색 엔진이 인코더를 사용해서, 전달된 이미지의 해시를 계산하고 이 해시에 해당하는 서버의 모든 이미지를 빠르게 반환할 수 있습니다.
인코더가 암호화하는 거니깐 결국 이미지는 16비트의 해시로 암호화한다고 볼 수도 있을 것 같다.
hashing_encoder = keras.models.Sequential([
keras.layers.Flatten(input_shape=[28, 28]),
keras.layers.Dense(100, activation='selu'),
keras.layers.GaussianNoise(15.),
keras.layers.Dense(16, activation='sigmoid')
])
hashing_decoder = keras.models.Sequential([
keras.layers.Dense(100, activation='selu', input_shape=[16]),
keras.layers.Dense(28*28, activation='sigmoid'),
keras.layers.Reshape([28, 28])
])
hashing_ae = keras.models.Sequential([hashing_encoder, hashing_decoder])
hashing_ae.compile(loss='binary_crossentropy', optimizer=keras.optimizers.Nadam())
history = hashing_ae.fit(X_train, X_train, epochs=10,\
validation_data=(X_valid, X_valid))
show_reconstructions(hashing_ae)
plt.show()
오토인코더가 이미지를 16비트로 많이 압축했습니다. 이미지가 많이 흐려졌지만 이미지를 재구성하는 게 목적이 아니라 시맨틱 해시를 생성하는게 목적이므로 상관없습니다.
plot_activations_histogram(hashing_encoder)
plt.show()
왼쪽 그래프에서 볼 수 있듯이 출력은 0과 1에 매우 가깝습니다.
hashes = np.round(hashing_encoder.predict(X_valid)).astype(np.int32) # 0, 1로 반올림
hashes *= np.array([[2**bit for bit in range(16)]])
# array([[ 1, 2, 4, 8, 16, 32, 64, 128, 256,
# 512, 1024, 2048, 4096, 8192, 16384, 32768]])
hashes = hashes.sum(axis=1) # 16비트 값으로 만듬
for h in hashes[:5]: # 5개 이미지에 대한 해시값 출력, 행 당 1개의 이미지
print("{:016b}".format(h))
print('...')
'''
1010100100101000
1000110100101000
1101100100101000
0010101100001001
0000110101010000
...
'''
from collections import Counter
n_hashes = 10
n_images = 8
top_hashes = Counter(hashes).most_common(n_hashes)
plt.figure(figsize=(n_images, n_hashes))
for hash_index, (image_hash, hash_count) in enumerate(top_hashes):
indices = (hashes == image_hash)
# X_valid[False]면 빈 배열 반환, True면 X_valid 반환
for index, image in enumerate(X_valid[indices][:n_images]):
plt.subplot(n_hashes, n_images, hash_index*n_images + index + 1)
plt.imshow(image, cmap='binary')
plt.axis('off')
출처: https://github.com/rickiepark/handson-ml2/blob/master/17_autoencoders_and_gans.ipynb
'핸즈온 머신러닝 2판' 카테고리의 다른 글
19장 대규모 텐서플로 모델 훈련과 배포 (0) | 2022.02.13 |
---|---|
18장 강화 학습 (0) | 2022.02.07 |
LSTM autoencoder (0) | 2022.02.04 |
17장 오토인코더와 GAN을 사용한 표현 학습과 생성적 학습 (2) | 2022.02.03 |
16장 RNN과 어텐션을 사용한 자연어 처리 (1) | 2022.01.26 |