Loop Question

FrontPage|FindPage|TitleIndex|RecentChanges| UserPreferences P RSS
Continued from SpssSyntaxQuestion

What is LOOP? And how to use LOOP? :

통계전공하는 경제학과생에게 질문한 결과 그분도 SPSS는 안써봐서 syntax를 어떻게 짜는지는 모르겠고 프로그래밍 procedure로 "loop"같은 걸 이용하면 될 것같다면서 다음과 같은 조언을 주셨습니다. 여기 과친구 중에 SPSS 잘하는 애한테 물었을 때도 걔도 "loop"를 이용하면 되지않겠냐는 말을 해준 적이 있는데... 문제는...이 loop가 무엇인지 제가 모른다는 것이죠.. 흑.. 다들 방학이라 집에 가있는 모양인데 계속 멜로 귀찮게 할 수도 없고.. 참 답답이노하네요.. 도대체 이 루프라는 게 뭐고 이걸 다음과 같이 이용하려면 어떻게 해야하는 걸까요? 아시는 분 조언 좀 주시면 대단히 감사하겠습니다. --우산

덧붙임: 근데 또 사실 아래의 논리적 구조가 맞는지어떤지도 잘 모르겠네요 (제가 아래 루프식을 전혀 이해를 못하고 있으므로..).. 그룹 내의 모든 페어의 합을 그룹당 한 값으로 구해서 한 그룹의 모든 멤버가 같은 값을 갖는 구조가 아니어야하는데... 각각의 멤버들이 '나'로부터 다른 멤버들 각자와의 거리(distance)의 차이의 합을 가지는 구조니까 멤버들이 각자 다른 값을 가지게될텐데...

시작
 
g=group의 수, 60 ?
 
i=1, group index
loop 1 ( i=1 to g), 그룹을 번갈아 가며 계산
 
    x=group i, group i의 data를 변수 x로 읽어들임
    n=x의 data 개수
    sum=0, group sum의 초기화
 
    j=1, 첫번째 index
    loop 2  (j=1 to n)
 
        k=1, 두번째 index
        loop 3 (k=1 to n)
 
            if k > j,
                s = abs( x(j)-x(k) ),   x의 j번째 data와 k번째 data의 차의 절대값을 구함
                sum = sum + s, 위에서 구한 것들을 이전의 sum에 합함
            end if
 
        end loop 3
 
    end loop 2      
 
    print sum, group i의 구하고자 했던 합
 
end loop 1
 
끝


원하시는게 Sum of pairs 가 아니었군요. 그룹 내에서의 각 member 들의 distance 였군요. Distance 구하는 방법은 굉장히 다양하지만, 가장 간단한 방법은 그룹 내의 평균으로부터의 편차를 distance 로 볼 수 있을 것 같은데, 결국 이것들을 모은 것이 분산과 표준편차가 되겠지요.
하지만 지금 우산님이 원하시는 것은, 그것이 아니고, 자신을 제외한 모든 member들과의 거리(편차의 절대값)를 더한 값으로 distance를 정의하고자 하시는 것으로 이해됩니다.
이것도 기술적으로 어려운 건 아닙니다. 내가 해 주는 것도 아니면서... 말은... ^^ 제가 감히 고수들 앞에서 프로그래밍을 논할 수 없어 그런 것이니 이해를...
그리고 위에 써 놓으신 코드는 말씀하신 distance 구하는 코드가 아니라, Sum of pairs 구하는 코드입니다. 유월님이 만들어 주신 거랑 똑같은 작용을 하는 코드입니다.
loop 는 순환문이란 뜻이고, 이걸 구하려면 알고리즘에 순환문이 반드시 필요하다는 얘기지, 특별한 해결책을 제시하는 내용은 아닙니다. --지상은

잘은 몰라도 제가 보기에도 위의 분이 해주신 게 유월님이 해주신 거랑 같은 것같아보이더라구요.. 그나저나 유월님이 어디가셨나.. 파이썬 코드를 수정해주시면 좋으련만...... --우산

참 근데 지상은님 난 아직도 섬오브페어랑 디스턴스합이랑 머가 어떻게 다른지 모르겠어요. 어떤 차이가 있나요? 디스턴스합의 개념은 알겠는데 섬오브페어가 그것과 어떻게 다른지 모르겠다는 표현이 더 정확하겠다...^^; --우산


