서울시의 공공자전거 대여 서비스인 ‘따릉이’의 대여 수요를 예측하는 문제에 사용되는 데이터셋입니다. 특정 시간대와 날씨, 요일, 공휴일 여부, 기온, 습도 등 다양한 데이터를 활용하여 자전거 대여 수요를 예측합니다.
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
bike_df = pd.read_csv('/본인의 구글드라이브 경로/SeoulBikeData.csv', encoding='CP949')
bike_df
※ CP949
bike_df.info()
bike_df.describe()
bike_df.columns
bike_df.columns = ['Date', 'Rented Bike Count', 'Hour', 'Temperature', 'Humidity',
'Wind speed', 'Visibility', 'Dew point temperature',
'Solar Radiation', 'Rainfall', 'Snowfall', 'Seasons',
'Holiday', 'Functioning Day']
bike_df.head()
sns.scatterplot(x='Temperature', y='Rented Bike Count', data=bike_df, alpha=0.3)
sns.scatterplot(x='Wind speed', y='Rented Bike Count', data=bike_df, alpha=0.3)
sns.scatterplot(x='Visibility', y='Rented Bike Count', data=bike_df, alpha=0.3)
sns.scatterplot(x='Hour', y='Rented Bike Count', data=bike_df, alpha=0.3)
bike_df.isna().sum()
bike_df.info()
bike_df['Date'] = pd.to_datetime(bike_df['Date'], format='%d/%m/%Y')
bike_df.info()
bike_df['year'] = bike_df['Date'].dt.year
bike_df['month'] = bike_df['Date'].dt.month
bike_df['day'] = bike_df['Date'].dt.day
bike_df.head()
plt.figure(figsize=(14, 4))
sns.lineplot(x='Date', y='Rented Bike Count', data=bike_df)
plt.xticks(rotation=45)
plt.show()
bike_df[bike_df['year'] == 2017].groupby('month')['Rented Bike Count'].mean()
bike_df[bike_df['year'] == 2018].groupby('month')['Rented Bike Count'].mean()
bike_df['TimeOfDay'] = pd.cut(bike_df['Hour'],
bins=[0, 5, 11, 17, 23],
labels=['Dawn', 'Morning', 'Afternoon', 'Evening'],
include_lowest=True)
※ pd.cut()
pd.cut()은 숫자 데이터를 구간(bins)으로 나누어 범주형 데이터로 변환하는 데 사용됩니다. 주로 연속형 데이터를 특정 범주로 분류할 때 활용됩니다.
| 0 ≤ Hour ≤ 5 | Dawn (새벽) |
| 5 < Hour ≤ 11 | Morning (아침) |
| 11 < Hour ≤ 17 | Afternoon (오후) |
| 17 < Hour ≤ 23 | Evening (저녁) |
bike_df.head()
sns.barplot(x='Functioning Day', y='Rented Bike Count', data=bike_df)
Seaborn의 barplot은 범주형 데이터(x)에 대해 수치형 데이터(y)의 통계 요약값을 계산하여 막대로 시각화하는 그래프로, 기본적으로 각 범주별 평균(mean)을 사용하며 평균의 불확실성을 나타내는 신뢰구간(error bar)을 함께 표시합니다. 내부적으로는 groupby와 집계 과정을 자동으로 수행하여 원본 데이터의 개수와 상관없이 범주 수만큼의 막대가 생성되며, estimator 옵션을 통해 평균 대신 합계·중앙값·개수 등으로 변경할 수 있고, hue를 사용하면 추가 범주에 따른 비교도 가능합니다. 즉, seaborn barplot은 값 자체가 아니라 집단 간 통계적 대표값을 비교하기 위한 시각화 도구입니다.
※ Seaborn의 barplot 을 읽는 법
1) 먼저 “막대가 뭘 뜻하는지”부터 확인합니다. Seaborn barplot의 막대 높이는 기본적으로 평균(mean) 입니다.
따라서 “막대가 높다” = 그 범주의 평균이 크다 입니다. (원본 데이터의 한 개 값이 아니라, “집단의 대표값”입니다.)
2) 축을 읽어 “무엇을 비교하는지”를 정합니다
3) 막대끼리 비교할 때는 “차이의 크기”를 봅니다. 막대의 높이 차이를 보고 해석합니다.
“평균이 비슷해도 데이터가 들쑥날쑥할 수 있다” → 그걸 보는 게 에러바입니다.
4) 에러바(error bar)는 “그 평균이 얼마나 믿을 만한지/흔들리는지”입니다. Seaborn barplot은 보통 막대 위아래에 선(에러바)가 그려집니다. 이 에러바는 설정에 따라 의미가 달라질 수 있지만(기본은 신뢰구간), 읽는 법은 공통입니다.
bike_df['Functioning Day'].value_counts()
bike_df[bike_df['Functioning Day'] == 'Yes']
bike_df[bike_df['Functioning Day'] == 'No']
bike_df.info()
bike_df = bike_df.drop('Date', axis=1)
bike_df.head()
bike_df.select_dtypes(exclude=['number']).columns.tolist()
for i in bike_df.select_dtypes(exclude=['number']).columns.tolist():
print(i, bike_df[i].nunique())
bike_df = pd.get_dummies(bike_df, columns=bike_df.select_dtypes(exclude=['number']).columns.tolist(), drop_first=True)
bike_df.head()
# 모든 컬럼 간 상관관계 분석
correlation_matrix = bike_df.corr()
# 목표 변수와의 상관관계만 확인
target_corr = correlation_matrix['Rented Bike Count'].sort_values(ascending=False)
print(target_corr)
※ corr() 함수
corr() 함수는 데이터프레임의 숫자형 열 간의 상관관계를 계산하는 데 사용됩니다. 상관관계는 두 변수 간의 선형 관계를 나타내며, 주로 -1에서 1 사이의 값으로 표현됩니다.
corr()를 사용하여 높은 상관관계를 가진 컬럼을 식별하고 제거할지 여부를 판단할 수 있습니다. 특히, 다중공선성(multicollinearity) 문제가 발생할 경우 머신러닝 모델의 성능이 저하될 수 있으므로, 상관관계가 높은 컬럼을 적절히 제거하는 것이 중요합니다.
※ 다중공선성
다중공선성(Multicollinearity)은 회귀 분석에서 독립 변수들(설명 변수) 간에 강한 상관관계가 존재하는 현상을 의미합니다. 이러한 상관관계가 높으면 각 독립 변수가 종속 변수에 미치는 개별적인 영향을 정확하게 추정하기 어려워지며, 회귀 계수의 추정치가 불안정해져 작은 데이터 변화에도 크게 변할 수 있습니다. 이는 모델의 예측 성능 저하와 해석의 신뢰성 감소로 이어질 수 있으므로, 다중공선성이 높은 변수를 식별하고 제거하거나 조정하는 것이 중요합니다.
plt.figure(figsize=(16, 12))
sns.heatmap(correlation_matrix, annot=True, fmt='.2f', cmap='coolwarm')
plt.title('Feature Correlation Heatmap')
plt.show()
bike_df = bike_df.drop(['Dew point temperature'], axis=1)
bike_df.head()
bike_df.info()
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(bike_df.drop('Rented Bike Count', axis=1), bike_df['Rented Bike Count'], test_size=0.3, random_state=2025)
X_train.shape, y_train.shape
X_test.shape, y_test.shape
결정 트리(Decision Tree)는 데이터를 기반으로 의사결정을 수행하는 트리 구조의 예측 모델입니다. 루트 노드(root node)에서 시작해 각 노드는 특정 특성(feature)의 조건에 따라 가지(branch)로 분기되며, 최종적으로 리프 노드(leaf node)에 도달해 예측 결과(클래스나 값)를 도출합니다. 주로 분류(Classification)와 회귀(Regression) 문제에 사용되며, 데이터의 패턴을 직관적으로 시각화할 수 있어 해석이 용이합니다. 하지만 트리가 너무 깊어지면 과적합(overfitting) 문제가 발생할 수 있으므로 가지치기(pruning)나 최대 깊이 설정 등으로 제어해야 합니다.
※ Gini 불순도 (Gini Impurity)
※ 엔트로피 (Entropy)
from sklearn.tree import DecisionTreeRegressor
dtr = DecisionTreeRegressor(random_state=2025)
dtr.fit(X_train, y_train)
pred1 = dtr.predict(X_test)
sns.scatterplot(x=y_test, y=pred1)
※ DecisionTreeRegressor
DecisionTreeRegressor는 주어진 데이터를 반복적으로 분할하여 예측을 수행합니다. 각 분할은 데이터의 목표 변수 값을 예측하는 데 가장 적합한 값을 찾기 위해 이루어집니다. 이를 통해 데이터를 점차 더 작은 부분으로 나누고, 각 부분에서 평균값을 예측값으로 사용하는 방식입니다. DecisionTreeRegressor 데이터를 두 가지 그룹으로 분할합니다. 각 분할에서 목표는 두 그룹의 MSE가 가능한 한 낮도록 만드는 것입니다. 즉, 각 분할에서의 MSE가 최소화되도록 분할점을 찾습니다.



