:bread: ๋ชจ๋ธ, ํ˜น์‹œ ์•”๊ธฐ๋งŒ ํ•˜๊ณ  ์žˆ๋‹ˆ?

์—ด์‹ฌํžˆ ๋งŒ๋“  ๋จธ์‹ ๋Ÿฌ๋‹ ๋ชจ๋ธ์ด ํ•™์Šต ๋ฐ์ดํ„ฐ์—์„œ๋Š” 100์ ์ธ๋ฐ, ๋ง‰์ƒ ์‹ค์ „์— ํˆฌ์ž…ํ•˜๋‹ˆ ์—‰๋šฑํ•œ ๋‹ต์„ ๋‚ด๋†“๋Š”๋‹ค๋ฉด ์–ด๋–จ๊นŒ? ๋งˆ์น˜ ์‹œํ—˜ ๋ฒ”์œ„๋งŒ ๋‹ฌ๋‹ฌ ์™ธ์šฐ๊ณ  ์‘์šฉ ๋ฌธ์ œ๋Š” ํ•˜๋‚˜๋„ ํ’€์ง€ ๋ชปํ•˜๋Š” ํ•™์ƒ ๊ฐ™์•˜๋‹ค. ์ด๋Ÿฐ ํ˜„์ƒ์„ ๊ณผ๋Œ€์ ํ•ฉ(Overfitting) ์ด๋ผ๊ณ  ํ•œ๋‹ค. ๋ฐ˜๋Œ€๋กœ ๋„ˆ๋ฌด ๊ณต๋ถ€๋ฅผ ์•ˆ ํ•ด์„œ ํŒจํ„ด์กฐ์ฐจ ํŒŒ์•…ํ•˜์ง€ ๋ชปํ•˜๋ฉด ๊ณผ์†Œ์ ํ•ฉ(Underfitting) ์ด๋‹ค.

๐Ÿ’ก โ€œ๋ชจ๋ธ์˜ ์ง„์งœ ์‹ค๋ ฅ์€ ์ƒˆ๋กœ์šด ๋ฐ์ดํ„ฐ์—์„œ ๋‚˜ํƒ€๋‚œ๋‹ค!โ€

๋ชจ๋ธ์ด ํ•™์Šต ๋ฐ์ดํ„ฐ์—๋งŒ ์น˜์šฐ์น˜์ง€ ์•Š๊ณ  ์ผ๋ฐ˜์ ์ธ ์„ฑ๋Šฅ์„ ๊ฐ–๋„๋ก ํ•˜๋Š” ๊ฒƒ, ๋ฐ”๋กœ ๊ต์ฐจ ๊ฒ€์ฆ๊ณผ ๋ฐ์ดํ„ฐ ์ „์ฒ˜๋ฆฌ๊ฐ€ ๊ทธ ํ•ด๋‹ต์ด์—ˆ๋‹ค. ์˜ค๋Š˜ ๋‚ด๊ฐ€ ๋ชจ๋ธ์˜ ๊ฑด๊ฐ• ์ƒํƒœ๋ฅผ ๊ผผ๊ผผํžˆ ์ง„๋‹จํ•˜๊ณ  ์ปจ๋””์…˜์„ ์ตœ์ƒ์œผ๋กœ ๋Œ์–ด์˜ฌ๋ ธ๋˜ ๋ฐฉ๋ฒ•์„ ๊ณต์œ ํ•ด๋ณธ๋‹ค.


๐Ÿš€ ์‹ ๋ขฐ๋„๋ฅผ ๋†’์ด๋Š” ํ›ˆ๋ จ๋ฒ•: ๊ต์ฐจ ๊ฒ€์ฆ

