import pandas as pd
# iris 데이터를 불러보자
from sklearn.datasets import load_iris
iris = load_iris()
iris
# sklearn의 datasets은 Python의 dict 형과 유사하다
iris.keys()
print(iris['DESCR'])
print(iris['target_names'])
len(iris['target'])
print(iris['target'])
iris.data
# pandas
import pandas as pd
# DataFrame으로 만들어보기
iris_pd = pd.DataFrame(iris.data, columns=iris.feature_names)
iris_pd.head()
# 품종 정보도 column에 포함
iris_pd['species'] = iris.target
iris_pd.head()
# 일단 그래프 그리는 모듈 import
import seaborn as sns
import matplotlib.pyplot as plt
# boxplot(x='sepal length (cm)')
# orient='h' : 수평으로 그리기 옵션
# sepal length (cm) 범위가 겹치는 부분이 있어 구분하기 어려울 수 있다.
# virginica의 한 값만 떨어져 있다.
# 'setosa', 'versicolor', 'virginica'
plt.figure(figsize=(12, 6))
sns.boxplot(x='sepal length (cm)', y= 'species', data=iris_pd, orient='h')
plt.show()
# boxplot(x='sepal width (cm)')
# 'setosa', 'versicolor', 'virginica'
plt.figure(figsize=(12, 6))
sns.boxplot(x='sepal width (cm)', y= 'species', data=iris_pd, orient='h')
plt.show()
# boxplot(x='petal length (cm)')
# 'setosa', 'versicolor', 'virginica'
# petal length (cm)으로 setosa는 구분하기에 적절하나, 나머지 품종은 구분하기가 애매하다
plt.figure(figsize=(12, 6))
sns.boxplot(x='petal length (cm)', y='species', data=iris_pd, orient='h');
# pairplot
# petal length (cm), sepal width (cm)을 동시에 본다면 세 품종을 구분할 수도 있을 것으로 보인다.
sns.pairplot(iris_pd, hue='species')
# petal length (cm), petal width (cm)으로 iris 3종에 대한 구분이 가능할 것 같다.
# setosa는 구분 가능하다.
# 몇 개의 데이터는 놓쳐지지만 patal width가 1.6정도에서 구분하면,
# versicolor : patal length가 2.5보다 크면서 petal width가 1.6보다 작을 경우
# virginica : patal length가 2.5보다 크면서 petal width가 1.6보다 클 경우
# 이 내용을 질문(조건문)으로 순차적으로 표현할 수 있다 - Decision Tree
sns.pairplot(data=iris_pd,
vars=['petal length (cm)', 'petal width (cm)'],
hue = 'species',
height=4);
# 상황설정
# setosa 구분은 잘 되는데 두 종류는 어떻게 구분할 것인가
plt.figure(figsize=(12, 6))
sns.scatterplot(x='petal length (cm)', y= 'petal width (cm)',
data= iris_pd, hue='species', palette='Set2');
# 데이터 변경
iris_12 = iris_pd[iris_pd['species'] != 0]
iris_12.info()
# 두 개의 데이터에 집중
# 두 개의 데이터 경계선이 어디에 있는 것이 최선일까
plt.figure(figsize=(12, 6))
sns.scatterplot(x='petal length (cm)', y= 'petal width (cm)',
data= iris_12, hue='species', palette='Set2');
Decision Tree의 분할 기준(Split Crierion)
정보 획득 : 정보의 가치를 반환하는데 발생하는 사전의 확률이 작을수록 정보의 가치는 커진다. 정보 이득이란 어떤 속성을 선택함으로 인해서 데이터를 더 잘 구분하게 되는 것.
엔트로피 개념 : 열역학의 용어로 물질의 열적 상태를 나타내는 물리 량의 단위 중 하나. 무질서의 정도를 나타냄. 1948년 엔트로피 개념에서 힌트를 얻어 확률 분포의 무질서도나 불확실성
혹은 정보 부담 정도를 나타내는 정보 엔트로피 개념을 클로드 섀넌이 고안함
entropy : 얼마만큼의 정보를 담고 있는가? 또한, 무질서도(disorder)를 의미, 불확실성(uncertainty)를 나타내기도 함
- 어떤 확률 분포로 일어나는 사건을 표현하는 데 필요한 정보의 양이며
이 값이 커질수록 확률 분포의 불확실성이 커지며 결과에 대한 예측이 어려워짐
# 엔트로피
import numpy as np
p = np.arange(0.001, 1, 0.001)
plt.grid()
plt.title('$-p \log_{2}-{p}$')
plt.plot(p, -p*np.log2(p));
ex) 10개의 빨간공, 6개의 파란공이 있을 때의 엔트로피
-(10/16)*np.log2(10/16) - 6/16*np.log2(6/16)
0.5*(-(7/8)*np.log2(7/8)-(1/8)*np.log2(1/8)) + 0.5*(-(3/8)*np.log2(3/8)-(5/8)*np.log2(5/8))
- 지니계수 : Gini index 혹은 불순도율, 엔트로피의 계산량이 많아서 비슷한 개념이면서 보다 계산량이 적은 지니계수를 사용하는 경우가 많다.
ex) 10개의 빨간공, 6개의 파란공이 있을 때의 지니계수
1-(6/16)**2 - (10/16)**2
0.5*(1-(7/8)**2 - (1/8)**2) + 0.5*(1-(3/8)**2 - (5/8)**2)
Scikit Learn : 2007년 구글 썸머 코드에서 처음 구현. 현재 파이썬에서 가장 유명한 기계 학습 오픈 소스 라이브러리
sklearn을 이용한 결정나무의 구현
# sklearn을 이용한 결정나무의 구현
from sklearn.tree import DecisionTreeClassifier
iris_tree = DecisionTreeClassifier()
iris_tree.fit(iris.data[:, 2:], iris.target)
# Accuracy 확인
from sklearn.metrics import accuracy_score
y_pred_tr = iris_tree.predict(iris.data[:, 2:])
accuracy_score(iris.target, y_pred_tr)
y_pred_tr
iris.target
# mlxtend 설치
#!pip install mlxtend
# iris의 품종을 분류하는 결정나무 모델이 어떻게 데이터를 분류했는지 확인
from mlxtend.plotting import plot_decision_regions
plt.figure(figsize=(14, 8))
plot_decision_regions(X=iris.data[:, 2:], y=iris.target, clf = iris_tree, legend=2)
plt.show()
# 데이터를 훈련 / 테스트로 분리
# 8:2 확률로 특성(features)과 정답(labels)를 분리해서
from sklearn.model_selection import train_test_split
features = iris.data[:, 2:]
labels = iris.target
X_train, x_test, Y_train, y_test = train_test_split(features, labels,
test_size=0.2, random_state=13)
# test_size=0.2 → 훈령용 데이터 사이즈 20%
# 훈련용 / 테스트용이 잘 분리 되었을까?
# 각 클래스(setosa, versicolor, verginica)별로 동일 비율이 아니다
import numpy as np
np.unique(y_test, return_counts=True)
# 그럴 때 쓰는 옵션 stratify
from sklearn.model_selection import train_test_split
features = iris.data[:, 2:]
labels = iris.target
X_train, x_test, Y_train, y_test = train_test_split(features, labels,
test_size=0.2,
stratify=labels,
random_state=13)
import numpy as np
np.unique(y_test, return_counts=True)
# 방금 전처럼 다시 train 데이터만 대상으로 결정나무 모델을 생성
# 학습할 때마다 일관성을 위해 random_state만 고정
# 모델을 단순화시키기 위해 max_depth 조정
from sklearn.tree import DecisionTreeClassifier
iris_tree = DecisionTreeClassifier(max_depth=2, random_state=13)
iris_tree.fit(X_train, Y_train)
# train 데이터에 대한 accuracy 확인
# iris 데이터는 단순해서 acc가 높게 나타남
from sklearn.metrics import accuracy_score
y_pred_tr = iris_tree.predict(X_train)
accuracy_score(Y_train, y_pred_tr)
# 모델 확인
# conda install python-graphviz 이걸로 설치해야 함
# from graphviz import Source
# from sklearn.tree import export_graphviz
# Source(export_graphviz(iris_tree, feature_names=['length', 'width'],
# class_names=iris.target_names,
# rounded=True, filled=True))
# 이걸 써야됨
from sklearn.tree import plot_tree
plt.figure(figsize=(12, 8))
plot_tree(iris_tree);
# 훈련데이터에 대한 결정경계를 확인
import matplotlib.pyplot as plt
from mlxtend.plotting import plot_decision_regions
plt.figure(figsize=(12, 8))
plot_decision_regions(X=X_train, y=Y_train, clf=iris_tree, legend=2)
plt.show()
# 테스트 데이터에 대한 accuracy
from sklearn.metrics import accuracy_score
y_pred_test = iris_tree.predict(x_test)
accuracy_score(y_test, y_pred_test)
# 잔기술 하나 - 전체 데이터에서 관찰해보기
scatter_highlight_kwargs = {'s':150, 'label':'Test data', 'alpha': 0.9}
scatter_kwargs = {'s':120, 'edgecolor': None, 'alpha':0.7}
plt.figure(figsize=(12, 8))
plot_decision_regions(X=features, y=labels,
X_highlight=x_test, clf=iris_tree, legend=2,
scatter_highlight_kwargs=scatter_highlight_kwargs,
scatter_kwargs=scatter_kwargs,
contour_kwargs={'alpha':0.2})
plt.show()
# feature를 네 개
features = iris.data
labels = iris.target
X_train, x_test, Y_train, y_test = train_test_split(features, labels,
test_size=0.2,
stratify=labels,
random_state=13)
iris_tree = DecisionTreeClassifier(max_depth=2, random_state=13)
iris_tree.fit(X_train, Y_train)
plt.figure(figsize=(12, 8))
plot_tree(iris_tree);
# 모델을 사용하는 방법
# 길가다가 주운 iris가 sepal과 petal의 length, width가 각각 [4.3, 2. , 1.2, 1.0]이라면
test_data = [[4.3, 2., 1.2, 1.0]]
iris_tree.predict_proba(test_data)
test_data = [[4.3, 2., 1.2, 1.0]]
iris_tree.predict(test_data)
# 각 클래스별 확률이 아니라 범주 값을 바로 알고 싶다면
iris.target_names
test_data = [[4.3, 2., 1.2, 1.0]]
iris.target_names[iris_tree.predict(test_data)]
# 주요 특성 확인하기
# 설정한 max_depth로 feature를 알 수 있음(?)
iris_tree.feature_importances_
# Tree계열 알고리즘은 특성을 파악하는데 장점을 가진다
iris_clf_model = dict(zip(iris.feature_names, iris_tree.feature_importances_))
iris_clf_model
# zip과 언패킹
# 리스트를 튜플로 zip
list1 = ['a', 'b', 'c']
list2 = [1, 2, 3]
pairs = [pair for pair in zip(list1, list2)]
pairs
# 튜플을 dict으로
dict(pairs)
# 한번에 설정
dict(zip(list1, list2))
# unpacking 인자를 이용한 역변환
a, b = zip(*pairs)
print(list(a))
print(list(b))
💻 출처 : 제로베이스 데이터 취업 스쿨