ไม่สามารถทำให้ฟังก์ชั่นเครือข่าย autoencoder นี้ถูกต้อง (กับชั้น convolutional และ maxpool)


9

เครือข่ายAutoencoderดูเหมือนจะมีความซับซ้อนกว่าเครือข่าย MLP ลักษณนามทั่วไป หลังจากความพยายามหลายครั้งในการใช้Lasagneทุกสิ่งที่ฉันได้รับในผลลัพธ์ที่สร้างขึ้นใหม่นั้นเป็นสิ่งที่คล้ายกับค่าเฉลี่ยที่เบลอที่สุดของภาพทั้งหมดของฐานข้อมูลMNISTโดยไม่แยกแยะว่าตัวเลขที่ป้อนเข้านั้นคืออะไร

โครงสร้างเครือข่ายที่ฉันเลือกคือเลเยอร์น้ำตกต่อไปนี้:

  1. ชั้นอินพุต (28x28)
  2. 2D convolutional layer ขนาดตัวกรอง 7x7
  3. Max Pooling layer, ขนาด 3x3, stride 2x2
  4. ชั้นแบนราบหนาแน่น (เชื่อมต่ออย่างเต็มที่) 10 ยูนิต (นี่คือคอขวด)
  5. ชั้นหนาแน่น (เชื่อมต่ออย่างเต็มที่) 121 หน่วย
  6. ปรับขนาดเลเยอร์เป็น 11x11
  7. 2D convolutional layer ขนาดตัวกรอง 3x3
  8. ตัวคูณยกระดับ 2D 2
  9. 2D convolutional layer ขนาดตัวกรอง 3x3
  10. ตัวคูณยกระดับ 2D 2
  11. 2D convolutional layer ขนาดตัวกรอง 5x5
  12. การรวมกำไรสูงสุด (จาก 31x28x28 ถึง 28x28)

เลเยอร์ 2 มิติทั้งหมดมีอคติผูกมัด, การเปิดใช้งาน sigmoid และตัวกรอง 31 ตัว

เลเยอร์ที่เชื่อมต่อทั้งหมดมีการเปิดใช้งาน sigmoid

ฟังก์ชั่นการสูญเสียที่ใช้เป็นข้อผิดพลาดยกกำลังสองadagradฟังก์ชั่นการอัพเดท ความยาวของก้อนสำหรับการเรียนรู้คือ 100 ตัวอย่างคูณด้วย 1,000 epochs

ต่อไปนี้เป็นภาพประกอบของปัญหา: แถวบนคือตัวอย่างบางส่วนที่ตั้งค่าเป็นอินพุตของเครือข่ายแถวล่างคือการสร้างใหม่:

อินพุตและเอาต์พุต autoencoder

เพียงเพื่อความสมบูรณ์ต่อไปนี้เป็นรหัสที่ฉันใช้:

import theano.tensor as T
import theano
import sys
sys.path.insert(0,'./Lasagne') # local checkout of Lasagne
import lasagne
from theano import pp
from theano import function
import gzip
import numpy as np
from sklearn.preprocessing import OneHotEncoder
import matplotlib.pyplot as plt
def load_mnist():

    def load_mnist_images(filename):
        with gzip.open(filename, 'rb') as f:
            data = np.frombuffer(f.read(), np.uint8, offset=16)
        # The inputs are vectors now, we reshape them to monochrome 2D images,
        # following the shape convention: (examples, channels, rows, columns)
        data = data.reshape(-1, 1, 28, 28)
        # The inputs come as bytes, we convert them to float32 in range [0,1].
        # (Actually to range [0, 255/256], for compatibility to the version
        # provided at http://deeplearning.net/data/mnist/mnist.pkl.gz.)
        return data / np.float32(256)

    def load_mnist_labels(filename):
        # Read the labels in Yann LeCun's binary format.
        with gzip.open(filename, 'rb') as f:
            data = np.frombuffer(f.read(), np.uint8, offset=8)
        # The labels are vectors of integers now, that's exactly what we want.
        return data

    X_train = load_mnist_images('train-images-idx3-ubyte.gz')
    y_train = load_mnist_labels('train-labels-idx1-ubyte.gz')
    X_test = load_mnist_images('t10k-images-idx3-ubyte.gz')
    y_test = load_mnist_labels('t10k-labels-idx1-ubyte.gz')
    return X_train, y_train, X_test, y_test

def plot_filters(conv_layer):
    W = conv_layer.get_params()[0]
    W_fn = theano.function([],W)
    params = W_fn()
    ks = np.squeeze(params)
    kstack = np.vstack(ks)
    plt.imshow(kstack,interpolation='none')
    plt.show()

