[AI ์คํฐ๋] Section 5 : ์ ํต์ ์ธ ๋จธ์ ๋ฌ๋ - ์ง๋ํ์ต ๋ชจ๋ธ part 2
Logistic Regression (๋ก์ง์คํฑ ํ๊ท)
๋ก์ง์คํฑ ํ๊ท ์๊ฐ
: regression์ด๋ผ๋ ์ด๋ฆ์ด์ง๋ง ๋ถ๋ฅ ๋ฌธ์ → ์ด์ง ๋ถ๋ฅ ๋ฌธ์
๋ก์ง์คํฑ ํ๊ท ๋ถ๋ฅ๊ธฐ
01. ๋ฐฉ๋ฒ
: ๋ ๋ฆฝ๋ณ์์ ์ข ์๋ณ์ ๊ฐ์ ๊ด๊ณ๋ฅผ ์ฐพ์๋ด๊ณ ํ๊ฐ
- ํ๊ท ์์ ๊ตฌํด์ ๊ฐ์ ์์ธก ⇒ ํ๋ฅ ๊ฐ์ ๋ฐํ
- 0.5 ๋ณด๋ค ์์ผ๋ฉด 0. 0.5 ๋ณด๋ค ํฌ๋ฉด 1๋ก ๋ถ๋ฅ
02. ํน์ง ๋ฐ ํ์ฉ
(1) ๊ตฌํ์ด ๊ฐ๋จ
(2) ๋ชจ๋ ๋ถ๋ฅ ๋ฌธ์ ์ ๊ธฐ์ด๊ฐ ๋จ
(3) ๋ก์ง์คํฑ ํ๊ท์ ๊ธฐ๋ณธ ๊ฐ๋ ์ด ๋ฅ๋ฌ๋์ ์ ์ฉ๋จ
(4) ๋ฌธ์ ์
- ๋ถ๋ฅ ๋ฌธ์ ์ ์ ํฉํ ํจ์์ธ๊ฐ
- ๋ชจํธํ ๊ฒฝ๊ณ ⇒ ํด๊ฒฐ : ์๊ทธ๋ชจ์ด๋ ํจ์
03. ์๊ทธ๋ชจ์ด๋ ํจ์ (= ๋ก์ง์คํฑ ํจ์)
(1) ๋ก์ง์คํฑ ํ๊ท์ ์ ํฉํ ์ด์
- ๊ฒฝ๊ณ๊ฐ ๋ช ํํ ๋ณด์ฌ์ง
- 0 ~ 1 ์ฌ์ด์ ๊ฐ์ ๊ฐ์ง๋ฏ๋ก ํ๋ฅ ๊ฐ์ผ๋ก ํด์ ๊ฐ๋ฅํจ
- ๋ฏธ๋ถ ๊ฐ๋ฅํจ
(2) ๊ณต์
$$ f(z) = \frac{1}{1+e^{-z}} $$
- z : logit = $\theta X$⇒ ๊ทธ๋์ ์ด๋ฆ์ด Logistic regression
- ⇒ logit์์ regression์ด ๋ค์ด๊ฐ์๋ ํํ (wx +b)
04. ๋ชจ๋ธ ์ฌ์ฉ ์ฝ๋
: sklearn.linear_model.LogisticRegression(solver=‘lbfgs’)
→ solver : optimization algorithm
๋ก์ง์คํฑ ํ๊ท ์ค์ต : ์ด์ง๋ถ๋ฅ
๋ฐ์ดํฐ ์๊ฐ
- ์นผ๋ผ : ์ฌ์ฉ์ id, ์ฑ๋ณ, ์ฐ๋ น, ์ถ์ ๊ธ์ฌ, ๊ตฌ๋งค์ฌ๋ถ
- ์์ธก : ํน์ ์ฌ์ฉ์๊ฐ ๊ตฌ๋งค ํ ์ง ์ฌ๋ถ → ๊ตฌ๋งค: 1, ๊ตฌ๋งค ์์: 0
User ID Gender Age EstimatedSalary Purchased
| 395 | 15691863 | Female | 46 | 41000 |
| 396 | 15706071 | Male | 51 | 23000 |
| 397 | 15654296 | Female | 50 | 20000 |
| 398 | 15755018 | Male | 36 | 33000 |
| 399 | 15594041 | Female | 49 | 36000 |
1. ๋ฐ์ดํฐ ํ์ธ ๋ฐ ๋ณ์ ์ค์
# ๋ฐ์ดํฐ ํ์ธ
df.head() # ์ฒ์๋ถํฐ ํ์ธ
df.tail() # ๋์์ ํ์ธ
df['purchased'].value_counts() # ์์ธก ๋ ์ด๋ธ์ด ํธํฅ ๋์๋์ง ํ์ธํ๊ธฐ ์ํด
# 50 50 ์ผ๋ก ๋์ด์์ผ๋ฉด ์ข๊ฒ ์ง๋ง, 2๋ 1 ์ ๋๋ฉด ๋ง์ด ํธํฅ ๋๊ฒ ์๋
# ๋ฐ์ดํฐ ๋ถ๋ฅ
# int๋ก ๋ฃ์ด์ค๋ ๋์ง๋ง float ํํ๊ฐ ์ผ๋ฐ์ ์ด๋ฏ๋ก ๋ณํ
X = df.iloc[:, [2,3]].values.astype("float32") # age, estimatedSalary๋ง ์ฌ์ฉ
y = df.iloc[:, 4].values.astype("float32") # purchased
X.shape, y.shape # 400,2 / 400,
# train, test split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)
X_train.shape, X_test.shape, y_train.shape, y_test.shape # 320,2 / 80,2 / 320, / 80,
2. Feature Scaling
# age = 10๋จ์, EstimatedSalaryy = 10000๋จ์
# => ์ซ์ ์ฐจ์ด๊ฐ ํฐ๋ฐ ์ด๋ฐ ๊ฒฝ์ฐ, ํฐ ์ซ์๊ฐ ๋ฆฌ๋ฉํ๊ธฐ ๋๋ฌธ์ ์ค์ผ์ผ๋ง ํ์
sc = StandardScaler() # ์ธ์คํด์ค ์์ฑ
X_train = sc.fit_transform(X_train) # fit, transform์ ๋ฐ๋ก ํ ์๋ ์์
# transform ๋ง ํด์ผํจ
# -> fitํ๋ฉด ๋ณ๋๋ก ๋ฐ์ดํฐ์
์ ํ๊ท , ํ์คํธ์ฐจ๋ฅผ ๋ค์ ๊ณ์ฐํ๋ฏ๋ก ๋ฏธ๋์ ๋ฐ์ดํฐ๋ฅผ ๋ฏธ๋ฆฌ ๊ณ์ฐํ๋ฉด ์๋จ
X_test = sc.transform(X_test)
print(X_train.shape) # 320, 2
3. ๋ชจ๋ธ
# fit
lr_clf = LogisticRegression(solver='lbfgs', random_state=0)
lr_clf.fit(X_train, y_train)
# predict : ์์ธก๋ class ๋ฐํ
y_pred = lr_clf.predict(X_test)
# ํ๊ฐ
print("Test set์ ์ค์ true ๊ฐฏ์ = ", sum(y_test)) # 22
print("๋ชจ๋ธ์ด ์์ธกํ true ๊ฐฏ์ = ", sum(y_pred)) #18
print("accuracy = {:.2f}".format(accuracy_score(y_test, y_pred))) # 0.925
print("precision = {:.2f}".format(precision_score(y_test, y_pred))) # 0.94
print("recall = {:.2f}".format(recall_score(y_test, y_pred))) # 0.77
# predict_proba : class ๋น probability ๋ฐํ
y_pred_proba = lr_clf.predict_proba(X_test)
print(y_pred_proba[:,1][:5]) # [0.12602436 0.17691062 0.2077208 0.10091478 0.10701443]
# predict๋ 0.5๋ฅผ threshold๋ก ํ์์ ํ์ธํ ์ ์๋ ์ฝ๋
sum((y_pred_proba[:, 1] > 0.5) == y_test)/len(y_test) # predict์ accuracy๊ฐ๊ณผ ๋์ผ
sum((y_pred_proba[:, 1] > 0.5) == y_test) # ๋ช๊ฐ๋ฅผ ๋ง์ท๋์ง ๊ฐ์ ํ์ธ
# threshold = 0.5 -> ๋ณดํต ๊ธฐ๋ณธ์ ์ผ๋ก ์ด ๊ฐ์ด ์ง์ ๋จ
threshold = 0.5
y_pred_proba = lr_clf.predict_proba(X_test)
y_pred_proba_1 = y_pred_proba[:, 1] > threshold
sum(y_pred_proba_1 == y_test) / len(y_test)
# threshold = 0.4
threshold = 0.4
y_pred_1 = y_pred_proba_1 > threshold
# threshold ๊ฐ์์, accuracy : ๊ฐ์, precision : ๊ฐ์, recall : ์ฆ๊ฐ
print("threshold๊ฐ {}์ผ ๋ 1 ๋ก ๋ถ๋ฅ๋ ๊ฐฏ์: ".format(threshold), sum(y_pred_1))
print("precision = {:.2f}".format(precision_score(y_test, y_pred_1)))
print("recall = {:.2f}".format(recall_score(y_test, y_pred_1)))
print("f1 score = ", f1_score(y_test, y_pred_1))
# threshold = 0.6
threshold = 0.6
y_pred_2 = y_pred_proba_1 > threshold
# threshold ์ฆ๊ฐ์, accuracy : ๊ฐ์, precision : ์ฆ๊ฐ, recall : ๊ฐ์
print("threshold๊ฐ {}์ผ ๋ 1 ๋ก ๋ถ๋ฅ๋ ๊ฐฏ์: ".format(threshold), sum(y_pred_2))
print("precision = {:.2f}".format(precision_score(y_test, y_pred_2))
print("recall = {:.2f}".format(recall_score(y_test, y_pred_2)))
print("f1 score = ", f1_score(y_test, y_pred_2))
04. ํ๊ฐ
# ํผ๋ํ๋ ฌ
cm = confusion_matrix(y_test, y_pred, labels=[1, 0])
ax = sns.heatmap(cm, annot=True, fmt='d')
ax.set_ylabel('true') # ๊ฐ๋ก ์ธ๋ก ์ฃผ์
ax.set_xlabel('predicted')
ax.set_title('Confusion Matirx')
# Roc curve
y_proba = lr_classifier.predict_proba(X_test)
y_scores = y_proba[:,1] # ์ ์ฒด ํ๋ฅ ์ ๋ํด 1์ผ ํ๋ฅ
# _ ์ฌ์ฉํด์ค์ผํจ
fpr, tpr, _ = roc_curve(y_test, y_scores) # false positive rate : fpr, true positive rate : tpr
auc = roc_auc_score(y_test, y_scores)
plt.plot(fpr, tpr, label="auc="+ "{:.2f}".format(auc))
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('ROC Curve')
plt.legend()
Ensemble Learning (์์๋ธ ํ์ต)
์์๋ธ ํ์ต ์ด๋ ?
: ๋ค์์ ์ฝํ ํ์ต๊ธฐ๋ฅผ ์กฐํฉ ํ์ฌ ๋ ๋์ ์ฑ๋ฅ์ ์ถ์ถํด๋
์์๋ธ ํ์ต ๋ฐฉ๋ฒ
01. Bagging (๋ฐฐ๊น ) (Bootstrap Aggregating)
(1) ๋ฐฐ๊น ์ด๋? : ๋ณต์ ์ถ์ถ์ ํตํด ์ฌ๋ฌ ๋ชจ๋ธ์ ๊ฒฐํฉํ์ฌ ๋จ์ผ ๋ชจ๋ธ๋ณด๋ค ๋ ๋์ ์ฑ๋ฅ์ ๋ด๋ ๊ฒ
(2) ๋ถ๋ฅ๊ธฐ ํ๋ จ๋ฐฉ๋ฒ : ํธ๋ ์ด๋ ์ํ์ subset์ ๋ฌด์์ ์ถ์ถ ํ, ๋ถ๋ฅ๊ธฐ ํ๋ จ
(3) ํจ๊ณผ : ํธํฅ(๋ชจ๋ธ ๋ณต์ก๋)์ด ์ปค์ง์ง ์์ผ๋ฉด์ ๋ถ์ฐ์ ์ค์ผ ์ ์์
→ ์ด์ : ๋๋ค ์ํ๋ง์ ์ํ ๋ชจ๋ธ fit
(4) Bootstrap (๋ณต์ ์ถ์ถ) : ์ํ์ ์ถ์ถํ๋๋ฐ, ์ด์ ์ ์ถ์ถ๋ ์ํ์ ๋ค์ ๋ฝํ ์ ์๋๋ก ํ๋ ์ถ์ถ ๋ฐฉ๋ฒ
→ ๋น๋ณต์ ์ถ์ถ : ์ค๋ณต ๋๋๊ฒ ์๋๋ก ์ํ ์ถ์ถ
→ ํจ๊ณผ
- variance = $\frac{๐ ^2}{b}$์ผ๋ก ๊ฐ์
- Mean = ๋์ผ
(5) Bagging tree ์๊ณ ๋ฆฌ์ฆ
- training data ์์ random sampling ํ์ฌ X_b, y_b ๋ฅผ ๊ณ ๋ฆ (ex. 1,000 ๊ฐ์ data ์ค 100 ๊ฐ sampling)
- X_b, y_b ๋ฅผ ์ด์ฉํ์ฌ ID3 ์๊ณ ๋ฆฌ์ฆ์ผ๋ก decision tree ๊ตฌ์ฑ
- B ๊ฐ์ tree ๊ฐ ๋ง๋ค์ด์ง ๋๊น์ง 1, 2 ๋ฐ๋ณต
- B ๊ฐ์ ๋ชจ๋ tree ๋ฅผ ์ด์ฉํ์ฌ classification ํ ํ majority vote ๋ก ๊ฒฐ์
- Bias ๋ฅผ ์ ์งํ๋ฉฐ Variance ๋ฅผ ์ค์ธ๋ค.
(6) ๋๋ค ํฌ๋ ์คํธ
- ๋ฌธ์ ์ : ๋ช ๊ฐ์ ํธ๋ฆฌ๋ฅผ ๋ง๋ค๋ ์ฒซ ๋ฒ์งธ ๋ ธ๋์๋ ๊ฐ์ ์ด์ด ์ฌ์ฉ๋ ๊ฒ์ ⇒ ๋๋ฌด๊ฐ ๋ค ๋น์ทํ ๊ฒ, ์ผ๋ฐํ ๋ฅ๋ ฅ์ ๋์์ด ๋์ง ์์
- ํด๊ฒฐ ๋ฐฉ๋ฒ : Decision Tree ์ ํฌํจ๋ attribute ๋ค์ random ํ๊ฒ ์ผ๋ถ๋ง ์ ์
โ ๋ชจ๋ attribute ๋ฅผ ๊ฐ์ง๊ณ Tree ๋ฅผ ๋ง๋ค ๊ฒฝ์ฐ ๋งค์ฐ ๊ฐํ attribute ๊ฐ ๋ชจ๋ tree ์ ํญ์ ํฌํจ๋จ - ์ฅ์
- ๋ Random ํ๊ณ ๋ ๋ฆฝ์ ์ธ classifier ์์ฑ๊ฐ๋ฅ
- ๋ค์ํ ๋ค๋ฅธ ํน์ฑ์ ๋๋ฌด๋ค์ด ์์ฑ๋๋ฏ๋ก ์ด ๊ฒฐ๊ณผ๋ฅผ voting ํด์ ์ต์ข ์ ๋ด๋ฉด ์ข์ ์ฑ๋ฅ์ ๋
- Tree-based model ์ด๋ฏ๋ก white box ํน์ง์ ์ ์ง
- High prediction accuracy
- ๋ณ๋ ฌ์ ์ผ๋ก ์์ฑ ๊ฐ๋ฅํ๋ฏ๋ก ์๋๊ฐ ๋น ๋ฆ
- ๊ฐ tree ๋ ๋งค์ฐ deep ํ๊ฒ ์์ฑ
02. Boosting
(1) ๋ถ์คํ ๋ฐฉ๋ฒ 2๊ฐ์ง
- ์๋ชป ๋ถ๋ฅ๋ ๋ฐ์ดํฐ์ ๋ ๋์ ๊ฐ์ค์น๋ฅผ ๋ถ์ฌํ์ฌ ๋ค์ ๋ชจ๋ธ์ ์ํ๋ง์ ํฌํจ๋ ํ๋ฅ ์ ๋์ด๋ ๋ฐฉ๋ฒ
- ๋ชจ๋ธ ์์ฒด๋ฅผ ๋ถ์คํ : ๋ค์์ ์ฝํ ํ์ต๊ธฐ๋ฅผ ํ๋ จ์์ผ majority voting (→ ๋ฐฐ๊น ๊ณผ ๋์ผํ ๋ฐฉ๋ฒ)
(2) ๋ํ์ ์ธ ๋ฉ์๋ : AdaBoost, Gradient Boost (XGBoost)
(3) Gradient Boost (XGBoost)
- ๋ฐฉ๋ฒ : weak learner๋ฅผ ์ด์ฉํ ๋ชจ๋ธ ๋ถ์คํ
- Weak Learner (์ฝํ ํ์ต๊ธฐ) : ๋๋คํ๊ฒ ์ ํํ๋ ๊ฒ ๋ณด๋ค ์ฝ๊ฐ ๋ ๋์ ์ฑ๋ฅ์ ๋ชจ๋ธ
⇒ ์์ฌ๊ฒฐ์ ๋๋ฌด๋ฅผ ์ฌ์ฉํ์์ - ๊ธฐ์กด์ weak learner ๊ฐ ์์ฑํ ์์ฐจ๋ฅผ ๊ฐ์์ํค๋ ์ถ๊ฐ tree ๋ฅผ ๊ฐ์ ํจ๊ณผ๊ฐ ์์ ๋๊น์ง ์์ฑ
- ์ด์ ์์ฌ๊ฒฐ์ ๋๋ฌด๋ก ๋ถํฐ ์์ฑ๋ ์์ฐจ๋ฅผ ๋ค์ ์์ฌ๊ฒฐ์ ๋๋ฌด์ ์ฌ์ฉ๋๋ input์ ๋ ์ด๋ธ๋ก ์ฌ์ฉ
- ์ฒซ๋ฒ์งธ ๋๋ฌด : ์์ฐจ ์์ฑ / ์ดํ์ ๋๋ฌด : ์ผ๋ง์ ์์ฐจ๊ฐ ์์ฑ๋ ์ง, ์์ธกํ๋ ํ๋ จ
⇒ ๋๋ฌด๋ค์ output์ ์ ๋ถ ๋ํ๋ฉด y๊ฐ์ด ์ผ๋ง์ธ์ง ์ ์ ์์
⇒ ๋๋ฌด๊ฐ ์์ฑ๋ ์๋ก ์์ฐจ = 0 ์ด ๋จ
- Weak Learner (์ฝํ ํ์ต๊ธฐ) : ๋๋คํ๊ฒ ์ ํํ๋ ๊ฒ ๋ณด๋ค ์ฝ๊ฐ ๋ ๋์ ์ฑ๋ฅ์ ๋ชจ๋ธ
- Optimization ๋ฐฉ๋ฒ : ๊ฒฝ์ฌํ๊ฐ๋ฒ์ ์ํ ์์ค ํจ์ optimize
(5) AdaBoost (Adaptive Boosting)
- ๋ฐฉ๋ฒ : ๋ฐ์ดํฐ๋ฅผ ๋ถ์คํ ํ๋ ๋ฐฉ๋ฒ
- ์ฒซ๋ฒ์งธ ์์ฑ๋๋ ๋ชจ๋ธ ⇒ Stump ( depth๊ฐ ๋ ๊ฐ์ธ ๋ถ์ ํํ ์ด์ง ๋ถ๋ฅ๊ธฐ )
์ด์ stump ์์ ์ ๋ชป ๋ถ๋ฅํ ๋ฐ์ดํฐ์ ๊ฐ์ค์น๋ฅผ ๋์ฌ, ๋ค์ sampling ์ ํฌํจ๋๋๋กํจ
⇒ ๋ชจ๋ธ๋ก ๋ถํฐ ๋ถ๋ฅ๋ ๊ฐ๋ค์ combinedํด์ ์ต์ข ๋ถ๋ฅ ๊ฒฐ๊ณผ๋ฅผ ๋
๋๋คํฌ๋ ์คํธ & gradient boosting ์ค์ต
๋ฐ์ดํฐ ์๊ฐ
- ์นผ๋ผ : ์ฌ์ฉ์ id, ์ฑ๋ณ, ์ฐ๋ น, ์ถ์ ๊ธ์ฌ, ๊ตฌ๋งค์ฌ๋ถ
- ์์ธก : ํน์ ์ฌ์ฉ์๊ฐ ๊ตฌ๋งค ํ ์ง ์ฌ๋ถ → ๊ตฌ๋งค: 1, ๊ตฌ๋งค ์์: 0
| User ID | Gender | Age | EstimatedSalary |
| 15706071 | Male | 51 | 23000 |
| 15654296 | Female | 50 | 20000 |
| 15755018 | Male | 36 | 33000 |
| 15594041 | Female | 49 | 36000 |
1. ๋ณ์ ์ค์
X = df.iloc[:, [2,3]].values.astype("float32") # age, estimatedSalary
y = df.iloc[:, 4].values.astype("float32") # purchased
# train, test split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)
X_train.shape, X_test.shape, y_train.shape, y_test.shape
2. feature scaling
# Feature Scaling
sc = StandardScaler()
X_train = sc.fit_transform(X_train)
X_test = sc.transform(X_test)
3. Random Forest model
# fit
# 10๊ฐ ๋๋ฌด ๋ง๋ค์ด์ ํ๋ ๋ฐฐ๊น
rf = RandomForestClassifier(n_estimators=10, random_state=0)
rf.fit(X_train, y_train)
# predict
y_pred = rf.predict(X_test)
# accuracy
accuracy_score(y_test,y_pred)
print("accuracy = {:.2f}".format(sum(y_pred == y_test) / len(y_test)))
# confusion matrix
print("confution matrix\\n",
confusion_matrix(y_test, y_pred, labels=[1, 0]))
# f1 score
print("f1 score\\n", f1_score(y_test, y_pred, labels=[1, 0]))
5. Gradient Boosting Classifier
- min_samples_split : node ๋ถ๋ฆฌ์ ํ์ํ ์ต์ sample ์ => overfitting ๋ฐฉ์ง
- max_depth : tree ๊น์ด ์กฐ์ => overfitting ๋ฐฉ์ง
- learning_rate : ๊ฐ tree ์ ๊ธฐ์ฌ๋ ์กฐ์ , n_estimators ์ trade-off
- n_estimators : number of sequential trees
from sklearn.ensemble import GradientBoostingClassifier
# ๋ชจ๋ธ
# ์์ฐจ๋ฅผ ๊ณ์ ์ด์ด์, ์์ ํธ๋ฆฌ๊ฐ ๋ง๋ ์ค๋ฅ๋ฅผ ๋ค์ ํธ๋ฆฌ๊ฐ ์ค๋ฅ๋ฅผ ์์ธกํ๋ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ ๋๋ฌด๋ฅผ ๋ง์ด ์์ฑํด์ผํจ -> 500
# ๋ถ์ ํํ ๋๋ฌด๋ค์ด ๊ณ์ ์ด์ด์ ธ์ ์์ ์์ฐจ๋ฅผ ์์ธกํ๋ ๋ชจ๋ธ์ด๋ฏ๋ก max_depth๋ฅผ ์๊ฒ
gb = GradientBoostingClassifier(learning_rate=0.1, n_estimators=500, max_depth=5)
# fit
gb.fit(X_train, y_train)
# predict
y_pred = gb.predict(X_test)
# ๊ฒฐ๊ณผ ํ์ธ
print("Test set true counts = ", sum(y_test))
print("predicted true counts = ", sum(y_pred))
print("accuracy = {:.2f}".format(
sum(y_pred == y_test) / len(y_test)))
# ํผ๋ํ๋ ฌ
print("confution matrix\\n",
confusion_matrix(y_test, y_pred, labels=[1, 0]))
# f1 score
print("f1 score\\n", f1_score(y_test, y_pred, labels=[1, 0]))
6. ํ๋ จ ๊ฒฐ๊ณผ ์๊ฐํ
์๊ฐํ๋ฅผ ์ํ ๊ฐ์์ ๋ฐ์ดํฐ ์์ฑ
# ๊ฐ์์ ๋ฐ์ดํฐ ์์ฑ : ์ ์ฒด ๋ ์ฝ๋์ ๋ํด์ ์ต์ ์ต๋ ์ฌ์ฉ
x1_min, x1_max = X_test[:, 0].min() - 1, X_test[:, 0].max() + 1
x2_min, x2_max = X_test[:, 1].min() - 1, X_test[:, 1].max() + 1
# x1, x2๊ฐ ์๋ก ๊ต์ฐจ๋๋ ์ ๋ง๋ค ๋ฐ์ดํฐ๋ฅผ ์์ฑํด์ค -> meshgrid
X1, X2 = np.meshgrid(np.arange(x1_min, x1_max, 0.1),
np.arange(x2_min, x2_max, 0.1))
X1.shape, X2.shape # (60, 61) / (60, 61)
# X1, X2๋ฅผ 1์ฐจ์์ผ๋ก ํผ์ณ์ค์ ๊ฐ ์ถ์ ๊ฐ์ ๋ง๋ฌ
XX = np.column_stack([X1.ravel(), X2.ravel()])
XX.shape # (3360,2)๋งํผ์ ๊ฐ์๋ฐ์ดํฐ๊ฐ ์์ฑ๋จ
๊ฐ์์ ๋ฐ์ดํฐ๋ก ๋ชจ๋ธ ์์ธก
# random forest๋ก ์์ธกํ ๊ฐ
Y_rf = np.array(rf.predict(XX))
# gradient boost๋ก ์์ธกํ ๊ฐ
Y_gb = np.array(gb.predict(XX))
์๊ฐํ
# ๋๊ฐ์ง ์ ๋ง๋ฌ
from matplotlib.colors import ListedColormap
cmap_light = ListedColormap(['#FFAAAA', '#AAFFAA']) # ์ฐํ ๊ฐ
cmap_bold = ListedColormap(['#FF0000', '#00FF00']) # ์งํ ๊ฐ
# ์๊ฐํ
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(10, 4), sharey=True)
# Random Forest ์๊ฐํ
# ๊ฒฐ์ ๊ฒฝ๊ณ ์์ฑ
ax1.pcolormesh(X1, X2, Y_rf.reshape(X1.shape),cmap=cmap_light, shading='auto')
# y_test๊ฐ 0์ผ๋, 1์ผ๋ ๋๋ ์ ๋ฐ์ดํฐ๋ฅผ ์ ์ผ๋ก ํํ -> ์์ ๋ค๋ฅด๊ฒ ๊ทธ๋ฆฌ๋๋ก ํจ
for i in range(2):
ax1.scatter(X_test[y_test == i, 0], X_test[y_test == i, 1], s=20, color=cmap_bold(i), label=i, edgecolor='k')
ax1.set_title('Random Forest')
ax1.set_xlabel('Age')
ax1.set_ylabel('Estimated Salary')
ax1.legend()
# Gradient Boosting ์๊ฐํ
ax2.pcolormesh(X1, X2, Y_gb.reshape(X1.shape), cmap=cmap_light, shading='auto')
for i in range(2):
ax2.scatter(X_test[y_test == i, 0], X_test[y_test == i, 1], s=20, color=cmap_bold(i), label=i, edgecolor='k')
ax2.set_title('Gradient Boosting')
ax2.set_xlabel('Age')
ax2.legend()
plt.tight_layout()

