기계 학습(기계 학습)
- 지도 학습 : 라벨이 지정된 데이터로 학습 ex.분류, 회귀
- 비지도 학습: 라벨이 없는 학습 데이터의 숨겨진 구조/특징 발견 ex. 쿨래스터링
- 강화 학습 : 보상 시스템에서 배우는 ex.위조 지폐 작성 시스템<->위조 지폐 여과 시스템
선형 회귀 (y = Wx+b)
- 손실 함수가 최소값(=오차 작음)을 갖도록(W, b)를 구하는 것이 최종 목적
- 기울기 하강 방법: 손실 함수가 최소값을 찾는 방법
손실 함수의 순간 기울기가 -면 W 증가, +면 W 감소, 기울기가 0이 되도록 - 학습률은 움직이는 정도(증감되는 비율)를 나타내며, 너무 크더라도 너무 작지 않다(밖으로 흩어지거나 발을 디딘다)
- 규제는 일반적인 선형 회귀의 과적합 문제를 해결하기 위해 회귀 계수에 페널티 값을 적용합니다.
(과적합: 학습 데이터에 대해서만 정확하게 예측 가능하고 새로운 데이터는 불가능한 상태) – 데이터는 보편적이고 일반적이어야 하며, 적합하면 W가 커지는 경향이 있음
L2 규제는 제곱, L1 규제는 절대값을 사용
회귀 직선을 구하는 함수 생성(회귀 직선은 y=6+4*X로 설정되며 이 직선을 추정해야 함)
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(0)
X = 2 * np.random.rand(100,1) # rand: 균일분포
y = 6 + 4 * X + np.random.randn(100,1) # randn:정규분포
# noise,error 더해줌
plt.scatter(X,y)
경사 하강법
① 임의의 가중치 W 선택
②그 W에서의 직선의 기울기를 나타내는 미분치(해당 W에서의 미분, 𝜕𝐸(𝑊)/𝜕𝑊)를 구한다
③그 미분값이 작아지는 방향으로 W감소(또는 증가)시켜 나가면
④ 최종적으로 기울기가 더 이상 작아지지 않는 곳을 찾을 수 있지만, 거기가 손실 함수 E(W) 최소값인 것을 알 수 있다.
# 비용함수 = 편차 제곱 합
def get_cost(y,y_pred):
N = len(y)
cost = np.sum(np.square(y-y_pred))/N
return cost
# 경사하강법 (w1: 회귀계수, w0: bias)
def get_weight_update(w1,w0,X,y,learning_rate=0.01):
N = len(y)
w1_update = np.zeros_like(w1) # 임의의 값 0으로
w0_update = np.zeros_like(w0)
y_pred = np.dot(X,w1.T)+w0 # 행렬 곱
diff = y - y_pred
w0_factors = np.ones((N,1)) # 1로 채워진 N행 1열
# 미분
w1_update = -(2/N)*learning_rate*(np.dot(X.T,diff))
w0_update = -(2/N)*learning_rate*(np.dot(w0_factors.T,diff)) # 1로 채워진 행렬이므로 행렬곱 결과는 diff
return w1_update,w0_update
# iters = 실행 횟수
def gradient_descent_steps(X,y,iters=10000):
w0 = np.zeros((1,1))
w1 = np.zeros((1,1))
for ind in range(iters):
w1_update,w0_update = get_weight_update(w1,w0,X,y)
w1 = w1 - w1_update # +가 나오면 빼줘야하고 -가 나오면 더해줘야하므로 -
w0 = w0 - w0_update
return w1,w0
실행 횟수가 클수록 미리 설정된 회귀 직선에 가까워지고 비용 함수의 값이 작아집니다.
라이브러리를 이용한 선형 회귀 (보스턴 주택 가격 예측)
데이터 준비
from sklearn import linear_model
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.datasets import load_boston
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error,r2_score
boston = load_boston()
bostonDf = pd.DataFrame(boston.data,columns=boston.feature_names)
bostonDf('PRICE')=boston.target
lm_features = ('RM','ZN','INDUS','NOX','AGE','PTRATIO','LSTAT','RAD')
fig,axs = plt.subplots(figsize=(16,8),ncols=4,nrows=2)
for i,feature in enumerate(lm_features):
row = int(i/4)
col = i%4
sns.regplot(x=feature,y='PRICE',data=bostonDf,ax=axs(row)(col))
그래프를 보면 RM과 LSTAT을 제외한 다른 변수는 주택 가격과 큰 상관 관계가 없음을 알 수 있습니다.
데이터 전체에서 학습하는 데이터와 테스트할 데이터를 구별
y_target = bostonDf('PRICE')
X_data = bostonDf.drop(columns="PRICE")
X_train,X_test,y_train,y_test = train_test_split(X_data,
y_target,
test_size=0.3,
random_state=156)
학습 후, mse(평균 제곱 오차)와 rmse(뿌리의 평균 제곱 오차), r2(예측값 분산/실제 데이터 분산)를 조사한다.
나머지 지표는 작을수록 좋지만 r2 점수는 1에 가까울수록 좋습니다.
lr = LinearRegression()
lr.fit(X_train,y_train)
y_preds = lr.predict(X_test)
mse = mean_squared_error(y_test,y_preds)
rmse= np.sqrt(mse)
r2 = r2_score(y_test,y_preds)
print(f'mse:{mse:.3f},rmse:{rmse:.3f},r2:{r2:.3f}') # mse:17.297,rmse:4.159,r2:0.757
print('절편:',lr.intercept_)
print('회귀계수:',np.round(lr.coef_,1))
절편: 40.99559517216473
회귀계수: ( -0.1 0.1 0. 3. -19.8 3.4 0. -1.7 0.4 -0. -0.9 0.
-0.6)
coeff = pd.Series(data=np.round(lr.coef_,1),index=X_data.columns)
coeff.sort_values(ascending=False)
from sklearn.model_selection import cross_val_score
y = bostonDf('PRICE')
X = bostonDf.drop(columns="PRICE")
lr = LinearRegression()
neg_mse = cross_val_score(lr,X,y,scoring='neg_mean_squared_error',cv=5)
# 분류에서도 쓰고 회귀에서도 씀 분류에서는 cross_val_score 커야 좋음
# 회귀는 오차가 작아야 좋은거니까 나온 수치에 - 처리 그래서 neg 붙음
np.mean(-neg_mse) # 교차검증, mse
# 37.13180746769912
np.sqrt(np.mean(-neg_mse)) # 교차검증, rmse
# 6.093587405436892