def main():

    #theano.config.exception_verbosity="high"
    #theano.config.optimizer='None'

    X_train, y_train, X_test, y_test = load_mnist()
    ohe = OneHotEncoder()

    y_train = ohe.fit_transform(np.expand_dims(y_train,1)).toarray()
    chunk_len = 100
    visamount = 10
    num_epochs = 1000
    num_filters=31
    dropout_p=.0
    print "X_train.shape",X_train.shape,"y_train.shape",y_train.shape
    input_var = T.tensor4('X')
    output_var = T.tensor4('X')
    conv_nonlinearity = lasagne.nonlinearities.sigmoid
    net = lasagne.layers.InputLayer((chunk_len,1,28,28), input_var)
    conv1 = net = lasagne.layers.Conv2DLayer(net,num_filters,(7,7),nonlinearity=conv_nonlinearity,untie_biases=True)
    net = lasagne.layers.MaxPool2DLayer(net,(3,3),stride=(2,2))
    net = lasagne.layers.DropoutLayer(net,p=dropout_p)
    #conv2_layer = lasagne.layers.Conv2DLayer(dropout_layer,num_filters,(3,3),nonlinearity=conv_nonlinearity)
    #pool2_layer = lasagne.layers.MaxPool2DLayer(conv2_layer,(3,3),stride=(2,2))
    net = lasagne.layers.DenseLayer(net,10,nonlinearity=lasagne.nonlinearities.sigmoid)

    #augment_layer1 = lasagne.layers.DenseLayer(reduction_layer,33,nonlinearity=lasagne.nonlinearities.sigmoid)
    net = lasagne.layers.DenseLayer(net,121,nonlinearity=lasagne.nonlinearities.sigmoid)

    net = lasagne.layers.ReshapeLayer(net,(chunk_len,1,11,11))

    net = lasagne.layers.Conv2DLayer(net,num_filters,(3,3),nonlinearity=conv_nonlinearity,untie_biases=True)
    net = lasagne.layers.Upscale2DLayer(net,2)

    net = lasagne.layers.Conv2DLayer(net,num_filters,(3,3),nonlinearity=conv_nonlinearity,untie_biases=True)
    #pool_after0 = lasagne.layers.MaxPool2DLayer(conv_after1,(3,3),stride=(2,2))
    net = lasagne.layers.Upscale2DLayer(net,2)

    net = lasagne.layers.DropoutLayer(net,p=dropout_p)

    #conv_after2 = lasagne.layers.Conv2DLayer(upscale_layer1,num_filters,(3,3),nonlinearity=conv_nonlinearity,untie_biases=True)
    #pool_after1 = lasagne.layers.MaxPool2DLayer(conv_after2,(3,3),stride=(1,1))
    #upscale_layer2 = lasagne.layers.Upscale2DLayer(pool_after1,4)

    net = lasagne.layers.Conv2DLayer(net,num_filters,(5,5),nonlinearity=conv_nonlinearity,untie_biases=True)
    net = lasagne.layers.FeaturePoolLayer(net,num_filters,pool_function=theano.tensor.max)
    print "output_shape:",lasagne.layers.get_output_shape(net)
    params = lasagne.layers.get_all_params(net, trainable=True)
    prediction = lasagne.layers.get_output(net)
    loss = lasagne.objectives.squared_error(prediction, output_var)
    #loss = lasagne.objectives.binary_crossentropy(prediction, output_var)
    aggregated_loss = lasagne.objectives.aggregate(loss)
    updates = lasagne.updates.adagrad(aggregated_loss,params)
    train_fn = theano.function([input_var, output_var], loss, updates=updates)

    test_prediction = lasagne.layers.get_output(net, deterministic=True)
    predict_fn = theano.function([input_var], test_prediction)

    print "starting training..."
    for epoch in range(num_epochs):
        selected = list(set(np.random.random_integers(0,59999,chunk_len*4)))[:chunk_len]
        X_train_sub = X_train[selected,:]
        _loss = train_fn(X_train_sub, X_train_sub)
        print("Epoch %d: Loss %g" % (epoch + 1, np.sum(_loss) / len(X_train)))
        """
        chunk = X_train[0:chunk_len,:,:,:]
        result = predict_fn(chunk)
        vis1 = np.hstack([chunk[j,0,:,:] for j in range(visamount)])
        vis2 = np.hstack([result[j,0,:,:] for j in range(visamount)])
        plt.imshow(np.vstack([vis1,vis2]))
        plt.show()
        """
    print "done."

    chunk = X_train[0:chunk_len,:,:,:]
    result = predict_fn(chunk)
    print "chunk.shape",chunk.shape
    print "result.shape",result.shape
    plot_filters(conv1)
    for i in range(chunk_len/visamount):
        vis1 = np.hstack([chunk[i*visamount+j,0,:,:] for j in range(visamount)])
        vis2 = np.hstack([result[i*visamount+j,0,:,:] for j in range(visamount)])
        plt.imshow(np.vstack([vis1,vis2]))
        plt.show()
    import ipdb; ipdb.set_trace()

