본문 바로가기

연구관련/Bioinfo류

정규화(normalization)




   많은 양의 데이터를 처리함에 있어 여러 이유로 정규화, 즉 데이터의 범위를 일치시키거나 분포를 유사하게 만들어 주는 등의 작업은 꼭 필요한 일이다. 


평균값을 이용한 정규화
중간값을 이용한 정규화
Quantile 정규화

평균값을 이용한 정규화

   데이터의 평균값을 0 으로 놓는 정규화는 일반적으로 원래의 데이터의 값의 분포가 '정규분포'임을 가정할 때가 많은데, 꼭 그렇지는 않아도 이와 같은 방법을 이용할 때가 있다. 이 때의 기본적인 아이디어는 '평균'에 해당하는 값은 0 으로, 그리고 평균에서 멀어질수록 값을 크게 주자, 는 것이다. 분산으로 나눈다는 의미는, 값의 분포가 고만고만한 상황에서 1이 차이나는 것과, 값의 분포가 매우 큰 경우에 1 차이나는 것은 분명 다른 경우이므로 분산으로 나눔으로써 원래 분포의 퍼짐에 의한 효과를 상쇄하고자 하는 것이다. 예를 들면,

1, 2, 3, 3, 2, 1, 2, 3, 4, 8, 1, 2 과 같은 데이터에서의 1과 3의 차이는
1002, 3929, 1949, 2212, 39, 2811, 7631, 9921, 877, 9929 에서의 9921과 9929 의 차이는

다를 것이라는 가정이다. 두 번째 데이터의 분산이 크기 때문에 9921과 9929는 별로 차이가 없는 값인 반면 첫 번재 데이터는 분산이 작고 그 와중에 2 가 차이가 나는 것이므로 1과 3은 분명 크게 차이가 나는 값인 것이다. 이와 같은 생각을 수식으로 표현하고자 분산으로 값을 나누어 주는 것이다. 일반적으로 이렇게 데이터에서 평균을 뺀 이후 표준편차로 나누어주는 작업을 z-transformation 이라고 하며, z-transformation은 데이터의 normal 분포를 가정하지 않는다. 평균값으로 정규화된 값은 다음과 같이 표현할 수 있겠다.




위의 식에서, 식 (1)의 di 위에 tilde(~)가 있는 것이 di 에 대한 정규화된 값이다. 이 값은, di 에서 d의 평균 E(d) 를 뺀 이후, d의 표준편차인 sigma_d 로 나누어 주면 된다. 이 과정을 C++ 코드로 나타내면 다음과 같다.



중간값을 이용한 정규화

   중간값을 이용한 정규화는 평균을 이용한 정규화의 절차와 거의 유사하나 데이터에서 값을 빼줄 때 (즉, 위의 식(1)에서) data의 평균 대신 중간값을 사용하는 것이다. 중간값을 이용한 정규화는 데이터에 너무 튀는 값이 있을 때 적당한 방법이다.  데이터의 중간값은 평균과는 달리 outlier에 영향을 받지 않는 성질을 갖고 있다. 평균이 아닌 중간값을 사용하는 이유는, 데이터에 너무 튀는 값, 즉 outlier 가 있을 것으로 보이는 경우에는 그와 같은 outlier가 되는 데이터 때문에 평균값이 잘못 구해질 수 있기 때문이다. 특히 이러한 경우는 data의 값이 작은 수로 나누어서 만들어지는 경우 자주 발생하는데, 분모가 너무 작으면 나누기를 행한 결과값 급격히 커지기 때문에 원래의 평균보다 큰 평균값이 구해질 수 있고, 이렇게 되면 전반적으로 데이터를 정규화시킨 값이 작게 나올 수 있게 된다. 데이터의 중간값(median)이란 N 개의 데이터를 오름차순으로 정렬하였을 때 [N/2] 에 위치하는 데이터의 값을 의미한다. 만약 N 이 홀수이면 N = 2k + 1 로 표시되는 자연수 k 에 대하여 k+1 번째 큰 값이 중간값이 되고, 만약 N 이 짝수라면 중간값을 결정하는 몇 가지 옵션이 존재하는데, 주로 N = 2k 를 만족하는 k에 대하여 k-1, k+1 번째로 큰 수의 평균을 중간값으로 사용할 수 있겠다. 이렇게 중간값을 구한 후 위의 식 1에서 E(d) 대신 그 중간값을 빼주면서 처리하면 중간값을 이용한 정규화가 된다. 따라서 식과 코드는 생략.



