Machine Learning - 1. iris 분류

김다희·2024년 6월 24일

Machine Learning

프로그래밍하지 않고도 컴퓨터에 학습할 수 있는 능력을 부여하는 학문

  • 명시적인 프로그램에 의해서가 아니라, 주어진 데이터를 통해 규칙을 찾는 것

머신러닝의 역사

  • 1969s 로젠블롯의 퍼셉트론(최초의 인공신경망)
  • 1974s 인공지능의 첫번째 겨울(성과부진 + 민스키의 비판)
  • 1987s 인공지능의 두번째 겨울(신경망 문제 + 과도한 기대)
  • 1993s~ 머신러닝 기법 발달, 신경망 이론 성숙

iris 분류

1. iris data 관찰

1) 데이터 불러오기

from sklearn.datasets import load_iris
iris = load_iris()

2) 데이터 확인

  • iris 품종 확인
iris.target
iris.target_names

  • 각각의 target
    0: setosa
    1: versicolor
    2: virginica
  • iris 데이터
iris.data

3) DataFrame

iris_pd = pd.DataFrame(iris.data, columns=iris['feature_names'])
iris_pd

4) 시각화

import matplotlib.pyplot as plt
import seaborn as sns

boxplot

  • sepal length
plt.figure(figsize=(12,6))
sns.boxplot(x= 'sepal length (cm)', y='species', data= iris_pd, orient='h');

📌 품종별 영역이 겹쳐있어 구분하기 어려움

  • sepal width
plt.figure(figsize=(12,6))
sns.boxplot(x= 'sepal width (cm)', y='species', data= iris_pd, orient='h');

📌 품종별 영역이 겹쳐있어 구분하기 어려움

  • petal length
plt.figure(figsize=(12,6))
sns.boxplot(x= 'petal width (cm)', y='species', data= iris_pd, orient='h');

📌 setosa 품종은 구분 가능

  • petal width
plt.figure(figsize=(12,6))
sns.boxplot(x= 'petal width (cm)', y='species', data= iris_pd, orient='h');

pairplot

sns.pairplot(iris_pd, hue= 'species')

📌 맨밑 오른쪽에서 2번째 그래프는 구별 가능

sns.pairplot(data= iris_pd,
             vars=['petal length (cm)', 'petal width (cm)'],
              hue='species', height=4);

📌 0번 품종은 구분 가능(petal length가 2.5보다 작으면 setosa)

5) 구분선

  • setosa는 구분 가능

  • 1번과 2번 품종을 어떻게 구분할 것인가?(구분선의 기준)

  • 3개 품종 구분 규칙

1. Decision Tree

📌 1번과 2번 품종을 어떻게 구분할 것인가?(구분선의 기준)
1) 1번, 2번 품종만 따로

iris_12 = iris_pd[iris_pd['species']!= 0]
iris_12.info()

2) 1번, 2번 품종 그래프

plt.figure(figsize=(12,6))
sns.scatterplot(x='petal length (cm)', y='petal width (cm)',
                data = iris_12, hue = 'species', palette="Set2");

경계선이 어디에 있어야 최고일까?

분할 기준

1) 엔트로피


엔트로피 = -pi log2 pi 의 모든 합

  • 무질서할수록 엔트로피 값 높음(불확실성 높을수록)
  • 엔트로피 값이 작아야 좋은 것

2) 지니계수

  • Gini index 혹은 불순도율
  • 엔트로피의 계산량이 많아서 계산량이 적은 지니계수를 사용하는 경우가 많다.
  • 1 - (시그마 p의 제곱 i)
  • 예제

2. Scikit Learn

  • 파이썬에서 가장 유명한 기계 학습 오픈 소스 라이브러리

  • import

from sklearn.tree import DecisionTreeClassifier

iris_tree = DecisionTreeClassifier()
  • petal data 슬라이싱(petal data가 잘 구분되므로 petal data만 이용!)
iris.data[:, 2:]

1) 학습: fit

모델명.fit(데이터, 정답)

iris_tree.fit(iris.data[:,2:], iris.target)

2) 예측: predict

모델명.predict(예측할데이터)

y_pred_tr = iris_tree.predict(iris.data[:, 2:])

3) 확인: accuracy_score()

  • import
from sklearn.metrics import accuracy_score

accuracy_score(정답, 예측답)
정확도 점수: 0.9933

accuracy_score(iris.target, y_pred_tr)

3. 과적합

1) Tree model visualization

모델 학습이 잘 되었는지 확인

from sklearn.tree import plot_tree

plt.figure(figsize=(12,8))
plot_tree(iris_tree)

2) plot_decition_regions

  • 설치: !pip install mlxtend
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()

