PCA'yı aşmak için Tensorflow'ta bir otomatik kodlayıcı oluşturma


31

Sinir Ağları ile Verilerin Boyutlarını Azaltan Hinton ve Salakhutdinov , Science 2006 , derin bir otomatik kodlayıcı kullanarak doğrusal olmayan bir PCA önerdi. Birkaç defa Tensorflowlu bir PCA otomatik kodlayıcı oluşturmaya ve eğitmeye çalıştım, ancak doğrusal PCA'dan daha iyi bir sonuç elde edemedim.

Bir otomatik kodlayıcıyı nasıl verimli bir şekilde eğitebilirim?

(@Amoeba tarafından daha sonra düzenleme: bu sorunun orijinal sürümü düzgün çalışmayan Python Tensorflow kodunu içeriyordu. Biri düzenleme geçmişinde bulabilir.)


Layer sınıfının activaction fonksiyonunda bir hata buldum. Şimdi çalışıyorsa test ediyorum
Donbeo

hatasını düzelttin mi?
Pinokyo

Selam Donbeo. Kodu sorunuzdan kaldırma özgürlüğünü kullandım (kod düzenleme geçmişinde yine de kolayca bulunabilir). Kodla birlikte, sorunuz biraz konu dışı olan "türünü bulmama yardım et" sorusuna benziyordu. Aynı zamanda, bu konu 4k görüşe sahip, bu da muhtemelen birçok insanın google aramaları yoluyla geldiği anlamına geliyor, bu yüzden sorunuzu kapatmak istemedim. Bir otomatik kodlayıcı geçişi ile bir cevap göndermeye karar verdim, ancak basitlik nedenleriyle ham Tensorflow yerine Keras (Tensorflow'un üstünde koşarken) kullandım. Bunun Q'nuza cevap verdiğini düşünüyor musunuz?
amip diyor Reinstate Monica

Yanıtlar:


42

İşte Hinton ve Salakhutdinov’un 2006 Bilim raporunda yer alan kilit rakam:

MNIST veri setinin ( tek basamaklı siyah beyaz görüntüler) boyutsallık azalmasını orijinal 784 boyutlarından ikiye indirdiğini göstermektedir .28x28

Hadi çoğaltmaya çalışalım. Doğrudan Tensorflow kullanmayacağım, çünkü Keras'ı (Tensorflow'un üzerinde çalışan üst düzey bir kütüphane) bunun gibi basit derin öğrenme görevleri için kullanmak çok daha kolay. H&S , Kısıtlı Boltzmann Makineleri yığınıyla önceden eğitilmiş lojistik birimlerle mimarisini kullandı. On yıl sonra bu kulağa çok eski geliyor . Herhangi bir ön eğitim olmadan üssel lineer birimlerle daha basit bir mimarisi . Adam optimizer'ı (momentum ile adaptif stokastik gradyan inişinin özel bir uygulaması) kullanacağım.

784100050025022505001000784
7845121282128512784

Kod, bir Jupyter not defterinden kopyalanır. Python 3.6'da matplotlib (pylab için), NumPy, seaborn, TensorFlow ve Keras'ı kurmanız gerekir. Python kabuğunda çalışırken plt.show(), grafikleri göstermek için eklemeniz gerekebilir .

Başlatma

%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)));

Bu çıktılar:

PCA reconstruction error with 2 PCs: 0.056

Otomatik kodlayıcıyı eğitme

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

Bu çalışma masaüstümde yaklaşık 35 saniye sürüyor ve çıktılar:

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

bu nedenle, yalnızca iki eğitim döneminden sonra PCA kaybını aştığımızı görebilirsiniz.

(Bu arada, tüm etkinleştirme işlevlerini değiştirmek activation='linear've kaybın PCA kaybına tam olarak nasıl yaklaştığını gözlemlemek öğreticidir. Bunun nedeni doğrusal otomatik kodlayıcının PCA'ya eşdeğer olmasıdır.)

Darboğaz gösterimi ile birlikte PCA projeksiyonunu yan yana çizmek

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()

görüntü tanımını buraya girin

rekonstrüksiyonlardır

Şimdi yeniden yapılanmalara bakalım (ilk satır - orijinal görüntüler, ikinci satır - PCA, üçüncü satır - otomatik kodlayıcı):

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()

görüntü tanımını buraya girin

Kişi daha derin ağ, biraz düzenli ve daha uzun bir eğitim ile çok daha iyi sonuçlar elde edebilir. Deney. Derin öğrenme kolaydır!


2
PCA'nın sadece 2 bileşenle ne kadar iyi çalıştığına şaşırdım! kodunu gönderdiğiniz için teşekkür ederiz
Aksakal

2
Fantastik! Stupendousness!
Matthew Drury

2
@shadi Aslında svd () basitine doğrudan bir çağrı buluyorum :)
amip