๋ฐ์ดํ„ฐ๋ฅผ ์—ฌ๋Ÿฌ ์กฐ๊ฐ์œผ๋กœ ๋‚˜๋ˆ ์„œ, ๋ชจ๋ธ์„ ์—ฌ๋Ÿฌ ๋ฒˆ ํ…Œ์ŠคํŠธํ•˜๊ณ  ํ‰๊ท  ์„ฑ๋Šฅ์„ ํ‰๊ฐ€ํ•˜๋Š” ์•„์ฃผ ์Šค๋งˆํŠธํ•œ ๋ฐฉ๋ฒ•์ด์—ˆ๋‹ค. ํŠนํžˆ K-ํด๋“œ ๊ต์ฐจ ๊ฒ€์ฆ์€ ๋ฐ์ดํ„ฐ๋ฅผ K๊ฐœ์˜ ๋ฉ์–ด๋ฆฌ(ํด๋“œ)๋กœ ๋‚˜๋ˆ„๊ณ , ํ•˜๋‚˜์”ฉ ๋Œ์•„๊ฐ€๋ฉฐ ํ…Œ์ŠคํŠธ์šฉ์œผ๋กœ ์‚ฌ์šฉํ•ด์„œ ๋ฐ์ดํ„ฐ๊ฐ€ ๋ถ€์กฑํ•ด๋„ ์‹ ๋ขฐ๋„ ๋†’์€ ๊ฒ€์ฆ์„ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ–ˆ๋‹ค.

# K-Fold๋กœ ๊ต์ฐจ ๊ฒ€์ฆ์„ ์ง์ ‘ ๊ตฌํ˜„ํ•ด๋ดค๋‹ค.
from sklearn.model_selection import KFold
from sklearn.metrics import accuracy_score
import numpy as np

# ์˜ˆ์‹œ ๋ฐ์ดํ„ฐ์™€ ๋ชจ๋ธ์ด ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ–ˆ๋‹ค.
# X, y, dt_clf

kfold = KFold(n_splits=5)
cv_accuracy = []

for train_index, test_index in kfold.split(X):
    X_train, X_test = X[train_index], X[test_index]
    y_train, y_test = y[train_index], y[test_index]

    dt_clf.fit(X_train, y_train)
    pred = dt_clf.predict(X_test)

    accuracy = np.round(accuracy_score(y_test, pred), 4)
    cv_accuracy.append(accuracy)

print(f'K-Fold ํ‰๊ท  ์ •ํ™•๋„: {np.mean(cv_accuracy):.4f} ์„ฑ๊ณต! ๐ŸŽ‰')

๋ฐ์ดํ„ฐ๋ฅผ ์•Œ์ฐจ๊ฒŒ ํ™œ์šฉํ•ด์„œ ๋ชจ๋ธ์˜ ์ผ๋ฐ˜ํ™” ์„ฑ๋Šฅ์„ ์ธก์ •ํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค. ์ด์ œ ๋‚ด ๋ชจ๋ธ์€ ๋” ์ด์ƒ ์šฐ๋ฌผ ์•ˆ ๊ฐœ๊ตฌ๋ฆฌ๊ฐ€ ์•„๋‹ˆ๋‹ค!:frog:


โœจ ๋ฐ์ดํ„ฐ ์„ฑํ˜•์ˆ˜์ˆ : ์ „์ฒ˜๋ฆฌ(Preprocessing)

โ€œGarbage in, Garbage out.โ€ ์ด๋ผ๋Š” ๋ง์ด ์žˆ๋‹ค. ์ข‹์€ ๋ชจ๋ธ์€ ์ข‹์€ ๋ฐ์ดํ„ฐ์—์„œ ๋‚˜์˜ค๋Š” ๋ฒ•. ๋ชจ๋ธ์ด ์ž˜ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋„๋ก ๋ฐ์ดํ„ฐ๋ฅผ ๊น”๋”ํ•˜๊ฒŒ ๋‹ค๋“ฌ์–ด์ฃผ๋Š” ์ „์ฒ˜๋ฆฌ ๊ธฐ๋ฒ•๋“ค์„ ์•Œ์•„๋ดค๋‹ค.

1. ๋ ˆ์ด๋ธ” ์ธ์ฝ”๋”ฉ (Label Encoding)

