LeeCreation! Media & Robot  
Front Page
Tag | Location | Media | Guestbook | Admin   
 
[요약 번역] 케라스(Keras)로 구현하는 오토인코더(AutoEncoder)

오토인코더를 비롯하여 여러 변형들의 구현과 간략 설명이 있는 케라스 블로그 글을 읽는 중에 공부도할 겸 그 내용을 아주 간략하게 한글로 요약해보았다.


https://blog.keras.io/building-autoencoders-in-keras.html


예제 코드는 다음의 모델들을 포함하고 있다.

  • 흔히 보는 CNN을 사용하는 autoencoder가 아니라 걍 fully-connected layer
  • Sparse autoencoder
  • Deep fully-connected autoencoder
  • CNN을 사용한 autoencoder
  • 이미지에서 노이즈 제거하는 모델
  • Sequence-to-sequence autoencoder
  • VAE (variational autoencoder)


*다시 한 번 이야기하지만 이 글은 요약을 한 것이지, 전체 번역은 아니다.


  • Autoencoder는 무엇인가?

데이터를 압축하고 다시 압축을 푸는 알고리즘이다.


특징으로는 1) 데이타 맞춤적(data-specific)이다. 2) 무손실 압축 형태가 아니다. 3) 데이터로부터 자동적으로 학습된다.


  • 데이터 압축에 좋은 방법인가?
딱히 그렇지는 않다. 기존 압축 방법인 JPEG나 MP3 같은 것보다 효율적이지 않다.

  • 그럼 뭐가 좋은데?
딱 맞는 분야를 찾아가는 중이다. 일단 데이터의 노이즈를 제거하는데 좋고, 데이터의 시각화를 위한 차원 축소(dimensionality reduction)에 좋다.

  • 근데 왜 이렇게 난리냐?
일단 비지도학습(unsupervised learning)으로 학습이 된다는 게 매력적이다. 아주 엄밀하게는 self-supervised 학습이라고 하는 것이 맞겠다.


  • 가장 간단한 fully-connected layer 버젼의 autoencoder
코드는 홈페이지에서 참고하자.

학습을 시켜보면 loss 값이 0.1 근처에 머무는 걸 볼 수 있다.


  • 압축된 정보에 희박함(sparsity) 조건 추가하기
앞서 예제는 hidden layer의 크기(앞 예제에서는 32차원으로 설정)만이 학습 조건이었다. 근데 이건 사실 PCA(principal component analysis)랑 크게 다를 것이 없다. 그래서 조금 더 효율적인 압축을 위해서 희박함(sparsity)이라는 추가 조건을 더해주는 방법을 추가한다.


원문 홈페이지 코드 참고.


regularization을 추가하여 학습시키는 건데 overfit을 줄일 수 있다고 한다. 근데 결과를 보면 성능이 뭐 딱히 더 좋아졌는지 티가 나지는 않는다.


  • Deep fully-connected autoencoder
앞서 예제는 단일 layer를 갖는 encoder와 decoder로 구현된 것이었고, layer를 몇 개 더 추가해보자.


원문 홈페이지 코드 참고.


약간 더 좋아졌다.


  • CNN을 사용한 autoencoder

MNIST 데이터는 손글씨 이미지이기 때문에 CNN을 쓰는 게 더 적합해보인다.


세번의 2D convolution 세번의 MaxPooling으로 총 128차원의 정보로 데이터를 압축시켰다가, 다시 이미지를 복원하는 코드로 구성되어 있다. 원문 코드 참고.


참고로, 모델을 학습시키기 전에, 학습 과정의 결과들을 시각화하기 위해 TensorBoard를 사용한다. 터미널 창을 하나 켜고 아래 명령을 실행시키고 학습을 시작하면, /tmp/autoencoder 폴더에 값들이 기록된다.

"tensorboard --logdir=/tmp/autoencoder"


결과를 보면 확실히 좋아졌다. 앞서서는 압축한 데이터가 32차원의 데이터였는데, 여기서는 128차원(8x4x4)의 데이터이기 때문에 loss 값이 큰 차이 없어 보여도 성능은 좋아진 것이라고 한다.


*visualization code에 오타가 있다. for loop 안에 suplot에 쓰이는 i가 i+1이어야 한다.


  • 이미지에서 노이즈 제거하는 모델

MNIST 데이터에 가우시안 노이즈를 섞어서 노이즈가 있는 이미지 데이터를 만든다.


이 데이터를 학습하는 autoencoder는 약간 다른 구조를 썼다. 두번의 2D convolution과 두번의 MaxPooling으로 1,568차원(7x7x32)으로 정보를 압축시켰다가 이미지를 복원함. (아마도 노이즈가 포함되서 그런지 압축차원을 이전 모델이 갖던 128차원보다 더 크게 설정한듯 하다. 이건 뭐 개발자의 느낌적 느낌인 건가)


  • Sequence-to-sequence autoencoder

이번에는 이미지가 아닌 시퀀스 데이터에 대한 학습. LSTM과 같은 구조를 이용하여서 입력 시퀀스를 하나의 벡터로 만들고, 이를 다시 LSTM decoder에 n번 입력해서 원하는 길이(n)의 출력을 얻는 방법이다.


아닛?! 근데 여기서는 그냥 어떻게 코딩이 이루어질 수 있는지 예제 코드만 있다. 코드는 간단하긴 한데, 아무런 입력 데이터 예제 없이 그냥 코드만 보여주다니. ㅠㅠ


  • VAE (variational autoencoder)

