AI/혼공파 머신러닝+딥러닝

[ML 06-1] 군집 알고리즘

doocong22 2024. 5. 24. 20:32
728x90

타깃을 모르는 비지도 학습

타깃을 모르는 사진을 종류별로 분류하려면 어떻게 해야할까? 타깃이 없을 때 사용하는 머신러닝 알고리즘을 비지도 학습(unsupervised learning)이라고 한다. 사람이 가르쳐 주지 않아도 데이터에 있는 무언가를 학습하는 것이다. 처음엔 데이터의 픽셀값을 이용해서 사진을 분류할 수 있겠다는 생각을 할 수 있을 것이다.

과일 사진 데이터 준비하기

다음은 사과, 바나나, 파인애플을 담고 있는 흑백 사진 데이터이다.

관련 패키지를 임포트하고 파일을 로드하고 fruits배열의 크기를 확인한다.

이 배열의 첫번째 차원은 샘플의 개수를 나타내고, 두 번재 차원은 이미지 높이, 세 번째 차원은 이미지 너비이다. 각 픽셀은 넘파이 배열의 원소 하나에 대응한다. 즉 배열의 크기가 100 x 100이다.

첫 번째 행에 있는 픽셀 100개에 들어 있는 값을 출력함.

이 넘파이 배열은 흑백 사진을 담고 있으므로 0~255까지의 정숫값을 가진다.

맷플롯립의 inshow() 함수를 사용하면 넘파이 배열로 저장된 이미지를 쉽게 그릴 수 있다. 흑백 이미지이므로 cmap 매개변수를 'gray'로 지정한다.

첫 이미지는 사과 같다. 0에 가까울수록 검게 나타나고 높은 값은 밝게 표시된다. 보통 흑백 샘플 이미지는 바탕이 밝고 물체가 짙은 색이다. 그런데 왜 이렇게 보일까? 사실 이 흑백 이미지는 사진으로 찍은 이미지를 너마이 배열로 변환할 때 반전시킨 것이다. 사진의 흰 바탕은 검은색으로 만들고 실제 사과가 있어 짙은 부분은 밝은색으로 바꾸었다. 이는 우리의 관심 대상이 바탕이 아니라 사과이기 때문인데 흰색 바탕은 우리에게 중요하지 않지만 컴퓨터는 255(흰색)에 가까운 바탕에 집중할 것 이기 때문에 그렇게 하는 것이다. 픽셀값이 0이면 출력도 0이 되어 의미가 없다. 픽셀값이 높으면 출력값도 커지기 때문에 의미를 부여하기 좋다.

맷플롯립으로 출력할 때 바탕이 검게 나오는 것이 보기에는 썩 좋지 않다. cmap 매개변수를 'gray_r'로 지정하면 다시 반전하여 우리 눈에 보기 좋게 출력된다.

이 데이터는 사과, 바나나, 파인애플이 각각 100개씩 들어 있다. 바나나와 파인애플 이미지도 출력해보자.

맷플롯립의 subplots()함수를 사용하면 여러 개의 그래프를 배열처럼 쌓을 수 있도록 도와준다. subplots() 함수의 두 매개변수는 그래프를 쌓을 행과 열을 지정한다. 여기에서는 하나의 행과 2개의 열을 지정했다.

이제 샘플 데이터가 준비가되었다. 이 데이터의 처음 100개는 사과, 그다음 100개는 파인애플, 마지막 100개는 바나나이다. 각 과일 사진의 평균을 내서 차이를 확인해보자.

픽셀값 분석하기

넘파이 배열을 나눌 때 100 x 100 이미지를 펼쳐서 길이가 10000인 1차원 배열로 만들면 이미지로 출력하긴 어렵지만 배열을 계산할 때 편리해진다.

fruits배열에서 순서대로 100개씩 선택하기 위해 슬라이싱 연산자를 사용한다. 그다음 reshape() 메서드를 사용해 두 번째 차원(100)과 세 번째 차원(100)을 10000으로 합니다. 첫 번째 차원을 -1로 지정하면 자동으로 남은 차원을 할당한다. 여기에서는 첫 번째 차원이 샘플 개수이다. 이제 apple, pineapple, banana 배열의 크기는(100, 10000)이다. 사과를 확인해보자.

