본문 바로가기

AI/머신러닝(코세라)

[ML] #11 비지도 학습 - 클러스터링(Unsupervised learning - clustering)

본 글은 학교 '머신러닝' 수업을 들으며 공부한 내용을, 저의 말로 바꿔서 남에게 설명해주듯이 쓰는 글입니다.
다시 한번 복습하는 과정에서 Coursera Andrew Ng 교수님의 강의를 일부 수강하였고, 인터넷 검색 등을 통해 내용을 보충하였습니다.
너무 쉬운 개념들은 따로 정리하지 않았습니다. 따라서 해당 글에는 적히지 않은 개념들이 일부 있을 수 있습니다.


본 글은 Andrew Ng 교수님의 'machine learning' 수업 강의 노트를 일부 사용하였습니다.
본 글에 사용된 강의노트 사진들 대부분의 저작권은 'DeepLearning.AI'에 귀속되어 있음을 밝히며,
본 글은 'DeepLearning.AI'의 'Copyright rights'에 따라 수익 창출을 하지 않고,
또한 해당 정책에 따라 '개인 공부 및 정보 전달'이라는 교육적 목적으로 글을 작성함을 밝힙니다.

Unsupervised learning introduction

 

우리가 기존에 해왔던 로지스틱 회귀처럼, 왼쪽과 같이 training set에 lable이 포함된 것을 지도 학습이라 함.

오른쪽과 같이 training set에 lable이 포함되지 않은 것을 비지도 학습이라 함.

 

클러스터링 알고리즘: 데이터들을 클러스터로 묶어주는 알고리즘

클러스터 : 클러스터링된 결과로 얻어진 데이터의 그룹으로, 각 클러스터는 비슷한 특성을 공유하는 데이터 포인트의 집합임.

클러스터링은 대표적인 비지도 학습의 사례.

 

클러스터링 응용 사례로는 여러가지가 있는데, 첫 번째 market segmentation의 일종으로, '추천 시스템'이 상당히 유용함.

우리가 실제로 클러스러팅을 쓰게 된다면 추천시스템에 쓰게 될텐데, 왜냐하면 암 판단 이런건 성능이 좋아야겠지만, 추천은 성능이 좀 떨어져도 됨. 우리도 할 수 있따!! 충분히 가능함.

 


 

K-means algorithm

클러스터 중심점(Cluster Centroid) : 특정 클러스터 내 데이터 포인트들의 평균 위치를 나타내는 점.

=> 클러스터에 속한 모든 데이터 포인트의 좌표 값을 평균 내어 계산된 점임. 예를 들어, 클러스터에 속한 데이터 포인트들이 다차원 공간에 위치한다면, 각 차원의 값에 대해 평균을 구해 중심점을 정의함.

 

k-means algorithm은 데이터(주어진 학습 셋)을 k개의 클러스터로 군집화(클러스터링)하는 클러스터링 알고리즘임.

 

위와 같이 2개의 feature에 대해, k = 2일 때로 k-means algorithm을 실행한다고 해보자.

 

1.  initial seed 설정 단계

임의의 클러스터 중심점을 잡는 것부터 시작함. 이 초기 클러스터 중심점을 initial seed(초기 시드)라고도 함.

 

2. 클러스터 할당 단계

각 데이터 점이 각 클러스터 중심점 중에 어느 점에 가까운지 계산해 할당함.

 

3. 클러스터 중심점 이동 단계

각 클러스터에 속한 데이터 점의 좌표값을 평균내어, 그 위치로 클러스터 중심점을 이동시킴.

 

4. 2 ~ 3 과정을 반복함.

 

1~4의 단계를 거치면, 위와 같이 클러스터링이 완료됨.

 

이러한 k-means 알고리즘은 K (몇 개의 클러스터로 나눌 거냐)와 학습 셋을 입력으로 받음.

클러스터링을 할 때, 몇 개의 클래스로 나눌 지 저 K는 우리가 입력을 해주는게 좋음. k-means의 경우도 k를 몇으로 주냐에 따라 결과가 완전히 달라짐. 이걸 자동화하려는 시도도 있었으나, 이건 우리가 정해주는 게 성능이 좋음. 그래서 그냥 K는 입력해줘야 한다고 박고 가자.

 

위 4단계 중 2~3단계를 수식으로 나타낸 건데, 천천히 읽으면 잘 이해가 될거임.

왼쪽처럼 분리된 학습 셋뿐만 아니라, 오른쪽처럼 잘 불리가 안되어있는 학습 셋이어도 k-means를 쓰면 잘 클러스터링이 가능함.

 

여담) 단계 2에서, "어느 중심점에 가까울지 계산"은 어떻게 하는 걸까?

=>젤 쉬운건 거리겠음.

이 때, 어떤 distance를 쓸 지가 중요할 거임. 그걸 선택하는 덴 도메인 지식이 필요. 근데 보통은 유클리디안 거리를 그냥 씀. 젤 직관적이고 쉬우니까.

