Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
Tags
- programmablesearchengine
- pandas
- Python
- 사이킷런
- python 정렬
- langchain
- 파이토치기본
- 파이썬
- konlpy
- deeplearning
- 딥러닝
- OpenAIAPI
- 파이토치
- 자연어분석
- chatGPT
- sklearn
- pytorch
- 머신러닝
- 비지도학습
- HTML
- 판다스
- NLP
- 판다스 데이터정렬
- 챗gpt
- fastapi #파이썬웹개발
- 랭체인
- MachineLearning
- fastapi
- fastapi #python웹개발
- 파이썬웹개발
Archives
- Today
- Total
Data Navigator
[sklearn,statsmodels] Linear Regression을 이용한 고객별 연간 지출액 예측 본문
Machine Learning, Deep Learning
[sklearn,statsmodels] Linear Regression을 이용한 고객별 연간 지출액 예측
코딩하고분석하는돌스 2021. 1. 22. 23:03
02 Linear Regression을 이용한 고객별 연간 지출액 예측(statsmodels 사용)¶
In [1]:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
In [2]:
data = pd.read_csv('./02 Linear Regression을 이용한 고객별 연간 지출액 예측/ecommerce.csv')
In [3]:
data.head()
Out[3]:
Address | Avatar | Avg. Session Length | Time on App | Time on Website | Length of Membership | Yearly Amount Spent | ||
---|---|---|---|---|---|---|---|---|
0 | mstephenson@fernandez.com | 835 Frank Tunnel\nWrightmouth, MI 82180-9605 | Violet | 34.497268 | 12.655651 | 39.577668 | 4.082621 | 587.951054 |
1 | hduke@hotmail.com | 4547 Archer Common\nDiazchester, CA 06566-8576 | DarkGreen | 31.926272 | 11.109461 | 37.268959 | 2.664034 | 392.204933 |
2 | pallen@yahoo.com | 24645 Valerie Unions Suite 582\nCobbborough, D... | Bisque | 33.000915 | 11.330278 | 37.110597 | 4.104543 | 487.547505 |
3 | riverarebecca@gmail.com | 1414 David Throughway\nPort Jason, OH 22070-1220 | SaddleBrown | 34.305557 | 13.717514 | 36.721283 | 3.120179 | 581.852344 |
4 | mstephens@davidson-herman.com | 14023 Rodriguez Passage\nPort Jacobville, PR 3... | MediumAquaMarine | 33.330673 | 12.795189 | 37.536653 | 4.446308 | 599.406092 |
In [4]:
data.tail()
Out[4]:
Address | Avatar | Avg. Session Length | Time on App | Time on Website | Length of Membership | Yearly Amount Spent | ||
---|---|---|---|---|---|---|---|---|
495 | lewisjessica@craig-evans.com | 4483 Jones Motorway Suite 872\nLake Jamiefurt,... | Tan | 33.237660 | 13.566160 | 36.417985 | 3.746573 | 573.847438 |
496 | katrina56@gmail.com | 172 Owen Divide Suite 497\nWest Richard, CA 19320 | PaleVioletRed | 34.702529 | 11.695736 | 37.190268 | 3.576526 | 529.049004 |
497 | dale88@hotmail.com | 0787 Andrews Ranch Apt. 633\nSouth Chadburgh, ... | Cornsilk | 32.646777 | 11.499409 | 38.332576 | 4.958264 | 551.620145 |
498 | cwilson@hotmail.com | 680 Jennifer Lodge Apt. 808\nBrendachester, TX... | Teal | 33.322501 | 12.391423 | 36.840086 | 2.336485 | 456.469510 |
499 | hannahwilson@davidson.com | 49791 Rachel Heights Apt. 898\nEast Drewboroug... | DarkMagenta | 33.715981 | 12.418808 | 35.771016 | 2.735160 | 497.778642 |
In [5]:
#Avg.SessionLength = 고객의 평균 접속 시간
In [6]:
data.info() # R의 str()과 같음
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 500 entries, 0 to 499
Data columns (total 8 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 Email 500 non-null object
1 Address 500 non-null object
2 Avatar 500 non-null object
3 Avg. Session Length 500 non-null float64
4 Time on App 500 non-null float64
5 Time on Website 500 non-null float64
6 Length of Membership 500 non-null float64
7 Yearly Amount Spent 500 non-null float64
dtypes: float64(5), object(3)
memory usage: 31.4+ KB
In [7]:
# 7개의 컬럼이 있고, 모두 500개의 데이터가 있는 것으로 보아 결측치 없음
# 데이터 타입은 object(텍스트) 3, float64(실수형 자료)5개가 있음을 알 수 있다.
In [8]:
data.describe() #R의 summary() 함수와 같음
Out[8]:
Avg. Session Length | Time on App | Time on Website | Length of Membership | Yearly Amount Spent | |
---|---|---|---|---|---|
count | 500.000000 | 500.000000 | 500.000000 | 500.000000 | 500.000000 |
mean | 33.053194 | 12.052488 | 37.060445 | 3.533462 | 499.314038 |
std | 0.992563 | 0.994216 | 1.010489 | 0.999278 | 79.314782 |
min | 29.532429 | 8.508152 | 33.913847 | 0.269901 | 256.670582 |
25% | 32.341822 | 11.388153 | 36.349257 | 2.930450 | 445.038277 |
50% | 33.082008 | 11.983231 | 37.069367 | 3.533975 | 498.887875 |
75% | 33.711985 | 12.753850 | 37.716432 | 4.126502 | 549.313828 |
max | 36.139662 | 15.126994 | 40.005182 | 6.922689 | 765.518462 |
In [9]:
# count: 총 데이터 갯수
# mean: 평균
# std: 표준편차
# min: 최소값
# 25%: 25%값
# 50%: 50%값
# 75%: 75%값
# max: 최대값
# 75%와 max값의 차이가 너무 크면 아웃라이어가 있다.
텍스트 데이터는 의미가 없는 경우가 많으므로 정리¶
In [10]:
data2 = data[['Avg. Session Length','Time on App','Time on Website','Length of Membership','Yearly Amount Spent']]
In [11]:
data2
Out[11]:
Avg. Session Length | Time on App | Time on Website | Length of Membership | Yearly Amount Spent | |
---|---|---|---|---|---|
0 | 34.497268 | 12.655651 | 39.577668 | 4.082621 | 587.951054 |
1 | 31.926272 | 11.109461 | 37.268959 | 2.664034 | 392.204933 |
2 | 33.000915 | 11.330278 | 37.110597 | 4.104543 | 487.547505 |
3 | 34.305557 | 13.717514 | 36.721283 | 3.120179 | 581.852344 |
4 | 33.330673 | 12.795189 | 37.536653 | 4.446308 | 599.406092 |
... | ... | ... | ... | ... | ... |
495 | 33.237660 | 13.566160 | 36.417985 | 3.746573 | 573.847438 |
496 | 34.702529 | 11.695736 | 37.190268 | 3.576526 | 529.049004 |
497 | 32.646777 | 11.499409 | 38.332576 | 4.958264 | 551.620145 |
498 | 33.322501 | 12.391423 | 36.840086 | 2.336485 | 456.469510 |
499 | 33.715981 | 12.418808 | 35.771016 | 2.735160 | 497.778642 |
500 rows × 5 columns
In [12]:
# 트레이닝 데이터와 테스트 데이터를 나누기 위해서 sklearn에서 train_test_split을 임포트
from sklearn.model_selection import train_test_split
In [13]:
X = data2[['Avg. Session Length','Time on App','Time on Website','Length of Membership']]
In [14]:
X
Out[14]:
Avg. Session Length | Time on App | Time on Website | Length of Membership | |
---|---|---|---|---|
0 | 34.497268 | 12.655651 | 39.577668 | 4.082621 |
1 | 31.926272 | 11.109461 | 37.268959 | 2.664034 |
2 | 33.000915 | 11.330278 | 37.110597 | 4.104543 |
3 | 34.305557 | 13.717514 | 36.721283 | 3.120179 |
4 | 33.330673 | 12.795189 | 37.536653 | 4.446308 |
... | ... | ... | ... | ... |
495 | 33.237660 | 13.566160 | 36.417985 | 3.746573 |
496 | 34.702529 | 11.695736 | 37.190268 | 3.576526 |
497 | 32.646777 | 11.499409 | 38.332576 | 4.958264 |
498 | 33.322501 | 12.391423 | 36.840086 | 2.336485 |
499 | 33.715981 | 12.418808 | 35.771016 | 2.735160 |
500 rows × 4 columns
In [15]:
y = data2['Yearly Amount Spent']
y
Out[15]:
0 587.951054
1 392.204933
2 487.547505
3 581.852344
4 599.406092
...
495 573.847438
496 529.049004
497 551.620145
498 456.469510
499 497.778642
Name: Yearly Amount Spent, Length: 500, dtype: float64
In [16]:
# X는 독립변수, y는 종속변수
# 사이킥런에서 데이터 스플릿을 할 때 변수명은 아래와 동일하게 사용해야 한다.
X_train, X_test, y_train, y_test = train_test_split(X,y)
In [17]:
# 기본값으로 테스트 데이터는 33%가 들어가게 되어 있음
X_train
Out[17]:
Avg. Session Length | Time on App | Time on Website | Length of Membership | |
---|---|---|---|---|
271 | 33.540479 | 12.884125 | 36.226042 | 5.007272 |
486 | 33.452295 | 12.005916 | 36.534096 | 4.712234 |
47 | 32.726785 | 12.988510 | 36.462003 | 4.113226 |
165 | 32.047801 | 12.718039 | 37.661107 | 3.675849 |
106 | 32.291756 | 12.190474 | 36.152462 | 3.781823 |
... | ... | ... | ... | ... |
269 | 34.318927 | 13.402332 | 37.292045 | 3.606087 |
78 | 32.597183 | 10.889567 | 38.212571 | 4.442054 |
326 | 33.217188 | 10.999684 | 38.442767 | 4.243813 |
455 | 33.421212 | 10.706642 | 35.766154 | 3.393975 |
8 | 33.987773 | 13.386235 | 37.534497 | 3.273434 |
375 rows × 4 columns
In [18]:
# 데이터가 적으면 테스트 데이터와 트레이닝 데이터 비율을 2:8, 1:9 로 해야 할 때도 있다.
# test_size = 테스트 데이터와 트레이닝 데이터 비율을 조절하기 위해서 옵션값을 준다.
# random_state = 다른 사람에게 동일하게 샘플링된 데이터를 보여주고 싶을 때 사용
#
X_train, X_test, y_train, y_test = train_test_split(X,y, test_size=0.2, random_state=100 )
In [19]:
# test_size를 0.2로 잡았기 때문에 X_train 데이터가 400개가 됨.
X_train
Out[19]:
Avg. Session Length | Time on App | Time on Website | Length of Membership | |
---|---|---|---|---|
205 | 34.967610 | 13.919494 | 37.952013 | 5.066697 |
404 | 32.278443 | 12.527472 | 36.688367 | 3.531402 |
337 | 31.827979 | 12.461147 | 37.428997 | 2.974737 |
440 | 33.200616 | 11.965980 | 36.831536 | 3.549036 |
55 | 33.925297 | 11.588655 | 35.252242 | 3.392050 |
... | ... | ... | ... | ... |
343 | 32.302748 | 12.815393 | 37.957810 | 4.615426 |
359 | 32.054262 | 13.149670 | 37.650400 | 4.195614 |
323 | 32.762456 | 10.952353 | 37.646292 | 4.019470 |
280 | 32.271848 | 13.485009 | 37.550880 | 3.086337 |
8 | 33.987773 | 13.386235 | 37.534497 | 3.273434 |
400 rows × 4 columns
In [21]:
# Linear Regression 모델링을 위한 API 호출
# !pip install statsmodels
import statsmodels.api as sm
In [22]:
# Linear Regressin Training Data를 만들기 위해서 sm.OLS() 함수 사용
# sm.OLS(y_train, X_train) 형식으로 사용하며 y_train이 먼저 온다는 것에 주의
model = sm.OLS(y_train, X_train)
In [23]:
# .fit()을 이용하여 실제로 training을 시킴
model = model.fit()
In [24]:
# tarining된 결과는 .summary() 로 볼 수 있다.
model.summary()
Out[24]:
Dep. Variable: | Yearly Amount Spent | R-squared (uncentered): | 0.998 |
---|---|---|---|
Model: | OLS | Adj. R-squared (uncentered): | 0.998 |
Method: | Least Squares | F-statistic: | 4.798e+04 |
Date: | Wed, 06 Jan 2021 | Prob (F-statistic): | 0.00 |
Time: | 08:49:43 | Log-Likelihood: | -1820.0 |
No. Observations: | 400 | AIC: | 3648. |
Df Residuals: | 396 | BIC: | 3664. |
Df Model: | 4 | ||
Covariance Type: | nonrobust |
coef | std err | t | P>|t| | [0.025 | 0.975] | |
---|---|---|---|---|---|---|
Avg. Session Length | 11.9059 | 0.869 | 13.696 | 0.000 | 10.197 | 13.615 |
Time on App | 34.3257 | 1.121 | 30.610 | 0.000 | 32.121 | 36.530 |
Time on Website | -14.1405 | 0.812 | -17.405 | 0.000 | -15.738 | -12.543 |
Length of Membership | 61.0149 | 1.144 | 53.318 | 0.000 | 58.765 | 63.265 |
Omnibus: | 0.490 | Durbin-Watson: | 1.987 |
---|---|---|---|
Prob(Omnibus): | 0.783 | Jarque-Bera (JB): | 0.606 |
Skew: | -0.022 | Prob(JB): | 0.739 |
Kurtosis: | 2.814 | Cond. No. | 55.4 |
Notes:
[1] R² is computed without centering (uncentered) since the model does not contain a constant.
[2] Standard Errors assume that the covariance matrix of the errors is correctly specified.
In [28]:
# 모델을 통한 예측 .predict()
pred = model.predict(X_test)
pred
Out[28]:
69 418.211323
29 567.097473
471 534.706617
344 425.690888
54 474.931682
...
460 570.877250
152 564.267305
154 557.093996
56 489.285778
392 550.720695
Length: 100, dtype: float64
In [27]:
y_test
Out[27]:
69 451.575685
29 554.722084
471 541.049831
344 442.722892
54 522.404141
...
460 618.845970
152 555.892595
154 595.803819
56 520.898794
392 549.131573
Name: Yearly Amount Spent, Length: 100, dtype: float64
In [31]:
plt.figure(figsize=(10,10)) # 그래프를 정사각형으로 metplotlib에서 조정
sns.scatterplot(x=y_test, y=pred) # 산점도 그래프 Seaborn 이용
Out[31]:
<AxesSubplot:xlabel='Yearly Amount Spent'>
MSE (Mean Squared Error)¶
실제값과 예측값의 차이 (잔차)¶
예측보다 값이 클수도 있고 작을 수도 있어서 값의 차이가 + 혹은 -가 될 수 있다.
e.g. 예측값 =12, 실제값 = 10 예측값-실제값 = +2¶
예측값 =7, 실제값 = 11 예측값-실제값 = -4¶
+값과 -값이 같이 있기 때문에 전체 데이터에서 잔차합의 평균을 구하면 거의 0에 가까워진다.¶
그러면 오류가 있음에도 불구하고 마치 오류가 없는 것 처럼 되어 버리기 때문에¶
+값과 -값이 상쇄되어 생기는 문제를 없애기 위해서 2가지 방법을 이용해 오류를 검증한다.¶
1. 절대값을 사용¶
2. 제곱값을 사용(분산) - 통계학이나 머신러닝에서 주로 사용함.¶
잔차의 제곱합의 평균 = 최소제곱합 (에러의 사이즈)¶
In [32]:
from sklearn.metrics import mean_squared_error
In [33]:
# MSE 값 구하기
# 482가 나오는데 데이터에 따라서 다르기 때문에 이 모델에서 나온 것 만으로 판단할 수는 없음.
# 데이터의 단위가 작을 경우 숫자가 작게 나옴
# 원본 데이터가 예측이 잘 될 수 있도록 되어 있는 경우 값이 작게 나옴.
# MSE는 상대적인 값이라는 점을 명심하자.
mean_squared_error(y_test, pred)
Out[33]:
482.2890139089
In [34]:
# RMSE (Rounded Meansquared Error)
# MSE는 제곱을 했기 때문에 값이 너무 커보여서 루트를 씌워서 결과를 봄
# numpy의 .sqrt() 사용
# 21.96정도의 에러율을 보인다고 할 수 있음.
np.sqrt(mean_squared_error(y_test, pred))
Out[34]:
21.961079525125808
In [ ]:
In [ ]:
In [ ]:
In [ ]:
In [ ]:
In [ ]:
In [ ]:
In [ ]:
'Machine Learning, Deep Learning' 카테고리의 다른 글
[sklearn] KNN(K Nearlist Neighbors) 알고리즘을 이용하여 고객이탈 예측하기 (0) | 2021.01.27 |
---|---|
[sklearn, NLP] 상품 리뷰 분석 NLP, Count Vectorizer, Naive Bayes Classifier (0) | 2021.01.24 |
[sklearn] Logistic Regression을 활용한 소비자 광고 반응률 예측 (0) | 2021.01.22 |
[sklearn, SVM] 서포트 백터 머신을 이용해서 외국어 문장 판별하기 (0) | 2021.01.17 |
1. 머신러닝(Machine Learning) - 1일차 머신러닝 개념 및 종류 (0) | 2021.01.04 |