Stacked Autoencoder

做者:chen_h
微信號 & QQ:862251340
微信公衆號:coderpai
簡書地址:https://www.jianshu.com/p/51d...php




深度學習的威力在於其可以逐層地學習原始數據的多種表達方式。每一層都之前一層的表達特徵爲基礎,抽取出更加抽象,更加適合複雜的特徵,而後作一些分類等任務。python

堆疊自編碼器(Stacked Autoencoder,SAE)實際上就是作這樣的事情,如前面的自編碼器稀疏自編碼器降噪自編碼器都是單個自編碼器,它們經過虛構一個 x -> h -> x 的三層網絡,能過學習出一種特徵變化 h = f(wx+b) 。實際上,當訓練結束後,輸出層已經沒有什麼意義了,咱們通常將其去掉,即將自編碼器表示爲:git

以前之因此將自編碼器模型表示爲3層的神經網絡,那是由於訓練的須要,咱們將原始數據做爲假想的目標輸出,以此構建監督偏差來訓練整個網絡。等訓練結束後,輸出層就能夠去掉了,由於咱們只關心的是從 xh 的變換。算法

接下來的思路就很天然了,咱們已經獲得特徵表達 h ,那麼咱們可不能夠將 h 再做爲原始信息,訓練一個新的自編碼器,獲得新的特徵表達呢?當軟能夠,並且這就是所謂的堆疊自編碼器(Stacked Autoencoder,SAE)。Stacked 就是逐層堆疊的意思,這個跟「棧」有點像。當把多個自編碼器 Stack 起來以後,這個系統看起來就像這樣:微信

這樣就把自編碼器改爲了深度結構了,即 learning multiple levels of representation and abstraction (Hinton, Bengio, LeCun, 2015)。須要注意的是,整個網絡的訓練不是一蹴而就的,而是逐層進行的。好比說咱們要訓練一個 n -> m -> k 結構的網絡,實際上咱們是先訓練網絡 n -> m -> n ,獲得 n -> m 的變換,而後再訓練 m -> k -> m 網絡,獲得 m -> k 的變換。最終堆疊成 SAE ,即爲 n -> m -> k 的結果,整個過程就像一層層往上面蓋房子,這就是大名鼎鼎的 layer-wise unsuperwised pre-training (逐層非監督預訓練)。網絡

接下來咱們來看一個具體的例子,假設你想要訓練一個包含兩個隱藏層的堆疊自編碼器,用來訓練 MNIST 手寫數字分類。dom

首先,你須要用原始輸入 x(k) 訓練第一個稀疏自編碼器中,它可以學習獲得原始輸入的一階特徵表示 h(1)(k),以下圖所示:學習

接着,你須要把原始數據輸入到上述訓練好的稀疏自編碼器中,對於每個輸入 x(k) ,均可以獲得它對應的一階特徵表示 h(1)(k) 。而後你再用這些一階特徵做爲另外一個稀疏自編碼器的輸入,使用它們來學習二階特徵 h(2)(k) ,以下圖:編碼

一樣,再把一階特徵輸入到剛訓練好的第二層稀疏自編碼器中,獲得每一個 h(1)(k) 對應的二階特徵激活值 h(2)(k) 。接下來,你能夠把這些二階特徵做爲 softmax 分類器的輸入,訓練獲得一個能將二階特徵映射到數字標籤的模型。以下圖:人工智能

最終,你能夠將這三層結合起來構建一個包含兩個隱藏層和一個最終 softmax 分類器層的堆疊自編碼網絡,這個網絡可以如你所願地對 MNIST 數據集進行分類。最終模型以下圖:

實驗代碼以下:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import tensorflow as tf 
import numpy as np
import input_data


N_INPUT = 28*28
N_HIDDEN_1 = 1000
N_OUTPUT_1 = N_INPUT
N_HIDDEN_2 = 1500
N_OUTPUT_2 = N_HIDDEN_1
N_OUTPUT = 10
BATCH_SIZE = 16 0
EPOCHES = 10
RHO = .1
BETA = tf.constant(3.0)
LAMBDA = tf.constant(.0001)

