6. 서울 자전거 공유 수요 예측 데이터셋

2025. 1. 8. 12:11LLM(Large Language Model)의 기초/머신러닝과 딥러닝

1. 서울 자전거 공유 수요 데이터셋
* 서울시의 공공자전거 대여 서비스인 ‘따릉이’의 대여 수요를 예측하는 문제에 사용되는 데이터셋입니다. 
* 특정 시간대와 날씨, 요일, 공휴일 여부, 기온, 습도 등 다양한 데이터를 활용하여 자전거 대여 수요를 예측합니다.

 

링크 들어가서 압축 풀구 다운받아서 구글 드라이브에 첨부해준다
링크 주소 : https://www.kaggle.com/datasets/joebeachcapital/seoul-bike-sharing/data

 

Seoul Bike Sharing Demand Prediction

Predict demand for shared bikes in Seoul based on various environmental factors

www.kaggle.com

 

2. 데이터셋 컬럼
* Date : 연월일
* Rented Bike count - 매 시간마다 대여한 자전거 수
* Hour - 하루 중 시간
* Temperature - 온도
* Humidity - 습도 %
* Windspeed - 풍속 m/s
* Visibility - 가시거리 m
* Dew point temperature - 이슬점 온도
* Solar radiation - 태양 복사 MJ/m2
* Rainfall - 강우량 mm
* Snowfall - 적설량 cm
* Seasons - 겨울, 봄, 여름, 가을
* Holiday - 휴일/휴일 없음
* Functional Day - 운영되지 않았던 날, 정상적으로 운영된 날

 

예시 1) import 시켜줍니다.

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

 

예시 2)

# CP949
#Microsoft Windows의 한국어 문자 인코딩입니다.
#EUC-KR을 확장한 형태로, 더 많은 한국어 문자(한자, 확장 문자 등)를 지원합니다.
#주로 Windows 환경에서 저장된 한글 파일에서 사용됩니다.
# 서울 자전거 데이터를 bike_df로 정의합니다.
# 인코딩은 CP949으로 합니다.

bike_df = pd.read_csv('/content/drive/MyDrive/KDT 시즌 4/10. 데이터분석/Data/SeoulBikeData.csv', encoding='CP949')
bike_df

 -->

 

예시 3)

#bike_df.info()는 Pandas에서 제공하는 메서드로, 데이터프레임의 요약 정보를 출력합니다. 
#데이터 구조와 데이터의 타입, 결측값 등을 확인할 수 있는 중요한 메서드입니다.
bike_df.info()
-->
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 8760 entries, 0 to 8759
Data columns (total 14 columns):
 #   Column                    Non-Null Count  Dtype  
---  ------                    --------------  -----  
 0   Date                      8760 non-null   object 
 1   Rented Bike Count         8760 non-null   int64  
 2   Hour                      8760 non-null   int64  
 3   Temperature(캜)            8760 non-null   float64
 4   Humidity(%)               8760 non-null   int64  
 5   Wind speed (m/s)          8760 non-null   float64
 6   Visibility (10m)          8760 non-null   int64  
 7   Dew point temperature(캜)  8760 non-null   float64
 8   Solar Radiation (MJ/m2)   8760 non-null   float64
 9   Rainfall(mm)              8760 non-null   float64
 10  Snowfall (cm)             8760 non-null   float64
 11  Seasons                   8760 non-null   object 
 12  Holiday                   8760 non-null   object 
 13  Functioning Day           8760 non-null   object 
dtypes: float64(6), int64(4), object(4)
memory usage: 958.2+ KB

 

예시 4)

#bike_df.describe()는 Pandas에서 제공하는 데이터 분석 메서드로, 데이터프레임의 요약 통계를 출력합니다. 
#수치형 데이터를 기준으로 작동하며, 아래와 같은 정보를 제공합니다
bike_df.describe()

-->

 

예시 5)

#bike_df.columns는 Pandas 데이터프레임에서 열(column)의 이름을 반환하는 속성
bike_df.columns
-->
Index(['Date', 'Rented Bike Count', 'Hour', 'Temperature(캜)', 'Humidity(%)',
       'Wind speed (m/s)', 'Visibility (10m)', 'Dew point temperature(캜)',
       'Solar Radiation (MJ/m2)', 'Rainfall(mm)', 'Snowfall (cm)', 'Seasons',
       'Holiday', 'Functioning Day'],
      dtype='object')

 

예시 6)

# 이 코드는 Pandas 데이터프레임의 열 이름을 새롭게 지정하는 방법을 보여줍니다.
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()

-->

 

예시 7)

#이 코드는 Seaborn 라이브러리를 사용하여 **산점도(scatter plot)**를 그리는 예제입니다. 
#산점도는 두 변수 간의 관계를 시각화할 때 사용됩니다.
sns.scatterplot(x='Temperature', y='Rented Bike Count', data=bike_df, alpha=0.3)
-->
<Axes: xlabel='Temperature', ylabel='Rented Bike Count'>

-->

 

예시 8)

sns.scatterplot(x='Wind speed', y='Rented Bike Count', data=bike_df, alpha=0.3)
-->
<Axes: xlabel='Wind speed', ylabel='Rented Bike Count'>

-->

 

예시 9)

sns.scatterplot(x='Visibility', y='Rented Bike Count', data=bike_df, alpha=0.3)
-->
<Axes: xlabel='Visibility', ylabel='Rented Bike Count'>

