방명록
- 자전거 대여량 예측 - 선형 회귀, 군집 모델 (클러스터링) 실습2024년 03월 15일 06시 42분 26초에 업로드 된 글입니다.작성자: 재형이반응형
- 가보자 가보자~
1. 자전거 대여량 예측 - 선형회귀
- 다음과 같은 항목들로 이루어져 있는 데이터를 사용해볼 것이다
- 시간 - 시간별 타임 스탬프
- 계절 - 1 = 봄, 2 = 여름, 3 = 가을, 4 = 겨울
- 휴일 - whether the day is considered a holiday
- 주간 - whether the day is neither a weekend nor holiday
- 날씨 -
- 1: 맑음, Few clouds, Partly cloudy, Partly cloudy
- 2: 안개낌 + Cloudy, Mist + Broken clouds, Mist + Few clouds, Mist
- 3: 약간 눈내림, 약간 비 + 천둥번개 + Scattered 구름, 약간의 비 + Scattered 구름
- 4: 소나기 + 우박 + 천둥번개 + 안개, 눈 + 짙은 안개
- 온도 - temperature in Celsius
- 체감온도 - "feels like" temperature in Celsius
- 습도 - relative humidity
- 풍량 - wind speed
- 미가입 - number of non-registered user rentals initiated
- 가입 - number of registered user rentals initiated
- 렌탈수 - number of total rentals (Dependent Variable)
import numpy as np import pandas as pd import matplotlib.pyplot as plt import seaborn as sns df = pd.read_csv('exercise2.csv') df.head()
- df.shape로 총 행의 갯수와 열의 갯수를 파악해보자
10886개의 행과 12개의 열로 이루어져있다는 것을 알 수 있다 - df.describe()로 데이터들이 어떻게 분포되어 있는지 확인해보자
- 우리가 구하고자 하는 값인 count를 기준으로 시각화해보자
- 각 항목들 별로 시각화
nrows, ncols = 2, 5 fig, axs = plt.subplots(nrows=nrows, ncols=ncols) fig.set_size_inches(20,8) for i in range(nrows): for j in range(ncols): attr = i * ncols + j + 1 sns.histplot(x = df.columns[attr], data = df, ax=axs[i][j])
- 히트맵으로 시각화
sns.heatmap(df.corr())
- 이제 데이터를 분할해보고 모델을 불러와서 학습시켜보자
from sklearn.model_selection import train_test_split from sklearn.linear_model import LinearRegression from sklearn.metrics import mean_squared_log_error Y = df['count'] X = df.drop(['datetime', 'count'], axis=1,inplace=False) X_train, X_test, y_train, y_test = train_test_split(X, Y, test_size=0.3, random_state=42) lr_model = LinearRegression() lr_model.fit(X_train, y_train) y_pred = lr_model.predict(X_test) mean_squared_log_error(y_test, y_pred) # 2.2538764933380931e-29
- 거의 0에 수렴하는 오차값이 나왔다...? 띠용? 성능 무엇?
- 사실 데이터 전처리를 제대로 하지 않고 학습을 진행했기 때문에 성능이 좋게 나온 것이다...
- 어떤 값이 영향을 가장 많이 주었는지 살펴보면 회원인지 아닌지가 가장 영향을 많이 준 것을 확인 할 수 있다. 하지만 count = registered + casual 이기 때문에 사실 registered랑 casual은 독립 변수가 아니다. 이 값들 또한 우리가 예측해야할 값들이기 때문에 drop 시켜줘야 한다
coef = pd.Series(lr_model.coef_, index=X.columns) coef_sort = coef.sort_values(ascending=False) sns.barplot(x=coef_sort.values, y=coef_sort.index)
1-1. 코드 개선하기
- 뿐만 아니라, 계절이 1,2,3,4로 되어 있는데 이런 식으로 모델에게 넣어주면 모델은 봄과 겨울이 1과 4이므로 서로 멀리 떨어져 있는 관계를 가지는구나라고 불필요한 선수지식을 알려주게 된다 → 원핫 인코딩 처리
- 그리고 단순 Linear Regressor 뿐만 아니라 다양한 모델들을 사용해서 어떤 모델이 가장 성능이 좋은지 찾아보자
# datetime 또한 사용하기 위해 전처리 df['datetime'] = df['datetime'].astype('datetime64') df['year'] = df['datetime'].dt.year df['month'] = df['datetime'].dt.month df['day'] = df['datetime'].dt.day df['hour'] = df['datetime'].dt.hour # 불필요한 feature 삭제 df.drop(['datetime','casual','registered'], axis=1,inplace=True)
- 그리고 현재 count 분포를 보면 정규분포의 형태가 아니다. 선형회귀는 정규분포의 형태를 나타낼 때 가장 성능이 좋으므로 log를 취해서 비슷하게 만들어주자. 실제 값을 사용해야할 때는 exponential를 취해주어야 한다.
y_log = np.log1p(Y) nrows, ncols = 1, 2 fig, axs = plt.subplots(nrows=nrows, ncols=ncols) fig.set_size_inches(10, 4) sns.histplot(Y, ax = axs[0]) sns.histplot(y_log, ax = axs[1])
- 위에서 말한대로 원핫 인코딩이 필요한 값들은 인코딩 진행 → get_dummies 메서드 활용
df = pd.get_dummies(df, columns=['year', 'month', 'day', 'hour', 'holiday', 'workingday','season','weather'])
- 이제 학습을 시킨 후에 오차값을 비교해보자
from sklearn.preprocessing import StandardScaler from sklearn.ensemble import RandomForestRegressor from xgboost import XGBRegressor from lightgbm import LGBMRegressor Y = y_log X = df.drop(['count'], axis=1,inplace=False) sc = StandardScaler() scaled_X = sc.fit_transform(X) X_train, X_test, y_train, y_test = train_test_split(scaled_X, Y, test_size=0.3, random_state=42) lr_model = LinearRegression() rf_model = RandomForestRegressor(random_state = 42) xgb_model = XGBRegressor(random_state = 42) lgbm_model = LGBMRegressor(random_state = 42) model_list = [lr_model, rf_model, xgb_model, lgbm_model] for model in model_list: model.fit(X_train, y_train) y_pred = model.predict(X_test) m = model.__class__.__name__ score = mean_squared_log_error(np.expm1(y_test), np.expm1(y_pred)) print('{0} msle: {1:.3f}'.format(m, score))
- LinearRegression msle: 0.342
- RandomForestRegressor msle: 0.125
- XGBRegressor msle: 0.119
- LGBMRegressor msle: 0.110
- 여기서는 LGBMRegressor 이 가장 성능이 좋다는 것을 알 수 있다
2. 고객 멤버십 분류하기 - 클러스터링 실습
- 고객들의 연평균 소득(그냥 알아냈다고 생각)과 소비량을 기준으로 클러스터링해서 어느 군집에 속해있느냐에 따라 멤버십을 정해보자
- 여기서도 사이킷런을 사용한다
- 데이터는 다음과 같다
import numpy as np import pandas as pd import matplotlib.pyplot as plt import seaborn as sns df = pd.read_csv('exercise3.csv') df.head() df.shape # (200, 5)
- df.info(): 데이터 값들의 정보를 더 자세히 확인
- 연평균 소득에 따른 소비 점수를 시각화해서 볼 수 있다
sns.scatterplot(x= 'Annual Income (k$)', y = 'Spending Score (1-100)', data = df)
- 모델을 실제로 학습해보자
- k 값의 따른 실루엣 점수를 비교해가며 최적의 k 값을 찾아보자
- 실루엣 점수는 0~1의 값이며 1에 가까울수록 좋다
from sklearn.preprocessing import StandardScaler from sklearn.cluster import KMeans from sklearn.metrics import silhouette_samples, silhouette_score X= df.iloc[:,3:] sc = StandardScaler() X = sc.fit_transform(X) silhouette_avg = [] for k in range(10): model = KMeans(n_clusters= k+2, random_state=42) y_preds = model.fit_predict(X) score = silhouette_score(X, y_preds) silhouette_avg.append(score) print("군집개수: {0}개, 평균 실루엣 점수: {1:.4f}".format(k+2, score)) # 군집개수: 2개, 평균 실루엣 점수: 0.3147 # 군집개수: 3개, 평균 실루엣 점수: 0.4666 # 군집개수: 4개, 평균 실루엣 점수: 0.4939 # 군집개수: 5개, 평균 실루엣 점수: 0.5547 # 군집개수: 6개, 평균 실루엣 점수: 0.5399 # 군집개수: 7개, 평균 실루엣 점수: 0.5263 # 군집개수: 8개, 평균 실루엣 점수: 0.4558 # 군집개수: 9개, 평균 실루엣 점수: 0.4553 # 군집개수: 10개, 평균 실루엣 점수: 0.4476 # 군집개수: 11개, 평균 실루엣 점수: 0.4385
- k가 5일 때 가장 좋은 성능을 보여준다는 것을 알 수 있다
plt.plot(range(2,12), silhouette_avg, 'bo--') plt.xlabel('# of clusters') plt.ylabel('silhouette_avg') plt.show()
- k가 5일 때, 데이터 분포를 시각화해보자
model = KMeans(n_clusters= 5, random_state=42) y_preds = model.fit_predict(X) df['cluster'] = y_preds sns.scatterplot(x = 'Annual Income (k$)', y = 'Spending Score (1-100)', data = df, hue = 'cluster', palette="deep")
- 이 결과값을 가지고 다양한 지표를 통해 시각화하면 멤버십을 분류할 때 도움을 받을 수 있다
- 각 군집에 따른 소비 점수 시각화
sns.barplot(x = 'cluster', y = 'Spending Score (1-100)', data = df)
- 각 군집에 따른 연평균 소득
sns.barplot(x = 'cluster', y = 'Annual Income (k$)', data = df)
- 각 군집에 따라 성별 분포가 어떻게 되어 있는지 시각화
sns.countplot(x='cluster', data = df, hue = 'Gender')
- 각 군집에 따라 나이 분포가 어떻게 되어 있는지 시각화
sns.swarmplot(x = 'cluster', y='Age', data = df)
반응형'인공지능 > 프레임워크 or 라이브러리' 카테고리의 다른 글
인공 신경망 코드로 구현해서 다중 분류해보기 (2) (4) 2024.03.17 인공 신경망 코드로 구현해서 다중 분류해보기 (1) (0) 2024.03.16 제조 데이터의 분류기 실습 (0) 2024.03.14 데이터 로더, 모델 실습, 로깅 (0) 2024.02.21 Image Captcha 라이브러리 (Library) (4) 2024.02.20 다음글이 없습니다.이전글이 없습니다.댓글