728x90
[빅데이터 직무연구회] 2주차 모임 정리
모임 요일 : 4월 30일 일요일 저녁 6시
2.1 분류와 회귀
지도 학습에는 분류(Classification)와 회귀(Regression)가 있다.
1. 분류 : 미리 정의된, 가능성 있는 여러 클래스 레이블(class label) 중 하나를 예측하는 것
- 이진 분류 : 두 개의 클래스로 분류, 양성(positive) 클래스, 음성(negative) 클래스
- 다중 분류 : 셋 이상의 클래스로 분류
2. 회귀 : 연속적인 숫자, 또는 프로그래밍 용어로 말하면 부동소수점수(수학 용어로는 실수)를 예측하는 것, 예상 출력 값 사이에 연속성이 있음
2.2 일반화, 과대적합, 과소적합
- 일반화(Generalization) : 모델이 처음 보는 데이터에 대해 정확하게 예측할 수 있을 때, 훈련 세트에서 테스트 세트로 일반화 되었다고 함. 가능한 한 정확하게 일반화되도록 해야 함
- 과대적합(Overfitting) : 가진 정보를 모두 사용해서 너무 복잡한 모델을 만드는 것. 훈련 세트에 너무 가깝게 맞춰져서 새로운 데이터에 일반화되기 어려움
- 과소적합(Underfitting) : 너무 간단한 모델. 데이터의 면면과 다양성을 잡아내지 못하고 훈련 세트에도 잘 맞지 않을 것
=> 과대적합과 과소적합 모두 피해 일반화 성능이 최대가 되는 최적점을 찾아야 함
2.2.1 모델 복잡도와 데이터셋 크기의 관계
데이터를 더 많이 수집하고 적절하게 더 복잡한 모델을 만들면, 놀라운 결과를 얻을 수 있음.
2.3 지도 학습 알고리즘
2.3.1 예제에 사용할 데이터셋
- forge 데이터셋 : 이진 분류 데이터셋 (26개의 데이터포인트, 2개의 특성)
- wave 데이터셋 : 회귀 알고리즘 설명
- 위스콘신 유방암 데이터셋 : 유방암 종양의 임상 데이터를 기록해놓은 것 (569개의 데이터포인트, 30개의 특성)
- 보스턴 주택가격 데이터셋 : 범죄율, 찰스강 인접도, 고속도록 접근성 등의 정보를 이용해 1970년대 보스턴 주변의 주택 평균 가격을 예측하는 것 (506개의 데이터포인트, 13개의 특성)
2.3.2 k-최근접 이웃
k-NN (k-Nearest Neighbors) 알고리즘 : 가장 간단한 머신러닝 알고리즘. 새로운 데이터 포인트에 대해 예측할 때 알고리즘이 훈련 데이터셋에서 가장 가까운 데이터 포인트, 즉 '최근접 이웃'을 찾는다.
k-최근접 이웃 분류
- k가 1일 때 : 가장 가까운 훈련 데이터 포인트 하나를 최근접 이웃으로 찾아 예측
- k가 2이상일 때 : 가장 가까운 k개를 선택, 이웃이 더 많은 클래스를 레이블로 지정
KNeighborsClassifier 분석
- 이웃을 적게 사용 : 모델의 복잡도 증가 ( 결정 경계가 뾰족함 )
- 이웃을 많이 사용 : 모델의 복잡도 감소 ( 결정 경계가 부드러움 )
k-최근접 이웃 회귀
- k가 1일 때 : 가장 가까운 이웃의 타깃값
- k가 2이상일 때 : 이웃 간의 평균이 예측
결정 계수 R^2 : 회귀 모델에서 예측의 적합도를 0과 1 사이의 값으로 계산한 것
KNeighborsRegressor 분석
이웃을 많이 사용 : 훈련 데이터에는 잘 안 맞을 수 있음. 그러나 더 안정된 예측이 가능
장단점과 매개변수
< 매개변수 >
- 데이터 포인트 사이의 거리를 재는 방법 : 기본적으로 유클리디안 거리 방식 ( metric 매개변수의 기본값은 민코프스키 거리, 거듭제곱의 크기는 2 )
- 이웃의 수
< 장점 >
- 이해하기 매우 쉬운 모델
- 많이 조정하지 않아도 자주 좋은 성능 발휘
- 매우 빠르게 만들 수 있음
< 단점 >
- 훈련 세트가 매우 크면 예측이 느려짐
- 데이터 전처리 과정 중요
- 많은 특성을 가진 데이터 셋에는 잘 동작하지 않음
- 특성 값 대부분이 0인 (희소한) 데이터셋과는 특히 잘 작동되지 않음
: 예측이 느리고 많은 특성을 처리하는 능력이 부족해 현업에서 쓰지 않음
2.3.3 선형 모델
: 입력 특성에 대한 선형 함수를 만들어 예측. 특성이 많은 데이터셋에서 매우 훌륭한 성능을 냄
회귀의 선형 모델
: 선형 모델을 위한 일반화된 예측 함수
x[0]~x[p] : 하나의 데이터 포인트에 대한 특성 ( 특성의 개수 : p + 1 )
w와 b : 모델이 학습할 파라미터
y햇 : 모델이 만들어낸 예측값
Note. 하이퍼파라미터(hyperparameter) : 모델이 학습할 수 없어서 사람이 직접 설정해 주어야 하는 파라미터
- 특성이 하나일 때 : 직선
- 두개일 때 : 평면
- 더 높은 차원 : 초평면(hyperplane)
< 회귀를 위한 선형 모델들 차이 >
- 훈련 데이터로부터 모델 파라미터 w와 b를 학습하는 방법
- 모델의 복잡도를 제어하는 방법
선형 회귀(최소제곱법)
- 가장 간단하고 오래된 회귀용 선형 알고리즘.
- 예측과 훈련 세트에 있는 타깃 y 사이의 평균제곱오차(Mean Squared Error)를 최소화하는 파라미터 w와 b를 찾음
평균제곱오차(MSE) : 예측값과 타깃값의 차이를 제곱하여 더한 후, 샘플의 개수로 나눈 것
- 매개변수가 없음. => 모델의 복잡도를 제어할 방법이 없음
- w : 기울기 파라미터, 가중치(weight) 또는 계수(coefficient). LinearRegression() 객체의 coef_ 속성에 저장됨
- b : 편향(offset) 또는 절편(intercept). 객체의 intercept_ 속성에 저장됨
- 훈련 데이터에서 유도된 속성은 끝에 밑줄(_)을 붙임
- 훈련 세트와 테스트 세트의 점수가 비슷함 : 과소적합 상태
- 훈련 세트의 점수는 좋지만, 테스트 세트의 점수는 좋지 않음 : 과대적합 상태
=> 복잡도를 제어할 수 있는 모델을 사용해야 함.
릿지 회귀(Ridge)
: 복잡도를 제어해주는 추가 제약 조건이 추가됨. L2 규제 사용
규제(Regularization) : 가중치의 절댓값을 가능한 한 작게 만듦. w(기울기)의 모든 원소가 0에 가깝게 만들어 줌. 모든 특성이 출력에 주는 영향을 최소한으로 만듦.
L2 규제 : 평균제곱오차(MSE) 식에
항이 추가 됨.
- 𝛂를 크게 : 패널티의 효과가 커짐
- 𝛂를 작게 : 그 반대가 됨
- 모델의 복잡도가 낮아짐 : 훈련 세트에서의 성능은 낮아짐. 그러나 더 일반화된 모델이 됨
- alpha 매개변수로 릿지 회귀 객체 생성 시 설정 가능
< 선형 회귀와 릿지 회귀의 비교 >
- 훈련 데이터셋 크기가 400 미만 : 선형 회귀는 어떤 것도 학습하지 못함. 릿지 회귀는 학습함
- 훈련 데이터셋 크기가 400보다 커짐 : 데이터가 많아질 수록 규제 항은 덜 중요해져서, 두 모델의 성능이 같아짐.
- 데이터셋이 커질 수록 선형 회귀의 훈련 데이터 성능이 감소함. 이는 데이터가 많아질수록 모델이 데이터를 기억하거나 과대적합하기 어려워지기 때문
라쏘(Lasso)
: 릿지와 마찬가지로 𝛂를 설정함. 계수를 0에 가깝게 만들고자 함. L1 규제를 사용함. 모델을 이해하기 쉽고 중요한 특성이 무엇인지 파악하기 쉬움
L1 규제 : 어떤 계수들은 값이 0이 되어 완전히 제외되기도 함. 특성 선택(feature selection)이 자동으로 이뤄짐
< 릿지와 라쏘 둘 중 무엇을 선택해야 할까? >
- Ridge : 어떤 계수도 0이 되지 않음. 주로 선호
- Lasso : 특성이 많고 그 중 일부분만 중요하다면 더 좋은 선택일 수 있음. 분석하기 쉬운 모델임
- ElasticNet : scikit-learn에서 제공. L1 규제와 L2 규제 두 매개변수를 조정할 수 있음
< 규제 방법 >
- Alpha 매개변수 지원. 기본 값 1.0
- 과소적합 줄임 : Alpha 값을 줄임 ( max_iter, 반복 실행하느 최대 횟수, 의 기본값을 늘려야 함 )
- Alpha 값을 너무 맞추면 규제의 효과가 없어져 과대적합이 됨
라쏘는 계수 벡터의 L1 노름(Norm)을 패널티로 사용. 계수의 절댓값의 합
from IPython.display import display
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import mglearn
# 폰트 관련 자료
# https://programmers.co.kr/learn/courses/21/lessons/950
import matplotlib
matplotlib.rc("font", family="NanumGothicCoding")
In [2]:
# 데이터셋을 만듭니다.
X, y = mglearn.datasets.make_forge()
# 산점도를 그립니다.
mglearn.discrete_scatter(X[:, 0], X[:, 1], y)
plt.legend(["클래스 0", "클래스 1"], loc=4)
plt.xlabel("첫 번째 특성")
plt.ylabel("두 번째 특성")
print("X.shape: {}".format(X.shape))
In [3]:
X, y = mglearn.datasets.make_wave(n_samples=40)
plt.plot(X, y, 'o')
plt.ylim(-3, 3)
plt.xlabel("특성")
plt.ylabel("타깃")
Out[3]:
In [4]:
# 위스콘신 유방암 데이터
from sklearn.datasets import load_breast_cancer
cancer = load_breast_cancer()
print("cancer.keys(): \n{}".format(cancer.keys()))
In [5]:
print("유방암 데이터의 형태: {}".format(cancer.data.shape))
In [6]:
print("클래스별 샘플 개수:\n{}".format(
{n: v for n, v in zip(cancer.target_names, np.bincount(cancer.target))}
))
In [7]:
print("특성 이름:\n{}".format(cancer.feature_names))
In [8]:
# 보스턴 주택가격
from sklearn.datasets import load_boston
boston = load_boston()
print("데이터의 형태: {}".format(boston.data.shape))
In [9]:
X, y = mglearn.datasets.load_extended_boston()
print("X.shape: {}".format(X.shape))
In [10]:
mglearn.plots.plot_knn_classification(n_neighbors=1)
In [11]:
mglearn.plots.plot_knn_classification(n_neighbors=3)
In [12]:
from sklearn.model_selection import train_test_split
X, y = mglearn.datasets.make_forge()
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)
In [13]:
from sklearn.neighbors import KNeighborsClassifier
clf = KNeighborsClassifier(n_neighbors=3)
In [14]:
clf.fit(X_train, y_train)
Out[14]:
In [15]:
print("테스트 세트 예측: {}".format(clf.predict(X_test)))
In [16]:
print("테스트 세트 정확도: {:.2f}".format(clf.score(X_test, y_test)))
In [17]:
fig, axes = plt.subplots(1, 3, figsize=(10, 3))
for n_neighbors, ax in zip([1, 3, 9], axes):
# fit 메서드는 self 객체를 반환
# 그래서 객체 생성과 fit 메서드를 한 줄에 쓸 수 있음
clf = KNeighborsClassifier(n_neighbors=n_neighbors).fit(X, y)
mglearn.plots.plot_2d_separator(clf, X, fill=True, eps=0.5, ax=ax, alpha=.4)
mglearn.discrete_scatter(X[:, 0], X[:, 1], y, ax=ax)
ax.set_title("{} 이웃".format(n_neighbors))
ax.set_xlabel("특성 0")
ax.set_ylabel("특성 1")
axes[0].legend(loc=3)
Out[17]:
In [18]:
from sklearn.datasets import load_breast_cancer
cancer = load_breast_cancer()
X_train, X_test, y_train, y_test = train_test_split(cancer.data, cancer.target, stratify=cancer.target, random_state=66)
training_accuracy = []
test_accuracy = []
# 1에서 10까지 n_neighbors를 적용
neighbors_settings = range(1, 11)
for n_neighbors in neighbors_settings:
# 모델 생성
clf = KNeighborsClassifier(n_neighbors=n_neighbors)
clf.fit(X_train, y_train)
# 훈련 세트 정확도 저장
training_accuracy.append(clf.score(X_train, y_train))
# 일반화 정확도 저장
test_accuracy.append(clf.score(X_test, y_test))
plt.plot(neighbors_settings, training_accuracy, label="train accuracy")
plt.plot(neighbors_settings, test_accuracy, label="test accuracy")
plt.ylabel("accuracy")
plt.xlabel("n_neighbors")
plt.legend()
Out[18]:
In [19]:
# k-최근접 이웃 회귀
mglearn.plots.plot_knn_regression(n_neighbors=1)
In [20]:
mglearn.plots.plot_knn_regression(n_neighbors=3)
In [21]:
from sklearn.neighbors import KNeighborsRegressor
X, y = mglearn.datasets.make_wave(n_samples=40)
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)
reg = KNeighborsRegressor(n_neighbors=3)
reg.fit(X_train, y_train)
print("테스트 세트 예측:\n{}".format(reg.predict(X_test)))
print("테스트 세트 R^2: {:.2f}".format(reg.score(X_test, y_test)))
In [22]:
# KNeighborsRegressor 분석
fig, axes = plt.subplots(1, 3, figsize=(15, 4))
# -3과 3사이에 1,000개의 데이터 포인터를 만듦
line = np.linspace(-3, 3, 1000).reshape(-1, 1)
for n_neighbors, ax in zip([1, 3, 9], axes):
# 1, 3, 9 이웃을 사용한 예측
reg = KNeighborsRegressor(n_neighbors=n_neighbors)
reg.fit(X_train, y_train)
ax.plot(line, reg.predict(line))
ax.plot(X_train, y_train, '^', c=mglearn.cm2(0), markersize=8)
ax.plot(X_test, y_test, 'v', c=mglearn.cm2(1), markersize=8)
ax.set_title("{} 이웃의 훈련 스코어: {:.2f} 테스트 스코어: {:.2f}".format(n_neighbors, reg.score(X_train, y_train), reg.score(X_test, y_test)))
ax.set_xlabel("특성")
ax.set_ylabel("타깃")
axes[0].legend(["모델 예측", "훈련 데이터/타깃", "테스트 데이터/타깃"], loc="best")
# 절댓값, 맨하탄 등 다른 방법들이 있다.
Out[22]:
In [23]:
mglearn.plots.plot_linear_regression_wave()
In [24]:
from sklearn.linear_model import LinearRegression
X, y = mglearn.datasets.make_wave(n_samples=60)
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=42)
lr = LinearRegression().fit(X_train, y_train)
print("lr.coef_: {}".format(lr.coef_))
print("lr.intercept_: {}".format(lr.intercept_))
In [25]:
print("훈련 세트 점수: {:.2f}".format(lr.score(X_train, y_train)))
print("테스트 세트 점수: {:.2f}".format(lr.score(X_test, y_test)))
In [26]:
X, y = mglearn.datasets.load_extended_boston()
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)
lr = LinearRegression().fit(X_train, y_train)
In [27]:
print("훈련 세트 점수: {:.2f}".format(lr.score(X_train, y_train)))
print("테스트 세트 점수: {:.2f}".format(lr.score(X_test, y_test)))
In [28]:
from sklearn.linear_model import Ridge
ridge = Ridge().fit(X_train, y_train)
print("훈련 세트 점수: {:.2f}".format(ridge.score(X_train, y_train)))
print("테스트 세트 점수: {:.2f}".format(ridge.score(X_test, y_test)))
In [29]:
ridge10 = Ridge(alpha=10).fit(X_train, y_train)
print("훈련 세트 점수: {:.2f}".format(ridge10.score(X_train, y_train)))
print("테스트 세트 점수: {:.2f}".format(ridge10.score(X_test, y_test)))
In [30]:
ridge01 = Ridge(alpha=0.1).fit(X_train, y_train)
print("훈련 세트 점수: {:.2f}".format(ridge01.score(X_train, y_train)))
print("테스트 세트 점수: {:.2f}".format(ridge01.score(X_test, y_test)))
In [31]:
plt.plot(ridge10.coef_, '^', label="Ridge alpha=10")
plt.plot(ridge.coef_, 's', label="Ridge alpha=1")
plt.plot(ridge01.coef_, 'v', label="Ridge alpha=0.1")
plt.plot(lr.coef_, 'o', label="LinearRegression")
plt.xlabel("계수 목록")
plt.ylabel("계수 크기")
plt.hlines(0, 0, len(lr.coef_))
plt.ylim(-25, 25)
plt.legend()
Out[31]:
In [32]:
mglearn.plots.plot_ridge_n_samples()
In [33]:
from sklearn.linear_model import Lasso
lasso = Lasso().fit(X_train, y_train)
print("훈련 세트 점수: {:.2f}".format(lasso.score(X_train, y_train)))
print("테스트 세트 점수: {:.2f}".format(lasso.score(X_test, y_test)))
print("사용한 특성의 수: {}".format(np.sum(lasso.coef_ != 0)))
In [34]:
lasso001 = Lasso(alpha=0.01, max_iter=100000).fit(X_train, y_train)
print("훈련 세트 점수: {:.2f}".format(lasso001.score(X_train, y_train)))
print("테스트 세트 점수: {:.2f}".format(lasso001.score(X_test, y_test)))
print("사용한 특성의 수: {}".format(np.sum(lasso001.coef_ != 0)))
In [35]:
lasso00001 = Lasso(alpha=0.0001, max_iter=100000).fit(X_train, y_train)
print("훈련 세트 점수: {:.2f}".format(lasso00001.score(X_train, y_train)))
print("테스트 세트 점수: {:.2f}".format(lasso00001.score(X_test, y_test)))
print("사용한 특성의 수: {}".format(np.sum(lasso00001.coef_ != 0)))
In [36]:
plt.plot(lasso.coef_, 's', label="Lasso alpha=1")
plt.plot(lasso001.coef_, '^', label="Lasso alpha=0.01")
plt.plot(lasso00001.coef_, 'v', label="Lasso alpha=0.0001")
plt.plot(ridge01.coef_, 'o', label="Ridge alpha=0.1")
plt.legend(ncol=2, loc=(0, 1.05))
plt.ylim(-25, 25)
plt.xlabel("계수 목록")
plt.ylabel("계수 크기")
Out[36]:
'인공지능' 카테고리의 다른 글
[빅데이터 직무연구회] 5회차 모임 예제 소스 (1) (0) | 2018.05.19 |
---|---|
[빅데이터 직무연구회] 5회차 모임 정리 (0) | 2018.05.19 |
[빅데이터 직무연구회] 4회차 모임 정리 (0) | 2018.05.18 |
[빅데이터 직무연구회] 3주차 모임 정리 (0) | 2018.05.04 |
[빅데이터 직무연구회] 1주차 모임 정리 (0) | 2018.04.14 |
댓글