-->

 

예시 10)

sns.scatterplot(x='Hour', y='Rented Bike Count', data=bike_df, alpha=0.3)
-->
<Axes: xlabel='Hour', ylabel='Rented Bike Count'>

-->

 

예시 11)

# bike_df.isna().sum()는 Pandas 메서드를 사용하여 데이터프레임의 결측값 개수를 열 단위로 합산하는 코드입니다.
# 0인 값을 나타냅니다.
bike_df.isna().sum()

-->

 

예시 12)

#bike_df.info()는 Pandas 메서드로, 데이터프레임의 구조적 요약 정보를 출력합니다. 
#이 메서드를 사용하면 데이터프레임의 크기, 데이터 타입, 결측값, 메모리 사용량 등을 빠르게 확인할 수 있습니다.
bike_df.info()
-->
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 8760 entries, 0 to 8759
Data columns (total 14 columns):
 #   Column                 Non-Null Count  Dtype  
---  ------                 --------------  -----  
 0   Date                   8760 non-null   object 
 1   Rented Bike Count      8760 non-null   int64  
 2   Hour                   8760 non-null   int64  
 3   Temperature            8760 non-null   float64
 4   Humidity               8760 non-null   int64  
 5   Wind speed             8760 non-null   float64
 6   Visibility             8760 non-null   int64  
 7   Dew point temperature  8760 non-null   float64
 8   Solar Radiation        8760 non-null   float64
 9   Rainfall               8760 non-null   float64
 10  Snowfall               8760 non-null   float64
 11  Seasons                8760 non-null   object 
 12  Holiday                8760 non-null   object 
 13  Functioning Day        8760 non-null   object 
dtypes: float64(6), int64(4), object(4)
memory usage: 958.2+ KB

 

예제 13)

#이 코드는 Pandas를 사용하여 데이터프레임의 'Date' 열을 문자열 데이터에서 날짜(datetime) 형식으로 변환한 후, 데이터프레임의 요약 정보를 출력합니다.
# 'Date' 열의 데이터를 문자열 형식에서 날짜/시간(datetime) 형식으로 변환합니다.
# pd.to_datetime 함수는 pandas 라이브러리의 메서드로, 문자열을 datetime 객체로 변환하는 데 사용됩니다.
# format='%d/%m/%Y'는 날짜의 형식이 '일/월/연도' 형식임을 지정합니다.
bike_df['Date'] = pd.to_datetime(bike_df['Date'], format='%d/%m/%Y')

# bike_df 데이터프레임의 정보를 출력합니다.
# info() 메서드는 데이터프레임의 열 이름, 데이터 타입, 결측치 유무 등 요약 정보를 제공합니다.
bike_df.info()
-->
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 8760 entries, 0 to 8759
Data columns (total 14 columns):
 #   Column                 Non-Null Count  Dtype         
---  ------                 --------------  -----         
 0   Date                   8760 non-null   datetime64[ns]
 1   Rented Bike Count      8760 non-null   int64         
 2   Hour                   8760 non-null   int64         
 3   Temperature            8760 non-null   float64       
 4   Humidity               8760 non-null   int64         
 5   Wind speed             8760 non-null   float64       
 6   Visibility             8760 non-null   int64         
 7   Dew point temperature  8760 non-null   float64       
 8   Solar Radiation        8760 non-null   float64       
 9   Rainfall               8760 non-null   float64       
 10  Snowfall               8760 non-null   float64       
 11  Seasons                8760 non-null   object        
 12  Holiday                8760 non-null   object        
 13  Functioning Day        8760 non-null   object        
dtypes: datetime64[ns](1), float64(6), int64(4), object(3)
memory usage: 958.2+ KB

 

예시 14)

# bike_df 데이터프레임의 첫 5개 행(row)을 출력합니다.
# head() 메서드는 데이터프레임의 상위 몇 개의 행을 간단히 확인하기 위해 사용됩니다.
# 기본적으로 첫 5개 행을 출력하지만, 원하는 개수를 인자로 전달하면 출력 행 수를 조정할 수 있습니다. (예: bike_df.head(10))
#년도와 월일이 형식이 달라진 것을 알수가 있다
bike_df.head()

 

-->

 

예시 15)

# 'Date' 열에서 연도(year)를 추출하여 새로운 열 'year'에 저장합니다.
# .dt.year는 datetime 객체에서 연도 정보를 추출하는 속성입니다.
bike_df['year'] = bike_df['Date'].dt.year

# 'Date' 열에서 월(month)을 추출하여 새로운 열 'month'에 저장합니다.
# .dt.month는 datetime 객체에서 월 정보를 추출하는 속성입니다.
bike_df['month'] = bike_df['Date'].dt.month

# 'Date' 열에서 일(day)을 추출하여 새로운 열 'day'에 저장합니다.
# .dt.day는 datetime 객체에서 일을 추출하는 속성입니다.
bike_df['day'] = bike_df['Date'].dt.day

# 데이터프레임의 첫 5개 행을 출력하여 새로 추가된 열('year', 'month', 'day')이 제대로 생성되었는지 확인합니다.
bike_df.head()

-->

 

예시 16)

# 새로운 그래프를 그릴 준비를 합니다. 
# figsize=(14, 4)는 그래프의 크기를 가로 14인치, 세로 4인치로 설정합니다.
plt.figure(figsize=(14, 4))