w_model_one_init = np.sqrt(6. / (N_INPUT + N_HIDDEN_1))

model_one_weights = {
    "hidden": tf.Variable(tf.random_uniform([N_INPUT, N_HIDDEN_1], minval = -w_model_one_init, maxval = w_model_one_init)),
    "out": tf.Variable(tf.random_uniform([N_HIDDEN_1, N_OUTPUT_1], minval = -w_model_one_init, maxval = w_model_one_init))
}
model_one_bias = {
    "hidden": tf.Variable(tf.random_uniform([N_HIDDEN_1], minval = -w_model_one_init, maxval = w_model_one_init)),
    "out": tf.Variable(tf.random_uniform([N_OUTPUT_1], minval = -w_model_one_init, maxval = w_model_one_init))
}

w_model_two_init = np.sqrt(6. / (N_HIDDEN_1 + N_HIDDEN_2))

model_two_weights = {
    "hidden": tf.Variable(tf.random_uniform([N_HIDDEN_1, N_HIDDEN_2], minval = -w_model_two_init, maxval = w_model_two_init)),
    "out": tf.Variable(tf.random_uniform([N_HIDDEN_2, N_OUTPUT_2], minval = -w_model_two_init, maxval = w_model_two_init))
}
model_two_bias = {
    "hidden": tf.Variable(tf.random_uniform([N_HIDDEN_2], minval = -w_model_two_init, maxval = w_model_two_init)),
    "out": tf.Variable(tf.random_uniform([N_OUTPUT_2], minval = -w_model_two_init, maxval = w_model_two_init))
}

w_model_init = np.sqrt(6. / (N_HIDDEN_2 + N_OUTPUT))

model_weights = {
    "out": tf.Variable(tf.random_uniform([N_HIDDEN_2, N_OUTPUT], minval = -w_model_init, maxval = w_model_init))
}
model_bias = {
    "out": tf.Variable(tf.random_uniform([N_OUTPUT], minval = -w_model_init, maxval = w_model_init))
}


model_one_X = tf.placeholder("float", [None, N_INPUT])
model_two_X = tf.placeholder("float", [None, N_HIDDEN_1])
Y = tf.placeholder("float", [None, N_OUTPUT])

def model_one(X):
    hidden = tf.sigmoid(tf.add(tf.matmul(X, model_one_weights["hidden"]), model_one_bias["hidden"]))
    out = tf.sigmoid(tf.add(tf.matmul(hidden, model_one_weights["out"]), model_one_bias["out"]))
    return [hidden, out]

def model_two(X):
    hidden = tf.sigmoid(tf.add(tf.matmul(X, model_two_weights["hidden"]), model_two_bias["hidden"]))
    out = tf.sigmoid(tf.add(tf.matmul(hidden, model_two_weights["out"]), model_two_bias["out"]))
    return [hidden, out]

def model(X):
    hidden_1 = tf.sigmoid(tf.add(tf.matmul(X, model_one_weights["hidden"]), model_one_bias["hidden"]))
    hidden_2 = tf.sigmoid(tf.add(tf.matmul(hidden_1, model_two_weights["hidden"]), model_two_bias["hidden"]))
    out = tf.add(tf.matmul(hidden_2, model_weights["out"]), model_bias["out"])
    return out

def KLD(p, q):
    invrho = tf.sub(tf.constant(1.), p)
    invrhohat = tf.sub(tf.constant(1.), q)
    addrho = tf.add(tf.mul(p, tf.log(tf.div(p, q))), tf.mul(invrho, tf.log(tf.div(invrho, invrhohat))))
    return tf.reduce_sum(addrho)

mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)
trX, trY, teX, teY = mnist.train.images, mnist.train.labels, mnist.test.images, mnist.test.labels

