K-Means와 계층적 클러스터링을 모두 다뤄보는 파이썬 예제이다. 본 예제에서는 학생들의 성적 데이터를 분석하여 유의미한 인사이트를 얻어보는 과정을 다룬다.
** 연습을 위한 엑셀 데이터와 가이드 노트북 파일은 글 하단에 깃허브 주소에서 확인해주세요. 댓글은 블로그를 운영하는 데 큰 기쁨이 됩니다 🙂
■ 학생 데이터 파이썬 분석
파이썬 예제에서 많이 다뤄본 내용은 이제 별도 설명없이 코드만 기재하겠다.
# 패키지 불러오기 import pandas as pd # 데이터 읽기 student_data = pd.read_excel('ex1.xls') # 데이터 개요 살펴보기 display(student_data.head())
데이터는 학생들의 수강 데이터로, 어떤 학기에 어떤 수업을 들었는지 출석과 성적까지 포함된 데이터이다. 한 학생이 여러 학기에 여러 과목을 들을 가능성이 크므로, 이름으로 그룹핑을 하여 이 학생의 출석과 성적이 어떤지 살펴보자.
# 이름으로 그룹핑하여 평균값 구하기 students = student_data.groupby('Name').mean() # 다시 데이터 살펴보기 display(students.head())
이번에는 학생들을 군집으로 나눠보자. 출석과 성적 데이터 기반이니 대략적으로 1) 출석도 좋고 성적도 좋은 학생군 2) 출석은 나쁘지만 성적은 좋은 학생군 3) 출석도 나쁘고 성적도 나쁜 학생군 으로 나눠보도록 하자.
# k=3 클러스터 생성 estimator = KMeans(n_clusters = 3) cluster_ids = estimator.fit_predict(students) # 플롯 plt.scatter(students['Attended'], students['Mark'], c=cluster_ids) plt.xlabel("Attended classes") plt.ylabel("Mark") # 범례 달기 for name, mark, attended in students.itertuples(): plt.annotate(name, (attended, mark)) plt.show()
결과값은 다음과 같다.
별다른 처리 없이 학생 데이터를 클러스터링했더니 ‘출석’에 좌우된 것이 보인다. 성적은 0~5점 사이인데 반해 출석은 0~13까지 범위가 더 크기 때문이다. 두 개의 클래스의 단위가 다를 때는 표준화(normalization)를 해주어야 한다. 여기서는 MinMaxScaler()로 표준화를 진행하고자 한다.
# normalizer 생성 min_max_scaler = preprocessing.MinMaxScaler() # 표준화하기 students[['Mark', 'Attended']] = min_max_scaler.fit_transform(students[['Mark', 'Attended']]) # 클러스터링 생성 estimator = KMeans(n_clusters = 3) cluster_ids = estimator.fit_predict(students) plt.scatter(students['Attended'], students['Mark'], c=cluster_ids) plt.xlabel("Attended classes") plt.ylabel("Mark") for name, mark, attended in students.itertuples(): plt.annotate(name, (attended, mark)) plt.show()
표준화를 통해 플로팅된 결과이다.
이번에는 같은 데이터로 계층적 클러스터링을 해보자. 어떤 linkage mode(군집 간의 거리를 재는 방식)가 적합한지 반복해서 돌려보고 시각화하여 확인해보는 연습이다. ** 계층적 클러스터링에 대한 이론적인 설명은 다음 글(링크)를 참고해주세요.
# 최단연결법은 single, 평균연결법은 average, 최장연결법은 complete으로 표기한다. modes = ['single', 'average', 'complete'] plt.figure(figsize=(20,5)) # subplot() 함수를 사용하여 서브 플롯을 추가하고 반환 값을 y_axis라는 변수에 할당 # sharey 매개 변수를 사용하여 서브 플롯에 대한 모든 호출에 이 변수를 전달하여 모든 플롯이 동일한 y 축 사용 y_axis = None # 모든 linkage mode 반복 생성 for i, mode in enumerate(modes): # 서브플롯 추가, y축은 공유 y_axis = plt.subplot(1, 4, i + 1, sharey = y_axis) # 레이블링 plt.title('Dendrogram - linkage mode: {}'.format(mode)) plt.xlabel('distance') plt.ylabel('student') # 클러스터링 clustering = linkage(students[['Mark', 'Attended']], mode) # 덴드로그램 dendrogram(clustering, labels=list(students.index), orientation='right') plt.tight_layout() plt.show()
결과를 해석하면 최단연결법(single)일 때 결과값이 가장 우수하다. Single만 ‘출석은 안하지만 성적은 좋은 학생군’과 ‘출석도 안하고 성적도 나쁜 학생군’을 잘 구분해주기 때문이다. 만약 클러스터를 4개로 나누면 어떨까?
k = 4 로 바꾼 결과값은 위와 같은데, 이때는 노란색 학생과 보라색 학생을 나누어주는 최장연결법(complete)이 가장 우수하다는 것을 확인할 수 있다.
엑셀 파일과 가이드 노트북 파일은 다음 깃허브 링크에 올려져 있습니다. 솔루션 참고해서 연습해보세요. 본 자료가 도움이 되셨다면 댓글 하나 부탁드립니다 🙂 혹은 어려운 점 있다면 남겨주세요, 확인 후 회신드리겠습니다.
https://github.com/lucy-the-marketer/k-means-clustering-student
좋은사이트개설해서 알찬예제 올려주셔서 공부하는데 큰 도움이 되고 있습니다. 실습에 필요한 엑셀파일 좀 메일로 부탁드립니다. -라일락
안녕하세요! 따뜻한 댓글 감사합니다. 자료는 다음 링크에서 다운로드 받아주세요. https://github.com/lucy-the-marketer/k-means-clustering-student
감사합니다.
안녕하세요! 현재 코딩 공부 중인 고등학생입니다. 해당 예제를 연습하고 연습한 내용을 고등학교 진로 시간 발표에 활용하려고 합니다. 블로그 내용을 그대로 쓰는 것이 아닌 깃허브에 올라온 예제를 보고 직접 코드를 짜본 다음 그 과정을 ppt로 보여주려고 하고, 데이터도 올려주신 엑셀파일을 사용하려고 합니다. 생기부 기재를 위한 활동이라서 괜찮으신지 여쭙고 싶습니다!
안녕하세요, 답변이 늦었습니다. 네, 괜찮습니다. 허락 구해주셔서 고맙습니다 🙂 화이팅!
피피티에 예제 출처도 당연히 기재하겠습니다!!
좋은정보 감사드립니다~~
따뜻한 댓글 감사합니다 🙂
댓글이 닫혔습니다.