대망의 VAE


Autoencoder랑 다른 점이 뭐냐하면, autoencoder는 latent vector를 찾아주는 반면에, VAE는 latent variable(평균과 표준편차)을 찾아준다. 이렇게 하면 latent 공간 상에서 데이터가 어떠한 분포를 갖고있는지 알 수 있고 이 분포로부터 얻어진 샘플로 decoder를 통해 입력을 다시 생성해낼 수 있다. (이게 꽤나 유용하다) 그래서 VAE가 '생성 모델(generative model)'이다.


VAE가 어떻게 동작하는가?


먼저, encoder는 입력 x를 받아와 latent 공간 상에서 어떤 평균과 표준편차를 갖는지 출력하는 역할을 한다. 그리고 이 평균과 표준편차로 decoder에 넘겨줄 z를 만든다. z = 평균 + 표준편차 x 랜덤값(0~1사이) 마지막으로 decoder는 x와 동일한 이미지를 만든다.


평균과 표준편차들은 두개의 loss function으로 학습된다. 하나는 재생성 loss function으로 기존 autoencoder에서 decoder가 입력과 동일한 데이터를 재생성하도록 학습시키는 것이다. 다른 하나는 학습된 latent 분포와 기존 분포 사이의 KL divergence를 계산하는 것으로 regularization처럼 동작한다. KL divergence는 사실 더 좋은 학습을 위한 것이라서 없어도 된다. (앞서 sparsity 조건을 추가할 때도 regularization에 대한 언급이 있었다.)


전체 코드는 Github 링크로 되어있고, 각 단계별 코드 설명이 되어있다.


먼저 입력을 어떻게 latent 공간의 변수로 매핑시키는지를 보자.


*여기부터는 코드 해석을 조금 더 추가해보았다.


x를 h라는 중간 레이어를 통과하게 하고, h로부터 latent 공간(z)의 평균값과, 표준편차를 얻을 수 있는 구조다. z의 차원수 만큼 평균과 표준편차가 존재하게 된다.


그 다음 정의된 sampling이라는 함수는, z 공간상의 평균과 표준편차를 파라미터로 받아서 decoder로 넘겨줄 z 값을 만들어준다.  z = 평균 + 표준편차 x 랜덤값(0~1사이) 입력은 하나의 값이 아니라 batch_size의 길이만큼 들어오기 때문에 함수 중간에 랜덤값(epsilon) 생성시에도 shape 설정을 길이에 맞게 해주었다. Lambda 함수는 keras에서 정의된 함수로 수식과 같은 임의의 함수를 layer 형태로 변환시켜주는 함수다.


이제 decoder_h layer를 이용해 z로부터 intermediate_dim 차원의 중간 vector인 h_decoded를 얻고, 이를 다시 decoder_mean layer를 통해 원본 데이타 크기의 출력을 만든다.


여기서 VAE전체, encoder만 따로, decoder(generator)만 따로 분리해서 정의해둔다.


Loss function은 VAE 전체 모델의 입출력이 같아지도록 하는 xent_loss와 KL divergence regularization을 이용하는 kl_loss의 합으로 정의된다.


본 예제 코드에서는 latent space를 2차원으로 설정했기 때문에, encoded된 입력들이 어떻게 분포되어 있는지를 그림으로 쉽게 나타낼 수 있다.


자 이제 기존에 학습된 입력이 아니더라도 우리는 데이터의 분포를 알 수 있기 때문에 새로운 출력을 생성해낼 수도 있다!


2차원 공간상에서 값들을 상하좌우로 옮겨가며 interpolated 된 z들을 decoder(generator)에 입력으로 넣어 얻은 출력들을 원문에서 볼 수 있다. 여기에 epsilon_std라는 변수가 어떤 값인지 안 정해지고 사용되었는데, 아마 시험적으로 출력이 가장 변화무쌍하게 보일 수 있는 값을 찾은 게 아닌가 싶다. 아! 예제코드를 직접 가서 보니 -4에서 4 범위 내로 되어있다. 그렇다면 설명문에 적힌 epsilon_std는 4/15 였는듯. 뭐 어차피 그냥 예제코드대로 돌릴 거면 큰 상관 없을듯.


덧)


VAE가 CNN이 아니고 fully connected leyer로 구현된 예제이기 때문에 CNN을 썼을 때는 어떨지 궁금하다. 근데 CNN 안써도 결과가 괜찮네. 


덧2)


예제 코드를 혹시나 Windows에서 돌린다면 GraphViz가 제대로 동작하지 않을 수 있다. 나는 그냥 plot_model이 들어간 line들을 다 주석처리하고 돌렸다.



BLOG main image
미디어와 로봇에 관심이 많은 아이 그 영역을 넓혀보려 합니다. '영상 제작'과 '감정 로봇'이 블로그의 주소재입니다. 자유로운 답글 환영합니다!
 Notice
 Category
전체보기 (749)
내가 사랑하는 MJ (0)
아이가 생긴다면 (4)
Media (98)
Robot (447)
타인과 약자를 위한 (81)
Etc. (118)
 TAGS
연구
 Calendar
«   2025/02   »
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
 Recent Entries
 Recent Comments
 Recent Trackbacks
 Archive
 Link Site
LeeCreation! Media & Robot
 Visitor Statistics
Total :
Today :
Yesterday :
rss