पीसीए को पार करने के लिए टेन्सरफ्लो में एक ऑटोएन्कोडर का निर्माण


31

न्यूरल नेटवर्क्स के साथ डेटा की आयामीता को कम करने में हिंटन और सलाखुद्दीनोव , विज्ञान 2006 ने एक गहन ऑटोएन्कोडर के उपयोग के माध्यम से एक गैर-रैखिक पीसीए का प्रस्ताव किया। मैंने कई बार Tensorflow के साथ PCA autoencoder बनाने और प्रशिक्षित करने की कोशिश की है लेकिन मैं रैखिक PCA से बेहतर परिणाम प्राप्त करने में कभी सक्षम नहीं रहा।

मैं कुशलता से एक ऑटोसेंकर को कैसे प्रशिक्षित कर सकता हूं?

(बाद में @amoeba द्वारा संपादित करें: इस प्रश्न के मूल संस्करण में पायथन टेंसोरफ़्लो कोड था जो सही ढंग से काम नहीं करता था। कोई इसे संपादित इतिहास में पा सकता है।)


मुझे लेयर वर्ग के सक्रियण समारोह में एक त्रुटि मिली है। मैं परीक्षण कर रहा हूं कि क्या अब यह काम कर रहा है
डोनोबो

क्या आपने अपनी त्रुटि ठीक की?
पिनोच्चियो

हाय डोनबियो। मैंने आपके प्रश्न से कोड हटाने के लिए स्वतंत्रता ले ली (संपादन इतिहास में कोड अभी भी आसानी से पाया जा सकता है)। कोड के साथ, आपका प्रश्न थोड़ा सा लग रहा था जैसे "मुझे एक बग ढूंढने में मदद करें" प्रकार का प्रश्न जो यहां ऑफ टॉपिक है। इसी समय, इस धागे के 4k विचार हैं, शायद इसका अर्थ है कि बहुत से लोग Google खोजों के माध्यम से यहां आते हैं, इसलिए मैं आपके प्रश्न को बंद नहीं करना चाहता था। मैंने एक ऑटोएन्कोडर वॉक-थ्रू के साथ एक उत्तर पोस्ट करने का फैसला किया, लेकिन सादगी के कारणों के लिए मैंने कच्चे टेंसरफ़्लो के बजाय केरस (टेन्सरफ़्लो के ऊपर चल रहा है) का इस्तेमाल किया। क्या आपको लगता है कि यह आपके प्रश्न का उत्तर देता है?
अमीबा का कहना है कि मोनिका

जवाबों:


42

हिंटन और सलाखुद्दीनोव द्वारा 2006 के विज्ञान पत्र के प्रमुख चित्र इस प्रकार हैं:

यह मूल 784 आयामों से दो तक MNIST डेटासेट ( एकल अंकों की 28 \ _ 2828×28 काली और सफेद छवियों) की गतिशीलता में कमी को दर्शाता है ।

आइए इसे पुन: पेश करने का प्रयास करें। मैं सीधे Tensorflow का उपयोग नहीं करूँगा, क्योंकि इस तरह के सरल गहन शिक्षण कार्यों के लिए Keras (Tensorflow के शीर्ष पर चल रहा एक उच्च-स्तरीय पुस्तकालय) का उपयोग करना बहुत आसान है। H & S ने उपयोग आर्किटेक्चर लॉजिस्टिक यूनिट्स के साथ पूर्व-प्रशिक्षित प्रतिबंधित बोल्ट्जमैन मशीनों के ढेर के साथ प्रशिक्षित किया। दस साल बाद, यह बहुत पुराना स्कूल लगता है । मैं बिना किसी पूर्व-प्रशिक्षण के घातीय रेखीय इकाइयों के साथ वास्तुकला का उपयोग करूँगा । मैं एडम ऑप्टिमाइज़र (गति के साथ अनुकूली स्टोचस्टिक ढाल वंश का एक विशेष कार्यान्वयन) का उपयोग करूंगा।