# 선형 그래프를 그립니다.
# sns.lineplot은 seaborn 라이브러리의 메서드로, 데이터의 변화를 시각화하는 선 그래프를 생성합니다.
# x='Date'는 x축에 'Date' 열을 사용하겠다는 의미입니다.
# y='Rented Bike Count'는 y축에 'Rented Bike Count' 열을 사용하겠다는 의미입니다.
# data=bike_df는 사용할 데이터프레임이 bike_df임을 지정합니다.
sns.lineplot(x='Date', y='Rented Bike Count', data=bike_df)

# x축의 눈금 레이블을 45도 회전시킵니다.
# plt.xticks(rotation=45)는 눈금 레이블이 겹치지 않도록 각도를 조정하는 데 사용됩니다.
plt.xticks(rotation=45)

# 그래프를 화면에 출력합니다.
plt.show()

-->

 

예시 17)

# bike_df 데이터프레임에서 'year' 열의 값이 2017인 데이터만 필터링합니다.
# bike_df[bike_df['year'] == 2017]는 'year' 열의 값이 2017인 행만 선택하는 코드입니다.
filtered_data = bike_df[bike_df['year'] == 2017]

# 필터링된 데이터에서 'month' 열을 기준으로 데이터를 그룹화합니다.
# groupby('month')는 월(month)별로 데이터를 그룹화하는 메서드입니다.
grouped_data = filtered_data.groupby('month')

# 그룹화된 데이터에서 'Rented Bike Count' 열의 평균값을 계산합니다.
# ['Rented Bike Count'].mean()는 각 그룹(월별)에 대해 자전거 대여 건수의 평균을 계산합니다.
monthly_mean = grouped_data['Rented Bike Count'].mean()

# 이걸 이어서 쓰면 
bike_df[bike_df['year'] == 2017].groupby('month')['Rented Bike Count'].mean()
# 결과를 출력합니다.
monthly_mean

-->

 

예시 18)

# bike_df 데이터프레임에서 'year' 열의 값이 2018인 데이터만 필터링합니다.
# bike_df[bike_df['year'] == 2018]는 'year' 열의 값이 2018인 행만 선택합니다.
filtered_data = bike_df[bike_df['year'] == 2018]

# 필터링된 데이터에서 'month' 열을 기준으로 데이터를 그룹화합니다.
# groupby('month')는 월(month)별로 데이터를 그룹화합니다.
grouped_data = filtered_data.groupby('month')

# 그룹화된 데이터에서 'Rented Bike Count' 열의 평균값을 계산합니다.
# ['Rented Bike Count'].mean()는 각 월별로 자전거 대여 건수의 평균을 계산합니다.
monthly_mean = grouped_data['Rented Bike Count'].mean()

#이걸 한줄로 요약하면
bike_df[bike_df['year'] == 2018].groupby('month')['Rented Bike Count'].mean()
# 결과를 출력합니다.
monthly_mean

-->

 

예시 19)

# 'Hour' 열의 값을 기준으로 새로운 범주형 열 'TimeOfDay'를 생성합니다.
# pd.cut() 함수는 데이터를 특정 구간(bins)으로 나누고, 각 구간에 레이블을 할당하는 데 사용됩니다.

# bins=[0, 5, 11, 17, 23]는 시간(Hour)을 다음과 같은 네 구간으로 나누는 기준입니다:
#   - 0~5: Dawn (새벽)
#   - 6~11: Morning (아침)
#   - 12~17: Afternoon (오후)
#   - 18~23: Evening (저녁)

# labels=['Dawn', 'Morning', 'Afternoon', 'Evening']는 각 구간에 대해 지정된 레이블(범주)입니다.
# include_lowest=True는 구간의 첫 번째 값(0)을 포함하도록 설정합니다.

bike_df['TimeOfDay'] = pd.cut(bike_df['Hour'], bins=[0, 5, 11, 17, 23], 
                              labels=['Dawn', 'Morning', 'Afternoon', 'Evening'], 
                              include_lowest=True)
                              
bike_df.head()

-->

 

예시 20)

# 막대 그래프를 생성하여 'Functioning Day'에 따른 'Rented Bike Count'의 평균값을 시각화합니다.
# sns.barplot()은 seaborn 라이브러리의 메서드로, 범주형 데이터(x축)에 따른 y축 값(연속형 데이터)의 평균을 막대 그래프로 보여줍니다.

# x='Functioning Day': x축에 'Functioning Day' 열을 사용합니다.
# 'Functioning Day'는 일반적으로 자전거 대여소가 정상적으로 운영되었는지 여부를 나타내는 범주형 데이터입니다(예: 'Yes', 'No').

# y='Rented Bike Count': y축에 'Rented Bike Count' 열을 사용합니다.
# 'Rented Bike Count'는 자전거 대여 건수 데이터를 나타냅니다.

# data=bike_df: 그래프에 사용할 데이터프레임을 지정합니다.
sns.barplot(x='Functioning Day', y='Rented Bike Count', data=bike_df)
-->
<Axes: xlabel='Functioning Day', ylabel='Rented Bike Count'>

-->

 

예시 21)