Quantile 정규화

   p quantile 이란 데이터를 오름차순으로 정렬하였을 때 p * data number 에 해당하는 데이터를 말한다. quantile 자체는 명확히 정의된 수학적 용어는 아닌 것 같으나, 일반적으로는 위의 의미로 사용되고 있다. quantile이 유용하게 사용되는 경우는, 주어진 분포가 가정하고 있는 분포와 유사한 것인지를 판단하는 Q-Q plot 을 이용하는 것이 있겠다. 흔히 말하는 '상위 몇 %' 에 해당하는 것이 quantile 과 비슷한 의미를 갖는다. Q-Q 정규화란 여러 데이터 set의 분포를 비슷하게 만들어 주는 작업으로,

data 1  D1 : d_11, d_12, ..., d_1N
data 2  D2 : d_21, d_22, ..., d_2M

인 두 data set D1과 D2가 있을 때, D1과 D2를 오름차순으로 정렬하였을 때 p%에 위치하는 데이터가 같은 값을 갖도록 해 주는 방법이 quantile 정규화이다. 좀 더 일반화시키면 D1, ..., DN 인 N 개의 data set이 있을 때, 각 data set의 p%에 위치하는 데이터의 값을 갖게 해 주는 작업이 quantile 정규화인 것이다. 각 데이터의

제일 작은 값들은 갖은 값을 갖고,
두 번째로 작은 값들이 같은 값을 갖고,
...
제일 큰 값이 같은 값을 갖도록 해 주는 작업.

이와 같은 작업은, 각 data set이 서로 다른 noise 에 의하여 분포의 전체 위치가 변할 가능성이 있는 경우 필요하다. 방법에 대한 아이디어는 매우 간단하여, 다음의 절차를 따른다.

i) N개의 각 데이터를 오름차순으로 정렬한다.
ii) 정렬된 데이터의 각 i 번째 데이터를 N 차원 상의 unit diagonal 직선으로 projection 시킨다.
iii) projection data 들에 대하여, 원래의 위치로 돌려 보낸다.

(방법상 오름차순이든 내림차순이든 상관은 없다. 이 글에서는 계속 오름차순으로 통일한다)
이 때 data 를 unit diagonal 로 projection 시킨다는 의미는, 2차원에 대해서 생각해 보면 (1,1)인 직선, N 차원에서 생각해 보면 (1, 1, ..., 1) 인 직선으로 데이터들을 projection 시킨다는 의미이고, projection 시키는 값은 주로 평균값을 사용한다. 그렇게 하여 새로운 값이 할당되면, 그 값을, 원래의 값이 원 데이터에서 위치하던 곳으로 옮겨 준다. 지금까지의 상황을 그림으로 나타내면 다음과 같다.



원래의 데이터가 위와 같은 모습이었다고 하자. 원 데이터들을 크기 순으로 정렬을 하면 다음과 같은 모습이다.



정렬된 데이터에서, 정렬된 순위가 같은 데이터들이 같은 값을 갖도록 할 것이다. 아래와 같이 다시 데이터들만 따로 뽑아서 살펴 보면,




새로운 값은, 각각의 정렬된 순위에 해당하는 데이터들의 '평균값'으로 설정한다. 이렇게 설정된 새로운 값으로 원래의 값들을 대체한다. 아래와 같이.




다시, 변환된 값의 이전 값이 원 데이터에서 차지하던 순위로 지금 변환시킨 값들을 위치시킨다. 이것은 즉, 변하기 전의 데이터의 값이 변한 후의 데이터의 값으로 대체되는 것을 의미한다. 따라서 결과적으로 최종 데이터는 아래와 같은 모습으로 바뀐다.





데이터를 각각 오름차순정렬하여 같은 순위에 해당하는 데이터를 좌표상에 찍는 Q-Q plot 을 그려 보면 quantile 정규화의 효과를 쉽게 알 수 있다.

Q-Q plot before Q-정규화Q-Q plot before Q-정규화Q-Q plot after Q-정규화Q-Q plot after Q-정규화



지금까지의 상황을 C++ 코드로 나타내면 다음과 같다.



몇 가지 관련 얘기들

   때에 따라서는 정규화(normalization)과 평균화(standardization)을 구분하여 사용하는 경우도 있다. 평균화는 모든 데이터의 값을 [0, 1] 의 구간으로 한정시키는 것으로, 다음과 같은 식을 사용할 수 있겠다.



이에 대한 C++ 코드는 다음과 같다.



