2.3.7 커널 서포트 벡터 머신 | 목차 | 2.4 분류 예측의 불확실성 추정
–
신경망이라 알려진 알고리즘들은 최근 ‘딥러닝deep learning’이란 이름으로 다시 주목받고 있습니다. 딥러닝이 많은 머신러닝 애플리케이션에서 매우 희망적인 성과를 보여주고 있지만, 특정 분야에 정교하게 적용되어 있을 때가 많습니다. 여기서는 복잡한 딥러닝 알고리즘의 출발점이며 비교적 간단하게 분류와 회귀에 쓸 수 있는 다층 퍼셉트론multilayer perceptrons, MLP을 다루겠습니다. 다층 퍼셉트론은 (기본) 피드포워드feed-forward 신경망, 또는 종종 그냥 신경망이라고도 합니다. 1
신경망 모델
MLP는 여러 단계를 거쳐 결정을 만들어내는 선형 모델의 일반화된 모습이라고 볼 수 있습니다.
선형 회귀 모델의 예측 공식은 다음과 같았습니다.
ŷ = w[0] * x[0] + w[1] * x[1] + … + w[p] * x[p] = b
글로 설명하면 ŷ은 x[0]에서 x[p]까지의 입력 특성과 w[0]에서 w[p]까지 학습된 계수의 가중치 합입니다. 이를 [그림 2-44]로 나타냈습니다. 2
In[90]:
display(mglearn.plots.plot_logistic_regression_graph())
그림 2-44 입력 특성과 예측은 노드node로, 계수는 노드 사이의 연결로 나타낸 로지스틱 회귀
왼쪽 노드는 입력 특성을 나타내며 연결선은 학습된 계수를 표현하고 오른쪽 노드는 입력의 가중치 합, 즉 출력을 나타냅니다.
MLP에서는 가중치 합을 만드는 과정이 여러 번 반복되며, 먼저 중간 단계를 구성하는 은닉 유닛hidden unit을 계산하고 이를 이용하여 최종 결과를 산출하기 위해 다시 가중치 합을 계산합니다(그림 2-45).
In[91]:
display(mglearn.plots.plot_single_hidden_layer_graph())
그림 2-45 은닉층이 하나인 다층 퍼셉트론
이런 모델은 많은 계수(또는 가중치)를 학습해야 합니다. 이 계수는 각 입력과 은닉층hidden layer의 은닉 유닛 사이, 그리고 각 은닉 유닛과 출력 사이마다 있습니다.
여러 개의 가중치 합을 계산하는 것은 수학적으로 보면 하나의 가중치 합을 계산하는 것과 같습니다. 3 그래서 이 모델을 선형 모델보다 강력하게 만들려면 또다른 기교가 필요합니다. 각 은닉 유닛의 가중치 합을 계산한 후 그 결과에 비선형 함수인 렐루rectified linear unit, ReLU나 하이퍼볼릭 탄젠트hyperbolic tangent, tanh를 적용합니다. 4 이 함수 결과의 가중치 합을 계산하여 출력 ŷ을 만듭니다. 두 함수를 [그림 2-46]에 나타냈습니다. 렐루 함수는 0 이하를 잘라버리고, tanh 함수는 낮은 입력값에 대해서는 -1로 수렴하고 큰 입력값에 대해서는 +1로 수렴합니다. 이런 비선형 함수를 이용해 신경망이 선형 모델에서보다 훨씬 더 복잡한 함수를 학습할 수 있습니다.
In[92]:
line = np.linspace(-3, 3, 100) plt.plot(line, np.tanh(line), label="tanh") plt.plot(line, np.maximum(line, 0), label="relu") plt.legend(loc="best") plt.xlabel("x") plt.ylabel("relu(x), tanh(x)")
그림 2-46 하이퍼볼릭 탄젠트 활성화 함수와 렐루 활성화 함수
[그림 2-45]의 작은 신경망으로 (tanh 비선형 함수를 사용해서) 회귀 분석을 할 때 ŷ을 계산하기 위한 전체 공식은 다음과 같습니다. 5
h[0] = tanh(w[0, 0] × x[0] + w[1, 0] × x[1] + w[2, 0] × x[2] + w[3, 0] × x[3] + b[0])
h[1] = tanh(w[0, 1] × x[0] + w[1, 1] × x[1] + w[2, 1] × x[2] + w[3, 1] × x[3] + b[1])
h[2] = tanh(w[0, 2] × x[0] + w[1, 2] × x[1] + w[2, 2] × x[2] + w[3, 2] × x[3] + b[2])
ŷ = v[0] × h[0] + v[1] × h[1] + v[2] × h[2] + b
w는 입력 x와 은닉층 h 사이의 가중치이고, v는 은닉층 h와 출력 ŷ 사이의 가중치입니다. 가중치 v와 w는 훈련 데이터에서 학습하고, x는 입력 특성이며, ŷ은 계산된 출력, h는 중간 계산 값입니다. 우리가 정해야 하는 중요한 매개변수는 은닉층의 유닛 개수입니다. 소규모 데이터셋일 경우 10개 정도도 괜찮지만 매우 복잡한 데이터셋에서는 10,000개가 될 수도 있습니다. 또한 [그림 2-47]처럼 은닉층을 추가할 수도 있습니다.
In[93]:
mglearn.plots.plot_two_hidden_layer_graph()
그림 2-47 은닉층이 두 개인 다층 퍼셉트론
이와 같이 많은 은닉층으로 구성된 대규모의 신경망이 생기면서 이를 딥러닝이라고 부르게 되었습니다.
신경망 튜닝
앞서 본 two_moons 데이터셋에 분류를 위한 다층 퍼셉트론(MLP) 구현인 MLPClassifier를 적용해보겠습니다. 결과는 [그림 2-48]에 나타냈습니다.
In[94]:
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")
그림 2-48 은닉 유닛이 100개인 신경망으로 학습시킨 two_moons 데이터셋의 결정 경계
그림에서 보듯 이 신경망은 매우 비선형적이지만 비교적 매끄러운 결정 경계를 만들었습니다. 여기서 사용한 최적화 알고리즘은 solver=’lbfgs’로 잠시 후에 설명하겠습니다.
MLP는 기본값으로 은닉 유닛 100개를 사용하는데 이런 작은 데이터셋에는 과분한 크기입니다. 은닉 유닛의 개수를 줄여도 (모델의 복잡도는 낮아지고) 여전히 좋은 결과를 얻을 수 있습니다(그림 2-49).
In[95]:
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")
그림 2-49 은닉 유닛이 10개인 신경망으로 학습시킨 two_moons 데이터셋의 결정 경계
은닉 유닛이 10개여서 결정 경계가 조금 더 날카로워졌습니다. 기본 비선형 함수는 [그림 2-46]에 나와 있는 렐루입니다. 은닉층이 하나이므로 결정 경계를 만드는 함수는 직선 10개가 합쳐져서 구성됩니다. 더 매끄러운 결정 경계를 원한다면 은닉 유닛을 추가하거나(그림 2-48), 은닉층을 추가하거나(그림 2-50), 또는 tanh 함수를 사용할 수 있습니다(그림 2-51).
In[96]:
# 10개의 유닛으로 된 두 개의 은닉층 mlp = MLPClassifier(solver='lbfgs', random_state=0, hidden_layer_sizes=[10, 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")
그림 2-50 10개의 은닉 유닛을 가진 두 개의 은닉층과 렐루 활성화 함수로 만든 결정 경계
In[97]:
# tanh 활성화 함수가 적용된 10개의 유닛으로 된 두 개의 은닉층 mlp = MLPClassifier(solver='lbfgs', activation='tanh', random_state=0, hidden_layer_sizes=[10, 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")
그림 2-51 은닉 유닛이 10개인 두 은닉층과 tanh 활성화 함수로 만든 결정 경계
그리고 릿지 회귀와 선형 분류기에서 한 것처럼 L2 페널티를 사용해서 가중치를 0에 가깝게 감소시켜 모델의 복잡도를 제어할 수 있습니다. MLPClassifier에서 이런 역할을 하는 매개변수는 alpha(선형 회귀 모델과 같습니다)이고 기본값은 매우 낮게(거의 규제하지 않게) 되어 있습니다. 6 [그림 2-52]는 two_moons 데이터셋에 유닛이 각각 10개와 100개인 은닉층 2개를 사용했을 때 다른 alpha 값이 미치는 영향을 보여줍니다.
In[98]:
fig, axes = plt.subplots(2, 4, figsize=(20, 8)) for axx, n_hidden_nodes in zip(axes, [10, 100]): for ax, alpha in zip(axx, [0.0001, 0.01, 0.1, 1]): mlp = MLPClassifier(solver='lbfgs', random_state=0, hidden_layer_sizes=[n_hidden_nodes, n_hidden_nodes], alpha=alpha) mlp.fit(X_train, y_train) mglearn.plots.plot_2d_separator(mlp, X_train, fill=True, alpha=.3, ax=ax) mglearn.discrete_scatter(X_train[:, 0], X_train[:, 1], y_train, ax=ax) ax.set_title("n_hidden=[{}, {}]\nalpha={:.4f}".format( n_hidden_nodes, n_hidden_nodes, alpha))
그림 2-52 은닉 유닛과 alpha 매개변수에 따라 변하는 결정 경계
아마 느꼈겠지만 신경망의 복잡도를 제어하는 방법이 많이 있습니다. 은닉층의 수, 은닉층의 유닛 개수, 규제(alpha)를 사용할 수 있습니다. 사실 더 있지만 여기서 다루지는 않겠습니다. 7
신경망에서는 학습을 시작하기 전에 가중치를 무작위로 설정하며 이 무작위한 초기화가 모델의 학습에 영향을 줍니다. 따라서 같은 매개변수를 사용하더라도 초깃값이 다르면 모델이 많이 달라질 수 있습니다. 신경망이 크고 복잡도도 적절하면 이런 점이 정확도에 미치는 영향은 크지 않지만 항상 기억하고는 있어야 합니다(특히 작은 신경망일 경우엔). [그림 2-53]은 같은 매개변수를 가졌지만 초기화를 다르게 하여 만든 모델들입니다.
In[99]:
fig, axes = plt.subplots(2, 4, figsize=(20, 8)) for i, ax in enumerate(axes.ravel()): mlp = MLPClassifier(solver='lbfgs', random_state=i, hidden_layer_sizes=[100, 100]) mlp.fit(X_train, y_train) mglearn.plots.plot_2d_separator(mlp, X_train, fill=True, alpha=.3, ax=ax) mglearn.discrete_scatter(X_train[:, 0], X_train[:, 1], y_train, ax=ax)
그림 2-53 무작위로 다른 초깃값을 주되 같은 매개변수로 학습한 결정 경계
신경망을 더 잘 이해하기 위해 실제 데이터인 유방암 데이터셋에 MLPClassifier를 적용해보겠습니다. 매개변수는 기본값을 사용하겠습니다.
In[100]:
print("유방암 데이터의 특성별 최댓값:\n{}".format(cancer.data.max(axis=0)))
Out[100]:
유방암 데이터의 특성별 최댓값: [ 28.110 39.280 188.500 2501.000 0.163 0.345 0.427 0.201 0.304 0.097 2.873 4.885 21.980 542.200 0.031 0.135 0.396 0.053 0.079 0.030 36.040 49.540 251.200 4254.000 0.223 1.058 1.252 0.291 0.664 0.207]
In[101]:
X_train, X_test, y_train, y_test = train_test_split( cancer.data, cancer.target, random_state=0) mlp = MLPClassifier(random_state=42) mlp.fit(X_train, y_train) print("훈련 세트 정확도: {:.2f}".format(mlp.score(X_train, y_train))) print("테스트 세트 정확도: {:.2f}".format(mlp.score(X_test, y_test)))
Out[101]:
훈련 세트 정확도: 0.91 테스트 세트 정확도: 0.88
MLP의 정확도는 꽤 좋지만 다른 모델만큼은 아닙니다. 앞서 SVC 예제에서는 데이터의 스케일이 영향을 미쳤습니다. 이와 비슷하게 신경망도 모든 입력 특성을 평균은 0, 분산은 1이 되도록 변형하는 것이 좋습니다. 8 그럼 이 조건에 맞도록 데이터의 스케일을 맞춰보겠습니다. 3장에서 이를 자동으로 처리해주는 StandardScaler를 배우겠지만 여기서는 우리가 직접 해보도록 하겠습니다.
In[102]:
# 훈련 세트 각 특성의 평균을 계산합니다. mean_on_train = X_train.mean(axis=0) # 훈련 세트 각 특성의 표준 편차를 계산합니다. std_on_train = X_train.std(axis=0) # 데이터에서 평균을 빼고 표준 편차로 나누면 # 평균 0, 표준 편차 1인 데이터로 변환됩니다. X_train_scaled = (X_train - mean_on_train) / std_on_train # (훈련 데이터의 평균과 표준 편차를 이용해) 같은 변환을 테스트 세트에도 합니다. X_test_scaled = (X_test - mean_on_train) / std_on_train mlp = MLPClassifier(random_state=0) mlp.fit(X_train_scaled, y_train) print("훈련 세트 정확도: {:.3f}".format(mlp.score(X_train_scaled, y_train))) print("테스트 세트 정확도: {:.3f}".format(mlp.score(X_test_scaled, y_test)))
Out[102]:
훈련 세트 정확도: 0.991 테스트 세트 정확도: 0.965
ConvergenceWarning: Stochastic Optimizer: Maximum iterations reached and the optimization hasn't converged yet.
스케일을 조정하니 결과가 매우 좋아졌으며 다른 모델의 성능 못지 않습니다. 하지만 경고가 출력되었는데 최대 반복 횟수에 도달했다고 알려주고 있습니다. 이는 모델을 학습시키는 adam 알고리즘에 관련한 것으로 이 경고가 나오면 반복 횟수를 늘려야 합니다. 9
In[103]:
mlp = MLPClassifier(max_iter=1000, random_state=0) mlp.fit(X_train_scaled, y_train) print("훈련 세트 정확도: {:.3f}".format(mlp.score(X_train_scaled, y_train))) print("테스트 세트 정확도: {:.3f}".format(mlp.score(X_test_scaled, y_test)))
Out[103]:
훈련 세트 정확도: 0.993 테스트 세트 정확도: 0.972
반복 횟수를 늘려서 훈련 세트와 테스트 세트의 성능을 올렸습니다. 이 정도로도 모델의 성능은 매우 좋습니다. 하지만 훈련 세트와 테스트 세트 사이에는 성능 차이가 있으므로 일반화 성능을 더 올리기 위해 모델의 복잡도를 낮춰보겠습니다. 여기서는 가중치를 더 강하게 규제하도록 alpha 매개변수를 (0.0001에서 1로 아주 크게) 증가시켜 보겠습니다.
In[104]:
mlp = MLPClassifier(max_iter=1000, alpha=1, random_state=0) mlp.fit(X_train_scaled, y_train) print("훈련 세트 정확도: {:.3f}".format(mlp.score(X_train_scaled, y_train))) print("테스트 세트 정확도: {:.3f}".format(mlp.score(X_test_scaled, y_test)))
Out[104]:
훈련 세트 정확도: 0.988 테스트 세트 정확도: 0.972
이 결과는 지금까지 가장 좋은 모델의 성능과 동일합니다. 10
신경망이 어떻게 학습하는지 분석할 수 있지만 선형 모델이나 트리 모델보다는 훨씬 까다롭습니다. 모델의 가중치를 확인해보면 무엇이 학습됐는지 알아볼 수 있습니다. 이와 관련한 예를 scikit-learn 예제에서 볼 수 있습니다(http://scikit-learn.org/stable/auto_examples/neural_networks/plot_mnist_filters.html). 유방암 데이터셋 같은 경우는 조금 더 어렵습니다. [그림 2-54]는 입력과 은닉층 사이의 학습된 가중치를 보여줍니다. 이 그림의 행은 30개의 입력 특성에 해당하며 열은 100개의 은닉 유닛에 해당합니다. 밝은 색은 큰 양수 값을 나타내고 어두운 색은 음수 값을 나타냅니다. 11
In[106]:
plt.figure(figsize=(20, 5)) plt.imshow(mlp.coefs_[0], interpolation='none', cmap='viridis') plt.yticks(range(30), cancer.feature_names) plt.xlabel("은닉 유닛") plt.ylabel("입력 특성") plt.colorbar()
그림 2-54 유방암 데이터셋으로 학습시킨 신경망의 첫 번째 층의 가중치 히트맵heat map
모든 은닉 유닛에서 작은 가중치를 가진 특성은 모델에 덜 중요하다고 추론할 수 있습니다. “smoothness error”와 “fractal dimension error” 사이에 있는 특성과 “mean smoothness”와 “mean compactness”가 다른 특성들보다 가중치가 낮습니다. 12 이 특성들은 덜 중요하거나 신경망에게 적절하게 입력되지 않았을 수 있습니다.
은닉층과 출력층 사이의 가중치도 시각화할 수 있지만 해석하긴 더 어렵습니다.
MLPClassifier와 MLPRegressor는 일반적인 신경망 구조를 위한 손쉬운 인터페이스를 제공하지만 전체 신경망 종류의 일부만 만들 수 있습니다. 13 더 복잡하고 대규모인 모델을 만들려면 scikit-learn을 넘어서 전문적인 딥러닝 라이브러리들을 살펴보십시요. 파이썬 사용자에게는 keras, lasagna, tensorflow 등이 가장 널리 사용되고 있습니다. 14 lasagna는 theano 라이브러리 위에 구축한 것이고 keras는 tensorflow와 theano 중 선택할 수 있습니다. 이 라이브러리들은 신경망을 만드는 데 훨씬 유연한 인터페이스를 제공하고 있어 딥러닝 연구 분야에서 빠르게 성장하고 있습니다. 잘 알려진 딥러닝 라이브러리들은 모두 scikit-learn에서는 지원하지 않는 기능인 고성능 그래픽 처리장치GPU를 사용할 수 있습니다. GPU를 사용하면 10배에서 100배까지 빠르게 연산할 수 있어서 대규모 데이터셋을 사용한 딥러닝 분야에서 필수입니다.
장단점과 매개변수
신경망은 머신러닝 분야의 많은 애플리케이션에서 최고의 모델로 다시 떠오르고 있습니다. 주요한 장점은 대량의 데이터에 내재된 정보를 잡아내고 매우 복잡한 모델을 만들 수 있다는 점입니다. 충분한 연산 시간과 데이터를 주고 매개변수를 세심하게 조정하면 신경망은 (분류와 회귀 문제에 모두) 종종 다른 머신러닝 알고리즘을 뛰어넘는 성능을 냅니다.
이로 인해 단점도 생깁니다. 신경망은 (특히 크고 강력한 모델이라면) 종종 학습이 오래 걸립니다. 또한 앞서 보았듯이 데이터 전처리에 주의해야 합니다. SVM과 비슷하게 모든 특성이 같은 의미를 가진 동질의 데이터에서 잘 작동합니다. 다른 종류의 특성을 가진 데이터라면 트리 기반 모델이 더 잘 작동할 수 있습니다. 신경망 매개변수 튜닝은 예술에 가까운 일입니다. 우리 예에서는 신경망 모델을 조정하고 학습시키는 많은 방법 중 아주 일부만 살짝 보았을 뿐입니다.
신경망의 복잡도 추정
신경망에서 가장 중요한 매개변수는 은닉층의 개수와 각 은닉층의 유닛 수입니다. 처음엔 한 개 또는 두 개의 은닉층으로 시작해서 늘려가야 합니다. 각 은닉층의 유닛 수는 보통 입력 특성의 수와 비슷하게 설정하지만 수천 초중반을 넘는 일은 거의 없습니다.
신경망의 모델 복잡도에 관해 도움이 될만한 측정치는 학습된 가중치 또는 계수의 수입니다. 특성 100개와 은닉 유닛 100개를 가진 이진 분류라면 입력층과 첫 번째 은닉층 사이에는 편향을 포함하여 100 * 100 + 100 = 10,100개의 가중치가 있습니다. 그리고 은닉층과 출력층 사이에 100 * 1 + 1 = 101개의 가중치가 더 있어서 가중치는 총 10,201개입니다. 은닉 유닛이 100개인 두 번째 은닉층을 추가하면 첫 번째 은닉층에서 두 번째 은닉층으로 100 * 100 + 100 = 10,100개의 가중치가 늘어나서 전체 가중치의 수는 20,301개입니다. 만약 유닛이 1,000개인 은닉층 하나만 사용한다면 입력층에서 은닉층 사이에 100 * 1,000 + 1000 = 101,000개의 가중치를 학습해야 하고 은닉층에서 출력층 사이에 1,000 * 1 + 1 = 1,001개의 가중치를 학습해야 합니다. 총 102,001개의 가중치를 학습해야 합니다. 만약 두 번째 은닉층을 추가하면 가중치는 1,000 * 1,000 + 1000 = 1,001,000개가 추가되어 전체 가중치는 1,103,001개로 뛰어올라 유닛 100개짜리 은닉층 두 개였을 때보다 50배나 커집니다.
신경망의 매개변수를 조정하는 일반적인 방법은 먼저 충분히 과대적합되어서 문제를 해결할 만한 큰 모델을 만듭니다. 그런 다음 훈련 데이터가 충분히 학습될 수 있다고 생각될 때 신경망 구조를 줄이거나 규제 강화를 위해 alpha 값을 증가시켜 일반화 성능을 향상시킵니다.
우리 예제에서는 대부분 모델의 구성에 촛점을 맞췄습니다. 층의 개수, 층당 유닛 개수, 규제, 비선형성 15 입니다. 이 요소들을 사용해 우리가 원하는 모델을 정의합니다. 또 solver 매개변수를 사용해 모델을 학습시키는 방법 또는 매개변수 학습에 사용하는 알고리즘을 지정할 수 있습니다. solver 매개변수에는 쉽게 사용할 수 있는 옵션이 두 가지 있습니다. 기본값은 ‘adam’으로 대부분의 경우에 잘 작동하지만 데이터의 스케일에 조금 민감합니다(그래서 데이터를 평균 0, 분산 1로 조정하는 게 중요합니다). 다른 하나는 ‘lbfgs’로 안정적이지만 규모가 큰 모델이나 대량의 데이터셋에서는 시간이 오래 걸립니다. 16 또 많은 딥러닝 연구자가 사용하는 고급 옵션인 ‘sgd’가 있습니다. ‘sgd’ 옵션은 다른 여러 매개변수와 함께 튜닝하여 최선의 결과를 만들 수 있습니다. 17 사용자 가이드에서 이런 매개변수들과 정의를 찾을 수 있습니다. MLP를 처음 사용할 때는 ‘adam’과 ‘lbfgs’를 추천합니다.18
노트_ fit 메서드는 모델을 다시 만듭니다. scikit-learn 모델의 중요한 특징 하나는 fit 메서드를 호출하면 이전에 학습한 것을 모두 초기화하는 점입니다. 그래서 어떤 데이터셋으로 모델을 만들고 나서 다른 데이터셋을 사용해 fit 메서드를 호출하면 첫 번째 데이터셋에서 학습한 것을 모두 잃어버립니다. 한 모델에서 원하는 만큼 fit 메서드를 호출할 수 있으며 그 결과는 새로운 모델 객체에서 fit 메서드를 호출하는 것과 같습니다. 19
–
–
- 옮긴이_ 또는 입력, 출력, 은닉층의 유닛들이 모두 연결되어 있다고 해서 완전 연결 신경망fully connected neural networks이라고도 합니다.
- 옮긴이_ 신경망에서는 종종 편향 값 b를 그림에 나타내지 않곤 합니다. 다층 퍼셉트론 혹은 피드포워드 신경망에서는 은닉 유닛마다 하나의 편향 값이 있다고 생각하면 됩니다.
- 옮긴이_ x[0]이 w[0] 하나의 가중치와 곱해져 출력으로 전달되는 것과 여러 은닉 유닛을 거쳐 다시 출력으로 가중치 합을 하는 것은 x[0]에 대해 가중치 변수를 정리하면 동일한 식으로 표현됩니다. 즉 단순 선형 함수만을 사용하면 하나의 가중치를 여러 개로 분할하는 역할만 할 뿐입니다.
- 옮긴이_ 이런 함수들을 활성화 함수activation function라 하며 렐루와 하이퍼볼릭 탄젠트 외에도 시그모이드sigmoid 함수가 있습니다. 로지스틱 함수로도 불리는 시그모이드 함수의 수식은
이며 z는 유닛의 출력값입니다. scikit-learn의 다층 퍼셉트론은 이 세 함수를 모두 지원합니다.
- 옮긴이_ 보통 분류의 경우에는 신경망 마지막 출력층에 시그모이드(이진 분류)나 소프트맥스(다중 분류) 함수를 적용하여 최종 출력 ŷ을 계산합니다. 소프트맥스 함수는 여러 유닛의 출력값을 정규화하기 위한 것으로써 함수의 수식은
으로 나타내며 z는 각 유닛의 출력값이고 k는 유닛 개수입니다.
- 옮긴이_ alpha 매개변수의 기본값은 0.0001입니다.
- 옮긴이_ 신경망에서 사용하는 대표적인 다른 규제 방법은 드롭아웃dropout입니다. 드롭아웃은 은닉층 유닛의 일부를 랜덤하게 작동시키지 않음로써 마치 서로 다른 많은 신경망을 앙상블시키는 것 같은 효과를 내어 과대적합을 방지합니다. scikit-learn에서는 아직 드롭아웃을 지원하지 않지만, 앞으로 추가될 예정입니다.
- 옮긴이_ 데이터에서 평균을 빼고 표준편차로 나눈 값을 z-점수(z-score) 또는 표준 점수standard score라고 합니다. z-점수는 평균이 0, 분산이 1인 표준정규분포입니다.
- 옮긴이_ AdamAdaptive Moment Estimation 알고리즘은 경사 하강법의 학습률learning rate 매개변수를 학습이 반복됨에 따라 조정해가는 알고리즘 중 하나입니다. MLPClassifier와 MLPRegressor의 solver 매개변수 기본값이 adam이고 max_iter 매개변수의 기본값은 200입니다.
- 여러 모델이 0.972의 동일한 정확도를 낸 것을 알 수 있습니다. 이는 모든 모델이 똑같은 개수, 즉 4개를 실수한다는 뜻입니다. 실제 예측한 것을 비교해보면 정확히 동일한 포인트를 잘못 분류한다는 것을 알 수 있습니다. 데이터셋이 작거나 무리와 동떨어진 데이터 포인트가 있는 경우 이런 일이 일어날 수 있습니다.
- 옮긴이_ mlp.coef_[0]은 입력과 은닉층 사이의 가중치가 저장되어 있는 (30, 100) 크기의 NumPy 배열이고 mlp.coef_[1]은 은닉층과 출력 사이의 가중치가 저장되어 있는 (100, 1) 크기의 NumPy 배열입니다.
- 옮긴이_ 이 특성들을 포함해 몇몇 특성들의 가중치는 0에 가까운 값을 가지고 있어 너무 밝거나 너무 어둡지 않은 밋밋한 색깔로 히트맵에 가로줄을 만드는 것 같은 느낌을 줍니다.
- 옮긴이_ scikit-learn에는 최근 널리 사용되는 콘볼루션 신경망CNN, convolutional neural network, 합성곱 신경망이나 리커런트 신경망RNN, recurrent neural network, 순환 신경망이 구현되어 있지 않습니다.
- 옮긴이_ 최근에는 페이스북에서 오픈 소스로 공개한 PyTorch 라이브러리도 빠르게 인기를 얻고 있습니다.
- 옮긴이_ 렐루, 하이퍼볼릭 탄제트와 같은 활성화 함수를 말합니다.
- 옮긴이_ BFGS 알고리즘은 연구자들의 이름을 따서 Broyden–Fletcher–Goldfarb–Shanno 알고리즘으로도 불리는 의사 뉴턴 메서드Newton Method 중 하나입니다. L-BFGSLimited-memory BFGS 는 BFGS 알고리즘을 제한된 메모리 공간에서 구현하는 방법으로 머신러닝에서 널리 사용합니다.
- 옮긴이_ ‘sgd’ 옵션일 때 영향을 미치는 매개변수 중 momentum과 nesterovs_momentum이 있습니다. 모멘텀 방식은 이전의 그래디언트를 momentum 매개변수 비율만큼 현재 계산된 그래디언트에 반영하여 갱신할 그래디언트를 구합니다. 이전의 그래디언트를 속도라고도 하며, 일정 비율의 과거 그래디언트를 모두 포함하고 있어서 마치 관성같은 효과를 준다고 볼 수 있습니다. 네스테로프 모멘텀은 모멘텀에서 구한 그래디언트를 이전 그래디언트로 가정하고 한 번 더 모멘텀 방식을 적용하여 갱신할 그래디언트를 계산합니다. 더 자세한 내용은 역자의 블로그를 참고하세요. https://tensorflow.blog/2017/03/22/momentum-nesterov-momentum/
- 옮긴이_ 최근에 나온 “The Marginal Value of Adaptive Gradient Methods in Machine Learning”, A. C. Wilson et al. (2017, https://goo.gl/NAkWIa) 논문에서 적응적인 최적화 방법인 Adam, RMSProp, AdaGrad가 일부 데이터셋에서 좋지 않은 성능을 내었습니다. 따라서 무조건 Adam 알고리즘을 기본으로 고정하지 말고 ‘sgd’+모멘텀 방식을 함께 테스트해 보는 것이 좋습니다.
- 옮긴이_ solver 매개변수를 ‘adam’ 또는 ‘sgd’로 두고 전체 데이터를 일정 크기로 나눈 미니 배치mini-batch를 사용하여 모델을 점진적으로 학습시킬 경우가 있습니다. 전체 데이터를 메모리에 모두 적재할 수 없을 때에는 fit 메서드 대신에 학습된 것을 유지하면서 반복하여 학습할 수 있는 partial_fit 메서드를 사용합니다.
–
2.3.7 커널 서포트 벡터 머신 | 목차 | 2.4 분류 예측의 불확실성 추정
–
이 글은 한빛미디어에서 출간한 “파이썬 라이브러리를 활용한 머신러닝“의 1장과 2장입니다. 이 책의 저작권은 한빛미디어(주)에 있으므로 무단 복제 및 무단 전제를 금합니다.
안녕하세요 선생님, 책보고 하다가 막히는 부분이 있어 또 문의남깁니다.
파이썬 라이브러리를 활용한 머신러닝 142페이지의 코드 중
mglearn.plots.plot_2d_separator(mlp, X_train, fill=True, alpha=.3)
에서 에러가 발생하는데 원인을 모르겠습니다. 바쁘시겠지만 도움 요청드립니다 ㅠ
에러코드는 아래와 같습니다.
AttributeError Traceback (most recent call last)
d:\python\lib\site-packages\mglearn\plot_2d_separator.py in plot_2d_separator(classifier, X, fill, ax, eps, alpha, cm, linewidth, threshold, linestyle)
85 try:
—> 86 decision_values = classifier.decision_function(X_grid)
87 levels = [0] if threshold is None else [threshold]
AttributeError: ‘MLPClassifier’ object has no attribute ‘decision_function’
During handling of the above exception, another exception occurred:
MemoryError Traceback (most recent call last)
in ()
6 X_train, X_test, y_train, y_test = train_test_split(X, y, stratify=y, random_state=42)
7 mlp = MLPClassifier(solver=’lbfgs’, random_state=0).fit(X_train, y_train)
—-> 8 mglearn.plots.plot_2d_separator(mlp, X_train, fill=True, alpha=.3)
9 mglearn.discrete_scatter(X_train[:, 0], X_train[:, 1], y_train)
d:\python\lib\site-packages\mglearn\plot_2d_separator.py in plot_2d_separator(classifier, X, fill, ax, eps, alpha, cm, linewidth, threshold, linestyle)
90 except AttributeError:
91 # no decision_function
—> 92 decision_values = classifier.predict_proba(X_grid)[:, 1]
93 levels = [.5] if threshold is None else [threshold]
94 fill_levels = [0] + levels + [1]
d:\python\lib\site-packages\sklearn\neural_network\multilayer_perceptron.py in predict_proba(self, X)
1048 “””
1049 check_is_fitted(self, “coefs_”)
-> 1050 y_pred = self._predict(X)
1051
1052 if self.n_outputs_ == 1:
d:\python\lib\site-packages\sklearn\neural_network\multilayer_perceptron.py in _predict(self, X)
674 for i in range(self.n_layers_ – 1):
675 activations.append(np.empty((X.shape[0],
–> 676 layer_units[i + 1])))
677 # forward propagate
678 self._forward_pass(activations)
좋아요좋아요
지금 다시 한번 이런 저런 시도해보다가 확인한 결과, hidden_layer가 30이하일 때만 정상적으로 그래프를 보여주고 있습니다. 31부터는 위와 같은 에러가 뜨구요. default 값은 100이 들어가서 역시 에러가 난것 같은데, 어떻게 해결할 수 있을까요?
좋아요좋아요
안녕하세요. 사용하시는 컴퓨터의 램이 부족한 것 같습니다. MLPClassifier는 역전파 알고리즘을 사용하기 때문에 샘플의 정방향 계산 값들을 모두 메모리에 저장해야 합니다. 간단한 방법은 hidden_layer 사이즈를 줄이는 것입니다. lbfgs 알고리즘은 미니배치 방식을 사용하지 않습니다. solver=’lbfgs’를 삭제하면 기본 solver인 adam을 사용합니다. 이 때 batch_size=20과 같이 작은 값을 주어 미니배치 학습을 하면 역전파시에 메모리를 조금 덜 사용할 것 같습니다. 하지만 책에 나온 결과와는 조금 다를 수 있으니 참고하세요. 🙂
좋아요좋아요
감사합니다!!! : )
좋아요Liked by 1명
안녕하세요, 선생님의 글은 잘 보고 있습니다.
다름이 아니라, 책의 page 150 에서
‘ 모든 은닉 유닛에서 작은 가중치를 가진 특성은 모델에 덜 중요하다고 추론할 수 있습니다. “smoothness error”와 “fractal dimension error” 사이에 있는 특성과 “mean smoothness”와 “mean compactness”가 다른 특성들보다 가중치가 낮습니다. 12 이 특성들은 덜 중요하거나 신경망에게 적절하게 입력되지 않았을 수 있습니다. ‘
이 부분은 솔직히, 그림 2-54를 통해서는 이해가 잘 어렵습니다.
수치를 통해서나 다른 방법을 통해서 특성이 덜 중요하거나 입력이 적절하게 되지 않음을 확인 할 수 있습니까?
좋아요좋아요
주피터 노트북의 그림을 보시면 도움이 될 것 같습니다! 🙂 (http://nbviewer.jupyter.org/github/rickiepark/introduction_to_ml_with_python/blob/master/02-supervised-learning.ipynb)
좋아요좋아요