原来有时神经网络要接受大量的输入信息, 比如输入信息是高清图片时, 输入信息量可能达到上千万, 让神经网络直接从上千万个信息源中学习是一件很吃力的工作. 所以, 何不压缩一下, 提取出原图片中的最具代表性的信息, 缩减输入信息量, 再把缩减过后的信息放进神经网络学习. 这样学习起来就简单轻松了. 所以, 自编码就能在这时发挥作用. 通过将原数据白色的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()
關鍵字: n_hidden_1 非监督学习 特征值