if __name__ == "__main__":
    main()

ความคิดเห็นใด ๆ เกี่ยวกับวิธีการปรับปรุงเครือข่ายนี้เพื่อให้มีโปรแกรมการทำงานอัตโนมัติที่สมเหตุสมผล

แก้ไขปัญหา!

ด้วยการใช้งานที่แตกต่างกันมากโดยใช้ rectifier ที่รั่วแทนฟังก์ชัน sigmoid ใน layer convolutional มีเพียง 2 (!!) โหนดใน layer คอขวดและ convolutions ที่มี 1x1 kernels ในตอนท้ายสุด

นี่คือผลลัพธ์ของการสร้างใหม่:

ป้อนคำอธิบายรูปภาพที่นี่

รหัส:

import theano.tensor as T
import theano
import sys
sys.path.insert(0,'./Lasagne') # local checkout of Lasagne
import lasagne
from theano import pp
from theano import function
import theano.tensor.nnet
import gzip
import numpy as np
from sklearn.preprocessing import OneHotEncoder
import matplotlib.pyplot as plt
def load_mnist():

    def load_mnist_images(filename):
        with gzip.open(filename, 'rb') as f:
            data = np.frombuffer(f.read(), np.uint8, offset=16)
        # The inputs are vectors now, we reshape them to monochrome 2D images,
        # following the shape convention: (examples, channels, rows, columns)
        data = data.reshape(-1, 1, 28, 28)
        # The inputs come as bytes, we convert them to float32 in range [0,1].
        # (Actually to range [0, 255/256], for compatibility to the version
        # provided at http://deeplearning.net/data/mnist/mnist.pkl.gz.)
        return data / np.float32(256)

    def load_mnist_labels(filename):
        # Read the labels in Yann LeCun's binary format.
        with gzip.open(filename, 'rb') as f:
            data = np.frombuffer(f.read(), np.uint8, offset=8)
        # The labels are vectors of integers now, that's exactly what we want.
        return data

    X_train = load_mnist_images('train-images-idx3-ubyte.gz')
    y_train = load_mnist_labels('train-labels-idx1-ubyte.gz')
    X_test = load_mnist_images('t10k-images-idx3-ubyte.gz')
    y_test = load_mnist_labels('t10k-labels-idx1-ubyte.gz')
    return X_train, y_train, X_test, y_test

