{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\n\ndata_path = '/kaggle/input/bike-sharing-demand/'\n\ntrain = pd.read_csv(data_path + 'train.csv')\ntest = pd.read_csv(data_path + 'test.csv')\nsubmission = pd.read_csv(data_path + 'sampleSubmission.csv')","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2022-07-23T08:39:16.203735Z","iopub.execute_input":"2022-07-23T08:39:16.205088Z","iopub.status.idle":"2022-07-23T08:39:16.275854Z","shell.execute_reply.started":"2022-07-23T08:39:16.205045Z","shell.execute_reply":"2022-07-23T08:39:16.274683Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 데이터 분석\ntrain.head(5)","metadata":{"execution":{"iopub.status.busy":"2022-07-23T08:39:16.278198Z","iopub.execute_input":"2022-07-23T08:39:16.278580Z","iopub.status.idle":"2022-07-23T08:39:16.296415Z","shell.execute_reply.started":"2022-07-23T08:39:16.278546Z","shell.execute_reply":"2022-07-23T08:39:16.295545Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"피처 정리\ndatetime : 기록 일시(1시간 간격)\\\nseason : 계절(1-4, 봄-겨울)\\\nholiday : 공휴일 여부(0 아님, 1 공휴일)\\\nworkongday : 근무일 여부(0 아님, 1 근무일), 주말 공휴일이 아니면 근무일로 가정\\\nweather : 날씨 (1 맑음, 2 약간 흐림, 3 흐리거나 약한 눈비, 4 폭우, 숫자가 클수록 날씨 안 좋음)\\\ntemp : 실제 온도\\\natemp : 체감 온도\\\nwindspeed : 풍속\\\ncasual : 비회원\\\nregistered : 등록회원\\\ncount : 자전거 대여 수량\\","metadata":{}},{"cell_type":"code","source":"train.info()","metadata":{"execution":{"iopub.status.busy":"2022-07-23T08:39:16.297705Z","iopub.execute_input":"2022-07-23T08:39:16.298222Z","iopub.status.idle":"2022-07-23T08:39:16.319587Z","shell.execute_reply.started":"2022-07-23T08:39:16.298190Z","shell.execute_reply":"2022-07-23T08:39:16.318376Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#datetime을 object에서 datetime 타입으로 변환(feat. 송석리 선생님)\ntrain['datetime'] = pd.to_datetime(train['datetime'])\ntrain.info()","metadata":{"execution":{"iopub.status.busy":"2022-07-23T08:39:16.320853Z","iopub.execute_input":"2022-07-23T08:39:16.321159Z","iopub.status.idle":"2022-07-23T08:39:16.342755Z","shell.execute_reply.started":"2022-07-23T08:39:16.321131Z","shell.execute_reply":"2022-07-23T08:39:16.340998Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train['year'] = train['datetime'].dt.year\ntrain['month'] = train['datetime'].dt.month\ntrain['day'] = train['datetime'].dt.day\ntrain['hour'] = train['datetime'].dt.hour\ntrain['minute'] = train['datetime'].dt.minute\ntrain['second'] = train['datetime'].dt.second\ntrain['weekday'] = train['datetime'].dt.day_name()\ntrain.info()","metadata":{"execution":{"iopub.status.busy":"2022-07-23T08:39:16.346332Z","iopub.execute_input":"2022-07-23T08:39:16.347064Z","iopub.status.idle":"2022-07-23T08:39:16.382896Z","shell.execute_reply.started":"2022-07-23T08:39:16.347021Z","shell.execute_reply":"2022-07-23T08:39:16.381684Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# season과 weather의 특징이 명확하도록 변환\ntrain['season'] = train['season'].map({1: 'spring', 2: 'summer', 3: 'fall', 4: 'winter'})\ntrain['weather'] = train['weather'].map({1: 'clear', 2: 'mist, few clouds', 3: 'light snow, rain, thunderstorm', 4: 'heavy rain, thunderstorm, snow, fog'})\ntrain.head()","metadata":{"execution":{"iopub.status.busy":"2022-07-23T08:39:16.384186Z","iopub.execute_input":"2022-07-23T08:39:16.384766Z","iopub.status.idle":"2022-07-23T08:39:16.413672Z","shell.execute_reply.started":"2022-07-23T08:39:16.384733Z","shell.execute_reply":"2022-07-23T08:39:16.412344Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 데이터 시각화를 위한 라이브러리\nimport seaborn as sns\nimport matplotlib as mpl\nimport matplotlib.pyplot as plt","metadata":{"execution":{"iopub.status.busy":"2022-07-23T08:39:16.415344Z","iopub.execute_input":"2022-07-23T08:39:16.415703Z","iopub.status.idle":"2022-07-23T08:39:16.420528Z","shell.execute_reply.started":"2022-07-23T08:39:16.415660Z","shell.execute_reply":"2022-07-23T08:39:16.419420Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"mpl.rc('font', size = 15)\nsns.displot(train['count'])","metadata":{"execution":{"iopub.status.busy":"2022-07-23T08:39:16.422376Z","iopub.execute_input":"2022-07-23T08:39:16.422781Z","iopub.status.idle":"2022-07-23T08:39:16.764462Z","shell.execute_reply.started":"2022-07-23T08:39:16.422747Z","shell.execute_reply":"2022-07-23T08:39:16.763171Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"매우 큰 값이 무시할 수 없는 확률로 발생하는 분포\n꼬리가 두꺼운 분포라고 하기도 하고\n예시로 파레토 분포와 레비 분포, 와이블 분포 등이 있음.\n이런 경우 로그 변환을 통해 정규분포화 해주자.","metadata":{}},{"cell_type":"code","source":"sns.histplot(np.log(train['count']))","metadata":{"execution":{"iopub.status.busy":"2022-07-23T08:39:16.766178Z","iopub.execute_input":"2022-07-23T08:39:16.766955Z","iopub.status.idle":"2022-07-23T08:39:17.031938Z","shell.execute_reply.started":"2022-07-23T08:39:16.766915Z","shell.execute_reply":"2022-07-23T08:39:17.030805Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"정규분포에 가까운 모양이 되었음.\n중간에 비는건?","metadata":{}},{"cell_type":"code","source":"for i in range(1, 8):\n    a=np.log(i)\n    print(a)","metadata":{"execution":{"iopub.status.busy":"2022-07-23T08:39:17.034332Z","iopub.execute_input":"2022-07-23T08:39:17.034973Z","iopub.status.idle":"2022-07-23T08:39:17.040660Z","shell.execute_reply.started":"2022-07-23T08:39:17.034934Z","shell.execute_reply":"2022-07-23T08:39:17.039818Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"log에 대입한 값이 양의 정수이므로 불연속적으로 발생\n그러면 왜 뒤에는 연속적인가?\n로그는 뒤로 갈 수록 차이가 줄어들어서 붙어서 표현한 것 같음","metadata":{}},{"cell_type":"code","source":"for feature in ['year', 'month', 'day', 'hour', 'minute', 'second'] : \n    sns.barplot(x = feature, y = 'count', data = train)\n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2022-07-23T08:39:17.043848Z","iopub.execute_input":"2022-07-23T08:39:17.044745Z","iopub.status.idle":"2022-07-23T08:39:20.824000Z","shell.execute_reply.started":"2022-07-23T08:39:17.044711Z","shell.execute_reply":"2022-07-23T08:39:20.822640Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for feature in ['season', 'weather', 'holiday', 'workingday'] : \n    sns.boxplot(x = feature, y = 'count', data = train)\n    plt.xticks(rotation=45)\n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2022-07-23T08:39:20.825889Z","iopub.execute_input":"2022-07-23T08:39:20.826732Z","iopub.status.idle":"2022-07-23T08:39:21.644762Z","shell.execute_reply.started":"2022-07-23T08:39:20.826673Z","shell.execute_reply":"2022-07-23T08:39:21.643423Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for feature in ['season', 'weather', 'holiday', 'workingday', 'weekday'] : \n    plt.figure(figsize = (20,4))\n    sns.pointplot(x = 'hour', y = 'count', data = train, hue = feature)\n    plt.xticks(rotation=45)\n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2022-07-23T08:39:21.646599Z","iopub.execute_input":"2022-07-23T08:39:21.647705Z","iopub.status.idle":"2022-07-23T08:39:39.393392Z","shell.execute_reply.started":"2022-07-23T08:39:21.647625Z","shell.execute_reply":"2022-07-23T08:39:39.391862Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"","metadata":{}},{"cell_type":"markdown","source":"2번째 차트에서 폭우인데 18시에 대여한 데이터는 삭제하는 것이 나을 듯. 이상치 개념\n교재에서도 삭제한 기능이 낫다고 판단함.","metadata":{}},{"cell_type":"code","source":"corrMat = train[['temp', 'atemp', 'humidity', 'windspeed', 'count']].corr()\nsns.heatmap(corrMat, annot = True)","metadata":{"execution":{"iopub.status.busy":"2022-07-23T08:39:39.395029Z","iopub.execute_input":"2022-07-23T08:39:39.395929Z","iopub.status.idle":"2022-07-23T08:39:39.727602Z","shell.execute_reply.started":"2022-07-23T08:39:39.395887Z","shell.execute_reply":"2022-07-23T08:39:39.726250Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for feature in ['temp', 'atemp', 'windspeed', 'humidity'] : \n    sns.regplot(x = feature, y = 'count', data = train,scatter_kws = {'alpha' : 0.2}, line_kws={'color':'red'})\n    plt.xticks(rotation=45)\n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2022-07-23T08:39:39.729987Z","iopub.execute_input":"2022-07-23T08:39:39.730492Z","iopub.status.idle":"2022-07-23T08:39:43.643226Z","shell.execute_reply.started":"2022-07-23T08:39:39.730426Z","shell.execute_reply":"2022-07-23T08:39:43.641786Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"windspeed 부분이 상식에 벗어남. 교재에서는 삭제했음. \n풍속 단위가 궁금. 평균 18에 최대 57까지 기록 된 것으로 미뤄볼때, 시속으로 계산한 것 같음.\n그런 경우 50 이상인 경우 사실 걷기가 어려워서 특이값으로 볼 수도 있고 교재처럼 0이 너무 많아 삭제하는 것도 좋은 방법일 것 같음. ","metadata":{}},{"cell_type":"code","source":"# 피처 정리\ntrain = pd.read_csv(data_path + 'train.csv')\ntest = pd.read_csv(data_path + 'test.csv')\nall_data=pd.concat([train, test], ignore_index=True)\nall_data","metadata":{"execution":{"iopub.status.busy":"2022-07-23T08:39:43.645238Z","iopub.execute_input":"2022-07-23T08:39:43.645941Z","iopub.status.idle":"2022-07-23T08:39:43.718478Z","shell.execute_reply.started":"2022-07-23T08:39:43.645895Z","shell.execute_reply":"2022-07-23T08:39:43.717499Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"all_data['datetime'] = pd.to_datetime(all_data['datetime'])\nall_data['year'] = all_data['datetime'].dt.year\nall_data['month'] = all_data['datetime'].dt.month\nall_data['day'] = all_data['datetime'].dt.day\nall_data['hour'] = all_data['datetime'].dt.hour\n# all_data['minute'] = all_data['datetime'].dt.minute # 분초까지 하면 지나치게 학습될 것 같음\n# all_data['second'] = all_data['datetime'].dt.second\n# all_data['weekday'] = all_data['datetime'].dt.day_name() # 요일보다는 공휴일 유무에 영향을 받음\nall_data","metadata":{"execution":{"iopub.status.busy":"2022-07-23T08:39:43.719819Z","iopub.execute_input":"2022-07-23T08:39:43.720345Z","iopub.status.idle":"2022-07-23T08:39:43.770556Z","shell.execute_reply.started":"2022-07-23T08:39:43.720305Z","shell.execute_reply":"2022-07-23T08:39:43.769357Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"drop_features=['casual', 'registered', 'datetime', 'windspeed', 'month']\nall_data=all_data.drop(drop_features, axis=1)","metadata":{"execution":{"iopub.status.busy":"2022-07-23T08:39:43.772376Z","iopub.execute_input":"2022-07-23T08:39:43.773095Z","iopub.status.idle":"2022-07-23T08:39:43.784247Z","shell.execute_reply.started":"2022-07-23T08:39:43.773050Z","shell.execute_reply":"2022-07-23T08:39:43.783088Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# train, test 분류\nX_train=all_data[~pd.isnull(all_data['count'])]\nX_test=all_data[pd.isnull(all_data['count'])]\n\n# 아까 찾은 이상치 컬럼 찾기\nX_train.loc[(X_train['weather']==4)& (X_train['hour']==18)]","metadata":{"execution":{"iopub.status.busy":"2022-07-23T08:39:43.785754Z","iopub.execute_input":"2022-07-23T08:39:43.786937Z","iopub.status.idle":"2022-07-23T08:39:43.808398Z","shell.execute_reply.started":"2022-07-23T08:39:43.786887Z","shell.execute_reply":"2022-07-23T08:39:43.807024Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 이상치 제거\nindex_1=X_train.loc[(X_train['weather']==4)& (X_train['hour']==18)].index\n\nX_train=X_train.drop(index_1)\n\n#제거 확인\nX_train.loc[(X_train['weather']==4)& (X_train['hour']==18)]","metadata":{"execution":{"iopub.status.busy":"2022-07-23T08:39:43.810434Z","iopub.execute_input":"2022-07-23T08:39:43.811505Z","iopub.status.idle":"2022-07-23T08:39:43.830511Z","shell.execute_reply.started":"2022-07-23T08:39:43.811434Z","shell.execute_reply":"2022-07-23T08:39:43.829028Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 타깃값 분리\ny=train['count']\ny=y.drop(index_1)\nX_train=X_train.drop(['count'], axis=1)\nX_test=X_test.drop(['count'], axis=1)","metadata":{"execution":{"iopub.status.busy":"2022-07-23T08:39:43.831937Z","iopub.execute_input":"2022-07-23T08:39:43.832352Z","iopub.status.idle":"2022-07-23T08:39:43.844876Z","shell.execute_reply.started":"2022-07-23T08:39:43.832319Z","shell.execute_reply":"2022-07-23T08:39:43.843780Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"X_train.head()","metadata":{"execution":{"iopub.status.busy":"2022-07-23T08:39:43.846247Z","iopub.execute_input":"2022-07-23T08:39:43.847290Z","iopub.status.idle":"2022-07-23T08:39:43.866816Z","shell.execute_reply.started":"2022-07-23T08:39:43.847244Z","shell.execute_reply":"2022-07-23T08:39:43.865407Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"X_train.info()","metadata":{"execution":{"iopub.status.busy":"2022-07-23T08:39:43.868025Z","iopub.execute_input":"2022-07-23T08:39:43.868872Z","iopub.status.idle":"2022-07-23T08:39:43.886818Z","shell.execute_reply.started":"2022-07-23T08:39:43.868833Z","shell.execute_reply":"2022-07-23T08:39:43.885935Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import numpy as np\n\ndef rmsle(y_true, y_pred, convertExp=True):\n    # 지수변환\n    if convertExp:\n        y_true = np.exp(y_true)\n        y_pred = np.exp(y_pred)\n        \n    # 로그변환 후 결측값을 0으로 변환\n    log_true = np.nan_to_num(np.log(y_true+1))\n    log_pred = np.nan_to_num(np.log(y_pred+1))\n    \n    # RMSLE 계산\n    output = np.sqrt(np.mean((log_true - log_pred)**2))\n    return output","metadata":{"execution":{"iopub.status.busy":"2022-07-23T08:39:43.888097Z","iopub.execute_input":"2022-07-23T08:39:43.888860Z","iopub.status.idle":"2022-07-23T08:39:43.895562Z","shell.execute_reply.started":"2022-07-23T08:39:43.888826Z","shell.execute_reply":"2022-07-23T08:39:43.894505Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from sklearn.linear_model import LinearRegression\nlinear_model=LinearRegression()\nlog_y = np.log(y)\nlinear_model.fit(X_train, log_y)","metadata":{"execution":{"iopub.status.busy":"2022-07-23T08:39:43.900867Z","iopub.execute_input":"2022-07-23T08:39:43.901924Z","iopub.status.idle":"2022-07-23T08:39:43.917798Z","shell.execute_reply.started":"2022-07-23T08:39:43.901882Z","shell.execute_reply":"2022-07-23T08:39:43.916689Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"preds=linear_model.predict(X_train)\nprint(f'선형 회귀의 RMSLE :{rmsle(log_y, preds, True):4f}')","metadata":{"execution":{"iopub.status.busy":"2022-07-23T08:39:43.919714Z","iopub.execute_input":"2022-07-23T08:39:43.920778Z","iopub.status.idle":"2022-07-23T08:39:43.938779Z","shell.execute_reply.started":"2022-07-23T08:39:43.920729Z","shell.execute_reply":"2022-07-23T08:39:43.936189Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from sklearn.linear_model import Ridge\nfrom sklearn.model_selection import GridSearchCV\nfrom sklearn import metrics\nfrom sklearn.ensemble import RandomForestRegressor\n\n# 교차 검증용 평가 함수(RMSLE 점수 계산)\nrmsle_scorer = metrics.make_scorer(rmsle, greater_is_better=False)\n\n# 모델 생성\nrandomforest_model = RandomForestRegressor()\n# 그리드서치 객체 생성\nrf_params = {'random_state':[42], 'n_estimators':[100, 120, 140]}\ngridsearch_random_forest_model = GridSearchCV(estimator=randomforest_model,\n                                              param_grid=rf_params,\n                                              scoring=rmsle_scorer,\n                                              cv=5)\n# 그리드서치 수행\nlog_y = np.log(y)\ngridsearch_random_forest_model.fit(X_train, log_y)\n\nprint('최적 하이퍼파라미터 :', gridsearch_random_forest_model.best_params_)","metadata":{"execution":{"iopub.status.busy":"2022-07-23T08:39:43.945652Z","iopub.execute_input":"2022-07-23T08:39:43.947888Z","iopub.status.idle":"2022-07-23T08:40:35.420603Z","shell.execute_reply.started":"2022-07-23T08:39:43.947824Z","shell.execute_reply":"2022-07-23T08:40:35.419639Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 예측\npreds = gridsearch_random_forest_model.best_estimator_.predict(X_train)\n\n# 평가\nprint(f'랜덤 포레스트 회귀 RMSLE 값 : {rmsle(log_y, preds, True):.4f}')","metadata":{"execution":{"iopub.status.busy":"2022-07-23T08:40:35.422096Z","iopub.execute_input":"2022-07-23T08:40:35.422694Z","iopub.status.idle":"2022-07-23T08:40:35.654069Z","shell.execute_reply.started":"2022-07-23T08:40:35.422660Z","shell.execute_reply":"2022-07-23T08:40:35.652941Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 제출전 확인\nrandomforest_preds = gridsearch_random_forest_model.best_estimator_.predict(X_test)\n\nfigure, axes = plt.subplots(ncols=2)\nfigure.set_size_inches(10, 4)\n\nsns.histplot(y, bins=50, ax=axes[0])\naxes[0].set_title('Train Data Distribution')\nsns.histplot(np.exp(randomforest_preds), bins=50, ax=axes[1])\naxes[1].set_title('Predicted Test Data Distribution');\n\n# 모델 속성 중요도\nrandomforest_model = RandomForestRegressor(random_state=42)\nrandomforest_model.fit(X_train, log_y)\nimportances=randomforest_model.feature_importances_\nindices_sorted=np.argsort(importances)\nplt.figure()\nplt.title(\"Feature importances\")\nplt.bar(range(len(importances)), importances[indices_sorted])\nplt.xticks(range(len(importances)), X_train.columns[indices_sorted], rotation=90)\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-07-23T08:40:35.655503Z","iopub.execute_input":"2022-07-23T08:40:35.655851Z","iopub.status.idle":"2022-07-23T08:40:39.818604Z","shell.execute_reply.started":"2022-07-23T08:40:35.655813Z","shell.execute_reply":"2022-07-23T08:40:39.817275Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 제출 파일\nsubmission = pd.read_csv(data_path + 'sampleSubmission.csv')\nsubmission['count'] = np.exp(randomforest_preds) # 지수변환\nsubmission.to_csv('submission.csv', index=False)","metadata":{"execution":{"iopub.status.busy":"2022-07-23T08:40:39.820150Z","iopub.execute_input":"2022-07-23T08:40:39.820531Z","iopub.status.idle":"2022-07-23T08:40:39.866077Z","shell.execute_reply.started":"2022-07-23T08:40:39.820494Z","shell.execute_reply":"2022-07-23T08:40:39.865037Z"},"trusted":true},"execution_count":null,"outputs":[]}]}