# 'Functioning Day' 열에서 각 값의 개수를 계산합니다.
# value_counts() 메서드는 데이터의 고유 값(unique value)별로 개수를 세어 반환합니다.
# 반환 결과는 값별로 몇 번 등장했는지를 나타내는 Pandas Series 형태로 출력됩니다.
bike_df['Functioning Day'].value_counts()

--->

 

예시 22)

# 'Functioning Day' 열의 값이 'Yes'인 데이터만 필터링합니다.
# bike_df['Functioning Day'] == 'Yes'는 'Functioning Day' 열에서 값이 'Yes'인 행을 선택하는 조건입니다.
# bike_df[...]는 위 조건에 맞는 행만 추출하여 새로운 데이터프레임으로 반환합니다.
bike_df[bike_df['Functioning Day'] == 'Yes']

--->

 

예시 23)

# 'Functioning Day' 열의 값이 'No'인 데이터만 필터링합니다.
# bike_df['Functioning Day'] == 'No'는 'Functioning Day' 열에서 값이 'No'인 행을 선택하는 조건입니다.
# bike_df[...]는 위 조건에 맞는 행만 추출하여 새로운 데이터프레임으로 반환합니다.
bike_df[bike_df['Functioning Day'] == 'No']

--->

 

예시 24)

# 'Date' 열을 데이터프레임에서 삭제합니다.
# drop() 메서드는 데이터프레임에서 특정 열이나 행을 제거할 때 사용됩니다.
# 'Date': 삭제할 열의 이름을 지정합니다.
# axis=1: 열을 기준으로 삭제한다는 것을 나타냅니다. (axis=0은 행 기준)
bike_df = bike_df.drop('Date', axis=1)

# 데이터프레임의 첫 5개 행을 출력합니다.
# head() 메서드는 데이터프레임의 구조와 삭제된 열이 제대로 반영되었는지 확인하기 위해 사용됩니다.
bike_df.head()

 

예시 25)

# 데이터프레임의 요약 정보를 출력합니다.
# info() 메서드는 데이터프레임의 구조, 각 열의 데이터 타입, 결측치 개수, 행과 열의 개수 등을 요약하여 보여줍니다.
bike_df.info()
--->
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 8760 entries, 0 to 8759
Data columns (total 17 columns):
 #   Column                 Non-Null Count  Dtype   
---  ------                 --------------  -----   
 0   Rented Bike Count      8760 non-null   int64   
 1   Hour                   8760 non-null   int64   
 2   Temperature            8760 non-null   float64 
 3   Humidity               8760 non-null   int64   
 4   Wind speed             8760 non-null   float64 
 5   Visibility             8760 non-null   int64   
 6   Dew point temperature  8760 non-null   float64 
 7   Solar Radiation        8760 non-null   float64 
 8   Rainfall               8760 non-null   float64 
 9   Snowfall               8760 non-null   float64 
 10  Seasons                8760 non-null   object  
 11  Holiday                8760 non-null   object  
 12  Functioning Day        8760 non-null   object  
 13  year                   8760 non-null   int32   
 14  month                  8760 non-null   int32   
 15  day                    8760 non-null   int32   
 16  TimeOfDay              8760 non-null   category
dtypes: category(1), float64(6), int32(3), int64(4), object(3)
memory usage: 1001.2+ KB

 

예시 26)

# 데이터프레임에서 숫자 데이터 유형을 제외한 열들의 이름을 추출합니다.
# select_dtypes() 메서드는 특정 데이터 유형을 포함하거나 제외한 열을 선택하는 데 사용됩니다.
# exclude=['number']: 숫자 데이터 타입(ex: int64, float64 등)을 제외한 열만 선택합니다.
# .columns: 선택된 열의 이름만 추출합니다.
# .tolist(): 열 이름을 리스트(list) 형태로 변환합니다.
non_numeric_columns = bike_df.select_dtypes(exclude=['number']).columns.tolist()
--->
['Seasons', 'Holiday', 'Functioning Day', 'TimeOfDay']

 

 

예시 27)

# 숫자가 아닌 데이터 타입의 열들에 대해 고유값 개수를 출력합니다.

# bike_df.select_dtypes(exclude=['number']).columns.tolist():
# 숫자 데이터 타입을 제외한 열들의 이름을 리스트 형태로 가져옵니다.

# for i in ...: 각 열의 이름에 대해 반복문을 수행합니다.
for i in bike_df.select_dtypes(exclude=['number']).columns.tolist():
    # bike_df[i].nunique(): i열의 고유값(unique value) 개수를 계산합니다.
    # print(): 열의 이름과 해당 열의 고유값 개수를 출력합니다.
    print(i, bike_df[i].nunique())
--->
Seasons 4
Holiday 2
Functioning Day 2
TimeOfDay 4

 

예시 28)

# 숫자가 아닌 데이터 유형의 열들을 원-핫 인코딩(One-Hot Encoding) 방식으로 변환합니다.
# pd.get_dummies()는 범주형 데이터를 0과 1로 이루어진 더미(dummy) 변수로 변환하는 데 사용됩니다.
# columns=bike_df.select_dtypes(exclude=['number']).columns.tolist():
# 숫자가 아닌 데이터 타입의 열들만 선택하여 원-핫 인코딩을 수행합니다.
# drop_first=True는 원-핫 인코딩 결과에서 첫 번째 범주를 삭제하여 다중공선성을 방지합니다.
bike_df = pd.get_dummies(
    bike_df, 
    columns=bike_df.select_dtypes(exclude=['number']).columns.tolist(), 
    drop_first=True
)

