PCA를 능가하기 위해 Tensorflow에서 자동 인코더 구축


31

신경망으로 데이터의 차원을 줄이는 데있어 Hinton과 Salakhutdinov는 과학 2006 은 딥 오토 인코더를 사용하여 비선형 PCA를 제안했습니다. Tensorflow를 사용하여 PCA 자동 인코더를 빌드하고 훈련하려고 시도했지만 선형 PCA보다 더 나은 결과를 얻을 수 없었습니다.

자동 인코더를 효율적으로 훈련시킬 수있는 방법은 무엇입니까?

(@amoeba의 나중에 편집 :이 질문의 원래 버전에는 올바르게 작동하지 않는 Python Tensorflow 코드가 포함되어 있습니다. 편집 기록에서 찾을 수 있습니다.)


Layer 클래스의 활성화 기능에서 오류를 발견했습니다. 지금 작동하는지 테스트 중입니다
Donbeo

오류를 해결 했습니까?
피노키오

안녕 돈보 귀하의 질문에서 코드를 제거 할 자유를 얻었습니다 (코드는 여전히 편집 기록에서 쉽게 찾을 수 있습니다). 코드를 사용하면 귀하의 질문은 "버그를 찾는 데 도움이됩니다"라는 질문과 비슷해 보였습니다. 동시에이 스레드에는 4k 조회수가 있습니다. 아마도 많은 사람들이 Google 검색을 통해 여기에 온다는 의미이므로 귀하의 질문을 끝내고 싶지 않았습니다. 나는 자동 인코더 연습을 통해 답변을 게시하기로 결정했지만 단순성 때문에 원시 Tensorflow 대신 Keras (Tensorflow 위에서 실행)를 사용했습니다. 이것이 Q에 대한 답변이라고 생각하십니까?
아메바는

답변:


42

Hinton과 Salakhutdinov의 2006 Science 논문의 주요 수치는 다음과 같습니다.

원래 784 치수에서 MNIST 데이터 세트 ( 한 자릿수의 흑백 이미지)의 치수 축소를 보여줍니다 .28×28

그것을 재현 해 봅시다. 이와 같은 간단한 딥 러닝 작업에는 Keras (Tensorflow 위에서 실행되는 고급 라이브러리)를 사용하는 것이 훨씬 쉽기 때문에 Tensorflow를 직접 사용하지 않을 것입니다. H & S 는 물류 장치가있는 아키텍처를 사용했으며, 제한된 Boltzmann 머신 스택으로 사전 교육을 받았습니다. 10 년 후, 이것은 매우 오래된 학교 인 것 같습니다. 더 간단한 784 512 128 2 128 512

784100050025022505001000784
사전 훈련없이 지수 선형 단위를 가진 784 아키텍처. 나는 Adam 옵티 마이저 (모멘텀에 따른 적응 적 확률 구배 하강의 특정 구현)를 사용할 것이다.
7845121282128512784

코드는 Jupyter 노트북에서 복사하여 붙여 넣습니다. Python 3.6에서는 matplotlib (pylab 용), NumPy, seaborn, TensorFlow 및 Keras를 설치해야합니다. Python 셸에서 실행할 때 plt.show()플롯을 표시 하기 위해 추가해야 할 수 있습니다 .

초기화

%matplotlib notebook

import pylab as plt
import numpy as np
import seaborn as sns; sns.set()

import keras
from keras.datasets import mnist
from keras.models import Sequential, Model
from keras.layers import Dense
from keras.optimizers import Adam