바나나, 파인애플도 확인해보면 같은 결과를 보인다.

이제 apple, pineapple, banana 배열에 들어 있는 샘플의 픽셀 평균값을 계산해 보자. 넘파이 mean() 메서드를 사용할 것 이다. 샘플마다 픽셀의 평균값을 계산해야 하므로 계산할 축을 지정해야한다. axis=0으로 하면 첫 번째 축인 행을 따라 계산한다. axis=1로 지정하면 두 번째 축인 열을 따라 계산한다.

샘플은 모두 가로로 값을 나열했으니 axis=1로 지정하여 평균을 계산하겠다.(앞서 2차원 배열을 1차원 배열로 치환했기에 가능한 계산이다.) 

사과 샘플 100개에 대한 픽셀 평균값이다.

맷플롯립의 hist()함수를 사용해 히스토그램으로 살펴보자. 각 과일에 대한 히스토그램을 모두 겹쳐 그릴 것이다. 이렇게 하려면 조금 투명하게 해야 겹친 부분을 잘 볼 수 있다. alpha 매개변수를 1보다 작게 하면 투명도를 줄 수 있다.

히스토그램을 보면 바나나는 사진에서 차지하는 영역이 작기 때문에 평균갑싱 작다. 하지만 사과와 파인애플을 많이 겹쳐있어서 픽셀값만으로는 구분하기 쉽지 않다. 둘 다 형태가 동그랗고 사진에서 차지하는 크기도 비슷하기 때문이다. 그래서 샘플의 평균값이 아니라 픽셀별 평균값을 비교해보는 방법을 사용해보자.

전체 샘플에 대해 한 픽셀이 얼마나 많이 사용되었는지 각 픽셀의 평균을 계산하는 것이다. 세 과일은 모양이 다르므로 픽셀값이 높은 위치가 조금씩 다를 것이다. 픽셀의 평균을 계산하려면 axis=0으로 지정하면 된다.

순서대로 사과, 파인애플, 바나나 그래프이다. 3개의 그래프를 보면 과일마다 값이 높은 구간이 다르다. 

픽셀 평균값을 100 x 100 크기로 바꿔서 이미지처럼 출력하여 위 그래프와 비교하면 더 좋다. 픽셀을 평균 낸 이미지를 모든 사진을 합쳐 놓은 대표이미지로 생각할 수 있다.

세 과일이 픽셀 위치에 따라 값의 크기가 차이 나는 것을 확인할 수 있다. 이 대표 이미지와 가까운 사진을 골라내면 과일을 구분할 수 있지 않을까?

평균값과 가까운 사진 고르기

사과 사진의 평균값인 apple_mean고 가장 가까운 사진을 골라보자. 절댓값 오차를 사용할 것이다. fruits 배열에 있는 모든 샘플에서 apple_mean을 뺀 절댓값의 평균을 계산하면 된다. 

그다음, 이 값이 가장 작은 순서대로 100개를 고를 것이다. 즉 apple_mean과 오차가 가장 작은 샘플 100개를 고르는 것이다. np.argsort()함수는 작은 것에서 큰 순서대로 나열한 abs_mean 배열의 인덱스를 반환한다. 이 인덱스 중에서 처음 100개를 선택해 10 x 10격자로 이루어진 그래프를 그릴 것이다.

apple_mean과 가장 가까운 사진 100개를 골랐더니 모두 사과이다!! 잘 분류가 되었다.

 

지금 까지 흑백 사진에 있는 픽셀값을 사용해 과일 사진을 모으는 작업을 해 보았다. 이렇게 비슷한 샘플끼리 그룹으로 모으는 작업을 군집(clustering)이라고 한다. 군집은 대표적인 비지도 학습 작업 중 하나이다. 군집 알고리즘에서 만든 그룹을 클러스터(cluster)라고 부른다.

728x90