[TENSORFLOW] Image AutoEncoder

2017. 4. 19. 09:25machine learning

2017/04/18 - [machine learning] - [TENSORFLOW] Autoencoder


지금까지 1차원 입력에 대해서만 auto encoder를 살펴보았다. 그렇다면 이미지 등과 같은 2차원 입력에 대해서는 어떤 식으로 autoencoder를 만들어야 하는 것일까?

우리는 이미지를 우선 gray scale로 변환 한 후 1차원으로 열거할 것이다. 우선 첫 번째로 빨간색, 녹색, 파란색의 평균을 구해 gray 픽셀 값으로 변환한다. 그 다음으로 2차원으로 나열되어 있는 이미지 배열을 1차원으로 열거해 놓는 것이다. 즉 [[1,2,3],[4,5,6],[7,8,9]] 이런 식의 이미지 데이터를 [1,2,3,4,5,6,7,8,9] 이런식으로 변환을 한 후 autoencoder를 적용해 볼 것이다.

코드를 살펴 보기 전에 우리는 CIFAR 라고 불리는 이미지 데이터를 가져와서 테스트 해 볼 것이다. 아래와 같이 명령어를 입력해서 데이터를 가져온 후 압축을 풀자.

$> wget https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz

$> tar xvf cifar-10-python.tar.gz   

압축을 풀면 기대했던 이미지 파일이라기 보단 data_batch_1.... 형태의 binary 파일들이 나타날 것이다. rgb 값들을 binary 형태로 제공하는 것이며 pickle이라는 package를 통해 이를 dictionary 형태로 읽을 수가 있다.

코드를 통해 살펴보자.

unpickle 함수는 설명했다시피 cifar binary 데이터를 dict 형태로 풀기 위한 함수이다.

grayscale은 RGB 형태의 이미지 파일을 gray 형태로 바꿔주는 함수이며, data_show는 gray 형태로 바뀐 이미지를 보여주기 위한 함수이다.

우선 cifar site를 통해 다운받은 cifar data 내의 메타데이터를 읽어서 names라는 변수에 담아보자.

names 변수를 print 해보면 아래와 같은 이미지 객체 리스트를 확인할 수가 있다.

['airplane', 'automobile', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck']

이제 for문을 돌려서 cifar data를 가져온 후, data와 label로 분해해 보자. 참고로 data는 한 개의 이미지가 32 * 32 픽셀에 RGB 값이 포함된 32 * 32 * 3 = 3072의 특징 벡터를 가진 50000개의 데이터로 구성이 되어 있다. 즉 50000 * 3072의 행렬을 가진다. label은 방금 위에서 살펴본 이미지 객체들에 대한 index 값을 가진다.

그럼 이제 RGB 데이터를 grayscale로 바꿔보자. 

a.reshape(a.shape[0], 3, 32, 32).mean(1).reshape(a.shape[0], -1)

우선 3072로 구성되어 있는 행렬을 RGB로 분해하기 위해 3 * 32 * 32로 분해를 한다. 그런 후에 RGB에 대한 평균을 구한 후 (32 * 32) 해당 32 * 32 행렬을 1차원으로 표현해주기 위해 1024행렬로 다시 합친다.

data에 대한 gray 작업이 끝났다면, 이제 data를 numpy matrix로 변환하고, label을 numpy array로 변환해 주자.

그런 후 label 중 말 이미지만 뽑아내기 위해 index가 7인 것들만 true list로 반환해서 horse_indices에 저장하고 저장된 true index list를 이용해서 실제 데이터에서 말 이미지만 뽑아내자.

말 이미지의 shape를 보면 이미지 개수 X 특징 벡터가 나오며, 특징 벡터는 32 * 32 픽셀이기 때문에 1024개가 잡히게 된다.

이제 이전 포스팅에서 만들어 놓은 Autoencoder 클래스를 생성해서 훈련을 시켜보자. 위의 예제에서는 10000번 epoch가 돌도록 실행시켜 놓았다.

train을 실행시키면 단계별로 loss가 떨어지는 것을 확인해 볼수가 있다.

10000번의 train이 완료되었으면.. 이제 test image를 넣어서 reconstruct 된 이미지를 한번 확인해 보자. (나 같은 경우에는 시간 관계상 1000번만 돌렸는데 loss가 45로 잘 안떨어졌음...)

unpickle 함수의 파라미터로 test_batch 파일을 넣고 dict 타입으로 변환을 한다. 그 후 dict에서 data만 뽑아서 gray scale로 변환을 해주고, 1 * 1024 행렬이 되도록 reshape를 해준다. data_show를 통해 이미지를 확인해 보면 말의 이미지를 확인해 볼 수가 있다. 

이 해당 말 이미지를 Autoencoder test 함수의 파라미터로 집어 넣고 reconst를 리턴 받는다.

마지막으로 아래의 그림과 같이 reconst된 이미지를 확인해 볼 수가 있다. 아래 그림은 왼쪽이 test하려는 이미지이고 오른쪽이 재구성된 이미지이다. loss가 45라 그런지 잘 복원이 안됐다...