from sklearn.metrics import root_mean_squared_error
root_mean_squared_error(y_test, pred1)
from sklearn.linear_model import LinearRegression
lr = LinearRegression()
lr.fit(X_train, y_train)
pred2 = lr.predict(X_test)
sns.scatterplot(x=y_test, y=pred2)
root_mean_squared_error(y_test, pred2)
# 하이퍼 파라미터 적용
dtr = DecisionTreeRegressor(random_state=2025, max_depth=50, min_samples_leaf=30)
dtr.fit(X_train, y_train)
pred3 = dtr.predict(X_test)
root_mean_squared_error(y_test, pred3)
from sklearn.tree import plot_tree
plt.figure(figsize=(24, 12))
plot_tree(dtr, max_depth=5, fontsize=10, feature_names=X_train.columns)
plt.show()
from sklearn.ensemble import RandomForestRegressor
rf = RandomForestRegressor(random_state=2025)
rf.fit(X_train, y_train)
pred4 = rf.predict(X_test)
root_mean_squared_error(y_test, pred4)
rf.feature_importances_
feature_imp = pd.DataFrame({
'features': X_train.columns,
'importances': rf.feature_importances_
})
feature_imp
top10 = feature_imp.sort_values('importances', ascending=False).head(10)
top10
plt.figure(figsize=(5, 10))
sns.barplot(x='importances', y='features', data=top10)| 슈퍼스토어 마케팅 캠페인 데이터셋 (1) | 2025.01.10 |
|---|---|
| 호텔 예약 수요 데이터셋 (1) | 2025.01.09 |
| 주택 임대료 예측 데이터셋 (4) | 2025.01.03 |
| 사이킷런 (1) | 2024.12.31 |
| 머신러닝 (3) | 2024.12.23 |