# 데이터프레임의 첫 5개 행을 출력합니다.
# 결과를 확인하여 원-핫 인코딩이 올바르게 적용되었는지 확인합니다.
# 결과는 가을이 빠진걸로 확인됩니다.
bike_df.head()

--->

 

예시 29)

# 모든 컬럼 간 상관관계 분석
# 데이터프레임의 모든 열 간 상관관계를 계산합니다.
# corr() 메서드는 데이터프레임의 숫자형 열들 간의 상관계수를 계산하여 상관행렬(correlation matrix)을 반환합니다.
# 상관계수(correlation coefficient)는 -1에서 1 사이의 값을 가지며, 다음을 의미합니다:
# - 1: 완벽한 양의 상관관계 (한 변수가 증가할 때 다른 변수도 일정 비율로 증가)
# - 0: 상관관계 없음 (두 변수 간에 선형적 관계가 없음)
# - -1: 완벽한 음의 상관관계 (한 변수가 증가할 때 다른 변수는 일정 비율로 감소)
correlation_matrix = bike_df.corr()

# 상관행렬을 출력합니다.
# 상관행렬은 모든 숫자형 열 간의 상관계수를 포함한 2차원 행렬입니다.
correlation_matrix

--->

 

예시 30)

# 목표 변수와의 상관관계만 확인

# 목표 변수('Rented Bike Count')와 다른 변수들 간의 상관계수만 추출합니다.
# correlation_matrix['Rented Bike Count']: 상관행렬에서 'Rented Bike Count' 열만 선택합니다.
# sort_values(ascending=False): 상관계수를 내림차순으로 정렬합니다.
# 이렇게 하면 'Rented Bike Count'와 상관관계가 높은 변수부터 낮은 변수 순으로 정렬된 결과를 반환합니다.
target_corr = correlation_matrix['Rented Bike Count'].sort_values(ascending=False)

# 정렬된 상관계수를 출력합니다.
target_corr

--->

 

 

> corr() 함수
corr() 함수는 데이터프레임의 숫자형 열 간의 상관관계를 계산하는 데 사용됩니다.

상관관계는 두 변수 간의 선형 관계를 나타내며, 주로 -1에서 1 사이의 값으로 표현됩니다.
* corr()는 Pearson 상관계수를 기본으로 사용합니다.
* 숫자형 열만 상관관계 분석에 포함됩니다.
* 높은 상관관계(>|0.5|): 강한 관계
* 낮은 상관관계(<|0.2|): 약한 관계
corr()를 사용하여 높은 상관관계를 가진 컬럼을 식별하고 제거할지 여부를 판단할 수 있습니다. 

특히, 다중공선성(multicollinearity) 문제가 발생할 경우 머신러닝 모델의 성능이 저하될 수 있으므로, 상관관계가 높은 컬럼을 적절히 제거하는 것이 중요합니다.

 

> 다중공선성
* 다중공선성(Multicollinearity)은 회귀 분석에서 독립 변수들(설명 변수) 간에 강한 상관관계가 존재하는 현상을 의미합니다. 
* 이러한 상관관계가 높으면 각 독립 변수가 종속 변수에 미치는 개별적인 영향을 정확하게 추정하기 어려워지며, 회귀 계수의 추정치가 불안정해져 작은 데이터 변화에도 크게 변할 수 있습니다. 
* 이는 모델의 예측 성능 저하와 해석의 신뢰성 감소로 이어질 수 있으므로, 다중공선성이 높은 변수를 식별하고 제거하거나 조정하는 것이 중요합니다.

 

예시 1)

# 그래프의 크기를 설정합니다.
# figsize=(16, 12)는 그래프 크기를 가로 16인치, 세로 12인치로 설정합니다.
plt.figure(figsize=(16, 12))

# 상관행렬을 히트맵(heatmap)으로 시각화합니다.
# sns.heatmap()은 데이터의 값을 색상으로 표현하는 그래프를 생성합니다.
# correlation_matrix: 히트맵에 표시할 상관행렬 데이터를 입력합니다.
# annot=True: 히트맵의 각 셀에 상관계수 값을 표시합니다.
# fmt='.2f': 각 셀에 표시되는 상관계수 값을 소수점 둘째 자리까지 포맷팅합니다.
# cmap='coolwarm': 색상 팔레트를 'coolwarm' 스타일로 지정하여 양수와 음수를 명확히 구분합니다 (양수는 빨간색, 음수는 파란색).
sns.heatmap(correlation_matrix, annot=True, fmt='.2f', cmap='coolwarm')

# 그래프 제목을 추가합니다.
# 'Feature Correlation Heatmap'는 히트맵의 제목입니다.
plt.title('Feature Correlation Heatmap')

# 그래프를 화면에 출력합니다.
plt.show()

--->

 

예시 2)

# 데이터프레임에서 'Dew point temperature', 'Visibility', 'day' 열을 삭제합니다.
# drop() 메서드는 데이터프레임에서 특정 열 또는 행을 제거하는 데 사용됩니다.
# ['Dew point temperature', 'Visibility', 'day']: 삭제할 열들의 이름을 리스트로 지정합니다.
# axis=1: 열을 기준으로 삭제하겠다는 것을 나타냅니다 (axis=0은 행 기준).
bike_df = bike_df.drop(['Dew point temperature', 'Visibility', 'day'], axis=1)

