2023.06.09 수업내용
1. 선형회귀
1. Rent 데이터셋 살펴보기
불러오기
import numpy as np
import pandas as pd
import seaborn as sns
rent_df = pd.read_csv('/content/drive/MyDrive/KDT/머신러닝&딥러닝/rent.csv')
rent_df
rent_df.info()
- 0 부터 4745번의 index를 가진 4746개의 data가 존재
- 총 columns는 12개
- BHK, Size 에서 결측치를 나타내고 있음
- Dtype은 float, int, object 3 가지 종류가 있음
컬럼 정리
- Posted On : 매물 등록 날짜
- BHK : 베드, 홀, 키친의 개수
- Rent : 렌트비
- Size : 집 크기
- Floor : 총 층수 중 몇 층
- Area Type : 공용공간을 포함하는지, 집의 면적만 포함하는지
- Area Locality : 지역
- City : 도시
- Furnishing Status : 풀옵션 여부
- Tenant Preferred : 선호하는 가족 형태
- Bathroom : 화장실 개수
- Point of Contact : 연락할 곳
rent_df.describe()
* Rent의 값이 지수적으로 나타남
round(rent_df.describe(), 2)
- 소수점 둘째 자리까지 반올림
- round를 통해 통계량을 반올림
sns.displot(rent_df['BHK'])
sns.displot(rent_df['Rent'])
* 3,500,000 내외의 Rent가 존재함을 알 수 있음
rent_df['Rent'].sort_values()
- 실재로 3,500,000 이 존재함을 확인
- 이상치 인지를 확인하는 작업을 진행
sns.boxplot(y=rent_df['Rent'])
rent_df.isna().sum()
rent_df.isna().mean()
rent_df.dropna(subset=['Size'])
- subset은 dropna()의 매개변수
- Size에 있는 결측치 데이터를 삭제
rent_df[rent_df['Size].isna()]
* rent_df 데이터프레임에서 Size 컬럼이 NaN인 행을 모두 출력
na_index = rent_df[rent_df['Size'].isna()].index
na_index
rent_df.iloc[na_index]
결측치 처리
1. 결측 데이터가 전체 데이터에 비해 양이 굉장히 적을 경우 삭제하는 것도 방법
2. 결측치에 데이터를 채울 경우 먼저 boxplot을 확인하는 것이 좋음
sns.boxplot(y = rent_df['Size'])
- boxplot을 확인 후 mean 보다는 median을 사용하는게 좋다고 판단
- 큰 이상치는 없다고 판단하였지만 분포의 비대칭성이 크다고 판단하여 중앙값을 사용하는 것이 평균보다 적절하다고 생각함
rent_df.fillna(rent_df.median()).loc[na_index]
* 마찬가지로 BHK도 똑같이 결측치 제거 작업
na_index = rent_df[rent_df['BHK'].isna()].index
na_index
sns.boxplot(y = rent_df['BHK'])
rent_df['BHK'].fillna(rent_df['BHK'].median()).loc[na_index]
rent_df = rent_df.fillna(rent_df.median())
- BHK의 경우 int 값이므로 mean(float)보다는 median(int)로 결측치를 제거하는 것이 좋음
rent_df.info()
결측치가 모두 제거된 것을 확인할 수 있음
rent_df['Area Type'].value.counts()
또는 unique를 사용할 수 있음
rent_df['Area Type'].unique()
rent_df['Area Type'].nunique()
- unique는 컬럼 값의 목록을 알 수 있음
- nunique는 목록의 개수를 알 수 있음
for i in ['Floor', 'Area Type', 'Area Locality', 'City', 'Furnishing Status', 'Tenant Preferred', 'Point of Contact']:
print(i, rent_df[i].nunique())
- Rent 값에 대한 영향을 미치는 요인을 파악하는 프로젝트라 가정한다면
- 'Posted On', 'Floor', 'Area Locality', 'Tenant Preferred', 'Point of Contact' 는 영향을 미치기 어렵다고 판단
- Floor의 경우 다음번의 데이터정리에서 다시 다루기 위해 배제함
rent_df.drop(['Posted On', 'Floor', 'Area Locality', 'Tenant Preferred', 'Point of Contact'], axis = 1, inplace = True)
rent_df.info()
* object 형태의 Area Type, City, Furnishing Status를 원 핫 인코딩으로 변환
rent_df = pd.get_dummies(rent_df, columns = ['Area Type', 'City', 'Furnishing Status'])
rent_df
* 데이터를 독립변수와 종속변수로 나눔
X = rent_df.drop('Rent', axis = 1) # 독립변수
y = rent_df['Rent'] # 종속변수
- 다른 요소 : X => 독립변수
- Rent : y => 종속변수
불러오기
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X,
y,
test_size=0.2,
random_state=10)
X_train.shape, X_test.shape
y_train.shape, y_test.shape
2. 선형 회귀(Linear Regression)
- 데이터를 통해 가장 잘 설명할 수 있는 직선으로 데이터를 분석하는 방법
- 단순 선형 회귀 분석(단일 독립변수를 이용)
- 다중 선형 회귀 분석(다중 독립변수를 이용)
from sklearn.linear_model import LinearRegression
lr = LinearRegression()
lr.fit(X_train, y_train)
pred = lr.predict(X_test)
pred
* 사진 상 데이터 생략
3. 평가 지표 만들기
3-1. MSE(Mean Squared Error)
- 예측값과 실제값의 차이에 대한 제곱에 대해 평균을 낸 값
- 제곱을 통해 오차의 음수를 제거
p = np.array([3, 4, 5]) # 예측값
act = np.array([1, 2, 3]) # 실제값
def my_mse(pred, actual):
return ((pred - actual) ** 2).mean()
my_mse(p, act)
3-2. MAE(Mean Absolute Error)
- 예측값과 실제값의 차이에 대한 절대값에 대해 평균을 낸 값
- 역전파에서 절대값은 미분이 되지 않기 때문에 딥러닝이나 머신러닝에서는 잘 쓰이지 않는다
def my_mae(pred, actual):
return np.abs(pred - actual).mean()
my_mae(p, act)
* 입력 - 히든(연산) - 출력 : 순전파
* 반대의 경우 역전파라고 함. 이때 역전파에서 미분으로 기울기를 구함
3-3. RMSE(Root Mean Squared Error)
- 예측값과 실제값의 차이에 대한 제곱에 대해 평균을 낸 후 루트를 씌운 값
def my_rmse(pred, actual):
return np.sqrt(my_mse(pred - actual))
my_rmse(p, act)
불러오기
from sklearn.metrics import mean_absolute_error, mean_squared_error
mean_absolution_error(p, act) # MAE
mean_squared_error(p, act) # MSE
mean_absolution_error(p, act, squared = False) # RMSE
3-4. 평가 지표 적용하기
mean_squared_error(y_test, pred)
mean_absolute_error(y_test, pred)
mean_squared_error(y_test, pred, squared = False)
* 이상치 제거 (1837번)
X_train.drop(1837, inplace = True)
y_train.drop(1837, inplace = True)
lr.fit(X_train, y_train)
pred = lr.predict(X_test)
mean_squared_error(y_test, pred, squared = False)
- 이상치를 제거 전, 후 비교
4. 로그 활용하기
a = [1, 2, 3, 4, 5]
b = [1, 10, 100, 1000, 10000]
sns.lineplot(x=a, y=b)
b_log = np.log(b)
b_log
np.exp(b_log)
y_train_log = np.log(y_train)
lr.fit(X_train, y_train_log)
pred = lr.predict(X_test)
mean_squared_error(y_test, pred, squared = False)
- 1837 데이터를 삭제하기전 RMSE : 41438.940
- 1837 데이터를 삭제한 후 RMSE : 41377.570
- log를 활용하여 비선형으로 변경한 후 RMSE : 70418.553
log를 이용하여 곡선으로 만들었을 때, 오차가 커짐 => 데이터가 곡선보다는 선형
데이터의 분포가 비선형일 때, 로그를 사용하는 것이 오차가 적으며, 선형일 때 로그를 사용하지 않는 것이 오차가 적음
'머신러닝&딥러닝' 카테고리의 다른 글
머신러닝 & 딥러닝 (6) - 랜덤 포레스트 (0) | 2023.06.14 |
---|---|
머신러닝&딥러닝 (5) - 서포트 백터 머신 (0) | 2023.06.13 |
머신러닝&딥러닝 (4) - 로지스틱 회귀 (2) | 2023.06.12 |
머신러닝&딥러닝 (3) - 의사결정나무 (0) | 2023.06.12 |
머신러닝&딥러닝 (1) - 머신러닝, 사이킷런, 아이리스 데이터셋, 타이타닉 데이터셋 (0) | 2023.06.08 |