데이콘 Basic 풍속 예측 AI 경진대회
- https://dacon.io/competitions/official/236126/data
- 57920개의 데이터
- ID : 샘플 별 고유 id
- 월: 데이터가 기록된 달을 나타냅니다.
- 일: 데이터가 기록된 날짜를 나타냅니다.
- 측정 시간대: 데이터가 측정된 시간대를 나타냅니다. 오전, 오후, 저녁, 새벽으로 구분되어 있습니다.
- 섭씨 온도 (° C)
- 절대 온도 (K)
- 이슬점 온도 (° C)
- 상대 습도 (%)
- 대기압 (mbar)
- 포화 증기압 (mbar)
- 실제 증기압 (mbar)
- 증기압 부족량 (mbar)
- 수증기 함량 (g/kg): 공기 1 kg당 수증기의 질량을 그램(g) 단위로 나타냅니다.
- 공기 밀도 (g/m**3): 1 m³의 부피에 들어있는 공기의 질량을 그램(g) 단위로 나타냅니다.
- 풍향 (deg): 바람의 향하는 방향을 각도(degree)로 나타냅니다.
- 풍속 (m/s): target값
라이브러리 정의
In [ ]:
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
import warnings
warnings.filterwarnings('ignore')
import os
import random
from scipy.stats import skew
from sklearn.preprocessing import LabelEncoder
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LinearRegression
from lightgbm import LGBMRegressor
from xgboost import XGBRegressor
#from autogluon.tabular import TabularDataset, TabularPredictor
#import autogluon.core as ag
In [ ]:
def seed_everything(seed):
random.seed(seed)
os.environ['PYTHONHASHSEED'] = str(seed)
np.random.seed(seed)
seed_everything(42) # Seed 고정
데이터 불러오기, 탐색
In [ ]:
train = pd.read_csv('/content/train.csv')
test = pd.read_csv('/content/test.csv')
In [ ]:
train.head()
Out[ ]:
ID | 월 | 일 | 측정 시간대 | 섭씨 온도(°C) | 절대 온도(K) | 이슬점 온도(°C) | 상대 습도 (%) | 대기압(mbar) | 포화 증기압(mbar) | 실제 증기압(mbar) | 증기압 부족량(mbar) | 수증기 함량 (g/kg) | 공기 밀도 (g/m**3) | 풍향 (deg) | 풍속 (m/s) | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | TRAIN_00000 | 7 | 2 | 저녁 | 13.97 | 287.78 | 9.84 | 76.1 | 992.08 | 15.98 | 12.16 | 3.82 | 7.66 | 1198.06 | 155.60 | 1.61 |
1 | TRAIN_00001 | 8 | 21 | 오전 | 16.94 | 290.85 | 12.14 | 73.3 | 991.07 | 19.33 | 14.17 | 5.16 | 8.94 | 1183.67 | 177.00 | 1.68 |
2 | TRAIN_00002 | 11 | 1 | 저녁 | 9.76 | 283.84 | 5.40 | 74.2 | 988.71 | 12.10 | 8.98 | 3.12 | 5.67 | 1213.22 | 146.20 | 0.73 |
3 | TRAIN_00003 | 12 | 28 | 오전 | 5.27 | 277.30 | 2.71 | 83.5 | 1014.25 | 8.89 | 7.43 | 1.47 | 4.57 | 1265.48 | 264.50 | 2.71 |
4 | TRAIN_00004 | 9 | 26 | 오후 | 17.35 | 290.86 | 12.68 | 74.0 | 995.77 | 19.84 | 14.68 | 5.16 | 9.22 | 1187.40 | 19.34 | 1.00 |
In [ ]:
train.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 36581 entries, 0 to 36580
Data columns (total 16 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 ID 36581 non-null object
1 월 36581 non-null int64
2 일 36581 non-null int64
3 측정 시간대 36581 non-null object
4 섭씨 온도(°C) 36581 non-null float64
5 절대 온도(K) 36581 non-null float64
6 이슬점 온도(°C) 36581 non-null float64
7 상대 습도 (%) 36581 non-null float64
8 대기압(mbar) 36581 non-null float64
9 포화 증기압(mbar) 36581 non-null float64
10 실제 증기압(mbar) 36581 non-null float64
11 증기압 부족량(mbar) 36581 non-null float64
12 수증기 함량 (g/kg) 36581 non-null float64
13 공기 밀도 (g/m**3) 36581 non-null float64
14 풍향 (deg) 36581 non-null float64
15 풍속 (m/s) 36581 non-null float64
dtypes: float64(12), int64(2), object(2)
memory usage: 4.5+ MB
In [ ]:
test.head()
Out[ ]:
ID | 월 | 일 | 측정 시간대 | 섭씨 온도(°C) | 절대 온도(K) | 이슬점 온도(°C) | 상대 습도 (%) | 대기압(mbar) | 포화 증기압(mbar) | 실제 증기압(mbar) | 증기압 부족량(mbar) | 수증기 함량 (g/kg) | 공기 밀도 (g/m**3) | 풍향 (deg) | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | TEST_00000 | 3 | 24 | 새벽 | 4.28 | 278.68 | -0.21 | 72.5 | 984.48 | 8.30 | 6.02 | 2.28 | 3.81 | 1233.29 | 251.80 |
1 | TEST_00001 | 9 | 24 | 저녁 | 13.40 | 286.81 | 10.36 | 81.8 | 996.98 | 15.40 | 12.59 | 2.80 | 7.89 | 1206.20 | 225.60 |
2 | TEST_00002 | 5 | 28 | 저녁 | 19.89 | 294.33 | 14.95 | 73.2 | 984.83 | 23.26 | 17.03 | 6.23 | 10.82 | 1163.06 | 10.39 |
3 | TEST_00003 | 1 | 17 | 저녁 | -2.88 | 270.44 | -4.47 | 88.7 | 998.02 | 4.94 | 4.38 | 0.56 | 2.73 | 1284.19 | 260.20 |
4 | TEST_00004 | 10 | 22 | 오후 | 6.97 | 281.18 | 4.36 | 83.4 | 987.00 | 10.01 | 8.35 | 1.66 | 5.28 | 1223.47 | 262.50 |
In [ ]:
test.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 15678 entries, 0 to 15677
Data columns (total 15 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 ID 15678 non-null object
1 월 15678 non-null int64
2 일 15678 non-null int64
3 측정 시간대 15678 non-null object
4 섭씨 온도(°C) 15678 non-null float64
5 절대 온도(K) 15678 non-null float64
6 이슬점 온도(°C) 15678 non-null float64
7 상대 습도 (%) 15678 non-null float64
8 대기압(mbar) 15678 non-null float64
9 포화 증기압(mbar) 15678 non-null float64
10 실제 증기압(mbar) 15678 non-null float64
11 증기압 부족량(mbar) 15678 non-null float64
12 수증기 함량 (g/kg) 15678 non-null float64
13 공기 밀도 (g/m**3) 15678 non-null float64
14 풍향 (deg) 15678 non-null float64
dtypes: float64(11), int64(2), object(2)
memory usage: 1.8+ MB
train, test 모두 결측치 없음
In [ ]:
train.describe()
Out[ ]:
월 | 일 | 섭씨 온도(°C) | 절대 온도(K) | 이슬점 온도(°C) | 상대 습도 (%) | 대기압(mbar) | 포화 증기압(mbar) | 실제 증기압(mbar) | 증기압 부족량(mbar) | 수증기 함량 (g/kg) | 공기 밀도 (g/m**3) | 풍향 (deg) | 풍속 (m/s) | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
count | 36581.000000 | 36581.000000 | 36581.000000 | 36581.000000 | 36581.000000 | 36581.000000 | 36581.000000 | 36581.000000 | 36581.000000 | 36581.000000 | 36581.000000 | 36581.000000 | 36581.00000 | 36581.000000 |
mean | 6.511468 | 15.648561 | 9.992694 | 283.971095 | 5.453064 | 75.827418 | 990.032953 | 14.037167 | 9.786895 | 4.250224 | 6.178010 | 1214.580682 | 176.58240 | 2.036446 |
std | 3.458678 | 8.803467 | 8.237177 | 8.354235 | 6.327009 | 16.089188 | 8.824477 | 8.075680 | 4.185701 | 5.191128 | 2.655054 | 39.528520 | 84.38269 | 1.544146 |
min | 1.000000 | 1.000000 | -13.930000 | 258.870000 | -15.560000 | 23.640000 | 956.890000 | 2.070000 | 1.810000 | 0.000000 | 1.120000 | 1110.650000 | 0.01000 | 0.100000 |
25% | 4.000000 | 8.000000 | 3.650000 | 277.700000 | 0.450000 | 65.360000 | 985.100000 | 7.940000 | 6.310000 | 0.950000 | 3.980000 | 1184.030000 | 129.40000 | 0.920000 |
50% | 7.000000 | 16.000000 | 9.130000 | 283.170000 | 5.070000 | 79.000000 | 990.250000 | 11.590000 | 8.770000 | 2.250000 | 5.520000 | 1214.650000 | 199.50000 | 1.630000 |
75% | 9.000000 | 23.000000 | 16.350000 | 290.370000 | 10.950000 | 89.200000 | 995.700000 | 18.620000 | 13.100000 | 5.410000 | 8.270000 | 1241.600000 | 233.90000 | 2.700000 |
max | 12.000000 | 31.000000 | 34.340000 | 308.620000 | 20.150000 | 100.000000 | 1015.300000 | 54.270000 | 23.640000 | 41.230000 | 14.980000 | 1349.460000 | 360.00000 | 11.890000 |
In [ ]:
train.corr()
Out[ ]:
월 | 일 | 섭씨 온도(°C) | 절대 온도(K) | 이슬점 온도(°C) | 상대 습도 (%) | 대기압(mbar) | 포화 증기압(mbar) | 실제 증기압(mbar) | 증기압 부족량(mbar) | 수증기 함량 (g/kg) | 공기 밀도 (g/m**3) | 풍향 (deg) | 풍속 (m/s) | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
월 | 1.000000 | -0.004106 | 0.150799 | 0.113863 | 0.225914 | 0.086025 | 0.414791 | 0.138394 | 0.210962 | 0.045196 | 0.204353 | -0.028760 | 0.009146 | -0.186495 |
일 | -0.004106 | 1.000000 | 0.036927 | 0.022892 | 0.034864 | -0.021352 | 0.160538 | 0.050455 | 0.051187 | 0.037222 | 0.048915 | 0.011268 | 0.044461 | 0.031513 |
섭씨 온도(°C) | 0.150799 | 0.036927 | 1.000000 | 0.996372 | 0.896195 | -0.624135 | -0.094014 | 0.962549 | 0.877030 | 0.790244 | 0.876737 | -0.958652 | 0.016658 | 0.098497 |
절대 온도(K) | 0.113863 | 0.022892 | 0.996372 | 1.000000 | 0.893198 | -0.622665 | -0.178365 | 0.956424 | 0.872587 | 0.784298 | 0.873683 | -0.979099 | 0.022562 | 0.114711 |
이슬점 온도(°C) | 0.225914 | 0.034864 | 0.896195 | 0.893198 | 1.000000 | -0.222133 | -0.087869 | 0.812883 | 0.981239 | 0.473384 | 0.980871 | -0.875042 | 0.016848 | -0.048942 |
상대 습도 (%) | 0.086025 | -0.021352 | -0.624135 | -0.622665 | -0.222133 | 1.000000 | 0.067025 | -0.659667 | -0.212495 | -0.854891 | -0.212696 | 0.577811 | -0.027953 | -0.321123 |
대기압(mbar) | 0.414791 | 0.160538 | -0.094014 | -0.178365 | -0.087869 | 0.067025 | 1.000000 | -0.058629 | -0.067328 | -0.036927 | -0.083381 | 0.370414 | -0.071336 | -0.200326 |
포화 증기압(mbar) | 0.138394 | 0.050455 | 0.962549 | 0.956424 | 0.812883 | -0.659667 | -0.058629 | 1.000000 | 0.825225 | 0.890279 | 0.824863 | -0.904433 | -0.012436 | 0.093631 |
실제 증기압(mbar) | 0.210962 | 0.051187 | 0.877030 | 0.872587 | 0.981239 | -0.212495 | -0.067328 | 0.825225 | 1.000000 | 0.477460 | 0.999841 | -0.848729 | 0.004169 | -0.073563 |
증기압 부족량(mbar) | 0.045196 | 0.037222 | 0.790244 | 0.784298 | 0.473384 | -0.854891 | -0.036927 | 0.890279 | 0.477460 | 1.000000 | 0.477025 | -0.722655 | -0.022698 | 0.204976 |
수증기 함량 (g/kg) | 0.204353 | 0.048915 | 0.876737 | 0.873683 | 0.980871 | -0.212696 | -0.083381 | 0.824863 | 0.999841 | 0.477025 | 1.000000 | -0.852909 | 0.005186 | -0.070159 |
공기 밀도 (g/m**3) | -0.028760 | 0.011268 | -0.958652 | -0.979099 | -0.875042 | 0.577811 | 0.370414 | -0.904433 | -0.848729 | -0.722655 | -0.852909 | 1.000000 | -0.038151 | -0.140572 |
풍향 (deg) | 0.009146 | 0.044461 | 0.016658 | 0.022562 | 0.016848 | -0.027953 | -0.071336 | -0.012436 | 0.004169 | -0.022698 | 0.005186 | -0.038151 | 1.000000 | -0.053000 |
풍속 (m/s) | -0.186495 | 0.031513 | 0.098497 | 0.114711 | -0.048942 | -0.321123 | -0.200326 | 0.093631 | -0.073563 | 0.204976 | -0.070159 | -0.140572 | -0.053000 | 1.000000 |
풍속과 유의미한 상관성을 보이는 피처가 없음
EDA
In [ ]:
!sudo apt-get install -y fonts-nanum
!sudo fc-cache -fv
!rm ~/.cache/matplotlib -rf
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following NEW packages will be installed:
fonts-nanum
0 upgraded, 1 newly installed, 0 to remove and 8 not upgraded.
Need to get 10.3 MB of archives.
After this operation, 34.1 MB of additional disk space will be used.
Get:1 http://archive.ubuntu.com/ubuntu jammy/universe amd64 fonts-nanum all 20200506-1 [10.3 MB]
Fetched 10.3 MB in 1s (8,597 kB/s)
debconf: unable to initialize frontend: Dialog
debconf: (No usable dialog-like program is installed, so the dialog based frontend cannot be used. at /usr/share/perl5/Debconf/FrontEnd/Dialog.pm line 78, <> line 1.)
debconf: falling back to frontend: Readline
debconf: unable to initialize frontend: Readline
debconf: (This frontend requires a controlling tty.)
debconf: falling back to frontend: Teletype
dpkg-preconfigure: unable to re-open stdin:
Selecting previously unselected package fonts-nanum.
(Reading database ... 120493 files and directories currently installed.)
Preparing to unpack .../fonts-nanum_20200506-1_all.deb ...
Unpacking fonts-nanum (20200506-1) ...
Setting up fonts-nanum (20200506-1) ...
Processing triggers for fontconfig (2.13.1-4.2ubuntu5) ...
/usr/share/fonts: caching, new cache contents: 0 fonts, 1 dirs
/usr/share/fonts/truetype: caching, new cache contents: 0 fonts, 3 dirs
/usr/share/fonts/truetype/humor-sans: caching, new cache contents: 1 fonts, 0 dirs
/usr/share/fonts/truetype/liberation: caching, new cache contents: 16 fonts, 0 dirs
/usr/share/fonts/truetype/nanum: caching, new cache contents: 12 fonts, 0 dirs
/usr/local/share/fonts: caching, new cache contents: 0 fonts, 0 dirs
/root/.local/share/fonts: skipping, no such directory
/root/.fonts: skipping, no such directory
/usr/share/fonts/truetype: skipping, looped directory detected
/usr/share/fonts/truetype/humor-sans: skipping, looped directory detected
/usr/share/fonts/truetype/liberation: skipping, looped directory detected
/usr/share/fonts/truetype/nanum: skipping, looped directory detected
/var/cache/fontconfig: cleaning cache directory
/root/.cache/fontconfig: not cleaning non-existent cache directory
/root/.fontconfig: not cleaning non-existent cache directory
fc-cache: succeeded
In [ ]:
plt.rc('font', family='NanumBarunGothic')
In [ ]:
time = train['측정 시간대'].value_counts()
sns.barplot(y=time.values, x=time.index)
Out[ ]:
<Axes: >
In [ ]:
month = train['월'].value_counts()
sns.barplot(x=month.index, y=month.values)
Out[ ]:
<Axes: >
In [ ]:
day = train['일'].value_counts()
sns.barplot(y=day.values, x = day.index.sort_values())
Out[ ]:
<Axes: >
In [ ]:
sns.scatterplot(data=train, y='섭씨 온도(°C)', x='풍속 (m/s)')
Out[ ]:
<Axes: xlabel='풍속 (m/s)', ylabel='섭씨 온도(°\u2063C)'>
In [ ]:
sns.scatterplot(data=train, y='절대 온도(K)', x='풍속 (m/s)')
Out[ ]:
<Axes: xlabel='풍속 (m/s)', ylabel='절대 온도(K)'>
In [ ]:
sns.scatterplot(data=train, y='이슬점 온도(°C)', x='풍속 (m/s)')
Out[ ]:
<Axes: xlabel='풍속 (m/s)', ylabel='이슬점 온도(°C)'>
In [ ]:
sns.scatterplot(data=train, y='상대 습도 (%)', x='풍속 (m/s)')
Out[ ]:
<Axes: xlabel='풍속 (m/s)', ylabel='상대 습도 (%)'>
In [ ]:
sns.scatterplot(data=train, y='대기압(mbar)', x='풍속 (m/s)')
Out[ ]:
<Axes: xlabel='풍속 (m/s)', ylabel='대기압(mbar)'>
In [ ]:
sns.scatterplot(data=train, y='포화 증기압(mbar)', x='풍속 (m/s)')
Out[ ]:
<Axes: xlabel='풍속 (m/s)', ylabel='포화 증기압(mbar)'>
In [ ]:
sns.scatterplot(data=train, y='실제 증기압(mbar)', x='풍속 (m/s)')
Out[ ]:
<Axes: xlabel='풍속 (m/s)', ylabel='실제 증기압(mbar)'>
In [ ]:
sns.scatterplot(data=train, y='실제 증기압(mbar)', x='풍속 (m/s)')
Out[ ]:
<Axes: xlabel='풍속 (m/s)', ylabel='실제 증기압(mbar)'>
In [ ]:
sns.scatterplot(data=train, y='수증기 함량 (g/kg)', x='풍속 (m/s)')
Out[ ]:
<Axes: xlabel='풍속 (m/s)', ylabel='수증기 함량 (g/kg)'>
In [ ]:
sns.scatterplot(data=train, y='공기 밀도 (g/m**3)', x='풍속 (m/s)')
Out[ ]:
<Axes: xlabel='풍속 (m/s)', ylabel='공기 밀도 (g/m**3)'>
In [ ]:
sns.scatterplot(data=train, y='풍향 (deg)', x='풍속 (m/s)')
Out[ ]:
<Axes: xlabel='풍속 (m/s)', ylabel='풍향 (deg)'>
타겟값인 '풍속 (m/s)'와 이슬점 온도(°C), 상대 습도 (%), 대기압(mbar), 포화 증기압(mbar), 실제 증기압(mbar), 증기압 부족량(mbar), 수증기 함량 (g/kg), 공기 밀도 (g/m**3), 풍향 (deg)의 산점도는 비슷한 모양을 띈다.
이상치라고 할만한 데이터는 없다고 판단
전처리
- 타겟값 분포도 살펴보기 → 로그 변환
In [ ]:
sns.histplot(train['풍속 (m/s)'], kde=True)
Out[ ]:
<Axes: xlabel='풍속 (m/s)', ylabel='Count'>
In [ ]:
log = np.log1p(train['풍속 (m/s)'])
sns.histplot(log, kde=True)
Out[ ]:
<Axes: xlabel='풍속 (m/s)', ylabel='Count'>
- 숫자형 피처들 분포도 살펴보기 → 왜곡 정도가 높은 피처들 로그 변환
In [ ]:
features = train.dtypes[train.dtypes != 'object'].index
skew_features = train[features].apply(lambda x : skew(x))
#skew 정도가 1 이상인 칼럼만 추출
skew_features_top = skew_features[skew_features > 1]
print(skew_features_top.sort_values(ascending=False))
증기압 부족량(mbar) 2.374898
풍속 (m/s) 1.624866
포화 증기압(mbar) 1.287343
dtype: float64
In [ ]:
train[skew_features_top.index] = np.log1p(train[skew_features_top.index])
In [ ]:
features2 = test.dtypes[test.dtypes != 'object'].index
skew_features2 = test[features2].apply(lambda x : skew(x))
#skew 정도가 1 이상인 칼럼만 추출
skew_features_top2 = skew_features2[skew_features2 > 1]
print(skew_features_top2.sort_values(ascending=False))
증기압 부족량(mbar) 2.280276
포화 증기압(mbar) 1.252155
dtype: float64
In [ ]:
test[skew_features_top2.index] = np.log1p(test[skew_features_top2.index])
- object형 피처 라벨 인코딩
In [ ]:
col = ['측정 시간대']
for i in col:
encoder = LabelEncoder()
encoder.fit(train[i])
train[i] = encoder.transform(train[i])
for i in col:
encoder = LabelEncoder()
encoder.fit(test[i])
test[i] = encoder.transform(test[i])
- StandardScaler 표준 정규화 → 데이터셋에 이상치가 있다면 적절하지 않지만 별다른 이상치가 있다고 판단하지 않았으므로 적용
In [ ]:
#데이터 나누고 정규화하자
X_train = train.drop(['ID', '풍속 (m/s)'], axis=1)
y_train = train['풍속 (m/s)']
X_test = test.drop('ID', axis=1)
In [ ]:
scaler = StandardScaler()
scaler.fit(X_train)
train_scaled = scaler.transform(X_train)
In [ ]:
#스케일링 전에 훈련용 데이터 분포
plt.hist(X_train, bins=30, alpha=0.7)
plt.title('Before Data Scaling')
plt.show()
In [ ]:
#스케일링 후 훈련용 데이터 분포
plt.hist(train_scaled, bins=30, alpha=0.7, density=True)
plt.title('After Data Scaling')
plt.show()
그래프가 0을 중심으로 정규 분포 모양
In [ ]:
scaler.fit(X_test)
test_scaled = scaler.transform(X_test)
In [ ]:
#스케일링 전에 테스트용 데이터 분포
plt.hist(X_test, bins=30, alpha=0.7)
plt.title('Before Data Scaling')
plt.show()
In [ ]:
#스케일링 후 테스트용 데이터 분포
plt.hist(test_scaled, bins=30, alpha=0.7, density=True)
plt.title('After Data Scaling')
plt.show()
'Data Science > Dacon' 카테고리의 다른 글
[회귀] 데이콘 Basic 풍속 예측 AI 경진대회 (2) - 모델링 1~4(회귀 트리, 선형 회귀, AutoGluon) (0) | 2023.08.02 |
---|---|
[회귀] 자동차 가격 예측 AI 경진대회 (2) - AutoML 라이브러리 AutoGluon (0) | 2023.07.03 |
[회귀] 자동차 가격 예측 AI 경진대회 (1) - 데이터 불러오기, 간단 EDA (0) | 2023.07.03 |
[회귀] 감귤 착과량 예측 AI 경진대회 (0) | 2023.06.14 |
[분류] 유전체 정보 품종 분류 AI 경진대회 (2) - AutoML을 이용한 모델링 3가지 (0) | 2023.06.13 |