본문 바로가기
Python/ML&DL

[파이썬, Python] 머신러닝 - 1️⃣ 선형 회귀(Linear Regression)

by coding-choonsik 2023. 6. 14.
728x90
반응형
SMALL

📄 예제로 사용할 파일

 

rent.csv
0.54MB

 

1. Rent 데이터셋 살펴보기

import numpy as np
import pandas as pd
import seaborn as sns
rent_df = pd.read_csv('/content/drive/MyDrive/KDT/Python/4.머신러닝 딥러닝/rent.csv')
rent_df

rent_df.info()

 

 

✅ 각 컬럼에 대한 설명

 

✅ 데이터셋의 수치형 데이터 정보 알아보기

rent_df.describe()

 

✅ float형 데이터를 반올림하여 보기

round(rent_df.describe(),2)   # 소수점 둘째자리까지 표현하여 나타냄

 

✅ 'BHK' 열의 데이터 별 개수를 시각화하여 알아보기

sns.displot(rent_df['BHK'])   # Bed, Hall, Kitchen의 개수(count)

 

✅ 'Rent' 열의 데이터별 개수 시각화하여 알아보기

 # 데이터가 한쪽에 쏠림 -> x축의 범위까지 데이터가 있다는 뜻임(보이진 않지만)
sns.displot(rent_df['Rent'])

 

✅ 'Rent'열의 x축 범위가 넓기 때문에 데이터를 정렬하여 알아보기

rent_df['Rent'].sort_values()   # 마지막 데이터와의 차이가 큼,3500000까지 있음 -> 이상치라고 판단할 수 있다.

 

boxplot을 통해 이상치 판단하기

sns.boxplot(y=rent_df['Rent'])  # 데이터가 몰려있는 부분을 제외한 벗어나는 부분은 outlier일 가능성이 높다.

▲ 데이터들의 분포가 너무 동떨어져있는 값은 이상치라고 판단할 수 있다.

 

✅ 결측치 알아보기

rent_df.isna().sum()

 

rent_df.isna().mean()  # 결측값의 비율

▲ 결측값의 비율이 1% 정도

 

 

✅ 'Size'열의 결측 데이터의 비율이 굉장히 작기 때문에 결측 데이터를 삭제

rent_df.dropna(subset=['Size'])  # Size 열에서의 null값인 데이터를 삭제

 

 

✅ Size열의 NaN이 있는 행을 출력

rent_df[rent_df['Size'].isna()]

 

 

✅ Size 열에서의 데이터가  NaN 인 데이터의 인덱스값들을 출력

 

na_index = rent_df[rent_df['Size'].isna()].index
na_index

>>> Int64Index([425, 430, 4703, 4731, 4732], dtype='int64')

 

✅ 결측치 처리

  • 1. 결측 데이터가 전체 데이터에 비해 양이 굉장히 적을 경우 삭제하는 것도 방법
  • 2. 결측치에 데이터를 채울 경우 먼저 boxplot을 확인하는 것이 좋음
  •  bokplot확인: 데이터의 분포의 범위가 넓기 때문에 평균으로 했을 때 데이터의 값이 증가될 것이라고 판단 -> 중앙값(50%)으로 결측치를 채우자.

'SIze'열의 결측치 처리

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
>>> Int64Index([3, 53, 89], dtype='int64')

rent_df['BHK'].fillna(rent_df['BHK'].median()).loc[na_index]

 

rent_df = rent_df.fillna(rent_df.median())

 

✅ rent_df의 정보 다시 확인

rent_df.info()

 

 

✅ Object형 데이터 라벨 인코딩 하기

  • Area Type은 텍스트 형태이기 때문에 모델에서 계산 할 수 없음
  • 라벨 인코딩을 통해 숫자로 변경
  • 독립변수로 들어갈 컬럼은 모두 숫자로 변경해야함
rent_df['Area Type'].value_counts()

 

✅ 중복값을 제외한 데이터의 종류 알아보기

rent_df['Area Type'].unique()  # 중복값을 제외한 종류를 알아볼 수 있음

>>> array(['Super Area', 'Carpet Area', 'Built Area'], dtype=object)

 

 

✅ 반복문을 이용하여 dtype이 object형인 컬럼들을 라벨인코딩하기 위해 중복데이터를 제외한 데이터 개수 알아보기

