본문 바로가기
지능형시스템_

[머신러닝] - Autoencoder

by CHML 2016. 7. 30.
1. 개요

Autoencoder는 이미지 데이터의 압축을 위해 연구된 인공신경망 (Artificial Neural Networks, ANNs)이다. Autoencoder의 구조는 일반적인 feedforward neural networks (FNNs)와 유사하지만, autoencoder는 비지도 학습 (unsupervised learning) 모델이다 [1]. Autoencoder는 기존에 대부분 데이터의 압축을 위해 활용되었으나, 최근에는 딥 러닝 (deep learning)에 대한 연구가 활발해지면서 입력 벡터의 차원 축소, 은닉층의 학습 등에 많이 이용되고 있다 [2, 3].


2. 구조

Autoencoder의 구조는 일반적인 FNN의 구조와 매우 유사하며, 한 가지 다른 점은 입력층 (input layer)과 출력층 (output layer)의 크기가 항상 같다는 것이다. 아래의 [그림 1]은 은닉층 (hidden layer)이 1개인 autoencoder의 구조를 나타낸다. 입력층과 출력층의 크기는 같으며, 입력층-은닉층 구간을 encoder, 은닉층-출력층 구간을 decoder라고 한다.


[그림 1] 은닉층이 1개인 autoencoder의 구조


Autoencoder의 중요한 동작은 입력 벡터의 차원을 축소하는 것이다. 이러한 동작은 입력층-은닉층 구간인 encoder에서 수행되며, 차원이 축소된 입력 벡터를 code 또는 latent variables라고 한다. Encoder 영역에서 생성된 code는 은닉층-출력층 구간인 decoder를 거쳐 입력 벡터와 동일한 출력 벡터로 변환된다.


3. 학습 알고리즘 (learning algorithm)

일반적으로 autoencoder는 FNNs처럼 역전파 (backpropagation) 알고리즘을 이용하여 학습을 수행행한다. FNNs 모델에 대한 역전파 알고리즘에 대한 설명은 이 글에 자세하게 서술되어 있다. 이 글에서 이용되는 기호와 각 기호가 갖는 의미는 아래의 [표 1]과 같으며, 뉴런의 활성 함수 (activation function)로는 시그모이드 함수 (sigmoid function)를 이용하였다.


[그림 1] 학습 연산 정의에 이용되는 기호들


[식 1]은 [그림 1]과 같은 구조를 갖는 autoencoder의 출력층 가중치 학습 연산이다. 출력층 가중치는 은닉층-출력층 사이의 연결강도를 의미한다.



[식 2]는 은닉층 가중치의 학습 연산이며, 은닉층 가중치는 입력층-은닉층 사이의 연결강도를 의미한다.




출력층 뉴런의 바이어스 학습 연산은 아래의 [식 4]과 같다.



마지막으로, 은닉층 뉴런의 바이어스 학습 연산은 [식 5]와 같다.



4. 구현

Autoencoder의 출력값 계산과 가중치 학습을 프로그래밍 언어로 구현하면 아래의 [코드 1]과 같다. 구현에 이용된 프로그래밍 언어는 Java이다.

  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
private void computeOutputsHL(final double[] vector) {
    double net;
    
    for(int i = 0; i < SIZE_HIDDEN_LAYER; i++) {
        net = biasWeightsHL[i];
        
        for(int j = 0; j < SIZE_INPUT_VECTOR; j++) {
            net += weightsHL[i][j] * vector[j];
        }
        
        outputsHL[i] = 1 / (1 + Math.exp(-net));
    }
}
 
private void computeOutputsOL() {
    double net;
    
    for(int i = 0; i < SIZE_INPUT_VECTOR; i++) {
        net = biasWeightsOL[i];
        
        for(int j = 0; j < SIZE_HIDDEN_LAYER; j++) {
            net += weightsOL[i][j] * outputsHL[j];
        }
        
        outputsOL[i] = 1 / (1 + Math.exp(-net));
    }
}
 
private void updateWeights(final int index) {
    double[] deltaHL = new double[SIZE_HIDDEN_LAYER];
    double[] deltaOL = new double[SIZE_INPUT_VECTOR];
    
    // Compute delta of the output layer
    for(int i = 0; i < SIZE_INPUT_VECTOR; i++) {
        deltaOL[i] = (learningVectors[index][i] - outputsOL[i])
* (1 - outputsOL[i]) * outputsOL[i];
    }
    
    for(int i = 0; i < SIZE_INPUT_VECTOR; i++) {                        
        for(int j = 0; j < SIZE_HIDDEN_LAYER; j++) {
            weightsOL[i][j] += LEARNING_RATE * deltaOL[i] * outputsHL[j];
        }
 
        biasWeightsOL[i] += LEARNING_RATE * deltaOL[i];
    }
    
    // Compute delta of the hidden layer
    for(int i = 0; i < SIZE_HIDDEN_LAYER; i++){
        double sum = 0;
        
        for(int j = 0; j < SIZE_INPUT_VECTOR; j++) {
            sum += deltaOL[j] * weightsOL[j][i];
        }
        
        deltaHL[i] = sum * (1 - outputsHL[i]) * outputsHL[i];
    }
    
    for(int i = 0; i < SIZE_HIDDEN_LAYER; i++) {                        
        for(int j = 0; j < SIZE_INPUT_VECTOR; j++) {
            weightsHL[i][j] += LEARNING_RATE * deltaHL[i] * learningVectors[index][j];
        }
 
        biasWeightsHL[i] += LEARNING_RATE * deltaHL[i];
    }
}
cs

[코드 1] Java를 이용한 autoencoder의 구현


가중치를 조정하는 updateWeights 함수에서는 계산량을 줄이기 위해 출력층의 $\delta$를 저장하여 은닉층의 가중치 조정에 이용하였다. 출력값을 계산할 때는 반드시 computeOutputsHL이 호출된 다음, computeOutputsOL이 호출되어야 한다. 그러나 가중치를 조정할 때는 반대로 출력층에 대한 가중치를 조정한 다음, 은닉층에 대한 가중치를 조정해야 한다.






References

[1] Yoshinori YAGINUMA, Takashi KIMOTO. 1996. Multi-Sensor Fusion Model for Constructing Internet Representation using Autoencoder Neural Networks. Neural Networks, 1996., IEEE International Conference on Vol. 3, pp. 1646 - 1651.

[2] Quoc V. Le. 2015. A Tutorial on Deep Learning, Part 2: Autoencoders, Convolutional Neural Networks and Recurrent Neural Networks.

[3] Andrew Ng. Sparse autoencoder. CS294A Lecture notes.