• 저 경계면은 올바른 걸까?(1번, 2번 모델쪽의 꺾인 부분)
• 저 결과는 내가 가진 데이터를 벗어나서 일반화할 수 있는 걸까?
• 어차피 얻은(혹은 구한) 데이터는 유한하고 내가 얻은 데이터를 이용해서 일반화를 추구하게 된다.
• 이때 복잡한 경계면은 모델의 성능을 결국 나쁘게 만든다
-> 과적합

4. 데이터 분리

가지고 있는 데이터를 분리하여(ex. 훈련 80%, 테스트 20%) 한쪽은 학습, 나머지는 검증 진행

1) 훈련 / 테스트 데이터 분리

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)
  • X_train : 훈련시킬 80%의 petal length & petal width 데이터
  • X_test : 나머지 20%의 petal length & petal width 데이터
  • y_train : 훈련시킬 80%의 정답(품종no)
  • y_test : 나머지 20%의 정답(품종no)

2) 확인

  • 그냥 하면 품종별 타겟 갯수가 제멋대로 할당됨
    -> stratify = labels 추가하여 맞춰주기
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)
-> (array([0, 1, 2]), array([10, 10, 10], dtype=int64))

3) 학습

  • max_depth: 성능을 제한(학습 dataset 과적합 방지 위해)
  • 여기서는 2로 제한
from sklearn.tree import DecisionTreeClassifier

iris_tree = DecisionTreeClassifier(max_depth=2, random_state=13)
iris_tree.fit(X_train, y_train)

4) 학습 data 확인

  • tree
import matplotlib.pyplot as plt
from sklearn.tree import plot_tree

plt.figure(figsize=(12,8))
plot_tree(iris_tree)

  • accuracy
from sklearn.metrics import accuracy_score

y_pred_tr = iris_tree.predict(iris.data[:, 2:])
accuracy_score(iris.target, y_pred_tr)
-> 0.9533333333333334
  • plot_decition_regions
from mlxtend.plotting import plot_decision_regions

plt.Figure(figsize=(14,8))
plot_decision_regions(X=X_train, y=y_train, clf=iris_tree, legend=2)
plt.show()

5) test data 확인

  • accuracy
y_pred_test = iris_tree.predict(X_test)
accuracy_score(y_test, y_pred_test)
-> 0.9666666666666667

6) 전체 data에 test data 표시

scatter_highlight_kwargs = {'s': 150, 'label': 'Test data', 'alpha': 0.9}
scatter_kwargs = {'s': 120, 'edgecolor': None, 'alpha': 0.9}

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,
                      contourf_kwargs={'alpha':0.2}
                      )

5. 학습모델 사용(전체 data)

1) data 분리 및 학습

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)

2) 모델 적용

: 길가다가 주운 iris가 sepal과 petal의 length, width가 각각 [4.3, 2. , 1.2, 1.0] 일 때 품종 예측

  • 값 추가
test_data = np.array([[4.3, 2., 1.2, 1.]])
iris_tree.predict(test_data)
  • 예측
test_data = np.array([[4.3, 2., 1.2, 1.]])
iris_tree.predict(test_data)
-> array([1])
  • 품종별 확률
iris_tree.predict_proba(test_data)
-> array([[0.        , 0.97222222, 0.02777778]])
  • 품종 이름이 나타나게 코드 짜보기
iris.target_names[iris_tree.predict(test_data)]
-> array(['versicolor'], dtype='<U10')

3) 정보 확인

  • 각 컬럼별 영향력
iris_tree = DecisionTreeClassifier(max_depth=2, random_state=13)
iris_tree.fit(X_train, y_train)

iris_tree.feature_importances_
-> array([0.        , 0.        , 0.42189781, 0.57810219])
  • zip을 이용한 각 컬럼별 영향력 알아보기
dict(zip(iris.feature_names, iris_tree.feature_importances_))
-> {'sepal length (cm)': 0.0, 
		'sepal width (cm)': 0.0,
        'petal length (cm)': 0.421897810218978,
        'petal width (cm)': 0.578102189781022}
        

6. ZIP

간단한 zip과 언패킹
1. 리스트를 튜플로 zip

list1 = ['a', 'b', 'c']
list2 = [1, 2, 3]
pairs = [pair for pair in zip(list1, list2)]
pairs
-> [('a', 1), ('b', 2), ('c', 3)]
  1. 튜플을 dict로
dict(pairs)
-> {'a': 1, 'b': 2, 'c': 3}
  1. 한번에!
dict(zip(list1, list2))
-> {'a': 1, 'b': 2, 'c': 3}
  1. unpacking 인자를 이용한 역변환
a, b = zip(*pairs)

print(list(a))
print(list(b))
-> ['a', 'b', 'c']
   [1, 2, 3]
profile
안녕하세요

0개의 댓글