Đây là con số chính từ bài báo Khoa học năm 2006 của Hinton và Salakhutdinov:
Nó cho thấy giảm kích thước của bộ dữ liệu MNIST ( 28 × 28 hình ảnh đen trắng của các chữ số đơn) từ kích thước 784 ban đầu xuống còn hai.
Hãy thử tái tạo nó. Tôi sẽ không trực tiếp sử dụng Tensorflow, bởi vì việc sử dụng Keras (một thư viện cấp cao hơn chạy trên đỉnh Tensorflow) dễ dàng hơn nhiều cho các nhiệm vụ học sâu đơn giản như thế này. H & S đã sử dụng kiến trúc với các đơn vị logistic, được đào tạo trước với ngăn xếp của Máy Boltzmann bị hạn chế. Mười năm sau, trường này nghe có vẻ rất cũ. Tôi sẽ sử dụng đơn giản hơn 784 → 512 → 128 → 2 → 128 → 512
784 → 1000 → 500 → 250 → 2 → 250 → 500 → 1000 → 784
Kiến trúc
784 với các đơn vị tuyến tính theo cấp số nhân mà không cần đào tạo trước. Tôi sẽ sử dụng trình tối ưu hóa Adam (một triển khai cụ thể của việc giảm độ dốc ngẫu nhiên thích ứng với động lượng).
784 → 512 → 128 → 2 → 128 → 512 → 784
Mã này được sao chép từ một máy tính xách tay Jupyter. Trong Python 3.6, bạn cần cài đặt matplotlib (cho pylab), NumPy, seaborn, TensorFlow và Keras. Khi chạy trong shell Python, bạn có thể cần thêm plt.show()
để hiển thị các ô.
Khởi tạo
%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)));
Kết quả này:
PCA reconstruction error with 2 PCs: 0.056
Đào tạo bộ mã hóa tự động
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
Quá trình này mất ~ 35 giây trên màn hình làm việc và kết quả đầu ra của tôi:
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
vì vậy bạn có thể thấy rằng chúng tôi đã vượt qua mất PCA chỉ sau hai kỷ nguyên đào tạo.
(Nhân tiện, hướng dẫn thay đổi tất cả các chức năng kích hoạt thành activation='linear'
và quan sát cách thức tổn thất hội tụ chính xác với tổn thất PCA. Đó là vì bộ tự động tuyến tính tương đương với PCA.)
Vẽ kế hoạch chiếu PCA cạnh nhau với biểu diễn nút cổ chai
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()
Tái thiết
Và bây giờ, hãy nhìn vào các bản dựng lại (hàng đầu tiên - hình ảnh gốc, hàng thứ hai - PCA, hàng thứ ba - autoencoder):
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()
Người ta có thể thu được kết quả tốt hơn nhiều với mạng lưới sâu hơn, một số chính quy và đào tạo lâu hơn. Thí nghiệm. Học sâu thật dễ!