2018. 1. 6. 00:04ㆍML(머신러닝)/BASIC
SVM
입력 데이터에서 단순한 초평면으로 정의되지 않는 더 복잡한 모델을 만들 수 있도록 확장한 것입니다.
분류와 회귀 모두 사용
SVC SVR : 사용하는 회귀 문제에도 같은 개념을 적용 할 수 있다.
개념 설명 : 프리드먼 "THE ELEMENTS OF STATISTICAL LEARNING" 12장
선형 모델과 비선형 특성:
직선과 초평면 -> 유연하지 못함 -> 저차원 데이터셋에서는 매우 제한적
선형 모델 유연하게 하는 법 -> 특성끼리 곱하거나 특성을 거듭제곱하는 식으로 새로운 특성 추가
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")
# 두 번째 특성을 제곱하여 추가합니다 X_new = np.hstack([X, X[:, 1:] ** 2]) from mpl_toolkits.mplot3d import Axes3D, axes3d figure = plt.figure() # 3차원 그래프 ax = Axes3D(figure, elev=-152, azim=-26) # y == 0 인 포인트를 먼저 그리고 그 다음 y == 1 인 포인트를 그립니다 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")
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")
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")
커널 기법
앞에서는 데이터 셋에 비선형 특성 추가 -> 선형 모델 강력하게 -> 하지만 어떤 특성 추가 할지 모르고 많이 추가하면 -> cost 증가
그래서 -> 수학적 기교를 사용해 -> 새로운 특성 안만들고 고차원에서 분류기 학습 -> 커널기법
실제로 데이터를 학습하지 않고 확장된 특성에 대한 데이터 포인터들의 거리를 스칼라 곱을 계산한다.
두가지 많이 사용하는 방법
1. RBF : 원래 특성의 가능한 조합을 지정된 차수까지 모두 계산하는 (EX 특성1**2 X 특성2**5 ) 다항식 커널있고 가우시안 커널
-> 차원이 무한한 특성 공간에 매핑하는 것 모든 차수의 모든 다항식을 고려한다 -> 특성의 중요도는 고차항 될수록 줄어듬
SVM : 두 클래스 사이 결정 경계 구분하는 데 얼마나 중요한지를 알게 됨 일반적으로 훈련데이터 일부만 결정 경계 만드는 데 영향을 줌
일부 : 경계에 위치한 벡터들 == 서포트 벡터
(SVC 객체의 dual_coef_ 속성에 저장 되는 것)
새로운 데이터 포인트에 대해 예측 -> 각 서포터 벡터와의 거리 측정 -> 분류 결정은 서포트 벡터 거리 기반하며 중요도는 훈련 과정에서 학습
포인트 사이의 거리는 가우시안 커널에 의해 계산 됨
x1, x2 는 데이터 포인트 ||x1 - x2|| 유클리디안 r = 감마 (가우시안 커널의 폭을 제어하는 매개변수)
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_ # dual_coef_ 의 부호에 의해 서포트 벡터의 클래스 레이블이 결정됩니다 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")
매개변수 C 와 Gamma 알아보기
Gamma :
r 로 가우시안 커널 폭의 역수에 해당 -> 하나의 훈련 샘플이 미치는 영향의 범위를 결정한다.
작은 값은 넓은 영역을 뜻하며 큰 값이라면 영향을 미치는 범위가 제한적입니다 즉, 가우시안 커널의 반경이 클수록 훈련샘플의 영향 범위도 커집니다.
C
선형 모델에서 사용하는 것과 비슷한 매개변수 , 각 포인트의 중요도(dual_coef_값) 를 제한한다.
<비교그림>
왼쪽 -> 오른쪽 gamma 0.1 1 10
작은 감마 값은 가우시안 커널의 반경을 크게 하여 많은 포인터들이 가까이 있는 것으로 고려
그래서 왼쪽은 매우 부드럽고 오른쪽으로 갈수록 예민하게 반응
작은 감마 값이 결정 경계를 천천히 바뀌게 하므로 복잡도를 낮춘다 / 큰 감마는 복잡도를 높인다.
위-> 아래 c 0.1 1 1000
c는 매우 제약이 큰 모델을 만들고 각 데이터 포인터들의 영향력이 작다.
왼쪽 위는 거의 선형 잘못 분류된 것이 큰 영향을 주지 않는다.
c를 증가시키면 포인트들이 큰 영향을 주어서 정확하게 분류하게 도와준다.
SVM은 매개변수 설정과 데이터 스케일에 큰 영향을 받는다.
X_train, X_test, y_train, y_test = train_test_split(
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)))
plt.boxplot(X_train, manage_xticks=False)
plt.yscale("symlog")
plt.xlabel("특성 목록")
plt.ylabel("특성 크기")
자릿수가 전체적으로 달라서 데이터 스케일이 필요하다
SVM을 위한 데이터 전처리 방법
해결 방법 -> 특성 값의 범위를 비슷해지도록 조정하기 (주로 SVM 에서는 0 ~ 1 사이로 맞추기)
MinMaxScaler 전처리 메서드 사용해서 -> 처리함
그 다음에 C 와 GAMMA 를 조정해 성능 향상 할 수 있다.
장단점과 매개변수
다양한 데이터 셋에서 강력한 모델 -> 특성 몇 개 안되도 복잡한 결정 경계 만들 수 있다
특성이 적거나 많을 때 잘 되지만, 샘플이 많을 때는 부적합하다.
10.000 개 정도까지는 잘 되지만 100.000개 이상의 데이터에서는 무리무리
또하나의 단점은 데이터 전처리와 매개변수에 신경을 많이 써야 한다.
그래서 요즘은 랜덤포레스트나 그래디언트 부스팅 (전처리가 거의 필요치 않는 것을 많이 활용)
분석하기도 이해하기도 어렵다
하지만 모든 특성이 비슷한 단위이고 스케일이 비슷한 정도면 시도 가능성
C : 규제 매개변수 어떤 커널 사용하지와 각 커널에 따른 매개변수
RBF 외에도 다양한 커널 많음 (가우시안 커널 폭의 역수인 감마 변수 하나 있음)
신경망 모델
딥러닝으로 많이 주목 받고 있음 -> 특정 분야에 정교하게 적용 됨 -> 다층 퍼셉트론(MLP)
신경망 모델은 MLP를 통해서 선형 모델의 일반화된 모습
가중치의 합을 계산하는 것은 수학적으로 -> 하나의 가중치 합을 계산하는 것
그래서 그 결과에 비선형 함수 RELU 나 TANH 를 적용시킨다. ( 활성화 함수 부분)
그래서 마지막 출력층에는 시그모이드(이진 분류) 나 소프트맥스(다중 분류) 적용하여 출력합니다.
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, hidden_layer_sizes=[10], activation='tanh',alpha=alpha).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")
alpha -> L2 패널티 사용해서 가중치 0에 가깝게 만들수 있다.
은닉층의 수나 유닛 개수 지정해서 제어 할 수 있다.
다른 규제 방법으른 DROP_OUT이 있다 -> 일부 은닉층 유닛은 작동 시키지 않아 -> 마치 서로 다른 앙상블 신경망 같은 효과 과대적합방지
## 신경망도 데이터 전처리 하면 좋음
평균은 0 분산은 1이 되게 조정 -> StandardScalr
다른 라이브러리 많음
-> keras tensorflow
매개변수 조정하는 일반적인 방법
1. 과대적합할만큼 큰 모델 -> 신경망 구조를 줄이거나 / 규제 강화를 위해 alpha 증가 시키기
solver 매개변수 : 모델을 학습시크는 방법 또는 매개변수 학습에 사용하는 알고리즘 지정
'adam' : 일반적으로 잘 작동하지만 데이터 스케일에 민감(전처리 중요)
'ibfgs' : 안정적이지만 규모가 큰 모델에서는 오래 걸림
'sgd' : 다른 여러 매개 변수와 함께 튜닝하여 최선의 결과 사용 가능
분류 예측의 불확실성
분류기에 예측의 불확실성을 추정할 수 있는 기능
불확실성 추정 할 수 있는 함수 decision_function / predict_proba
# ex ) gradientboostingclassifier
from sklearn.ensemble import GradientBoostingClassifier from sklearn.datasets import make_circles X, y = make_circles(noise=0.25, factor=0.5, random_state=1) # 예제를 위해 클래스의 이름을 "blue" 와 "red" 로 바꿉니다 y_named = np.array(["blue", "red"])[y] # 여러개의 배열을 한꺼번에 train_test_split 에 넣을 수 있습니다 # 훈련 세트와 테스트 세트로 나뉘는 방식은 모두 같습니다. X_train, X_test, y_train_named, y_test_named, y_train, y_test = \ train_test_split(X, y_named, y, random_state=0) # 그래디언트 부스팅 모델을 만듭니다 gbrt = GradientBoostingClassifier(random_state=0)
gbrt.fit(X_train, y_train_named)
# 결정함수
이진분류에서 decision_function 반환값의 크기는 (n_samples, ) 각 샘플이 하나의 실수 값을 반환
print("X_test.shape: {}".format(X_test.shape))
print("결정 함수 결과 형태: {}".format(gbrt.decision_function(X_test).shape))
# 결정 함수 결과 중 앞부분 일부를 확인합니다
print("결정 함수:\n{}".format(gbrt.decision_function(X_test)[:6]))
print("임계치와 결정 함수 결과 비교:\n{}".format(
gbrt.decision_function(X_test) > 0))
print("예측:\n{}".format(gbrt.predict(X_test)))
# 불리언 값을 0과 1로 변환합니다
greater_zero = (gbrt.decision_function(X_test) > 0).astype(int)
# classes_에 인덱스로 사용합니다
pred = gbrt.classes_[greater_zero]
# pred 와 gbrt.predict의 결과를 비교합니다
print("pred 는 예측 결과와 같다: {}".format(
np.all(pred == gbrt.predict(X_test))))
decision_function = gbrt.decision_function(X_test)
print("결정 함수 최소값: {:.2f} 최대값: {:.2f}".format(
np.min(decision_function), np.max(decision_function)))
fig, axes = plt.subplots(1, 2, figsize=(13, 5))
mglearn.tools.plot_2d_separator(gbrt, X, ax=axes[0], alpha=.4,
fill=True, cm=mglearn.cm2)
scores_image = mglearn.tools.plot_2d_scores(gbrt, X, ax=axes[1],
alpha=.4, cm=mglearn.ReBl)
for ax in axes:
# 훈련 포인트와 테스트 포인트를 그리기
mglearn.discrete_scatter(X_test[:, 0], X_test[:, 1], y_test,
markers='^', ax=ax)
mglearn.discrete_scatter(X_train[:, 0], X_train[:, 1], y_train,
markers='o', ax=ax)
ax.set_xlabel("특성 0")
ax.set_ylabel("특성 1")
cbar = plt.colorbar(scores_image, ax=axes.tolist())
cbar.set_alpha(1)
cbar.draw_all()
axes[0].legend(["테스트 클래스 0", "테스트 클래스 1", "훈련 클래스 0",
"훈련 클래스 1"], ncol=4, loc=(.1, 1.1))
결정 경계(좌) 결정함수(우)
결정 함수 그래프에서는 두 클래스 사이 경계 구분이 어려움
print("확률 값의 형태: {}".format(gbrt.predict_proba(X_test).shape))
# predict_proba 결과 중 앞부분 일부를 확인합니다
print("Predicted probabilities:\n{}".format(
gbrt.predict_proba(X_test[:6])))
fig, axes = plt.subplots(1, 2, figsize=(13, 5))
mglearn.tools.plot_2d_separator(
gbrt, X, ax=axes[0], alpha=.4, fill=True, cm=mglearn.cm2)
scores_image = mglearn.tools.plot_2d_scores(
gbrt, X, ax=axes[1], alpha=.5, cm=mglearn.ReBl, function='predict_proba')
for ax in axes:
# 훈련 포인트와 테스트 포인트를 그리기
mglearn.discrete_scatter(X_test[:, 0], X_test[:, 1], y_test,
markers='^', ax=ax)
mglearn.discrete_scatter(X_train[:, 0], X_train[:, 1], y_train,
markers='o', ax=ax)
ax.set_xlabel("특성 0")
ax.set_ylabel("특성 1")
# colorbar 를 감추지 않습니다.
cbar = plt.colorbar(scores_image, ax=axes.tolist())
cbar.set_alpha(1)
cbar.draw_all()
axes[0].legend(["테스트 클래스 0", "테스트 클래스 1", "훈련 클래스 0",
"훈련 클래스 1"], ncol=4, loc=(.1, 1.1))
다중클래스도 이와 같이 합니다
(n_samples, n_classes)
'ML(머신러닝) > BASIC' 카테고리의 다른 글
비지도_전처리 스케일 조정 (0) | 2018.01.07 |
---|---|
지도 학습 알고리즘별 간단한 사용법 정리 (0) | 2018.01.06 |
지도학습_k-최근접 이웃 , 선형모델(로지스틱,svm) , 나이브 베이즈 분류기 (0) | 2018.01.03 |
문제와 데이터 이해하기 (0) | 2018.01.03 |
기계학습 (0) | 2018.01.02 |