# model one
model_one_hidden, model_one_out = model_one(model_one_X)
# loss
model_one_cost_J = tf.reduce_sum(tf.pow(tf.sub(model_one_out, model_one_X), 2))
# cost sparse
model_one_rho_hat = tf.div(tf.reduce_sum(model_one_hidden), N_HIDDEN_1)
model_one_cost_sparse = tf.mul(BETA, KLD(RHO, model_one_rho_hat))
# cost reg
model_one_cost_reg = tf.mul(LAMBDA, tf.add(tf.nn.l2_loss(model_one_weights["hidden"]), tf.nn.l2_loss(model_one_weights["out"])))
# cost function
model_one_cost = tf.add(tf.add(model_one_cost_J, model_one_cost_reg), model_one_cost_sparse)
train_op_1 = tf.train.AdamOptimizer().minimize(model_one_cost)
# =======================================================================================

# model two
model_two_hidden, model_two_out = model_two(model_two_X)
# loss
model_two_cost_J = tf.reduce_sum(tf.pow(tf.sub(model_two_out, model_two_X), 2))
# cost sparse
model_two_rho_hat = tf.div(tf.reduce_sum(model_two_hidden), N_HIDDEN_2)
model_two_cost_sparse = tf.mul(BETA, KLD(RHO, model_two_rho_hat))
# cost reg
model_two_cost_reg = tf.mul(LAMBDA, tf.add(tf.nn.l2_loss(model_two_weights["hidden"]), tf.nn.l2_loss(model_two_weights["out"])))
# cost function
model_two_cost = tf.add(tf.add(model_two_cost_J, model_two_cost_reg), model_two_cost_sparse)
train_op_2 = tf.train.AdamOptimizer().minimize(model_two_cost)
# =======================================================================================

# final model
model_out = model(model_one_X)
cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(model_out, Y))
train_op = tf.train.RMSPropOptimizer(0.001, 0.9).minimize(cost)
predict_op = tf.argmax(model_out, 1)
# =======================================================================================


with tf.Session() as sess:

    init = tf.initialize_all_variables()
    sess.run(init)

    for i in xrange(EPOCHES):
        for start, end in zip(range(0, len(trX), BATCH_SIZE), range(BATCH_SIZE, len(trX), BATCH_SIZE)):
            input_ = trX[start:end]
            sess.run(train_op_1, feed_dict = {model_one_X: input_})
    print 'finish model one ...'

    for i in xrange(EPOCHES):
        for start, end in zip(range(0, len(trX), BATCH_SIZE), range(BATCH_SIZE, len(trX), BATCH_SIZE)):
            input_ = trX[start:end]
            input_ = sess.run(tf.sigmoid(tf.add(tf.matmul(input_, model_one_weights["hidden"]), model_one_bias["hidden"])))
            sess.run(train_op_2, feed_dict = {model_two_X: input_})
    print 'finish model two ...'

    for i in xrange(EPOCHES):
        for start, end in zip(range(0, len(trX), BATCH_SIZE), range(BATCH_SIZE, len(trX), BATCH_SIZE)):
            input_ = trX[start:end]
            sess.run(train_op, feed_dict = {model_one_X: input_, Y: trY[start:end]})

        print i, np.mean(np.argmax(teY, axis = 1) == sess.run(predict_op, feed_dict = {model_one_X: teX, Y: teY}))

    print 'finish model ...'
    print np.mean(np.argmax(teY, axis = 1) == sess.run(predict_op, feed_dict = {model_one_X: teX, Y: teY}))

Reference:

UFLDL

知乎


做者:chen_h
微信號 & QQ:862251340
簡書地址:https://www.jianshu.com/p/51d...

CoderPai 是一個專一於算法實戰的平臺,從基礎的算法到人工智能算法都有設計。若是你對算法實戰感興趣,請快快關注咱們吧。加入AI實戰微信羣,AI實戰QQ羣,ACM算法微信羣,ACM算法QQ羣。長按或者掃描以下二維碼,關注 「CoderPai」 微信號(coderpai)
圖片描述


圖片描述

相關文章
相關標籤/搜索