'TV', '๋ƒ‰์žฅ๊ณ ' ๊ฐ™์€ ๋ฌธ์ž์—ด ๋ฐ์ดํ„ฐ๋ฅผ ์ˆซ์ž๋กœ ๋ฐ”๊ฟ”์ฃผ์ง€๋งŒ, ์ˆซ์ž ํฌ๊ธฐ์— ์˜๋ฏธ๊ฐ€ ๋ถ€์—ฌ๋  ์ˆ˜ ์žˆ์–ด ์ฃผ์˜๊ฐ€ ํ•„์š”ํ–ˆ๋‹ค. (e.g., TV(0) < ๋ƒ‰์žฅ๊ณ (1))

from sklearn.preprocessing import LabelEncoder

items = ['TV', '๋ƒ‰์žฅ๊ณ ', '์ „์ž๋ ˆ์ธ์ง€', '์ปดํ“จํ„ฐ', '์„ ํ’๊ธฐ', '์„ ํ’๊ธฐ', '๋ฏน์„œ', '๋ฏน์„œ']
encoder = LabelEncoder()
labels = encoder.fit_transform(items)
# ์ธ์ฝ”๋”ฉ ๋ณ€ํ™˜๊ฐ’: [0 1 4 5 3 3 2 2]

2. ์›-ํ•ซ ์ธ์ฝ”๋”ฉ (One-Hot Encoding)

์œ„ ๋‹จ์ ์„ ๋ณด์™„ํ•˜๊ธฐ ์œ„ํ•ด ๊ฐ ์นดํ…Œ๊ณ ๋ฆฌ๋ฅผ ์ƒˆ๋กœ์šด ํ”ผ์ฒ˜(์—ด)๋กœ ๋งŒ๋“ ๋‹ค. ํ•ด๋‹นํ•˜๋ฉด 1, ์•„๋‹ˆ๋ฉด 0์œผ๋กœ ํ‘œ์‹œํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ํ”ผ์ฒ˜๊ฐ€ ๋„ˆ๋ฌด ๋งŽ์•„์ง€๋Š” ๋‹จ์ ์€ ๊ฐ์ˆ˜ํ•ด์•ผ ํ–ˆ๋‹ค.

from sklearn.preprocessing import OneHotEncoder

# 2์ฐจ์› ๋ฐฐ์—ด๋กœ ๋ณ€ํ™˜ํ•ด์•ผ ํ–ˆ๋‹ค.
items_2d = np.array(items).reshape(-1, 1)
oh_encoder = OneHotEncoder()
oh_labels = oh_encoder.fit_transform(items_2d)
# print(oh_labels.toarray())

3. ํ”ผ์ฒ˜ ์Šค์ผ€์ผ๋ง (Feature Scaling)

ํ‚ค(cm)์™€ ๋ชธ๋ฌด๊ฒŒ(kg)์ฒ˜๋Ÿผ ๋‹จ์œ„๊ฐ€ ๋‹ค๋ฅธ ํ”ผ์ฒ˜๋“ค์˜ ๊ฐ’ ๋ฒ”์œ„๋ฅผ ๋งž์ถฐ์ฃผ๋Š” ์ž‘์—…์ด๋‹ค.

๊ตฌ๋ถ„ StandardScaler MinMaxScaler
๊ฐœ๋… ํ‰๊ท  0, ๋ถ„์‚ฐ 1์˜ ์ •๊ทœ๋ถ„ํฌ ํ˜•ํƒœ๋กœ ๋ณ€ํ™˜ ๋ชจ๋“  ๊ฐ’์„ 0๊ณผ 1 ์‚ฌ์ด๋กœ ์กฐ์ •
ํŠน์ง• ์ด์ƒ์น˜์— ์ƒ๋Œ€์ ์œผ๋กœ ๋œ ๋ฏผ๊ฐ ์ด์ƒ์น˜์— ๋ฏผ๊ฐํ•˜๊ฒŒ ๋ฐ˜์‘ํ•  ์ˆ˜ ์žˆ์Œ
# ๋ถ“๊ฝƒ ๋ฐ์ดํ„ฐ๋กœ ์Šค์ผ€์ผ๋ง์„ ์ง์ ‘ ํ•ด๋ณด๋‹ˆ ๋ฐ์ดํ„ฐ ๋ถ„ํฌ๊ฐ€ ๋ฐ”๋€Œ๋Š” ๊ฒŒ ์‹ ๊ธฐํ–ˆ๋‹ค.
from sklearn.preprocessing import StandardScaler, MinMaxScaler

