머신 러닝의 가장 큰 목적은 실제 데이터를 바탕으로 모델을 생성해서 만약 다른 입력 값을 넣었을 때 발생할 아웃풋을 예측하는 데에 있다.
이때 우리가 찾아낼 수 있는 가장 직관적이고 간단한 모델은 선(line)이다. 그래서 데이터를 놓고 그걸 가장 잘 설명할 수 있는 선을 찾는 분석하는 방법을 선형 회귀(Linear Regression) 분석이라 부른다.
- 📌StandardScaler
평균=0, 표준편차=1로 조정해서 모든 특성이 같은 크기를 갖게 한다.- 📌MinMaxScaler
최대값=1, 최소값=0으로 조정, 아웃라이어에 취약- 📌RobustScaler
중앙값=0, IQR(1분위~3분위값)=1로 조정, 아웃라이어 영향을 최소화하며 정규분포보다 더 넓게 분포- 📌MaxAbsScaler
0을 기준으로 절대값이 가장 큰 수가 1 또는 -1이 되도록 조정, 양수 데이터로만 구성된 데이터셋에서는 아웃라이어에 민감데이터 스케일링을 하는 이유가 아웃라이어의 영향을 최소화하는 것이기 때문에 보통은 이상치 영향을 가장 적게 받는 StandardScaler 혹은 RobustScaler를 주로 사용한다. 모두 사이킷런에서 모듈을 제공한다.
출처 : https://for-my-wealthy-life.tistory.com/18
LinearRegression의 경우 summary() 지원 하지 않으므로
R squeared 값을 확인한다.
from sklearn.linear_model import LinearRegression
from sklearn.metrics import r2_score, explained_variance_score, mean_squared_error
from sklearn.preprocessing import MinMaxScaler, StandardScaler, RobustScaler
import numpy as np
import matplotlib.pyplot as plt
sample_size = 100
np.random.seed(1)
x = np.random.normal(0, 10, sample_size)
y = np.random.normal(0, 10, sample_size) + x * 30
print(x[:5])
print(y[:5])
'''
[ 16.24345364 -6.11756414 -5.28171752 -10.72968622 8.65407629]
[ 482.83232345 -171.28184705 -154.41660926 -315.95480141 248.67317034]
'''
print(x.reshape(-1, 1)[:5])
'''
[[ 16.24345364]
[ -6.11756414]
[ -5.28171752]
[-10.72968622]
[ 8.65407629]]
'''
예를 들어 x(1차원배열)가 10개의 값이 있다고 한다면
x.reshape(2, -1) 은 2행으로 만드는데 x값의 개수에 맞춰 자동으로 2행 5열 2차원 맞춰준다.
그의 반대로 x.reshape(-1, 2) 는 2열에 맞춰 5행 2열로 차원을 만들어준다.
여기서는 x 의 값 개수가 100개 이므로 x.reshape(-1, 1) 은 100행 1열 2차원으로 재배열한다.
이렇게 2차원 배열로 만드는 이유는 사이킷런에서 x 값은 2차원 형태로 넣어주어야하기 떄문이다.
# 정규화 (0 ~ 1 사이의 값으로 변환)
x_scaled = MinMaxScaler().fit_transform(x.reshape(-1, 1))
print(x_scaled[:5])
'''
[[0.87492405]
[0.37658554]
[0.39521325]
[0.27379961]
[0.70578689]]
위와 같이 0 ~ 1 사이의 범위 값으로 변한것을 확인할 수 있다.
'''
📌MinMaxScaler은 데이터의 값들을 0과 1사이의 범위 값으로 변환하여 줍니다.
데이터들의 분포가 가우시안 분포가 아닐 경우에 적용을 해 볼 수 있습니다.
✏️fit() : 데이터를 학습시키는 메서드
✏️transform() : 실제로 학습시킨 것을 적용하는 메서드
✏️fit_transform() : 말그대로 fit()과 transform()을 한번에 처리할 수 있게 하는 메서드인데
조심해야 하는 것은 테스트 데이터에는 fit_transform()메서드를 쓰면 안된다.
# numpy.corrcoef(): 피어슨 상관계수 값을 계산해준다.
print('r :', np.corrcoef(x, y))
'''
아래에서 flatten() 으로 x_scaled의 차원을 축소한 이유는
np.corrcoef() 인자 값으로 2차원배열은 맞지 않아 다시 축소 시켜서 값을 넣어주었다.
'''
print('r :', np.corrcoef(x_scaled.flatten(), y))
'''
r : [[1. 0.99939357]
[0.99939357 1. ]]
r : [[1. 0.99939357]
[0.99939357 1. ]]
강한 양의 상관관계를 확인하였다.
'''
# 모델 학습
model = LinearRegression().fit(x_scaled, y)
y_pred = model.predict(x_scaled)
print('예측값 :', y_pred[:5])
print('실제값 :', y[:5])
'''
예측값 : [ 490.32381062 -182.64057041 -157.48540955 -321.44435455 261.91825779]
실제값 : [ 482.83232345 -171.28184705 -154.41660926 -315.95480141 248.67317034]
'''
print()
def regScoreFunc(y_true, y_pred):
print('r2_score(결정 계수):{}'.format(r2_score(y_true, y_pred)))
print('explained_variance_score(설명분산점수):{}'.format(explained_variance_score(y_true, y_pred)))
print('mean_squared_error(RMSE = 평균제곱근오차) :{}'.format(mean_squared_error(y_true, y_pred)))
regScoreFunc(y, y_pred)
'''
r2_score(결정 계수):0.9987875127274646
explained_variance_score(설명분산점수):0.9987875127274646
mean_squared_error(RMSE = 평균제곱근오차) :86.14795101998743
'''
r2_score(결정 계수)와 explained_variance_score(설명분산점수) 이 다르다면 에러에 편향이 있다는것이고, 이는 모델학습이 잘못되었다는 뜻이다.
위의 결과는 모델이 올바르게 되었다는것을 알 수 있다.
from sklearn.model_selection import train_test_split
train_test_split(arrays, test_size, train_size, random_state, shuffle, stratify)
[출처] [Python] sklearn의 train_test_split() 사용법|작성자 Paris Lee
train_test_split을 사용하는 예제를 확인해보자
from sklearn.linear_model import LinearRegression
from sklearn.metrics import r2_score, explained_variance_score, mean_squared_error
from sklearn.preprocessing import MinMaxScaler, StandardScaler, RobustScaler
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
# 공부 시간에 따른 시험점수 자료 사용
df = pd.DataFrame({'studytime':[3,4,5,8,10,5,8,6,3,6,10,9,7,0,1,2],
'score':[76,74,74,89,92,75,84,82,73,81,89,88,83,40,70,68]})
print(df)
# 학습된 모델의 성능을 확인하기 위해 dataset을 분리작업 (train(학습데이터)/ test(검정데이터))
from sklearn.model_selection import train_test_split
train, test = train_test_split(df, test_size=0.4, random_state=12) # 6:4
print(df.shape) # (16, 2)
print(train.shape) # (9, 2)
print(test.shape) # (7, 2)
x_train = train[['studytime']]
y_train = train['score']
x_test = test[['studytime']]
y_test = test['score']
print(x_train)
print(y_train)
print(x_train.shape, x_test.shape, y_train.shape, y_test.shape)
# (9, 1) (7, 1) (9,) (7,)
# 모델생성
# 모델 학습은 train 사용
model = LinearRegression().fit(x_train, y_train)
# 검정 시 test 사용
y_pred = model.predict(x_test)
print('실제값 :', y_test.values)
print('예측값 :', y_pred)
'''
실제값 : [75 73 81 70 82 92 83]
예측값 : [74.00923788 66.05080831 77.98845266 58.09237875 77.98845266 93.90531178
81.96766744]
'''
# 모델 성능을 수치로 표현
print('결정계수 :', r2_score(y_test, y_pred))
# 결정계수 : 0.3299587521497388
Linear Regression의 기본 알고리즘에 오버피팅 방지 목적의 제약조건을 담은 Ridge, Lasso, ElasticNet 회귀모형이 있다.
❗(Linear Regression 으로 사용했더니 오버피팅 증상발생 시 사용)
# Linear Regression의 기본 알고리즘에 오버피팅 방지 목적의 제약조건을 담은 Ridge, Lasso, ElasticNet 회귀모형이 있다.
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris
from sklearn.metrics import mean_squared_error
iris = load_iris()
print(iris)
print(iris.keys())
# dict_keys(['data', 'target', 'frame', 'target_names', 'DESCR', 'feature_names', 'filename'])
iris_df = pd.DataFrame(iris.data, columns=iris.feature_names)
iris_df["target"] = iris.target
iris_df["target_names"] = iris.target_names[iris.target]
print(iris_df[:3])
# train dataset, test dataset으로 나누기
from sklearn.model_selection import train_test_split
train_set, test_set = train_test_split(iris_df, test_size = 0.3,random_state=12)
# 회귀분석 방법 1 - LinearRegression
from sklearn.linear_model import LinearRegression
print(train_set.iloc[:, [2]]) # petal length (cm), 독립변수
print(train_set.iloc[:, [3]]) # petal width (cm), 종속변수
# 학습은 train dataset 으로 작업
model_linear = LinearRegression().fit(X=train_set.iloc[:, [2]], y=train_set.iloc[:, [3]])
print('slope : ', model_linear.coef_) # 0.42259168
print('bias : ', model_linear.intercept_) # -0.39917733
# 모델 평가는 test dataset 으로 작업
pred = model_linear.predict(test_set.iloc[:, [2]])
print('예측값 : ', np.round(pred[:5].flatten(),1))
print('실제값 : ', test_set.iloc[:, [3]][:5].values.flatten())
from sklearn.metrics import r2_score
print('r2_score(결정계수):{}'.format(r2_score(test_set.iloc[:, [3]], pred))) # 0.93833
plt.scatter(train_set.iloc[:, [2]], train_set.iloc[:, [3]], color='red')
plt.plot(np.array(test_set.iloc[:, [2]]), model_linear.predict(test_set.iloc[:, [2]]))
plt.show()
print('\nRidge -----------')
# 회귀분석 방법 - Ridge: alpha값을 조정(가중치 제곱합을 최소화)하여 과대/과소적합을 피한다. 다중공선성 문제 처리에 효과적.
from sklearn.linear_model import Ridge
model_ridge = Ridge(alpha=10).fit(X=train_set.iloc[:, [2]], y=train_set.iloc[:, [3]])
#점수
print(model_ridge.score(X=train_set.iloc[:, [2]], y=train_set.iloc[:, [3]])) # 0.91880
print(model_ridge.score(X=test_set.iloc[:, [2]], y=test_set.iloc[:, [3]])) # 0.94101
pred_ridge = model_ridge.predict(test_set.iloc[:, [2]])
print('ridge predict : ', pred_ridge[:5])
print('r2_score(결정계수):{}'.format(r2_score(test_set.iloc[:, [3]], pred_ridge))) # 0.9410
plt.scatter(train_set.iloc[:, [2]], train_set.iloc[:, [3]], color='blue')
plt.plot(np.array(test_set.iloc[:, [2]]), model_ridge.predict(test_set.iloc[:, [2]]))
plt.show()
print('\nLasso -----------')
# 회귀분석 방법 - Lasso: alpha값을 조정(가중치 절대값의 합을 최소화)하여 과대/과소적합을 피한다.
from sklearn.linear_model import Lasso
model_lasso = Lasso(alpha=0.1).fit(X=train_set.iloc[:, [2]], y=train_set.iloc[:, [3]])
#점수
print(model_lasso.score(X=train_set.iloc[:, [2]], y=train_set.iloc[:, [3]])) # 0.913863
print(model_lasso.score(X=test_set.iloc[:, [2]], y=test_set.iloc[:, [3]])) # 0.940663
pred_lasso = model_lasso.predict(test_set.iloc[:, [2]])
print('lasso predict : ', pred_lasso[:5])
print('r2_score(결정계수):{}'.format(r2_score(test_set.iloc[:, [3]], pred_lasso)))
plt.scatter(train_set.iloc[:, [2]], train_set.iloc[:, [3]], color='green')
plt.plot(np.array(test_set.iloc[:, [2]]), model_lasso.predict(test_set.iloc[:, [2]]))
plt.show()
# 회귀분석 방법 4 - Elastic Net 회귀모형 : Ridge + Lasso의 형태로 가중치 절대값의 합(L1)과 제곱합(L2)을 동시에 제약 조건으로 가지는 모형
print('\nElasticNet -----------')
# 회귀분석 방법 - ElasticNet: alpha값을 조정(가중치 절대값의 합을 최소화)하여 과대/과소적합을 피한다.
from sklearn.linear_model import ElasticNet
model_elastic = ElasticNet(alpha=0.1).fit(X=train_set.iloc[:, [2]], y=train_set.iloc[:, [3]])
#점수
print(model_elastic.score(X=train_set.iloc[:, [2]], y=train_set.iloc[:, [3]])) # 0.913863
print(model_elastic.score(X=test_set.iloc[:, [2]], y=test_set.iloc[:, [3]])) # 0.940663
pred_elastic = model_elastic.predict(test_set.iloc[:, [2]])
print('ElasticNet predict : ', pred_elastic[:5])
print('r2_score(결정계수):{}'.format(r2_score(test_set.iloc[:, [3]], pred_elastic)))
plt.scatter(train_set.iloc[:, [2]], train_set.iloc[:, [3]], color='cyan')
plt.plot(np.array(test_set.iloc[:, [2]]), model_elastic.predict(test_set.iloc[:, [2]]))
plt.show()