근데 유클리디안 거리의 최소값은 0 최대값은 무한대인데, Normalized equation의 경우는 유사도는 -1 ~ 1임. 그러다 보니 0~무한대 보단 -1~1 거리를 계산하는 게 더 쉬울 수도 있음. → 각각의 메져에 따라 특성이 다르니 잘 선택하라는 말

 

근데, 대부분의 경우는 그냥 유클라디안 거리를 씀. 젤 쉽고 단순하니까.


 

Optimization objective

k-means도 최적화할 수 있음. k-means을 최적화한다는 건, 만들어진 클러스터의 mean과 그 클러스터에 속한 녀석들의 거리 차가, 최소가 되게 만드는 거임. 

일단, 목적 함수(여기선 비용 함수가 아니라 목적 함수라 햇음. 왤까)는 위와 같이 정의가 될거임. 클러스터 내 어떤 데이터와, 그 클러스터 내 데이터들의 좌표 평균 점, 이 둘의 유클리디안 거리를 구해서 제곱을 하고, 데이터 개수 m으로 나눠주면 됨. 그 값을 목적 함수로 하자.

그럼, 1부터 m까지 모든 데이터에 대해, 저 목적 함수를 최소로 만드는 cluster와 cluster centroid를 구하면 됨.

 

즉, 목적 함수가 최소가 됐다는 건, 각 점에 할당된 클러스터 중심점까지의 거리의 합이 가장 작다는 거니까, 클러스터링이 잘 됐다는 걸 의미함. 이렇게 클러스터링이 잘 된, 즉 J가 최소가 된 상태의 <각 점에 할당되는 cluster 이름>과, <각 cluster의 cluster centroid>가 있을 거 아님. 이게 우리가 구하고자 하는 거잖음. 끝!!

 

위를 반복하면 되는데, 사실 아까 처음에 말한 2~3단계를 반복하는 걸, J를 써서 표현한 것 뿐임.

결국 할당, 이동, 할당, 이동, 할당, ... 의 반복이다!!

 


 

Random initialization

k-means의 가장 큰 단점 : initial seed가 어떻게 됐냐에 따라 클러스터링 결과가 달라질 수 있음.

극단적으로, initial seeds가 동일한 곳에서 시작했으면, 클러스터링이 안됨.

 

일단 일반적으론 완전 랜덤한 공간에서 centroid를 잡기 보단, 데이터 셋에서 샘플을 좀 가져와서 그걸 centroid로 씀.

보면, 왼쪽과 같이 운이 좋게 저렇게 초기 시드가 설정됐다면 클러스터링이 잘 되겠지만, 오른쪽같이 좀 똥같이 초기 시드가 설정됐다면 클러스터링이 잘 안될거임. => 결과가 달라짐... local optima에 빠질 가능성이 큼.

 

이런식으로, 원래 lable은 왼쪽과 같다고 하면,

오른쪽 위와 같이 global optima에 잘 도달할 수도 있지만, 아래 두 개와 같이 local optima에 빠질 수도 있는거임.

 

이를 최대한 좀 완화해보기 위해... 우리 강노에서 제시하는 방법은

"그냥 여러 번 학습 돌려서, 그 중 가장 작은 objective function J가 나오는 파라미터(c, 뮤)를 고르자"임.

사실 좀 단순무식한 방법이긴함... 자원도 시간도 많이 들거임.

 

그럼, 다른 해결 방안은 없을까.

 

혹자는 유전 알고리즘을 주장하기도 하는데, 이걸 부모에서 해서 자손대에서 막 형질을 주고받고… 근데 코드 보면 별거 없고, 속도는 드럽게 느림. 논문쓸 땐 좋은데 느림.

 

그럼, 만약 2개의 initial seed를 택한다 하면, 어떻게 하면 좋을까?

⇒ 일단 데이터 셋에서 샘플로 시드 하나 뽑았어. 그럼 그 다음엔 멀리있는 샘플로 시드로 선택해야됨.

-> 근데, 그렇다고 가장 멀리 있는 거 가져가기도 좀 그럼.

⇒ 그냥 1 0이 아니라, 멀리 있는 건 두 번째 시드로 더 잘 선택되게, 가까이 있는 건 두 번째 시드로 덜 선택되게 하면 됨.

(말이 좀 이상한데, 처음에 초기 시드로 어떤 A라는 샘플을 선택했으면, 내 학습 셋 중에서 A에서 멀리 있는 놈들은 두 번째 시드가 될 확률을 높이고, 가까이 있는 놈들은 그 확률을 낮추는 거임.)

 

k means++가 그렇게 함. 거리에 따라 확률(가중치, weighted)을 조절해줌. 얘가 선택됐으면 멀리 있는 건 뽑힐 확률이 더 높고, 가까이 있는 건 뽑힐 확률이 더 낮도록 함.

요즘은 저거 많이 쓰는듯?


 

Outlier

 

 

또, outlier가 생기면 엄청 쥐약임. 만약 seed가 outlier 주변에서 생겨났으면, distance가 엄청 멀기에 저 뭉친 쪽으로 가기 힘듦.