for i in ['Floor', 'Area Type', 'Area Locality', 'City', 'Furnishing Status', 'Tenant Preferred', 'Point of Contact']:
  print(i, rent_df[i].nunique())

▲라벨인코딩 할 수가 너무 많은 경우 학습의 부하와 정확도가 떨어질 수 있음 ➡ 빼는 것이 좋다

 

 

 

모델 학습에 있어서 빼는 것이 좋다고 판단한 피쳐들 제거하기

rent_df.drop(['Posted On', 'Floor', 'Area Locality', 'Tenant Preferred', 'Point of Contact'], axis=1, inplace=True)  # 학습에 필요없는 열들을 날림
rent_df.info()

 

 

✅ object형 컬럼 원 핫 인코딩 하기

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']  # 종속변수

 

✅ 학습 데이터와 검증 데이터 분할하기

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
>>> ((3796, 15), (950, 15))

y_train.shape, y_test.shape
>>> ((3796,), (950,))

2. 선형회귀(Linear Regression)

  • 데이터를 통해 가장 잘 설명할 수 있는 직선으로 데이터를 분석하는 방법
    • 단순 선형 회귀 분석(단일 독립변수를 이용)
    • 다중 선형 회귀 분석(다중 독립변수를 이용)
from sklearn.linear_model import LinearRegression

lr = LinearRegression()  # 객체 생성

# 모델 학습
lr.fit(X_train, y_train)

# 검증 데이터로 예측
pred = lr.predict(X_test)
pred

 


3. 평가지표 적용하기

평가 지표 종류 알아보기 ⬇⬇⬇

 

[파이썬, Python] 평가지표 - MSE, MAE, RMSE

1. MSE(Mean Squared Error, 평균 제곱근 오차) 예측값과 실제값의 차이에 대한 제곱에 대하여 평균을 낸 값 p = np.array([3,4,5]) # 예측값 act = np.array([1,2,3]) # 실제값 (오차가 있는것!) def my_mse(pred, actual): retu

coding-yesung.tistory.com

 

# MSE
mean_squared_error(y_test, pred)  
>>> 1717185779.0021067

# RMSE
mean_squared_error(y_test, pred, squared=False)  
>>> 41438.9403701652

# MAE
mean_absolute_error(y_test, pred) 
>>> 22779.17722543894

 

✅ 이상치를 제거한 후 모델 성능 평가하기

# rent_df['Rent']에서의 이상치라고 판단한 데이터 인덱스값 1837
X_train.drop(1837, inplace=True)
y_train.drop(1837, inplace=True)


# 학습
lr.fit(X_train, y_train)

# 검증데이터로 예측
pred = lr.predict(X_test)

# RMSE
mean_squared_error(y_test, pred, squared=False)  
>>> 41377.57030234839

 # 이상치 제거 후 오차가 줄어듦
# 41438.9403701652 - 41377.57030234839 
>>> 61.37006781680975

 


4. log 활용하기

평가 지표를 로그 변환하여 적용하는 이유!

1. 비선형 관계의 선형화

  • 종속 변수와 독립 변수 간의 비선형적인 관계가 있는 경우, 로그 변환을 통해 비선형 관계를 선형 관계로 변환할 수 있음
  • 이를 통해 선형 회귀 모델이 더 적합한 예측이 가능

 

2. 이상치 처리

  • 로그 변환은 이상치에 민감하지 않은 변환 방법
  • 이상치가 있는 경우에 로그 변환을 적용하면 이상치의 영향을 완화시킬 수 있음
# 종속변수 학습 데이터를 log화 하기
# exp(): 지수함수로 변환
y_train_log = np.log(y_train)

# 학습
lr.fit(X_train, y_train_log)

# 검증 데이터로 예측
pred = lr.predict(X_test)

# RMSE
mean_squared_error(y_test, pred, squared=False)

# 41377.57030234839 - 70418.55375574114 = -29040.983453392757

 

  • 1837 데이터를 삭제하기 전 RMSE: 41438.9403701652
  • 1837 데이터를 삭제한 후 RMSE: 41377.57030234839
  • log를 활용하여 비선형으로 변경한 후 RMSE : 70418.55375574114

📍  데이터의 분포가 비선형일 때 로그를 사용하는 것이 오차가 적으며, 선형일 때 로그를 사용하지 않는 것이 오차가 적음.

 

 

728x90
반응형
LIST