위와 같은 절차를 수행함에 있어 원래의 데이터를 면밀히 검토하여 어떠한 방법을 사용할 것인지를 결정해야 하며, 데이터의 특성에 상관없이 모두 적용할 수 있는 방법은 없는 것으로 보인다. 일반적으로 평균값을 이용한 정규화를 많이 이용하는데, 이럴 때 data에 약간의 noise가 있을 경우, 상/하위 1% 정도를 없애는 전처리 작업 후 정규화를 할 수도 있다. 데이터의 상/하위 p %를 버리는 코드는 C++로 보면 다음과 같다.





ps. 에러 처리는 하지 않는다. 실제 코드에서는 위의 루틴 들어 가기 전에 왠만한 에러 처리를 다 한다. container가 비어 있던가, max_value - min_value 가 너무 작다던가, 하는 등의 에러 처리가 포함된다.


  • IHSV 2010.06.20 22:17

    와, 주인장님 잘 보고 갑니다. 배우는 사람으로써 이런 자료 정말 필요했는데, 잘 정리해주셔서 감사해요. 코드까지 ㅎㅎ 그런데 이런거 자세히 책을 보려면 어떤 책들을 봐야 하나요?

  • IHSV 2010.06.23 01:52

    아, 그렇군요, 대단하십니다, 정리도 너무 깔끔하게 해주시고 ㅠ
    그런데 Quantile Normalization이 참 좋은거 같애서 A Comparison of Normalization Methods for High Density Oligonucleotide Array Data Based on Variance and Bias 라는 관련 논문에 설명을 봤는데요, 그 논문 2쪽 우측 하단에 Quantile normalization에 대한 설명이 있는데, unit vector가 루트 n 분에 1 이라고 나옵니다. 이게 무슨 뜻인지요? 정말 이해가 안되서 염치 불구하고 여쭙습니다. ㅠㅠ

    • Favicon of https://adnoctum.tistory.com adnoctum 2010.06.23 06:56 신고

      본문에 그 말을 쓸까, 하다가 쓰지 않았는데, unit이란 unity, 즉 일반적인 실수체계에선 1.0 이 되겠지요. 그래서 unit vector 란 길이가 1인 벡터를 말하는데, n 차원에서 모든 축에서 동일한 각도를 가지며 길이가 1인 벡터를 만들기 위해 그렇게 한 것입니다. Quantile normalization 의 경우 어차피 그 벡터를 연장시킨 직선 위에서 작업을 진행하기 때문에 저는 길이는 중요하지 않다고 판단, 본문에서는 언급을 생략하였습니다.

  • IHSV 2010.06.23 11:24

    그렇군요, 정말 친절하신 설명 감사합니다.ㅠ
    저는 정보검색,분류 쪽 공부하는 학생인데요,
    댓글 관리해주실줄 몰랐는데 정말 감사합니다.

  • IHSV 2010.06.23 12:06

    제 선배중에 배워서 남주자가 신조인 형이 있는데, 정말 adnoctum님도 아마 대단하신분일듯 싶습니다. 저도 이렇게 똑똑해지면 좋겠어요 ^_^;;

  • UAK 2011.09.21 13:29

    좋은 자료 잘 보고갑니다 퍼갈게요

  • Jaeng 2012.01.04 16:40

    좋은 자료 감사합니다.
    따라해 보는 중인데 헷갈리는 부분이 있어서 질문드립니다.
    만약에
    data가 같은 값이 있는 경우 오름차순으로 할 때 순서를 어떻게 처리해야하는지 궁금합니다.

    예를 들어

    data1 : 3,0,1,0,5
    data2 : 0,1,3,4,5
    원순위 : 1,2,3,4,5

    일 경우 오름 차순 정렬을 하면

    data1 : 0,0,1,3,5
    원순위 : 2,4,3,1,5

    data2 : 0,1,3,4,5
    원순위 : 1,2,3,4,5

    평 균 : 0,0.5,2,3.5,5

    순서로 정렬이 되고 평균이 계산 되겠죠?
    그리고 원순위 대로 되돌리면

    data1 : 3.5,0,2,0.5,5
    data2 : 0,0.5,2,3.5,5
    원순위 : 1,2,3,4,5

    로 될겁니다.
    이 경우 data1의 2순위와 4순위의 값 '0'은 같은 값이지만, data2의 값에 따라 0이 되기도 하고 0.5가 되기도 합니다.
    이렇게 같은 값이지만 정렬되는 순서에 따라 다른 값으로 나오는게 맞는지 다른 처리과정이 있는건지 궁금합니다.
    낮은 값은 노이즈로 간주하고 0으로 처리하고 quantile normalization을 하다 보니 이런 궁금증이 생겼는데 답변해 주시면 정말 감사하겠습니다.

    • Favicon of https://adnoctum.tistory.com adnoctum 2012.01.06 13:55 신고

      답변이 많이 늦었군요. 정답은 없는 것 같습니다. 그렇게, discrete 한 값을 다룰 경우 같은 값이 나오는 문제를 tiling 이라고 하는데, 검색해 봐도 딱히 좋은 결과가 나오지 않는군요. 차라리 noise로 간주, 0 으로 하는 처리를 가장 마지막 단계에서 하는 것이 어떨까요?

  • JuNe 2012.11.27 19:24

    안녕하세요. 정규화에 관한 글 잘 읽고 갑니다.
    저는 서울소재 모 대학에서 연구중인 대학원생입니다.
    죄송스럽사오나 위 게시글에 대한 내용이 언급된 논문의 제목을 알 수 있을까요?
    레퍼런스에 언급을 해야할것같아서요...
    무튼 좋은글 감사드립니다.

    • Favicon of https://adnoctum.tistory.com adnoctum 2012.11.27 22:38 신고

      qq-normalization 말씀하시는 건가요? 일단은 http://bioinformatics.oxfordjournals.org/content/19/2/185.full.pdf+html 이 논문을 얘기할 수 있는데, 사실 이 방법은 quick-sort 처럼 일반적 알고리즘이라 qq-norm. 방법만을 주제로 한 논문을 찾기는 힘듦니다.

    • Favicon of https://adnoctum.tistory.com adnoctum 2012.11.27 22:40 신고

      저는 quantile-quantile normalization 의 알고리즘을 본 후 구현한 것인데, 그 알고리즘은 어느 문서에서나 나오든 동일합니다, 표현 방법만 조금 다를 뿐.

      만약 reference 로 참조해야 하는 문제라면, 다른 방법이 아닌 qq-norm. 을 쓸 때 연구 주제와 관련된 장점이 나와 있는 논문을 따로 찾으셔서 그것을 참조해야 하며, 그렇지 않고 단순히 qq-norm. 을 쓴 것이라면 굳이 qq-norm. 의 방법에 관한 논문을 ref로 달 필요는 없을 것 같습니다.

  • JuNe 2012.11.29 16:58

    친절하신 답변글에 다시한번 감사드립니다.
    현재 저는 지반공학을 전공으로 하고 있는 학생인데요...
    저희쪽에서는 이런 통계처리부분에 대해서 다루지 않다보니 사소한 것이라도 레퍼런스를 다는 편입니다...
    제가 알고싶은 부분은 위 글의 정규화부분에서 "평균화"가 언급된 페이퍼를 알고싶습니다..
    레퍼런스뿐만이 아니라 제가 통계적 자료처리 후 적용하는 인공신경망을 연구주제로 하고 있다보니 이런 부분에 공부가 필요할거같아서요...

    • Favicon of https://adnoctum.tistory.com adnoctum 2012.11.30 00:38 신고

      아... 저 내용은 제가 commentary 같은 아주 짧은 논문에서 본 거라 정확한 ref. 를 모르겠네요. 저희 쪽에서는 흔히 하는 일이라 별로 중요하게 생각하지 않아서 저도 굳이 기억하진 않았거든요. 검색을 좀 해봐도 저건 너무 간단한 거라 나오질 않네요.

  • JuNe 2012.11.30 11:13

    그렇군요...
    친절한 답변 감사드립니다.

  • IDEAJI 2013.08.26 16:34

    잘 보고 갑니다. :)
    링크 걸어두고 한번씩 보아야겠어요.
    분석 전에 데이터 전처리에 대해 고려하는 일이 사실 중요한 일인 듯 하네요.

  • Favicon of http://cafe.naver.com/0hy0 용장 2013.12.23 16:14

    잘 정리된 내용 감사합니다. 퍼갈께요.

  • 궁금파워 2020.06.18 14:53

    아주 초보자입니다. quantile 정규화 코드를 쓰고 싶은데 어떤 변수에 어떻게 생긴 값을 넣어야 되는지, 그리고 텍스트 파일을 읽어들이고 싶은데 그부분은 어디서 처리하고 있는건지, 그리고 int main()에는 무슨 코드를 넣어야 이 소스코드를 사용할 수 있는지 궁금합니다.
    답변 부탁드립니다.