본문 바로가기
study/Python

[Python] 47. 비지도학습. 군집

by 금이패런츠 2022. 7. 8.
728x90
반응형

1. 비지도학습. 군집

1-1. K-means 알고리즘

1-2. DBSCAN 알고리즘 : 공간의 밀집도로 클러스터 구분

# -*- coding: utf-8 -*-
"""
Created on Fri Jul  8 09:00:16 2022

@author: p011v
"""

'''
    지도학습   : 학습시 정답제공
        회귀분석 : 과거의 데이터를 회귀선을 이용하여 분석
                  단순회귀분석 : 독립변수 1개, 종속변수 1개
                        단항회귀분석 : 직선의 방정식
                        다항회귀분석 : 곡선의 방정식
                  다중회귀분석 : 독립변수 여러개, 종속변수 1개
                  알고리즘 : 선형회귀분석(LinearRegression)
                  평가방식 : RMSE : mse(평균제곱오차)의 제곱근
                               mse : (실제데이터 - 예측데이터)**2의 평균
                                      작은 값일수록 정확도가 높아짐
        분류(Classification) : 설명변수를 이용하여 목표변수의 값을 예측
               알고리즘 : KNN(K-Nearset-Nerghbors) : 최근접이웃알고리즘
                         SVM(Support Vector Machine)
                         Decision Tree : 의사결정나무
               평가방식 : TP(실제:T, 예측:T), TN(실제:F, 예측:F), 
                         FP(실제:F, 예측:T), FN(실제:T, 예측:F)          
                         정확도(accuracy) : (TP + TN) / (TP+ TN + FP + FN)
                         정밀도(precision) : TP / (TP + FP)
                         재현율,민감도(recall): TP / (TP + FN)
                         f1-score(조화평균) : 2 * (정밀도 * 재현율) / (정밀도 + 재현율) 
                         
    비지도학습 : 학습시 정답제공 안함
        군집(Clustering) : 데이터의 유사성을 기준으로 그룹화
               알고리즘 : K-means
                         DBSCAN
'''
########## 1. 비지도학습. 군집
########## 1-1. K-means 알고리즘
# 고객의 연간 구매금액을 상품 종류별로 구분한 데이터
import pandas as pd
import matplotlib.pyplot as plt
from sklearn import cluster
uci_path = 'https://archive.ics.uci.edu/ml/machine-learning-databases/00292/Wholesale%20customers%20data.csv'
df = pd.read_csv(uci_path, header=0)
df.info()
df.head()
X = df.iloc[:,:]
from sklearn import preprocessing
X = preprocessing.StandardScaler().fit(X).transform(X) # 정규화. 수치들을 일정하게 변경
X
# init="k-means++" : 랜덤하게 중심점을 선정하기 위한 알고리즘 설정
# n_clusters=5 : 그룹(클러스터)의 갯수설정. 5개 종류로 구분
# n_init=10 : 10개 중심점으로 시작
kmeans = cluster.KMeans(init="k-means++", n_clusters=5, n_init=10) #KMeans 객체

kmeans.fit(X) #학습하기
cluster_label = kmeans.labels_ #그룹한 결과값
len(cluster_label)
df['cluster'] = cluster_label
df['cluster'].unique() # 0 ~ 4. 5가지 정보
df.info()
# cluster 별 평균 조회하기
df.groupby('cluster').mean()[["Fresh", "Milk", "Grocery", "Frozen", "Detergents_Paper", "Delicassen"]]

# 산점도 출력하기
# Grocery, Frozen의 산점도 출력하기
# cluster컬럼을 색상으로 표현
df.plot(kind='scatter', x='Grocery', y='Frozen', c='cluster', cmap='Set1', \
        colorbar=True, figsize=(10, 10))
# Milk, Delicassen의 산점도 출력하기
# cluster컬럼을 색상으로 표현
df.plot(kind='scatter', x='Milk', y='Delicassen', c='cluster', cmap='Set1', \
        colorbar=True, figsize=(10, 10))

# iris 데이터를 이용하여 군집 알고리즘 연습
from sklearn import datasets
iris = datasets.load_iris()    
type(iris)    
iris    
iris.data   #독립변수
iris.target #속성변수

import pandas as pd
labels = pd.DataFrame(iris.target)
labels.columns=["labels"]
labels.info()
datas = pd.DataFrame(iris.data)
datas.columns=["Sepal length", "Sepal width", "Petal length", "Petal width"]
data = pd.concat([datas, labels], axis=1)
data.info()

# 꽃받침 정보로 그룹화하기
feature = data[["Sepal length", "Sepal width"]]
# Kmeans 알고리즘으로 군집화하기
# 3개의 그룹으로 그룹화하는 K-Means 객체 생성하기
model = cluster.KMeans(init="k-means++", n_clusters=3, n_init=6) #KMeans 객체
model.fit(feature) #학습하기
model.predict(feature)
model.labels_ #그룹한 결과값
predict = pd.DataFrame(model.predict(feature))
predict.columns=['predict']
predict.info()
r = pd.concat([feature, predict], axis=1)
r.head()