결론부터 말씀드리면, SP는 한 그룹에 대해서 하나의 대표값으로 나오는 거고, 우산님이 정의한 디스턴스의 합은 그룹내 member 각각에 대해서 구한 값이죠. 디스턴스의 합들을 모두 합하면 SP 와 비슷한 개념이 되겠죠. 단, AB, BA pair 의 같은 조합의 수치가 두 번 중복되어서 합해지게 되니 실제 값은 다르지만요.

SP score를 잠시 더 설명드리면, 이것의 응용 중의 하나는 생물정보학의 multiple alignment에서 쓰이는 건데, 예를 들어 다음의 경우에는 두 개의 그룹에 대해서 간단히 비교할 수 있죠.

{{|
1, 3
2, 6
|}}

밑의 것이 더 다르다는 것이 확연하죠. 하지만 여러 가지가 함께 섞여 있어서

{{|
2, 3, 4, 1, 5
1, 9, 2, 8, 9
|}}

이런 식일 때 member들이 몇십, 몇백개가 된다면 눈으로 봐서는 어느 쪽이 더 다른지 쉽게 알 수 없을 겁니다. 따라서 그룹 전체를 대표할 수 있는 산포도의 수치가 필요한데 바로 그것이 분산이고, 분산은 편차의 제곱의 합의 평균이니까, Sum of squares를 그룹의 N으로 나눈 값이죠.

하지만 단순한 산포도를 원하는 것이 아니라, 어떤 의미를 가친 수치여서 제곱을 하면 그 의미를 잃게 된다거나 그런 경우에는 SP score를 쓰게 되는 거죠. Member 각각에서 평균을 빼서 나온 편차를 사용하는 것이 아니라, 각각의 pair 에 대해서 구한 차이를 가지고 다 더한 값이 바로 SP score 가 되고요. 이것도 역시 그 그룹에 대한 대표값으로서의 의미를 당연히 할 수 있습니다. 분산이나 평균처럼...

디스턴스를 정의하는 방법은 다양해서, 반드시 어떤 것으로 해야 한다는 법은 없다고 합니다. 지금은 그룹 내에서 다른 멤버들과의 차이의 절대값을 전부 더한 것을 디스턴스로 정의한 거구요. 다른 말로는 각 멤버와의 디스턴스의 합이죠. 이것은 그룹 전체가 아니라 한 멤버마다 고유하게 가지게 되는 값이죠. 왜 이것이 필요한지는 정확히 잘 모르겠지만, outlier 같은 것을 찾아내기 위해서가 아닐까 싶네요.

Clustering 에 사용되는 알고리즘들이나 개념들이 관련 있는 것이 많을 것 같은데, 차이점이라면 Clustering은 그룹이 정해지지 않은 상태에서 그룹핑 하기 위해서 쓰는 거고, 디스턴스나 SP 는 그룹이 나눠진 상태에서 각 member 나 그룹의 특징을 기술하기 위해서 쓰는 거라고 하면 될 것 같습니다.

간단하게 말하면 디스턴스합을 각자에게 구해서 다 더한 뒤에 두 배하면 섬오브페어가 된단말인가요? --우산


해보니 거꾸로군요. 한 그룹에 3명의 member 가 있을 때,

{{|
a b c
|}}

이때 계산상의 편리를 위해서 a>b>c 라고 가정하고,

1. 각 member 에 대해서 Distance를 구해 보겠습니다.
a-b
+ |a-c|, |a-b| + |b-c|, |a-c| + |b-c|

2. Distance 의 합을 구해 보겠습니다.
(2a-b-c) + (a-c) + (a+b-2c) = 4a-4c

3. sum of pairs를 구해 보겠습니다.
a와 b 사이의 차이 : a-b
a와 c 사이의 차이 : a-c
b와 c 사이의 차이 : b-c
이걸 모두 더하면
(a-b) + (a-c) + (b-c) = 2a-2c
이렇게 되는군요.

distance 는 자신의 제외한 다른 멤버들과 계산을 하기 때문에 (n-1) 개 의 항의 계산을 n개의 member 들에 대해서 해야 합니다. 결국 이걸 다 더한 distance 의 합은 n(n-1) 개의 항을 가지겠군요. Sum of pair 는 n 개 중에서 2개 뽑는 조합, nC2 입니다. 이것은 n! / (2!)(n-2)! 이므로 n(n-1)/2 가 됩니다.
항들이 서로 틀릴 수가 없기 때문에, 결국 Distance를 모두 합하면 동일한 걸 한번씩 더 계산하는 것이 되어서 Sum of pairs 의 두배가 된다는 결론이 나오는군요. ^^


"; if (isset($options[timer])) print $menu.$banner."
".$options[timer]->Write()."
"; else print $menu.$banner."
".$timer; ?> # # ?>