06-1 군집 알고리즘
타깃을 모르는 비지도 학습
비지도 학습(unsupervised learning) : 타깃이 없을 때 사용하는 머신러닝 알고리즘
과일 사진 데이터 준비하기
Jupyter Notebook이나 Google Colab 같은 환경에서 사용되는 shell 명령어
!
: Jupyter Notebook에서 셸 명령어를 실행하기 위한 접두사
-O
: 저장할 파일 이름을 지정
이 배열의 첫 번째 차원(300) : 샘플의 개수
두 번째 차원(100) : 이미지 높이
세 번때 차원(100) : 이미지 너비
이미지 크기는 100×100 (각 픽셀은 넘파이 배열의 원소 하나에 대응)
우리가 보는 것과 컴퓨터가 처리하는 방식이 다르기 때문에 종종 흑백 이미지를 이렇게 반전하여 사용합니다.
관심 대상의 영역을 높은 값으로 바꾸었지만 맷플롯립으로 출력할 때 바탕이 검게 나오므로 cmap 매개변수를 ‘gray_r’로 지정하여 다시 반전하여 보기 좋게 출력합니다.
밝은 부분이 0에 가깝고 짙은 부분이 255에 가까운 값입니다.
fig
: 전체 그림(figure)을 의미
axs
: 2개의 서브플롯을 담고 있는 배열(리스트처럼 생긴 객체)
plt.subplots(1, 2)
: 1행 2열의 서브플롯을 생성하는 함수
cmap='gray_r'
: 색상맵을 반전된 흑백으로 지정
픽셀값 분석하기
넘파일 배열을 나눌 때 100×100 이미지를 펼쳐서 길이가 10,000인 1차원 배열로 만들면 이미지로 출력하긴 어렵지만 배열을 계산할 때 편리합니다.
axis=0
→ “열 단위로 계산” (행을 따라 내려가면서)
-
즉, 각 열(column)의 값을 기준으로 계산합니다.
-
예: 평균을 구하면, 각 열의 평균이 나옵니다.
axis=1
→ “행 단위로 계산” (열을 따라 가로로)
-
즉, 각 행(row)의 값을 기준으로 계산합니다.
-
예: 평균을 구하면, 각 행의 평균이 나옵니다.
사과와 파인애플은 많이 겹쳐있어서 픽셀값만으로는 구분하기 쉽지 않음
→ 샘플의 평균값이 아니라 픽셀별 평균값을 비교
각 샘플의 평균값 : 각 이미지를 한 장의 사진 → 한 개의 숫자로 만드는 방식
픽셀별 평균값 : 모든 이미지에서 같은 위치의 픽셀끼리 평균을 냄
여기서 axs
는 matplotlib의 subplot(여러 개의 그래프 영역)을 한 번에 만들었을 때, 각 그래프 영역(axes 객체)**를 담고 있는 배열
평균값과 가까운 사진 고르기
abs_diff의 크기 (300, 100, 100)
- 300 → 사진이 300장 있음 (샘플 개수)
- 100 → 한 장의 사진 높이 (픽셀 수)
- 100 → 한 장의 사진 너비 (픽셀 수)
즉, 300장의 흑백 사진이 있고, 각 사진은 100×100 픽셀로 되어 있음.
그래서 전체 데이터는 3차원 배열 (사진 개수, 높이, 너비)
모양이 됨.
axis=(1,2)
의미
- axis=1 → 사진의 “높이 방향”
- axis=2 → 사진의 “너비 방향”
(1, 2)
를 같이 지정하면 → 각 사진의 모든 픽셀을 평균낸다는 뜻.
abs_mean
의 크기 (300,)
- 사진 한 장(100×100) → 평균을 내면 숫자 1개가 됨.
- 300장의 사진 → 숫자 300개가 나옴.
- 그래서
(300,)
→ 길이가 300인 1차원 배열이 됨.
apple_index = np.argsort(abs_mean)[:100]
abs_mean
에는 각 사진이 사과 평균 사진과 얼마나 다른지(차이 평균값)가 들어 있음np.argsort(abs_mean)
→ 차이가 작은 순서대로 사진의 인덱스(번호)를 정렬[:100]
→ 그 중에서 가장 사과에 가까운 사진 100장만 선택
apple_index = apple_index.reshape(10, 10)
- 100장의 사진을 10×10 형태로 바꿈 (나중에 그래프를 10행 10열에 맞춰서 그림)
fig, axs = plt.subplots(10, 10, figsize=(10,10))
- 10행 10열짜리 빈 그림판(
axs
)을 만듦 figsize=(10,10)
→ 전체 그림 크기를 10×10 인치로 설정
for i in range(10):
for j in range(10):
axs[i, j].imshow(fruits[apple_index[i, j]], cmap='gray_r')
axs[i, j].axis('off')
- 10×10 반복문을 돌면서 각 위치(
axs[i, j]
)에 사과에 가장 가까운 사진을 차례대로 그림 cmap='gray_r'
→ 흑백(역상)으로 표시[:100]
→ 그 중에서 가장 사과에 가까운 사진 100장만 선택
군집(clustering) : 비슷한 샘플끼리 그룹으로 모으는 작업
클러스터(cluster) : 군집 알고리즘에서 만든 그룹
06-2 k-평균
k-평균(k-means) 군집 알고리즘 이 평균값을 자동으로 찾아줍니다.
이 평균값이 클러스터의 중심에 위치하기 때문에 클러스터 중심(cluster center) 또는 센트로이드(centroid)라고 부릅니다.
k-평균 알고리즘 소개
- 무작위로 k개의 클러스터 중심을 정합니다.
- 각 샘플에서 가장 가까운 클러스터 중심을 찾아 해당 클러스터의 샘플로 지정합니다.
- 클러스터에 속한 샘플의 평균값으로 클러스터 중심을 변경합니다.
- 클러스터 중심에 변화가 없을 때까지 2번으로 돌아가 반복합니다.
KMeans 클래스
사이킷런의 k-평균 알고리즘은 sklearn.cluster 모듈 아래 KMeans 클래스에 구현되어 있습니다.
이 클래스에서 설정할 매개변수는 클러스터 개수를 지정하는 n_clusters입니다.
레이블값 0,1,2와 레이블 순서에는 어떤 의미도 없습니다.
실제 레이블 0,1,2가 어떤 과일 사진을 주로 모았는지 알아보려면 직접 이미지를 출력하는 것이 최선입니다.
.labels_
속성 → 각 데이터 포인트가 어느 클러스터에 속하는지 나타내는 배열
np.unique()
→ 배열 안에서 고유값(중복 없는 값)을 찾아서 정렬해 반환
return_counts=True
→ 각 고유값이 몇 번 등장했는지도 함께 반환
첫 번째 배열 → 클러스터 번호 목록
두 번째 배열 → 각 클러스터에 속한 샘플 개수
draw_fruits(arr, ratio=1)
arr
배열(예: 여러 장의 과일 이미지)을 받아서 여러 이미지를 그리드(격자) 형태로 예쁘게 한 번에 보여주는 함수- (샘플 개수, 너비, 높이)의 3차원 배열을 입력받으며 가로로 10개씩 이미지를 출력
ratio
는 각 이미지 크기 조절에 쓰임.
n = len(arr)
arr
에 들어있는 이미지 개수를 저장
rows = int(np.ceil(n/10))
- 한 행에 최대 10개씩 놓는다고 가정
np.ceil(n/10)
는 n을 10으로 나눈 후 올림 (예: 35 → 3.5 → 4행 필요)int()
는 정수형으로 변환- 즉, 필요한 행(row) 개수 계산
cols = n if rows < 2 else 10
- 만약 이미지 개수가 10개 이하면 → 한 행에 다 놓음 (
cols = n
) - 10개 넘으면 → 열은 무조건 10개 (
cols = 10
)
fig, axs = plt.subplots(rows, cols, figsize=(cols*ratio, rows*ratio), squeeze=False)
plt.subplots
로rows x cols
크기의 빈 그래프판 만들기figsize
→ 전체 그림 크기 설정 (가로cols * ratio
, 세로rows * ratio
)squeeze=False
→axs
를 항상 2차원 배열로 만들어서 인덱싱 편하게 함
for i in range(rows):
for j in range(cols):
if i*10 + j < n:
axs[i, j].imshow(arr[i*10 + j], cmap='gray_r')
axs[i, j].axis('off')
- 2중 for문으로
rows
행,cols
열만큼 반복 i*10 + j
는 현재 그리드에서 몇 번째 이미지를 그릴지 계산- 만약 인덱스가 이미지 개수
n
보다 작으면 →axs[i, j].imshow()
로 해당 위치에 이미지 그림 axs[i, j].axis('off')
→ 축 눈금이나 테두리 표시 안 함
불리언 인덱싱(Boolean Indexing) : 배열(예: NumPy 배열)에서 조건에 맞는 원소들만 선택해서 추출하는 방법
배열에서 True
또는 False
값을 가진 같은 크기의 불리언 배열을 만들어서,
True
인 위치에 해당하는 원소들만 골라내는 방식