def main():

    X_train, y_train, X_test, y_test = load_mnist()
    ohe = OneHotEncoder()

    y_train = ohe.fit_transform(np.expand_dims(y_train,1)).toarray()
    chunk_len = 100
    num_epochs = 10000
    num_filters=7
    input_var = T.tensor4('X')
    output_var = T.tensor4('X')
    #conv_nonlinearity = lasagne.nonlinearities.sigmoid
    #conv_nonlinearity = lasagne.nonlinearities.rectify
    conv_nonlinearity = lasagne.nonlinearities.LeakyRectify(.1)
    softplus = theano.tensor.nnet.softplus
    #conv_nonlinearity = theano.tensor.nnet.softplus
    net = lasagne.layers.InputLayer((chunk_len,1,28,28), input_var)
    conv1 = net = lasagne.layers.Conv2DLayer(net,num_filters,(7,7),nonlinearity=conv_nonlinearity,untie_biases=True)
    net = lasagne.layers.MaxPool2DLayer(net,(3,3),stride=(2,2))
    net = lasagne.layers.DenseLayer(net,2,nonlinearity=lasagne.nonlinearities.sigmoid)
    net = lasagne.layers.DenseLayer(net,49,nonlinearity=lasagne.nonlinearities.sigmoid)
    net = lasagne.layers.ReshapeLayer(net,(chunk_len,1,7,7))
    net = lasagne.layers.Conv2DLayer(net,num_filters,(3,3),nonlinearity=conv_nonlinearity,untie_biases=True)
    net = lasagne.layers.MaxPool2DLayer(net,(3,3),stride=(1,1))
    net = lasagne.layers.Upscale2DLayer(net,4)
    net = lasagne.layers.Conv2DLayer(net,num_filters,(3,3),nonlinearity=conv_nonlinearity,untie_biases=True)
    net = lasagne.layers.MaxPool2DLayer(net,(3,3),stride=(1,1))
    net = lasagne.layers.Upscale2DLayer(net,4)
    net = lasagne.layers.Conv2DLayer(net,num_filters,(5,5),nonlinearity=conv_nonlinearity,untie_biases=True)
    net = lasagne.layers.Conv2DLayer(net,num_filters,(1,1),nonlinearity=conv_nonlinearity,untie_biases=True)
    net = lasagne.layers.FeaturePoolLayer(net,num_filters,pool_function=theano.tensor.max)
    net = lasagne.layers.Conv2DLayer(net,1,(1,1),nonlinearity=conv_nonlinearity,untie_biases=True)
    print "output shape:",net.output_shape
    params = lasagne.layers.get_all_params(net, trainable=True)
    prediction = lasagne.layers.get_output(net)
    loss = lasagne.objectives.squared_error(prediction, output_var)
    #loss = lasagne.objectives.binary_hinge_loss(prediction, output_var)
    aggregated_loss = lasagne.objectives.aggregate(loss)
    #updates = lasagne.updates.adagrad(aggregated_loss,params)
    updates = lasagne.updates.nesterov_momentum(aggregated_loss,params,0.5)#.005
    train_fn = theano.function([input_var, output_var], loss, updates=updates)

    test_prediction = lasagne.layers.get_output(net, deterministic=True)
    predict_fn = theano.function([input_var], test_prediction)

    print "starting training..."
    for epoch in range(num_epochs):
        selected = list(set(np.random.random_integers(0,59999,chunk_len*4)))[:chunk_len]
        X_train_sub = X_train[selected,:]
        _loss = train_fn(X_train_sub, X_train_sub)
        print("Epoch %d: Loss %g" % (epoch + 1, np.sum(_loss) / len(X_train)))
    print "done."

    chunk = X_train[0:chunk_len,:,:,:]
    result = predict_fn(chunk)
    print "chunk.shape",chunk.shape
    print "result.shape",result.shape
    visamount = 10
    for i in range(10):
        vis1 = np.hstack([chunk[i*visamount+j,0,:,:] for j in range(visamount)])
        vis2 = np.hstack([result[i*visamount+j,0,:,:] for j in range(visamount)])
        plt.imshow(np.vstack([vis1,vis2]))
        plt.show()

    import ipdb; ipdb.set_trace()
if __name__ == "__main__":
    main()

คำตอบ:


4

คุณอาจได้รับข้อมูลเชิงลึกมากขึ้นโดยการมองเห็นน้ำหนักแทนที่จะเป็นเพียงไทปัน ฉันมีปัญหาคล้ายกันเมื่ออคติของฉันถูกกำหนดค่าผิดพลาด ทุกอย่างด้านล่างนี้เขียนขึ้นจากประสบการณ์ของฉันในการเขียนห้องสมุดการเรียนรู้ของฉันเอง คุณสามารถดูรหัสที่นี่ใน Github http://github.com/josephcatrambone/aij

นี่คือภาพหน้าจอของโปรแกรมของฉันเมื่อไม่มีอคติ หลังจากนี้อาจมีเพียงสิบยุคเท่านั้นเนื่องจากฉันรีบเขียนบทความนี้ให้เสร็จ:

น้ำหนักเท่านั้น - ไม่มีอคติ

การปรับปรุงน้ำหนักทำได้โดยการดำเนินการเหล่านี้:

weights.add_i(positiveProduct.subtract(negativeProduct).elementMultiply(learningRate / (float) batchSize));
//visibleBias.add_i(batch.subtract(negativeVisibleProbabilities).meanRow().elementMultiply(learningRate));
//hiddenBias.add_i(positiveHiddenProbabilities.subtract(negativeHiddenProbabilities).meanRow().elementMultiply(learningRate));

หากฉันไม่ใส่เครื่องหมายอคติที่มองเห็นได้ฉันจะได้ผลลัพธ์ดังนี้:

แก้ไขอคติที่มองเห็นได้

หากฉันเพิ่มเครื่องหมายของรหัสอคติที่มองเห็นได้ (ลบแทนการเพิ่ม):

visibleBias.subtract_i(batch.subtract(negativeVisibleProbabilities).meanRow().elementMultiply(learningRate));

ฉันได้รับภาพนี้:

กลับอคติสัญญาณ

ลูกบอลหิมะก้อนไหนและในที่สุดก็ถึงสิ่งที่คุณมีอยู่ด้านบน ตรวจสอบสัญลักษณ์ของฟังก์ชั่นข้อผิดพลาดของคุณ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.