๋ชฉํ
- ์ฌ์ดํท๋ฟ ํ์ดํ๋ผ์ธ(pipeline) ์ดํด
- ์ฌ์ดํท๋ฐ ๊ฒฐ์ ํธ๋ฆฌ(decision tree) ์ดํด
- ๊ฒฐ์ ํธ๋ฆฌ์ ํน์ฑ ์ค์๋(feature importance)๋ฅผ ํ์ฉ
- ๊ฒฐ์ ํธ๋ฆฌ ๋ชจ๋ธ์ ์ฅ์ ์ ์ดํดํ๊ณ ์ ํํ๊ท๋ชจ๋ธ๊ณผ ๋น๊ต
๊ฐ๋จํ ๋ฐ์ดํฐ ํ์ธ ํ
train.head().T # Transpose ์ฌ์ฉํ์ฌ feature์ ๋ํด ๋ณด๊ธฐ ํธํ๊ฒ
# target์ ๋ํด ํ๊ท์ ๋ถ๋ฅ ์ค ์ด๋ ๊ฒ์ผ๋ก ํ ์ง ํ๋จ ๊ฐ๋ฅ/ ๋ถ๋ฅ๋ฌธ์ ๋ผ๋ฉด ์ต๋น๊ธฐ์ค๋ชจ๋ธ ์ ํ๋ ๊ธฐ์ค, ๋ฐ์ดํฐ ๋ถํฌ ํ์ธ
train[target].value_counts(normalize=True)
# ProfileReport
!pip install pandas-profiling==2.8.0 --user # ์ต์ ์ด ์๋๋ฉด ์๋ฌ๊ฐ ๋๋ ๊ฒฝ์ฐ๊ฐ ์์
from pandas_profiling import ProfileReport
profile = ProfileReport(train)
# '์ค๋ณต๋ ํน์ฑ'์ด ์๋์ง ํ์ธ
train.T.duplicated()
# '์ซ์ํ' ๋ณ์๊ฐ ์๋ ๋ณ์๋ค ํ์ธ -> OneHotencoding ์ Cardinality ๋๋ฌด ๋์ ์ ๋ค ํ์ธ ๊ฐ๋ฅ
train.describe(exclude='number')
train.describe(exclude='number').T.sort_values(by='unique')
def engineer(df):
# ๋ด๊ฐ ์์ง๋์ด๋ง ํ๊ณ ์ถ์๋๋ก ํจ์ ๋ง๋ค๊ธฐ (ํ์ X_train/X_val/X_test์ ์ ์ฉํ๊ธฐ ํธํ๊ฒ)
# ์ถ๊ฐ๋ก target ์ด์ธ์ features ๊ณ ๋ฅผ ๋
features = train.drop(columns=[target]).columns # 1๋ฒ ๋ฐฉ๋ฒ
features = train.columns.difference([target], sort=False) # 2๋ฒ ๋ฐฉ๋ฒ
Pipeline(ํ์ดํ๋ผ์ธ) ๋ผ์ด๋ธ๋ฌ๋ฆฌ
- ๋ง ๊ทธ๋๋ก ๋จธ์ ๋ฌ๋ ํ๋ก์ธ์ค์ ๋ค์ด๊ฐ๋ ์ฌ๋ฌ ์ธ์ฝ๋๋ค์ ๊น๋ํ๊ฒ ์ธ ์ ์๋ค!
pipe = make_pipeline(
OneHotEncoder(),
SimpleImputer(),
StandardScaler(),
LogisticRegression(n_jobs=-1)
)
pipe.fit(X_train, y_train)
- ๋จ, ๊ทธ ์์ ์๋ ์ธ์ฝ๋์ ์ ๊ทผํ๊ณ ์ถ์ ๋๋ ์ ๊น ๋ถํดํด์ ์ฌ์ฉํ๋ ๋๋์ผ๋ก ๊ฐ๋ฉด ๋๋ค.
pipe.named_steps # pipe ๋ด์ ์ฌ๋ฌ ์ธ์ฝ๋๋ค์ dictionary ํ์์ผ๋ก ์ ์ฅ
# ์ด๋ฐ ์์ผ๋ก ๊ฐ ์ธ์ฝ๋๋ฅผ ๊ฐ์ ธ์ฌ ์ ์๋ค.
model_lr = pipe.named_steps['logisticregression']
enc = pipe.named_steps['onehotencoder']
{'onehotencoder': OneHotEncoder(cols=['opinion_h1n1_vacc_effective', 'opinion_h1n1_risk', 'opinion_h1n1_sick_from_vacc', 'agegrp', 'census_msa']), 'simpleimputer': SimpleImputer(), 'standardscaler': StandardScaler(), 'logisticregression': LogisticRegression(n_jobs=-1)}
Decision Tree Model(๊ฒฐ์ ํธ๋ฆฌ๋ชจ๋ธ)
- ํน์ฑ๋ค์ ๊ธฐ์ค์ผ๋ก ์ํ์ ๋ถ๋ฅํด ๋์๊ฐ๋๋ฐ, ๊ทธ ํํ๊ฐ ๋๋ฌด์ ๊ฐ์ง๊ฐ ๋ป์ด๋๊ฐ๋ ๋ชจ์ต๊ณผ ๋ฎ์์ต๋๋ค.
- ๋ง์น ์ค๋ฌด๊ณ ๊ฐ๋ฅผ ํ๋ฏ์ด ํน์ฑ๋ค์ ์์น๋ฅผ ๊ฐ์ง๊ณ ์ง๋ฌธ์ ํ๋ฉฐ ์ ์ฐจ ์ ๋ต์ ์ฐพ์๊ฐ๋ ๊ณผ์
- ์ง๋ฌธ ํน์ ๋ง๋จ์ ์ ๋ต์ 'node(๋ ธ๋)'๋ผ๊ณ ํ๋ฉฐ ๋ ธ๋๋ฅผ ์ฐ๊ฒฐํ๋ ์ ์ 'edge(์ฃ์ง)'๋ผ๊ณ ํฉ๋๋ค.
- ๊ฐ node(๋ ธ๋)๋ root node(๋ฟ๋ฆฌ๋ ธ๋), internal node(์ค๊ฐ๋ ธ๋), leaf(external, terminal) node(๋ง๋จ ๋ ธ๋)๋ก ๊ตฌ๋ถ
- ๊ฒฐ์ ํธ๋ฆฌ๋ ๋ถ๋ฅ์ ํ๊ท๋ฌธ์ ์ ๋ชจ๋ ์ ์ฉ ๊ฐ๋ฅ
- ๊ฒฐ์ ํธ๋ฆฌ๋ ๋ฐ์ดํฐ๋ฅผ '๋ถํ 'ํด ๋์๊ฐ๋ ๊ณผ์
- ๋ถ๋ฅ ๊ณผ์ ์ ์๋ก์ด ๋ฐ์ดํฐ๊ฐ ํน์ ๋ง๋จ ๋ ธ๋์ ์ํ๋ค๋ ์ ๋ณด๋ฅผ ํ์ธํ ๋ค ๋ง๋จ๋ ธ๋์ ๋น๋๊ฐ ๊ฐ์ฅ ๋์ ๋ฒ์ฃผ๋ก ๋ฐ์ดํฐ๋ฅผ ๋ถ๋ฅ
- ๊ฒฐ์ ํธ๋ฆฌ๋ ๋ถ๋ฅ๊ณผ์ ์ ํธ๋ฆฌ๊ตฌ์กฐ๋ก ๊ต์ฅํ ์ง๊ด์ ์ผ๋ก ํ์ธํ ์ ์๋ค๋ ์ฅ์ ์ด ์์ต๋๋ค.
Decision Tree Model(๊ฒฐ์ ํธ๋ฆฌ๋ชจ๋ธ) - ํ์ต ์๊ณ ๋ฆฌ์ฆ
- ๊ฒฐ์ ํธ๋ฆฌ๋ฅผ ํ์ตํ๋ ๊ฒ์ '๋ ธ๋๋ฅผ ์ด๋ป๊ฒ ๋ถํ ํ๋๊ฐ'์ ๋ํ ๋ฌธ์ ์ฆ, ๋ถํ ๋ฐฉ๋ฒ์ ๋ฐ๋ผ ๋ค๋ฅธ ํธ๋ฆฌ๊ฐ ๋์ค๊ฒ ๋ฉ๋๋ค.
- ๊ฒฐ์ ํธ๋ฆฌ์ ๋น์ฉํจ์๋ฅผ ์ ์ํ๊ณ ๊ทธ๊ฒ์ ์ต์ํํ๋๋ก ๋ถํ ํ๋ ๊ฒ์ด ํธ๋ฆฌ๋ชจ๋ธ ํ์ต ์๊ณ ๋ฆฌ์ฆ
- Gini Impurity(Index) : ์ง๋ ๋ถ์๋
$${\displaystyle I_{G}(p)=\sum_{i=1}^{J}p_{i}(1-p_{i})=1-\sum_{i=1}^{J}{p_{i}}^{2}}$$
- Entropy(์ํธ๋กํผ)
$${\displaystyle \mathrm {H}(T)=\operatorname I_{E}\left(p_{1},p_{2},...,p_{J}\right)=-\sum_{i=1}^{J}{p_{i}\log_{2}p_{i}}}$$
์ํธ๋กํผ๊ฐ ์ข๋ ๊ท ํ์กํ Tree๋ฅผ ๋ง๋ ๋ค๊ณ ํฉ๋๋ค. ๋ค๋ง, ์ง๋๋ถ์๋๊ฐ ๋ ๊ณ์ฐ์ด ๋น ๋ฅด๊ธฐ ๋๋ฌธ์ ์์ฃผ ์ฌ์ฉ๋ฉ๋๋ค.
- Impurity(๋ถ์๋)๋ '์ฌ๋ฌ ๋ฒ์ฃผ๊ฐ ์์ฌ ์๋ ์ ๋' ์ฆ, ์์๋์ ๋ฐ๋ ๋๋..!
- A,B ๋ ํด๋์ค๊ฐ 1๋ฒ(45%, 55%), 2๋ฒ(80%, 20%)๋ก ์์ธ ๊ฒฝ์ฐ, 1๋ฒ์ด ๋ถ์๋๊ฐ ๋ ๋๋ค.
- ๋ถํ ์ ์ฌ์ฉํ ํน์ฑ์ด๋ ๋ถํ ์ง์ (๊ฐ)์ ํ๊ฒ๋ณ์๋ฅผ ๊ฐ์ฅ ์ ๊ตฌ๋ณํด์ฃผ๋(๋ถ์๋์ ๊ฐ์๊ฐ ์ต๋๊ฐ ๋๋, ์ฆ '์ ๋ณดํ๋์ด ๊ฐ์ฅ ํฐ') ๊ฒ์ ์ ํํฉ๋๋ค.
- ์ฌ๊ธฐ์ 'Information Gain(์ ๋ณดํ๋)'์ด๋ ํน์ ํน์ฑ์ ์ฌ์ฉํด ๋ถํ ํ์ ๋ ๋ถ์๋์ ๊ฐ์๋์ ๋ปํฉ๋๋ค.
$${\displaystyle I_G(T,a)=\mathrm {H} {(T)}-\mathrm {H} {(T|a)}} = ๋ถํ \ ์ \ ๋ ธ๋\ ๋ถ์๋ - ๋ถํ \ ํ\ ์์๋ ธ๋๋ค์\ ๋ถ์๋$$
Decision Tree Model(๊ฒฐ์ ํธ๋ฆฌ๋ชจ๋ธ) - DecisionTreeClassifier()
# ์์
from sklearn.tree import DecisionTreeClassifier # ๊ฒฐ์ ํธ๋ฆฌ๋ถ๋ฅ ๋ชจ๋ธ์ ์ค์ผ์ผ๋ง์ ํด์ค ํ์๊ฐ ์๋ค. ๋ถ๋ฅ ๊ฐ๋
์ด๊ธฐ์ ๊ฐ ์นผ๋ผ ๋ณ ๋จ์๋ฅผ ๋ง์ถ ํ์๊ฐ ์์
pipe = make_pipeline(
OneHotEncoder(use_cat_names=True),
SimpleImputer(),
DecisionTreeClassifier(random_state=1, criterion='entropy')
)
๋ง๋ค์ด์ง Tree model ์๊ฐ์ ์ผ๋ก ํ์ฉํ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์์
# graphviz ์ค์น๋ฐฉ๋ฒ: conda install -c conda-forge python-graphviz
import graphviz
from sklearn.tree import export_graphviz
model_dt = pipe.named_steps['decisiontreeclassifier']
enc = pipe.named_steps['onehotencoder']
encoded_columns = enc.transform(X_val).columns
dot_data = export_graphviz(model_dt
, max_depth=3
, feature_names=encoded_columns
, class_names=['no', 'yes']
, filled=True
, proportion=True)
display(graphviz.Source(dot_data))
Decision Tree Model(๊ฒฐ์ ํธ๋ฆฌ๋ชจ๋ธ) - DecisionTreeClassifier()์ Hyperpaameter
ํธ๋ฆฌ ๋ชจ๋ธ์ ๊ณผ์ ํฉ์ด ๋ฐ์ํ๊ธฐ ์ฝ์ต๋๋ค.(๊ฐ ๊ด์ธก๊ฐ์ ๋ถํ ํ๋ฉด์ ๊ฒฐ๊ตญ์ ๋๊น์ง ๊ทธ ๊ฐ ํ๋๋ง ๋จ์ ๋ ๊น์ง ๋ถ๊ธฐ๋ฅผ ํ๋ฏ๋ก)
ํด์ ์ด๋ฐ ๊ณผ์ ํฉ์ ๋ง์์ค ์ ์๋ ์กฐ๊ฑด์ ์ค์ ํ ์ ์์ต๋๋ค.(ํ์ดํผ๋ง๋ผ๋ฏธํฐ์ ์ญํ )
๋ํ์ ์ธ 3๊ฐ์ง
- min_samples_split -> ex) 100์ผ๋ก ์ค์ ํ๋ฉด sample์ด 100๊ฐ ์ด์์ผ ๋๋ง ๋ถ๊ธฐ
- min_samples_leaf -> ex) 100์ผ๋ก ์ค์ ํ๋ฉด leaf node์ ์ต์ํ 100๊ฐ์ sample์ด ์์ด์ผ ํจ
- max_depth -> Tree์ ์ ์ฒด์ ์ธ ๊น์ด๋ฅผ ์กฐ์ (๋ถ๊ธฐํ๋ ์ธต์ ์ต๋ ๋ช๊น์ง ๊ฐ์ ธ๊ฐ๋๋)
Decision Tree Model(๊ฒฐ์ ํธ๋ฆฌ๋ชจ๋ธ) - DecisionTreeClassifier()์ feature importance(ํน์ฑ ์ค์๋)
- ์ ํ๋ชจ๋ธ์์๋ ํน์ฑ๊ณผ ํ๊ฒ์ ๊ด๊ณ๋ฅผ ํ์ธํ๊ธฐ ์ํด coefficients(ํ๊ท ๊ณ์)๋ฅผ ์ดํด๋ณด์์ต๋๋ค.
- ๊ฒฐ์ ํธ๋ฆฌ์์๋ ๊ทธ ์ญํ ์ ํ๋ ๊ฒ feature importance(ํน์ฑ ์ค์๋)์ ๋๋ค.
- ํน์ฑ์ด ์ผ๋ง๋ ์ผ์ฐ, ์์ฃผ ๋ถ๊ธฐ์ ์ฌ์ฉ๋๋์ง๋ฅผ ํ์ธ ๊ฐ๋ฅํฉ๋๋ค.
model_dt = pipe.named_steps['decisiontreeclassifier'] # ํ์ดํ๋ผ์ธ์ผ๋ก ๋ฌถ์ฌ์๋ ๊ฒฝ์ฐ
importances = pd.Series(model_dt.feature_importances_, encoded_columns)
plt.figure(figsize=(10,30))
importances.sort_values().plot.barh(); # ํน์ฑ ์ค์๋๋ ์ดํฉ์ด 1์ด ๋๊ฒ๋ normalized ๋์ด์๋ค.
์ถ๊ฐ ๋ด์ฉ
- ๊ฒฐ์ ํธ๋ฆฌ๋ชจ๋ธ์ ์ ํ๋ชจ๋ธ๊ณผ ๋ฌ๋ฆฌ ๋น์ ํ, ๋น๋จ์กฐ(Non-monotonic), feature interactions(ํน์ฑ์ํธ์์ฉ) ํน์ง์ ๊ฐ์ง๊ณ ์๋ ๋ฐ์ดํฐ ๋ถ์์ ์ฉ์ดํฉ๋๋ค.
- ํน์ฑ์ํธ์์ฉ : ํน์ฑ๋ค๋ผ๋ฆฌ ์๋ก ์ํธ์์ฉ์ ํ๋ ๊ฒฝ์ฐ(==๋ค์ค๊ณต์ ์ฑ), ํ๊ท ๋ถ์์์๋ ๋ณ์๋ค๊ฐ์ ์ํธ์์ฉ์ด ๋์ผ๋ฉด ๊ฐ๋ณ ๊ณ์๋ฅผ ํด์ํ๋๋ฐ ์ด๋ ค์์ด ์๊ณ ํ์ต์ด ์ฌ๋ฐ๋ฅด๊ฒ ๋์ง ์์ ์ ์์ต๋๋ค. ํ์ง๋ง, ํธ๋ฆฌ๋ชจ๋ธ์ ์ด๋ฐ ์ํธ์์ฉ์ ์๋์ผ๋ก ๊ฑธ๋ฌ๋ด๋ ํน์ง์ด ์์ต๋๋ค
์๊ฐํด๋ณด๋ฉด, ๋ ธ๋๊ฐ ๋ถ๊ธฐํ ๋ ๋ถ์๋๋ฅผ ๋ง์ด ๋ฎ์ถ๋ ํน์ง์ผ๋ก ๋ถ๊ธฐ๋ฅผ ํ๊ฒ ๋๋๋ฐ ๋ง์ฝ ์๊ด์ฑ์ด ๊ต์ฅํ ๋์ ๋ณ์๊ฐ ์์ด์ ์์์ ์ด๋ฏธ ๊ทธ ๋ณ์๋ฅผ ํตํ ๋ถํ ์ด ๋์๋ค๋ฉด, ๊ทธ ๋ค์ ์๊ด์ฑ์ด ๋์ ๋ณ์๋ ์ด์ฐจํผ ๋ถ์๋๋ฅผ ๋ฎ์ถ๋๋ฐ ํฐ ์ญํ ์ ํ ์ ์๊ฒ ๋จ(์ด๋ฏธ ์์์ ์ ์ฌํ ์ญํ ๋ก ๋ถํ ์ ์งํํ๊ธฐ์) ๋ฐ๋ผ์, ํธ๋ฆฌ๋ชจ๋ธ์์๋ ๋ค์ค๊ณต์ ์ฑ์ด ํฐ ๋ฌธ์ ๊ฐ ๋์ง ์์ต๋๋ค.
๋์ค์ ์ฐธ๊ณ ํ ์ ์์ ์๋ฃ
DecisionTreeRegressor Model์ max_depth๋ฅผ ์กฐ์ ํจ์ผ๋ก์จ ์ ์ ๊ด์ฐฎ๊ฒ fitting ๋๋ ๋ชจ์ต
import pandas as pd
from sklearn.linear_model import LinearRegression
columns = ['mobility', 'density']
data = [[80.574, -3.067]
,[84.248, -2.981]
,[87.264, -2.921]
,[87.195, -2.912]
,[89.076, -2.84]
,[89.608, -2.797]
,[89.868, -2.702]
,[90.101, -2.699]
,[92.405, -2.633]
,[95.854, -2.481]
,[100.696, -2.363]
,[101.06, -2.322]
,[401.672, -1.501]
,[390.724, -1.46]
,[567.534, -1.274]
,[635.316, -1.212]
,[733.054, -1.1]
,[759.087, -1.046]
,[894.206, -0.915]
,[990.785, -0.714]
,[1090.109, -0.566]
,[1080.914, -0.545]
,[1122.643, -0.4]
,[1178.351, -0.309]
,[1260.531, -0.109]
,[1273.514, -0.103]
,[1288.339, 0.01]
,[1327.543, 0.119]
,[1353.863, 0.377]
,[1414.509, 0.79]
,[1425.208, 0.963]
,[1421.384, 1.006]
,[1442.962, 1.115]
,[1464.35, 1.572]
,[1468.705, 1.841]
,[1447.894, 2.047]
,[1457.628, 2.2]]
thurber = pd.DataFrame(columns=columns, data=data)
# ๋ฐ์ดํฐ๋ฅผ ์๊ฐํ ํฉ๋๋ค.
thurber.plot('mobility', 'density', kind='scatter', title='Thurber');
# ์ ํํ๊ท๋ชจ๋ธ์ ํตํด ์ฑ๋ฅ ํ์ธ
X_thurber = thurber[['mobility']]
y_thurber = thurber['density']
linear = LinearRegression()
linear.fit(X_thurber, y_thurber)
print('R2: ', linear.score(X_thurber, y_thurber))
ax = thurber.plot('mobility', 'density', kind='scatter', title='Thurber')
ax.plot(X_thurber, linear.predict(X_thurber));
from ipywidgets import interact
from sklearn.tree import DecisionTreeRegressor, export_graphviz
import matplotlib.pyplot as plt
import graphviz
def show_tree(tree, colnames):
dot = export_graphviz(tree, feature_names=colnames, filled=True, rounded=True)
return graphviz.Source(dot)
def thurber_tree(max_depth=1):
tree = DecisionTreeRegressor(max_depth=max_depth)
tree.fit(X_thurber, y_thurber)
print('R2: ', tree.score(X_thurber, y_thurber))
ax = thurber.plot('mobility', 'density', kind='scatter', title='Thuber')
ax.step(X_thurber, tree.predict(X_thurber), where='mid')
plt.show()
display(show_tree(tree, colnames=['mobility']))
interact(thurber_tree, max_depth=(1,6,1));
'๐ฟ Data > ๋ถํธ์บ ํ' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[TIL]30.Evaluation Metrics for Classification(Precision, Recall, f1score, threshold, ROC curve, AUC) (0) | 2021.12.29 |
---|---|
[TIL]29.RandomForest(๋๋คํฌ๋ ์คํธ) (0) | 2021.12.27 |
[TIL]27.Section2_sprint1 challenge (0) | 2021.12.24 |
[TIL]26.Logistic Regression(๋ก์ง์คํฑ ํ๊ท; ๋ถ๋ฅ) (0) | 2021.12.22 |
[TIL]25.Ridge Regression(๋ฅํ ํ๊ท) (0) | 2021.12.21 |