ML/ 앙상블 모델(1)
앙상블 모델
- tree구조(결정트리)를 기반으로 만들어진 모델
- 여러개의 트리 모델을 이용해서 훈련하는 모델을 앙상블 모델이라고 칭합니다.
앙상블 모델 분류
- 회귀와 분류에서 모두 사용한 모델들 입니다.
- sklearn 패키지 모델은 모두 가능.
배깅(Bagging)과 부스팅(Boosting) 방식으로 나뉜다.
배깅(Bagging)
- 사용되는 여러개의 모델(여러 트리)들은 서로 독립적으로 사용됨(연관성 없음)
- 훈련 데이터는 여러 모델에 랜덤하게 적용되며, 중복되는 데이터가 있을 수도 있음.
- 훈련데이터를 사용 후에는 반환하는 방식을 사용함.
→ 반환 후에 다시 랜덤하게 추출하여 여러 모델(여러 트리)에 적용합니다.
- 대표적인 배깅 앙상블 모델은 RandomForest 모델이 있음.
- 배깅 앙상블 모델 : RandomForest , ExtraTree
- 예측 : 회귀에서는 평균값을 이용하며, 분류에서는 과반수(확률)에 따라 결정됨.
- 과적합을 해소하는 모델로 주로 사용됨
부스팅(Boosting)
- 사용되는 여러개의 모델(여러 트리)들은 서로 연관성을 가짐.
- 이전 모델(이전 트리)의 오차를 보완하여 다음 모델(다음 트리)에서 이어서 훈련이 진행되는 방식.
- 훈련데이터는 랜덤하게 추출되어 사용되지만,
→ 이전 모델 훈련에서 오차가 크게 발생했던 훈련데이터에 가중치를 부여하여 사용하게 됨.
- 대표적인 부스팅 앙상블 모델 : GradientBoost 모델이 있음.
- 모델 : GradientBoost, HistGradientBoost, XGboost
- 정확도를 높이는 모델로 주로 사용됨.
현재 글에서는 RandomForest를 적용하여 진행 예정이다.
이번 분석에서는 와인의 종류를 레드와인(0)과 화이트와인(1)로 구분하는 모델을 만들 것이다.
데이터를읽어온뒤 wine 이라는 변수에 담는다.
wine = pd.read_csv
기본사항들을 확인해준뒤, 진행하도록 하자.
wine.info()
wine.describe()
독립변수는 알콜,설탕,산성도로 하겠고 종속변수는 클래스(종류)로 하겠다.
독립변수와 종속변수로 데이터 분리하기
data = wine[["alcohol","sugar","pH"]].to_numpy()
# data = wine.iloc[:, :-1]
data.shape
두가지 형식으로 데이터를 분류할 수 있다.
to_numpy() 로하면 numpy의 형식, iloc를 활용하면 리스트의 형식으로 가져오니 알고있도록 하자.
(6497, 3)
target = wine["class"].to_numpy()
# target = wine["class"]
target.shape
이 또한 마찬가지다.
(6497,)
분리를 완료했다면 다음단계로 가는길은 두가지다. 훈련 및 테스트 데이터로 분류하기 or 정규화(스케일링)
이번에는 분리를 먼저 하도록 하겠다.
훈련과 테스트데이터로 분리하기(8:2)
#분리할때 사용하는 모델
from sklearn.model_selection import train_test_split
변수는 train_input, train_target, test_input, test_target을 사용하도록 하겠다.
train_input, test_input, train_target, test_target =
train_test_split(data, target, test_size = 0.2, random_state=42)
print(f"train_input={train_input.shape} / train_target={train_target.shape}")
print(f"test_input={test_input.shape} / test_target={test_target.shape}")
train_input=(5197, 3) / train_target=(5197,)
test_input=(1300, 3) / test_target=(1300,)
train_test_split을 이용하여 test_size=0.2(20%)로 정하여 훈련값을 0.8(80%)로 놓을 수 있다.
데이터 스케일링(정규화 또는 표준화)
데이터 스케일링이란 서로 다른 변수(특성)의 값을 범위(단위)를 일정한 수준으로 맞추는 작업이다.
정규화 1. StandardScaler / 분류 또는 회귀에서 사용가능하며, 주로 분류에서 사용 된다.
2. RobustScaler → 분류 및 회귀 모두 사용 가능.(거의사용안함)
표준화 3. MinMaxScaler / 분류 또는 회귀에서 사용 가능, 회귀에서 주로 사용 됨.
(최대 및 최소 범위 내에서 처리되는 방식)
스케일링을 위해 세가지 모두 import 해주기로 한다.
from sklearn.preprocessing import StandardScaler
from sklearn.preprocessing import RobustScaler
from sklearn.preprocessing import MinMaxScaler
정규화가 된 변수들은
훈련데이터 정규화 변수 : train_std_scaler, train_rs_scaler, train_mm_scaler
테스트데이터 정규화 변수 : test_std_scaler, test_rs_scaler , test_mm_scaler 로 하겠다.
ss = StandardScaler()
ss.fit(train_input)
train_std_scaler = ss.transform(train_input)
test_std_scaler = ss.transform(test_input)
print(f"{train_std_scaler.shape}/{test_std_scaler.shape}")
(5197, 3)/(1300, 3)
shape를 통하여 표현한것과 하지않은것의 차이를 보고가자.
rs = RobustScaler()
rs.fit(train_input)
train_rs_scaler = rs.transform(train_input)
test_rs_scaler = rs.transform(test_input)
train_rs_scaler, test_rs_scaler
(array([[ 0.11111111, 0.734375 , -0.0952381 ],
[ 1.16666667, -0.140625 , 0.23809524],
[ 0.83333333, -0.140625 , 0.95238095],
...,
[-0.44444444, 0.40625 , 0.14285714],
[-0.44444444, 0.78125 , -0.14285714],
[-0.44444444, -0.046875 , 1.42857143]]),
array([[ 1.05555556, 1.53125 , 0.23809524],
[-0.22222222, -0.125 , 0.28571429],
[ 0.94444444, 0.6875 , -0.14285714],
...,
[ 1.16666667, -0.1875 , -0.0952381 ],
[-0.5 , 1.046875 , 0.42857143],
[-0.88888889, 1.953125 , -1.47619048]]))
굉장히 복잡하고 보기싫은 형태이므로 shape를 사용하도록 하겠다.
mm = MinMaxScaler()
mm.fit(train_input)
train_mm_scaler = mm.transform(train_input)
test_mm_scaler = mm.transform(test_input)
train_mm_scaler.shape,test_mm_scaler.shape
((5197, 3), (1300, 3))
세가지 방법 모두 사용하는 방법을 알아봤으니, 가장 많이 사용하는 StandardScaler로 사용하도록 하겠다.
이를 이용하여 머신러닝을 시작하도록 하자.
머신러닝훈련하기
#훈련 모델 생성을 위한 import
from sklearn.ensemble import RandomForestClassifier
#모델 생성
rf = RandomForestClassifier(n_jobs=-1, random_state=42)
랜덤포레스트의 앞글자만 따와서 rf라는 변수로 넣는다.
해당 n_jobs = -1 이라는건 cpu의 모든 코어를 사용해서 연산한다는 뜻이고, random_state=42의 경우는 랜덤으로 섞되 42번의 방식으로 섞는다는 뜻.
# 모델훈련
rf.fit(train_std_scaler, train_target)
#정확도 확인
train_score = rf.score(train_std_scaler, train_target)
test_score = rf.score(test_std_scaler, test_target)
train_score, test_score
(0.996921300750433, 0.8892307692307693)
약간 과대적합으로 의심해 볼 수 있으려나..? 애매하다.
한번 예측을 해보도록 하자.
y_pred = rf.predict(test_std_scaler)
print(y_pred[:10])
print(test_target[:10])
[1. 0. 1. 1. 1. 1. 1. 1. 0. 1.]
[1. 0. 1. 1. 1. 0. 1. 1. 0. 1.]
10개중 1개 틀린거보면 성능이 준수해 보인다.
다음 글에서는 오차행렬도와 성능 평가방법을 알아보도록 하겠다.