原來有時神經網絡要接受大量的輸入信息, 比如輸入信息是高清圖片時, 輸入信息量可能達到上千萬, 讓神經網絡直接從上千萬個信息源中學習是一件很吃力的工作. 所以, 何不壓縮一下, 提取出原圖片中的最具代表性的信息, 縮減輸入信息量, 再把縮減過後的信息放進神經網絡學習. 這樣學習起來就簡單輕鬆了. 所以, 自編碼就能在這時發揮作用. 通過將原數據白色的X 壓縮, 解壓 成黑色的X, 然後通過對比黑白 X ,求出預測誤差, 進行反向傳遞, 逐步提升自編碼的準確性. 訓練好的自編碼中間這一部分就是能總結原數據的精髓. 可以看出, 從頭到尾, 我們只用到了輸入數據 X, 並沒有用到 X 對應的數據標籤, 所以也可以說自編碼是一種非監督學習. 到了真正使用自編碼的時候. 通常只會用到自編碼前半部分.
Autoencoder 簡單來說就是將有很多Feature的數據進行壓縮,之後再進行解壓的過程。 本質上來說,它也是一個對數據的非監督學習,如果大家知道 PCA (Principal component analysis), 與 Autoencoder 相類似,它的主要功能即對數據進行非監督學習,並將壓縮之後得到的“特徵值”,這一中間結果正類似於PCA的結果。 之後再將壓縮過的“特徵值”進行解壓,得到的最終結果與原始數據進行比較,對此進行非監督學習。
今天的代碼,我們會運用兩個類型:
- 第一,是通過Feature的壓縮並解壓,並將結果與原始數據進行對比,觀察處理過後的數據是不是如預期跟原始數據很相像。(這裡會用到MNIST數據)
- 第二,我們只看 encoder 壓縮的過程,使用它將一個數據集壓縮到只有兩個Feature時,將數據放入一個二維座標系內.
第一:
import tensorflow as tf import numpy as np import matplotlib.pyplot as plt from tensorflow.examples.tutorials.mnist import input_data learning_rate = 0.01 training_epochs = 20 batch_size = 256 example_image_show = 10 mnist = input_data.read_data_sets('MNIST_data', one_hot=True) n_input = 28*28 n_hidden_1 = 256 n_hidden_2 = 128 weights = { 'encode_1': tf.Variable(tf.random.normal([n_input, n_hidden_1])), 'encode_2': tf.Variable(tf.random.normal([n_hidden_1, n_hidden_2])), 'decode_1': tf.Variable(tf.random.normal([n_hidden_2, n_hidden_1])), 'decode_2': tf.Variable(tf.random.normal([n_hidden_1, n_input])) } bais = { 'encode_1': tf.Variable(tf.random.normal([n_hidden_1])), 'encode_2': tf.Variable(tf.random.normal([n_hidden_2])), 'decode_1': tf.Variable(tf.random.normal([n_hidden_1])), 'decode_2': tf.Variable(tf.random.normal([n_input])) } def encode(x): layer1 = tf.nn.sigmoid(tf.matmul(x, weights['encode_1']) + bais['encode_1']) layer2 = tf.nn.sigmoid(tf.matmul(layer1, weights['encode_2']) + bais['encode_2']) return layer2 def decode(x): layer1 = tf.nn.sigmoid(tf.matmul(x, weights['decode_1']) + bais['decode_1']) layer2 = tf.nn.sigmoid(tf.matmul(layer1, weights['decode_2']) + bais['decode_2']) return layer2 x = tf.placeholder(tf.float32, shape=[None, n_input]) encode_op = encode(x) decode_op = decode(encode_op) y_pred = decode_op y_true = x cost = tf.reduce_mean(tf.pow(y_true - y_pred, 2)) train_op = tf.train.AdamOptimizer(learning_rate).minimize(cost) re_loss = [] with tf.Session() as sess: sess.run(tf.global_variables_initializer()) batch = int(mnist.train.num_examples/batch_size) for i in range(training_epochs): mean_loss = 0 for j in range(batch): batch_x, _ = mnist.train.next_batch(batch_size) feed = {x:batch_x} _, ls = sess.run([train_op, cost], feed_dict=feed) mean_loss += ls re_loss.append(mean_loss / batch) plt.plot(np.linspace(0, training_epochs, training_epochs), re_loss, c='red') plt.show() plt.figure(2) auto_y = sess.run(decode_op, feed_dict={x: mnist.test.images[:example_image_show]}) f, ax = plt.subplots(2, 10, figsize=(10, 2)) for i in range(example_image_show): ax[0][i].imshow(np.reshape(mnist.test.images[i], [28, 28])) ax[1][i].imshow(np.reshape(auto_y[i], [28, 28])) plt.show()
第二: 我們只顯示 encoder 之後的數據, 並畫在一個二維直角座標系內。做法很簡單,我們將原有 784 Features 的數據壓縮成僅剩 2 Features 的數據:
import tensorflow as tf import numpy as np import matplotlib.pyplot as plt from tensorflow.examples.tutorials.mnist import input_data learning_rate = 0.01 batch_size = 256 training_epoch = 10 mnist = input_data.read_data_sets("MNIST_data", one_hot=True) print(np.argmax(mnist.test.labels, axis=1).shape) n_inputs = 28*28 n_hidden_1 = 128 n_hidden_2 = 64 n_hidden_3 = 10 n_hidden_4 = 2 weight = { 'encoder_1': tf.Variable(tf.random.normal([n_inputs, n_hidden_1])), 'encoder_2': tf.Variable(tf.random.normal([n_hidden_1, n_hidden_2])), 'encoder_3': tf.Variable(tf.random.normal([n_hidden_2, n_hidden_3])), 'encoder_4': tf.Variable(tf.random.normal([n_hidden_3, n_hidden_4])), 'decoder_1': tf.Variable(tf.random.normal([n_hidden_4, n_hidden_3])), 'decoder_2': tf.Variable(tf.random.normal([n_hidden_3, n_hidden_2])), 'decoder_3': tf.Variable(tf.random.normal([n_hidden_2, n_hidden_1])), 'decoder_4': tf.Variable(tf.random.normal([n_hidden_1, n_inputs])) } bais = { 'encoder_1': tf.Variable(tf.random.normal([n_hidden_1])), 'encoder_2': tf.Variable(tf.random.normal([n_hidden_2])), 'encoder_3': tf.Variable(tf.random.normal([n_hidden_3])), 'encoder_4': tf.Variable(tf.random.normal([n_hidden_4])), 'decoder_1': tf.Variable(tf.random.normal([n_hidden_3])), 'decoder_2': tf.Variable(tf.random.normal([n_hidden_2])), 'decoder_3': tf.Variable(tf.random.normal([n_hidden_1])), 'decoder_4': tf.Variable(tf.random.normal([n_inputs])), } def encoder(x): l1 = tf.nn.sigmoid(tf.matmul(x, weight['encoder_1']) + bais['encoder_1']) l2 = tf.nn.sigmoid(tf.matmul(l1, weight['encoder_2']) + bais['encoder_2']) l3 = tf.nn.sigmoid(tf.matmul(l2, weight['encoder_3']) + bais['encoder_3']) l4 = tf.nn.sigmoid(tf.matmul(l3, weight['encoder_4']) + bais['encoder_4']) return l4 def decoder(x): l1 = tf.nn.sigmoid(tf.matmul(x, weight['decoder_1']) + bais['decoder_1']) l2 = tf.nn.sigmoid(tf.matmul(l1, weight['decoder_2']) + bais['decoder_2']) l3 = tf.nn.sigmoid(tf.matmul(l2, weight['decoder_3']) + bais['decoder_3']) l4 = tf.nn.sigmoid(tf.matmul(l3, weight['decoder_4']) + bais['decoder_4']) return l4 x = tf.placeholder(tf.float32, shape=[None, n_inputs]) encoder_op = encoder(x) decoder_op = decoder(encoder_op) y_pred = decoder_op y_true = x cost = tf.reduce_mean(tf.square(y_true - y_pred)) train_op = tf.train.AdamOptimizer(learning_rate).minimize(cost) with tf.Session() as sess: sess.run(tf.global_variables_initializer()) batchs = int(mnist.train.num_examples/batch_size) re_ls = [] for i in range(training_epoch): mean_ls = 0 for j in range(batchs): batch_xs, _ = mnist.train.next_batch(batch_size) feed = {x: batch_xs} _, ls = sess.run([train_op, cost], feed_dict=feed) mean_ls += ls re_ls.append(mean_ls/batchs) plt.plot(np.linspace(0, training_epoch, training_epoch), re_ls, c='red') plt.show() ## 觀測編碼原始數據 與 原始數據標籤 構成的二維圖 encoder_result = sess.run(encoder_op, feed_dict={x: mnist.test.images}) print(mnist.test.labels.shape) plt.scatter(encoder_result[:, 0], encoder_result[:, 1], c=np.argmax(mnist.test.labels, axis=1)) plt.colorbar() plt.show()