2013년 11월 9일 토요일

차원 축소(dimensionality reduction)

크기가 32x32인 얼굴 영상이 50장 있다.  한장의 영상은 픽셀이 1024개가 있는 하나의 벡터이다.
따라서 1024개의 벡터가 50개 이다.  즉, 행렬 A의 크기는 1024x50이다. 

각각의 벡터는 1024차원에서 하나의 점이다.  50개가 있으므로 1024차원의 공간에서 50개의 점을 정의한다. 

점 하나에 1024개의 좌표가 필요하다. 점 표현을 위해 사용되는 주축이 1024개이기 때문이다. 


데이터를 압축해서 표현하기 위해 주축의 수를 줄여본다. 

50개 점의 분포, 즉 분산이 가장 큰 축을 몇 개  찾으면 된다.  분산이 큰 방향이 데이터의 변량을 잘 표현하는 방향이다.
5개을 찾아 보자. 

데이터는 크기가 1024x50인 행렬이다.  먼저 평균을 구하자.  즉, 데이터의 중심점을 지나는 주축을 구할 것이다.

mu = mean(data,2); 

각 데이터에서 평균을 제거하자. 

data = data-repmat(mu, [1,50]);

data를 특이값 분해한다. 

[u,d,v] = svd(data); % data=udv'

d 행렬은 특이값이 들어 있는 대각 행렬이다. 
u 행렬의 1~5열을 취한다. 

u1=u(:,1:5); 



주축 5개를 구했으므로 첫번째 데이터를 새 축에서 표시해 보자. 

c1=u1'*data(:,1); % 5x1=(5x1024).(1024x1)

5개의 값이 나오는데 이는 5개의 주축에서 좌표 값이다. 
즉, 데이터의 표현이 1024개에서 5개로 줄었다.   

이제 5개의 좌표 값 만으로 원 데이터를 재생해보자.  

o1=c1(1)*u1(:,1)+c1(2)*u1(:,2)+...+c1(5)*u1(:,5)

이다. matlab 명령으로

o1 = u1*c1; % 1024x1=(1024x5).(5x1).  o1=u1*c1=u1*u1'*data(:,1)

이다. 원 데이터와 재생 데이터의 차이는 

res1=data(:,1)-o1;

이다.



모든 데이터를 새 축에서 표시해 보자.

c = u1'*data;  % (5x50) = (5x1024).(1024x50)
o = u1*c; % (1024x50) = (1024x5).(5x50)
res = data-o; % (1024x50)-(1024x50)



행렬 c는 [5x50]으로,  50장의 영상을 각기 5개의 계수치로 표현한 것이다.

mean(c,2)를 통해 5개 계수치의 평균을 구해서 m2에 저장한다.
어떤 새로운 이미지 t1를 템플릿과 비교할 때는 c2=u1'*t1으로 5개의 계수를 구하고 norm(m2-c2)로 거리를 계산하면 된다.

 



댓글 4개:

  1. u 행렬의 1~5행을 취한다.
    u1=u[:,1:5];

    본문에 위와 같이 쓰여있는데, 저 코드는 1~5열을 취하는 것 아닌가요?

    답글삭제
  2. 또한, 매트랩 인덱스 슬라이싱 접근시, [ ] 가 아닌 ( ) 만 되는것 같습니다;; (2010기준..)

    답글삭제