본문 바로가기

Hello MLop/ML

MLop_ML_RandomForest_중고차 가격 예측

20221114

27일차

 


오늘 할 내용은 RandomForest를 이용한 중고차 가격예측이다.

데이터는 kaggle에서 참조했다.

 

간단한 데이터 세트 정보이다.

 


💡 RandomForest의 사전적 의미

 

다수결정 트리들을 학습하는 앙상블 방법이다.

랜덤 포레스트는 검출, 분류, 그리고 회귀 등 다양한 문제에 활용되고 있다.

 


 

❗ 앙상블 방법

 

학습 알고리즘(learning algorithm)들을 따로 쓰는 경우에 비해 더 좋은 예측 성능을 얻기위해 다수의 학습 알고리즘을 사용하는 방법이다.

 

앙상블 방법은 랜덤 포레스트의 랜덤화 특성을 더욱 향상 시켜준다.

 

이러한 방법으로한 포레스트의 예측 결과모든 트리예측 결과들의 평균으로 얻는다.


간단하게 설명하면 결정트리한계점을 보완해 만들어진것이 랜덤 포레스트이다.

 

💡 결정트리의 한계점

 

1. 결정 트리를 이용한 방법의 경우, 그 결과 또는 성능의 변동 폭이 크다.

2. 랜덤성에 따라 매우 다르기 때문에 일반화하여 사용하기에 어려움

3. 계층적 접근방식이기 때문에 만약 중간에 에러가 발생한다면 다음 단계로 에러가 계속 전파되는 특성

 

 

💡 랜덤 포레스트의 장점

  • 월등히 높은 정확성
  • 간편하고 빠른 학습 및 테스트 알고리즘
  • 변수소거 없이 수천 개의 입력 변수들을 다루는 것이 가능
  • 임의화를 통한 좋은 일반화 성능
  • 다중 클래스 알고리즘 특성

 


💡 랜덤 포레스트의 가장 중요한 특징!

 

랜덤성(randomness)에 의해 트리들이 서로 조금씩 다른 특성을 갖는다는 점이다.

 

이 특성은 각 트리들예측(prediction)들비상관화(decorrelation) 되게하며,

결과적으로 일반화(generalization) 성능을 향상

 


쉽게 설명하면 포레스트는 , 즉 나무(트리)가 모여있는 형태이다.

결정트리는 하나의 이념을 가지고 결과를 냈다면

 

랜덤포레스트는 서로 조금씩 다른 이념1 이념2 이념3 ....을 가지고 결과를 내기 때문에

결과들이 다르며 추가로 서로 상관성이 없다.

 

때문에 일반화 성능이 향상된다.

 

 


그럼 이제 데이터를 불러보자.

 

 

데이터 불러오기 및 임포트

 


 

데이터 확인

 

 

결측치 및 데이터 타입 확인

 


전처리 시작

 

engine컬럼unique()를 찍어보니단위에 의해 unique의 개수가 너무 많다는것을 확인했다.심지어 숫자와 문자가 합쳐진 양식이다.

 


오브젝트만을 df에서 describe 했더니

 

'mileage','engine','max-power' 컬럼이 동일한 형태로 데이터가 저장되어 있는것을 확인했다.

 

# (숫자) (단위)

 


 

.split을 통해 나눠주는데 expand=True를 통해 열로 쪼개준것을 확인할 수 있다.

 


이를 df에 저장해주면

'engine'컬럼은 수치를 가지는 컬럼

'engine_unit' 컬럼은 단위를 가지는 컬럼으로 저장된다.


하지만 수치를 원했던 'engine'컬럼이 문자열에서 split된 결과

dtype이 object였고 우린 이를 숫자형태로 바꿔줘야 했다.

 


.astype('float32')를 사용해

'engine'컬럼의 데이터가 float32로 바뀐것을 볼 수 있다.

 

그리고 .unique()를 찍어보니

문자는 'CC'만 남아있었다.

 

마지막으로 깔끔하게

다 써먹고 필요없는 'engine_unit'컬럼을 삭제해 주었다.

 


'max_power_unit' 컬럼 또한 똑같은 방법으로 처리하려고 했지만

오류가 났다!

 

 

바로 'max_power_unit' 컬럼 안에 (숫자) (단위) 형태가 아닌

'bhp' # (단위) 만 존재하는 데이터가 있었기 때문이다.

 



함수를 선언(def)해 처리하는 방식도 있지만

 

정규표현식을 이용해 처리해 주었다.

 

 

 

✨ 정규 표현식

 

문자열내에서 원하는 조건을 검색하여 뽑아 주는식

위의 정규표현식 '([\d\.]+)' 

 

[] 인덱싱 하겠다.

''(문자열) 안에서

(dtype =digit)를 . 을 포함해서+ 는 2개이상을 의미한다!\ 는 범위다. \~\까지 검색하겠다.

 

