[ํผ๊ณต๋จธ์ ] 05. ํธ๋ฆฌ ์๊ณ ๋ฆฌ์ฆ
์บ์ ์ธ์๋ ์์ฝ์ฌ, ๋์, ๋น๋, pH ๊ฐ์ผ๋ก ์์ธ ์ข ๋ฅ ๊ตฌ๋ณ
๋ก์ง์คํฑ ํ๊ท๋ก ์์ธ ๋ถ๋ฅํ๊ธฐ
species ์ด์์ ๊ณ ์ ๊ฐ ์ถ์ถ
## ๋ก์ง์คํฑ ํ๊ท๋ก ์์ธ ๋ถ๋ฅํ๊ธฐ
import pandas as pd
wine = pd.read_csv('https://bit.ly/wine-date')
์ํ ํ์ธ - head
* head() : ์ฒ์ n๊ฐ์ ์ํ ํ์ธ (๊ธฐ๋ณธ๊ฐ 5)
wine.head()
์ฒ์ 3๊ฐ ์ด(alchol, sugar pH) - ๊ฐ๊ฐ ์์ฝ์ฌ ๋์, ๋น๋, pH๊ฐ ๋ํ๋
๋ค ๋ฒ์งธ ์ด(class) ํ๊น๊ฐ - 0 ๋ ๋์์ธ, 1 ํ์ดํธ ์์ธ
-> ๋ ๋์์ธ vs ํ์ดํธ ์์ธ ๊ตฌ๋ถํ๋ ์ด์ง ๋ถ๋ฅ
ํ์ดํธ ์์ธ์ด ์์ฑ ํด๋์ค -> ์ ์ฒด ์์ธ ๋ฐ์ดํฐ์์ ํ์ดํธ ์์ธ ๊ณจ๋ผ๋ด๋ ๋ฌธ์
์ํ ํ์ธ - info
* info() : ๋ฐ์ดํฐํ๋ ์์ ๊ฐ ์ด์ ๋ฐ์ดํฐ ํ์ ๊ณผ ๋๋๋ ๋ฐ์ดํฐ๊ฐ ์๋์ง ํ์ธ
wine.info()
์ํ - 6497๊ฐ / ์ด - 4๊ฐ (๋ชจ๋ ์ค์๊ฐ) / non-null count๊ฐ 6497๊ฐ -> ๋๋ฝ๋ ๊ฐ ์์
์ํ ํ์ธ - describe()
* describe() : ์ด์ ๋ํ ๊ฐ๋ตํ ํต๊ณ ์ถ๋ ฅ. ์ต์, ์ต๋, ํ๊ท ๊ฐ ๋ฑ์ ๋ณผ ์ ์์
wine.describe()
ํ๊ท (mean), ํ์คํธ์ฐจ(std), ์ต์(min), ์ต๋(max), ์ค๊ฐ๊ฐ(50%), 1์ฌ๋ถ์์(25%), 3์ฌ๋ถ์์(75%) ์ถ๋ ฅ
-> ์์ฝ์ฌ ๋์์ ๋น๋, pH ๊ฐ์ ์ค์ผ์ผ์ด ๋ค๋ฆ -> StandardScaler ํด๋์ค ์ฌ์ฉ ํน์ฑ ํ์คํ ํ์
ํ๋ค์ค ๋ฐ์ดํฐํ๋ ์ -> ๋ํ์ด ๋ฐฐ์ด ๋ณํ
wine ๋ฐ์ดํฐํ๋ ์์์ ์ฒ์ 3๊ฐ ์ด ๋ํ์ด ๋ฐฐ์ด๋ก ๋ฐ๊ฟ์ data ์ ์ฅ,
๋ง์ง๋ง class์ด ๋ํ์ด ๋ฐฐ์ด๋ก ๋ฐ๊ฟ์ target ๋ฐฐ์ด์ ์ ์ฅ
data = wine[['alcohol','sugar','pH']].to_numpy()
target = wine['class'].to_numpy()
ํ๋ จ ์ธํธ์ ํ ์คํธ ์ธํธ ๋๋๊ธฐ
sklearn.model_select ์๋ train_test_split
* train_test_split() : ํ๋ จ์ธํธ, ํ ์คํธ ์ธํธ๋ก ๋๋ ( test_size ํ ์คํธ ์ธํธ ์ง์ , ์ง์ x - 25% )
from sklearn.model_selection import train_test_split
train_input, test_input, train_target, test_target = train_test_split(data, target, test_size=0.2, random_state=42)
ํ๋ จ ์ธํธ์ ํ ์คํธ ์ธํธ ํฌ๊ธฐ ํ์ธ
* shape : ํฌ๊ธฐ ํ์ธ
print(train_input.shape, test_input.shape)
(5197, 3) (1300, 3) -> ํ๋ จ ์ธํธ 5197๊ฐ / ํ ์คํธ ์ธํธ 1300๊ฐ
์ ์ฒ๋ฆฌ
* sklearn.preprocessing ์์ StandardScaler : ์ ์ฒ๋ฆฌ
from sklearn.preprocessing import StandardScaler
ss = StandardScaler()
ss.fit(train_input)
train_scaled = ss.transform(train_input)
test_scaled = ss.transform(test_input)
๋ก์ง์คํฑ ํ๊ท ๋ชจ๋ธ ํ๋ จ
* sklearn.linear_model ์์ LogisticRegression
from sklearn.linear_model import LogisticRegression
lr = LogisticRegression()
lr.fit(train_scaled, train_target)
print(lr.score(train_scaled, train_target))
print(lr.score(test_scaled, test_target))
0.7808350971714451
0.7776923076923077
-> ํ๋ จ์ธํธ, ํ ์คํธ ์ธํธ ์ ์ ๋ชจ๋ ๋ฎ์ -> ๊ณผ์์ ํฉ
๊ณ์, ์ ํธ ์ถ๋ ฅ
๋ก์ง์คํฑ ํ๊ท๊ฐ ํ์ตํ ๊ณ์์ ์ ํธ ์ถ๋ ฅ
* .coef_ : ๊ณ์
* .intercept_ : ์ ํธ
print(lr.coef_, lr.intercept_)
[[ 0.51270274 1.6733911 -0.68767781]] [1.81777902]
์ด ๋ชจ๋ธ์ ์์ฝ์ฌ ๋์์ 0.51270274๋ฅผ ๊ณฑํ๊ณ , ๋น๋์ 1.6733911์ ๊ณฑํ๊ณ , pH์ -0.68767781์ ๊ณฑํ ๋ค์ ๋ชจ๋ ๋ํ๋ค. ๋ง์ง๋ง์ผ๋ก 1.81777902๋ฅผ ๋ํ๋ค. ์ด ๊ฐ์ด 0๋ณด๋ค ํฌ๋ฉด ํ์ดํธ ์์ธ, ์์ผ๋ฉด ๋ ๋์์ธ์ด๋ค. ํ์ฌ ์ฝ 77% ์ ํ๋๋ก ํ์ดํธ ์์ธ์ ๋ถ๋ฅํ๋ค...... ~~~~~~~> ๋ณด๊ณ ์ ์ดํด ๋ถ๊ฐ! ๋ก์ง์คํฑ ํ๊ท๋ ์ค๋ช ์ด ์ด๋ ค์!
05-1. ๊ฒฐ์ ํธ๋ฆฌ
๋ชจ๋ธ์ด ์ด์ ๋ฅผ ์ค๋ช ํ๊ธฐ ์ฌ์
๊ฒฐ์ ํธ๋ฆฌ ์ง๋ฌธ์ ํ๋์ฉ ๋์ ธ์ ์ ๋ต์ ๋ง์ถฐ๋๊ฐ๋ค (=์ค๋ฌด๊ณ ๊ฐ)
๋ฐ์ดํฐ๋ฅผ ์ ๋๋ ์ ์๋ ์ง๋ฌธ์ ์ฐพ๋๋ค๋ฉด ๊ณ์ ์ง๋ฌธ์ ์ถ๊ฐํด์ ๋ถ๋ฅ ์ ํ๋ ๋์ผ ์ ์์
๊ฒฐ์ ํธ๋ฆฌ ๋ชจ๋ธ ํ๋ จ
* sklearn.tree ์์ DecisionTreeClassifier ํด๋์ค ์ฌ์ฉ
* fit() : ๋ชจ๋ธ ํ๋ จ
* score() : ์ ํ๋ ํ๊ฐ
from sklearn.tree import DecisionTreeClassifier
dt = DecisionTreeClassifier(random_state=42)
dt.fit(train_scaled, train_target)
print(dt.score(train_scaled, train_target)) # ํ๋ จ ์ธํธ
print(dt.score(test_scaled, test_target)) # ํ
์คํธ ์ธํธ
0.996921300750433
0.8592307692307692
-> ํ๋ จ ์ธํธ ์ ์ ์์ฒญ ๋์ -> ๊ณผ๋์ ํฉ
๊ฒฐ์ ํธ๋ฆฌ ๋ชจ๋ธ ํ๋ จ
* plot_tree() : ๊ฒฐ์ ํธ๋ฆฌ๋ฅผ ์ดํดํ๊ธฐ ์ฌ์ด ํธ๋ฆฌ ๊ทธ๋ฆผ์ผ๋ก ์ถ๋ ฅ
import matplotlib.pyplot as plt
from sklearn.tree import plot_tree
plt.figure(figsize=(10, 7))
plot_tree(dt)
plt.show()
๊ฒฐ์ ํธ๋ฆฌ๋ ์์์๋ถํฐ ์๋๋ก ๊ฑฐ๊พธ๋ก ์๋ผ๋จ
๋ ธ๋ : ๊ฒฐ์ ํธ๋ฆฌ๋ฅผ ๊ตฌ์ฑํ๋ ํต์ฌ ์์, ํ๋ จ ๋ฐ์ดํฐ์ ํน์ฑ์ ๋ํ ํ ์คํธ๋ฅผ ํํ
๋ฃจํธ ๋ ธ๋ : ๋งจ ์์ ๋ ธ๋ / ๋ฆฌํ ๋ ธ๋ : ๋งจ ์๋ ๋์ ๋ฌ๋ฆฐ ๋ ธ๋
๊ฐ์ง : ํ ์คํธ์ ๊ฒฐ๊ณผ(Ture, False)
์ผ๋ฐ์ ์ผ๋ก ํ๋์ ๋ ธ๋๋ 2๊ฐ์ ๊ฐ์ง ๊ฐ์ง
ํธ๋ฆฌ ๊น์ด ์ ํ ์ถ๋ ฅ
* max_depth : ๊น์ด (1 - ๋ฃจํ ๋ ธ๋๋ฅผ ์ ์ธํ๊ณ ํ๋์ ๋ ธ๋๋ฅผ ๋ ํ์ฅ)
* filled : ํด๋์ค์ ๋ง๊ฒ ๋ ธ๋ ์์น
* feature_names : ํน์ฑ์ ์ด๋ฆ ์ ๋ฌ
plt.figure(figsize=(10,7))
plot_tree(dt, max_depth=1, filled=True, feature_names=['alcohol', 'sugar', 'pH'])
plt.show()
> ๊ทธ๋ฆผ์ด ๋ด๊ณ ์๋ ์ ๋ณด
๋ฃจํ๋ ธ๋ ๋น๋ -0.239 ์ดํ์ธ์ง ์ง๋ฌธ
-0.239์ ๊ฐ๊ฑฐ๋ ์์ผ๋ฉด ์ผ์ชฝ ๊ฐ์ง(yes)
๊ทธ๋ ์ง ์์ผ๋ฉด ์ค๋ฅธ์ชฝ ๊ฐ์ง(no) ์ด๋
๋ฃจํ๋ ธ๋ ์ํ์ = 5197
์ด ์ค์์ ์์ฑํด๋์ค(๋ ๋์์ธ) 1258๊ฐ, ์์ฑํด๋์ค(ํ์ดํธ์์ธ) 3939๊ฐ
* plot_tree() ํจ์์์ filled=True๋ก ์ง์ ํ๋ฉด ํด๋์ค๋ง๋ค ์๊น์ ๋ถ์ฌ,
์ด๋ค ํด๋์ค์ ๋น์จ์ด ๋์์ง๋ฉด ์ ์ ์งํ ์์ผ๋ก ํ์
๋ฆฌํ ๋ ธ๋์์ ๊ฐ์ฅ ๋ง์ ํด๋์ค ->์์ธก ํด๋์ค
๋ถ์๋
gini ์ง๋ ๋ถ์๋
* criterion : ๋ ธ๋์์ ๋ฐ์ดํฐ๋ฅผ ๋ถํ ํ ๊ธฐ์ค ์ ํจ
DecisionTreeClassifier ํด๋์ค์ criterion ๋งค๊ฐ๋ณ์ ๊ธฐ๋ณธ๊ฐ 'gini'
์ง๋ ๋ถ์๋๋ ํด๋์ค์ ๋น์จ์ ์ ๊ณฑํด์ ๋ํ ๋ค์ 1์์ ๋นผ๋ฉด ๋จ
์ง๋ ๋ถ์๋ = 1 - (์์ฑ ํด๋์ค ๋น์จ^2 + ์์ฑ ํด๋์ค ๋น์จ^2)
ex) ๋ฃจํธ ๋ ธ๋์ ์ง๋ ๋ถ์๋ ๊ณ์ฐ
์ํ ์ด 5197๊ฐ, ์์ฑ ํด๋์ค 1258๊ฐ, ์์ฑ ํด๋์ค 3939๊ฐ
๋ฃจํ๋ ธ๋ ์ง๋ ๋ถ์๋ = 1 - ((1258/5197)^2 + (3939/5197)^2) = 0.367
๋ถ์๋ 0.5 = ์ต์
์์ ๋ ธ๋ : ๋ถ์๋ 0
์ ๋ณด์ด๋
๋ถ๋ชจ์ ์์ ๋ ธ๋ ์ฌ์ด์ ๋ถ์๋ ์ฐจ์ด
๊ฒฐ์ ํธ๋ฆฌ ๋ชจ๋ธ์ ๋ถ๋ชจ ๋ ธ๋์ ์์ ๋ ธ๋์ ๋ถ์๋ ์ฐจ์ด๊ฐ ๊ฐ๋ฅํ ํฌ๋๋ก ํธ๋ฆฌ๋ฅผ ์ฑ์ฅ์ํด
- > ๋ถ๋ชจ ๋ ธ๋์ ์์ ๋ ธ๋์ ๋ถ์๋ ์ฐจ์ด ๊ณ์ฐ
์์ ๋ ธ๋์ ๋ถ์๋๋ฅผ ์ํ ๊ฐ์์ ๋น๋กํ์ฌ ๋ชจ๋ ๋ํ ๋ค์ ๋ถ๋ชจ ๋ ธ๋์ ๋ถ์๋์ ๋นผ๋ฉด ๋จ
์ ๋ณด ์ด๋ = ๋ถ๋ชจ์ ๋ถ์๋ -(์ผ์ชฝ ๋ ธ๋ ์ํ ์ / ๋ถ๋ชจ ์ํ ์) x ์ผ์ชฝ ๋ ธ๋ ๋ถ์๋ - (์ค๋ฅธ์ชฝ ๋ ธ๋ ์ํ ์ / ๋ถ๋ชจ ์ํ ์) x ์ค๋ฅธ์ชฝ ๋ ธํธ ๋ถ์๋
ex) ๋ฃจํธ ๋ ธ๋๋ฅผ ๋ถ๋ชจ ๋ ธ๋, ์ผ์ชฝ๊ณผ ์ค๋ฅธ์ชฝ ๋ ธ๋๊ฐ ์์ ๋ ธ๋
์ผ์ชฝ ๋ ธ๋๋ก๋ 2922 ์ํ ์ด๋, ์ค๋ฅธ์ชฝ ๋ ธ๋๋ก๋ 2275๊ฐ ์ํ ์ด๋
์ ๋ณด ์ด๋ = 0.367 - (2922.5197) x 0.481 - (2275 / 5197) x 0.069 = 0.066
=> ๊ฒฐ์ ํธ๋ฆฌ ์๊ณ ๋ฆฌ์ฆ์ ๋ถ์๋ ๊ธฐ์ค์ ์ฌ์ฉํด ์ ๋ณด ์ด๋์ด ์ต๋๊ฐ ๋๋๋ก ๋ ธ๋๋ฅผ ๋ถํ
๋ ธ๋๋ฅผ ์์ํ๊ฒ ๋๋์๋ก ์ ๋ณด ์ด๋์ด ์ปค์ง
์๋ก์ด ์ํ์ ๋ํด ์์ธกํ ๋์๋ ๋ ธ๋์ ์ง๋ฌธ์ ๋ฐ๋ผ ํธ๋ฆฌ ์ด๋
๋ง์ง๋ง์ ๋๋ฌํ ๋ ธ๋์ ํด๋์ค ๋น์จ์ ๋ณด๊ณ ์์ธก ๋ง๋ฆ
๊ฐ์ง์น๊ธฐ
๊ฐ์ง์น๊ธฐ๋ฅผ ์ ํ๋ฉด ๋ฌด์์ ๋๊น์ง ์๋ผ๋๋ ํธ๋ฆฌ ๋ง๋ค์ด์ง
ํ๋ จ ์ธํธ์๋ ์์ฃผ ์ ๋ง์ง๋ง, ํ ์คํธ ์ธํธ์์ ์ ์๋ ๊ทธ์ ๋ชป ๋ฏธ์นจ -> ๊ณผ๋์ ํฉ -> ์ผ๋ฐํ ์ ์ ๋จ
* max_depth() : ์๋ผ๋ ์ ์๋ ํธ๋ฆฌ์ ์ต๋ ๊น์ด ์ง์
dt = DecisionTreeClassifier(max_depth=3, random_state=42)
dt.fit(train_scaled, train_target)
print(dt.score(train_scaled, train_target))
print(dt.score(test_scaled, test_target))
0.8454877814123533
0.8415384615384616
-> ํ๋ จ ์ธํธ ์ฑ๋ฅ ๋ฎ์์ก์ง๋ง ํ ์คํธ ์ธํธ ์ฑ๋ฅ์ ๊ฑฐ์ ๊ทธ๋๋ก
ํธ๋ฆฌ ๊ทธ๋ํ
* .plot_tree() : ํธ๋ฆฌ ๊ทธ๋ํ
plt.figure(figsize=(20,15))
plot_tree(dt, filled=True, feature_names=['alcohol', 'sugar', 'pH'])
plt.show()
๊ทธ๋ฐ๋ฐ -0.802๋ผ๋ ์์๋ก ๋ ๋น๋ ... ?
๋ถ์๋ ๊ธฐ์ค์ผ๋ก ์ํ์ ๋๋. ๋ถ์๋๋ ํด๋์ค๋ณ ๋น์จ์ ๊ฐ์ง๊ณ ๊ณ์ฐ
์ํ์ ์ด๋ค ํด๋์ค ๋น์จ๋ก ๋๋๋์ง ๊ณ์ฐํ ๋ ํน์ฑ๊ฐ์ ์ค์ผ์ผ ์ํฅ ๋ฏธ์น์ง ์์
=> ๊ฒฐ์ ํธ๋ฆฌ ์๊ณ ๋ฆฌ์ฆ์ ํ์คํ ์ ์ฒ๋ฆฌ ํ ํ์ ์์
์ ์ฒ๋ฆฌ ์ ํ๋ จ ์ธํธ, ํ ์คํธ ์ธํธ๋ก ๊ฒฐ์ ํธ๋ฆฌ ๋ชจ๋ธ ํ๋ จ
dt = DecisionTreeClassifier(max_depth=3, random_state=42)
dt.fit(train_input, train_target)
print(dt.score(train_input, train_target))
print(dt.score(test_input, test_target))
0.8454877814123533
0.8415384615384616
ํธ๋ฆฌ ๊ทธ๋ํ
plt.figure(figsize=(20,15))
plot_tree(dt, filled=True, feature_names=['alcohol', 'sugar', 'pH'])
plt.show()
๊ฒฐ๊ณผ๋ ๊ฐ์ ํธ๋ฆฌ์ง๋ง, ํน์ฑ๊ฐ์ ํ์ค์ ์๋ก ๋ฐ๊พธ์ง ์์ ์ดํดํ๊ธฐ ํจ์ฌ ์ฌ์
๋น๋๊ฐ 1.625๋ณด๋ค ํฌ๊ณ 4.325๋ณด๋ค ์์ ์์ธ ์ค์ ์์ฝ์ฌ ๋์๊ฐ 11.025์ ๊ฐ๊ฑฐ๋ ์์ ๊ฒ์ด ๋ ๋ ์์ธ, ๊ทธ์ธ ํ์ดํธ ์์ธ
ํน์ฑ ์ค์๋
* feature_importances_ : ์ด๋ค ํน์ฑ์ด ๊ฐ์ฅ ์ ์ฉํ์ง ํน์ฑ ์ค์๋
print(dt.feature_importances_)
[0.12345626 0.86862934 0.0079144 ]
-> ๋ ๋ฒ์งธ ํน์ฑ์ธ ๋น๋๊ฐ 0.87๋ก ํน์ฑ ์ค์๋ ๊ฐ์ฅ ๋์ - ์์ฝ์ฌ ๋์ - pH
ํน์ฑ ์ค์๋ ๊ฐ์ ๋ชจ๋ ๋ํ๋ฉด 1
ํน์ฑ ์ค์๋๋ ๊ฐ ๋ ธ๋์ ์ ๋ณด ์ด๋๊ณผ ์ ์ฒด ์ํ์ ๋ํ ๋น์จ์ ๊ณฑํ ํ ํน์ฑ๋ณ๋ก ๋ํ์ฌ ๊ณ์ฐ
ํน์ฑ ์ค์๋๋ฅผ ํ์ฉํ๋ฉด ๊ฒฐ์ ํธ๋ฆฌ ๋ชจ๋ธ์ ํน์ฑ ์ ํ์ ํ์ํ ์ ์์
05-2. ๊ต์ฐจ ๊ฒ์ฆ๊ณผ ๊ทธ๋ฆฌ๋ ์์น
์ง๊ธ๊น์ง ํ๋ จ์ธํธ์์ ๋ชจ๋ธ ํ๋ จ, ํ ์คํธ ์ธํธ์์ ๋ชจ๋ธ ํ๊ฐํจ
ํ ์คํธ ์ธํธ์์ ์ป์ ์ ์๋ฅผ ๋ณด๊ณ ์ผ๋ฐํ ์ฑ๋ฅ ๊ฐ๋
๊ทธ๋ฐ๋ฐ ํ ์คํธ ์ธํธ๋ฅผ ์ฌ์ฉํด ์๊พธ ์ฑ๋ฅ์ ํ์ธํ๋ค ๋ณด๋ฉด ์ ์ ํ ์คํธ ์ธํธ์ ๋ง์ถ๊ฒ ๋๋ ์
ํ ์คํธ ์ธํธ๋ก ์ผ๋ฐํ ์ฑ๋ฅ์ ์ฌ๋ฐ๋ฅด๊ฒ ์์ธกํ๋ ค๋ฉด ๊ฐ๋ฅํ ํ ํ ์คํธ ์ธํธ๋ฅผ ์ฌ์ฉํ์ง ๋ง์์ผ ํจ
๋ชจ๋ธ์ ๋ง๋ค๊ณ ๋์ ๋ง์ง๋ง์ ๋ฑ ํ ๋ฒ ์ฌ์ฉํ๋ ๊ฒ์ด ์ข์
๊ฒ์ฆ ์ธํธ
ํ ์คํธ ์ธํธ๋ฅผ ์ฌ์ฉํ์ง ์์ผ๋ฉด ๋ชจ๋ธ์ด ๊ณผ๋/๊ณผ์์ ํฉ์ธ์ง ํ๋จํ๊ธฐ ์ด๋ ค์
ํ ์คํธ ์ธํธ๋ฅผ ์ฌ์ฉํ์ง ์๊ณ ์ด๋ฅผ ์ธก์ ํ๋ ๊ฐ๋จํ ๋ฐฉ๋ฒ์ ํ๋ จ ์ธํธ๋ฅผ ๋ ๋๋ ๊ฒ -> ์ด ๋ฐ์ดํฐ๋ฅผ '๊ฒ์ฆ ์ธํธ'๋ผ๊ณ ๋ถ๋ฆ
ํ๋ จ ์ธํธ - ๋ชจ๋ธ ํ๋ จ / ๊ฒ์ฆ ์ธํธ - ๋ชจ๋ธ ํ๊ฐ / ํ ์คํธ ์ธํธ - ์ต์ข ์ ์ ํ๊ฐ
๋ฐ์ดํฐ ๋ถ๋ฌ์ค๊ธฐ
import pandas as pd
wine = pd.read_csv('https://bit.ly/wine-date')
ํ๊น, ํน์ฑ ๋ฐฐ์ด ์ ์ฅ
class ์ด - ํ๊น / ๋๋จธ์ง ์ด - ํน์ฑ ๋ฐฐ์ด ์ ์ฅ
data = wine[['alcohol', 'sugar', 'pH']].to_numpy()
target = wine['class'].to_numpy()
ํ๋ จ / ํ ์คํธ ์ธํธ ๋๋๊ธฐ
train_test_split() ํจ์ 2๋ฒ ์ ์ฉํด์ ํ๋ จ ์ธํธ์ ๊ฒ์ฆ ์ธํธ๋ก ๋๋ ์ค
ํ๋ จ ์ธํธ์ ์ ๋ ฅ ๋ฐ์ดํฐ์ ํฐ๊น ๋ฐ์ดํฐ๋ฅผ train_input, train_target ๋ฐฐ์ด์ ์ ์ฅ
from sklearn.model_selection import train_test_split
train_input, test_input, train_target, test_target = train_test_split(data, target, test_size=0.2, random_state=42)
train_input๊ณผ train_target์ ๋ค์ train_test_split() ํจ์์ ๋ฃ์ด
ํ๋ จ์ธํธ sub_input, sub_target / ๊ฒ์ฆ ์ธํธ val_input, val_target์ ๋ง๋ฆ
sub_input, val_input, sub_target, val_target = train_test_split(train_input, train_target, test_size=0.2, random_state=42)
ํ๋ จ ์ธํธ, ๊ฒ์ฆ ์ธํธ ํฌ๊ธฐ ํ์ธ
print(sub_input.shape, val_input.shape)
(4157, 3) (1040, 3)
-> ์๋ 5197๊ฐ์๋ ํ๋ จ์ธํธ๊ฐ 4157๋ก ์ค๊ณ , ๊ฒ์ฆ ์ธํธ๋ 1040๊ฐ๊ฐ ๋จ
๋ชจ๋ธ ์์ฑ ํ ํ๊ฐ
sub_input, sub_target, val_input, val_target ์ฌ์ฉํด ๋ชจ๋ธ ๋ง๋ค๊ณ ํ๊ฐ
from sklearn.tree import DecisionTreeClassifier
dt = DecisionTreeClassifier(random_state=42)
dt.fit(sub_input, sub_target)
print(dt.score(sub_input, sub_target))
print(dt.score(val_input, val_target))
๊ต์ฐจ ๊ฒ์ฆ
๊ฒ์ฆ ์ธํธ ๋ง๋๋๋ผ ํ๋ จ ์ธํธ ์ค์์ - ๋ณดํต ๋ง์ ๋ฐ์ดํฐ๋ฅผ ํ๋ จ์ ์ฌ์ฉํ ์๋ก ์ข์ ๋ชจ๋ธ์ด ๋ง๋ค์ด์ง
๊ฒ์ฆ ์ธํธ๋ฅผ ๋๋ฌด ์กฐ๊ธ๋ง ๋ผ์ด ๋์ผ๋ฉด ๊ฒ์ฆ ์ ์ ๋ถ์์
=> ๊ต์ฐจ ๊ฒ์ฆ์ ์ด์ฉ!
๊ต์ฐจ๊ฒ์ฆ : ๊ฒ์ฆ ์ธํธ๋ฅผ ๋ด์ด ๋ด์ฌ ํ๊ฐํ๋ ๊ณผ์ ์ ์ฌ๋ฌ ๋ฒ ๋ฐ๋ณต
๊ทธ ๋ค์ ์ด ์ ์๋ฅผ ํ๊ท ํ์ฌ ์ต์ ๊ฒ์ฆ ์ ์ ์ป์
k-ํด๋ ๊ต์ฐจ ๊ฒ์ฆ : ํ๋ จ ์ธํธ๋ฅผ ๋ช ๋ถ๋ถ์ผ๋ก ๋๋๋์ ๋ฐ๋ผ..
๊ฐ ํด๋์์ ๊ณ์ฐํ ๊ฒ์ฆ ์ ์๋ฅผ ํ๊ท ํ๊ธฐ ๋๋ฌธ์ ์์ ์ ์ธ ์ ์ ์ป์ ์ ์์
๊ต์ฐจ ๊ฒ์ฆ
* cross_validate() : ๊ต์ฐจ ๊ฒ์ฆ ํจ์ (๊ธฐ๋ณธ๊ฐ 5-ํด๋ ๊ต์ฐจ ๊ฒ์ฆ)
cross_validate(ํ๊ฐํ ๋ชจ๋ธ ๊ฐ์ฒด, ํ๋ จ์ธํธ ์ ์ฒด)
from sklearn.model_selection import cross_validate
scores = cross_validate(dt, train_input, train_target)
print(scores)
{'fit_time': array([0.01800036, 0.00823307, 0.00744772, 0.00747132, 0.00703192]), 'score_time': array([0.0013876 , 0.00073624, 0.00069189, 0.00070477, 0.00066996]), 'test_score': array([0.86923077, 0.84615385, 0.87680462, 0.84889317, 0.83541867])}
-> fit_time, scroe_time, test_score ํค๋ฅผ ๊ฐ์ง ๋์ ๋๋ฆฌ ๋ฐํ
* fit_time, score_time : ๊ฐ์ ๋ชจ๋ธ์ ํ๋ จํ๋ ์๊ฐ๊ณผ ๊ฒ์ฆํ๋ ์๊ฐ
cross_validate() ๊ธฐ๋ณธ๊ฐ 5-ํด๋ ๊ต์ฐจ ๊ฒ์ฆ
* .cv ๋งค๊ฐ๋ณ์์์ ํด๋ ์ ๋ฐ๊ฟ ์ ์์
๊ต์ฐจ ๊ฒ์ฆ ์ต์ข ์ ์
* test_scroe : ๊ฒ์ฆ ํด๋์ ์ ์
๊ต์ฐจ ๊ฒ์ฆ์ ์ต์ข ์ ์๋ test_score ํค์ ๋ด๊ธด ์ ์ ํ๊ท
import numpy as np
print(np.mean(scores['test_score']))
0.855300214703487
์ฃผ์. cross_validate() ํ๋ จ ์ธํธ๋ฅผ ์์ด ํด๋ ๋๋์ง x
train_test_split() ํจ์๋ ์ ์ฒด ๋ฐ์ดํฐ๋ฅผ ์์ ํ ํ๋ จ ์ธํธ๋ฅผ ์ค๋น -> ๋ฐ๋ก ์์ ํ์ ์์
๊ต์ฐจ ๊ฒ์ฆ์ ํ ๋ ํ๋ จ ์ธํธ๋ฅผ ์์ผ๋ ค๋ฉด ๋ถํ ๊ธฐ ์ง์ ํด์ผ ํจ
๋ถํ ๊ธฐ : ๊ต์ฐจ ๊ฒ์ฆ์์ ํด๋๋ฅผ ์ด๋ป๊ฒ ๋๋์ง ๊ฒฐ์
* .cross_validate() ๋ ํ๊ท ๋ชจ๋ธ - KFold ๋ถํ ๊ธฐ / ๋ถ๋ฅ ๋ชจ๋ธ - StratifiedKFold ์ฌ์ฉ
์์์ ์ํํ ์ฝ๋๋ ๋ค์ ์ฝ๋์ ๋์ผ
from sklearn.model_selection import StratifiedKFold
scores = cross_validate(dt, train_input, train_target, cv=StratifiedKFold())
print(np.mean(scores['test_score']))
0.855300214703487
ํ๋ จ ์ธํธ ์์ ํ, 10-ํด๋ ๊ต์ฐจ ๊ฒ์ฆ
* n_splits : ๋ช(k) ํด๋ ๊ต์ฐจ ๊ฒ์ฆํ ์ง ์ง์
splitter = StratifiedKFold(n_splits=10, shuffle=True, random_state=42)
scores = cross_validate(dt, train_input, train_target, cv=splitter)
print(np.mean(scores['test_score']))
ํ์ดํผํ๋ผ๋ฏธํฐ ํ๋
๋ชจ๋ธ ํ๋ผ๋ฏธํฐ : ๋จธ์ ๋ฌ๋ ๋ชจ๋ธ์ด ํ์ตํ๋ ํ๋ผ๋ฏธํฐ
ํ์ดํผํ๋ผ๋ฏธํฐ : ๋ชจ๋ธ์ด ํ์ตํ ์ ์์ด์ ์ฌ์ฉ์๊ฐ ์ง์ ํด์ผ๋ง ํ๋ ํ๋ผ๋ฏธํฐ
ํ์ดํผํ๋ผ๋ฏธํฐ๋ ๋ชจ๋ ํด๋์ค๋ ๋ฉ์๋์ ๋งค๊ฐ๋ณ์๋ก ํํ
๊ธฐ๋ณธ๊ฐ์ ๊ทธ๋๋ก ์ฌ์ฉํด ๋ชจ๋ธ์ ํ๋ จ -> ๊ฒ์ฆ ์ธํธ ์ ์๋ ๊ต์ฐจ ๊ฒ์ฆ์ ํตํด์ ๋งค๊ฐ๋ณ์ ์กฐ๊ธ์ฉ ๋ณ๊ฒฝ
๊ทธ๋ฆฌ๋ ์์น GridSearchCV : ํ์ดํผํ๋ผ๋ฏธํฐ ํ์๊ณผ ๊ต์ฐจ ๊ฒ์ฆ์ ํ ๋ฒ์ ์ํ
min_impurtiy_decrease ๋งค๊ฐ๋ณ์ ์ต์ ๊ฐ ์ฐพ๊ธฐ
GridSearchCV ํด๋์ค ์ํฌํธ
ํ์ํ ๋งค๊ฐ๋ณ์์ ํ์ํ ๊ฐ์ ๋ฆฌ์คํธ๋ฅผ ๋์ ๋๋ฆฌ๋ก ๋ง๋ฆ
from sklearn.model_selection import GridSearchCV
params = {'min_impurity_decrease': [0.0001, 0.0002, 0.0003, 0.0004, 0.0005]}
0.0001๋ถํฐ 0.0005๊น์ง 0.0001์ฉ ์ฆ๊ฐํ๋ 5๊ฐ ๊ฐ ์๋
๊ทธ๋ฆฌ๋ ์์น ๊ฐ์ฒด ์์ฑ
GridSearchCV ํด๋์ค์ ํ์ ๋์ ๋ชจ๋ธ๊ณผ params ๋ณ์ ์ ๋ฌํ์ฌ ๊ทธ๋ฆฌ๋ ์์น ๊ฐ์ฒด ์์ฑ
gs = GridSearchCV(DecisionTreeClassifier(random_state=42), params, n_jobs=-1)
gs๊ฐ์ฒด์ fit() ๋ฉ์๋ ํธ์ถ
์ด ๋ฉ์๋๋ฅผ ํธ์ถํ๋ฉด ๊ทธ๋ฆฌ๋ ์์น ๊ฐ์ฒด๋ ๊ฒฐ์ ํธ๋ฆฌ ๋ชจ๋ธ min_impurity_decrease ๊ฐ์ ๋ฐ๊ฟ๊ฐ๋ฉฐ ์ด 5๋ฒ ์คํํจ
GridSearchCV์ cv ๋งค๊ฐ๋ณ์ ๊ธฐ๋ณธ๊ฐ 5
๋ฐ๋ผ์ min_impurity_decrease 5 x 5 = 25๊ฐ์ ๋ชจ๋ธ ํ๋ จ
* n_jobs() : ๋ณ๋ ฌ ์คํ์ ์ฌ์ฉํ CPU ์ฝ์ด ์ ์ง์ (๊ธฐ๋ณธ๊ฐ 1 / -1 ์ง์ ์ ์์คํ ์ ์๋ ๋ชจ๋ ์ฝ์ด ์ฌ์ฉ)
gs.fit(train_input, train_target)
best_estimator_
๊ทธ๋ฆฌ๋ ์์น๋ ํ๋ จ์ด ๋๋๋ฉด ๋ชจ๋ธ ์ค์์ ๊ฒ์ฆ ์ ์๊ฐ ๊ฐ์ฅ ๋์ ๋ชจ๋ธ์ ๋งค๊ฐ๋ณ์ ์กฐํฉ์ผ๋ก
์ ์ฒด ํ๋ จ ์ธํธ์์ ์๋์ผ๋ก ๋ค์ ๋ชจ๋ธ์ ํ๋ จํจ
์ด ๋ชจ๋ธ์ gs ๊ฐ์ฒด์ best_estimator_ ์์ฑ์ ์ ์ฅ๋จ
* best_estimator_ : ๊ฒ์ฆ ์ ์๊ฐ ๊ฐ์ฅ ๋์ ๋ชจ๋ธ์ ๋งค๊ฐ๋ณ์ ์กฐํฉ์ผ๋ก ์ ์ฒด ํ๋ จ ์ธํธ์์ ๋ค์ ๋ชจ๋ธ ํ๋ จ
dt = gs.best_estimator_
print(dt.score(train_input, train_target))
0.9615162593804117
best_params_
* best_params_ : ๊ทธ๋ฆฌ๋ ์์น๋ก ์ฐพ์ ์ต์ ์ ๋งค๊ฐ๋ณ์ ๊ฐ ์ ์ฅ
print(gs.best_params_)
{'min_impurity_decrease': 0.0001}
-> 0.0001์ด ๊ฐ์ฅ ์ข์ ๊ฐ์ผ๋ก ์ ํ๋จ
mean_test_score
* cv_results_ ์์ฑ์ mean_test_score : ๊ฐ ๋งค๊ฐ๋ณ์์์ ์ํํ ๊ต์ฐจ ๊ฒ์ฆ์ ํ๊ท ์ ์ ์ ์ฅ
print(gs.cv_results_['mean_test_score'])
์ต์์ ๋งค๊ฐ๋ณ์ ์กฐํฉ
* argmax() : ๊ฐ์ฅ ํฐ ๊ฐ์ ์ธ๋ฑ์ค ์ถ์ถ
์ธ๋ฑ์ค ์ฌ์ฉํด params ํค์ ์ ์ฅ๋ ๋งค๊ฐ๋ณ์ ์ถ๋ ฅ
=> ์ต์์ ๊ฒ์ฆ ์ ์ ๋ง๋ ๋งค๊ฐ๋ณ์ ์กฐํฉ
best_index = np.argmax(gs.cv_results_['mean_test_score'])
print(gs.cv_results_['params'][best_index])
{'min_impurity_decrease': 0.0001}
์ ๋ฆฌ
1. ๋จผ์ ํ์ํ ๋งค๊ฐ๋ณ์๋ฅผ ์ง์
2. ํ๋ จ์ธํธ์์ ๊ทธ๋ฆฌ๋ ์์น๋ฅผ ์ํํ์ฌ ์ต์์ ํ๊ท ๊ฒ์ฆ ์ ์๊ฐ ๋์ค๋ ๋งค๊ฐ๋ณ์ ์กฐํฉ ์ฐพ๊ธฐ
์ด ์กฐํฉ์ ๊ทธ๋ฆฌ๋ ์์น ๊ฐ์ฒด์ ์ ์ฅ๋จ
3. ๊ทธ๋ฆฌ๋ ์์น๋ ์ต์์ ๋งค๊ฐ๋ณ์์์ ์ ์ฒด ํ๋ จ ์ธํธ๋ฅผ ์ฌ์ฉํด ์ต์ข ๋ชจ๋ธ์ ํ๋ จ
์ด ๋ชจ๋ธ๋ ๊ทธ๋ฆฌ๋ ์์น ๊ฐ์ฒด์ ์ ์ฅ
๋ณต์กํ ๋งค๊ฐ๋ณ์ ์กฐํฉ ํ์
* min_impurity_decrease : ๋ ธ๋๋ฅผ ๋ถํ ํ๊ธฐ ์ํ ๋ถ์๋ ๊ฐ์ ์ต์๋
* max_depth : ํธ๋ฆฌ์ ๊น์ด ์ ํ
* min_samples_split : ๋ ธ๋๋ฅผ ๋๋๊ธฐ ์ํ ์ต์ ์ํ ์
params = {'min_impurity_decrease': np.arange(0.0001, 0.001, 0.0001),
'max_depth': range(5, 20, 1),
'min_samples_split': range(2, 100, 10)}
arrange() ํจ์ 0.0001์์ ์์ 0.001๋ ๋๊น์ง 0.0001์ ๊ณ์ ๋ํจ
range() max_depth๋ฅผ 5์์ 20๊น์ง 1์ฉ ์ฆ๊ฐํ๋ฉด์ 15๊ฐ ๊ฐ ๋ง๋ฆ
min_samples_split 2์์ 100๊น์ง 10์ฉ ์ฆ๊ฐํ๋ฉด์ 10๊ฐ์ ๊ฐ
=> ์ด ๋งค๊ฐ๋ณ์๋ก ์ํํ ๊ต์ฐจ ๊ฒ์ฆ ํ์๋ 9 x 15 x 10 =1350๊ฐ
๊ธฐ๋ณธ 5-ํด๋ ๊ต์ฐจ ๊ฒ์ฆ์ ์ํ -> ๋ง๋ค์ด์ง๋ ๋ชจ๋ธ ์ 6750๊ฐ
๊ทธ๋ฆฌ๋ ์์น ์คํ
gs = GridSearchCV(DecisionTreeClassifier(random_state=42), params, n_jobs=-1)
gs.fit(train_input, train_target)
์ต์์ ๋งค๊ฐ๋ณ์ ์กฐํฉ ํ์ธ
print(gs.best_params_)
{'max_depth': 14, 'min_impurity_decrease': 0.0004, 'min_samples_split': 12}
์ต์์ ๊ต์ฐจ ๊ฒ์ฆ ์ ์ ํ์ธ
print(np.max(gs.cv_results_['mean_test_score']))
0.8683865773302731
GridSearchCV ํด๋์ค - ์ํ๋ ๋งค๊ฐ๋ณ์ ๊ฐ์ ๋์ดํ๋ฉด ์๋์ผ๋ก ๊ต์ฐจ ๊ฒ์ฆ์ ์ํํด์ ์ต์์ ๋งค๊ฐ๋ณ์ ์ฐพ์ ์ ์์
๋๋ค ์์น
๋งค๊ฐ๋ณ์ ๊ฐ์ ๋ชฉ๋ก์ ์ ๋ฌํ๋ ๊ฒ์ด ์๋๋ผ ๋งค๊ฐ๋ณ์๋ฅผ ์ํ๋งํ ์ ์๋ ํ๋ฅ ๋ถํฌ ๊ฐ์ฒด ์ ๋ฌ
์ธ์ดํ์ด - ํ๋ฅ ๋ถํฌ ํด๋์ค ์ํฌํธ
from scipy.stats import uniform, randint
์ธ์ดํ์ด stats ์๋ธ ํจํค์ง uniform, randint ํด๋์ค๋ ๋ชจ๋ ์ฃผ์ด์ง ๋ฒ์์์ ๊ณ ๋ฅด๊ฒ ๊ฐ์ ๋ฝ์
์ด๋ฅผ ๊ท ๋ฑ ๋ถํฌ์์ ์ํ๋งํ๋ค๊ณ ํจ
randint
* randint : ์ฃผ์ด์ง ๋ฒ์์์ ๊ณ ๋ฅด๊ฒ ์ ์๊ฐ ๋ฝ์
0์์ 10์ฌ์ด์ ๋ฒ์๋ฅผ ๊ฐ๋ ๊ฐ์ฒด ๋ง๋ค๊ณ 10๊ฐ์ ์ซ์ ์ํ๋ง
rgen = randint(0, 10)
rgen.rvs(10)
uniform
* uniform : ์ฃผ์ด์ง ๋ฒ์์์ ๊ณ ๋ฅด๊ฒ ์ค์๊ฐ ๋ฝ์
0~1 ์ฌ์ด์์ 10๊ฐ์ ์ค์ ์ถ์ถ
ugen = uniform(0,1)
ugen.rvs(10)
๋๋ค์์น์ randint, uniform ํด๋์ค ๊ฐ์ฒด ๋๊ฒจ์ฃผ๊ณ ์ด ๋ช ๋ฒ์ ์ํ๋งํด์ ์ต์ ์ ๋งค๊ฐ๋ณ์๋ฅผ ์ฐพ์ผ๋ผ๊ณ ๋ช ๋ น ๊ฐ๋ฅ
min_samples_leaf
* min_samples_leaf : ๋ฆฌํ ๋ ธ๋๊ฐ ๋๊ธฐ ์ํ ์ต์ ์ํ์ ๊ฐ์
์ด๋ค ๋ ธ๋๊ฐ ๋ถํ ํ์ฌ ๋ง๋ค์ด์ง ์์ ๋ ธ๋์ ์ํ ์๊ฐ ์ด ๊ฐ๋ณด๋ค ์์ ๊ฒฝ์ฐ ๋ถํ ํ์ง ์์
params = {'min_impurity_decrease': uniform(0.0001, 0.001),
'max_depth': randint(20, 50),
'min_samples_split': randint(2, 25),
'min_samples_leaf': randint(1, 25)}
min_imputiry_decrease๋ 0.0001์์ 0.001 ์ฌ์ด์ ์ค์๊ฐ์ ์ํ๋ง
max_depth์ 20์์ 50์ฌ์ด์ ์ ์
min_samples_split 2์์ 25 ์ฌ์ด์ ์ ์
min_samples_leaf 1์์ 25 ์ฌ์ด์ ์ ์ ์ํ๋ง
n_iter
* n_iter : ์ํ๋ง ํ์
์ํ๋ง ํ์๋ ์ฌ์ดํท๋ฐ ๋๋ค ์์น ํด๋์ค์ธ RandomizedSerchCV์ n_iter ๋งค๊ฐ๋ณ์์ ์ง์
from sklearn.model_selection import RandomizedSearchCV
gs = RandomizedSearchCV(DecisionTreeClassifier(random_state=42),
params, n_iter=100, n_jobs=-1, random_state=42)
gs.fit(train_input, train_target)
params์ ์ ์๋ ๋งค๊ฐ๋ณ์ ๋ฒ์์์ ์ด 100๋ฒ์ ์ํ๋งํ์ฌ ๊ต์ฐจ ๊ฒ์ฆ์ ์ํํ๊ณ ์ต์ ์ ๋งค๊ฐ๋ณ์ ์กฐํฉ ์ฐพ์
์ต์ ์ ๋งค๊ฐ๋ณ์ ์กฐํฉ
print(gs.best_params_)
{'max_depth': 39, 'min_impurity_decrease': 0.00034102546602601173, 'min_samples_leaf': 7, 'min_samples_split': 13}
์ต๊ณ ์ ๊ต์ฐจ ๊ฒ์ฆ ์ ์
print(np.max(gs.cv_results_['mean_test_score']))
์ต์ข ๋ชจ๋ธ ํ ์คํธ ์ธํธ ์ฑ๋ฅ ํ์ธ
์ต์ ์ ๋ชจ๋ธ์ ์ด๋ฏธ ์ ์ฒด ํ๋ จ ์ธํธ(train_input, train_target)๋ก ํ๋ จ๋์ด
best_estimator ์์ฑ์ ์ ์ฅ -> ์ด ๋ชจ๋ธ์ ์ต์ข ๋ชจ๋ธ๋ก ๊ฒฐ์ -> ํ ์คํธ ์ธํธ ์ฑ๋ฅ ํ์ธ
dt = gs.best_estimator_
print(dt.score(test_input, test_target))
0.86
= ์๋์ผ๋ก ๋งค๊ฐ๋ณ์ ๋ฐ๊พธ๋ ๋์ ์ ๊ทธ๋ฆฌ๋ ์์น, ๋๋ค ์์น ์ฌ์ฉํ์!
05-3. ํธ๋ฆฌ์ ์์๋ธ
๋์ฒด๋ก ์ฑ๋ฅ์ด ์ข์ ์๊ณ ๋ฆฌ์ฆ - ๋๋ค ํฌ๋ ์คํธ
์ ํ ๋ฐ์ดํฐ์ ๋น์ ํ ๋ฐ์ดํฐ
์ ํ ๋ฐ์ดํฐ : ์ด๋ค ๊ตฌ์กฐ๋ก ๋์ด ์๋ ๋ฐ์ดํฐ ex) csv, ๋ฐ์ดํฐ๋ฒ ์ด์ค, ์์
๋น์ ํ ๋ฐ์ดํฐ : ์ ํ ๋ฐ์ดํฐ์ ๋ฐ๋ ex) ํ ์คํธ ๋ฐ์ดํฐ, ์ฌ์ง, ์์
์์๋ธ ํ์ต : ์ ํ ๋ฐ์ดํฐ๋ฅผ ๋ค๋ฃจ๋ ๋ฐ ๊ฐ์ฅ ๋ฐ์ด๋ ์ฑ๊ณผ๋ฅผ ๋ด๋ ์๊ณ ๋ฆฌ์ฆ
์ ๊ฒฝ๋ง ์๊ณ ๋ฆฌ์ฆ : ๋น์ ํ ๋ฐ์ดํฐ๋ ๊ท์น์ฑ์ ์ฐพ๊ธฐ ์ด๋ ค์. ์ ๊ฒฝ๋ง ์๊ณ ๋ฆฌ์ฆ์ผ๋ก ๋ชจ๋ธ ๋ง๋ค ์ ์์
๋๋ค ํฌ๋ ์คํธ RandomForestClassifier
์์๋ธ ํ์ต์ ๋ํ ์ฃผ์ ์ค ํ๋๋ก ์์ ์ ์ธ ์ฑ๋ฅ ๋๋ถ์ ๋๋ฆฌ ์ฌ์ฉ
๊ฒฐ์ ํธ๋ฆฌ๋ฅผ ๋๋คํ๊ฒ ๋ง๋ค์ด ๊ฒฐ์ ํธ๋ฆฌ์ ์ฒ์ ๋ง๋ฆ
๊ทธ๋ฆฌ๊ณ ๊ฐ ๊ฒฐ์ ํธ๋ฆฌ์ ์์ธก์ ์ฌ์ฉํด ์ต์ข ์์ธก์ ๋ง๋ฆ
๊ฐ ํธ๋ฆฌ๋ฅผ ํ๋ จํ๊ธฐ ์ํ ๋ฐ์ดํฐ๋ฅผ ๋๋คํ๊ฒ ๋ง๋ ๋ค
์ ๋ ฅํ ํ๋ จ ๋ฐ์ดํฐ์์ ๋๋คํ๊ฒ ์ํ์ ์ถ์ถํ์ฌ ํ๋ จ ๋ฐ์ดํฐ๋ฅผ ๋ง๋ ๋ค - ์ด๋ ํ ์ํ์ด ์ค๋ณต๋์ด ์ถ์ถ๋ ์ ์์
์) 1000๊ฐ ๊ฐ๋ฐฉ์์ 100๊ฐ์ฉ ์ํ์ ๋ฝ๋๋ค๋ฉด ๋จผ์ 1๊ฐ๋ฅผ ๋ฝ๊ณ , ๋ฝ์๋ 1๊ฐ๋ฅผ ๋ค์ ๊ฐ๋ฐฉ์ ๋ฃ๋๋ค
์ด๋ฐ ์์ผ๋ก ๊ณ์ํด์ 100๊ฐ๋ฅผ ๊ฐ๋ฐฉ์์ ๋ฝ์ผ๋ฉด ์ค๋ณต๋ ์ํ ๋ฝ์ ์ ์์ -> ๋ถํธ์คํธ๋ฉ ์ํ
๋ถํธ์คํธ๋ฉ : ๋ฐ์ดํฐ ์ธํธ์์ ์ค๋ณต์ ํ์ฉํ์ฌ ๋ฐ์ดํฐ๋ฅผ ์ํ๋งํ๋ ๋ฐฉ์
๋ถํธ์คํธ๋ฉ ์ํ์ ํ๋ จ ์ธํธ์ ํฌ๊ธฐ์ ๊ฐ์
๊ฐ ๋ ธ๋๋ฅผ ๋ถํ ํ ๋ ์ ์ฒด ํน์ฑ ์ค์์ ์ผ๋ถ ํน์ฑ์ ๋ฌด์์๋ก ๊ณ ๋ฅธ ๋ค์ ์ด ์ค์์ ์ต์ ์ ๋ถํ ์ ์ฐพ์
๋ถ๋ฅ ๋ชจ๋ธ RandomForestClassifier - ์ ์ฒด ํน์ฑ ๊ฐ์์ ์ ๊ณฑ๊ทผ๋งํผ์ ํน์ฑ์ ์ ํ
ํ๊ท ๋ชจ๋ธ RandomForestRegressor - ์ ์ฒด ํน์ฑ ์ฌ์ฉ
์ฌ์ดํท๋ฐ ๋๋ค ํฌ๋ ์คํธ๋ ๊ธฐ๋ณธ 100๊ฐ์ ๊ฒฐ์ ํธ๋ฆฌ ํ๋ จ
๋ถ๋ฅ - ๊ฐ ํธ๋ฆฌ์ ํด๋์ค๋ณ ํ๋ฅ ์ ํ๊ท ํ์ฌ ๊ฐ์ฅ ๋์ ํ๋ฅ ์ ๊ฐ์ง ํด๋์ค๋ฅผ ์์ธก
ํ๊ท - ๋จ์ํ ๊ฐ ํธ๋ฆฌ์ ์์ธก ํ๊ท
๋๋ค ํฌ๋ ์คํธ๋ ๋๋คํ๊ฒ ์ ํํ ์ํ๊ณผ ํน์ฑ์ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์
ํ๋ จ ์ธํธ์ ๊ณผ๋์ ํฉ๋๋ ๊ฒ์ ๋ง์์ฃผ๊ณ ๊ฒ์ฆ ์ธํธ์ ํ ์คํธ ์ธํธ์์ ์์ ์ ์ธ ์ฑ๋ฅ ์ป์
๋ฐ์ดํฐ ์ค๋น, ํ๋ จ/ํ ์คํธ ์ธํธ ๋ถํ
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
wine = pd.read_csv('https://bit.ly/wine-date')
data = wine[['alcohol', 'sugar', 'pH']].to_numpy()
target = wine['class'].to_numpy()
train_input, test_input, train_target, test_target = train_test_split(data,
target, test_size=0.2, random_state=42)
๊ต์ฐจ ๊ฒ์ฆ
* return_train_score : True ์ง์ - ๊ฒ์ฆ ์ ์๋ฟ๋ง ์๋๋ผ ํ๋ จ ์ธํธ์ ๋ํ ์ ์๋ ๊ฐ์ด ๋ฐํ (๊ธฐ๋ณธ๊ฐ False)
from sklearn.model_selection import cross_validate
from sklearn.ensemble import RandomForestClassifier
rf = RandomForestClassifier(n_jobs=-1, random_state=42)
scores = cross_validate(rf, train_input, train_target, return_train_score=True, n_jobs=-1)
print(np.mean(scores['train_score']), np.mean(scores['test_score']))
0.9973541965122431
0.8905151032797809
๋๋ค ํฌ๋ ์คํธ๋ ๊ฒฐ์ ํธ๋ฆฌ์ ์์๋ธ์ด๊ธฐ ๋๋ฌธ์ DecisionTreeClassifier๊ฐ ์ ๊ณตํ๋ ์ค์ ๋งค๊ฐ๋ณ์ ๋ชจ๋ ์ ๊ณต
criterion, max_depth, max_features, min_samples_split, min_impurity_decrease, min_samples_leaf
๋๋ค ํฌ๋ ์คํธ ๋ชจ๋ธ ํ๋ จ ํ ํน์ฑ ์ค์๋ ์ถ๋ ฅ
๋๋ค ํฌ๋ ์คํธ ํน์ฑ ์ค์๋ : ๊ฐ ๊ฒฐ์ ํธ๋ฆฌ์ ํน์ฑ ์ค์๋๋ฅผ ์ทจํฉํ ๊ฒ
rf.fit(train_input, train_target)
print(rf.feature_importances_)
[0.23167441 0.50039841 0.26792718]
๋๋ค ํฌ๋ ์คํธ๋ ํน์ฑ์ ์ผ๋ถ๋ฅผ ๋๋คํ๊ฒ ์ ํํ์ฌ ๊ฒฐ์ ํธ๋ฆฌ๋ฅผ ํ๋ จ -> ํ๋์ ํน์ฑ์ ๊ณผ๋ํ๊ฒ ์ง์คํ์ง ์๊ณ
์ข ๋ ๋ง์ ํน์ฑ์ด ํ๋ จ์ ๊ธฐ์ฌํ ๊ธฐํ ์ป์ -> ๊ณผ๋์ ํฉ ์ค์ด๊ณ ์ผ๋ฐํ ์ฑ๋ฅ ๋์ด๋๋ฐ ๋์
OOB ์ ์ ์ถ๋ ฅ
์์ฒด์ ์ผ๋ก ๋ชจ๋ธ์ ํ๊ฐํ๋ ์ ์ ์ป์ ์ ์์
OBB ์ํ : ๋ถํธ์คํธ๋ฉ ์ํ์ ํฌํจ๋์ง ์๊ณ ๋จ๋ ์ํ
์ด ๋จ์ ์ํ์ ์ฌ์ฉํ์ฌ ๋ถํธ์คํธ๋ฉ ์ํ๋ก ํ๋ จํ ๊ฒฐ์ ํธ๋ฆฌ ํ๊ฐ ~ ๊ฒ์ฆ ์ธํธ ์ญํ !
rf = RandomForestClassifier(oob_score=True, n_jobs=-1, random_state=42)
rf.fit(train_input, train_target)
print(rf.oob_score_)
OOB ์ ์๋ฅผ ์ฌ์ฉํ๋ฉด ๊ต์ฐจ ๊ฒ์ฆ์ ๋์ ํ ์ ์์ด์
๊ฒฐ๊ณผ์ ์ผ๋ก ํ๋ จ ์ธํธ์ ๋ ๋ง์ ์ํ์ ์ฌ์ฉํ ์ ์์
์์คํธ๋ผ ํธ๋ฆฌ ExtraTreesClassifier
๋๋ค ํฌ๋ ์คํธ์ ์ ์ฌ
์ฐจ์ด์ : ๋ถํธ์คํธ๋ฉ ์ํ ์ฌ์ฉ X
๊ฒฐ์ ํธ๋ฆฌ๋ฅผ ๋ง๋ค ๋ ์ ์ฒด ํ๋ จ ์ธํธ๋ฅผ ์ฌ์ฉ
๋์ , ๋ ธ๋๋ฅผ ๋ถํ ํ ๋ ๊ฐ์ฅ ์ข์ ๋ถํ ์ ์ฐพ๋ ๊ฒ์ด ์๋๋ผ ๋ฌด์์๋ก ๋ถํ
์์คํธ๋ผ ํธ๋ฆฌ ์ฌ์ฉํ๋ ๊ฒฐ์ ํธ๋ฆฌ splitter='random'
ํ๋์ ๊ฒฐ์ ํธ๋ฆฌ์์ ํน์ฑ์ ๋ฌด์์๋ก ๋ถํ ํ๋ค๋ฉด ์ฑ๋ฅ์ด ๋ฎ์์ง๊ฒ ์ง๋ง
๋ง์ ํธ๋ฆฌ๋ฅผ ์์๋ธ ํ๊ธฐ ๋๋ฌธ์ ๊ณผ๋์ ํฉ์ ๋ง๊ณ ๊ฒ์ฆ ์ธํธ์ ์ ์ ๋์ด๋ ํจ๊ณผ์์
์์คํธ๋ผ ํธ๋ฆฌ ๊ต์ฐจ ๊ฒ์ฆ ์ ์ ํ์ธ
from sklearn.ensemble import ExtraTreesClassifier
et = ExtraTreesClassifier(n_jobs=-1, random_state=42)
scores = cross_validate(et, train_input, train_target,
return_train_score=True, n_jobs=-1)
print(np.mean(scores['train_score']), np.mean(scores['test_score']))
0.9974503966084433
0.8887848893166506
๋ณดํต ์์คํธ๋ผ ํธ๋ฆฌ๊ฐ ๋ฌด์์์ฑ์ด ์ข ๋ ํฌ๊ธฐ ๋๋ฌธ์ ๋๋ค ํฌ๋ ์คํธ๋ณด๋ค ๋ ๋ง์ ๊ฒฐ์ ํธ๋ฆฌ๋ฅผ ํ๋ จํด์ผ ํจ
ํ์ง๋ง ๋๋คํ๊ฒ ๋ ธ๋๋ฅผ ๋ถํ ํ๊ธฐ ๋๋ฌธ์ ๋น ๋ฅธ ๊ณ์ฐ ์๋๊ฐ ์ฅ์
ํน์ฑ ์ค์๋ ์ถ๋ ฅ
et.fit(train_input, train_target)
print(et.feature_importances_)
[0.20183568 0.52242907 0.27573525]
๊ทธ๋ ์ด๋์ธํธ ๋ถ์คํ GradientBoosintClassifier
๊น์ด๊ฐ ์์ ๊ฒฐ์ ํธ๋ฆฌ๋ฅผ ์ฌ์ฉํ์ฌ ์ด์ ํธ๋ฆฌ์ ์ค์ฐจ๋ฅผ ๋ณด์ํ๋ ๋ฐฉ์์ผ๋ก ์์๋ธ
๊ธฐ๋ณธ์ ์ผ๋ก ๊น์ด๊ฐ 3์ธ ๊ฒฐ์ ํธ๋ฆฌ๋ฅผ 100๊ฐ ์ฌ์ฉ
๊น์ด๊ฐ ์์ ๊ฒฐ์ ํธ๋ฆฌ๋ฅผ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ ๊ณผ๋์ ํฉ์ ๊ฐํ๊ณ ์ผ๋ฐ์ ์ผ๋ก ๋์ ์ผ๋ฐํ ์ฑ๋ฅ ๊ธฐ๋
๊ฒฝ์ฌ ํ๊ฐ๋ฒ์ ์ฌ์ฉํ์ฌ ํธ๋ฆฌ๋ฅผ ์์๋ธ์ ์ถ๊ฐ
๋ถ๋ฅ - ๋ก์ง์คํฑ ์์ค ํจ์
ํ๊ท - ํ๊ท ์ ๊ณฑ ์ค์ฐจ ํจ์
๊ฒฝ์ฌ ํ๊ฐ๋ฒ : ์์ค ํจ์๋ฅผ ์ฐ์ผ๋ก ์ ์ํ๊ณ
๋ชจ๋ธ์ ๊ฐ์ค์น์ ์ ํธ์ ์กฐ๊ธ์ฉ ๋ฐ๊ฟ์ ๊ฐ์ฅ ๋ฎ์ ๊ณณ์ ์ฐพ์ ๋ด๋ ค์ค๋ ๊ณผ์
๊ทธ๋ ์ด๋์ธํธ ๋ถ์คํ - ๊ฒฐ์ ํธ๋ฆฌ๋ฅผ ๊ณ์ ์ถ๊ฐํ๋ฉด์ ๊ฐ์ฅ ๋ฎ์ ๊ณณ์ ์ฐพ์ ์ด๋
๊ทธ๋ ์ด๋์ธํธ ๊ต์ฐจ ๊ฒ์ฆ ์ ์
from sklearn.ensemble import GradientBoostingClassifier
gb = GradientBoostingClassifier(random_state=42)
scores = cross_validate(gb, train_input, train_target,
return_train_score=True, n_jobs=-1)
print(np.mean(scores['train_score']), np.mean(scores['test_score']))
0.8881086892152563
0.8720430147331015
๊ฒฐ์ ํธ๋ฆฌ์ ๊ฐ์๋ฅผ ๋๋ ค๋ ๊ณผ๋์ ํฉ์ ๋งค์ฐ ๊ฐํจ
ํ์ต๋ฅ ์ ์ฆ๊ฐ์ํค๊ณ ํธ๋ฆฌ์ ๊ฐ์๋ฅผ ๋๋ฆฌ๋ฉด ์กฐ๊ธ ๋ ์ฑ๋ฅ ํฅ์ ๊ฐ๋ฅ
* learning_rate : ํ์ต๋ฅ (๊ธฐ๋ณธ๊ฐ 0.1)
ํน์ฑ ์ค์๋
gb.fit(train_input, train_target)
print(gb.feature_importances_)
[0.11949946 0.74871836 0.13178218]
* subsample : ํธ๋ฆฌ ํ๋ จ์ ์ฌ์ฉํ ํ๋ จ ์ธํธ์ ๋น์จ ์ ํจ
(๊ธฐ๋ณธ๊ฐ 1.0 ์ ์ฒด ํ๋ จ ์ธํธ ์ฌ์ฉ / 1๋ณด๋ค ์์ผ๋ฉด ํ๋ จ ์ธํธ์ ์ผ๋ถ ์ฌ์ฉ)
๊ทธ๋ ์ด๋์ธํธ ๋ถ์คํ ์ด ๋๋ค ํฌ๋ ์คํธ๋ณด๋ค ์กฐ๊ธ ๋ ๋์ ์ฑ๋ฅ ์ป์ ์ ์์
ํ์ง๋ง ์์๋๋ก ํธ๋ฆฌ๋ฅผ ์ถ๊ฐํ๊ธฐ ๋๋ฌธ์ ํ๋ จ ์๋ ๋๋ฆผ
์ฆ, GradientBoostingClassifier์๋ n_jobs ๋งค๊ฐ๋ณ์ ์์
ํ์คํ ๊ทธ๋จ ๊ธฐ๋ฐ ๊ทธ๋ ์ด๋์ธํธ ๋ถ์คํ HistGradientBoosintClassifier
์ ํ ๋ฐ์ดํฐ๋ฅผ ๋ค๋ฃจ๋ ๋จธ์ ๋ฌ๋ ์๊ณ ๋ฆฌ์ฆ ์ค์์ ๊ฐ์ฅ ์ธ๊ธฐ๊ฐ ๋์ ์๊ณ ๋ฆฌ์ฆ
์ ๋ ฅ ํน์ฑ์ 256๊ฐ์ ๊ตฌ๊ฐ์ผ๋ก ๋๋ - ๋ ธ๋๋ฅผ ๋ถํ ํ ๋ ์ต์ ์ ๋ถํ ์ ๋งค์ฐ ๋น ๋ฅด๊ฒ ์ฐพ์ ์ ์์
256๊ฐ์ ๊ตฌ๊ฐ ์ค์์ ํ๋๋ฅผ ๋ด์ด ๋๊ณ ๋๋ฝ๋ ๊ฐ์ ์ํด์ ์ฌ์ฉ
ํธ๋ฆฌ ๊ฐ์๋ฅผ ์ง์ ํ๋๋ฐ n_estimators ๋์ ๋ถ์คํ ๋ฐ๋ณต ํ์๋ฅผ ์ง์ ํ๋ max_iter ์ฌ์ฉ
ํ์คํ ๊ทธ๋จ ๊ธฐ๋ฐ ๊ทธ๋ ์ด๋์ธํธ ๋ถ์คํ ๊ฒ์ฆ ์ ์
from sklearn.experimental import enable_hist_gradient_boosting
from sklearn.ensemble import HistGradientBoostingClassifier
hgb = HistGradientBoostingClassifier(random_state=42)
scores = cross_validate(hgb, train_input, train_target, return_train_score=True, n_jobs=-1)
print(np.mean(scores['train_score']), np.mean(scores['test_score']))
0.9321723946453317
0.8801241948619236
๊ณผ๋์ ํฉ์ ์ ์ต์ ํ๋ฉด์, ๊ทธ๋ ์ด๋์ธํธ ๋ถ์คํ ๋ณด๋ค ์ข ๋ ๋์ ์ฑ๋ฅ
ํ๋ จ ์ธํธ ํน์ฑ ์ค์๋
* permutation_importance() : ๊ทธ๋ ์ด๋์ธํธ ๋ถ์คํ ์ ํน์ฑ ์ค์๋
ํน์ฑ์ ํ๋์ฉ ๋๋คํ๊ฒ ์์ด์ ๋ชจ๋ธ์ ์ฑ๋ฅ์ด ๋ณํํ๋์ง๋ฅผ ๊ด์ฐฐํ์ฌ ์ด๋ค ํน์ฑ์ด ์ค์ํ์ง ๊ณ์ฐ
* n_repeats : ๋๋คํ๊ฒ ์์ ํ์ (๊ธฐ๋ณธ๊ฐ 5)
from sklearn.inspection import permutation_importance
hgb.fit(train_input, train_target)
result = permutation_importance(hgb, train_input, train_target,
n_repeats=10, random_state=42, n_jobs=-1)
print(result.importances_mean)
[0.08876275 0.23438522 0.08027708]
permutation_importancer() ํจ์๊ฐ ๋ฐํํ๋ ๊ฐ์ฒด๋ ๋ฐ๋ณตํ์ฌ ์ป์ ํน์ฑ ์ค์๋, ํ๊ท , ํ์คํธ์ฐจ ๋ด๊ณ ์์
ํ ์คํธ ์ธํธ ํน์ฑ ์ค์๋
result = permutation_importance(hgb, test_input, test_target,
n_repeats=10, random_state = 42, n_jobs=-1)
print(result.importances_mean)
[0.05969231 0.20238462 0.049 ]
ํ ์คํธ ์ธํธ ์ต์ข ์ฑ๋ฅ ํ์ธ
hgb.score(test_input, test_target)
0.8723076923076923
์ฌ์ดํท๋ฐ ๋ง๊ณ ๊ทธ๋ ์ด๋์ธํธ ๋ถ์คํ ์๊ณ ๋ฆฌ์ฆ ๊ตฌํํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ
XGBoost
from xgboost import XGBClassifier
xgb = XGBClassifier(tree_method='hist', random_state=42)
scores = cross_validate(xgb, train_input, train_target, return_train_score=True, n_jobs=-1)
print(np.mean(scores['train_score']), np.mean(scores['test_score']))
LightGBM
from lightgbm import LGBMClassifier
lgb = LGBMClassifier(random_state=42)
scores = cross_validate(lgb, train_input, train_target, return_train_score=True, n_jobs=1)
print(np.mean(scores['train_score']), np.mean(scores['test_score']))
์ฐธ๊ณ ๋์ : ํผ์๊ณต๋ถํ๋ ๋จธ์ ๋ฌ๋ + ๋ฅ๋ฌ๋, ๋ฐํด์ , ํ๋น๋ฏธ๋์ด, 2020๋
'Ability ๐ฑ > ML' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[ํผ๊ณต๋จธ์ ] 06. ๋น์ง๋ ํ์ต - ๊ตฐ์ง, ์ฃผ์ฑ๋ถ ๋ถ์ (0) | 2022.06.23 |
---|---|
[ํผ๊ณต๋จธ์ ] 05. ์ ๋ฆฌ (0) | 2022.06.22 |
[ํผ๊ณต๋จธ์ ] 04. ์ ๋ฆฌ (1) | 2022.06.21 |
[ํผ๊ณต๋จธ์ ] 04. ๋ค์ํ ๋ถ๋ฅ ์๊ณ ๋ฆฌ์ฆ - ๋ก์ง์คํฑ ํ๊ท, ํ๋ฅ ์ ๊ฒฝ์ฌ ํ๊ฐ๋ฒ (0) | 2022.06.19 |
[ํผ๊ณต๋จธ์ ] 03. ์ ๋ฆฌ (0) | 2022.04.26 |