-
핸즈온 머신러닝[4] 모델 훈련(1)핸즈온머신러닝 2022. 5. 13. 18:58
https://www.youtube.com/watch?v=6omvN1nuZMc&list=PLJN246lAkhQjX3LOdLVnfdFaCbGouEBeb&index=13
선형회귀
MSE를 최소화하는 모델 파라미터를 찾는다.
행렬 곱셈: [θ0,θ1,..,θn][x0,x1,...,xn]^(T)
선형 회귀 계산 방식1: 정규 방정식
import numpy as np X = 2 * np.random.rand(100, 1) y = 4 + 3 * X + np.random.randn(100, 1)
rand 함수로 0과 1 사이의 난수를 발생, 100x1 행렬이 생긴다.
randn -> 표준 분포 난수
plt.plot(X, y, "b.") plt.xlabel("$x_1$", fontsize=18) plt.ylabel("$y$", rotation=0, fontsize=18) plt.axis([0, 2, 0, 15]) save_fig("generated_data_plot") plt.show()
식 4-4: 정규 방정식
X_b = np.c_[np.ones((100, 1)), X] # 모든 샘플에 x0 = 1을 추가합니다. theta_best = np.linalg.inv(X_b.T.dot(X_b)).dot(X_b.T).dot(y) # (2, 100)(100, 2) --> (2, 2) # (2, 2)(2, 100) --> (2, 100) # (2, 100)(100, 1) --> (2, 1)
c_ 함수: 여러 행렬을 column으로 이어붙임 -> X_b 행렬은 100x2 행렬이 됨
정규 방정식을 사용해서 theta_best를 구한다.
numpy의 linearalgebra 밑의 inverse 함수를 통해 역행렬을 구함
theta_best
array([[4.21509616], [2.77011339]]) -> 절편, 기울기
X_new = np.array([[0], [2]]) X_new_b = np.c_[np.ones((2, 1)), X_new] # 모든 샘플에 x0 = 1을 추가합니다. y_predict = X_new_b.dot(theta_best) y_predict
array([[4.21509616], [9.75532293]])
plt.plot(X_new, y_predict, "r-") plt.plot(X, y, "b.") plt.axis([0, 2, 0, 15]) plt.show()
plt.plot(X_new, y_predict, "r-", linewidth=2, label="Predictions") plt.plot(X, y, "b.") plt.xlabel("$x_1$", fontsize=18) plt.ylabel("$y$", rotation=0, fontsize=18) plt.legend(loc="upper left", fontsize=14) plt.axis([0, 2, 0, 15]) save_fig("linear_model_predictions_plot") plt.show()
from sklearn.linear_model import LinearRegression lin_reg = LinearRegression() lin_reg.fit(X, y) lin_reg.intercept_, lin_reg.coef_
(array([4.21509616]), array([[2.77011339]]))
lin_reg.predict(X_new)
array([[4.21509616], [9.75532293]]) -> 예측값
# 싸이파이 lstsq() 함수를 사용하려면 scipy.linalg.lstsq(X_b, y)와 같이 씁니다. theta_best_svd, residuals, rank, s = np.linalg.lstsq(X_b, y, rcond=1e-6) # residual: (yhat - y)**2, svd--->특잇값*rcond > 특잇값: 모두 0으로 바꿈 theta_best_svd
array([[4.21509616], [2.77011339]])
np.linalg.pinv(X_b).dot(y)
유사역행렬을 구하는 함수 (역행렬을 구하지 못하는 경우에 역행렬 근삿값을 구할 수 있다.)
array([[4.21509616], [2.77011339]])
경사 하강법(Gradient Descent)
비용 함수를 최소화하기 위해 반복적으로 모델 파라미터를 조정
경사 하강법의 문제 -> 이차함수가 아니기 때문에 지역 최솟값이 존재
경사하강법을 사용할 때는 사용하는 특성의 scale을 맞춰주어야 함
배치 경사 하강법
전체 샘플을 이용해서 경사 하강법 단계를 수행하는 것
미분값 -> 경사, 미분값을 이용해서 경사를 줄여나감
eta = 0.1 # 학습률 n_iterations = 1000 m = 100 theta = np.random.randn(2,1) # 랜덤 초기화 for iteration in range(n_iterations): gradients = 2/m * X_b.T.dot(X_b.dot(theta) - y) theta = theta - eta * gradients
theta
array([[4.21509616], [2.77011339]])
X_new_b.dot(theta)
array([[4.21509616], [9.75532293]]) -> 예측값
theta_path_bgd = [] # 그래프를 그리는 함수 def plot_gradient_descent(theta, eta, theta_path=None): m = len(X_b) plt.plot(X, y, "b.") n_iterations = 1000 for iteration in range(n_iterations): if iteration < 10: y_predict = X_new_b.dot(theta) style = "b-" if iteration > 0 else "r--" plt.plot(X_new, y_predict, style) gradients = 2/m * X_b.T.dot(X_b.dot(theta) - y) theta = theta - eta * gradients if theta_path is not None: theta_path.append(theta) plt.xlabel("$x_1$", fontsize=18) plt.axis([0, 2, 0, 15]) plt.title(r"$\eta = {}$".format(eta), fontsize=16)
np.random.seed(42) theta = np.random.randn(2,1) # random initialization plt.figure(figsize=(10,4)) plt.subplot(131); plot_gradient_descent(theta, eta=0.02) plt.ylabel("$y$", rotation=0, fontsize=18) plt.subplot(132); plot_gradient_descent(theta, eta=0.1, theta_path=theta_path_bgd) plt.subplot(133); plot_gradient_descent(theta, eta=0.5) save_fig("gradient_descent_plot") plt.show()
확률적 경사 하강법
* 모델 파라미터 랜덤 초기화
* 에포크 시작
-> 훈련 세트 섞기
* 훈련 세트에서 샘플 하나 꺼내기
* 경사 하강법 수행
* 모델 파라미터 수정
* 반복
* 종료
theta_path_sgd = [] m = len(X_b) np.random.seed(42)
n_epochs = 50 # 50번 반복 t0, t1 = 5, 50 # 학습 스케줄 하이퍼파라미터 def learning_schedule(t): return t0 / (t + t1) theta = np.random.randn(2,1) # 랜덤 초기화 for epoch in range(n_epochs): for i in range(m): if epoch == 0 and i < 20: # 책에는 없음 y_predict = X_new_b.dot(theta) # 책에는 없음 style = "b-" if i > 0 else "r--" # 책에는 없음 plt.plot(X_new, y_predict, style) # 책에는 없음 random_index = np.random.randint(m) # 실제로는 중복을 허용하지 않음 xi = X_b[random_index:random_index+1] yi = y[random_index:random_index+1] gradients = 2 * xi.T.dot(xi.dot(theta) - yi) # gradient 값을 점점 줄임, 정답에 가까워질 수록 조심 eta = learning_schedule(epoch * m + i) theta = theta - eta * gradients theta_path_sgd.append(theta) # 책에는 없음 plt.plot(X, y, "b.") # 책에는 없음 plt.xlabel("$x_1$", fontsize=18) # 책에는 없음 plt.ylabel("$y$", rotation=0, fontsize=18) # 책에는 없음 plt.axis([0, 2, 0, 15]) # 책에는 없음 save_fig("sgd_plot") # 책에는 없음 plt.show() # 책에는 없음
theta
array([[4.21076011], [2.74856079]])
from sklearn.linear_model import SGDRegressor sgd_reg = SGDRegressor(max_iter=1000, tol=1e-3, penalty=None, eta0=0.1, random_state=42) sgd_reg.fit(X, y.ravel())
SGDRegressor(eta0=0.1, penalty=None, random_state=42)
sgd_reg.intercept_, sgd_reg.coef_
(array([4.24365286]), array([2.8250878]))
미니배치 경사 하강법
theta_path_mgd = [] n_iterations = 50 minibatch_size = 20 np.random.seed(42) theta = np.random.randn(2,1) # 랜덤 초기화 t0, t1 = 200, 1000 def learning_schedule(t): return t0 / (t + t1) t = 0 for epoch in range(n_iterations): shuffled_indices = np.random.permutation(m) X_b_shuffled = X_b[shuffled_indices] y_shuffled = y[shuffled_indices] for i in range(0, m, minibatch_size): t += 1 xi = X_b_shuffled[i:i+minibatch_size] yi = y_shuffled[i:i+minibatch_size] gradients = 2/minibatch_size * xi.T.dot(xi.dot(theta) - yi) eta = learning_schedule(t) theta = theta - eta * gradients theta_path_mgd.append(theta) theta
array([[4.25214635], [2.7896408 ]])
theta_path_bgd = np.array(theta_path_bgd) theta_path_sgd = np.array(theta_path_sgd) theta_path_mgd = np.array(theta_path_mgd)
plt.figure(figsize=(7,4)) plt.plot(theta_path_sgd[:, 0], theta_path_sgd[:, 1], "r-s", linewidth=1, label="Stochastic") plt.plot(theta_path_mgd[:, 0], theta_path_mgd[:, 1], "g-+", linewidth=2, label="Mini-batch") plt.plot(theta_path_bgd[:, 0], theta_path_bgd[:, 1], "b-o", linewidth=3, label="Batch") plt.legend(loc="upper left", fontsize=16) plt.xlabel(r"$\theta_0$", fontsize=20) plt.ylabel(r"$\theta_1$ ", fontsize=20, rotation=0) plt.axis([2.5, 4.5, 2.3, 3.9]) save_fig("gradient_descent_paths_plot") plt.show()
문제
1. 미니 배치 경사하강법, 확률적 경사하강법, 배치 경사하강법의 다른점을 서술하시오
2. rand 함수와 randn 함수는 어떻게 다른가?
3. 유사역행렬이 무엇이며 선형 모델의 파라미터를 구할 때 유사역행렬이 사용되는 경우는 무엇인가?
4. SVD가 무엇인지 서술하시오
5. SGD가 무엇인지 서술하시오
'핸즈온머신러닝' 카테고리의 다른 글
핸즈온 머신러닝[4] 모델 훈련(3) (0) 2022.06.14 핸즈온 머신러닝[4] 모델 훈련(2) (0) 2022.06.13 핸즈온 머신러닝[3] 분류(2) (0) 2022.05.05 핸즈온 머신러닝[3] 분류(1) (0) 2022.05.04 핸즈온 머신러닝[2] 머신러닝 프로젝트 처음부터 끝까지(3) (0) 2022.04.28