예를 들어, 위와 같이 K = 3인 k-means 알고리즘을 돌린다고 해보자.

근데, 오른쪽 끝에 outlier 하나가 있다!!!!!

 

거기에 더해서, initial seed가 저렇게 오른쪽에 outlier에 잡혀버렸다!!!(파란색 점)

이러면... 중심 할당 및 이동을 했을 때, 위와 같이 된다.

그리고, 반복을 아무리 돌려도, 클러스터링 결과는 바뀌지 않는다.

 

이렇게 k-means 알고리즘은 outlier에 initial seed가 잡힌다면 엄청 쥐약임.

만약 seed가 outlier 주변에서 생겨났으면, distance가 엄청 멀기에 다른 쪽으로 가기 힘듦.

 

그럼, outlier을 어케할까…

⇒ 하나나 두개의 점으로 이루어진 클러스터가 동떨어져 있으면 아웃라이어인가?

⇒ 근데, 데이터가 10개면, 하나가 아웃라이어가 아닐 수도 있음… 샘플이 100개면 하나 두개정도가 아웃라이어일 수도 있겠고…

데이터가 5개 10개밖에 안되면, 저렇게 오른쪽에 튀어나온 게 아웃라이어가 아니라, 그냥 그렇게 분포가 된걸수도 있잖아. 또, 샘플이 10000개면 1개는아웃라이어라고 할 수 있겠지. 그치만 데이터가 10000개에 100개는 아웃라이어라고 할 수 있을까? 애매함. 그러나 1000000000개의 데이터 중에서 100개면 아웃라이어라고 할 만하잖아 충분이.

 

즉, 아웃라이어의 기준을 절대적인 수치로 정해두고 따지면 안됨.

 

그러면, 비율로 하면 됨 !! ex. 특정 클러스터 또는 전체 데이터에서 1% 이하는 아웃라이어이다.

데이터 셋의 크기에 따라 아웃라이어의 기준이 상대적으로 바뀜!! 비율의 힘.

ex.10000개 에서 3개 동떨어져 있으면 아웃라이어다. 근데, 10개에서 3개 동떨어져 있으면 아웃라이어라 하기는 좀 어렵다.

이런 식으로 해결할 수 있을거임.

 


 

K 어떻게 정할까(Choosing the number of clusters)

k값을 어떻게 정할까 -> 이건 사실 정해진 답이 없음...

위와 같이, 같은 학습 셋에 따라서 누구는 K를 4로, 누구는 2로 할 수가 있음.

 

K 값을 정하는 데 도움이 될 수 있는 방법으로, Elbow method라는 게 있음. 

왼쪽과 같이 K에 따른 J 그래프를 그려봤을 때, 저렇게 꺾이는 점(Elbow)가 있으면, 저 K값을 사용하면 좀 괜찮다는 거임.

근데... 결국 이건 각 K에 따라 학습을 돌리는 거잖음?? 자원과 시간이 많이 들어감. 저렇게 학습 여러번 돌릴 시간, 자원이 있겠냐구... ㅠㅠ

또, 오른쪽과 같이 Elbow의 위치가 명확하지 않을 수도 있음.

우측과 같은 그래프가 나왔다면 아마 K를 3이나 4, 5같은 걸로 하면 괜찮아보이긴 하나... 근거가 부족함.

따라서 Elbow method는 시도할 가치는 있지만 모든 문제에서 명확한 해답을 찾아주진 않음.

(사실 일종의 greedy search느낌 아닌가??)

 

 

결국, 적절한 K값을 고르기 위해선 모델링하는 사람의 경험, 역량이 중요함.

결국, K값 정하는 덴 도메인 지식이 매우매우매우 중요함!!!!

위에 그림을 보면, 예를 들어 내가 아디다스 브랜드의 옷을 가지고 군집화할건데, 아디다스는 S M L의 3가지 사이즈 분류를 쓴다고 해보자. 그러면 K = 3으로 하는 게 좋겠지? XS, S, M, L, XL 5가지 사이즈 분류를 쓰는 브랜드에서 일을 하면, K = 5로 설정해주는 게 가장 좋을 거임.

 

흠.....ㅠㅠ 도메인 지식 어케쌓냐...ㅠ.ㅠㅠㅠ.ㅠㅠ.ㅠ

 

K-means의 장단점은 위와 같음.

 

가장 큰 장점은 simple and fast하다는 거임.

쉬우니까 오버피팅도 덜 일어나구. 좋음 ㅎㅎ

구현 쉬운 것도 있구. 데이터 표현하기도 쉬움.

 

근데... 단점들이 좀 있음.

1. 일단 K를 직접 정해줘야함.

2. 그리고 위에서 다뤘듯이 outlier에 쥐약임.

3. 또 local minima에도 잘 빠짐. k-means++ 등 완화법이 소개되긴 했지만, 그럼에도 불구하고 잘 빠짐.

4번과 5번 단점같은 경우는 아래와 같음.(gpt답변)