2022.03.28 월
= multilayer perceptrons
= MLP
선형 회귀 모델
$\hat y = w[0]x[0] + w[1] x[1] + ... + w[p]*x[p] + b$
입력 특성 학습된 계수 가중치 합
다층 퍼셉트론 가중치 합을 만드는 과정이 여러 번 반복
은닉층이 하나인 다층 퍼셉트론
활성화 함수
여러 개의 가중치 합 계산 = (수학적) 하나의 가중치 합 계산 → 선형 모델과 다를 바가 없음 → 그래서!
= 비선형성이라고도 함
$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])$
$\hat y = v[0]h[0] + v[1] h[1] + v[2]*[h2] + v[3]*h[3] + b$
→ 은닉층의 유닛 개수 = 우리가 정해야 하는 중요 매개변수
→ 은닉층 개수 추가 가능
기본값 - moon 데이터셋
from sklearn.model_selection import train_test_split
from sklearn.neural_network import MLPClassifier
from sklearn.datasets import make_moons
# moon 데이터셋 사용
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)
# 기본 함수 : ReLU
# 은닉 유닛 기본 값 : 100
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")
은닉 유닛 바꾸기
# 기본 함수 : ReLU
# 은닉 유닛 : 10개
mlp = MLPClassifier(solver="lbfgs", random_state=0, **hidden_layer_sizes=[10]**, max_iter=1000)
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")
→ 기본값 설정에 비해 결정 경계 날카로워짐
결정 경계 ← 직선 10개 합쳐져서 구성 (은닉층 하나이므로)
은닉층 추가
# 기본 함수 : ReLU
# 은닉 유닛 : 10개, 10개
# 은닉 층 개수 : 2개
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")
은닉층 추가 + tanh 함수
# 기본 함수 : tanh
# 은닉 유닛 : 10개, 10개
# 은닉 층 개수 : 2개
mlp = MLPClassifier(solver="lbfgs", **activation='tanh'**, random_state=0,
**hidden_layer_sizes=[10,10]**,max_iter=1000)
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")
복잡도 제어
: 과대 적합이 되지 않도록 모델을 강제로 제한
alpha
선형회귀 와 동일
기본값 : 매우 낮음 → 거의 규제하지 않게
# alpha (복잡도 제어 - L2 페널티)
# 기본 함수 : ReLU
# 은닉 유닛 : 10개, 10개 / 100개, 100개
# 은닉 층 개수 : 2개
# alpha : 0.0001 / 0.01 / 0.1 / 1
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, max_iter = 1000,
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))
→ alpha 커질수록 규제 많이 들어가서 과대 적합이 되지 않도록 복잡도 낮춤
초기화
가중치를 무작위로 설정 = 무작위한 초기화
같은 매개 변수 사용하더라도 초깃값 다름 → 결과 다름
# 초기화 = 가중치 무작위 설정 (random_state)
# 기본 함수 : ReLU
# 은닉 유닛 : 100개, 100개
# 은닉 층 개수 : 2개
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)
ax.set_title("i={}".format(i))