# Age, EstimatedSalary ์ ์ค์๋
feature_imp = pd.Series(gb.feature_importances_,
['Age', 'EstimatedSalary']).sort_values(ascending=False)
feature_imp.plot(kind='bar', title='feature importance')ใด

Feature Engineering
์ข์ ํผ์ฒ์ ์กฐ๊ฑด
- Target ๊ณผ์ ๋์ ๊ด๋ จ์ฑ
- prediction ์์ ์ ์ ์ ์์
- ์ ์ค์๋ ์ ์ ์๊ณ , ์๋ง์๋ง ์ ์ ์๋ ๋ฐ์ดํฐ๋ค → ex. sales data ๋ ์ต์์ ์ง๊ณ
- ์์ง ๋ฐ์ํ์ง๋ ์์ ๋ฐ์ดํฐ๋ก ํ๋ จํ๊ฒ ๋๋ ์ํฉ
- numeric
- ์ถฉ๋ถํ ๋ฐ์ดํฐ ์
- ์ธ๊ฐ ์ ๋ฌธ๊ฐ์ ๋๋ฉ์ธ ์ง์ ํ์ฉ ๊ฐ๋ฅ : ๊ด์ ์ ์ฐจ์ด๊ฐ ๋ค๋ฅผ ์ ์์
- Example ) ๊ตํต ์ ๋ณด ๋ฐ์ดํฐ : ๋ฐ์ ์์
- → ์์ผ๋ณ๋ก ๋๋๋๊ฒ ์ข์ ๊ฑฐ์ผ! ๋ผ๋ ์ง์์ด ์์ ๊ฒฝ์ฐ, ์์ธก์ ๋์์ด ๋ ์๋ ์์
๋จธ์ ๋ฌ๋์ ์ํ ํผ์ฒ ์์ง๋์ด๋ง
- ๊ฒฐ์ธก์น ์ฒ๋ฆฌ
- Data formatting : ๋ฐ์ดํฐ ํต์ผ
- ํธํฅ ์ฒ๋ฆฌ
- Normalization (= feature scaling) : scale์ด ๋ค๋ฅผ ๋, ๋น์ทํ ์ค์ผ์ผ๋ก ํด์ฃผ๋๊ฒ ์์ธก์ด ๋ ์๋จ
- Binning : ์ฐ์๋ ์ซ์๋ฅผ ์ด๋ ํ ๊ธฐ์ค์ผ๋ก ๊ทธ๋ฃนํ ํ๊ธฐ ์ํด ๋ฒ์๋ฅผ ์ ํด์ฃผ๋ ๊ฒ
- Categorical ๋ณ์ → ์์นํ์ผ๋ก
- ordinal category (์์/ํฌ๊ธฐ๊ฐ ์๋ feature)
- ์ซ์๋ก ํฌ๊ธฐ(์์) ํ์
- ex) L > M > S → 3, 2, 1
- nominal category (์์/ํฌ๊ธฐ๊ฐ ์๋ feature)
- ์ด๋ฐ ๊ฒฝ์ฐ๊ฐ ํจ์ฌ ๋ง์
- ๋ฐฉ๋ฒ : one-hot encoding
- ordinal category (์์/ํฌ๊ธฐ๊ฐ ์๋ feature)
Feature engineering & ๋๋คํฌ๋ ์คํธ ์ค์ต
์ฌ์ฉ๋ฐ์ดํฐ : ํ์ดํ๋ ๋ฐ์ดํฐ → ํ์ดํ๋ํธ์ ์์กด ์ฌ๋ถ ๋ฐ์ดํฐ
01. ๋ฐ์ดํฐ ํ์ธ
# ํ์์๋ ์นผ๋ผ drop
df.drop(['PassengerId', 'Name', 'Cabin', 'Ticket'], axis=1, inplace=True)
# ๋ฐ์ดํฐ ํ์ธ
df_titanic.info()
df_titanic.isnull().sum()
df_titanic.describe()
02. Feature Analysis
→ feature ๊ฐ์ correlation check / Survived ์ ๊ฐ Feature ๊ฐ ์๊ด๊ด๊ณ ํ์
# ๊ฐ ํผ์ฒ๋ค๊ฐ์ ๊ด๊ณ๊ฐ ์ผ๋ง๋
# ์์ : ์ญ์ ์๊ด๊ด๊ณ, 0 : ๊ฑฐ์ ๊ด๊ณ ์์, ์์ : ์์ ์๊ด๊ด๊ณ
# cov ๋ผ๋ ๊ณต๋ถ์ฐ์ -1, 1 ์ฌ์ด๋ก ์ ๊ทํ ์ํจ ๊ฒ
df_titanic.corr(numeric_only=True)
# ์๊ด๊ด๊ณ ์๊ฐํ
g = sns.heatmap(df_titanic.corr(numeric_only=True), annot=True, cmap="coolwarm")

