앞선 게시물에서 MNIST를 이용하여 오토인코더를 구현하였다.
이 포스팅은 학습된 디코더로 새로운 샘플을 생성하는 프로그램으로 두가지 실험을 수행한다.
- 생성실험 1 첫 번째 샘플의 잠복 공간 표현에 잡음을 섞어 새로운 샘플 생성
- 생성실험 2 같은 부류의 샘플 사이를 보간하여 새로운 샘플 생성
전체 코드
#생성 실험 1
x0 = x_test[0]
z = model_encoder.predict(x0.reshape(1,28,28,1))
print(np.round(z,3))
zz=np.zeros((20,zdim))
for i in range(20):
zz[i]=z[0]+(i-10)/10.0
generated_img = model_decoder.predict(zz)
plt.figure(figsize=(20,4))
for i in range(20):
plt.subplot(2,10,i+1)
plt.imshow(generated_img[i].reshape(28,28),cmap='gray')
plt.xticks([]); plt.yticks([])
plt.title('noise='+str((i-10)/10.0))
plt.show()
#생성 실험 2
x4_6 = np.array((x_test[4],x_test[6]))
z=model_encoder.predict(x4_6)
zz=np.zeros((20,zdim))
for i in range(20):
alpha=i/(20.0-1.0)
zz[i]=(1.0-alpha)*z[0]+alpha*z[1]
generated_img=model_decoder.predict(zz)
plt.figure(figsize=(20,4))
for i in range(20):
plt.subplot(2,10,i+1)
plt.imshow(generated_img[i].reshape(28,28),cmap='gray')
plt.xticks([]); plt.yticks([])
plt.title('alpha='+str(round(i/(20.0-1.0),3)))
plt.show()
실행 결과
첫번째 실험결과에서는 샘플과 비슷게 생성이 되었다.
기존 샘플은 noise=0.0이라고 표기된 잡음이 섞이지 않은 샘플을 보면 된다.
사실 내 실행결과에서는 변화가 별로 없는데, 책에 있는 실행결과를 보면 noise가 커질수록 왜곡이 심하게 일어난다.
잡음이 0.3보다 커질수록 형편없는 모양이 되어버렸다.
교재 실행결과
두번째 실험결과를 보면 alpha=0.0일때 샘플에서 alpha=1.0일때의 샘플 모양으로 서서히 변해가는 것을 볼 수 있다.
alpha=0.5가 두 샘플의 중간지점인데 획이 끊여저서 샘플의 품질이 그다지 좋진 않음
즉, 정리하면 다음과 같다!
- 오토인코더는 생성 모델로서 가능성 있다.
- 어떤 점은 품질이 좋은 샘플을 성공적으로 생성하는데, 반면 어떤 점은 품질이 떨어지는 샘플을 생성한다.
코드 해설
첫 번째 실험
x0 = x_test[0]
z = model_encoder.predict(x0.reshape(1,28,28,1))
print(np.round(z,3))
zz=np.zeros((20,zdim))
for i in range(20):
zz[i]=z[0]+(i-10)/10.0
generated_img = model_decoder.predict(zz)
plt.figure(figsize=(20,4))
for i in range(20):
plt.subplot(2,10,i+1)
plt.imshow(generated_img[i].reshape(28,28),cmap='gray')
plt.xticks([]); plt.yticks([])
plt.title('noise='+str((i-10)/10.0))
plt.show()
앞선 프로그램의 실행 결과에서 첫 번째 샘플에 해당하는 잠복 공간의 점에 잡음을 추가한 새로운 점을 디코더로 복원.
잡음을 -1.0 부터 1.0까지 0.1만큼 증가시키며 추가한 다음 디코더로 복원해 디스플레이 한다.
오토인코더는 인코더로 압축하고 디코더로 복원하는데, 인코더로 압축한 것이 잠복 공간에 표현이 되고 여기에 잡음을 추가한 것을 디코더로 복원하겠다는 의미이다.
코드를 자세히 살펴보자.
x0 = x_test[0]
0번째 샘플을 뽑아 저장한다.
◀ x0 샘플 그림
z = model_encoder.predict(x0.reshape(1,28,28,1))
model_encoder로 예측 수행
= 원본 패턴을 잠복 공간으로 매핑함
print(np.round(z,3))
매핑한 점의 좌표를 확인함
np.round(수, 자리수)
넘파이의 반올림 함수
(z,3)이므로 z를 소수 세번째자리까지 표기
zz=np.zeros((20,zdim))
for i in range(20):
zz[i]=z[0]+(i-10)/10.0
위 벡터에 -1.0부터 1.0까지 0.1만큼씩 증가하는 잡음을 추가한 벡터 20개를 만듦
generated_img = model_decoder.predict(zz)
잡음이 추가된 벡터를 model_decoder를 이용해 원본 패턴과 같은 크기로 복원
나머지는 복원된 패턴을 디스플레이 하는 코드
두 번째 실험
x4_6 = np.array((x_test[4],x_test[6]))
z=model_encoder.predict(x4_6)
zz=np.zeros((20,zdim))
for i in range(20):
alpha=i/(20.0-1.0)
zz[i]=(1.0-alpha)*z[0]+alpha*z[1]
generated_img=model_decoder.predict(zz)
plt.figure(figsize=(20,4))
for i in range(20):
plt.subplot(2,10,i+1)
plt.imshow(generated_img[i].reshape(28,28),cmap='gray')
plt.xticks([]); plt.yticks([])
plt.title('alpha='+str(round(i/(20.0-1.0),3)))
plt.show()
이전에 생성한 오토인코더의 실행결과를 보면, 다섯 번째 샘플과 일곱 번째 샘플이 같은 부류(4)에 속한다.
◀ 5, 7번째 샘플 그림
둘 사이를 잇는 직선상의 점을 등간격으로 20개 선택하고 이 점들을 디코더에 입력해 원래 크기의 패턴으로 복원.
코드를 자세히 보자.
x4_6 = np.array((x_test[4],x_test[6]))
두 샘플을 x4_6에 저장
z=model_encoder.predict(x4_6)
둘을 model_encoder로 예측하여 잠복 공간의 점 z를 얻는다
zz=np.zeros((20,zdim))
for i in range(20):
alpha=i/(20.0-1.0)
zz[i]=(1.0-alpha)*z[0]+alpha*z[1]
둘을 잇는 직선 상에서 점 20개를 샘플링 하여 zz에 저장
generated_img=model_decoder.predict(zz)
zz를 model_encoder에 입력하여 원래 크기로 복원
나머지는 복원된 패턴을 디스플레이 하는 코드
참고교재 파이썬으로 만드는 인공지능 - 한빛미디어