# 예측된 데이터를 그래프로 표시하기
plt.rc('font', family='Malgun Gothic')
fig = plt.figure()
plt.scatter(r['Sepal length'], r['Sepal width'], c=r['predict'], alpha=0.5)
plt.title("예측 cluster")
plt.show()
# 실제 데이터를 그래프로 표시하기
fig = plt.figure()
plt.scatter(data['Sepal length'], data['Sepal width'], c=data['labels'], alpha=0.5)
plt.title("실제 labels")
plt.show()

########## 1-2. DBSCAN 알고리즘 : 공간의 밀집도로 클러스터 구분
import pandas as pd
import folium
file_path = "data/2016_middle_shcool_graduates_report.xlsx"
df = pd.read_excel(file_path, header=0)
df.info()
df.head()
# df데이터에서 각 중학교의 정보를 지도에 원으로 표시하기
mschool_map = folium.Map(location=[37.55,126.98],zoom_start=12)
for name, lat, lng in zip(df.index, df.위도, df.경도):
    folium.CircleMarker([lat, lng],         #위도, 경도값
                        radius=5,          #반지름 크기
                        color='brown',      #원 둘레 색상
                        fill=True,          #원 내부를 채움
                        fill_color="coral", #원 내부 색상
                        fill_opacity=0.7,   #원 내부의 투명도 0 ~ 1 : 0(투명), 1(불투명)
                        popup=name          #클릭시 나타나는 내용
                        ).add_to(mschool_map)
mschool_map.save('mid_shcool.html')
df.info()   
df.지역.unique()
df.코드.unique()
df.유형.unique()

# 원핫인코딩 : 문자열 => 숫자형 컬럼으로 변경
# label인코딩 : 문자열 => 숫자형 컬럼으로 변경
#               크기정보가 아닌 숫자인경우 변경
from sklearn import preprocessing
label_encoder = preprocessing.LabelEncoder() # label 인코딩 기능
onehot_encoder = preprocessing.OneHotEncoder() #원핫 인코딩 기능

label_code = label_encoder.fit_transform(df["코드"])
label_code
df["코드"].values[:10]
label_code[:10]
df["코드"].values[-10:-1]
label_code[-10:-1]

label_loc = label_encoder.fit_transform(df["지역"])
df["지역"].values[:10]
label_loc[:10]
df["지역"].values[-10:-1]
label_loc[-10:-1]

label_type = label_encoder.fit_transform(df["유형"])
label_day = label_encoder.fit_transform(df["주야"])

# label_encoder 된 데이터를 df의 컬럼[code, location, type, day]로 추가하기
df["code"] = label_code
df["location"] = label_loc
df["type"] = label_type
df["day"] = label_day

# 진학률을 기준 분리하기
X=df.iloc[:,[9,10,13]]
# X 데이터 정규화하기
X = preprocessing.StandardScaler().fit(X).transform(X)
X[:10]
# DBSCAN 알고리즘 : 밀도기반 클러스터링
# eps=0.2 : 반지름 크기 
# min_samples=5 : 갯수의 최소값. eps의 영역내에 최소 5개 이상의 점(point)이 있으면 클러스터로 인정
# cluster : 그룹
# core point : 그룹화시의 중심점
# border point : 그룹에는 속하지만, core point는 아님. 중심점인 경우 최소갯수에는 미달
# noise point : 그룹화 되지 못하는 데이터. 값이 -1로 설정됨
dbm = cluster.DBSCAN(eps=0.2, min_samples=5) 
dbm.fit(X) #학습하기
cluster_label = dbm.labels_
df["cluster"] = cluster_label
df["cluster"].unique()

# 클러스터별로 지도의 색으로 표시하기
colors = {-1:'gray', 0:'coral', 1:'blue', 2:'green', 3:'red'}
cluster_map = folium.Map(location=[37.55,126.98],zoom_start=12)
for name, lat, lng, clus in zip(df.index, df.위도, df.경도, df.cluster):
    folium.CircleMarker([lat, lng],              #위도, 경도값
                        radius=5,                #반지름 크기
                        color=colors[clus],      #원 둘레 색상
                        fill=True,               #원 내부를 채움
                        fill_color=colors[clus], #원 내부 색상
                        fill_opacity=0.7,        #원 내부의 투명도 0 ~ 1 : 0(투명), 1(불투명)
                        popup=name,              #클릭시 나타나는 내용
                        tooltip=name
                        ).add_to(cluster_map)
cluster_map.save('./seoul_maschool_cluster.html')

# academy1.csv 파일을 읽어서 3개로 (KMeans 알고리즘) 군집화하기
data = pd.read_csv("data/academy1.csv")

from sklearn.cluster import KMeans
model = KMeans(init="k-means++", n_clusters=3) #KMeans 객체 생성
model.fit(data.iloc[:,1:]) # 학생번호는 제외
result = model.predict(data.iloc[:,1:])
result
data["group"] = result

fig = plt.figure()
plt.scatter(data['국어점수'], data['영어점수'], c=data['group'], alpha=0.5)
plt.xlabel("국어점수")
plt.ylabel("영어점수")
plt.show()

# cluster 별로 평균 출력하기
data.groupby("group").mean()
for s in data.groupby("group") :
    print(s)
728x90
반응형