# 데이터프레임의 첫 5개 행을 출력합니다.
# head() 메서드는 데이터프레임이 올바르게 업데이트되었는지 확인하기 위해 사용됩니다.
bike_df.head()

--->

 

예시 3)

bike_df.info()
--->
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 8760 entries, 0 to 8759
Data columns (total 18 columns):
 #   Column               Non-Null Count  Dtype  
---  ------               --------------  -----  
 0   Rented Bike Count    8760 non-null   int64  
 1   Hour                 8760 non-null   int64  
 2   Temperature          8760 non-null   float64
 3   Humidity             8760 non-null   int64  
 4   Wind speed           8760 non-null   float64
 5   Solar Radiation      8760 non-null   float64
 6   Rainfall             8760 non-null   float64
 7   Snowfall             8760 non-null   float64
 8   year                 8760 non-null   int32  
 9   month                8760 non-null   int32  
 10  Seasons_Spring       8760 non-null   bool   
 11  Seasons_Summer       8760 non-null   bool   
 12  Seasons_Winter       8760 non-null   bool   
 13  Holiday_No Holiday   8760 non-null   bool   
 14  Functioning Day_Yes  8760 non-null   bool   
 15  TimeOfDay_Morning    8760 non-null   bool   
 16  TimeOfDay_Afternoon  8760 non-null   bool   
 17  TimeOfDay_Evening    8760 non-null   bool   
dtypes: bool(8), float64(5), int32(2), int64(3)
memory usage: 684.5 KB

 

예시 4)

from sklearn.model_selection import train_test_split

# sklearn의 train_test_split을 사용하여 데이터를 학습용과 테스트용으로 분리합니다.

# bike_df.drop('Rented Bike Count', axis=1): 목표 변수('Rented Bike Count')를 제외한 나머지 열들을 입력 데이터(X)로 설정합니다.
# bike_df['Rented Bike Count']: 목표 변수('Rented Bike Count')를 출력 데이터(y)로 설정합니다.

# test_size=0.3: 전체 데이터의 30%를 테스트 데이터로 사용합니다. 나머지 70%는 학습 데이터로 사용됩니다.
# random_state=2025: 랜덤 분할의 재현성을 보장하기 위해 시드를 고정합니다. (같은 데이터에서 항상 동일한 분할 결과를 얻음)

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                          # 랜덤 시드 고정
)

 

예시 5)

X_train.shape, X_test.shape
--->
((6132, 17), (2628, 17))
y_train.shape, y_test.shape
--->
((6132,), (2628,))

 

4. 결정 트리
* 결정 트리(Decision Tree)는 데이터를 기반으로 의사결정을 수행하는 트리 구조의 예측 모델입니다. 
* 루트 노드(root node)에서 시작해 각 노드는 특정 특성(feature)의 조건에 따라 가지(branch)로 분기되며, 최종적으로 리프 노드(leaf node)에 도달해 예측 결과(클래스나 값)를 도출합니다. 
* 주로 분류(Classification)와 회귀(Regression) 문제에 사용되며, 데이터의 패턴을 직관적으로 시각화할 수 있어 해석이 용이합니다. 하지만 트리가 너무 깊어지면 과적합(overfitting) 문제가 발생할 수 있으므로 가지치기(pruning)나 최대 깊이 설정 등으로 제어해야 합니다.

 

학습 과정
* 1.전체 데이터셋을 하나의 노드로 시작합니다.
* 2.최적의 특성(feature)과 분할 기준(threshold)을 찾아 첫 번째 분할을 수행합니다.
  * 분류 (Classification):
      * Gini 불순도(Gini Impurity)
      * 엔트로피(Entropy)
  * 회귀 (Regression):
      * 평균 제곱 오차(Mean Squared Error, MSE)
      * 절대 평균 오차(Mean Absolute Error, MAE)
* 3.각 하위 노드에 대해 위 단계를 반복합니다.
* 4.이 과정을 통해 트리는 여러 깊이로 성장합니다.
* 5.모든 노드가 더 이상 나눌 수 없거나 특정 조건(max_depth, min_samples_split)을 만족할 때까지 반복됩니다.
* 6.더 이상 분할이 불가능할 때 리프 노드가 생성됩니다.
* 분류 문제: 가장 많은 클래스가 있는 클래스를 예측값으로 사용
* 회귀 문제: 평균값을 예측값으로 사용

 

예시 1)

from sklearn.tree import DecisionTreeRegressor

# sklearn의 DecisionTreeRegressor를 사용하여 회귀 모델을 생성합니다.

# DecisionTreeRegressor(random_state=2025):
# 의사결정 트리 회귀 모델을 생성합니다.
# random_state=2025는 모델의 재현성을 보장하기 위해 시드를 고정합니다.
dtr = DecisionTreeRegressor(random_state=2025)

# 학습 데이터를 사용하여 의사결정 트리 모델을 학습시킵니다.
# fit() 메서드는 모델을 학습 데이터(X_train, y_train)에 맞추어 훈련시킵니다.
dtr.fit(X_train, y_train)

# 학습된 모델을 사용하여 테스트 데이터(X_test)에 대한 예측값을 생성합니다.
# predict() 메서드는 테스트 데이터에 대한 목표 변수(y)의 예측값을 반환합니다.
pred1 = dtr.predict(X_test)