03. ๊ฒฐ์ธก์น ์ฒ๋ฆฌ
# Age -> median์ผ ์ฒ๋ฆฌ : ์์ ๊ธฐ์ ๋๋ฌด ๋ง๊ธฐ ๋๋ฌธ
df_titanic['Age'].fillna(df_titanic['Age'].median(), inplace=True)
# Embarked -> ์ผ๋ง ์์ด์ ์ญ์
df_titanic.dropna(inplace=True)
04. ํธํฅ ํ์ธ
# ํ์คํ ๊ทธ๋จ์ ์ด์ฉํด ๋ถํฌ๋ฅผ ํ์ธํด ํธํฅ ํ์ธ
df_titanic.hist(bins=30, figsize=(8, 8));

⇒ ๊ฒฐ๊ณผ : Fare๊ฐ ์ฐ์๋ ์ซ์๊ฐ์ธ๋ฐ ์ฌํ๊ฒ ์น์ฐ์นจ ⇒ log๊ฐ์ผ๋ก ๋ฐ๊ฟ
(log๋ก ํ๋ ์ด์ : ๊ฐ์ด๋ฐ ์ชฝ์ผ๋ก ์ซ์๊ฐ ๋ชฐ๋ฆฌ๊ฒ ํด์ค / ์์ ๊ฐ์ ์ปค์ง๊ฒ, ํฐ๊ฐ์ ์๊ฒ ํด์ฃผ๋๋ฐ ๋์๊ด๊ณ๋ ๋ฐ๋์ง ์์)
05. ํธํฅ ์ฒ๋ฆฌ
# ๋ก๊ทธ๋ก ๋ฐ๊ฟ
df_titanic['Fare'] = df_titanic['Fare'].map(lambda x: np.log(x) if x > 0 else 0)
# ๋ค์ ํ์ธ
df_titanic.hist(bins=30, figsize=(8, 8));
06. ์นดํ ๊ณ ๋ฆฌ ๋ณ์ → ์์นํ ๋ณ์
# ์ํซ ์ธ์ฝ๋ฉ : ์นดํ
๊ณ ๋ฆฌ์ปฌ์ธ ์นผ๋ผ์ ์๋์ผ๋ก ๊ณจ๋ผ์ ๋ฐ๊ฟ์ค
df_titanic = pd.get_dummies(df_titanic)
| Survived | Pclass | Age | SibSp | Parch | Fare | Sex_female | Sex_male | Embarked_C | Embarked_Q | Embarked_S |
| 0 | 3 | 22.0 | 1 | 0 | 1.981001 | False | True | False | False | True |
| 1 | 1 | 38.0 | 1 | 0 | 4.266662 | True | False | True | False | False |
| 1 | 3 | 26.0 | 0 | 0 | 2.070022 | True | False | False | False | True |
| 1 | 1 | 35.0 | 1 | 0 | 3.972177 | True | False | False | False | True |
| 0 | 3 | 35.0 | 0 | 0 | 2.085672 | False | True | False | False | True |
07. ๋ฐ์ดํฐ ๋ถํ / ์ค์ผ์ผ๋ง
# train, test split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)
X_train.shape, X_test.shape, y_train.shape, y_test.shape # 711,10 / 178,10 / 711, / 178,
# standart scaling
sc = StandardScaler()
X_train_scaled = sc.fit_transform(X_train)
X_test_scaled = sc.transform(X_test)
08. ๋ชจ๋ธ๋ง ๋ฐ ํ๊ฐ : ๋๋คํฌ๋ ์คํธ
from sklearn.ensemble import RandomForestClassifier
# ๋ชจ๋ธ ์์ฑ
rf = RandomForestClassifier(n_estimators=10, criterion='entropy', random_state=0)
# fit
rf.fit(X_train_scaled, y_train)
# ์์ธก : predict
y_pred = rf.predict(X_test_scaled)
# ์ ํ๋
print("accuracy = {:.2f}".format(sum(y_pred == y_test) / len(y_test))) #0.85