1
Daha fazla bileşen kullanıldığında performans farkı daha da yüksektir. İki yerine 10 tane denedim ve otomatik kodlayıcı çok daha iyiydi. Dezavantajı hız ve hafıza tüketimi
Aksakal

1
python 2 için aşağıdaki ithalatları eklemeniz gerekiyorfrom __future__ import absolute_import from __future__ import division from __future__ import print_function
user2589273

7

Bu harika örnek için @ amoeba için büyük sahne. Ben sadece bu görevde açıklanan otomatik kodlayıcı eğitim ve yeniden yapılandırma prosedürünün benzer bir şekilde R'de de yapılabileceğini göstermek istiyorum. Aşağıdaki otomatik kodlayıcı ayardır, böylece amipanın örneğini mümkün olduğunca yakın öykünür - aynı iyileştirici ve genel mimari. TensorFlow'un arka ucu benzer şekilde ekilmediği için kesin maliyetler tekrarlanamaz.

Bafllatma

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

Autoencoder

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

Darboğaz gösterimi ile birlikte PCA projeksiyonunu yan yana çizmek

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 )

görüntü tanımını buraya girin

rekonstrüksiyonlardır

Rakamların rekonstrüksiyonunu her zamanki gibi yapabiliriz. (Üst sıra orijinal basamaklardır, PCA rekonstrüksiyonunun orta sıra ve otomatik kodlayıcı rekonstrüksiyonun alt sıradır.)

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')
}

görüntü tanımını buraya girin

k0,03560,0359


2
+1. Güzel. Keras'ı R'de Python'da kullanmak kadar basit olduğunu görmek güzel. Görebildiğim kadarıyla, derin öğrenme topluluğunda bugünlerde herkes Python kullanıyor, bu yüzden başka yerlerde daha zor olması gerektiği izlenimini edindim.
amip diyor Reinstate Monica

2

İşte şu farklılıklarıyla sonucunuzu kopyalamaya çalıştığım jupyter defterim:

  • doğrudan tensorflow kullanmak yerine, kerasları görüntülemek için kullanıyorum
  • doygunluğu önlemek için relu yerine sızdıran relu (yani kodlanmış çıkış 0'dır)
    • bu, AE'nin düşük performansının bir nedeni olabilir
  • otomatik kodlayıcı girişi [0,1] olarak ölçeklendirilmiş veridir
    • Sanırım relu'lu otomatik kodlayıcıların [0-1] verilerle en iyi şekilde çalıştığını okudum.
    • dizüstü bilgisayarımı otomatik kodlayıcıların girişinin ortalama = 0, std = 1 olmasıyla çalıştırıyorum, tüm boyutluluk azalmaları için AE> 0.7 için MSE verdi, bu yüzden belki de sorunlarınızdan biri.
  • PCA girişi, ortalama = 0 ve std = 1 ile veri olarak tutulur.
    • Bu aynı zamanda PCA'nın MSE sonucunun PCA'nın MSE sonucuyla karşılaştırılabilir olmadığı anlamına gelebilir
    • Belki bunu daha sonra PCA ve AE için [0-1] verilerle tekrar çalıştırırım.
  • PCA girişi de [0-1] olarak ölçeklendirilir. PCA da (ortalama = 0, std = 1) verilerle çalışır, ancak MSE AE ile karşılaştırılamaz

Benim MSE, PCA'nın 1'den 6'ya boyutsallık azaltmasından (girişin 6 sütunu olduğu) ve AE'den dim'den kaynaklanıyor. kırmızı. 1 ila 6 arasında:

PCA girişi (ortalama = 0, std = 1) iken, AE girişi [0-1] aralığı - 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

Boyutsallık azalması olmayan doğrusal PCA 9e-15'e ulaşabilir, çünkü son bileşene sığamadığı her şeyi itebilir.


vasiliy, dizüstü ithalatı örneğin standart dışı fonksiyonların çok utils.buildNetwork ve utils.ae_fit_encode_plot_mse var gibi görünüyor bir utils paketi ...
Berowne Hlavaty

Bu sadece dizüstü bilgisayar ile aynı düzeyde aynı depodaki bir dosya.
shadi
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.