처리한 결과 'max_power_unit' 컬럼의 unique는

추출한 'bhp'  , 숫자형 결측치 nan, str형 결측치 None으로

조회된다.

 

역시 마무리는 drop 해 주었다.

 


'mileage'컬럼을

'mileage'에는 수치'mileage_unit'에는 단위를 저장하게 split해주고

 

 

'mileage'컬럼의  데이터 타입을 'float32'으로  바꿔주면

원하는 형태로 된다.

 


 

하지만 'mileage'컬럼의 데이터는 단위가 위와 같이

'mileage_unit'의 단위이다.

 

그런데 문제는 단위가 복합단위이기때문에 수치 또한 저 복합단위에 의한 수치이다.

그래서 이것을 쪼개서 반영해줘야한다.

 


도메인 지식을 활용해

특정 시점의 종류별 연료금액을  가져와서 딕셔너리 형태로  만들고

 

함수를 선언해 현재 'mileage'의 값들을 환산해주는 로직을 만들었다.

 

그 결과 'mileage'컬럼의 데이터가 환산된 수치로 저장 되었고

마지막으로 'mileage_unit'컬럼을 drop해 주었다.

 

 


'torque'컬럼은 위와 같이 특수문자 및 문자, 숫자가 섞여있는 데이터로 이루어져 있었다.

이 데이터들을 차례대로 분해해서 인덱싱해 원하는 값을 추출하는 전처리를 해보자.

 

 

우선 위의 데이터에서 단위들을 뽑기 위해

'torque'컬럼의 데이터중 str.upper() # 대문자 로 바꿔주었다.

 

 

그리고 단위를 뽑아내는 함수를 선언하고

'torque_unit' 컬럼에 저장해주었다.

 

이렇게 하고 보니 결측치가 생겼고

 

결측치를 채워주기위해 결측치를 세어보니

'Nm'이 100개 이상이었고

'kgm'은 100개 미만이었기에 'Nm'으로 결측치를 채워줬다.

 

 

위의 정규표현식으로 'torque'의 데이터를 원하는 값만 뽑아주는 작업을 하고 보니현재 추출해낸 값들은 단위가 다 다르다.

 

그래서 통일화된 연속병 변수로 만들기 위해도메인 지식을 활용했다.

 

df.torque 즉  'torque'컬럼에 정규표현식을 사용해 추출한 연속형 변수들을 저장하고

 

9.8066kgm = Nm이다.도메인 지식을 활용해

 

단위변환 함수를 선언해주고

'torque'의 값들을 치환해주었다.

 

마지막으로 'torque_unit'을 삭제해

'torque'컬럼의 전처리를 마무리 해준다.

 


'name'컬럼의 데이터들은 너무 고유성이 확실하므로 그대로 보존해두고

 

다만 한가지 걸린 'Land Rover'의 브랜드를 'Land'로 저장해놔서

다시  원래대로 바꿔줬다.

 


전처리의 막바지.범주형 변수들을 전부 get_dummies 해주었다.

 

❗ drop_first = True 필수

 

 


 

훈련셋과 시험셋으로 나눠주고

종속변수'selling_price'로 해준다.

 

 

⭐⭐⭐⭐⭐

우리의 주된 목적은 분류가 아닌 가격 예측 이므로

RandomForestRegressor모델로 사용한다.

 

그리고 학습! 예측!

 

값을 예측하는것은

오차를 확인해야 하기에

 

대표적인 Regressor오차 확인법

 

RMSE (제곱평균오차)를 확인하기 위해 사이키런에서 mean_squared_error 를 임포트 해준다.

 

그 결과 출력된 RMSE를 보니

train값과 test값이 너무 차이나는것을 확인할 수 있다.

 

 


이럴 경우 좀 더 많은 시험셋과 테스트셋 구성을 만들어 비교해 볼 수 있는

K-Fold 교차검증!

 

조금 더 모델의 신뢰성을 높이기 위한 귀찮은 과정이다.

 

사이키런 라이브러리에서 KFold를 임포트 해준다.

 

df의 인덱스를 초기화 시켜 RangeIndex로 바꿔주고

이미 모델링이 되있기 때문

다시 훈련셋과 테스트셋으로 나눠질

X(독립변수)와 y(종속변수)를 정해준다.

 

그리고 위와 같이 for문을 통해 5개훈련셋 & 테스트셋을 만들어 준다.

 

 

이제 반복문을 통해

결과를 출력해보자.

 

총 5개의 결과가 나왔고 평균을 구해준다.

 

그럼에도 불구하고 train_rmsetest_rmse오차가 큰것을 알 수 있다. 


 

 

 

💡 하이퍼 파라미터 설정 후 재 러닝

 

결과 차이 없음.