사례 연구: 이미지 데이터의 시각화
- 목적: 손글씨 이미지 파일을 2차원에 시각화하기
- 8 X 8 사이즈의 이미지 파일, 즉 64차원
- 밝기: 1~16
패키지 설치
install.packages(c('lle', 'tsne', 'vegan'))
데이터 파일 불러오기
data = read.csv('digit.csv')
데이터 정보
dim(data)
[1] 1797 65
- 1797개의 손글씨 이미지
- 65개의 종: 64개의 점의 밝기 + 손글씨 숫자가 무슨 숫자인지에 대한 정보
첫 번째 손글씨의 정보
data[1,1:8]
V1 V2 V3 V4 V5 V6 V7 V8 1 0 0 5 13 9 1 0 0
data[1,9:16]
V9 V10 V11 V12 V13 V14 V15 V16 1 0 0 13 15 10 15 5 0
data[1,17:24]
V17 V18 V19 V20 V21 V22 V23 V24 1 0 3 15 2 0 11 8 0
data[1,25:32]
V25 V26 V27 V28 V29 V30 V31 V32 1 0 4 12 0 0 8 8 0
시각화를 위한 사전 작업
image = data[1:64]
number = as.character(data[,65])
color = rainbow(10)[data[,65]+1]
image
: 이미지에 해당하는 부분number
: 숫자 정보에 해당하는 부분number
는 후에 텍스트 형태로 출력을 하기 위해 문자 형태로 변환함color
: 숫자 별로 색을 지정
PCA
pca = prcomp(image)
plot(pca$x, typ = 'n')
text(pca$x, number, col = color)
- 64차원의 이미지를 2차원으로 축소
- 비슷한 숫자들끼리 비슷한 위치에 있음
- 5, 7, 8이 잘 구분이 안되어 있음
- 비선형적인 패턴을 많이 가진 부분은 잘 표현되지 못함
MDS
d = dist(image)
mds = cmdscale(d)
plot(mds, typ = 'n')
text(mds, number, col = color)
- 5, 7, 8이 잘 구분이 안되어 있음
IsoMap
library(vegan)
iso = isomap(d, ndim = 2, k = 30)
plot(iso$points, typ = 'n')
text(iso$points, number, col = color)
Loading required package: permute Loading required package: lattice This is vegan 2.5-6
- 앞에서 했던 것보다 숫자들끼리 덜 겹쳐짐
- 원래 공간에 복잡하게 접혀져 있는 것들을 잘 펼쳐서 표현
- IsoMap은 거리만을 이용하니까 이번 사례에서는 LLE보다 잘 나옴
LLE
library(lle)
lin = lle(image, 2, 30)
plot(lin$Y, typ = 'n')
text(lin$Y, number, col = color)
Loading required package: scatterplot3d Loading required package: MASS Loading required package: snowfall Loading required package: snow
finding neighbours calculating weights computing coordinates
- 결과가 좋지 않음
- LLE는 평면이 있을 것이라고 가정을 하는데 이 데이터에는 평면이 없어 이런 결과를 도출한 듯함
tsne
library(tsne)
ts = tsne(image, initial_dims = 64)
plot(ts, typ = 'n')
text(ts, number, col = color)
sigma summary: Min. : 0.221408575610339 |1st Qu. : 0.620063784622015 |Median : 0.675069430571825 |Mean : 0.687671788667607 |3rd Qu. : 0.739130003054694 |Max. : 1.52805698437237 | Epoch: Iteration #100 error is: 19.217536943355 Epoch: Iteration #200 error is: 1.3587223315932 Epoch: Iteration #300 error is: 1.14080852254214 Epoch: Iteration #400 error is: 1.04440997888217 Epoch: Iteration #500 error is: 1.00637787550838 Epoch: Iteration #600 error is: 0.986854976155903 Epoch: Iteration #700 error is: 0.975567595309222 Epoch: Iteration #800 error is: 0.968378888065802 Epoch: Iteration #900 error is: 0.963365469441065 Epoch: Iteration #1000 error is: 0.959970056385717
- 숫자별로 구분이 잘 되었음
- 겹치는 숫자도 거의 없음
- 부분적인 구조를 잘 보존했기 때문에 이런 결과가 나옴
- 전체적인 구조를 잘 보존하지 못한다는 단점이 이 사례에서는 장점이 되었음