(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train = x_train.reshape(60000, 784) / 255
x_test = x_test.reshape(10000, 784) / 255

PCA

mu = x_train.mean(axis=0)
U,s,V = np.linalg.svd(x_train - mu, full_matrices=False)
Zpca = np.dot(x_train - mu, V.transpose())

Rpca = np.dot(Zpca[:,:2], V[:2,:]) + mu    # reconstruction
err = np.sum((x_train-Rpca)**2)/Rpca.shape[0]/Rpca.shape[1]
print('PCA reconstruction error with 2 PCs: ' + str(round(err,3)));

이 결과는 다음과 같습니다.

PCA reconstruction error with 2 PCs: 0.056

오토 인코더 훈련

m = Sequential()
m.add(Dense(512,  activation='elu', input_shape=(784,)))
m.add(Dense(128,  activation='elu'))
m.add(Dense(2,    activation='linear', name="bottleneck"))
m.add(Dense(128,  activation='elu'))
m.add(Dense(512,  activation='elu'))
m.add(Dense(784,  activation='sigmoid'))
m.compile(loss='mean_squared_error', optimizer = Adam())
history = m.fit(x_train, x_train, batch_size=128, epochs=5, verbose=1, 
                validation_data=(x_test, x_test))

encoder = Model(m.input, m.get_layer('bottleneck').output)
Zenc = encoder.predict(x_train)  # bottleneck representation
Renc = m.predict(x_train)        # reconstruction

내 작업 데스크탑에서 약 35 초가 걸리고 출력됩니다.

Train on 60000 samples, validate on 10000 samples
Epoch 1/5
60000/60000 [==============================] - 7s - loss: 0.0577 - val_loss: 0.0482
Epoch 2/5
60000/60000 [==============================] - 7s - loss: 0.0464 - val_loss: 0.0448
Epoch 3/5
60000/60000 [==============================] - 7s - loss: 0.0438 - val_loss: 0.0430
Epoch 4/5
60000/60000 [==============================] - 7s - loss: 0.0423 - val_loss: 0.0416
Epoch 5/5
60000/60000 [==============================] - 7s - loss: 0.0412 - val_loss: 0.0407

두 번의 훈련 시대 만에 PCA 손실을 능가했음을 이미 알 수 있습니다.

( activation='linear'그러므로 모든 활성화 기능을 변경 하고 손실이 PCA 손실에 정확하게 수렴하는 방식을 관찰하는 것이 유익합니다. 이는 선형 자동 인코더가 PCA와 동일하기 때문입니다.)

병목 현상 표현과 함께 PCA 프로젝션 플로팅

plt.figure(figsize=(8,4))
plt.subplot(121)
plt.title('PCA')
plt.scatter(Zpca[:5000,0], Zpca[:5000,1], c=y_train[:5000], s=8, cmap='tab10')
plt.gca().get_xaxis().set_ticklabels([])
plt.gca().get_yaxis().set_ticklabels([])

plt.subplot(122)
plt.title('Autoencoder')
plt.scatter(Zenc[:5000,0], Zenc[:5000,1], c=y_train[:5000], s=8, cmap='tab10')
plt.gca().get_xaxis().set_ticklabels([])
plt.gca().get_yaxis().set_ticklabels([])

plt.tight_layout()

여기에 이미지 설명을 입력하십시오

재건

이제 재구성 (첫 번째 행-원본 이미지, 두 번째 행-PCA, 세 번째 행-자동 인코더)을 살펴 보겠습니다.

plt.figure(figsize=(9,3))
toPlot = (x_train, Rpca, Renc)
for i in range(10):
    for j in range(3):
        ax = plt.subplot(3, 10, 10*j+i+1)
        plt.imshow(toPlot[j][i,:].reshape(28,28), interpolation="nearest", 
                   vmin=0, vmax=1)
        plt.gray()
        ax.get_xaxis().set_visible(False)
        ax.get_yaxis().set_visible(False)

plt.tight_layout()

여기에 이미지 설명을 입력하십시오

더 깊은 네트워크, 정규화 및 더 긴 교육으로 훨씬 더 나은 결과를 얻을 수 있습니다. 실험. 딥 러닝은 쉽습니다!


2
PCA가 2 개의 구성 요소로 얼마나 잘 작동했는지 놀랐습니다! 코드를 게시 해 주셔서 감사합니다
Aksakal

2
환상적인! 튼튼함!
Matthew Drury

2
@shadi 실제로 () 간단한 : SVD에 직접 전화를 찾을 수
아메바는 분석 재개 모니카 말한다

1
더 많은 구성 요소를 사용하면 성능 차이가 훨씬 커집니다. 나는 2 대신 10을 시도했고 자동 인코더가 훨씬 낫습니다. 단점은 속도와 메모리 소비입니다
Aksakal

1
Python 2의 경우 다음 가져 오기를 추가해야합니다from __future__ import absolute_import from __future__ import division from __future__ import print_function
user2589273

7

이 훌륭한 모범을 보여준 @amoeba에 대한 거대한 소품. 그 게시물에 설명 된 자동 인코더 훈련 및 재구성 절차가 R에서도 쉽게 수행 될 수 있음을 보여주고 싶습니다. 아래의 자동 인코더는 설정되어 있으므로 동일한 최적화 프로그램 및 전체 아키텍처와 같은 아메바의 예제를 최대한 가깝게 모방합니다. TensorFlow 백엔드가 유사하게 시드되지 않아 정확한 비용을 재현 할 수 없습니다.

초기화

library(keras)
library(rARPACK) # to use SVDS
rm(list=ls())
mnist   = dataset_mnist()
x_train = mnist$train$x
y_train = mnist$train$y
x_test  = mnist$test$x
y_test  = mnist$test$y

# reshape & rescale
dim(x_train) = c(nrow(x_train), 784)
dim(x_test)  = c(nrow(x_test), 784)
x_train = x_train / 255
x_test = x_test / 255

PCA

mus = colMeans(x_train)
x_train_c =  sweep(x_train, 2, mus)
x_test_c =  sweep(x_test, 2, mus)
digitSVDS = svds(x_train_c, k = 2)

ZpcaTEST = x_test_c %*% digitSVDS$v # PCA projection of test data

자동 인코더

model = keras_model_sequential() 
model %>%
  layer_dense(units = 512, activation = 'elu', input_shape = c(784)) %>%  
  layer_dense(units = 128, activation = 'elu') %>%
  layer_dense(units = 2,   activation = 'linear', name = "bottleneck") %>%
  layer_dense(units = 128, activation = 'elu') %>% 
  layer_dense(units = 512, activation = 'elu') %>% 
  layer_dense(units = 784, activation='sigmoid')

model %>% compile(
  loss = loss_mean_squared_error, optimizer = optimizer_adam())

history = model %>% fit(verbose = 2, validation_data = list(x_test, x_test),
                         x_train, x_train, epochs = 5, batch_size = 128)

# Unsurprisingly a 3-year old laptop is slower than a desktop
# Train on 60000 samples, validate on 10000 samples
# Epoch 1/5
#  - 14s - loss: 0.0570 - val_loss: 0.0488
# Epoch 2/5
#  - 15s - loss: 0.0470 - val_loss: 0.0449
# Epoch 3/5
#  - 15s - loss: 0.0439 - val_loss: 0.0426
# Epoch 4/5
#  - 15s - loss: 0.0421 - val_loss: 0.0413
# Epoch 5/5
#  - 14s - loss: 0.0408 - val_loss: 0.0403

# Set the auto-encoder
autoencoder = keras_model(model$input, model$get_layer('bottleneck')$output)
ZencTEST = autoencoder$predict(x_test)  # bottleneck representation  of test data

병목 현상 표현과 함께 PCA 프로젝션 플로팅

par(mfrow=c(1,2))
myCols = colorRampPalette(c('green',     'red',  'blue',  'orange', 'steelblue2',
                            'darkgreen', 'cyan', 'black', 'grey',   'magenta') )
plot(ZpcaTEST[1:5000,], col= myCols(10)[(y_test+1)], 
     pch=16, xlab = 'Score 1', ylab = 'Score 2', main = 'PCA' ) 
legend( 'bottomright', col= myCols(10), legend = seq(0,9, by=1), pch = 16 )

plot(ZencTEST[1:5000,], col= myCols(10)[(y_test+1)], 
     pch=16, xlab = 'Score 1', ylab = 'Score 2', main = 'Autoencoder' ) 
legend( 'bottomleft', col= myCols(10), legend = seq(0,9, by=1), pch = 16 )

여기에 이미지 설명을 입력하십시오

재건

일반적인 방식으로 숫자를 재구성 할 수 있습니다. (맨 위 행은 원래 숫자, PCA 재구성의 중간 행, 자동 엔코더 재구성의 맨 아래 행입니다.)

Renc = predict(model, x_test)        # autoencoder reconstruction
Rpca = sweep( ZpcaTEST %*% t(digitSVDS$v), 2, -mus) # PCA reconstruction

dev.off()
par(mfcol=c(3,9), mar = c(1, 1, 0, 0))
myGrays = gray(1:256 / 256)
for(u in seq_len(9) ){
  image( matrix( x_test[u,], 28,28, byrow = TRUE)[,28:1], col = myGrays, 
         xaxt='n', yaxt='n')
  image( matrix( Rpca[u,], 28,28, byrow = TRUE)[,28:1], col = myGrays , 
         xaxt='n', yaxt='n')
  image( matrix( Renc[u,], 28,28, byrow = TRUE)[,28:1], col = myGrays, 
         xaxt='n', yaxt='n')
}

여기에 이미지 설명을 입력하십시오

케이0.03560.0359시원한!


2
+1. 좋은. Keras를 Python 에서처럼 R에서 사용하는 것이 간단하다는 것을 알면 좋습니다. 내가 볼 수있는 한, 딥 러닝 커뮤니티에서 모든 사람들 이 요즘 파이썬을 사용하고 있기 때문에 다른 곳에서는 더 어려워 야한다는 인상을 받았습니다.
amoeba는

2

이리 나는 다음과 같은 차이점, 당신의 결과를 복제하려고 내 jupyter 노트북은 다음과 같습니다

  • tensorflow를 직접 사용하는 대신 view keras를 사용합니다.
  • 채도를 피하기 위해 relu 대신에 누출이있는 relu (예 : 인코딩 된 출력이 0 임)
    • 이것은 AE의 성능 저하의 원인 일 수 있습니다.
  • 자동 인코더 입력은 [0,1]
    • relu가있는 자동 인코더가 [0-1] 데이터와 가장 잘 작동하는 곳을 읽은 것 같습니다.
    • 자동 엔코더의 입력이 평균 = 0 인 내 노트북을 실행하면 std = 1로 모든 치수 감소에 대해 AE> 0.7 인 MSE를 얻었으므로 이것이 문제 중 하나 일 수 있습니다
  • PCA 입력은 평균 = 0이고 표준 = 1 인 데이터입니다.
    • 이는 PCA의 MSE 결과가 PCA의 MSE 결과와 비교할 수 없음을 의미 할 수도 있습니다.
    • PCA와 AE 모두에 대해 [0-1] 데이터로 나중에 다시 실행하겠습니다.
  • PCA 입력도 [0-1]으로 조정됩니다. PCA는 (mean = 0, std = 1) 데이터에서도 작동하지만 MSE는 AE와 비교할 수 없습니다

내 MSE 결과는 1에서 6까지의 차원 축소 (입력에 6 개의 열이 있음) 및 AE에서 희미한 PCA에 대한 결과입니다. 빨간. 1에서 6까지는 다음과 같습니다.

PCA 입력이 (평균 = 0, 표준 = 1) 인 상태에서 AE 입력이 [0-1] 범위 인 경우-4e-15 : PCA6-.015 : PCA5-.0502 : AE5-.0508 : AE6-.051 : AE4- .053 : AE3-157 : PCA4-.258 : AE2-.259 : PCA3-.377 : AE1-.483 : PCA2-.682 : PCA1

  • 9e-15 : PCA6
  • .0094 : PCA5
  • .0502 : AE5
  • .0507 : AE6
  • .0514 : AE4
  • .0532 : AE3
  • .0772 : PCA4
  • .1231 : PCA3
  • .2588 : AE2
  • .2831 : PCA2
  • .3773 : AE1
  • .3885 : PCA1

치수 감소가없는 Linear PCA는 마지막 구성 요소에 맞지 않는 모든 것을 밀어 낼 수 있기 때문에 9e-15를 달성 할 수 있습니다.


shadi, 당신의 노트북은 예를 들어 많은 비표준 기능 utils.buildNetwork 및 utils.ae_fit_encode_plot_mse가있는 utils 패키지를 가져옵니다 ...
Berowne Hlavaty

그것은 노트북과 같은 레벨에있는 동일한 저장소에있는 파일 일뿐입니다.
shadi
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.