회귀 및 평가지표
회귀 및 평가지표.pdf
4.60MB
회귀 및 평가지표.ipynb
0.42MB
회귀 및 평가지표.html
0.70MB
사진이 포함되어 있으므로 pdf 로 확인
회귀¶
- 독립변수가 종속변수에 영향을 미치는지 알아보고자 할 때 사용
- 연속형 변수들에 대해 두 변수 사이의 적합도를 측정
- 단순회귀
- 하나의 종속변수와 하나의 독립변수 사이의 관계 분석
- 다중회귀
- 하나의 종속변수와 여러 독립변수 사이의 관계 분석
![No description has been provided for this image](../images/7.png)
In [ ]:
# 회귀란? 최적의 선을 찾는것...!!!
# 최적의 선이랑 예측 값의 선....
# 예측 값의 선으로 부터 결과 값들의 거리가 작을수록 좋은 예측이다
회귀 평가지표¶
- MSE(Mean Squared Error)(평균 제곱 오차)
- 예측값과 실제값의 차이에 대한 제곱에 대하여 평균을 낸 값
- 회귀 문제에서 가장 많이 사용하는 성능 지표
- 모델을 평가하는 평가 지표로 오차를 나타내는 식이므로 수치가 적을 수록 좋은 모델
- 다른 모델과 비교해야만 성능이 좋은지 알 수 있다.
- RMSE(Root Mean Squared Error)
- 0에 가까울수록 좋은 모델
- MSE에 ROOT를 쒸운 값
- MAE(Mean Absolute Error, 평균 절대 오차)
- 실제값 대비 예측값의 오차를 나타내는 것으로 값이 낮을 수록 좋다
- 예측값과 실제값의 차이에 대한 절대값에 대하여 평균을 낸 값
- MAPE(Mean Absolute Percentage Error, 평균 절대 비율 오차)
- 실제값 대비 예측차이가 얼마나 있는지를 비율(%)로 측정
- 퍼센트값을 가지며 0에 가까울수록 회귀모형의 성능이 좋다고 해석
- r2(결정계수)
- 0~1 사이의 값을 표현해 주며 r2의 값이 높을수록 좋다
- 예측 모델과 실제 모델이 얼마나 강한 상관관계를 가지고 있는지
- 타겟 데이터
- 1978년 보스턴 주택 가격
- 506개 타운의 주택 가격 중앙값(단위 1,000달러)
- 특징 데이터
- CRIM : 범죄율
- ZM : 25,000평방 피트 당 주거용 토지의 비율
- INDUS : 비소매상업지역 면적 비율
- CHAS : 찰스강의 경계에 위치한 경우는 1, 아니면 0(통로가 하천을 향하면1, 아니면 0)
- NOX : 일산화질소 농도(천만분의 1)
- RM : 주택당 방수
- AGE : 1940년 이전에 건축된 주택의 비율
- DIS : 5개 주요 고용센터까지의 가중거리
- RAD : 고속도로 접근성 지수
- TAX : 재산세율
- PTRATIO : 학생/교사 비율
- B ; 인구 중 흑인 거주 비율
- LSTAT : 인구 중 하위 계층 비율
- MEDV : 본인 소유의 주택가격(중앙값) (단위: $1,000)
In [1]:
import pandas as pd
import numpy as np
import warnings
warnings.filterwarnings("ignore")
In [2]:
df = pd.read_csv("../data_set/6.회귀/HousingData.csv")
df.head()
Out[2]:
CRIM | ZN | INDUS | CHAS | NOX | RM | AGE | DIS | RAD | TAX | PTRATIO | B | LSTAT | MEDV | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0.00632 | 18.0 | 2.31 | 0.0 | 0.538 | 6.575 | 65.2 | 4.0900 | 1 | 296 | 15.3 | 396.90 | 4.98 | 24.0 |
1 | 0.02731 | 0.0 | 7.07 | 0.0 | 0.469 | 6.421 | 78.9 | 4.9671 | 2 | 242 | 17.8 | 396.90 | 9.14 | 21.6 |
2 | 0.02729 | 0.0 | 7.07 | 0.0 | 0.469 | 7.185 | 61.1 | 4.9671 | 2 | 242 | 17.8 | 392.83 | 4.03 | 34.7 |
3 | 0.03237 | 0.0 | 2.18 | 0.0 | 0.458 | 6.998 | 45.8 | 6.0622 | 3 | 222 | 18.7 | 394.63 | 2.94 | 33.4 |
4 | 0.06905 | 0.0 | 2.18 | 0.0 | 0.458 | 7.147 | 54.2 | 6.0622 | 3 | 222 | 18.7 | 396.90 | 0.00 | 36.2 |
In [3]:
from sklearn.model_selection import train_test_split
y = df['MEDV']
X = df.drop(["MEDV"], axis=1)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3)
In [4]:
from sklearn.neighbors import KNeighborsRegressor
kn = KNeighborsRegressor()
kn.fit(X_train, y_train)
Out[4]:
KNeighborsRegressor()In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
KNeighborsRegressor()
In [20]:
pred = kn.predict( X_test )
pred
Out[20]:
array([23.46, 15.06, 23.38, 25.44, 22.14, 16.52, 20.02, 28.02, 23.52, 21.5 , 41.54, 16.52, 23.9 , 29.94, 23.56, 17.32, 21.46, 24.3 , 14.84, 28.64, 23.46, 24.78, 17.92, 29.26, 18.62, 20.6 , 20.56, 20.64, 18.32, 15.54, 11.68, 18.32, 28.72, 39.32, 38. , 20.16, 27.36, 20.98, 23.94, 24.06, 30.38, 9.96, 16.64, 34.9 , 28.76, 15.4 , 30.02, 23.82, 13.26, 10.56, 28.02, 33.18, 20.88, 22.62, 28.36, 24.56, 23.16, 21.64, 26.14, 11.14, 28.06, 15.2 , 21.5 , 13.26, 12.88, 13.34, 25.38, 12.3 , 13.28, 26.44, 23.96, 28.22, 31.48, 18.24, 15.4 , 28.42, 24.46, 23.9 , 21.72, 34.34, 16.84, 8.2 , 28.02, 23.36, 20.7 , 32.32, 12.34, 28.26, 15.4 , 29. , 20.9 , 29.86, 23. , 21.5 , 21.5 , 22.08, 20.96, 20.76, 28.06, 13.1 , 17.96, 19.58, 14.76, 18.62, 11.92, 11.46, 18.14, 36.86, 29.04, 22.48, 29.82, 25.52, 24.82, 14.68, 29.96, 28.02, 21.12, 10.8 , 22.68, 20.7 , 30.34, 10.04, 21.64, 41.54, 12.32, 21.58, 19.94, 31.92, 22.12, 11.82, 24.78, 19.26, 25.38, 36.18, 29.66, 16.74, 22.38, 20.12, 41.54, 11.94, 22.42, 12.18, 17.76, 25.48, 17.58, 27.02, 22.48, 24.66, 35.24, 27.82, 22.68, 40.16])
In [6]:
y_test
Out[6]:
63 25.0 417 10.4 339 19.0 84 23.9 215 25.0 ... 294 21.7 232 41.7 150 21.5 172 23.1 94 20.6 Name: MEDV, Length: 152, dtype: float64
In [21]:
from sklearn.metrics import mean_squared_error, r2_score
mse = mean_squared_error(y_test, pred)
r2 = r2_score(y_test, pred)
print("mse : ", mse)
print("r2 : ", r2)
print("score : ", kn.score(X_train, y_train))
print("score : ", kn.score(X_test, y_test))
# mse 는 0과 가까울 수록 좋은 결과
# r2, score 는 높을 수록 좋은 결과
mse : 43.82906578947368 r2 : 0.5349249633916936 score : 0.6057676219071229 score : 0.5349249633916936
In [ ]:
In [ ]:
In [17]:
from sklearn.ensemble import RandomForestRegressor
rfr = RandomForestRegressor()
rfr.fit(X_train, y_train)
Out[17]:
RandomForestRegressor()In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
RandomForestRegressor()
In [19]:
pred = rfr.predict( X_test )
mse = mean_squared_error(y_test, pred)
r2 = r2_score(y_test, pred)
print("mse : ", mse)
print("r2 : ", r2)
print("score : ", rfr.score(X_train, y_train))
print("score : ", rfr.score(X_test, y_test))
mse : 13.420632730263165 r2 : 0.857592190344317 score : 0.9701950979154201 score : 0.857592190344317
In [ ]:
In [ ]:
자전거 수요 예측¶
- 자전거 수요를 파악하여 효율적으로 자전거 대여수를 예측하고자 한다
- 월, 일, 시 별로 언제 자전거를 많이 대여하는지를 파악한다
- 컬럼
- datetime : 대여 날짜
- season : 1(봄), 2(여름), 3(가을), 4(겨울)
- holiday : 1(토,일 주말을 제외한 국경일 등의 휴일), 0(휴일이 아닌 날)
- workingday : 1(토, 일 주말 및 휴일이 아닌 주중), 0(주말 및 휴일)
- weather : 1(맑음), 2(흐림), 3(가벼운 눈, 비), 4(심한 눈, 비)
- temp : 온도(섭씨)
- atemp : 체감온도(섭씨)
- humidity : 습도
- windspeed : 풍속
- casual : 비등록 대여 횟수
- registered : 등록 대여 횟수
- count : 총 대여 횟수
In [23]:
df = pd.read_csv("../data_set/6.회귀/data.csv")
df.head()
Out[23]:
datetime | season | holiday | workingday | weather | temp | atemp | humidity | windspeed | casual | registered | count | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 2011-01-01 00:00:00 | 1 | 0 | 0 | 1 | 9.84 | 14.395 | 81 | 0.0 | 3 | 13 | 16 |
1 | 2011-01-01 01:00:00 | 1 | 0 | 0 | 1 | 9.02 | 13.635 | 80 | 0.0 | 8 | 32 | 40 |
2 | 2011-01-01 02:00:00 | 1 | 0 | 0 | 1 | 9.02 | 13.635 | 80 | 0.0 | 5 | 27 | 32 |
3 | 2011-01-01 03:00:00 | 1 | 0 | 0 | 1 | 9.84 | 14.395 | 75 | 0.0 | 3 | 10 | 13 |
4 | 2011-01-01 04:00:00 | 1 | 0 | 0 | 1 | 9.84 | 14.395 | 75 | 0.0 | 0 | 1 | 1 |
In [24]:
df.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 10886 entries, 0 to 10885 Data columns (total 12 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 datetime 10886 non-null object 1 season 10886 non-null int64 2 holiday 10886 non-null int64 3 workingday 10886 non-null int64 4 weather 10886 non-null int64 5 temp 10886 non-null float64 6 atemp 10886 non-null float64 7 humidity 10886 non-null int64 8 windspeed 10886 non-null float64 9 casual 10886 non-null int64 10 registered 10886 non-null int64 11 count 10886 non-null int64 dtypes: float64(3), int64(8), object(1) memory usage: 1020.7+ KB
In [25]:
# 문자열(object) 형식으로 저장되어 있던 datetime 을
# datetime 자료형으로 변환
df['datetime'] = df['datetime'].apply(pd.to_datetime)
df.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 10886 entries, 0 to 10885 Data columns (total 12 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 datetime 10886 non-null datetime64[ns] 1 season 10886 non-null int64 2 holiday 10886 non-null int64 3 workingday 10886 non-null int64 4 weather 10886 non-null int64 5 temp 10886 non-null float64 6 atemp 10886 non-null float64 7 humidity 10886 non-null int64 8 windspeed 10886 non-null float64 9 casual 10886 non-null int64 10 registered 10886 non-null int64 11 count 10886 non-null int64 dtypes: datetime64[ns](1), float64(3), int64(8) memory usage: 1020.7 KB
In [29]:
# 년 / 월 / 일 / 시
# 컬럼으로 따로 분리
df['year'] = df['datetime'].dt.year
df['month'] = df['datetime'].dt.month
df['day'] = df['datetime'].dt.day
df['hour'] = df['datetime'].dt.hour
In [28]:
df.head()
Out[28]:
datetime | season | holiday | workingday | weather | temp | atemp | humidity | windspeed | casual | registered | count | year | month | day | hour | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 2011-01-01 00:00:00 | 1 | 0 | 0 | 1 | 9.84 | 14.395 | 81 | 0.0 | 3 | 13 | 16 | 2011 | 1 | 1 | 0 |
1 | 2011-01-01 01:00:00 | 1 | 0 | 0 | 1 | 9.02 | 13.635 | 80 | 0.0 | 8 | 32 | 40 | 2011 | 1 | 1 | 1 |
2 | 2011-01-01 02:00:00 | 1 | 0 | 0 | 1 | 9.02 | 13.635 | 80 | 0.0 | 5 | 27 | 32 | 2011 | 1 | 1 | 2 |
3 | 2011-01-01 03:00:00 | 1 | 0 | 0 | 1 | 9.84 | 14.395 | 75 | 0.0 | 3 | 10 | 13 | 2011 | 1 | 1 | 3 |
4 | 2011-01-01 04:00:00 | 1 | 0 | 0 | 1 | 9.84 | 14.395 | 75 | 0.0 | 0 | 1 | 1 | 2011 | 1 | 1 | 4 |
In [31]:
# 시간 별로 빌린 자전거 댓수의 합
d = df.groupby('hour').agg({"count":sum}).reset_index()
d
Out[31]:
hour | count | |
---|---|---|
0 | 0 | 25088 |
1 | 1 | 15372 |
2 | 2 | 10259 |
3 | 3 | 5091 |
4 | 4 | 2832 |
5 | 5 | 8935 |
6 | 6 | 34698 |
7 | 7 | 96968 |
8 | 8 | 165060 |
9 | 9 | 100910 |
10 | 10 | 79667 |
11 | 11 | 95857 |
12 | 12 | 116968 |
13 | 13 | 117551 |
14 | 14 | 111010 |
15 | 15 | 115960 |
16 | 16 | 144266 |
17 | 17 | 213757 |
18 | 18 | 196472 |
19 | 19 | 143767 |
20 | 20 | 104204 |
21 | 21 | 79057 |
22 | 22 | 60911 |
23 | 23 | 40816 |
In [35]:
import seaborn as sns
import matplotlib.pyplot as plt
plt.figure(figsize=(7,5))
sns_result = sns.pointplot(data=d, x="hour", y="count")
plt.xticks(rotation=45)
plt.title("bicycle rental", fontsize=15, color="black")
plt.show()
In [44]:
# 휴일과 휴일이 아닌 날로 그룹화
d = df.groupby(['hour','workingday']).agg({"count":sum}).reset_index()
d.head()
Out[44]:
hour | workingday | count | |
---|---|---|---|
0 | 0 | 0 | 13701 |
1 | 0 | 1 | 11387 |
2 | 1 | 0 | 10427 |
3 | 1 | 1 | 4945 |
4 | 2 | 0 | 7686 |
In [45]:
# 1 : 주중
# 0 : 휴일 ( 토, 일 )
sns.pointplot(data=d, x="hour", y="count", hue="workingday")
plt.show()
In [46]:
# 시간대 별, 월 별로 확인
d = df.groupby(['hour','month']).agg({"count":sum}).reset_index()
d.head()
Out[46]:
hour | month | count | |
---|---|---|---|
0 | 0 | 1 | 852 |
1 | 0 | 2 | 1096 |
2 | 0 | 3 | 1249 |
3 | 0 | 4 | 1480 |
4 | 0 | 5 | 2441 |
In [47]:
sns.pointplot(data=d, x="hour", y="count", hue="month")
plt.show()
In [49]:
# 시간대 별, 날씨 별로 확인
# weather : 1(맑음), 2(흐림), 3(가벼운 눈, 비), 4(심한 눈, 비)
d = df.groupby(['hour','weather']).agg({"count":sum}).reset_index()
d.head()
sns.pointplot(data=d, x="hour", y="count", hue="weather")
plt.show()
In [50]:
df.columns
Out[50]:
Index(['datetime', 'season', 'holiday', 'workingday', 'weather', 'temp', 'atemp', 'humidity', 'windspeed', 'casual', 'registered', 'count', 'year', 'month', 'day', 'hour'], dtype='object')
In [51]:
f = ['season', 'holiday', 'workingday', 'weather', 'temp',
'atemp', 'humidity', 'windspeed', 'year', 'month', 'day', 'hour']
l = 'count'
X, y = df[f], df[l]
In [52]:
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3)
In [53]:
from sklearn.ensemble import RandomForestRegressor
rfr = RandomForestRegressor()
rfr.fit(X_train, y_train)
print("train : ", rfr.score(X_train, y_train))
print("test : ", rfr.score(X_test, y_test))
train : 0.9914114957469251 test : 0.9376778114053523
In [54]:
from sklearn.model_selection import GridSearchCV
params = {
"n_estimators" : range(5, 100, 10), # 트리 갯수(알고리즘)
"max_depth" : range(4, 11, 2), # 트리의 최대 깊이
"min_samples_split" : range(4, 21, 4) # 립노드 조건 샘플 수
}
rfr = RandomForestRegressor()
grid_cv = GridSearchCV(rfr, param_grid=params, cv=3, n_jobs=-1)
grid_cv.fit(X_train, y_train)
print("최적의 파라미터 : ", grid_cv.best_params_)
print("train : ", grid_cv.score(X_train, y_train))
print("test : ", grid_cv.score(X_test, y_test))
최적의 파라미터 : {'max_depth': 10, 'min_samples_split': 4, 'n_estimators': 75} train : 0.9525772588841167 test : 0.9206851922918676
In [55]:
X.head(3)
Out[55]:
season | holiday | workingday | weather | temp | atemp | humidity | windspeed | year | month | day | hour | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 0 | 0 | 1 | 9.84 | 14.395 | 81 | 0.0 | 2011 | 1 | 1 | 0 |
1 | 1 | 0 | 0 | 1 | 9.02 | 13.635 | 80 | 0.0 | 2011 | 1 | 1 | 1 |
2 | 1 | 0 | 0 | 1 | 9.02 | 13.635 | 80 | 0.0 | 2011 | 1 | 1 | 2 |
In [59]:
# 대략 아래와 같은 상황에서는 자전거가 20대가 필요하겠다....!!
# 아래와 같은 계절, 흄, 날씨, 온도 등등등.... 에서
re = grid_cv.predict([[1, 0, 0, 1, 9.84, 14.395, 81, 0.0, 2011, 1, 1, 0]])
re[0]
Out[59]:
20.63599993470582
In [58]:
int(re[0])
Out[58]:
20
In [ ]:
In [ ]:
In [60]:
# 예제 : 두 값을 비교하기 위함
df_result = pd.DataFrame({"y_test ": [11,12,13,14,15,16,17,18,19],
"line_test" : [10,11,12,13,14,15,16,17,18]})
sns.lineplot(data = df_result)
plt.legend(labels=["Legend_Day1","Legend_Day2"])
# 실제 정답과 예측 정답 두가지를 넣고 lineplot를 이용하여 그리면 된다
Out[60]:
<matplotlib.legend.Legend at 0x1b203e646d0>
In [61]:
grid_cv.predict(X_test)
Out[61]:
array([147.88696059, 272.60793329, 18.18288773, ..., 197.27226131, 415.09046011, 419.37438723])
In [62]:
y_test
Out[62]:
7971 95 848 162 642 37 1023 1 6050 508 ... 5327 31 3742 121 4530 209 4375 209 8311 294 Name: count, Length: 3266, dtype: int64
In [69]:
range_start = 0
range_end = 30
line_test = grid_cv.predict(X_test)
y_test_reset = y_test[range_start : range_end].reset_index()
y_test_reset['pred_test'] = line_test[range_start : range_end]
y_test_reset['pred_test'] = y_test_reset['pred_test'].apply( int )
sns.lineplot( data = y_test_reset[['count', 'pred_test']])
plt.legend(labels = ['y_test', 'pred test'])
Out[69]:
<matplotlib.legend.Legend at 0x1b20aae5b10>
728x90
'BE > 머신러닝(ML)' 카테고리의 다른 글
[머신러닝] 군집 ( 고객분류 ) (0) | 2024.05.28 |
---|---|
[머신러닝] 변수 선택법 ( feature selection ) (0) | 2024.05.28 |
[머신러닝] 과적합 및 하이퍼파라미터 (0) | 2024.05.27 |
[머신러닝] 지도학습 ( 분류, 회귀 ), 평가지표 선택하는 방법 (0) | 2024.05.24 |
[머신러닝] 탐색적 데이터분석 ( EDA, 표준화, 가중치 ) (0) | 2024.05.24 |