# iris ๋ฐ์ดํ„ฐ๊ฐ€ ๋กœ๋“œ๋˜์–ด ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ–ˆ๋‹ค.
std_scaler = StandardScaler()
iris_scaled_std = std_scaler.fit_transform(iris.data)

minmax_scaler = MinMaxScaler()
iris_scaled_minmax = minmax_scaler.fit_transform(iris.data)

๐Ÿ“Š ๋ชจ๋ธ ์„ฑ์ ํ‘œ ์ œ๋Œ€๋กœ ์ฝ๊ธฐ: ์„ฑ๋Šฅ ์ธก์ • ์ง€ํ‘œ

์ •ํ™•๋„(Accuracy)๋งŒ ๋ฏฟ์œผ๋ฉด ํฐ์ฝ”๋‹ค์น  ์ˆ˜ ์žˆ๋‹ค. ํŠนํžˆ ๋ฐ์ดํ„ฐ๊ฐ€ ๋ถˆ๊ท ํ˜•ํ•  ๋•Œ ๊ทธ๋ ‡๋‹ค. ๋ชจ๋ธ์˜ ์ง„์งœ ์‹ค๋ ฅ์„ ๋‹ค๊ฐ๋„๋กœ ํ‰๊ฐ€ํ•˜๋Š” ์ง€ํ‘œ๋“ค์„ ์•Œ์•„๋ดค๋‹ค.

  • ์˜ค์ฐจ ํ–‰๋ ฌ (Confusion Matrix): ๋ชจ๋ธ์ด ๋ญ˜ ๋งž์ถ”๊ณ  ๋ญ˜ ํ—ท๊ฐˆ๋ฆฌ๋Š”์ง€ ํ•œ๋ˆˆ์— ๋ณด์—ฌ์ฃผ๋Š” ํ‘œ๋‹ค. ๋ชจ๋“  ์ง€ํ‘œ์˜ ์–ด๋จธ๋‹ˆ!
  • ์ •๋ฐ€๋„ (Precision): โ€œ๋ชจ๋ธ์ด ์ •๋‹ต์ด๋ผ๊ณ  ์˜ˆ์ธกํ•œ ๊ฒƒ ์ค‘ ์ง„์งœ ์ •๋‹ต ๋น„์œจโ€์ด๋‹ค. (Positive ์˜ˆ์ธก ์„ฑ๋Šฅ)
  • ์žฌํ˜„์œจ (Recall): โ€œ์‹ค์ œ ์ •๋‹ต ์ค‘ ๋ชจ๋ธ์ด ์ •๋‹ต์ด๋ผ๊ณ  ๋งž์ถ˜ ๋น„์œจโ€์ด๋‹ค. (๋†“์น˜๋ฉด ์•ˆ ๋˜๋Š” ๊ฒƒ์„ ์ฐพ์•„๋‚ด๋Š” ๋Šฅ๋ ฅ)
  • F1 ์Šค์ฝ”์–ด (F1 Score): ์ •๋ฐ€๋„์™€ ์žฌํ˜„์œจ์˜ ์กฐํ™” ํ‰๊ท . ๋‘˜ ๋‹ค ์ค‘์š”ํ•  ๋•Œ ๋น›์„ ๋ฐœํ•œ๋‹ค.
  • ROC ๊ณก์„ ๊ณผ AUC: ๋ชจ๋ธ์ด ์ •๋‹ต๊ณผ ์˜ค๋‹ต์„ ์–ผ๋งˆ๋‚˜ ์ž˜ ๊ตฌ๋ถ„ํ•˜๋Š”์ง€ ๋ณด์—ฌ์ฃผ๋Š” ๊ณก์„ ๊ณผ ๊ทธ ์•„๋ž˜ ๋ฉด์ . AUC๊ฐ€ 1์— ๊ฐ€๊นŒ์šธ์ˆ˜๋ก ์™„๋ฒฝํ•œ ๋ชจ๋ธ์ด๋‹ค.