# 실제값(y_test)과 예측값(pred1)을 산점도로 시각화합니다.
# sns.scatterplot()은 두 변수 간의 관계를 점으로 나타냅니다.
# x=y_test: 실제 목표 변수 값을 x축에 표시합니다.
# y=pred1: 모델이 예측한 목표 변수 값을 y축에 표시합니다.
sns.scatterplot(x=y_test, y=pred1)
--->
<Axes: xlabel='Rented Bike Count'>

--->

 

 

 

예시 2)

from sklearn.metrics import root_mean_squared_error
# sklearn.metrics의 root_mean_squared_error를 사용하여 모델의 성능을 평가합니다.

# root_mean_squared_error(y_test, pred1):
# - y_test: 실제 목표 변수 값 (테스트 데이터의 정답 레이블)
# - pred1: 모델이 예측한 목표 변수 값 (테스트 데이터에 대한 예측값)
# 루트 평균 제곱 오차(RMSE)를 계산하여 모델의 예측 정확도를 평가합니다.

# RMSE는 다음을 계산합니다:
# 1. 각 데이터 포인트에 대해 실제값(y_test)과 예측값(pred1)의 차이를 제곱합니다.
# 2. 모든 데이터 포인트에 대해 평균을 계산합니다.
# 3. 그 평균값의 제곱근을 구합니다.

# RMSE는 오차의 크기를 직관적으로 이해할 수 있게 해주는 척도입니다. 
# 값이 작을수록 모델의 예측이 실제값과 가까움을 나타냅니다.
root_mean_squared_error(y_test, pred1)
--->
314.3922587940898

 

예시 3)

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)
--->
<Axes: xlabel='Rented Bike Count'>

--->

 

예시 4)

# 두 번째 모델의 예측값(pred2)에 대해 루트 평균 제곱 오차(RMSE)를 계산합니다.

# root_mean_squared_error(y_test, pred2):
# - y_test: 실제 목표 변수 값 (테스트 데이터의 정답 레이블)
# - pred2: 두 번째 모델이 예측한 목표 변수 값 (테스트 데이터에 대한 예측값)
# RMSE는 두 번째 모델의 예측 성능을 수치적으로 평가합니다.

# RMSE 계산 과정:
# 1. 각 데이터 포인트에 대해 실제값(y_test)과 예측값(pred2)의 차이를 제곱합니다.
# 2. 모든 데이터 포인트에 대해 평균을 계산합니다.
# 3. 그 평균값의 제곱근을 구하여 오차의 크기를 측정합니다.

# RMSE 값은 작을수록 예측 정확도가 높음을 의미합니다.
root_mean_squared_error(y_test, pred2)
--->
420.7751923450068

 

예시 5)

#DecisionRegressor : 314.3922587940898
#LinearRegression :  420.7751923450068

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)
--->
# 하이퍼파라미터를 지정하여 의사결정 트리 회귀 모델을 생성합니다.
# DecisionTreeRegressor(random_state=2025, max_depth=50, min_samples_leaf=30):
# - random_state=2025: 랜덤성을 고정하여 결과의 재현성을 보장합니다.
# - max_depth=50: 트리의 최대 깊이를 50으로 제한합니다. 
#   트리의 깊이를 제한하면 과적합(overfitting)을 방지하고 일반화 성능을 개선할 수 있습니다.
# - min_samples_leaf=30: 리프 노드(최종 노드)에 있어야 하는 최소 샘플 수를 30으로 설정합니다.
#   이 설정은 트리의 분할을 제한하여 모델이 지나치게 복잡해지는 것을 방지합니다.
dtr = DecisionTreeRegressor(random_state=2025, max_depth=50, min_samples_leaf=30)

# 학습 데이터를 사용하여 모델을 학습시킵니다.
# fit() 메서드는 모델을 학습 데이터(X_train, y_train)에 맞추어 훈련시킵니다.
dtr.fit(X_train, y_train)

# 학습된 모델을 사용하여 테스트 데이터(X_test)에 대한 예측값을 생성합니다.
# predict() 메서드는 테스트 데이터에 대한 목표 변수(y)의 예측값을 반환합니다.
pred3 = dtr.predict(X_test)

# 새로운 모델의 예측 성능을 RMSE로 평가합니다.
# root_mean_squared_error(y_test, pred3): 실제값(y_test)과 예측값(pred3) 간의 RMSE를 계산합니다.
root_mean_squared_error(y_test, pred3)
--->
292.4445072721054

 

예시 6)

#DecisionTreeRegressor : 314.3922587940898
#DecisionTreeRegressor (하이퍼 파라미터 적용) : 292.4445072721054
#LinearRegression :  420.7751923450068

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()

--->
# 학습된 의사결정 트리 모델을 시각화합니다.

# plt.figure(figsize=(24, 12)):
# - 그래프의 크기를 가로 24인치, 세로 12인치로 설정합니다.
# - 트리의 복잡도에 따라 적절한 크기를 설정하면 트리가 더 잘 보입니다.
plt.figure(figsize=(24, 12))

