In [1]:
Copied!
import pandas as pd
df = pd.read_csv("../../data/WineQT.csv")
df
import pandas as pd
df = pd.read_csv("../../data/WineQT.csv")
df
Out[1]:
| fixed acidity | volatile acidity | citric acid | residual sugar | chlorides | free sulfur dioxide | total sulfur dioxide | density | pH | sulphates | alcohol | quality | Id | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 7.4 | 0.700 | 0.00 | 1.9 | 0.076 | 11.0 | 34.0 | 0.99780 | 3.51 | 0.56 | 9.4 | 5 | 0 |
| 1 | 7.8 | 0.880 | 0.00 | 2.6 | 0.098 | 25.0 | 67.0 | 0.99680 | 3.20 | 0.68 | 9.8 | 5 | 1 |
| 2 | 7.8 | 0.760 | 0.04 | 2.3 | 0.092 | 15.0 | 54.0 | 0.99700 | 3.26 | 0.65 | 9.8 | 5 | 2 |
| 3 | 11.2 | 0.280 | 0.56 | 1.9 | 0.075 | 17.0 | 60.0 | 0.99800 | 3.16 | 0.58 | 9.8 | 6 | 3 |
| 4 | 7.4 | 0.700 | 0.00 | 1.9 | 0.076 | 11.0 | 34.0 | 0.99780 | 3.51 | 0.56 | 9.4 | 5 | 4 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 1138 | 6.3 | 0.510 | 0.13 | 2.3 | 0.076 | 29.0 | 40.0 | 0.99574 | 3.42 | 0.75 | 11.0 | 6 | 1592 |
| 1139 | 6.8 | 0.620 | 0.08 | 1.9 | 0.068 | 28.0 | 38.0 | 0.99651 | 3.42 | 0.82 | 9.5 | 6 | 1593 |
| 1140 | 6.2 | 0.600 | 0.08 | 2.0 | 0.090 | 32.0 | 44.0 | 0.99490 | 3.45 | 0.58 | 10.5 | 5 | 1594 |
| 1141 | 5.9 | 0.550 | 0.10 | 2.2 | 0.062 | 39.0 | 51.0 | 0.99512 | 3.52 | 0.76 | 11.2 | 6 | 1595 |
| 1142 | 5.9 | 0.645 | 0.12 | 2.0 | 0.075 | 32.0 | 44.0 | 0.99547 | 3.57 | 0.71 | 10.2 | 5 | 1597 |
1143 rows × 13 columns
In [18]:
Copied!
df.describe()
df.describe()
Out[18]:
| fixed acidity | volatile acidity | citric acid | residual sugar | chlorides | free sulfur dioxide | total sulfur dioxide | density | pH | sulphates | alcohol | quality | Id | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| count | 1143.000000 | 1143.000000 | 1143.000000 | 1143.000000 | 1143.000000 | 1143.000000 | 1143.000000 | 1143.000000 | 1143.000000 | 1143.000000 | 1143.000000 | 1143.000000 | 1143.000000 |
| mean | 8.311111 | 0.531339 | 0.268364 | 2.532152 | 0.086933 | 15.615486 | 45.914698 | 0.996730 | 3.311015 | 0.657708 | 10.442111 | 5.657043 | 804.969379 |
| std | 1.747595 | 0.179633 | 0.196686 | 1.355917 | 0.047267 | 10.250486 | 32.782130 | 0.001925 | 0.156664 | 0.170399 | 1.082196 | 0.805824 | 463.997116 |
| min | 4.600000 | 0.120000 | 0.000000 | 0.900000 | 0.012000 | 1.000000 | 6.000000 | 0.990070 | 2.740000 | 0.330000 | 8.400000 | 3.000000 | 0.000000 |
| 25% | 7.100000 | 0.392500 | 0.090000 | 1.900000 | 0.070000 | 7.000000 | 21.000000 | 0.995570 | 3.205000 | 0.550000 | 9.500000 | 5.000000 | 411.000000 |
| 50% | 7.900000 | 0.520000 | 0.250000 | 2.200000 | 0.079000 | 13.000000 | 37.000000 | 0.996680 | 3.310000 | 0.620000 | 10.200000 | 6.000000 | 794.000000 |
| 75% | 9.100000 | 0.640000 | 0.420000 | 2.600000 | 0.090000 | 21.000000 | 61.000000 | 0.997845 | 3.400000 | 0.730000 | 11.100000 | 6.000000 | 1209.500000 |
| max | 15.900000 | 1.580000 | 1.000000 | 15.500000 | 0.611000 | 68.000000 | 289.000000 | 1.003690 | 4.010000 | 2.000000 | 14.900000 | 8.000000 | 1597.000000 |
In [25]:
Copied!
# X / Y Split
Y = df['quality']
X = df.drop(['quality','Id'], axis=1)
from sklearn.model_selection import train_test_split
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size = 0.3)
# 모델 import
from sklearn.tree import DecisionTreeClassifier
# 모델 생성
dt = DecisionTreeClassifier(max_depth=4)
dt.fit(X_train, Y_train)
dt
# X / Y Split
Y = df['quality']
X = df.drop(['quality','Id'], axis=1)
from sklearn.model_selection import train_test_split
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size = 0.3)
# 모델 import
from sklearn.tree import DecisionTreeClassifier
# 모델 생성
dt = DecisionTreeClassifier(max_depth=4)
dt.fit(X_train, Y_train)
dt
Out[25]:
DecisionTreeClassifier(max_depth=4)In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
DecisionTreeClassifier(max_depth=4)
In [27]:
Copied!
import matplotlib.pyplot as plt
from sklearn.tree import plot_tree
plot_tree(dt, feature_names=X.columns, filled=True, fontsize=5)
plt.title("Decision Tree")
plt.show()
import matplotlib.pyplot as plt
from sklearn.tree import plot_tree
plot_tree(dt, feature_names=X.columns, filled=True, fontsize=5)
plt.title("Decision Tree")
plt.show()
4. 평가하기¶
- 얼마나 맞췄는지 수치화하기
In [33]:
Copied!
Y_pred = dt.predict(X_test)
Y_pred
Y_pred = dt.predict(X_test)
Y_pred
Out[33]:
array([5, 6, 6, 5, 6, 5, 6, 7, 5, 5, 5, 6, 6, 6, 5, 6, 5, 5, 7, 5, 5, 7,
5, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 6, 6, 5, 7, 6, 7, 5, 6, 6, 6, 5,
6, 6, 6, 5, 5, 6, 5, 6, 5, 7, 5, 7, 6, 6, 5, 6, 5, 5, 5, 5, 5, 5,
6, 5, 7, 5, 5, 5, 6, 5, 6, 5, 5, 6, 6, 5, 6, 6, 6, 5, 5, 6, 6, 6,
5, 6, 5, 6, 6, 5, 6, 7, 5, 6, 5, 5, 6, 5, 5, 5, 6, 6, 5, 6, 5, 5,
6, 7, 5, 6, 5, 6, 6, 5, 5, 6, 5, 6, 5, 5, 6, 5, 5, 6, 6, 6, 5, 7,
5, 6, 5, 6, 5, 5, 7, 5, 6, 5, 6, 5, 5, 5, 5, 6, 5, 6, 6, 6, 6, 5,
5, 5, 7, 6, 6, 7, 5, 5, 7, 6, 5, 5, 5, 7, 6, 6, 7, 7, 6, 5, 6, 6,
5, 5, 7, 6, 5, 5, 6, 7, 6, 5, 6, 5, 5, 5, 5, 7, 5, 5, 5, 5, 5, 7,
5, 6, 5, 5, 5, 6, 7, 5, 5, 6, 5, 6, 5, 5, 6, 5, 7, 5, 5, 5, 6, 5,
6, 5, 7, 6, 6, 5, 7, 5, 7, 5, 5, 5, 5, 7, 6, 6, 5, 5, 6, 6, 5, 5,
6, 6, 5, 5, 5, 7, 5, 7, 5, 6, 6, 5, 5, 7, 6, 5, 5, 5, 5, 6, 5, 5,
5, 5, 7, 5, 5, 7, 7, 5, 6, 5, 6, 6, 5, 5, 7, 5, 6, 5, 5, 5, 5, 5,
6, 5, 5, 5, 5, 7, 5, 5, 5, 5, 7, 6, 7, 7, 5, 5, 6, 5, 7, 5, 6, 5,
5, 5, 7, 5, 5, 5, 7, 5, 5, 7, 5, 5, 5, 6, 5, 6, 5, 7, 7, 6, 5, 6,
5, 7, 6, 6, 7, 6, 6, 5, 7, 5, 7, 6, 6])
In [28]:
Copied!
# 모델 평가지표 출력
from sklearn.metrics import classification_report
print(classification_report(Y_test,Y_pred))
# 모델 평가지표 출력
from sklearn.metrics import classification_report
print(classification_report(Y_test,Y_pred))
precision recall f1-score support
3 0.00 0.00 0.00 1
4 0.00 0.00 0.00 9
5 0.62 0.80 0.70 138
6 0.59 0.48 0.53 146
7 0.39 0.41 0.40 46
8 0.00 0.00 0.00 3
accuracy 0.58 343
macro avg 0.27 0.28 0.27 343
weighted avg 0.56 0.58 0.56 343
/Users/jonhpark/workspace/courses_archive/mkdocs_venv/lib/python3.12/site-packages/sklearn/metrics/_classification.py:1565: UndefinedMetricWarning: Precision is ill-defined and being set to 0.0 in labels with no predicted samples. Use `zero_division` parameter to control this behavior.
_warn_prf(average, modifier, f"{metric.capitalize()} is", len(result))
/Users/jonhpark/workspace/courses_archive/mkdocs_venv/lib/python3.12/site-packages/sklearn/metrics/_classification.py:1565: UndefinedMetricWarning: Precision is ill-defined and being set to 0.0 in labels with no predicted samples. Use `zero_division` parameter to control this behavior.
_warn_prf(average, modifier, f"{metric.capitalize()} is", len(result))
/Users/jonhpark/workspace/courses_archive/mkdocs_venv/lib/python3.12/site-packages/sklearn/metrics/_classification.py:1565: UndefinedMetricWarning: Precision is ill-defined and being set to 0.0 in labels with no predicted samples. Use `zero_division` parameter to control this behavior.
_warn_prf(average, modifier, f"{metric.capitalize()} is", len(result))
결과 해석!¶
- precision (정밀도):
• 모델이 특정 클래스로 예측한 것 중 실제로 맞은 비율.
• 예를 들어, 클래스 5에서 0.62는 모델이 클래스 5로 예측한 것 중 62%가 실제로 클래스 5였다는 뜻. - recall (재현율):
• 실제로 특정 클래스인 것 중에서 모델이 맞게 예측한 비율.
• 클래스 5에서 0.80은 실제 클래스 5인 데이터 중 80%를 맞췄다는 의미. - f1-score:
• 정밀도와 재현율의 조화 평균으로, 모델의 전체적인 성능을 나타냄.
• 클래스 5에서 0.70은 해당 클래스에서 정밀도와 재현율의 균형이 적절하다는 뜻. - support:
• 각 클래스에 속하는 실제 데이터의 개수.
• 예를 들어, 클래스 5의 support 값 138은 실제로 클래스 5인 데이터가 138개라는 것을 의미.
각 클래스별 성능 해석
- 클래스 3, 4, 8:
• 정밀도, 재현율, f1-score가 모두 0. 이는 모델이 해당 클래스에 대해 전혀 올바르게 예측하지 못했다는 뜻.
• support가 낮아서 데이터가 부족했을 가능성이 높음. - 클래스 5:
• 정밀도(0.62), 재현율(0.80), f1-score(0.70) 모두 높음. 모델이 이 클래스에서는 비교적 잘 작동함. - 클래스 6:
• 정밀도(0.59), 재현율(0.48), f1-score(0.53). 성능이 중간 정도. - 클래스 7:
• 정밀도(0.39), 재현율(0.41), f1-score(0.40). 성능이 낮음.
전체 성능
- accuracy (정확도):
• 전체 데이터 중 모델이 맞춘 비율. 58%로, 모델의 성능이 보통 수준임. - macro avg (매크로 평균):
• 모든 클래스의 정밀도, 재현율, f1-score의 단순 평균.
• 클래스 간 데이터 불균형이 심한 경우 낮을 수 있음. 여기서는 각각 약 0.27 정도로 낮음. - weighted avg (가중 평균):
• 각 클래스의 support(데이터 개수)를 반영하여 계산된 평균.
• 여기서는 accuracy와 비슷한 0.56~0.58 수준으로 나타남.
In [ ]:
Copied!
5. 다른 모델 사용하기 - Random Forest¶
- Decesion Tree 들의 앙상블 (Ensemble)!
마치 집단 지성처럼, 여러가지의 decistion tree 가 선택한 결과들을 토대로 최종 대답을 도출함
In [38]:
Copied!
# 모델 import
from sklearn.ensemble import RandomForestClassifier
# 모델 생성
rfr = RandomForestClassifier( max_depth=10, n_estimators = 100)
# 모델 학습
rfr.fit(X_train, Y_train)
# 모델 import
from sklearn.ensemble import RandomForestClassifier
# 모델 생성
rfr = RandomForestClassifier( max_depth=10, n_estimators = 100)
# 모델 학습
rfr.fit(X_train, Y_train)
Out[38]:
RandomForestClassifier(max_depth=10)In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
RandomForestClassifier(max_depth=10)
In [39]:
Copied!
Y_pred = rfr.predict(X_test)
print(classification_report(Y_test,Y_pred))
Y_pred = rfr.predict(X_test)
print(classification_report(Y_test,Y_pred))
precision recall f1-score support
3 0.00 0.00 0.00 1
4 0.00 0.00 0.00 9
5 0.69 0.79 0.74 138
6 0.63 0.68 0.66 146
7 0.62 0.39 0.48 46
8 0.00 0.00 0.00 3
accuracy 0.66 343
macro avg 0.32 0.31 0.31 343
weighted avg 0.63 0.66 0.64 343
/Users/jonhpark/workspace/courses_archive/mkdocs_venv/lib/python3.12/site-packages/sklearn/metrics/_classification.py:1565: UndefinedMetricWarning: Precision is ill-defined and being set to 0.0 in labels with no predicted samples. Use `zero_division` parameter to control this behavior.
_warn_prf(average, modifier, f"{metric.capitalize()} is", len(result))
/Users/jonhpark/workspace/courses_archive/mkdocs_venv/lib/python3.12/site-packages/sklearn/metrics/_classification.py:1565: UndefinedMetricWarning: Precision is ill-defined and being set to 0.0 in labels with no predicted samples. Use `zero_division` parameter to control this behavior.
_warn_prf(average, modifier, f"{metric.capitalize()} is", len(result))
/Users/jonhpark/workspace/courses_archive/mkdocs_venv/lib/python3.12/site-packages/sklearn/metrics/_classification.py:1565: UndefinedMetricWarning: Precision is ill-defined and being set to 0.0 in labels with no predicted samples. Use `zero_division` parameter to control this behavior.
_warn_prf(average, modifier, f"{metric.capitalize()} is", len(result))


