고객이 보낸 과일 사진을 구별하는 '군집' 작업을 했었다. '샘플 평균값'을 활용해 대표 이미지(ex.apple_mean
)를 얻은 뒤, 그것과 개별 사진들의 차이를 바탕으로 과일을 구분할 수 있었다! 하지만, 타깃을 알고 있었으니 사실상 '비지도 학습'이 아니었다...
➡️ 전달받은 이미지 300개가 사과 몇 개 파인애플 몇 개 바나나 몇 개인지 아무것도 모르는 상태에서, 위와 같은 대표 이미지(=평균값)을 구할 수 있을까?
아무것도 모르는 사진 300장을 받았을 때, 위에서 말한 '평균값'을 자동으로 찾아주는 알고리즘이 있다?!?
apple_mean
같은 '평균값(대표이미지를 구성하는 픽셀 10,000개)'을 다르게 표현한 것뿐임.n_clusters
로 설정함. (*뒤에 나옴)사이킷런의 k-평균 모델로 과일을 알아서 구분하는 비지도학습 모델을 만들어보자!
.fit()
으로 모델 훈련 (단, 비지도학습이니 입력데이터만 넣어줌!)KMeans()
: 사이킷런에서 k-평균 알고리즘이 구현되어있는 클래스n_clusters
: 클러스터 개수를 지정하는 매개변수 (*).labels_
에 저장되어 있음. (0,1,2 순서 같은 건 의미 없음)np.unique()
를 활용!return_counts
: 고유값의 개수를 보여주는 옵션 매개변수draw_fruits
: arr
에 3차원 배열을 입력받아서 그림으로 출력해줄 함수.squeeze=False
: axs
를 항상 2차원 배열로 다루기 위해서 설정해줌.불리언 인덱싱
)fit
으로 찾았던 '클러스터 중심(=샘플 평균값)'은 .cluster_centers_
에 저장되어 있음. .transform()
메소드인데, 특정 샘플을 집어넣으면, 그 샘플과 클러스터 중심들까지의 거리로 반환해 줌..predict()
메소드도 제공함.predict
로 출력해보니 정말 그러함!.n_iter_
: 클러스터 중심을 옮기는 '반복 횟수'가 저장된 속성.transform()
과 .predict()
는 다른 군집 알고리즘엔 잘 없음. KMeans의 특징적인 메소드임...!n_cluster=3
으로 fit 했었음.1) 앞에서 .transform()
으로 구했던 '거리'의 제곱 합을 이너셔(inertia)라고 함.
2) 이 이너셔 값이 작다는 것은, 클러스터 중심에 샘플들이 조밀하게 잘 모여있다고 해석할 수 있음. (= 작을수록 좋다고 볼 수 있음)
3) 보통 클러스터 개수(k)를 늘리면, 더 곳곳에 센트로이드가 자리하니까 이너셔가 줄어듦.
.inertia_
: KMeans에서 자동으로 계산한 이너셔 값307p.
draw_fruits
함수 내에서n=len(arr)
로 정의하는데, arr에 3차원 데이터를 집어넣어도 len, 즉 '길이'라는 걸 계산할 수가 있는 건가요? 그냥 알아서 1차원으로 펼쳐서 개수를 세는 걸까요..?👨🏻🏫
len()
함수는 첫 번째 차원의 길이를 반환합니다. 🆗
⭐310p.
transform
함수를 사용할 때, fruits_2d[100] 으로 하는 것과 fruits[100:101]로 하는 것의 차이를 모르겠습니다ㅠㅠㅠfruits_2d[100]은 2차원 배열에서 101번째 원소(1차원 배열)를 선택합니다. 🆗
그러니까 이게, 그냥 [100]으로 '인덱싱'을 하게 되면 그냥 원소를 (1차원 크기로) 조회하게 되는 것인데, [100:101]로 '슬라이싱'을 하게 되면 2차원 배열을 형태가 유지된 채로 그 부분을 뽑아쓰는 거라고 보면 될 듯! 여기서transform
함수는 2차원 배열을 기대하니까 후자를 사용해야 하는 거고!
※ 그냥 [100]으로 출력해봐도 겉에 [ ]가 감싸져있어서 나는 그게 (1,10000) 크기의 리스트인 줄 알았다. 근데 그건 그냥 numpy array view 라고 한다 ..
이번엔 정말로 '타깃'이 없는 상황에서, 알아서 자기가 어떤 패턴을 학습하는 알고리즘을 배웠다. 수학적인 논리를 기반으로 알아서 학습하는 모델을 만든다는 게 새삼 신기했고, AI가 어떤 느낌인지 좀 더 가까이서 보게 된 느낌이다. 머신러닝만으로 할 수 있는 프로젝트를 하루빨리 찾아야한다! (* [11]에 나온 슬라이싱 문법 하나 때문에 애를 엄청나게 먹었다... 기본기를 더 다져야한다....)
타깃 모르는 상태에서 (제대로 된 비지도학습) 사진을 분류하기 위해 k-평균 알고리즘 도입 → 사이킷런의 KMeans 클래스를 사용하여 clustering → 군집 결과는 labels_
에, 계산된 '클러스터 중심'은 cluster_centers_
에 저장됨 → 결과를 이미지로 그려보니, 알아서 비슷한 것끼리 잘 묶었음!👏🏻 → transform()
메소드를 사용하면 특정 샘플을 거리로 변환하여, 데이터의 차원을 줄일 수 있음 & predict()
메소드도 제공함 → 하지만 KMeans는 결정적으로, 적절한 클러스터 개수를 사전에 지정해야 한다는 단점이 있음 → 이를 해결하기 위한 한 가지 방법으로, inertia_
를 활용한 엘보우 방법을 사용해 봄.