# plot_tree(dtr, max_depth=5, fontsize=10, feature_names=X_train.columns):
# - plot_tree(): 의사결정 트리 구조를 시각화하는 sklearn의 함수입니다.
# - dtr: 시각화할 학습된 의사결정 트리 모델.
# - max_depth=5: 트리의 깊이를 최대 5로 제한하여, 너무 복잡한 트리가 출력되지 않도록 조정합니다.
# - fontsize=10: 트리 노드와 텍스트의 폰트 크기를 10으로 설정합니다.
# - feature_names=X_train.columns: 입력 데이터의 특성 이름을 표시합니다. (노드의 분할 기준을 이해하기 쉽게 만듭니다.)
plot_tree(dtr, max_depth=5, fontsize=10, feature_names=X_train.columns)

# 트리를 화면에 출력합니다.
plt.show()

---->

 

예시 7)

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)
---->

# 랜덤 포레스트 회귀 모델(Random Forest Regressor)을 생성하고 학습시킵니다.

# RandomForestRegressor(random_state=2025):
# - 랜덤 포레스트는 여러 개의 의사결정 트리를 결합하여 예측 성능을 높이는 앙상블 학습 기법입니다.
# - random_state=2025는 결과의 재현성을 보장하기 위해 시드를 고정합니다.
rf = RandomForestRegressor(random_state=2025)

# 학습 데이터를 사용하여 랜덤 포레스트 모델을 학습시킵니다.
# fit() 메서드는 모델을 학습 데이터(X_train, y_train)에 맞추어 훈련시킵니다.
rf.fit(X_train, y_train)

# 학습된 랜덤 포레스트 모델을 사용하여 테스트 데이터(X_test)에 대한 예측값을 생성합니다.
# predict() 메서드는 테스트 데이터에 대한 목표 변수(y)의 예측값을 반환합니다.
pred4 = rf.predict(X_test)

# 새로운 모델의 예측 성능을 RMSE로 평가합니다.
# root_mean_squared_error(y_test, pred4): 실제값(y_test)과 예측값(pred4) 간의 RMSE를 계산합니다.
root_mean_squared_error(y_test, pred4)
--->
236.76857513356003

 

예시 8)

#DecisionTreeRegressor : 314.3922587940898
#DecisionTreeRegressor (하이퍼 파라미터 적용) : 292.4445072721054
#DecisionTreeRegressor : 236.76857513356003
#LinearRegression :  420.7751923450068

# 학습된 랜덤 포레스트 모델의 특성 중요도를 확인합니다.

# rf.feature_importances_:
# - 랜덤 포레스트 모델에서 각 특성이 예측에 기여한 중요도를 반환합니다.
# - 반환 값은 각 특성의 중요도를 나타내는 숫자(0~1)로, 모든 특성의 중요도를 합치면 1이 됩니다.
# - 값이 클수록 해당 특성이 모델 예측에 더 큰 영향을 미쳤음을 의미합니다.
rf.feature_importances_
---->
array([0.27265999, 0.33176286, 0.09043393, 0.02106805, 0.09702416,
       0.04001984, 0.00099521, 0.0004268 , 0.02514481, 0.00211512,
       0.00204257, 0.01558588, 0.00293549, 0.08622191, 0.00221576,
       0.00447922, 0.00486842])

 

예시 9)

# 랜덤 포레스트 모델에서 계산된 특성 중요도를 데이터프레임으로 정리합니다.

# pd.DataFrame():
# - Pandas를 사용하여 데이터프레임을 생성합니다.
# - 데이터프레임은 두 개의 열로 구성됩니다:
#   1. 'features': 학습 데이터(X_train)의 열 이름(특성 이름).
#   2. 'importances': 랜덤 포레스트 모델에서 계산된 각 특성의 중요도(rf.feature_importances_).

feature_imp = pd.DataFrame({
    'features': X_train.columns,        # 학습 데이터의 각 특성 이름
    'importances': rf.feature_importances_  # 각 특성의 중요도 값
})

feature_imp
--->

--->

 

예시 10)

# 랜덤 포레스트 모델의 특성 중요도 데이터프레임에서 가장 중요한 10개의 특성을 선택합니다.

# feature_imp.sort_values('importances', ascending=False):
# - 'importances' 열을 기준으로 데이터프레임(feature_imp)을 내림차순으로 정렬합니다.
# - 가장 중요한 특성부터 덜 중요한 특성 순으로 정렬됩니다.

# .head(10):
# - 정렬된 데이터프레임에서 상위 10개의 행(가장 중요한 10개의 특성)을 선택합니다.

top10 = feature_imp.sort_values('importances', ascending=False).head(10)

 

예시 11)

# 가장 중요한 10개의 특성을 막대 그래프로 시각화합니다.

# plt.figure(figsize=(5, 10)):
# - 그래프의 크기를 가로 5인치, 세로 10인치로 설정합니다.
# - 세로로 긴 막대 그래프를 그리기 위해 적합한 크기로 설정합니다.
plt.figure(figsize=(5, 10))

# sns.barplot(x='importances', y='features', data=top10):
# - sns.barplot(): Seaborn 라이브러리를 사용하여 막대 그래프를 생성합니다.
# - x='importances': x축에 특성 중요도 값(`importances`)을 표시합니다.
# - y='features': y축에 특성 이름(`features`)을 표시합니다.
# - data=top10: 그래프에 사용할 데이터로, 상위 10개의 특성과 중요도를 포함한 `top10` 데이터프레임을 사용합니다.
sns.barplot(x='importances', y='features', data=top10)
--->
<Axes: xlabel='importances', ylabel='features'>

--->

728x90
LIST