784100050025022505001000784
7845121282128512784

कोड ज्यूपिटर नोटबुक से कॉपी-पेस्ट किया जाता है। Python 3.6 में आपको matplotlib (pylab के लिए), NumPy, seaborn, TensorFlow और Keras स्थापित करने की आवश्यकता है। पायथन शेल में दौड़ते समय, आपको 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

पीसीए

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

इसलिए आप पहले से ही देख सकते हैं कि हमने केवल दो प्रशिक्षण युगों के बाद पीसीए नुकसान को पार कर लिया है।

(वैसे, यह सभी सक्रियण कार्यों को बदलने और यह देखने के लिए निर्देश है activation='linear'कि नुकसान पीसीए हानि में कैसे परिवर्तित होता है। ऐसा इसलिए है क्योंकि रैखिक ऑटोएन्कोडर पीसीए के बराबर है।)

टोंटी प्रतिनिधित्व के साथ पीसीए प्रक्षेपण पक्ष की ओर से प्लॉटिंग

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

यहाँ छवि विवरण दर्ज करें

पुनर्निर्माण

और अब आइए पुनर्निर्माण को देखें (पहली पंक्ति - मूल चित्र, दूसरी पंक्ति - पीसीए, तीसरी पंक्ति - ऑटोएन्कोडर):

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
मुझे आश्चर्य है कि पीसीए ने सिर्फ 2 घटकों के साथ कितना अच्छा काम किया! धन्यवाद कोड पोस्ट करने के लिए
Aksakal

2
विलक्षण! Stupendousness!
मैथ्यू ड्र्यू

2
@ शदी मैं वास्तव में svd () को सरलता से कहता हूं :)
अमीबा का कहना है कि मोनिका

1
अधिक घटकों का उपयोग करने पर प्रदर्शन भिन्नता और भी अधिक होती है। मैंने दो के बजाय 10 की कोशिश की और ऑटोकेनोडर ज्यादा बेहतर था। नुकसान गति और स्मृति की खपत है
अक्कल १५'१

1
अजगर 2 के लिए आपको निम्नलिखित आयातों को जोड़ने की आवश्यकता हैfrom __future__ import absolute_import from __future__ import division from __future__ import print_function
user2589273

7

इस महान उदाहरण को बनाने के लिए विशाल ने @amoeba को सहारा दिया। मैं बस यह बताना चाहता हूं कि उस पोस्ट में वर्णित ऑटो-एनकोडर प्रशिक्षण और पुनर्निर्माण प्रक्रिया को भी समान आसानी से आर में किया जा सकता है। नीचे दिया गया ऑटो-एनकोडर सेटअप है इसलिए यह अमीबा के उदाहरण का यथासंभव अनुकरण करता है - समान आशावादी और समग्र वास्तुकला। TensorFlow बैक-एंड के समान बीज नहीं होने के कारण सटीक लागत प्रजनन योग्य नहीं है।

initialisation

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

पीसीए

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

टोंटी प्रतिनिधित्व के साथ पीसीए प्रक्षेपण पक्ष की ओर से प्लॉटिंग

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 )

यहाँ छवि विवरण दर्ज करें

पुनर्निर्माण

हम सामान्य तरीके से अंकों का पुनर्निर्माण कर सकते हैं। (शीर्ष पंक्ति मूल अंक हैं, मध्य पंक्ति पीसीए पुनर्निर्माण और नीचे पंक्ति ऑटोकारोडर पुनर्निर्माण)।

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

यहाँ छवि विवरण दर्ज करें

जैसा कि उल्लेख किया गया है, अधिक युग और एक गहरा और / या अधिक चालाकी से प्रशिक्षित नेटवर्क बेहतर परिणाम देगा। उदाहरण के लिए, = 9 का पीसीए पुनर्निर्माण त्रुटि लगभग , हम ऊपर वर्णित ऑटोकेन्डर से लगभग एक ही त्रुटि ( ) प्राप्त कर सकते हैं , बस प्रशिक्षण युग को 5 से बढ़ाकर 25 कर सकते हैं। इस उपयोग-मामले में, 2 ऑटोएन्कोडर-व्युत्पन्न घटक 9 प्रमुख घटकों के समान पुनर्निर्माण त्रुटि प्रदान करेगा। ठंडा!k0.03560.0359


