Kaggle의 멜버른 주택가격 데이터셋을 사용하여 예측을 하도록 하겠습니다.
데이터는 아래 주소에서 다운로드 받으셔서 사용하시면 됩니다.
Melbourne Housing Dataset
Discover Insights and Trends from Housing Market
www.kaggle.com
데이터 로드
import pandas as pd
df = pd.read_csv('/content/Melbourne_housing.csv')
#pd.set_option('display.max_column', 100)
df.head().T
컬럼이 많은 경우 df.head().T 로 전치(transpose)해서 보시면 편합니다.
set_option을 사용해서 모든 컬럼이 보이게 하셔도 됩니다.
EDA(데이터 탐색)
dfSummary(df)
라이브러리가 설치되어 있지 않으신분은 dfSummary자료 참고하시기 바랍니다.
간단히 보시려면 기존 코드로 단계별로 보시면 됩니다.
df.shape
#(34857, 22)
df.isnull().sum()[df.isnull().sum()>0]
#Distance 1
#Postcode 1
#Bedroom 8217
#Bathroom 8226
#Car 8728
#Landsize 11810
#BuildingArea 21097
#YearBuilt 19306
#CouncilArea 3
#Latitude 7976
#Longtitude 7976
#Propertycount 3
#Price 7610
df.describe().T
df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 34857 entries, 0 to 34856
Data columns (total 22 columns):
# Column Non-Null Count Dtype
0 Suburb 34857 non-null object
1 Address 34857 non-null object
2 Rooms 34857 non-null int64
3 Type 34857 non-null object
4 Method 34857 non-null object
5 SellerG 34857 non-null object
6 Date 34857 non-null object
7 Distance 34856 non-null float64
8 Postcode 34856 non-null float64
9 Bedroom 26640 non-null float64
10 Bathroom 26631 non-null float64
11 Car 26129 non-null float64
12 Landsize 23047 non-null float64
13 BuildingArea 13760 non-null object
14 YearBuilt 15551 non-null float64
15 CouncilArea 34854 non-null object
16 Latitude 26881 non-null float64
17 Longtitude 26881 non-null float64
18 Regionname 34857 non-null object
19 Propertycount 34854 non-null float64
20 ParkingArea 34857 non-null object
21 Price 27247 non-null float64
dtypes: float64(11), int64(1), object(10)
memory usage: 5.9+ MB
df.nuique()
#Suburb 351
#Address 34009
#Rooms 12
#Type 3
#Method 9
#SellerG 388
#Date 78
#Distance 215
#Postcode 211
#Bedroom 15
#Bathroom 11
#Car 15
#Landsize 1684
#BuildingArea 994
#YearBuilt 160
#CouncilArea 33
#Latitude 13402
#Longtitude 14524
#Regionname 8
#Propertycount 342
#ParkingArea 8
#Price 2871
#dtype: int64
데이터 전처리
#컬럼선택
Columns1 = ['Suburb', 'Rooms', 'Type', 'Method', 'SellerG', 'Regionname', 'Propertycount', 'Distance', 'CouncilArea', 'Bedroom', 'Bathroom', 'Car', 'Landsize', 'BuildingArea', 'Price']
df1 = df[Columns1]
#값 채우기 Fillna 0으로 채우기
Columns2 = ['Car', 'Bathroom', 'Bedroom', 'Distance', 'Propertycount']
df1[Columns2] = df[Columns2].fillna(0)
df1['Landsize'] = pd.to_numeric(df1['Landsize'], errors='coerce')
df1['BuildingArea'] = pd.to_numeric(df1['BuildingArea'], errors='coerce')
df1['Landsize'] = df1['Landsize'].fillna(df1['Landsize'].mean())
df1['BuildingArea'] = df1['BuildingArea'].fillna(df1['BuildingArea'].mean())
df1 = df1.replace([np.inf, -np.inf], np.nan).dropna()
결측치에 대해서 0 채우기, mean, mode, 보간법 등 다양한 방안이 있으나 컬럼 속성에 맞게 처리가 필요한다.
Category 컬럼에 대하여 숫자로 인코딩이 필요하며 다양한 방안이 있지만 가장 일반적인 One-Hot 인코딩을
사용하도록 한다.
#one-hot 인코딩
df1 = pd.get_dummies(df1, drop_first=True)
#컬럼이 많아 옵션 변경이 필요함
pd.set_option('display.max_columns', 1000)
df1.head()
모델 훈련 및 평가
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
X = df1.drop('Price', axis='columns')
y = df1.Price
X_train, X_test, y_train, y_test = train_test_split(X, y, train_size=0.8, random_state=2)
model = LinearRegression()
model.fit(X_train, y_train)
print('test accuracy',model.score(X_test, y_test))
print('train accuracy',model.score(X_train, y_train))
test accuracy 0.7007745077719215
train accuracy 0.7272548867643198
추가적으로 L2, L1 규제를 적용한 Lasso/Ridge 모델 결과도 보도록 하겠습니다.
from sklearn.linear_model import Lasso # Sklearn's Lass regression is the L1 regularization.
from sklearn.linear_model import Ridge
from sklearn.linear_model import ElasticNet
lasso_model = Lasso()
lasso_model.fit(X_train, y_train)
print('l2 test accuracy',lasso_model.score(X_test, y_test))
print('l2 train accuracy',lasso_model.score(X_train, y_train))
l1_model = Ridge()
l1_model.fit(X_train, y_train)
print('l1 test accuracy',l1_model.score(X_test, y_test))
print('l1 train accuracy',l1_model.score(X_train, y_train))
el_model = ElasticNet(alpha=0.1, l1_ratio=0.5)
el_model.fit(X_train, y_train)
print('Elastic Net test accuracy',el_model.score(X_test, y_test))
print('Elastic Net train accuracy',el_model.score(X_train, y_train))
l2 test accuracy 0.7009527568387347
l2 train accuracy 0.7272489742782413
l1 test accuracy 0.7043454519542658
l1 train accuracy 0.7253954749500959
Elastic Net test accuracy 0.6371874976568843
Elastic Net train accuracy 0.6323263194777249
L2 규제를 적용한 Lasso 모델이 정확도가 가장 높았습니다. 과적합이 높으면 L2/L1 Regulation을 적용을
검토해 보시기 바랍니다.
위코드에 값의 차이가 큰 Feature에 의해 영향을 받을 수 있어 Scaler를 적용이 필요합니다.
MinMaxScaler나 StandardScaler를 사용하시면됩니다. 아래코드는 MinMaxScaler 적용코드입니다.
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
X_scaled = scaler.fit_transform(X)
X_train, X_test, y_train, y_test = train_test_split(X_scaled, y, train_size=0.8, random_state=2)
회귀모델에서는 metric을 MAE를 사용함으로 MAE를 통하여 값이 가장 낮은 모델을 선택하시면됩니다.
RandomForestRegressor가 성능이 좋아 코드를 비교해 보도록 하겠습니다.
from sklearn.ensemble import RandomForestRegressor
rfr = RandomForestRegressor()
rfr.fit(X_train, y_train)
prediction = rfr.predict(X_test)
rfr_mae = mean_absolute_error(y_test, prediction)
rfr_mae
167547.84318792998
랜덤포레스터는 스케일링이 불필요하니 참고하시기 바랍니다.(간단히 코드 구현 가능)
MAE도 linerRegression의 MAE 242425에 비해 성능이 더 좋아 보입니다.