์•” ํ™˜์ž ์˜ˆ์ธก ๋ชจ๋ธ์—์„œ, ์‹ค์ œ ํ™˜์ž(True)๋ฅผ ๋†“์น˜์ง€ ์•Š๋Š” ๊ฒƒ(Recall)์ด ์ค‘์š”ํ• ๊นŒ, ์•„๋‹ˆ๋ฉด ์ผ๋ฐ˜์ธ(False)์„ ํ™˜์ž๋กœ ์ž˜๋ชป ์˜ˆ์ธกํ•˜์ง€ ์•Š๋Š” ๊ฒƒ(Precision)์ด ์ค‘์š”ํ• ๊นŒ? ์ด์ฒ˜๋Ÿผ ์ƒํ™ฉ์— ๋งž๋Š” ์ง€ํ‘œ ์„ ํƒ์ด ํ•„์ˆ˜๋ผ๋Š” ๊ฑธ ๋А๊ผˆ๋‹ค.


โœจ ์˜ค๋Š˜์˜ ํšŒ๊ณ 

์˜ค๋Š˜ ํ•™์Šต์œผ๋กœ ๋ชจ๋ธ์˜ ์„ฑ๋Šฅ์„ ์ œ๋Œ€๋กœ ์ธก์ •ํ•˜๊ณ  ๊ฐœ์„ ํ•˜๋Š” ๊ธฐ๋ณธ๊ธฐ๋ฅผ ๋‹ค์กŒ๋‹ค. ๊ณผ๋Œ€์ ํ•ฉ์„ ํ”ผํ•˜๊ธฐ ์œ„ํ•œ ๊ต์ฐจ ๊ฒ€์ฆ์˜ ์ค‘์š”์„ฑ๊ณผ ๋ฐ์ดํ„ฐ ํŠน์„ฑ์— ๋งž๋Š” ์ „์ฒ˜๋ฆฌ ๊ธฐ๋ฒ•์„ ์ ์šฉํ•˜๋Š” ๋ฒ•๋„ ๋ฐฐ์› ๋‹ค.

ํŠนํžˆ ์ •ํ™•๋„๋ผ๋Š” ํ•˜๋‚˜์˜ ์ˆซ์ž ๋’ค์— ์ˆจ๊ฒจ์ง„ ๋ชจ๋ธ์˜ ์ง„์งœ ์„ฑ๋Šฅ์„ ์˜ค์ฐจ ํ–‰๋ ฌ, ์ •๋ฐ€๋„, ์žฌํ˜„์œจ, AUC ๋“ฑ ๋‹ค์–‘ํ•œ ์ง€ํ‘œ๋กœ ๋‹ค๊ฐ์ ์œผ๋กœ ํ‰๊ฐ€ํ•ด์•ผ ํ•œ๋‹ค๋Š” ์ ์ด ๊ฐ€์žฅ ์ค‘์š”ํ•˜๊ฒŒ ๋‹ค๊ฐ€์™”๋‹ค. ์•ž์œผ๋กœ ๋ชจ๋ธ์„ ๋งŒ๋“ค ๋•Œ, ์ด ๊ฑด๊ฐ•๊ฒ€์ง„ํ‘œ๋“ค์„ ๊ผผ๊ผผํžˆ ํ™•์ธํ•˜๋ฉฐ ๋” ์‹ ๋ขฐ๋„ ๋†’์€ AI๋ฅผ ๋งŒ๋“ค์–ด ๋‚˜๊ฐ€์•ผ๊ฒ ๋‹ค๊ณ  ๋‹ค์งํ–ˆ๋‹ค. ๐Ÿ˜„