당신은 주제를 찾고 있습니까 “파이썬 군집 분석 – [파이썬 실습] 군집분석“? 다음 카테고리의 웹사이트 you.charoenmotorcycles.com 에서 귀하의 모든 질문에 답변해 드립니다: https://you.charoenmotorcycles.com/blog/. 바로 아래에서 답을 찾을 수 있습니다. 작성자 김성범[ 소장 / 인공지능공학연구소 ] 이(가) 작성한 기사에는 조회수 5,356회 및 좋아요 29개 개의 좋아요가 있습니다.
파이썬 군집 분석 주제에 대한 동영상 보기
여기에서 이 주제에 대한 비디오를 시청하십시오. 주의 깊게 살펴보고 읽고 있는 내용에 대한 피드백을 제공하세요!
d여기에서 [파이썬 실습] 군집분석 – 파이썬 군집 분석 주제에 대한 세부정보를 참조하세요
파이썬 군집 분석 주제에 대한 자세한 내용은 여기를 참조하세요.
고객 유형을 나누기(파이썬 클러스터링, 군집 분석 … – Everly.
고객 유형을 나누기(파이썬 클러스터링, 군집 분석) / 파이썬 데이터 분석 실무 테크닉 100. Everly. 2022. 4. 6. 09:20. 안녕하세요, Everly입니다.
Source: suy379.tistory.com
Date Published: 6/17/2021
View: 6137
[Python] 사이킷런(sklearn)을 활용한 K-평균 군집분석(K-Means …
비지도 학습 중 유사한 속성을 가진 데이터끼리 군집을 만들어주는 클러스터링(군집분석)을 학습해 보겠습니다. sklearn에서 제공하는 iris(붓꽃) …
Source: planharry.tistory.com
Date Published: 6/25/2021
View: 4478
[Python 머신러닝] 8장. 군집분석 (Cluster Analysis)
군집분석이란? 서로 유사한 정도에 따라 다수의 객체를 군집으로 나누는 작업 또는 이에 기반한 분석을 의미한다. – 유사도가 높은 데이터끼리 그룹화 …
Source: joyfuls.tistory.com
Date Published: 3/9/2022
View: 7670
[python] 자연어처리(NLP) – Kmeans, K대푯값 군집 분석
이제는 군집분석을 파이썬으로 구현하여 보겠습니다. 우선 데이터를 준비해 주어야 하는데요. 저는 네이버 api를 이용해 뉴스 제목, 요약, …
Source: wonhwa.tistory.com
Date Published: 2/12/2022
View: 5825
[ML] 군집분석(K-means, K-means++) – 데이터분석
파이썬 활용하여 K-평균 군집분석 진행하기 # 무작위 데이터셋 생성 from sklearn.datasets import make_blobs X, y = make_blobs(n_samples = 150, …
Source: hyunse0.tistory.com
Date Published: 8/30/2021
View: 4986
K-Means 클러스터링 파이썬 연습 예제 – 고객 구매 데이터 분석
ZipCode와 Product는 군집 분석 결과를 해석할 때 사용한다. 즉,남은 ItemsBought과 ItemsReturned로 클러스터링을 한다.
Source: lucy-the-marketer.kr
Date Published: 8/30/2021
View: 1280
[머신러닝] 군집분석, 군집화 (파이썬 싸이킷런) – 네이버블로그
[머신러닝] 군집분석, 군집화 (파이썬 싸이킷런) – 레이블되지 않은 … [ 머신러닝 교과서 with 파이썬, 사이킷런, 텐서플로 _ 세바스찬 라시카, …Source: blog.naver.com
Date Published: 3/14/2022
View: 3796
14 장 군집분석 | 데이터과학 – Big data Lab.
14 장 군집분석 | 데이터과학. … 군집분석. 모집단 또는 범주에 대한 사전 정보가 없는 경우 주어진 관측값들 사이의 거리(distance) 또는 … 14.3 Python 예제.
Source: bigdata.dongguk.ac.kr
Date Published: 11/20/2022
View: 3791
주제와 관련된 이미지 파이썬 군집 분석
주제와 관련된 더 많은 사진을 참조하십시오 [파이썬 실습] 군집분석. 댓글에서 더 많은 관련 이미지를 보거나 필요한 경우 더 많은 관련 기사를 볼 수 있습니다.
주제에 대한 기사 평가 파이썬 군집 분석
- Author: 김성범[ 소장 / 인공지능공학연구소 ]
- Views: 조회수 5,356회
- Likes: 좋아요 29개
- Date Published: 2021. 5. 29.
- Video Url link: https://www.youtube.com/watch?v=_U7AUJqzlJs
고객 유형을 나누기(파이썬 클러스터링, 군집 분석) / 파이썬 데이터 분석 실무 테크닉 100
안녕하세요, Everly입니다.
정말 오랫만에 ‘파이썬 분석 실무 테크닉’ 공부한 부분을 리뷰하는데요! (3달 만이군요..) 앞으로는 좀 더 자주 업로드해보도록 하겠습니다 🙂
오늘은 지난 포스팅에서 다뤘던 스포츠 센터(편의상 헬스장) 데이터를 바탕으로, 이 헬스장을 사용하는 고객이 어떤 유형이 있고, 고객의 행동을 에측하는 데이터 분석을 공부해봅니다.
이번 포스팅에서는 클러스터링(clustering)을 통해 고객의 유형을 나눠 보고,
바로 다음 포스팅에서는 고객의 과거 데이터를 기반으로 예측하는 머신러닝 모델을 만들어 봅니다.
[고객의 소리] 지난번 분석으로 어느 정도 경향을 파악할 수 있었습니다. 아직 전체적인 경향밖에 파악하지 못해서, 이번에는 좀 더 구체적인 분석을 부탁드리려고 합니다.고객별로 이용 경향이 다르기 때문에 이런 경향을 분석해서 고객별 이용 횟수 같은 것도 예측할 수 있지 않을까라는 생각이 듭니다. 이런 분석도 가능할까요?
지난 포스팅에서 사용했던 데이터를 그대로 사용합니다.
use_log.csv : 헬스장 이용이력 데이터. (기간: 2018.04 ~ 2019.03)
customer_join.csv : 앞서 [파이썬 데이터 분석 #3] 포스팅에서 가공한, 이용 이력을 포함한 고객 데이터.
지난번 [파이썬 데이터 분석 #3] 포스팅을 통해, 헬스장을 사용하는 고객들의 특징에 대해 몇 가지 인사이트를 도출해 봤었죠. 고객 1인당 월평균 5회 정도를 사용하고 있었고, 지속적으로 이용하는 사람(flag 변수)도 전체의 81%나 있었습니다. 또한 회원 기간의 분포를 살펴보니 10개월을 기점으로 회원 기간 분포가 뚝 끊기는 것을 볼 수 있어, ‘마의 10개월’을 발견하기도 했습니다.
이러한 인사이트는 전체 고객을 대상으로 본 것이었습니다. 하지만 이번에는 좀 더 구체적으로, 어떤 유형의 고객들이 있는지가 궁금합니다. 자주 이용하는 고객 그룹과, 아닌 그룹이 있지 않을까요? 이를 나누기 위해선 어떤 변수를 사용해서 나눌 수 있을까요? 좀 더 자세히 알아보겠습니다.
✔Table of Contents
Tech 31. 데이터 불러오기
import pandas as pd ul = pd.read_csv(‘3장/use_log.csv’) c = pd.read_csv(‘customer_join.csv’) ul.isnull().sum() c.isnull().sum()
use_log 데이터는 ‘ul’, customer_join 데이터는 ‘c’로 불러옵니다.
결측치를 확인해 보니 ul은 없고, c의 경우 end_date(탈퇴시점)에 2842개의 결측치가 있네요. 아직 탈퇴를 하지 않은 회원은 이렇게 end_date에 결측값이 있습니다. 딱히 이상 없는 데이터입니다.
Tech 32. 클러스터링을 활용한 회원 그룹화
※ 클러스터링(Clustering) 이란?
– 군집 분석이라고도 하며, 정답 데이터가 없기 때문에 ‘비지도학습’ 의 일종입니다.
주로 고객을 그룹화하는 등 공통된 특성을 가진 군집들로 묶는 알고리즘을 의미합니다. 가장 유명한 것은 K-means 클러스터링인데, 이번 장에서도 이를 활용합니다.
클러스터링은 ‘c’ 데이터로 진행합니다. 회원의 이용이력에 따라 고객을 유형화해볼 수 있을 것 같네요. 그래서 회원의 이용이력과 관련한 변수를 사용합니다.
cc = c[[‘mean’, ‘median’, ‘max’, ‘min’, ‘mem_period’]] cc.head()
바로 mean, median, max, min, mem_period인데요. 각각 고객별 한달 평균, 중위수, 최대, 최소 이용횟수와 회원 기간(단위: month)입니다.
c 데이터는 유일한 고객별 이용이력을 담고 있습니다. 이를테면 c 데이터의 0번 행의 고객은, 한 달 평균 4.83회를 사용하고, 한달 중위수 5회, 한달에 최소 2회~최대 8회까지 사용하네요.
어쨌든 이러한 컬럼들만 따로 떼어 변수 ‘cc’를 만들어줍니다.
이제 k-means 클러스터링을 실시합니다. 단, 조건이 있습니다.
<조건>
#1. 그룹 개수 설정: 4개
#2. mean, median, max, min 변수는 월 이용 횟수와 관련한 변수이므로 1~8 사이값을 갖지만, mem_period는 이에 비해 값이 너무 크다. -> 그러므로 mem_period에는 표준화를 하자.
2번 조건을 토대로 5개 변수의 값을 평균 0, 표준편차 1을 따르는 정규분포를 따르도록 바꿔줍니다. 이를 ‘표준화’라고 합니다.
이런 과정을 거치지 않고 그냥 클러스터링을 해버리면 값이 너무 큰 ‘mem_period’ 변수가 가장 중요한 변수로 인식될 수 있고 올바른 클러스터링이 불가능하기 때문에 표준화를 해줍니다.
from sklearn.cluster import KMeans from sklearn.preprocessing import StandardScaler #표준화 sc = StandardScaler() cc_scaled = sc.fit_transform(cc) pd.DataFrame(cc_scaled) #mean~min, mem_period 5개 변수가 표준화됨.
표준화를 통해 위의 5가지 변수가 이와 같이 바뀌었습니다. 모든 변수의 값이 비슷해졌죠? 이 데이터는 ‘cc_scaled’ 입니다.
#cc_scaled 데이터를 넣어 클러스터링 kmeans = KMeans(n_clusters=4, random_state=0) clusters = kmeans.fit(cc_scaled) #클러스터링 변수인 clusters 값을 원본 데이터인 ‘cc’내에 넣기 cc[‘cluster’] = clusters.labels_ cc.head()
위의 코드를 통해 군집이 4개(n_clusters)인 k-means 클러스터링을 수행할 수 있습니다.
어떤 클러스터가 만들어졌는지는 labels_ 메서드를 통해 알 수 있는데요, 더 쉽게 알아보기 위해 초반에 만들어 둔 ‘cc’ 데이터(변수 5개만 있는 데이터프레임)에 ‘clsuter’라는 새로운 컬럼을 만들어 클러스터 번호를 넣어줍니다.
이렇게 ‘cluster’ 컬럼이 새로 생겼음을 알 수 있죠.
unique 메서드를 활용하면 cluster가 0, 1, 2, 3 이렇게 4개가 생성되었음을 알 수 있습니다. 이제, k-means 알고리즘이 자동으로 군집화해준 이 클러스터가 어떤 특징을 띠고 있는지를 분석해봅시다.
Tech 33. 클러스터링 결과 분석
#먼저 열 이름을 알아보기 쉽게 한글로 바꾼다. cc.rename(columns = {‘mean’:’월평균값’, ‘median’:’월중앙값’, ‘max’:’월최댓값’, ‘min’:’월최솟값’, ‘mem_period’:’회원기간’}, inplace=True) cc
#cluster를 기준으로 데이터 개수 세기 cc.groupby(‘cluster’).count()
#그룹별 특징을 알아보자! -그룹별 평균값 cc.groupby(‘cluster’).mean()
groupby를 통해 다양한 통계량을 알아봅니다.
count() 메서드를 통해선 각 클러스터(그룹)별로 개수가 몇개인지를 셉니다. 그룹 0이 1334개로 가장 많이 들어있고, 그룹3 > 그룹2 > 그룹 1 순이네요.
다음은 mean() 메서드를 통해 각 클러스터별 평균값을 알아봅니다.
그룹 2는 평균 회원기간은 가장 짧지만(7일), 월평균 이용횟수는 8회로 가장 높네요.
그룹 1은 평균 회원기간도 9일로 짧은데다가 월평균 이용횟수는 3회로 가장 낮습니다.
그룹 0, 그룹 3은 평균 회원기간이 그룹 1, 2보다는 깁니다. 그런데 그룹 3은 그룹 0보다 회원기간은 길지만(36일 > 14일), 월평균 이용횟수는 더 적습니다(4.6회 < 5.5회) 이렇게 그룹의 특징을 파악해보면, 그룹별로 다른 캠페인이나 프로모션을 사용할 수 있겠죠? 여기서는 사용한 변수가 단 5개이지만, 더 특징적인 변수를 포함시킨다면 보다 복잡한 클러스터링도 가능합니다. 이제는 이 클러스터링 결과를 눈으로 보기 쉽도록 그래프로 나타내봅시다. Tech 34. 클러스터링 결과 시각화(차원 축소 활용) 하지만 문제가 생깁니다. 보통 우리가 그리는 그래프는 2차원입니다. 그런데 여기서 사용한 변수는 5개로, 5차원 그래프는 그리기도 힘들뿐더러 이해하기도 쉽지 않습니다. 여기서 우리는 5개의 변수를 2개의 변수로 줄이는 작업을 통해, 2차원 그래프로 나타내봅니다. 이것이 바로 '차원 축소'인데요, 대표적인 차원 축소 방법인 PCA(Principal Component Analysis)를 수행합니다. ※ 차원 축소란? - 정보를 되도록 잃지 않게 하면서 새로운 축을 만드는 기법. 여기서 사용하는 차원축소 기법 중 하나인 PCA는 주성분분석이라고도 하며, 5개의 변수를 2개의 주성분(정보를 가장 많이 담고 있는) 으로 만듭니다. from sklearn.decomposition import PCA X = cc_scaled.copy() #객체 pca = PCA(n_components=2) #적용 pca.fit(X) x_pca = pca.transform(X) x_pca 앞서 만들었던 표준화 변수 'cc_scaled'를 copy한 새로운 변수 'X'를 만들어 PCA를 적용했습니다. 결과가 array 형태라 보기가 불편하네요. 보기 쉽게 데이터프레임으로 바꿔봅시다. 클러스터 넘버도 포함해서요! #x_pca를 보기 쉽게 데이터프레임으로 만들기 pca_df = pd.DataFrame(x_pca) pca_df['cluster'] = cc['cluster'] pca_df.head() 이와 같이 5개였던 변수가 2개의 주성분으로 바뀌었습니다. 어차피 컬럼만 줄어든 것뿐, 행의 수는 똑같으니까 cc 데이터의 'cluster' 컬럼으로 그대로 가져와도 문제없습니다. 이제는 2개의 주성분 변수를 2차원 그래프로 나타내봅시다. 저는 교재 외의 방법으로 seaborn, matplotlib 라이브러리 2가지를 사용해 만들어 보았습니다. import matplotlib.pyplot as plt import seaborn as sns axs = plt.subplots() axs = sns.scatterplot(0, 1, hue='cluster', data=pca_df) seaborn 라이브러리 사용 for i in sorted(pca_df['cluster'].unique()): tmp = pca_df.loc[pca_df['cluster'] == i] #해당하는 클러스터 번호일 때 그림을 그리고, for문 실행하며 위에 덧그림 plt.scatter(tmp[0], tmp[1]) plt.legend(sorted(pca_df['cluster'].unique())) matplotlib 라이브러리 사용 코드는 seaborn이 더 간단해서 저는 보통 seaborn을 애용하는 편입니다. scatterplot 메서드를 사용해 변수 2개를 넣어주고, 'hue' 옵션을 통해 클러스터별로 색상을 다르게 할 수 있습니다. matplotlib을 사용하려면 for문을 활용해, 각 클러스터별로 scatter plot을 그리고 위에 덧그리는 방식을 활용합니다. 이를테면 클러스터 0번이 파란색으로 칠해지고, 그 다음 클러스터 1번이 주황색으로 그 위에 덧그려집니다. 이를 위해선 클러스터 번호에 해당하는 i 를 for문의 인자로 사용합니다. 참고로 sorted(pca_df['cluster'].unique()) <- 이 코드에서 sorted를 사용하였는데요, 사실 sorted를 쓰지 않아도 그래프는 비슷합니다. sorted는 정렬을 해주는 함수인데, 얘를 쓰지않으면 클러스터 번호가 뒤죽박죽이 되어서 개인적으로 정렬되어 있는 형태를 좋아하는 편이라(ㅎㅎ,,) 사용해주었습니다. 어쨌든, 결과를 보면 두 그래프 모두 아주 깨끗하게 색깔이 나뉘어 있음을 볼 수 있죠? 정보를 보존한 채, 깔끔하게 데이터를 축소했음을 알 수 있습니다. (참고로, 주성분의 개수를 적절치 않게 설정하면 그래프가 겹치게 그려집니다.) 이제 이 결과를 활용하여, 탈퇴 회원의 경향을 파악해봅시다. 이번 포스팅의 마지막 파트입니다. Tech 35. 클러스터별 회원 특징 파악하기(탈퇴, 정기적 이용 여부) 앞서 만든 4개의 클러스터에서 지속회원(탈퇴하지 않은 회원)과 탈퇴회원은 얼마나 있을까요? 탈퇴여부를 파악하고 싶으므로, 'cc' 데이터에 원본 데이터인 'c' 데이터를 붙입니다. 'c' 데이터에 'is_deleted(탈퇴여부)' 열이 포함되어 있기 때문입니다. (참고로 is_deleted 값이 1이면 탈퇴, 0이면 지속회원입니다.) #앞서 만든 cc에서 지속/탈퇴회원 여부를 알아야 하므로 'is_deleted' 열을 추가한다. (이 열은 c 데이터에 있으므로 둘을 조인) cc_join= pd.concat([cc, c], axis=1) cc_join.head() pd.concat 함수를 사용하여 'cc' 데이터에 'c' 데이터가 조인된 'cc_join' 데이터가 만들어졌습니다. 우리가 필요한 것은 클러스터별 탈퇴여부이므로, 이에 대해 groupby를 해서 해당 회원이 몇 명이나 있는지 알아봅시다. newdf = cc_join.groupby(['cluster','is_deleted'], as_index=False).count()[['cluster', 'is_deleted', 'customer_id']] newdf 이렇게 결과가 나왔습니다. 교재에서는 여기서 끝냈지만, 저는 클러스터 및 탈퇴여부별 고객 비율이 궁금했습니다. 이를 자동으로 출력해주면 편하지 않을까 싶어 코드를 이렇게 짜봤습니다. #위의 newdf에서 cluster별 탈퇴 및 미탈퇴회원 비율을 for문으로 뽑아보자. de0 = (newdf['is_deleted']==0) #지속회원 de1 = (newdf['is_deleted']==1) #탈퇴회원 for i in range(0, 4): tmp = (newdf['cluster']==i) print('Cluster '+ str(i) + '의 탈퇴회원 비율은 ' + str(round((newdf.loc[(tmp & de1), 'customer_id'].sum() / newdf.loc[tmp, 'customer_id'].sum())*100, 2)) + '%') print('Cluster '+ str(i) + '의 지속회원 비율은 ' + str(round((newdf.loc[(tmp & de0), 'customer_id'].sum() / newdf.loc[tmp, 'customer_id'].sum())*100, 2)) + '%') print(' ') 이렇게 데이터프레임의 loc 메서드를 활용하면 쉽게 출력해볼 수 있습니다. (저는 loc 애용자입니다,,) 아무튼 뽑힌 결과를 읽어보면, 클러스터별로 탈퇴회원과 지속회원의 수를 알아볼 수 있네요! 클러스터 1: 탈퇴회원만 존재 클러스터 2,3: 지속회원 >> 탈퇴회원
클러스터 0: 지속회원과 탈퇴회원 수 비슷
앞서,
클러스터 2는 평균 회원기간은 가장 짧지만, 월 평균 이용횟수는 가장 높았다.
클러스터 1은 평균 회원기간도 짧고 월평균 이용횟수도 적은 그룹이다.
클러스터 0, 3은 평균 회원기간은 클러스터 1,2보다는 길다. 그런데 그룹3은 그룹0보다 회원기간은 길지만, 이용횟수는 더 적은 편이다.
였음을 참고하면, 다음과 같이 정리해볼 수 있겠네요!
– 클러스터 1: 가장 안좋은 그룹 (가장 짧게 이용하고, 모두 탈퇴함.)
– 클러스터 2: 초반에 불타오르는 좋은 그룹 (이용횟수가 많고 지속회원이 많다. 그런데 평균 회원기간이 짧아서 초기에 의욕적으로 이용하는 그룹인 듯)
– 클러스터 3: 안정적인 그룹 (회원기간이 길고, 이용횟수는 적으나 지속회원이 많다.)
– 클러스터 0: 회원기간이 길고, 탈퇴회원과 지속회원이 비등비등한 그룹.
다음으로는 정기적 이용여부(flag 컬럼)을 살펴봅니다. 이 또한 앞에서와 마찬가지로, 클러스터 및 flag 컬럼별 회원 수를 세면 되겠죠? (*flag 열은 ‘파이썬 데이터 분석 #3’ 포스팅에서 자체제작한 컬럼인데, 1이면 정기적으로 이용하고 0이면 비정기적으로 이용함을 의미합니다)
newdf2 = cc_join.groupby([‘cluster’,’flag’], as_index=False).count()[[‘cluster’, ‘flag’, ‘customer_id’]] newdf2
마찬가지로 이렇게는 보기가 좀 힘드니 앞서 만든 for문을 살짝 수정해서 비율을 뽑아봅니다.
#마찬가지로 for문으로 비율을 자동출력해보자. flag0 = (newdf2[‘flag’]==0) #비정기회원 flag1 = (newdf2[‘flag’]==1) #정기회원 for i in range(0, 4): tmp = (newdf2[‘cluster’]==i) print(‘Cluster ‘+ str(i) + ‘의 정기회원 비율은 ‘ + str(round((newdf2.loc[(tmp & flag1), ‘customer_id’].sum() / newdf2.loc[tmp, ‘customer_id’].sum())*100, 2)) + ‘%’) print(‘Cluster ‘+ str(i) + ‘의 비정기회원 비율은 ‘ + str(round((newdf2.loc[(tmp & flag0), ‘customer_id’].sum() / newdf2.loc[tmp, ‘customer_id’].sum())*100, 2)) + ‘%’) print(‘ ‘)
결과를 해석해보면 앞서 나타난 결과와 비슷합니다.
클러스터 1: 가장 이용을 적게하는 그룹 -> 정기 35% < 비정기 65% 클러스터 2: 초반에 불타오르는 좋은 그룹 -> 정기 93% >> 비정기 6%
클러스터 3: 안정적 이용그룹 -> 정기 99% >> 비정기 0.1%
클러스터 0: 지속, 탈퇴 비등한 그룹 -> 정기 83% > 비정기 17% (정기가 조금 더 많다)
만일 제가 이 헬스장의 마케터라면 클러스터 2와 3에 해당하는 회원을 꽉 잡을 마케팅을 해볼 것 같네요!
이렇게 이번 포스팅을 마칩니다. 이번 포스팅에서는 헬스장 고객 데이터에 클러스터링(군집분석)을 활용해, 좀 더 구체적인 데이터 분석을 해보았습니다.
지금까지의 분석을 통해, 회원의 이용 방법(회원의 행동 데이터)가 정말 중요함을 알 수 있었습니다.
다음 포스팅에서는 회원의 “이용 횟수”를 예측하는 모델을 만들어봅니다. 고객의 과거 행동 데이터로부터, 알지 못하는 다음 달 이용횟수를 예측해봅니다.
감사합니다. 궁금한 점이 있으시면 언제든 댓글 주세요 🙂
반응형
[Python] 사이킷런(sklearn)을 활용한 K-평균 군집분석(K-Means Clustering)
비지도 학습 중 유사한 속성을 가진 데이터끼리 군집을 만들어주는 클러스터링(군집분석)을 학습해 보겠습니다.
sklearn에서 제공하는 iris(붓꽃) 데이터를 활용하겠습니다. 분류형 모델에서 많이 사용됩니다~
1. 데이터 불러오기
# 필요한 패키지 설치 import pandas as pd import numpy as np # iris 데이터 불러오기 위한 datasets 설치 from sklearn import datasets
2. 분석에 사용할 학습용 데이터 만들기
# skearn.datasets에 포함된 iris(붓꽃) 데이터 가져오기 iris = datasets.load_iris() # iris 데이터 내 data값들 data= pd.DataFrame(iris.data) ; data # iris데이터의 feature 이름 feature= pd.DataFrame(iris.feature_names) ; feature # data의 컬럼명을 feature이름으로 수정하기 data.columns = feature[0] # 세가지 붓꽃의 종류 target=pd.DataFrame(iris.target) ; target # 컬럼명 바꾸기 target.columns=[‘target’] # data와 target 데이터프레임을 합치기 (axis=1, columns으로 합치기) df= pd.concat([data,target], axis=1) df.head()
3. 데이터 구조 확인(컬럼 타입과 결측치 등)
df.info()
#target 컬럼을 object 타입으로 변경 df = df.astype({‘target’: ‘object’})
# 결측치 없음, 각 속성마다 150개 row씩 있음 df.describe()
# 클러스터 돌리기 전 변수를 생성 df_f = df.copy()
4. 시각화 하기
import seaborn as sns from matplotlib import pyplot as plt from mpl_toolkits.mplot3d import Axes3D from mpl_toolkits.mplot3d import proj3d
sns.pairplot(df_f, hue=”target”) plt.show()
위 그림 3열에 petal length를 가지고도 어느정도 분류가 가능하겠네요.
그래도 4개 속성을 모두 가지고 클러스터링을 해보겠습니다.
원하는 속성을 사용해서 2차원, 3차원 그래프도 자세하게 그려보겠습니다.
# 2차원 그리기 fig = plt.figure(figsize=(5,5)) X = df_f plt.plot( X.iloc[:,0] , X.iloc[:,3] , ‘o’ , markersize=2 , color=’green’ , alpha=0.5 , label=’class1′ ) plt.xlabel(‘x_values’) plt.ylabel(‘y_values’) plt.legend() #범례표시 plt.show()
# 3차원 그리기 fig = plt.figure(figsize=(8, 8)) ax = fig.add_subplot(111, projection=’3d’) X = df_f # 3d scatterplot 그리기 ax.scatter( X.iloc[:,0] , X.iloc[:,1] , X.iloc[:,2] # , c=X.index #마커컬러 , s=10 #사이즈 , cmap=”orange” #컬러맵 , alpha=1 #투명도 , label=’class1′ #범례 ) plt.legend() #범례표시 plt.show()
5. K-Means cluster
from sklearn.cluster import KMeans
# 적절한 군집수 찾기 # Inertia(군집 내 거리제곱합의 합) value (적정 군집수) ks = range(1,10) inertias = [] for k in ks: model = KMeans(n_clusters=k) model.fit(df_f) inertias.append(model.inertia_) # Plot ks vs inertias plt.figure(figsize=(4, 4)) plt.plot(ks, inertias, ‘-o’) plt.xlabel(‘number of clusters, k’) plt.ylabel(‘inertia’) plt.xticks(ks) plt.show()
k개수가 3에서 완만하게 변하기 때문에 군집을 3개로 하면 적당할 것 같습니다.
# K-Means 모델과 군집 예측값을 생성 # 클러스터 모델 생성 파라미터는 원할 경우 추가 clust_model = KMeans(n_clusters = 3 # 클러스터 갯수 # , n_init=10 # initial centroid를 몇번 샘플링한건지, 데이터가 많으면 많이 돌릴수록안정화된 결과가 나옴 # , max_iter=500 # KMeans를 몇번 반복 수행할건지, K가 큰 경우 1000정도로 높여준다 # , random_state = 42 # , algorithm=’auto’ ) # 생성한 모델로 데이터를 학습시킴 clust_model.fit(df_f) # unsupervised learning # 결과 값을 변수에 저장 centers = clust_model.cluster_centers_ # 각 군집의 중심점 pred = clust_model.predict(df_f) # 각 예측군집 print(pd.DataFrame(centers)) print(pred[:10])
[1 1 1 1 1 1 1 1 1 1]# 원래 데이터에 예측된 군집 붙이기 clust_df = df_f.copy() clust_df[‘clust’] = pred clust_df.head()
여기서 target의 번호와 clust의 번호가 다른것은 군집이 잘못나온게 아니라 넘버링된 번호가 다를 뿐입니다.
스케일링 한 후에 아래에서 잘 묶여 나왔는지 확인하겠습니다.
6. 군집분석 결과를 가지고 시각화 하기
# scaling하지 않은 데이터를 학습하고 시각화하기 plt.figure(figsize=(20, 6)) X = clust_df plt.subplot(131) sns.scatterplot(x=X.iloc[:,0], y=X.iloc[:,1], data=df_f, hue=clust_model.labels_, palette=’coolwarm’) plt.scatter(centers[:,0], centers[:,1], c=’black’, alpha=0.8, s=150) plt.subplot(132) sns.scatterplot(x=X.iloc[:,0], y=X.iloc[:,2], data=df_f, hue=clust_model.labels_, palette=’coolwarm’) plt.scatter(centers[:,0], centers[:,2], c=’black’, alpha=0.8, s=150) plt.subplot(133) sns.scatterplot(x=X.iloc[:,0], y=X.iloc[:,3], data=df_f, hue=clust_model.labels_, palette=’coolwarm’) plt.scatter(centers[:,0], centers[:,3], c=’black’, alpha=0.8, s=150) plt.show()
스케일링을 하지 않아도 3가지로 잘 분류된 것 같습니다.
# 3차원으로 시각화하기 fig = plt.figure(figsize=(8, 8)) ax = fig.add_subplot(111, projection=’3d’) X = clust_df # 데이터 scatterplot ax.scatter( X.iloc[:,0] , X.iloc[:,1] , X.iloc[:,2] , c = X.clust , s = 10 , cmap = “rainbow” , alpha = 1 ) # centroid scatterplot ax.scatter(centers[:,0],centers[:,1],centers[:,2] ,c=’black’, s=200, marker=’*’) plt.show()
7. 군집 별 특징 확인하기
cluster_mean= clust_df.groupby(‘clust’).mean() cluster_mean
8. 스케일링 하고 다시 군집분석하기
기존 데이터 값이 각 변수 별 값의 편차가 적어서 스케일링을 하지 않고도 아주 잘 군집이 되었지만,
일반적으로는 변수 별로 편차가 크기 때문에 스케일링이 필요할 수 있습니다.
*스케일링(표준화): 데이터 피처(속성)들을 평균이 0이고 분산이 1인 가우시안 정규 분포를 가진 값으로 변환해주는 것
from sklearn.pipeline import make_pipeline from sklearn.preprocessing import StandardScaler standard_scaler = StandardScaler() scaled_df = pd.DataFrame(standard_scaler.fit_transform(df_f.iloc[:,0:4]), columns=df_f.iloc[:,0:4].columns) # scaled된 데이터
# create model and prediction # clust_model은 스케일링 전 fit과 동일하게 맞춤 clust_model.fit(scaled_df) # unsupervised learning #애초에 결과를 모르기 때문에 data만 넣어주면 됨 centers_s = clust_model.cluster_centers_ pred_s = clust_model.predict(scaled_df)
# 스케일링 전에 합쳐준 데이터프레임에 스케일한 군집 컬럼 추가하기 clust_df[‘clust_s’] = pred_s clust_df
# scaling 완료한 데이터를 학습하고 시각화하기 plt.figure(figsize=(20, 6)) X = scaled_df plt.subplot(131) sns.scatterplot(x=X.iloc[:,0], y=X.iloc[:,1], data=scaled_df, hue=clust_model.labels_, palette=’coolwarm’) plt.scatter(centers_s[:,0], centers_s[:,1], c=’black’, alpha=0.8, s=150) plt.subplot(132) sns.scatterplot(x=X.iloc[:,0], y=X.iloc[:,2], data=scaled_df, hue=clust_model.labels_, palette=’coolwarm’) plt.scatter(centers_s[:,0], centers_s[:,2], c=’black’, alpha=0.8, s=150) plt.subplot(133) sns.scatterplot(x=X.iloc[:,0], y=X.iloc[:,3], data=scaled_df, hue=clust_model.labels_, palette=’coolwarm’) plt.scatter(centers_s[:,0], centers_s[:,3], c=’black’, alpha=0.8, s=150) plt.show()
스케일링 한 데이터도 잘 시각적으로는 잘 나눠진 듯 합니다.
아래에서 자세한 비교를 해보겠습니다.
9. 스케일링 한 데이터와 안한 데이터의 군집 성능 비교하기
# 스케일링 전 데이터의 군집 pd.crosstab(clust_df[‘target’],clust_df[‘clust’]) # 스케일링 후 데이터의 군집 pd.crosstab(clust_df[‘target’],clust_df[‘clust_s’])
스케일링 전 데이터는 원래 target분류값과 1개만 다르게 나타남
스케일링 후 데이터는 원래 target분류값과 많이 다르게 나타남
스케일하지 않았던 clust컬럼 데이터가 훨씬 정확하게 나왔습니다.
[Python 머신러닝] 8장. 군집분석 (Cluster Analysis)
군집분석이란?
서로 유사한 정도에 따라 다수의 객체를 군집으로 나누는 작업 또는 이에 기반한 분석을 의미한다.
– 유사도가 높은 데이터끼리 그룹화 (대표적으로 유클리드 거리식 이용)
– 계층형 클러스터링과 비계층형 클러스터링으로 분류
– 주요 알고리즘 : k-means, hierarchical
> 군집분석의 특징
– 종속변수(y변수)가 없는 데이터 마이닝 기법 (비지도 학습)
– 유클리드 거리 기반 유사 객체 묶음 (유사성 = 유클리드 거리)
– 전체적인 데이터 구조를 파악하는데 이용
– 분석결과에 대한 가설 검정 없음 (타당성 검증 방법 없음)
– 계층적 군집분석(탐색적), 비계층적 군집분석(확인적)
– 고객 DB -> 알고리즘 적용 -> 패턴 추출(rule) -> 근거리 모형으로 군집 형성
– 척도 : 등간, 비율척도 => 명목척도를 만듦
1) 유클리드 거리
– 두 점 사이의 거리를 계산하는 방법
– 이 거리를 이용하여 유클리드 공간 정의
2) 계층적 군집분석 (hierarchical)
– 유클리드 거리를 이용한 군집분석 방법
– 계층적으로 군집 결과 도출
– 탐색적 군집분석
– 계층적 군집분석의 결과
=> 덴드로그램 (Dendrogram) : 표본들이 군을 형성하는 과정을 나타내는 나무 형식의 그림
– 군집 수는 사용자가 정할 수 있음 (2집단, 3집단, … 등)
– 군집화 방식
① 단일기준결합방식 : 각 군집에서 중심으로부터 거리가 가까운 것 1개씩 비교하여 가장 가까운 것끼리 군집화
② 완전기준결합방식 : 각 군집에서 중심으로부터 가장 먼 대상끼리 비교하여 가장 가까운 것끼리 군집화
③ 평균기준결합방식 : 한 군집 안에 속해 있는 모든 대상과 다른 군집에 속해있는 모든 대상의 쌍 집합에 대한 거리를 평균 계산하여 가장 가까운 것끼리 군집화
3) 비계층적 군집분석 (k-Means)
– 계층적 군집분석보다 속도 빠름
– 군집의 수를 알고 있는 경우 이용
– k는 미리 정하는 군집 수
– 확인적 군집분석
– 계층적 군집화의 결과에 의거하여 군집 수 결정
– 변수보다 관측대상 군집화에 많이 이용
– 군집의 중심(Cluster Center)은 사용자가 정함
> k-평균(k-Menas) 군집분석 알고리즘
① k값을 초기값으로, k개의 centroid 선정 (랜덤)
② 각 데이터 포인터를 가장 가까운 centroid에 할당
③ centroid에 할당된 모든 데이터 포인트의 중심 위치 계산 (centroid 재조정)
④ 재조정된 centroid와 가장 가까운 데이터 포인트 할당
⑤ centroid 재조정이 발생되지 않을 때까지 ③, ④단계 반복
<실습한 내용>
1. hierachical (hierarchy)
2. kMeans 실습(1)
3. kMeans 실습(2)
1. hierachical (hierarchy)
“””
계층적 군집분석
– 유클리드 거리계산식 이용
– 상향식(Bottom-up)으로 군집을 형성
“””
import pandas as pd # dataset load
from sklearn.datasets import load_iris
# 계층적 군집 model
from scipy.cluster.hierarchy import linkage, dendrogram
# 1. dataset load
iris.csv 0.00MB
iris = pd.read_csv(“../data/iris.csv”)
iris.info()
cols = list(iris.columns)
iris_x = iris[cols[:4]]
iris_x.head()
iris[‘Species’].value_counts() # ‘Species’ : y변수
”’
versicolor 50
virginica 50
setosa 50
”’
# 2. y변수 수치화
X, y = load_iris(return_X_y=True)
# 사이킷런 라이브러리에서 제공하는 데이터셋을 불러오면 범주값을 숫자로 받을 수 있음
y # 0,1,2로 구성됨
labels = pd.DataFrame(y, columns = [‘labels’])
# df = df + df
irisDF = pd.concat([iris_x, labels], axis = 1)
irisDF.head()
irisDF.tail() # x변수들과 수치화된 y변수(labels)로 데이터프레임 만들어진 것을 확인
# 3. 계층적 군집분석 model
clusters = linkage(y=irisDF, method=’complete’, metric=’euclidean’)
clusters
clusters.shape # (149, 4)
”’
연결방식
1. 단순연결방식(single)
2. 완전연결방식(complete)
3. 평균연결방식(average)
”’
# 4. 덴드로그램 시각화 : 군집수 결정
import matplotlib.pyplot as plt
plt.figure( figsize = (25, 10) )
dendrogram(clusters, leaf_rotation=90, leaf_font_size=12,)
# leaf_rotation=90 : 글자 각도
# leaf_font_size=20 : 글자 사이즈
plt.show()
# 5. 클러스터링(군집) 결과
from scipy.cluster.hierarchy import fcluster # 지정한 클러스터 자르기
cut_tree = fcluster(clusters, t=3, criterion=’distance’)
cut_tree # prediction
labels = irisDF[‘labels’] # 정답
df = pd.DataFrame({‘pred’:cut_tree, ‘labels’:labels})
con_mat = pd.crosstab(df[‘pred’], df[‘labels’])
con_mat
”’
labels 0 1 2
pred
1 50 0 0
2 0 0 34
3 0 50 16
”’
# irisDF에 군집 예측치 추가
irisDF.head()
irisDF[‘cluster’] = cut_tree
irisDF.head()
# 클러스터 단위 산점도 시각화
plt.scatter(x=irisDF[‘Sepal.Length’], y=irisDF[‘Petal.Length’], c=irisDF[‘cluster’])
# 클러스터 빈도수
irisDF[‘cluster’].value_counts()
”’
3 66
1 50
2 34
”’
# 각 클러스터별 통계(평균)
cluster_g = irisDF.groupby(‘cluster’)
cluster_g.mean()
”’
Sepal.Length Sepal.Width Petal.Length Petal.Width labels
cluster
1 5.006000 3.428000 1.462000 0.246000 0.000000
2 6.888235 3.100000 5.805882 2.123529 2.000000
3 5.939394 2.754545 4.442424 1.445455 1.242424
”’
2. kMeans 실습(1)
“””
kMeans 알고리즘
– 확인적인 군집분석
– 군집 수 k를 알고 있는 경우 이용
“””
import pandas as pd # dataset load
from sklearn.cluster import KMeans # model
import matplotlib.pyplot as plt # 시각화
# 1. dataset load
# 위와 똑같은 iris.csv 파일 이용
iris.csv 0.00MB
iris = pd.read_csv(“../data/iris.csv”)
iris.info()
irisDF = iris[[‘Sepal.Length’, ‘Petal.Length’]] # 두 개의 칼럼만 이용
irisDF.head()
# 2. 비계층적 군집 분석 model
model = KMeans(n_clusters=3, random_state=0, algorithm=’auto’)
# n_clusters=3 : 군집의 개수 (k) (이미 알고 있음)
# random_state=0 : seed 역할 (모델을 일정하게 생성 = 랜덤X)
model.fit(irisDF)
# 3. 클러스터링(군집) 결과
pred = model.predict(irisDF)
pred
len(pred) # 150 (관측치 개수만큼 예측치 생성됨)
# 4. 군집결과 시각화
plt.scatter(x=irisDF[‘Sepal.Length’], y=irisDF[‘Petal.Length’], c=pred)
# 군집별 중앙값
centers = model.cluster_centers_
centers
”’
array([[5.00784314, 1.49215686],
[5.87413793, 4.39310345], [6.83902439, 5.67804878]])”’
# 군집별 중앙값 시각화
plt.scatter(x=centers[:,0], y=centers[:,1], marker=’D’, c=’r’)
# marker=’D’, c=’r’ : 마커 모양은 Diamond, 색깔은 red
plt.show()
# 군집결과와 중앙값 함께 시각화
plt.scatter(x=irisDF[‘Sepal.Length’], y=irisDF[‘Petal.Length’], c=pred)
plt.scatter(x=centers[:,0], y=centers[:,1], marker=’D’, c=’r’)
plt.show()
# 블럭 실행
3. kMeans 실습(2)
“””
kMeans 알고리즘
– testSet.txt 파일 데이터셋 이용
“””
testSet.txt 0.00MB
import pandas as pd
from sklearn.cluster import KMeans # model
import matplotlib.pyplot as plt # 시각화
import numpy as np # dataset
# testSet 데이터는 다음과 같은 형태로 입력되어 있음
# dataset 생성 함수
def loadDataSet(fileName) :
rows = [] # 전체 행(80개)
f = open(fileName, mode=’r’)
lines = f.readlines() # 줄단위 전체 행 읽기
for row in lines : # 줄 단위 읽기 : 1.658985 4.285136
line = row.split(‘\t’) # ‘1.658985’ ‘4.285136’
row = [] # 1줄 행
for l in line :
row.append( float(l) ) # [‘1.658985’, ‘4.285136’]
rows.append(row) # [[‘1.658985’, ‘4.285136’], …. ]
return np.array(rows) # 2차원(80, 2) 행렬 구조로 return
# 1. 함수 호출
dataset = loadDataSet(“../data/testSet.txt”)
dataset.shape # (80, 2)
type(dataset) # numpy.ndarray
dataset
dataset[:10, :] # 10행
plt.plot(dataset[:,0], dataset[:,1], ‘go’) # 0번째 열은 x값, 1번째 열은 y값, ‘go’ : green 색깔의 o 모양 마커
plt.show()
# 2. df 생성
dataDF = pd.DataFrame(dataset, columns = [‘x’, ‘y’])
dataDF.info()
# 3. kMeans model
model = KMeans(n_clusters=4, algorithm=’auto’) # k = 4
model.fit(dataDF)
# kMeans 예측치
pred = model.predict(dataDF)
pred # 0~3, 총 4개의 도메인으로 군집 형성
plt.scatter(x=dataDF[‘x’], y=dataDF[‘y’], c=pred)
# 각 군집의 중앙값
centers = model.cluster_centers_
centers
plt.scatter(x=centers[:,0], y=centers[:,1], marker=’D’, c=’r’)
plt.show()
# 예측치부터 블럭실행
# 4. 원형 데이터에 군집 예측치 추가
dataDF[‘cluster’] = pred
dataDF.head()
Example
exam01.py 0.00MB exam02.py 0.00MB bodycheck.csv 0.00MB product_sales.csv 0.00MB
[python] 자연어처리(NLP) – Kmeans, K대푯값 군집 분석
반응형
안녕하세요! 오늘은 텍스트 군집분석을 진행해보고자 합니다.
군집분석은 여러 문서들이 있을 때 유사한 텍스트끼리 그룹화하는 분석을 말합니다.
그중에서도 오늘은 분할 군집분석을 진행해 보겠습니다.
분할 군집 분석은 데이터를 k개의 그룹으로 나누어 주는 것을 말하는데 k개는 분석하는 사람에 따라 지정되는 숫자입니다. 연구자가 주관적으로 데이터 내에서 2개의 그룹으로 나누거나 3개의 그룹으로 나누어 겠다라고 결정하면 그 그룹 숫자에 따라 데이터들이 군집화 됩니다.
K-평균 군집 분석(K-means)
K-means (K-평균 군집 분석) 알고리즘은 아래의 사진으로쉽게 이해가 가능합니다.
위의 사진을 만들어 준비해 보았는데 이해가 잘 가시나요? ㅎㅎ
이제는 군집분석을 파이썬으로 구현하여 보겠습니다.
우선 데이터를 준비해 주어야 하는데요
저는 네이버 api를 이용해 뉴스 제목, 요약, 링크 등을 크롤링 하여 준비해 보았습니다.
검색어는 ‘크리스마스’ , ‘쇼미더머니’ , ‘SK하이닉스’ 이렇게 3개의 키워드로 검색된 내용을 데이터프레임으로 만들었습니다.
각각 15기사씩 총 45개의 기사가 있습니다.
데이터 파일 준비
clustering_ex.csv 0.02MB
필요한 모듈 설치
sklearn 설치
pip install sklearn
c_konlpy 설치(커스텀 할 수 있는 형태소분석기, 사전에 konlpy설치 후 ckonlpy설치)
git clone https://github.com/lovit/customized_konlpy.git
pip install customized_konlpy
pyclustering 설치
pip install pyclustering
코드
import pandas as pd from sklearn.feature_extraction.text import CountVectorizer from sklearn.cluster import KMeans from pyclustering.cluster import kmedoids from ckonlpy.tag import Twitter twitter = Twitter() #데이터 불러오기 df = pd.read_csv(‘clustering_ex.csv’) print(df.head())
출력:
준비한 데이터셋을 보면 요약 부분에 태그 등이 남아 있어 제거 한 후 분석을 진행해 보도록 하겠습니다.
# 텍스트 전처리 import re desc = df[‘요약’] for i in range(len(desc)): desc[i] = re.sub(‘(||”)’,”,desc[i]) print(desc)
출력:
위와 같이 태그가 깔끔하게 없어진 것을 확인해 볼 수 있습니다.
이번 군집 분석에는 요약부분을 사용하여 분석해보도록 하겠습니다.
각 텍스트의 형태소 분석을 ckonlpy로 진행해줍니다. ckonlpy에서 검색키워드였던 크리스마스, 쇼미더머니, sk하이닉스를 명사로 추가해 줍니다. 다른 명사를 추가하고 싶다면 [] 안에 추가하면 됩니다.
분석 후 명사가 추출된 문장을 띄어쓰기로 구분하여 기사당 한 문장으로 만들어 줍니다.
contents = [] # 형태소 분석, 명사만 추출 twitter.add_dictionary([‘크리스마스’,’쇼미더머니’,’SK하이닉스’],’Noun’) for i in desc: contents.append(twitter.nouns(i)) text = [‘ ‘.join(contents[i]) for i in range(len(contents))] print(text)
출력:
그 후 문장 벡터화를 하여 분석할 수 있는 형태로 텍스트를 바꾸어 줍니다.
#문장 벡터화 vectorize = CountVectorizer() x = vectorize.fit_transform(text)
이렇게 준비가 되었으면 평균 군집 분석을 진행해 줍니다.
데이터 셋이 3개의 키워드로 검색후 만든 파일이기 때문에 k=3으로 설정하여 진행해 보도록 하겠습니다.
######### 평균 군집 분석 ########### #데이터 프레임 생성 (문장 단어 매트릭스 만들기) new_df = pd.DataFrame(x.toarray(), columns=vectorize.get_feature_names_out()) # K- 평균 군집 분석 kmeans = KMeans(n_clusters=3).fit(new_df) print(‘[K-평균 군집 분석 결과]’) print(‘###########################################’) print(kmeans.labels_)
출력:
아까의 문장들이 k=3이라고 했기 때문에 0,1,2의 3 그룹 중 하나로 배정되었음을 확인할 수 있습니다.
K-대푯값 군집 분석
위의 데이터를 가지고 이번에는 대푯값 군집 분석을 진행하겠습니다.
k-대푯값은 보통 데이터들 중 어느 한 값만 매우 높거나 매우 작을때 평균값이 그 데이터들을 대표하지 못할 때 평균 아닌 다른 방법으로 중심값을 찾아야 할 때 쓰는 방법입니다.
숫자로 예를 들자면
[1,2,3,4,5,6,100] 이라는 데이터가 있을 때위 숫자들의 평균은 (1+2+3+4+5+6+100)/7 =17.28… 이 되는데, 이 평균이 숫자들의 값을 대표한다고 보기 어렵습니다.
이 때 중앙값인 4를 대푯값으로 정하는 등의 다른 방법이 필요하게 됩니다.
텍스트도 평균 값이 아닌 대푯값을 정하여 군집 분석을 진행해 보도록 하겠습니다.
초기 대푯값으로는 각 키워드의 기사들 중 임의의 기사를 1개씩 선정하여 initial_index_medoids에 세팅해 주었습니다.
######### k-대푯값 군집 분석 ########### #인스턴스 생성 kmedoids_ins = kmedoids.kmedoids(new_df.values,initial_index_medoids=[4,18,36]) # initial_index는 df행 중 대푯값 행 지정 kmedoids_ins.process() clusters = kmedoids_ins.get_clusters() print(‘###########################################’) print(‘[K-대푯값 군집 분석 결과]’) print(clusters)
출력:
각각 []로 3개의 군집으로 나누어졌음을 확인할 수 있습니다.
이번 텍스트에서는 k대푯값보다 kmeans가 더 분석이 잘 되었네요. 다른 텍스트로도 한 번 진행해 보시고 분석 목적에 맞는 방법을 선택해서 진행하면 됩니다 ㅎㅎ
전체코드
import pandas as pd from sklearn.feature_extraction.text import CountVectorizer from sklearn.cluster import KMeans from pyclustering.cluster import kmedoids from ckonlpy.tag import Twitter twitter = Twitter() #데이터 불러오기 df = pd.read_csv(‘clustering_ex.csv’) print(df.head()) # 텍스트 전처리 import re desc = df[‘요약’] for i in range(len(desc)): desc[i] = re.sub(‘(||”)’,”,desc[i]) #print(desc) contents = [] # 형태소 분석, 명사만 추출 twitter.add_dictionary([‘크리스마스’,’쇼미더머니’,’SK하이닉스’],’Noun’) for i in desc: contents.append(twitter.nouns(i)) #print(contents) text = [‘ ‘.join(contents[i]) for i in range(len(contents))] print(text) #문장 벡터화 vectorize = CountVectorizer() x = vectorize.fit_transform(text) ######### 평균 군집 분석 ########### #데이터 프레임 생성 (문장 단어 매트릭스 만들기) new_df = pd.DataFrame(x.toarray(), columns=vectorize.get_feature_names_out()) # K- 평균 군집 분석 kmeans = KMeans(n_clusters=3).fit(new_df) print(‘[K-평균 군집 분석 결과]’) print(‘###########################################’) print(kmeans.labels_) ######### k-대푯값 군집 분석 ########### #인스턴스 생성 kmedoids_ins = kmedoids.kmedoids(new_df.values,initial_index_medoids=[4,18,36]) # initial_index는 df행 중 대푯값 행 지정 kmedoids_ins.process() clusters = kmedoids_ins.get_clusters() print(‘###########################################’) print(‘[K-대푯값 군집 분석 결과]’) print(clusters)
참고자료
책- 「잡아라 텍스트 마이닝 with 파이썬」
보너스
PCA (주성분 분석)으로 군집 시각화하기
PCA(Principal component analysis)는 간단하게 말해 고차원의 데이터를 저차원의 데이터로 바꾸는 방법입니다.
여러 변수가 있으면 그 것을 융합해 주성분을 뽑아내어 그것을 새로운 변수로 만들어내는 방법입니다.여기서는 텍스트를 2차원으로 축소 후 결과를 시각화하여 보겠습니다.
#pca(주성분 분석)으로 시각화하기 from sklearn.decomposition import PCA import matplotlib.pyplot as plt pca = PCA(n_components=2) # 2차원으로 축소 pc = pca.fit_transform(new_df) p_df = pd.DataFrame(data=pc, columns=[‘main1’, ‘main2’]) p_df.index=df[‘검색어’] plt.scatter(p_df.iloc[kmeans.labels_ == 0,0], p_df.iloc[kmeans.labels_ == 0,1], s = 10, c = ‘red’, label = ‘clustering1’) plt.scatter(p_df.iloc[kmeans.labels_ == 1,0], p_df.iloc[kmeans.labels_ == 1,1], s = 10, c = ‘blue’, label = ‘clustering2’) plt.scatter(p_df.iloc[kmeans.labels_ == 2,0], p_df.iloc[kmeans.labels_ == 2,1], s = 10, c = ‘green’, label = ‘clustering3’) plt.legend() plt.show()
주성분 분석에 대해 더 알아보고 싶은 분은 아래의 링크를 참고해 주세요 🙂
전체 코드 파일
text_clustering.py 0.00MB
반응형
[ML] 군집분석(K-means, K-means++)
728×90
– 정답이 없는 문제를 해결하기 위한 알고리즘 → 비지도학습 ‘군집분석’
– 군집분석(Clustering Analysis)
ex) 쇼핑몰에서 페이지 체류 시간, 구매 금액대 등을 토대로 소비자 유형 그룹을 나누고(군집 설정), 새로운 소비자가 쇼핑몰에 들어왔을 때 행동을 바탕으로 앞서 설정해놓은 그룹으로 할당, 비슷한 소비자가 구매한 상품 노출하여 제품 구매율을 높힘
군집은 정답을 모르는 데이터 안에서 숨겨진 구조를 찾는 것
클래스 레이블이 없는 데이터를 특정 군집으로 묶고자 할 때 활용
계층 군집, 밀집도 기반 군집(클러스터 모양이 원형이 아닐 때 사용)
– K-평균(K-means)
매우 쉬운 구현성, 높은 계산 효율성 → 학계와 산업현장을 가리지 않고 활약
프로토타입 기반 군집 : 각 클러스터가 하나의 프로토타입으로 표현됨 프로토타입(Prototype) 연속적인 특성에서는 비슷한 데이터 포인트의 센트로이드(centroid – 평균) 범주형 특성에서는 메도이드(medoid – 가장 자주 등장하는 포인트)
원형 클러스터 구분에 뛰어남
사전에 몇 개의 클러스터를 만들 것인지 직접 지정해줘야함 → 주관적인 사람의 판단 개입
적절한 K값을 선택했다면 높은 성능, 부적합한 K값은 모델의 성능을 보장할 수 없음
– 파이썬 활용하여 K-평균 군집분석 진행하기
# 무작위 데이터셋 생성 from sklearn.datasets import make_blobs X, y = make_blobs(n_samples = 150, # 150개 n_features = 2, # 2차원 centers = 3, # 3개의 클러스터 혹은 중심 cluster_std = 0.5, # 클러스터의 표준편차 값 shuffle = True, # 무작위로 섞을 지 여부 random_state = 0) # 시드 값 #시각화 : 2차원 산점도 그리기 import matplotlib.pyplot as plt plt.scatter(X[:, 0], X[:, 1], c = ‘white’, marker = ‘o’, edgecolor = ‘black’, s= 50) plt.grid() plt.tight_layout() plt.show()
목표 : 특성의 유사도에 기초하여 데이터들을 그룹으로 모으는 것
K-평균 4단계 알고리즘 데이터 포인트에서 랜덤하게 K개의 센트로이드를 초기 클러스터 중심으로 선택 각 데이터를 가장 가까운 센트로이드에 할당 할당된 샘플들을 중심으로 센트로이드를 이동 클러스터 할당이 변하지 않거나, 사용자가 지정한 허용오차나 최대 반복횟수에 도달할 때 까지 2/3 과정 반복
유사도 측정 방법 임의의 차원 공간에 있는 두 데이터 포인트 x와 y사이의 유클리디안 거리 혹은 유클리디안 거리 제곱 지표 기반 → 최적화 문제 클러스터 내의 제곱 오차합(SSE)을 반복적으로 최소화 각 데이터를 센트로이드에 할당할 때마다, 센트로이드는 이동 → 센트로이드가 변화할 때마다 오차 제곱합을 반복적으로 계산하면서 변화량에 대한 허용 오차값이 일정 수준내 로 들어온다면 더 이상 클러스터가 변화하지 않는다는 것이고, 최적화가 완료 되었다는 것
첫 번째 줄은 μ, 두 번째 줄은 w에 관한 설명
각 점들간의 거리를 측정할 때, 점들간의 단위와 변동폭이 크다면 왜곡 발생 → 거리 산출 시 불필요한 항목간의 특성을 제거하고 단위를 일치시키는 ‘표준화’과정으로 왜곡을 줄일 수 있음
from sklearn.cluster import KMeans km = KMeans(n_clusters = 3, # 클러스터 개수 3개 init = ‘random’, # K평균 알고리즘 설정, 초기 중심 좌표를 무작위로 선정하여 random n_init = 10, # 각기 다른 랜덤한 센트로이드에서 독립적으로 몇 번 실행하여 가장 낮은 제곱오차합을 만들 것인지 설정 max_iter = 300, # 최대 몇 번을 반복할 것인지 tol = 1e-04, # 허용 오차값 random_state = 0) # 군집분석 알고리즘에 의한 예측 클래스 레이블 y_km = km.fit_predict(X) # 시각화 import matplotlib.pyplot as plt plt.scatter(X[y_km == 0, 0], X[y_km == 0, 1], s = 50, c = ‘lightgreen’, marker = ‘s’, edgecolor = ‘black’, label = ‘cluster 1’) plt.scatter(X[y_km == 1, 0], X[y_km == 1, 1], s = 50, c = ‘orange’, marker = ‘o’, edgecolor = ‘black’, label = ‘cluster 2’) plt.scatter(X[y_km == 2, 0], X[y_km == 2, 1], s = 50, c = ‘lightblue’, marker = ‘v’, edgecolor = ‘black’, label = ‘cluster 3’) plt.scatter(km.cluster_centers_[:, 0], km.cluster_centers_[:,1], s = 250, marker = ‘*’, c = ‘red’, edgecolor = ‘black’, label = ‘centroids’) plt.legend(scatterpoints = 1) plt.grid() plt.tight_layout() plt.show()
초기 센트로이드를 설정할 때, 랜덤으로 위치를 선정하기 때문에 애초에 잘못 선정된 곳에서 시작한 경우 (여기에 더불어 데이터가 적은 악조건이 붙게 된다면) 클러스터의 성능이 매우 불안정해짐
따라서 초기 클러스터 센트로이드를 좀 더 똑똑하게 할당할 수 있는 기법 등장 → K-means++
K-means 알고리즘에서 클러스터는 중첩되지 않고 계층적이지 않음, 클러스터 당 하나 이상의 데이터가 존재 → 데이터가 꼭 하나의 클러스터로만 구분되지 않을 경우 문제 발생 → K-means++
– K-means++
km = KMeans(n_clusters = 3, # 클러스터 개수 3개 init = ‘k-means++’, # K평균++ 알고리즘 설정 n_init = 10, # 각기 다른 랜덤한 센트로이드에서 독립적으로 몇 번 실행하여 가장 낮은 제곱오차합을 만들 것인지 설정 max_iter = 300, # 최대 몇 번을 반복할 것인지 tol = 1e-04, # 허용 오차값 random_state = 0) y_km = km.fit_predict(X)
K-평균의 무작위성을 보완하기 위한 기법
초기 센트로이드가 서로 멀리 떨어지도록 위치 시킴
기본 K-평균보다 일관되고 좋은 결과 보여줌
– 사이킷런 사용하여 군집의 품질 평가하기
비지도학습은 올바른 정답이 없기 때문에 군집의 품질을 평가해야 하는 경우 알고리즘 자체의 지표를 사용해야함 ex) k-평균 군집의 성능 비교를 위한 오차 제곱합
KMeans 모델 학습을 진행한 객체 안에 관성이라는 뜻을 가진 ‘inertia’ 속성안에 이미 계산이 완료 되어 있음
print(‘왜곡 : %.2f’ % km.inertia_)
왜곡 값이 적절한 값인지는 k를 다양한 값으로 할당한 후에 왜곡값을 비교해봐야함 → 엘보우 방법
– 엘보우 방법(elbow method)
최적인 클러스터 개수 k를 추정
k값의 증가 → 센트로이드의 증가 →데이터들이 센트로이드에 더 가까워지는 것 → 왜곡값(SSE)의 감소
# k를 1부터 10까지 구축, 각각의 SSE를 시각화 distortions = [] for i in range(1, 11) : km = KMeans(n_clusters = i, init = ‘k-means++’, n_init = 10, max_iter = 300, random_state = 0) km.fit(X) distortions.append(km.inertia_) plt.plot(range(1,11), distortions, marker = ‘o’) plt.xlabel(‘Number of clusters’) plt.ylabel(‘Distortion’) plt.tight_layout() plt.show()
사람의 팔꿈치 형상
– 실루엣 분석(silhouette analysis)
군집 품질을 평가하는 또 다른 방법
클러스터 내 데이터들이 얼마나 조밀하게 모여있는지를 측정하는 그래프 도구
계수 구하는 방법 하나의 임의의 데이터(x(i))와 동일한 클러스터 내의 모든 다른 데이터 포인트 사이의 거리를 평균하여 클러스터의 응집력(a(i)) 을 계산 앞서 선정한 데이터와 가장 가까운 클러스터의 모든 샘플간 평균 거리로 최근접 클러스터의 클러스터 분리도(b(i)) 를 계산 클러스터 응집력과 분리도 사이의 차이를 둘 중 큰 값으로 나눠 실루엣 계수(s(i)) 를 계산
분리도 = 응집력 : 실루엣 계수는 0이 됨, 클러스터가 중첩되어 있다는 의미
분리도 > 응집력 : 이상적인 실루엣 계수인 1에 가깝게 됨
분리도 : 데이터가 다른 클러스터와 얼마나 다른지를 나타냄
응집력 : 클러스터 내 다른 샘플과 얼마나 비슷한지를 나타냄, 작을수록 클러스터 내 다른 데이터들과 비슷함
import numpy as np from matplotlib import cm from sklearn.metrics import silhouette_samples # sklearn의 metrics 모델 안에 silhouette_samples함수로 계산 # k-means++ 알고리즘 km = KMeans(n_clusters = 3, init = ‘k-means++’, n_init = 10, max_iter = 300, tol = 1e-04, random_state = 0) y_km = km.fit_predict(X) cluster_labels = np.unique(y_km) n_clusters = cluster_labels.shape[0] # 실루엣 분석 silhouette_vals = silhouette_samples(X, y_km, metric = ‘euclidean’) # 시각화 y_ax_lower, y_ax_upper = 0, 0 yticks = [] for i, c in enumerate(cluster_labels) : c_silhouette_vals = silhouette_vals[y_km == c] c_silhouette_vals.sort() y_ax_upper += len(c_silhouette_vals) color = cm.jet(float(i) / n_clusters) plt.barh(range(y_ax_lower, y_ax_upper), c_silhouette_vals, height = 1.0, edgecolor = ‘none’, color = color) yticks.append((y_ax_lower + y_ax_upper) / 2) y_ax_lower += len(c_silhouette_vals) silhouette_avg = np.mean(silhouette_vals) plt.yticks(yticks, cluster_labels + 1) plt.ylabel(‘Cluster’) plt.xlabel(‘Silhouette coefficient’) plt.tight_layout() plt.show()
이상치를 가진 클러스터 구별할 수 있게 됨 / 위의 그래프 경우에는 실루엣 계수가 대부분 최대값 1에 가깝게 형성되어 있으므로 군집이 잘 형성된 경우라 볼 수 있음 군집의 개수가 2개일 경우 → 군집이 비교적 잘 형성되어 있지 않다고 평가됨
728×90
K-Means 클러스터링 파이썬 연습 예제 – 고객 구매 데이터 분석
K-Means 클러스터링의 파이썬 예제이다. 본 예제에서는 고객 구매 데이터를 분석하여 유의미한 인사이트를 얻어보는 과정을 다룬다. K-Means에 대한 개념적인 설명은 다음 글(클릭)을 참고하면 좋다.
** 연습을 위한 엑셀 데이터와 가이드 노트북 파일은 글 하단에 깃허브 주소에서 확인해주세요. 댓글은 블로그를 운영하는 데 큰 기쁨이 됩니다 🙂
** [2021년 11월 6일 코드 업데이트: Joon님의 제보로 오타 수정하였습니다. 코드 작성하고 블로그에 옮길 때 변수명을 수정했는데 전부 수정되지 않은 실수가 있었습니다. 알려주셔서 감사합니다.
■ K 값이 변하면 클러스터링에 어떤 영향을 미치나?
우선 연습 데이터인 엑셀 파일을 파이썬 주피터 노트북에 pandas 패키지를 이용하여 읽어오도록 한다. 파이썬 기초가 필요하신 분들은 다음 시리즈: 파이썬 첫걸음 을 참고하길 바란다.
# pandas 패키지 임포트 import pandas as pd # read_excel() 함수를 이용하여 파일 불러오기 data = pd.read_excel(‘CustomerDataSet.xls’) # 데이터 몇 행만 보기 data.head()
데이터는 5개의 열(Customer ID, ItemsBought, ItemsReturned, ZipCode, Product)로 이뤄져있다. 우리가 알고 싶은 것은 우리의 제품 포트폴리오와 지역의 관계라고 하자. Customer ID는 고객 ID로 각 고객을 구분해주는 유니크한 값이나 본 분석에는 크게 의미가 없으므로 사용하지 않는다. ZipCode와 Product는 군집 분석 결과를 해석할 때 사용한다. 즉,남은 ItemsBought과 ItemsReturned로 클러스터링을 한다.
이제 레코드끼리의 거리를 계산하여 클러스터링을 해야하는데 그 전에 ItemsBought과 ItemsReturned의 측정 단위을 같게하는 작업, 즉 데이터의 정규화(normalization) 작업이 필요하다. 여기서는 MinMaxScaler()를 이용해 정규화를 진행해보기로 한다.
# 필요 패키지 불러오기 (KMeans, matplotlib, preprocessing) from sklearn.cluster import KMeans import matplotlib.pyplot as plt from sklearn import preprocessing # 원본 데이터를 복사해서 전처리하기 (원본 데이터를 가지고 바로 전처리하지 않는다) processed_data = data.copy() # 데이터 전처리 – 정규화를 위한 작업 scaler = preprocessing.MinMaxScaler() processed_data[[‘ItemsBought’, ‘ItemsReturned’]] = scaler.fit_transform(processed_data[[‘ItemsBought’, ‘ItemsReturned’]]) # 화면(figure) 생성 plt.figure(figsize = (10, 6))
# K 값을 늘려가며 반복 테스트 for i in range(1, 7) # 클러스터 생성 estimator = KMeans(n_clusters = i) ids = estimator.fit_predict(processed_data[[‘ItemsBought’, ‘ItemsReturned’]]) # 2행 3열을 가진 서브플롯 추가 (인덱스 = i) plt.subplot(3, 2, i) plt.tight_layout() # 서브플롯의 라벨링 plt.title(“K value = {}”.format(i)) plt.xlabel(‘ItemsBought’) plt.ylabel(‘ItemsReturned’) # 클러스터링 그리기 plt.scatter(processed_data[‘ItemsBought’], processed_data[‘ItemsReturned’], c=ids) plt.show()
결과값은 다음과 같다.
해석해보면, K가 3이나 4일때 군집화가 잘 되는 것을 확인할 수 있다. 구분을 하자면 제품을 많이 사고 유지하는 고객군 – 제품을 많이 사나 환불을 조금 하는 고객군 – 제품을 많이 안사고 환불도 많이 하는 고객군 으로 나눌 수 있겠다.
■ 각 군집과 제품 ID의 관계를 살펴보자
이번에는 K를 3으로 잡아 product id를 기준으로 범례를 붙여보자.
# K = 3으로 클러스터링 estimator = KMeans(n_clusters = 3) # 클러스터링 생성 cluster_ids = estimator.fit_predict(processed_data[[‘ItemsBought’, ‘ItemsReturned’]]) # create a scatter plot plt.scatter(processed_data[‘ItemsBought’], processed_data[‘ItemsReturned’], c=cluster_ids) # 제품과 클러스터 id로 데이터에 범례 달기 for index, c_id, bought, returned, zip_code, product in processed_data.itertuples(): plt.annotate(“Clu{}: {}”.format(cluster_ids[index], product),(bought, returned)) plt.xlabel(‘ItemsBought’) plt.ylabel(‘ItemsReturned’) plt.show()
코드를 돌리면 다음과 같은 결과를 얻는다.
그래프를 살펴보면 Clu1인 제품 2435이 많이 안팔릴 뿐만 아니라 환불이 발생하는 것을 알 수 있다. 현재 그래프 상에는 데이터가 정규화되었기 때문에 면밀히 파악하기 어려우니 원래 데이터로 돌아가서 해당 제품을 찾아보자.
# 클러스터 1로 분류된 데이터를 추출해보자 data[ cluster_ids == 1 ]
안좋은 고객으로 할당된 고객 데이터를 보고 이제 문제점을 찾아 개선하면 된다!
■ 각 군집과 지역의 관계를 살펴보자
이번에는 클러스터링을 이용하여 지역마다의 마케팅 활동에 대해 인사이트를 얻어보자. 우편번호이기 때문에 따로 전처리를 할 필요는 없다. 다만, 전처리된 데이터 세트와 원 데이터의 세트의 레코드가 동일한 순서이기 때문에 cluster로는 전처리된 데이터에서 생성된 것을 그대로 사용해도 된다.
# 플로팅하기 plt.scatter(data[‘ItemsBought’], data[‘ItemsReturned’], c=cluster_ids) # 우편번호로 범례달기 for (index, c_id, bought, returned, zip_code, product) in data.itertuples(): plt.annotate(zip_code,(bought + 0.6, returned + 0.6)) plt.xlabel(‘ItemsBought’) plt.ylabel(‘ItemsReturned’) plt.show()
결과를 살펴보면, 우편번호가 1과 2인 지역에서 성과가 좋음을 알 수 있다. 1, 2 지역에서 어떤 마케팅을 진행하는지 확인하고 다른 지역에도 적용할 수 있는지 살펴보고, 다른 지역의 성과를 개선할 방안을 찾는다!
파이썬 가이드 자료 공유에 대한 문의가 많아 깃허브를 만들었습니다. 아래 링크로 가이드 파일을 확인해주세요. https://github.com/lucy-the-marketer/k-means-clustering
도움이 되셨다면 댓글 하나 써주시면 감사하겠습니다 🙂
[머신러닝] 군집분석, 군집화 (파이썬 싸이킷런) – 레이블되지 않은 데이터 다루기 _ 머신러닝교과서 ch10
머신러닝 [머신러닝] 군집분석, 군집화 (파이썬 싸이킷런) – 레이블되지 않은 데이터 다루기 _ 머신러닝교과서 ch10 파밀밭의 호수꾼 ・ URL 복사 본문 기타 기능 공유하기 신고하기 본 문서는 [ 머신러닝 교과서 with 파이썬, 사이킷런, 텐서플로 _ 세바스찬 라시카, 바히드 미자리리 ] 도서의 chapter11 내용을 기반으로 하고 있으며, 본인이 직접 요약 / 정리한 내용입니다. https://coupa.ng/bKVKMW 길벗 머신 러닝 교과서 with 파이썬 사이킷런 텐서플로 COUPANG coupa.ng 파트너스 활동을 통해 일정액의 수수료를 제공받을 수 있음 contents 1. k-평균 알고리즘을 사용하여 유사한 객체 그룹핑 2. 계층적인 트리로 클러스터 조직화 3. DBSCAN을 사용하여 밀집도가 높은 지역 찾기 군집분석 * 데이터 안에서 숨겨진 구조를 찾는다. * 데이터에 있는 자연스러운 그룹을 찾는 것 군집화(clustering)에 대한 상용 어플리케이션의 예 문서나 음악, 영화를 여러 주제로 그룹화하는 경우, 추천 엔진에서 하듯이 구매 이력의 공통 부분을 기반으로 관심사가 비슷한 고객을 찾는 것 1. k-평균 알고리즘을 사용하여 유사한 객체 그룹핑 k-means 알고리즘은 <구현하기 매우 쉽고>, <계산 효율성이 높다> 프로토타입 기반(prototype-based) 군집화, 계층적(hierarchical) 군집화, 밀집도 기반(density-based) 군집화 중 프로토타입 기반 군집화기법(중심 기반 군집화라고도 함)에 속함 중심기반 군집화기법은 데이터 내에 원형구조가 있다고 가정한다. 단계 1. 정의된 특성공간 내에서 랜덤하게 k개의 좌표점(특성공간 내 랜덤포인트(not sample point))을 초기 클러스터 중심점(centroid)으로 선택 2. 모든 샘플들을 가장 가까운 centroid에 할당한다. 3. 할당된 샘플들의 중심으로 centroid의 위치를 조정한다(update) 4. 클러스터 할당이 더이상 변하지 않거나, 사용자가 지정한 허용 오차나 최대 반복횟수에 도달할 때까지 반복 1.1 사이킷런을 사용한 k-Means clustering 2차원 데이터셋 준비 # data prepare from sklearn.datasets import make_blobs X,y = make_blobs(n_samples=150, n_features=2, centers=3, cluster_std=0.5, shuffle=True, random_state=0) import matplotlib.pyplot as plt plt.scatter(X[:,0], X[:,1], c=’white’, marker=’o’, edgecolor=’black’, s=50) plt.grid() plt.tight_layout() plt.show() 150개의 샘플데이터포인트 목표 → 특성의 유사도에 기초하여 샘플을 그룹으로 모으자. 샘플 간 유사도는 어떻게 측정하는가? 일반적으로 유클리디안 거리의 제곱을 사용한다. 유클리디안 거리지표를 기반으로 k-평균 알고리즘을 아래와 같은 최적화문제로써 표현해볼 수 있다. ( mu^j는 클러스터 j의 센트로이드(중심점), 샘플 x^i가 클러스터 j 안에 있다면 wij = 1이고 아니면 0이다. ) 클러스터 내 오차제곱합(SSE) 또는 클러스터 관성(cluster inertia)을 반복적으로 최소화하는 방법. 알고리즘 적용 # clustering from sklearn.cluster import KMeans km = KMeans(n_clusters=3, # 클러스터 개수를 사정에 지정해야하는 단점 init=’random’, # 초기중심값을 랜덤하게 설정할 것임 n_init=10, # 랜덤한 초기 중심점설정을 10번 다르게 잡아보고 진행하여 가장 SSE낮은 결과를 채택 max_iter=300, # 최대반복 수 제한 tol=1e-04, # 수렴 조기종료를 위한 허용오차한계 random_state=0) y_km = km.fit_predict(X) Note k-means 알고리즘에 유클리디안 거리지표 사용하여 실제 데이터에 적용할 때 특성들이 측정된 스케일이 같은지 확인하라! 각 특성마다 산포의 정도가 다르다면 문제될 수 있음 표준화, 정규화 등의 스케일링이 필요할 수 있다. (ex – (몸무게, 키) 이변량데이터 ⇒ 1kg차이 ≠ 1m차이) 시각화 plt.scatter(X[y_km == 0, 0], X[y_km == 0, 1], s=50, c=’lightgreen’, marker=’s’, edgecolor=’black’, label=’cluster 1′) plt.scatter(X[y_km == 1, 0], X[y_km == 1, 1], s=50, c=’orange’, marker=’o’, edgecolor=’black’, label=’cluster 2′) plt.scatter(X[y_km == 2, 0], X[y_km == 2, 1], s=50, c=’lightblue’, marker=’v’, edgecolor=’black’, label=’cluster 3′) plt.scatter(km.cluster_centers_[:, 0], km.cluster_centers_[:, 1], s=250, marker=’*’, c=’red’, edgecolor=’black’, label=’centroids’) plt.legend(scatterpoints=1) plt.grid() plt.tight_layout() plt.show() 1.2 k-Means++로 초기 클러스터 센트로이드를 똑똑하게 할당 k-Means 군집화 수행 시 초기 중심점 설정에 의해 군집화 결과과 많이 영향받을 수 있다. k-Means++은 다음과 같은 과정에 의해 초기 중심점을 설정하여 기본 k-Means보다 좋은 결과를 만들어낸다. 1.3 직접군집 vs 간접군집 직접군집화(hard clustering)는 데이터셋의 샘플이 정확히 하나의 클러스터에 할당되는 방법 ex) k-means 간접군집화(soft clustering) (혹은 fuzzy clustering)는 샘플을 하나 이상의 클러스터에 할당한다. (각 클러스터에 속할 확률 반환) ex) soft k-means ( = fuzzy k-means, = fuzzy C-means; FCM) FCM는 포인트가 직접적으로 클러스터에 할당되는 것이아닌 각 클러스터에 속할 확률을 반환한다. FCM의 진행단계 1. 센트로이드 개수 k를 지정하고 랜덤하게 각 포인트에 대해 클러스터 확률 할당 2. 클러스터 센트로이드 mu^(j) 를 다시 계산 3. 각 샘플들에 대해 클러스터 소속확률 업데이트 4. 클러스터 확률이 더이상 변하지 않거나 사용자가 지정한 허용오차, 반복횟수 도달 시 종료 FCM의 목적함수는 k-means에서 최소화하는 SSE와 매우 흡사. 단, 여기서 클러스터 소속 가중치 w는 0,1(binary)이 아닌 0과 1사이 실수값(확률)이 된다. m은 퍼지계수로 클러스터의 fuzziness(흐릿함(?))복잡성(?)을 조절한다. → 1이상의 실수이며, 튜닝파라미터임. 클러스터 소속확률은 다음과 같이 계산된다. (첨자 p는 개별 클러스터에 대응됨) 클러스터 중심 mu^j는 샘플의 소속확률을 가중치로 주어 모든 샘플의 평균으로 계산됨. 1.4 엘보우 방법을 사용하여 최적의 클러스터 개수 찾기 군집화는 비지도학습이므로 성능평가를 위해서는 알고리즘 자체의 지표를 활용해야함. → k-Means clustering의 성능 비교를 위해 위에서 언급한 “클래스 내 SSE(distortion / inertia)”를 사용한다. 엘보우 기법(Elbow method) 군집의 개수 파리미터 k 값에 따른 SSE의 변화를 그래프로 그려 SSE의 감소가 완만해지는 지점을 찾는다. (k가 커질수록 당연히 sse는 감소한다. 중요한건 감소하는 정도) distortions = [] # SSE with-in cluster for i in range(1, 11): km = KMeans(n_clusters=i, init=’k-means++’, n_init=10, max_iter=300, random_state=0) km.fit(X) distortions.append(km.inertia_) plt.plot(range(1,11),distortions, marker=’o’) plt.xlabel(‘Number of clusters’) plt.ylabel(‘Distortion’) plt.tight_layout() plt.show() 이 데이터에서는 k값이 3인 지점에서 엘보우(급감하다가 완만해지는)가 나타나므로 최적의 k=3 1.5 실루엣 그래프로 군집 품질 정량화 실루엣 분석(silhouette analysis) : 클러스터 내 샘플들이 얼마나 조밀하게 모여있는지 특정하는 그래프 도구 1. 샘플 xi와 동일 클러스터 내 다른 모든 샘플 사이의 거리를 평균하여 클러스터 응집력(cluster cohesion) ai계산 2. 샘플 xi와 외부의 가장 가까운 클러스터 내 모든 샘플들과 평균거리로 최근접 클러스터의 클러스터 분리도(cluster separation) bi를 계산한다 3. 클러스터 응집력과 분리도 사이의 차이를 둘 중 큰 값으로 나누어 실루엣 si를 다음과 같이 계산한다. 실루엣 계수는 -1 ~ 1사이 값을 가지며 1에 가까울수록 이상적 ** 실루엣 계수는 원형클러스터인 경우에만 한하여 타당한 평가측도임 Silhouette Analysis _ (good case) import numpy as np from matplotlib import cm from sklearn.metrics import silhouette_samples km = KMeans(n_clusters=3, init=’k-means++’, n_init=10, max_iter=300, tol=1e-04, random_state=0) y_km = km.fit_predict(X) cluster_labels = np.unique(y_km) n_clusters = cluster_labels.shape[0] silhouette_vals = silhouette_samples(X, y_km, metric=’euclidean’) y_ax_lower, y_ax_upper = 0, 0 yticks = [] for i, c in enumerate(cluster_labels): c_silhouette_vals = silhouette_vals[y_km == c] c_silhouette_vals.sort() y_ax_upper += len(c_silhouette_vals) color = cm.jet(float(i) / n_clusters) plt.barh(range(y_ax_lower, y_ax_upper), c_silhouette_vals, height=1.0, edgecolor=’none’, color=color) yticks.append((y_ax_lower + y_ax_upper) / 2.) y_ax_lower += len(c_silhouette_vals) silhouette_avg = np.mean(silhouette_vals) plt.axvline(silhouette_avg, color=”red”, linestyle=”–“) plt.yticks(yticks, cluster_labels + 1) plt.ylabel(‘Cluster’) plt.xlabel(‘Silhouette coefficient’) plt.tight_layout() plt.show() 평균 실루엣 계수값이 0.7보다 커 군집화가 잘 되었음을 확인할 수 있다. 나쁜 군집에 대한 실루엣 분석 km = KMeans(n_clusters=2, init=’k-means++’, n_init=10, max_iter=300, tol=1e-04, random_state=0) y_km = km.fit_predict(X) plt.scatter(X[y_km == 0, 0], X[y_km == 0, 1], s=50, c=’lightgreen’, edgecolor=’black’, marker=’s’, label=’cluster 1′) plt.scatter(X[y_km == 1, 0], X[y_km == 1, 1], s=50, c=’orange’, edgecolor=’black’, marker=’o’, label=’cluster 2′) plt.scatter(km.cluster_centers_[:, 0], km.cluster_centers_[:, 1], s=250, marker=’*’, c=’red’, label=’centroids’) plt.legend() plt.grid() plt.tight_layout() plt.show() 군집의 개수를 2개로 설정하여 위의 3개일 때보다 좋지 못한 clustering 수행 cluster_labels = np.unique(y_km) n_clusters = cluster_labels.shape[0] silhouette_vals = silhouette_samples(X, y_km, metric=’euclidean’) y_ax_lower, y_ax_upper = 0, 0 yticks = [] for i, c in enumerate(cluster_labels): c_silhouette_vals = silhouette_vals[y_km == c] c_silhouette_vals.sort() y_ax_upper += len(c_silhouette_vals) color = cm.jet(float(i) / n_clusters) plt.barh(range(y_ax_lower, y_ax_upper), c_silhouette_vals, height=1.0, edgecolor=’none’, color=color) yticks.append((y_ax_lower + y_ax_upper) / 2.) y_ax_lower += len(c_silhouette_vals) silhouette_avg = np.mean(silhouette_vals) plt.axvline(silhouette_avg, color=”red”, linestyle=”–“) plt.yticks(yticks, cluster_labels + 1) plt.ylabel(‘Cluster’) plt.xlabel(‘Silhouette coefficient’) plt.tight_layout() plt.show() * 1번 클러스터의 대부분의 관측값들이 0.5 이하의 낮은 실루엣 계수를 갖는다. * 클러스터의 길이와 두깨가 고르지 않다. (확연히 다르다.) 2. 계층적인 트리로 클러스터 조직화 계층적 군집화(hierarchical clusting) : 작은 단위에서 큰 단위로, 혹은 큰 단위에서 작은 단위로 순차적 군집화를 진행화는 방식 장점 – 덴드로그램(dendrogram)을 그릴 수 있다. 클러스터 개수 사전설정 필요가 없다. 계층 군집의 두 가지 방법으로 상향식 – 병합 계층 군집(agglomerative hierarchical clustering)과 하향식 – 분할 계층 군집(divisive hierarchical clustering)이 있다. 일반적으로 시간복잡도가 낮은 병합계층군집을 먼저 사용해보고, 결과가 별로일 경우 더 정밀한 경향이 있는 분할계층군집을 추가적으로 시도해 보는 것이 좋다. 2.1 상향식으로 클러스터 묶기 연결 기준(클러스터 간 거리를 계산하기 위한 기준) * 단일연결(single linkage) : 클러스터 쌍에서 가장 비슷한 샘플 간 거리가 가장 가까운 군집 병합 * 완전연결(complete linkage) : 클러스터 쌍에서 가장 비슷하지 않은 샘플 간 거리가 가장 가까운 군집 병합 * 평균연결(average linkage) : 클러스터 샘플 평균점의 거리가 가장 가까운 군집 병합 * 와드연결(Ward’s linkage) : 클러스터 내 SSE가 가장 작게 증가하는 방향으로 군집 병합 과정 요약 1. 모든 샘플들의 거리행렬을 계산한다. 2. 모든 샘플들 각각을 단일 클러스터로 표현한다. 3. 가장 비슷하지 않은 샘플 사이 거리에 기초하여 가장 가까운 두 클러스터를 병합한다 4. 유사도행렬을 업데이트 한다. 5. 하나의 클러스터가 남을 때까지 반복 데이터 생성 군집화를 위한 샘플데이터를 생성한다. (3개의 변수값을 가진 5개의 관측) # data generate import pandas as pd import numpy as np np.random.seed(123) variables = [‘X’,’Y’,’Z’] labels = [‘ID_0′,’ID_1′,’ID_2′,’ID_3′,’ID_4′] # sampling 5*3 float from Unif(0,1) X = np.random.random_sample([5,3])*10 df = pd.DataFrame(X, columns=variables, index=labels) df 2.2 거리 행렬에서 계층군집 수행 거리행렬 확인 샘플들 간 유클리디안 거리를 계산하여 거리행렬을 구성한다. # distance matrix from scipy.spatial.distance import pdist, squareform row_dist = pd.DataFrame(squareform(pdist(df, metric=’euclidean’)), columns = labels, index=labels) row_dist 연결행렬 확인 # linkage matrix from scipy.cluster.hierarchy import linkage row_clusters = linkage(pdist(df, metric=’euclidean’),method=’complete’) pd.DataFrame(row_clusters, columns=[‘row label 1′,’row label 2′,’distance’,’# of items in cluster’], index=[‘cluster %d’%(i+1) for i in range(row_clusters.shape[0])]) 클러스터 생성과정을 확인할 수 있다. 덴드로그램 그리기 덴드로그램은 병합 계층 군집화가 수행되는 동안 만들어지는 클러스터들을 요약해 보여준다. #dendrogram from scipy.cluster.hierarchy import dendrogram row_dendr = dendrogram(row_clusters, labels = labels) plt.tight_layout() plt.ylabel(‘Euclidean distance’) plt.show() 샘플 0과 4가 가장 유사하여 먼저 합쳐지고, 이후 1,2 병합, 3↔(0,4)병합 순으로 진행됨을 확인가능 2.3 사이킷런에서 병합군집 적용 from sklearn.cluster import AgglomerativeClustering ac = AgglomerativeClustering(n_clusters=3, affinity=’euclidean’, linkage=’complete’) labels = ac.fit_predict(X) print(‘클러스터 레이블: %s’%labels) ac = AgglomerativeClustering(n_clusters=2, affinity=’euclidean’, linkage=’complete’) labels = ac.fit_predict(X) print(‘클러스터 레이블: %s’%labels) 사이킷런의 AgglomerativeClustering클래스를 이용해 병합군집화를 수행할 수 있는데, 클러스터 수를 사전에 입력해야하고, 덴드로그램은 바로 그릴 수 없다. 클러스터링 결과는 Scipy에서 pdist, linkage를 사용해 진행한 것과 동일하다. 3. DBSCAN을 사용하여 밀집도가 높은 지역 찾기 DBSCAN(density-based spatial clustering of applications with noise) : 샘플이 조밀하게 모인(밀집도가 높은) 지역에 클러스터 레이블을 할당. 밀집도는 특정 반경 안에 있는 샘플 개수로 정의한다. 다음의 조건에 따라 샘플에 클래스레이블과는 별도인 특별한 레이블이 할당된다. * 어떤 샘플의 특정반경 내에 있는 이웃 샘플이 지정된 개수 이상이면 핵심샘플(core point) * 반경 내 지정개수보다 이웃이 적으나, 다른 핵심샘플의 반경안에 있으면 경계샘플(border point) * 핵심샘플과 경계샘플이 아닌 다른 모든 샘플은 잡음샘플(noise point)가 된다. 알고리즘 요약 1. 개별 핵심샘플이나 반경 내 핵심샘플들끼리 연결한 핵심샘플의 그룹을 클러스터로 만든다. 2. 경계샘플들을 해당 핵심샘플의 클러스터에 할당한다. * 원형 클러스터를 가정하지 않는다는 장점이 있고 (more general) * 모든 샘플들을 반드시 클러스터에 할당하지는 않으며 잡음샘플을 구분하는 능력이 있다. 알고리즘 비교 (k-means, agg, dbscan) # 군집화를 위한 반달모양 데이터셋 from sklearn.datasets import make_moons X, y = make_moons(n_samples=200, noise=0.05, random_state=0) plt.scatter(X[:,0],X[:,1]) plt.tight_layout() plt.show() # k-means와 agglomerative clust-의 결과 f, (ax1, ax2) = plt.subplots(1, 2, figsize=(8, 3)) km = KMeans(n_clusters=2, random_state=0) y_km = km.fit_predict(X) ax1.scatter(X[y_km == 0, 0], X[y_km == 0, 1], edgecolor=’black’, c=’lightblue’, marker=’o’, s=40, label=’cluster 1′) ax1.scatter(X[y_km == 1, 0], X[y_km == 1, 1], edgecolor=’black’, c=’red’, marker=’s’, s=40, label=’cluster 2′) ax1.set_title(‘K-means clustering’) ac = AgglomerativeClustering(n_clusters=2, affinity=’euclidean’, linkage=’complete’) y_ac = ac.fit_predict(X) ax2.scatter(X[y_ac == 0, 0], X[y_ac == 0, 1], c=’lightblue’, edgecolor=’black’, marker=’o’, s=40, label=’cluster 1′) ax2.scatter(X[y_ac == 1, 0], X[y_ac == 1, 1], c=’red’, edgecolor=’black’, marker=’s’, s=40, label=’cluster 2′) ax2.set_title(‘Agglomerative clustering’) plt.legend() plt.tight_layout() plt.show() 반달모양 클러스터를 잘 식별해내지 못했음. # DBSCAN의 결과 from sklearn.cluster import DBSCAN db = DBSCAN(eps=0.2, min_samples=5, metric=’euclidean’) y_db = db.fit_predict(X) plt.scatter(X[y_db == 0, 0], X[y_db == 0, 1], c=’lightblue’, marker=’o’, s=40, edgecolor=’black’, label=’cluster 1′) plt.scatter(X[y_db == 1, 0], X[y_db == 1, 1], c=’red’, marker=’s’, s=40, edgecolor=’black’, label=’cluster 2′) plt.legend() plt.tight_layout() plt.show() → 밀도기반 군집화 방법으로 다양한 형태의 데이터를 처리할 수 있다. DBSCAN의 단점 * 훈련샘플 갯수가 고정되어 있을 때, 특성 개수가 증가하면 차원의 저주로 인한 역효과 증가 특히 유클리디안 거리 측정을 사용할 때 (다른 군집화 알고리즘도 마찬가지) * 좋은 결과를 얻기 위해 두 개의 파라미터 (최소샘플 수, 반경)을 최적화해야함 결론 * 데이터 마다 적절한 군집화 알고리즘에 차이가 있음 * 거리측정 측도로 유클리디안 거리를 사용할 경우 데이터 표준화/정규화 필수 * 성공적인 군집화를 위해서는 알고리즘/하이퍼파라미터튜닝 뿐만 아니라 적절한 거리지표 선정과 도메인 지식이 더 중요할 수 있음 * 차원의 저주를 고려하여 군집화 수행 전 차원축소기법을 적용하는 것이 일반적. → 2차원으로 압축하면 시각화도 가능 인쇄
14 장 군집분석
import pandas as pd pandaspd import numpy as np numpynp import matplotlib.pyplot as plt matplotlib.pyplotplt # K-Means 알고리즘 from sklearn.cluster import KMeans, MiniBatchKMeans sklearn.clusterKMeans, MiniBatchKMeans from sklearn.datasets import load_iris sklearn.datasetsload_iris from sklearn.model_selection import train_test_split sklearn.model_selectiontrain_test_split # CLustering 알고리즘의 성능 평가 측도 from sklearn.metrics import homogeneity_score, \ sklearn.metricshomogeneity_score, \ completeness_score, v_measure_score, \ adjusted_rand_score, silhouette_score, rand_score calinski_harabasz_score from sklearn.metrics.cluster import contingency_matrix sklearn.metrics.clustercontingency_matrix from sklearn.preprocessing import StandardScaler # 변수 표준화 sklearn.preprocessingStandardScaler from sklearn import metrics sklearnmetrics # iris data = load_iris() irisload_iris() X = iris.data iris.data y = iris.target iris.target # 변수 표준화 = StandardScaler() # 변수 표준화 클래스 scalerStandardScaler() # 표준화를 위해 변수별 파라미터(평균, 표준편차) 계산 scaler.fit(X) # scaler.mean_, scaler.scale_ = scaler.transform(X) # 훈련자료 표준화 변환 X_stdscaler.transform(X)
키워드에 대한 정보 파이썬 군집 분석
다음은 Bing에서 파이썬 군집 분석 주제에 대한 검색 결과입니다. 필요한 경우 더 읽을 수 있습니다.
이 기사는 인터넷의 다양한 출처에서 편집되었습니다. 이 기사가 유용했기를 바랍니다. 이 기사가 유용하다고 생각되면 공유하십시오. 매우 감사합니다!
사람들이 주제에 대해 자주 검색하는 키워드 [파이썬 실습] 군집분석
- 동영상
- 공유
- 카메라폰
- 동영상폰
- 무료
- 올리기
YouTube에서 파이썬 군집 분석 주제의 다른 동영상 보기
주제에 대한 기사를 시청해 주셔서 감사합니다 [파이썬 실습] 군집분석 | 파이썬 군집 분석, 이 기사가 유용하다고 생각되면 공유하십시오, 매우 감사합니다.