#4. 얼렁뚱땅 주피터로 맛보기학습
1. Iris dataset 불러오기¶
#붓꽃iris 데이터세트 불러오기. scikit-learn의 dataset모듈에 포함되어 있다.
from sklearn.datasets import load_iris
iris_dataset = load_iris()
#load_iris가 반환하는 iris객체는 파이썬의 딕셔너리와 유사하다. Bunch 클래스 객체로, 키와 값으로 구성되어 있다.
print("iris_dataset의 키: \n{}".format(iris_dataset.keys())) #\n은 줄바꿈 역할을 한다.
iris_dataset의 키:
dict_keys(['data', 'target', 'frame', 'target_names', 'DESCR', 'feature_names', 'filename', 'data_module'])
#DESCR안에 있는 데이터셋에 대한 설명 일부 불러오기
print(iris_dataset['DESCR'][:193] + "\n...")
##target_names에 들어있는 꽃 품종 이름 불러오기
print("붓꽃 품종의 이름: {}".format(iris_dataset.target_names)) ##교재에는 iris_dataset['target_names']로 표현함
###feature_names안에 들어있는 특성 불러오기
print("붓꽃 특성의 이름: {}".format(iris_dataset.feature_names))
.. _iris_dataset:
Iris plants dataset
--------------------
**Data Set Characteristics:**
:Number of Instances: 150 (50 in each of three classes)
:Number of Attributes: 4 numeric, pre
...
붓꽃 품종의 이름: ['setosa' 'versicolor' 'virginica']
붓꽃 특성의 이름: ['sepal length (cm)', 'sepal width (cm)', 'petal length (cm)', 'petal width (cm)']
위와 같이 필드의 문자열 리스트를 불러올수 있지만, 실제 데이터는 target, data필드에 저장되어 있다.
data필드는 Numpy배열로, 배열의 행과 열은 각각 개별 꽃의 값 그리고 각각의 꽃의 속성(측정치)를 나타낸다.
#data의 타입 알아내기
print("data의 타입: {}".format(type(iris_dataset.data))) #필드의 내용이 아니라 형식을 알고싶으면 format다음에 type()으로 감싼다
##data의 크기 알아내기
print("data의 크기: {}".format(iris_dataset.data.shape)) ##교재에서는 format(iris_dataset['data'].shape)으로 표현됨
data의 타입: <class 'numpy.ndarray'>
data의 크기: (150, 4)
data를 살펴보니 150개의 꽃과 네 개의 꽃의 속성으로 구성되어 있는 것을 볼 수 있다.
각각의 꽃을 머신러닝에서는 '샘플'이라고 한다. 그리고 속성은 '특성'이라고 부른다.
data배열의 크기는 샘플과 특성의 크기를 곱한 것과 같다. scikit-learn스타일은 항상 데이터가 이러한 구조라고 가정한다.
#샘플 5개의 특성값 확인하기
print("data의 처음 다섯 행: \n{}".format(iris_dataset['data'][:5]))
data의 처음 다섯 행:
[[5.1 3.5 1.4 0.2]
[4.9 3. 1.4 0.2]
[4.7 3.2 1.3 0.2]
[4.6 3.1 1.5 0.2]
[5. 3.6 1.4 0.2]]
2. 데이터를 훈련 데이터와 시험 데이터(테스트 데이터, 홀드아웃 세트)로 나누기¶
scikit-learn에서는 데이터셋을 섞어서 분할하는 train_test_split함수를 사용할 수 있다.
기본적으로 75%를 레이블 데이터와 훈련 세트로 뽑고 나머지 25%를 레이블 데이터와 테스트 세트에 할당한다.
비율을 직접 지정하고 싶으면 test_size를 매개변수로 사용하면 된다.
scikit-learn에서는 데이터가 대문자X, 그리고 레이블이 소문자y로 표기된다.¶
데이터는 입력값의 입장이므로 함수의 표현을 따라 x의 모양이고, 2차원 배열(샘플과 특성)이므로 대문자로 표기한다.
레이블 데이터, 즉 타깃은 출력값에 해당하므로 함수의 표현을 따라 y의 모양이고, 1차원 배열(타깃값)을 가지므로 소문자로 표기한다.
from sklearn.datasets import load_iris
iris_dataset = load_iris()
#sklearn의 model_selection모듈에서 train_teat_split함수 호출하기
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(
iris_dataset['data'], iris_dataset['target'], random_state = 0)
## data 필드 안의 데이터를 훈련, 시험세트로 분할. target 필드의 타깃값을 훈련, 시험세트로 분할
## 유사 난수 생성기로 데이터셋을 섞어줘야한다. 난수 초깃값(random_state)를 0으로 설정해 매번 다른 때에 코드를 실행해도 동일한 값이 나오도록 함
## 난수 초깃값 0을 random_state 매개변수에 전달한 것
print("X_train의 크기: {}".format(X_train.shape))
print("y_train의 크기: {}".format(y_train.shape))
print("X_test의 크기: {}".format(X_test.shape))
print("y_test의 크기: {}".format(y_test.shape))
X_train의 크기: (112, 4)
y_train의 크기: (112,)
X_test의 크기: (38, 4)
y_test의 크기: (38,)
#X_train 데이터로 데이터프레임 만들기
import pandas as pd
iris_dataframe = pd.DataFrame(X_train, columns = iris_dataset.feature_names)
#생성한 데이터프레임을 사용해서 y_train에 따라 산점도 행렬 만들기
import mglearn
pd.plotting.scatter_matrix(iris_dataframe, c = y_train, figsize = (10, 10), marker = 'o',
hist_kwds = {'bins': 20}, s = 60, alpha = .8, cmap = mglearn.cm3)
array([[<AxesSubplot:xlabel='sepal length (cm)', ylabel='sepal length (cm)'>,
<AxesSubplot:xlabel='sepal width (cm)', ylabel='sepal length (cm)'>,
<AxesSubplot:xlabel='petal length (cm)', ylabel='sepal length (cm)'>,
<AxesSubplot:xlabel='petal width (cm)', ylabel='sepal length (cm)'>],
[<AxesSubplot:xlabel='sepal length (cm)', ylabel='sepal width (cm)'>,
<AxesSubplot:xlabel='sepal width (cm)', ylabel='sepal width (cm)'>,
<AxesSubplot:xlabel='petal length (cm)', ylabel='sepal width (cm)'>,
<AxesSubplot:xlabel='petal width (cm)', ylabel='sepal width (cm)'>],
[<AxesSubplot:xlabel='sepal length (cm)', ylabel='petal length (cm)'>,
<AxesSubplot:xlabel='sepal width (cm)', ylabel='petal length (cm)'>,
<AxesSubplot:xlabel='petal length (cm)', ylabel='petal length (cm)'>,
<AxesSubplot:xlabel='petal width (cm)', ylabel='petal length (cm)'>],
[<AxesSubplot:xlabel='sepal length (cm)', ylabel='petal width (cm)'>,
<AxesSubplot:xlabel='sepal width (cm)', ylabel='petal width (cm)'>,
<AxesSubplot:xlabel='petal length (cm)', ylabel='petal width (cm)'>,
<AxesSubplot:xlabel='petal width (cm)', ylabel='petal width (cm)'>]],
dtype=object)
3. k-최근접 이웃 알고리즘¶
훈련 데이터를 모델링하여 만드는 알고리즘. 새로운 데이터에 대한 타겟값은 가장 가까운 훈련 데이터 포인트의 레이블로 예측한다. k는 이웃의 개수를 의미한다. 예측의 대상이 되는 새로운 데이터의 k개의 이웃을 찾는다는 것이다. k개의 이웃을 찾은 후에는 가장 빈도가 높은 계층을 예측값으로 사용한다. 유사도는 기업 활동에 있어 도움이 된다. 예를 들어, A고객과 B고객이 유사하다는 사실을 알면 A고객이 구입한 제품C를 B고객에도 소개하는 광고를 낼 수 있다.
특징 벡터(속성)의 값으로 표현된 공간(2차원 좌표평면)에서 상대적으로 거리가 가까운 객체들은 서로 비슷하다고 여겨진다. 비슷하다고 판단하기 위해서는 공간을 일정한 기준에 따라 나눠야 한다. 동일한 영역 내에 있는 객체들이어야 서로 유사하다고 판단할 수 있기 때문이다. 공간을 나누는 방법에 따라 유사도를 판단하기 위한 영역은 달라지고, 결과 또한 변화한다.
(1) k-최근접 이웃 분류 알고리즘은 neighbor모듈 아래 KNeighborsClassifier 클래스에 구현되어 있다. - 이게 뭔소린가?¶
모듈이란?¶
파이썬에서 모듈이란 파이썬 파일(.py)과 같다. 모듈은 import명령어를 통해 사용할 수 있다. 모듈A를 import하면 코딩하고 있는 페이지에 모듈 안의 함수가 옮겨온다고 생각하면 된다. 모듈에 저장된 함수를 사용하려면 함수나 변수 앞에 온점과 함께 적어주면 된다.(모듈이 animals라고 하면 모듈을 사용하는 변수A를 animals.A라고 표현)
모듈에 있는 일부 함수만 사용하고 싶을 때는 from module import function의 구조로 사용하면 표현해주면 된다. (from animals import functionA)
클래스란?¶
틀과 같은 존재. 클래스라는 도구를 사용해서 객체를 알 수 있다. 클래스는 속성(데이터)과 메서드(동작)으로 구성된다. 클래스에서 정의된 데이터를 멤버 필드, 동작을 멤버 메서드라고 한다. 예를 들어 학생이라는 클래스에는 학교명, 성별, 학년 등의 속성이 있고 동작으로는 공부하기 운동하기 동이라활동참여 등이 있을 것이다.
따라서 k-최근접 이웃 분류 알고리즘은 neighbor이라는 이름의 파이썬 파일 안에 있는 KNeighborsClassifier함수를 사용하는 것과 같다. 우리는 불러온 클래스를 구성하는 객체를 만들어야 한다. 이때 필요한 매개변수가 있는데, 바로 이웃의 개수이다. 살펴볼 예제에서 지정된 최근접 이웃의 개수는 1이다.
from sklearn.neighbors import KNeighborsClassifier
knn = KNeighborsClassifier(n_neighbors = 1)
(2) knn 객체는 최근접 분류 알고리즘을 캡슐화한 것이다.¶
캡슐화란?¶
캡슐화는 두 가지 역할이 있다. 첫째, 클래스 안의 속성(멤버)과 메서드(동작)를 하나의 형식으로 묶어 표현한다. 속성과 메서드를 묶어 클래스를 만드는 것을 캡슐화 한다 하고 하는 것이다. 두번째, 구현된 객체의 내용 일부에 외부요소가 접근하지 못하게 한다. 변수 또는 메서드(동작)앞에 두 개를 붙이면 외부에서 접근할 수 없다. 특수 메서드는 변수와 동작 앞뒤에 를 2개 붙이는 것을 의미하는데, 이때는 외부에서 접근할 수 있다. 다만 이 방법은 바뀐 이름으로는 접근 가능하므로 완벽한 캡슐화라고는 할 수 없다. 이와 유사하게 변수 앞에 _ 를 하나 붙일 떄가 있는데, 이는 속성을 private한 것으로 간주한다.
외부에서 객체에 직접 접근할 수 없게 되었으니, 객체와 속성을 하나로 묶어서 함수로 접근한다.
훈련 데이터셋으로부터 모델을 만들려면 knn객체의 fit메서드를 사용한다. fit메서드는 훈련 데이터인 X_train과 훈련 데이터의 레이블을 포함한 y_train을 매개변수로 받는다.
-> knn과 관련된 내용 이해가 더 필요하다.(객체의 속성과 동작을 하나로 묶는 캡슐화 내용. 여기서 knn은 여러 메서드를 가지고 있다. 이것의 의미는?)
knn.fit(X_train, y_train)
KNeighborsClassifier(n_neighbors=1)
4. 예측하기¶
특성값을 아는 붓꽃의 레이블(타깃값, 즉 품종)을 예측해보자! 우선 붓꽃의 정보를 샘플과 특성으로 이루어진 Numpy배열로 만들어야 한다.
import numpy as np
X_new = np.array([[5, 2.9, 1, 0.2]])
print("X_new.shape: {}".format(X_new.shape))
#scikit-learn은 데이터가 항상 2차원 배열일 것이라고 가정한다.
X_new.shape: (1, 4)
#knn객체의 predict메서드 사용해서 예측하기
prediction = knn.predict(X_new)
print("예측: {}".format(prediction))
print("예측한 타깃의 이름: {}".format(
iris_dataset['target_names'][prediction]))
예측: [0]
예측한 타깃의 이름: ['setosa']
5. 모델 평가하기¶
레이블을 모르는 데이터의 레이블(타깃값)을 추정해보았다. 이 결과는 신뢰할 수 있는가? 결과를 신뢰할 수 있도록 우리는 훈련 데이터로 만든 모델을 시험 데이터를 활용해서 평가해야 한다. 테스트 데이터 안의 샘플들의 레이블을 예측하고 테스트 데이터 안에는 실제 품종 정보가 포함되어있으니 예측값과 비교해볼 수 있다. 이렇게 정확도를 계산해 모델의 성능을 평가해야 한다.
y_pred =knn.predict(X_test)
print("테스트 세트에 대한 예측값: {}".format(y_pred))
print("테스트 세트에 대한 정확도: {:.2f}".format(np.mean(y_pred == y_test)))
테스트 세트에 대한 예측값: [2 1 0 2 0 2 0 1 1 1 2 1 1 1 1 0 1 1 0 0 2 1 0 0 2 0 0 1 1 0 2 1 0 2 2 1 0
2]
테스트 세트에 대한 정확도: 0.97
6. 보충하기¶
- 분류 알고리즘을 만들기 위해 이미 분류가 완료된 데이터를 사용했으므로 지도 학습에 해당한다.
- 아이리스 문제에서 품종은 '클래스'에 해당하고, 개별 품종에 대한 정보를 '레이블'이라고 한다.
- 붓꽃 데이터셋은 데이터(입력값)를 담은 X와 레이블(출력값)을 담은 y 두 개의 NumPy배열로 이루어져 있다.
- 이번 분류 문제를 해결하기 위해 KNeighborsClassifier 클래스에 구현된 알고리즘을 사용했다.
- 그리고 매개변수 n_neighbors를 포함해 객체 knn으로 캡슐화했다. (아직까진 어떤 의미인지 애매하게 받아들여짐. 클래스 안에 객체를 생성한 것? 클래스 안에 클래스를 만든 것?)
'배우는 것 > Maching Learning' 카테고리의 다른 글
#6. 파이썬 기본지식 공부(1) (0) | 2021.12.21 |
---|---|
#5. 지도학습에서의 과적합화 (0) | 2021.12.20 |
#3. 분류 트리, 트리 구조 모델, 분할정복법, 논리문 (0) | 2021.12.19 |
#2. 감독 학습, 정보를 전달하는 속성, 엔트로피, 정보증가량(IG) (0) | 2021.12.17 |
#1. CRISP데이터 마이닝 프로세스, 사용 시나리오, 누설 (0) | 2021.12.17 |