생각하는 감쟈

[Python] 4-4) 머신러닝 - 그래디언트,커널 본문

Language/Python

[Python] 4-4) 머신러닝 - 그래디언트,커널

생각하는 감쟈🥔 2023. 6. 10. 20:38

 

 
 

 

 

✔4DAY

그래디언트 부스팅 회귀 트리

커널 서서포트 벡터 머신

커널기법

출처 입력


그래디언트 부스팅 회귀 트리

  • 여러 개의 결정트리를 묶어 강력한 모델을 만드는 앙상블 기법 중 하나
  • 이름은 회귀히지만 회귀와 분류에 모두 사용 가능
  • 랜덤포레스트와 달라 이전 트리의 오차를 보완하는 방식
    • 순차적으로 트리 생성
    • 무작이성이 없음
  • 강력한 사전 가지치기를 하용하는 방식
    • 보통 하나에서 다섯 정도의 깊지 않은 트리 사용
    • 빠른 예측과 적은 메모리 사용량

 

높은 정확도의 그래디언트 부스팅 트리

  • 머신러닝 경연 대회 다수 우승
    • 업계에서도 널리 사용
    • 매개변수 설정에 따라 높은 정확도 제공
      • 랜덤 폴스트 보다 매개변수 설정에 조금 더 민감한 편
  • 중요한 매개 변수
    • 앙상블 방식의 사전 가지치기, 트리 개수
    • 이전트리의 오차 보정치 제어값
      • learning_rate : 학습률
      • 학습률이 크면 트리를 강하게 보정하여 복잡한 모델 생성
    • 앙상블에 추가할 트래 갯수
      • n_estimeators : 트리 개수
      • 값을 높이면 앙상블에 트리가 더 많이 추가
        • 모델의 복잡도 증가
        • 훈현 세트에서 실수를 바로 잡을 기회 증가
from sklearn.ensemble import GradientBoostingClassifier
X_train, X_test, y_train, y_test = train_test_split(
 cancer.data, cancer.target, random_state=0)
gbrt = GradientBoostingClassifier(random_state=0)
gbrt.fit(X_train, y_train)
print("훈련 세트 정확도: {:.3f}".format(gbrt.score(X_train, y_train)))
print("테스트 세트 정확도: {:.3f}".format(gbrt.score(X_test, y_test)))
 
훈련 세트 정확도: 1.000
테스트 세트 정확도: 0.958
 
gbrt = GradientBoostingClassifier(random_state=0, max_depth=1)
gbrt.fit(X_train, y_train)
print("훈련 세트 정확도: {:.3f}".format(gbrt.score(X_train, y_train)))
print("테스트 세트 정확도: {:.3f}".format(gbrt.score(X_test, y_test)))
훈련 세트 정확도: 0.991
테스트 세트 정확도: 0.972
 
gbrt = GradientBoostingClassifier(random_state=0, learning_rate=0.01)
gbrt.fit(X_train, y_train)
print("훈련 세트 정확도: {:.3f}".format(gbrt.score(X_train, y_train)))
print("테스트 세트 정확도: {:.3f}".format(gbrt.score(X_test, y_test)))
훈련 세트 정확도: 0.988
테스트 세트 정확도: 0.965
 