2
+1। अच्छा लगा। यह देखना अच्छा है कि आर में केरस का उपयोग करना उतना ही सरल है जितना कि पायथन में। जहां तक ​​मैं देख सकता हूं, गहन शिक्षण समुदाय में इन दिनों हर कोई पायथन का उपयोग कर रहा है, इसलिए मैं इस धारणा के तहत था कि यह कहीं और कठिन होना चाहिए।
अमीबा का कहना है कि मोनिका

2

यहां मेरा जपयटर नोटबुक है जहां मैं निम्नलिखित अंतरों के साथ आपके परिणाम को दोहराने की कोशिश करता हूं:

  • सीधे टेंसरफ़्लो का उपयोग करने के बजाय, मैं इसका उपयोग केर को देखने के लिए करता हूं
  • संतृप्ति से बचने के लिए रिले के बजाय टपका हुआ रिले (यानी एन्कोडेड आउटपुट 0 हो रहा है)
    • यह एई के खराब प्रदर्शन का एक कारण हो सकता है
  • Autoencoder इनपुट डेटा को 0,1 पर स्केल किया गया है
    • मुझे लगता है कि मैंने कहीं पढ़ा है कि रिले के साथ ऑटोएन्कोडर्स [0-1] डेटा के साथ सबसे अच्छा काम करते हैं
    • मेरे नोटबुक को ऑटोएन्कोडर्स इनपुट के साथ चलाने का मतलब है = 0, std = 1 ने MSE को AE> 0.7 के लिए सभी आयामी कटौती के लिए दिया, तो शायद यह आपकी समस्याओं में से एक है।
  • PCA इनपुट को माध्य = 0 और std = 1 के साथ डेटा रखा जा रहा है
    • इसका मतलब यह भी हो सकता है कि पीसीए का एमएसई परिणाम पीसीए के एमएसई परिणाम के लिए तुलनीय नहीं है
    • हो सकता है कि मैं इसे बाद में पीसीए और एई दोनों के लिए [0-1] डेटा के साथ फिर से चलाऊं
  • PCA इनपुट भी [0-1] तक बढ़ाया जाता है। PCA (माध्य = 0, std = 1) डेटा के साथ भी काम करता है, लेकिन MSE AE के लिए अतुलनीय होगा

पीसीए के लिए मेरा एमएसई परिणाम 1 से 6 की आयामीता में कमी (जहां इनपुट में 6 कॉलम हैं) और एई के लिए मंद है। लाल। 1 से 6 नीचे हैं:

पीसीए इनपुट होने के साथ (मतलब = 0, एसटीडी = 1) जबकि एई इनपुट [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: पीसीए 5
  • .0502: AE5
  • .0507: AE6
  • .0514: AE4
  • .0532: AE3
  • .0772: पीसीए 4
  • .1231: पीसीए 3
  • .2588: AE2
  • .2831: पीसीए 2
  • .3773: AE1
  • .3885: पीसीए 1

रैखिक पीसीए बिना किसी आयाम की कमी के 9e-15 को प्राप्त कर सकता है क्योंकि यह केवल अंतिम घटक में फिट होने में असमर्थ होने पर धक्का दे सकता है।


shadi, आपकी नोटबुक एक ऐसे बर्तन पैकेज का आयात करती है जो लगता है कि बहुत सारे गैर-मानक फ़ंक्शंस utils.buildNetwork और utils.ae_fit_encode_plot_mse उदाहरण के लिए हैं ...
Berowne Hlavatia

यह नोटबुक के समान स्तर पर समान भंडार में सिर्फ एक फ़ाइल है।
shadi
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.