2025. 1. 8. 12:11ㆍLLM(Large Language Model)의 기초/머신러닝과 딥러닝
1. 서울 자전거 공유 수요 데이터셋
* 서울시의 공공자전거 대여 서비스인 ‘따릉이’의 대여 수요를 예측하는 문제에 사용되는 데이터셋입니다.
* 특정 시간대와 날씨, 요일, 공휴일 여부, 기온, 습도 등 다양한 데이터를 활용하여 자전거 대여 수요를 예측합니다.
링크 들어가서 압축 풀구 다운받아서 구글 드라이브에 첨부해준다
링크 주소 : https://www.kaggle.com/datasets/joebeachcapital/seoul-bike-sharing/data
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'>
--->
'LLM(Large Language Model)의 기초 > 머신러닝과 딥러닝' 카테고리의 다른 글
8. 호텔 예약 수요 데이터셋 (0) | 2025.01.09 |
---|---|
7. 파이토치로 구현한 논리 회귀 (0) | 2025.01.08 |
5. 주택 임대료 예측 데이터셋 (0) | 2025.01.07 |
4. 사이킷런 (0) | 2025.01.07 |
3. 파이토치로 구현한 선형 회귀 (2) | 2025.01.06 |