gbrt = GradientBoostingClassifier(random_state=0, max_depth=1)
gbrt.fit(X_train, y_train)
plot_feature_importances_cancer(gbrt
 

 

대규모 머신러닝 문제

  • 대규모 머신러닝 문제 해결 시 발생되는 성능 문제
    • 그래디언트 부스팅을 적용하는 것이 유리
  • xgboost 패키지와 파이썬 인터페이스 사용하는 것이 좋음
    • scikit-learn의 그래디언트 부스팅 보다 빠름
    • 튜닝하기도 편함

 

장점

  • 지도학습에서 가장 강력함
    • 가장 널리 사용하는 모델 중의 하나
  • 특성의 스케일 조정이 필요
    • 이진 특성이 연솓적인 특성에도 잘 동작

 

단점

  • 매개변수를 잘 조정해야 한다는 것
  • 긴 훈련 시간
  • 트리 기반 모델을 사용
    • 희소한 고차원 데이터에는 부적합

 

중요한 매개변수

  • n_estimators
    • 트리의 개수 지정
    • 너무 클 모델이 복잡해지고 과대적합 가능성
  • learning_rate
    • 이전 트리의 오차 보정 강도 조절(학습률)
  • 두 개의 매개변수는 깊이 연관선
    • learning_rate를 낮추면, 복잡도 유지를 위해 트리를 추가해야함

 

일반적인 관례

  • 가용한 시간과 메모리 한도에서 n_setimatores 부터 설정
  • 이후 적절한 learning_rate 설정

 


커널서포트벡터 머신

SVM

  • 입력데이터에서 단순한 초평면으로 정의되지 않는 더 복잡한 모델을 만들 수 있도록 확장한 지도 학습 모델
  • 분류와 회귀에 모두 사용 가능
  • SVR를 사용하는 회귀 문제에도 같은 개념을 적용 가능
  • 수학적으로 매우 복잡한 알고리즘

 

선형모델과 비선형 특성

  • 직선과 초평면의 유연하지 못한 문제
    • 저차원 데이터셋에서는 선형 모델이 매우 제한적
    • 선형 모델을 유연하게 만드는 방법
      • 특성끼리 곱하거나, 특성을 거듭제곱식으로 새로운 특성을 추가하는 방식

 

X, y = make_blobs(centers=4, random_state=8)
y = y % 2
mglearn.discrete_scatter(X[:, 0], X[:, 1], y)
plt.xlabel("특성 0")
plt.ylabel("특성 1")
 

 

분류를 위한 선형 모델의 한계

  • 직선으로만 데이터 포인트를 나누는 방식
from sklearn.svm import LinearSVC
linear_svm = LinearSVC().fit(X, y)
mglearn.plots.plot_2d_separator(linear_svm, X)
mglearn.discrete_scatter(X[:, 0], X[:, 1], y)
plt.xlabel("특성 0")
plt.ylabel("특성 1")
 

 

새로운 특성을 추가해 입력 특성 확장

  • 두번째 특성을 제곱(**) 하여 새로운 특성으로 추가
  • 2차원(특성0, 특성1) > 3차원(특성0,특성1,특성1**2)
X_new = np.hstack([X, X[:, 1:] ** 2]) 

from mpl_toolkits.mplot3d import Axes3D, axes3d
figure = plt.figure()
ax = Axes3D(figure, elev=-152, azim=-26)

mask = y == 0 
ax.scatter(X_new[mask, 0], X_new[mask, 1], X_new[mask, 2], c='b',
 cmap=mglearn.cm2, s=60, edgecolor='k')
ax.scatter(X_new[~mask, 0], X_new[~mask, 1], X_new[~mask, 2], c='r', 
marker='^', cmap=mglearn.cm2, s=60, edgecolor='k')
ax.set_xlabel("특성0")
ax.set_ylabel("특성1")
ax.set_zlabel("특성1 ** 2")
 

 

3차원 산점도 출력

  • 3차원으로 확장된 데이터셋
  • 선현 모델과 3차원 공간의 평면을 사용해 두 클래스를 구분 가능
linear_svm_3d = LinearSVC().fit(X_new, y)
coef, intercept = linear_svm_3d.coef_.ravel(), linear_svm_3d.intercept_

figure = plt.figure()
ax = Axes3D(figure, elev=-152, azim=-26)
xx = np.linspace(X_new[:, 0].min() - 2, X_new[:, 0].max() + 2, 50)
yy = np.linspace(X_new[:, 1].min() - 2, X_new[:, 1].max() + 2, 50)
XX, YY = np.meshgrid(xx, yy)
ZZ = (coef[0] * XX + coef[1] * YY + intercept) / -coef[2]
ax.plot_surface(XX, YY, ZZ, rstride=8, cstride=8, alpha=0.3)
ax.scatter(X_new[mask, 0], X_new[mask, 1], X_new[mask, 2], c='b',
 cmap=mglearn.cm2, s=60, edgecolor='k')
ax.scatter(X_new[~mask, 0], X_new[~mask, 1], X_new[~mask, 2], c='r', 
marker='^', cmap=mglearn.cm2, s=60, edgecolor='k')
ax.set_xlabel("특성0")
ax.set_ylabel("특성1")
ax.set_zlabel("특성1 ** 2")
 

 

원래 특성으로 투영해 보면 더 이상 선형이 아님

  • 직선 보다 타원에 가까운 모습의 모델
ZZ = YY ** 2
dec = linear_svm_3d.decision_function(np.c_[XX.ravel(), YY.ravel(), 
ZZ.ravel()])
plt.contourf(XX, YY, dec.reshape(XX.shape), levels=[dec.min(), 0, dec.max()],
 cmap=mglearn.cm2, alpha=0.5)
mglearn.discrete_scatter(X[:, 0], X[:, 1], y)
plt.xlabel("특성 0")
plt.ylabel("특성 1")
 

 


  • 데이터 셋에 비선형 특성을 추가하여 강력한 선형 모델 생성 가능
    • 어떤 특성을 추가해야할지 파악하기 어려운 문제
    • 특성을 지나치게 주가할 경우 연산 비용 증가 문제

 

커널기법

  • 수학 연산으로 새 특증을 만들지 않고 고차원에서 분류기를 학습 시키는 방법
  • 실제 데이터를 확장하지 않고 확장된 특성에 대한 데이터 포인트들의 거리 게산
    • 포인트들의 거리 : 스칼라 곱

 

서포트 백터 머신에서 데이터를 고차원 공안에 매핑 방법 2가지

  • 다항식 커널
    • 원래 특성의 가능한 조합을 지정된 차수까지 모두 계산하는 방법
  • RBF 커널
    • 가우시안 커널로도 가능
    • 차원이 무한한 특성 공간에 매핑하는 방법
      • 모든 차수의 모든 다항식을 고려하는 방식
    • 고차항이 될 수록 해당 특성의 중요도는 떨어짐

 

 

SVM 이해하기

  • SVM의 학습
    • 각 훈련 데이터 포인들의 중요도를 파악해 가는 과정
      • 두 클래스 사이의 결정 경계 생성 시 중요도

 

  • 서포트 벡터
    • 일반적으로 훈련데이터의 일부만 결정경계 생성에 영향
    • 두 클래스 사이의 경계에 위치한 데이터 포인트들
    • 서포트 벡터 머신아란 이름의 유래

 

  • 새로운 데이터 포안터에 대해 예측하기
    • 각 서포트 백터와의 거리를 측정
    • 분류 결정은 서포트 백터싸지의 거리에 기반
    • 서포트 백터의 중요도는 훈련 과정에서 학습
      • svc 객체의 dual_coef_ 속성에 저장

 

  • 데이터 포인트 사이의 거리
    • 사우시안 커널에 의해 계산
    • x1, x2 : 데이터 포인트
    • || x1 - x2 || : 유클리디안 거리
    • y ( 감마, gamma) : 가우시안 커널의 폭을 제어

 

 

forge 데이터셋에 svm을 학습시켜 그래프 그리기

  • 2개의 클래스를 가진 2차원 데이터셋에 서프터 백터 머신 학습 시키기
from sklearn.svm import SVC
X, y = mglearn.tools.make_handcrafted_dataset()
svm = SVC(kernel='rbf', C=10, gamma=0.1).fit(X, y) 
mglearn.plots.plot_2d_separator(svm, X, eps=.5)

mglearn.discrete_scatter(X[:, 0], X[:, 1], y)

sv = svm.support_vectors_

sv_labels = svm.dual_coef_.ravel() > 0
mglearn.discrete_scatter(sv[:, 0], sv[:, 1], sv_labels, s=15, 
markeredgewidth=3)
plt.xlabel("특성 0")
plt.ylabel("특성 1")
 

RBF 커널을 사용한 SVM으로 만든 결정경계와 서포트 벡터

  • 결정 경계는 검은 실선
  • 서포트 벡터는 굵은 테두리
  • SVM은 매우 부드러운 곡선 경계를 생성
    • 두 매개변수 (C, gamma) 사용

 

 

 

gamma 매개변수

  • 가우시안 커널 폭의 역수
  • 하나의 훈련 샘플이 미치는 영향의 범위 결정
    • 작은 값 : 넓은 영역
    • 큰 값 : 좁은 영역
  • 카우시안 커널의 반경이 클 수록 훈련 샘플의 영향 범위도 증가
  • 가우시안 커널의 반경이 클 수록 훈련 샘플의 영향 범위도 증가

 

C 매개변수

  • 선형 모델에서 사용한 것과 비슷한 규제 매개변수
  • 각 포인트의 중요도 (dual_coef_ 값)를 제한

 

 

 

매개변수 값을 변화시켜 보기

fig, axes = plt.subplots(3, 3, figsize=(15, 10))
for ax, C in zip(axes, [-1, 0, 3]):
 for a, gamma in zip(ax, range(-1, 2)):
 mglearn.plots.plot_svm(log_C=C, log_gamma=gamma, ax=a)
 
axes[0, 0].legend(["클래스 0", "클래스 1", "클래스 0 서포트 벡터", "클래스 1 서
포트 벡터"], ncol=4, loc=(.9, 1.2))
 

 

 

 

실험 결과 분석

왼쪽에서 오른쪽으로 가면서 gamma 값 증가

  • 작은 gamma값
    • 가우시안 컨널 반경을 증가 시켜 가까운 포인트 사용
    • 왼쪽 그림은 매우 부드럽고 오른쪽은 각 포인트에 민감해짐
    • 작은 gamma 값이 결정 경계를 부드럽게해 보델 복잡도를 낮춤
  • 큰 gamma 값
    • 더 복잡한 모델 생성

 

위에서 아래로 가면서 C값 증가

  • 작은 C값 (위쪽) : 높은 제약
    • 제약이 높은 모델 생성
    • 각 데이터 포인터의 영향력이 작아짐
    • 선형에 가까운 결정 경계 생성
    • 잘못 분류된 데이터 포인트가 경계에 거의 영향을 주지 않음
  • 큰 C값(아래쪽) : 낮은 제약
    • 포인트들이 모델에 큰 영향을 끼침
    • 결정 경계를 휘어서 정확하게 분류

 

 

유방암 데이터셋에 적용

 cancer.data, cancer.target, random_state=0)
svc = SVC()
svc.fit(X_train, y_train)
print("훈련 세트 정확도: {:.2f}".format(svc.score(X_train, y_train)))
print("테스트 세트 정확도: {:.2f}".format(svc.score(X_test, y_test)))
 
훈련 세트 정확도: 1.00
테스트 세트 정확도: 0.6
 

SVM은 잘 잘동하는 편이지만 매개변수 설정과 데이터 스케일이 매우 민감

  • 입력 특성의 범위가 비슷해야 함

 

각 특성의 최소값과 최대값을 로그스케일로 표시하기

plt.boxplot(X_train, manage_xticks=False)
plt.yscale("symlog")
plt.xlabel("특성 목록")
plt.ylabel("특성 크기")
 
TEXT(0,0.5,'특성크기')
 

자리수엣 큰 차이를 보이는 데이터 특성

  • Y축은 로그 스케일
  • 데이터 특성의 크기가 1000배가지 차이가 있어 커널 SVM에서는 문제 발생 가능

특성 값의 범위가 비슷해지도록 조정하기

  • 커널 SVM에서는모든 특성 값을 0과 1사이로 맞추는 방법 사용
  • MinMaxScaler 전처리 ㅂ메서드를 이용해 맞출수 있으나. 직접 구현해보기

 

 

 

 

 

 

 

커널 서포트 벡트 머신의 장단점

  • 강력한 모델이며, 다양힌 데이터셋에서 잘 작동
    • 데이터의 특성이 몇개 안되더라도 복잡한 결정 경계를 잘 만들 수 있음
    • 저차원과 고차원의 데이터(특성이 적을 떄와 많을 때)에 모두 잘 작동
  • 샘플이 많을 때에는 잘 맞지 않음
    • 10,000개의 샴플 정조에서 SVM 모델이 잘 작동
    • 100,000개 이상의 데이터셋에서는 속도와 메모리의 한계
  • 데이터 전처리와 매개변수 설정의 어려움
    • 일반적으로 전처리가 필요없는 트리 기반 모델을 주로 사용
  • 분석이 어려움
    • 예측이 어떨게 결정되었는지 이해하기 어려움
    • 비전문가에게 모델을 설명하기 난해함
  • 모든 특성이 비슷한 단위이고, 스케일이 비슷하면 SVM이 적합함

 

 


딥러닝과 신경망

 

딥러닝

  • 신경망이라고 알려진 알고리즘들은 최근 딥러닝이란 이름으로 주목
  • 많은 머신러닝 응용에서 매우 희망적인 성과
  • 특정 분야에 정교하게 적용되어 있는 경우가 많음

 

다층 퍼셉트론(MLP)

  • 복잡한 딥러닝 알고리즘의 출발점
  • 비교적 간단하게 분류와 회귀에 사용 가능
  • 피드포워드 신경망, 또는 그냥 신경망이라고 부름

 

MLP

  • 여러 단계를 거쳐 결정을 만들어내는 선형 모델의 일반화된 모습
  • 선형 회귀 모델의 예측 공식
사진 삭제

사진 설명을 입력하세요.

  • 선형 회귀 모델의 예측 공식을 그래프로 표시하기

 

로지스틱 회귀 그래프

  • 입력 특성과 예측은 노드로 표시
    • 왼쪽 노드는 입력 특성
    • 오른쪽 노드는 입력의 가중치를 합한 출력
  • 학습된 계수는 노드 사이의 연결로 표시

 

MLP

  • 가중치의 합을 만드는 과정이 여러번 반복
    • 먼전 중간 단계를 구성하는 은딕 유닛을 계산
    • 최종 결과를 산출하기 위해 다시 가중치의 합을 계산

 

MLP의 은닉층

  • MLP은 많은 계수를 학습해야 함
    • 계수는 각 입력고 은닉층의 은닉 유닛 사이, 각 은닉 유닛과 출력 사이마다 존재
    • 여러개의 가중치 합을 계산하는 것
      • 수학적으로 보면 하나의 가중치 합을 계싼하는 것과 동일
  • 선형 모델보다 걍력하게 만들기 위한 기법
    • 각 은닉 유닛의 가중치 합을 계산
    • 비선형 함수인 렐루나 하이퍼볼릭 탄젠트 적용
    • 이 함수 결과의 가중치 합을 계사나여 출려

 

비선형 함수를 이용해 훨씬 더 복잡한 함수 학습 가능

  • 렐루 함수는 0이하를 잘라버림
  • hanh함수는 낮은 입력값에 대해서는-1로 수렴, 큰 입력값은 +1로 수렴
line = np.linspace(-3, 3, 100)
plt.plot(line, np.tanh(line), label="tanh")
plt.plot(line, np.maximum(line, 0), linestyle='--', label="relu")
plt.legend(loc="best")
plt.xlabel("x")
plt.ylabel("relu(x), tanh(x)")
 
대표사진 삭제

사진 설명을 입력하세요.

은닉충 추가하기

  • 많은 은닉층으로 구성된 대규모 신경망이 생기면서 딥러닝이라고 부르게 됨
mglearn.plots.plot_two_hidden_layer_graph()
 

 


two_moons 데이터셋 활용

  • 분류를 위한 다층 퍼셉트론(MLP)구현인 MLPClassifier 적용하기
from sklearn.neural_network import MLPClassifier
from sklearn.datasets import make_moons
X, y = make_moons(n_samples=100, noise=0.25, random_state=3)
X_train, X_test, y_train, y_test = train_test_split(X, y, stratify=y,
 random_state=42)
mlp = MLPClassifier(solver='lbfgs', random_state=0).fit(X_train, y_train)
mglearn.plots.plot_2d_separator(mlp, X_train, fill=True, alpha=.3)
mglearn.discrete_scatter(X_train[:, 0], X_train[:, 1], y_train)
plt.xlabel("특성 0")
plt.ylabel("특성 1")
 

two_moons 데이터셋의 결정경계

  • 은닉 유닛이 100개인 신경망으로 학습
  • 매우 비선형적이지만,비교적 매끄러운 결정 경계 생성
  • solver 매개변수, 최적화 알고리즘 지정

 

MLP

  • 기본 값으로 은닉 유닛 100개 사용
    • 작은 데이터셋에는 너무 큰 크기
    • 은닉 유닛의 개수를 줄여도 좋은 결과를 얻을 수 있음
    • 은닉 유닛의 개수를 줄이면 복잡도가 낮아지는 효과
mlp = MLPClassifier(solver='lbfgs', random_state=0, 
hidden_layer_sizes=[10])
mlp.fit(X_train, y_train)
mglearn.plots.plot_2d_separator(mlp, X_train, fill=True, alpha=.3)
mglearn.discrete_scatter(X_train[:, 0], X_train[:, 1], y_train)
plt.xlabel("특성 0")
plt.ylabel("특성 1")
 

two_moons 데이터셋의 결정 경계

  • 은닛 유닛이 10개인 신경망으로 학습하여, 이전 보다 날카로워진 모습
  • 기본 비선형 함수는 ReLU 사용
  • 은닉충이 하나이므로. 결정 경계를 만드는 함수는 직선 10개가 합쳐져서 구성됨

 

 

 

 

 

Comments