ML&DL_sklearn공부(2). Iris Data를 이용한 학습과 평가
데이터 불러오기.
from sklearm.dataset import load_iris
data = load_iris()
- 여기서 load_iris는 데이터 및 데이터의 설명을 담은 딕셔너리를 반환.
- dictionary를 아래의 코드를 통해 확인해볼 수 있다.
전처리 및 EDA
np.unique(data.target, return_counts = True)
# unique한 데이터를 반환해주고, return_counts를 설정해주면 갯수도 반환해준다.
print(data.target_names) #['setosa' 'versicolor' 'virginica']
print(data.target_names.shape, data.target_names[data.target].shape) # (3,) (150,)
# 열이름, 타겟값 수정
iris.columns = ['sl', 'sw', 'pl', 'pw']
iris['Species'] = data.target_names[data.target]
# => data.target_names를 data.target의 개수 즉 150번만큼 색인해준다는 것을 의미. 타겟값을 수정.
iris.head()

결측값 있는지 확인해주기.
- 결측값이 있다면 처리를 해주어야 함.
- 결측값 제거: dropna
- 결측값 대체: fillna, interpolate
iris.isna().sum() # 결측값 몇개냐?
기초통계 분석
- iris.describe() : 통계정보 알려줌.
- iris.info() : Dataframe의 기본정보 확인.
- iris.groupby('Species').size() : 종류별로 개수 알려줌.
- iris.Species.value_counts() : 종류별로 개수 알려줌.
데이터 시각화
기초 통계량 및 이상치 시각화(boxplot)
def boxplot_iris(feature_names, dataset):
i = 1
plt.figure(figsize = (11, 9))
for col in feature_names:
plt.subplot(2, 2, i)
plt.axis('on')
plt.tick_params((axis = 'both', left = True, top = False,
right = False, bottom = True, labelleft = False,
labeltop = False, labelright = False, labelbottom = False)
dataset[col].plot(kind = 'box', subplots = True, sharex = False, sharey = False)
plt.title(col)
i += 1
plt.show()
boxplot_iris(iris.columns[:-1], iris)
만약에 상대적인 위치를 보고 싶으면 sharex와 sharey를 True로 해줄 것.
fig, axes = plt.subplots(2, 2, figsize = (11, 9), sharex = True, sharey = True)
axes = axes.ravel() # np.ravel()은 1차원 배열로 만들어준다.
for i, ax in enumerate(axes):
iris.iloc[:, i].plot(kind = 'box', ax = ax)
ax.set_title(iris.columns[i])
plt.show()

데이터 분포 시각화(histogram)
def histogram_iris(feature_names, dataset):
i = 1
plt.figure(figsize = (11, 9))
for col in feature_names:
plt.subplot(2, 2, i)
plt.axis('on')
plt.tick_params(axis = 'both', left = True, top = False,
right = False, bottom = False, labelleft = False,
labeltop = False, labelright = False, labelbottom = False)
dataset[col].plot(kind = 'hist', subplots = True, sharex = False, sharey = False)
plt.title(col)
i += 1
plt.show()
histogram_iris(iris.columns[:-1], iris)
상관관계 시각화(heatmap)
correlationship matrix를 생성해줌.
corr = iris.corr() cmap = sns.diverging_palette(220, 19, as_cmap = True) plt.figure(figsize=(11,9)) sns.heatmap(corr, cmap=cmap, vmax=1.0, vmin=-1.0, center=0, square=True, linewidths=.5, cbar_kws={'shrink':.5}) plt.show()
피처 간의 상관관계 및 데이터 분포 시각화(pairplot)
sns.pairplot(iris, hue = 'Species')
plt.show()
타겟의 클래스 비율(piechart)
타겟의 클래스 비율을 시각화해서 살펴본다.
def piechar_iris(feature_names, target, dataset): i = 1 plt.figure(figsize = (11, 9)) for colName in [target]: labels = []; sizes = [] df = dataset.groupby(colName).size() for key in df.keys(): labels.append(key) sizes.append(df[key]) plt.subplot(2, 2, i) plt.axis('on') plt.tick_params(axis = 'both', left = False, top = False, right = False, bottom = False, labelleft = True, labeltop = True, labelright = False, labelbottom = False) plt.pie(sizes, labels = labels, autopct = '%1.1f%%', shadow = True, startangle = 140) plt.axis('equal') i += 1 #plt.axis('equal') 은 동그란 표를 만들자는 뜻. plt.show() piechar_iris(iris.columns[:-1], iris.Species, iris)
Hold out
```python
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(iris.iloc[:, :-1], iris.iloc[:, -1], test_size = 0.33, random_state = 42)
```
- : sklearn의 train_test_split 함수로 훈련용 데이터셋과 성능평가용 데이터셋을 나눈다.
학습
train : 학습 파라미터를 학습시키는 용도
validation : 어떤 hyperparameter가 좋은지 튜닝과 평가
test : Best parameter로 학습시킨 모델을 평가하는 용도
모델생성🙊
\- 알고리즘 선택 : 이 예제에서는 **Decision Tree Classifier** 을 이용할 것이다.
`python from sklearn.tree import DecisionTreeClassifier model = DecisionTreeClassifier(random_state = 42)`
\- 모델학습
`python model.fit(X_train, y_train)`
\- score
`python model.score(X_test, y_test) # 0.98, iris 데이터는 굉장히 좋은 데이터라 어떻게 학습을 시켜도 높은 점수가 나온다.`
모델 일반화 전략 & Learning curve🙊
머신러닝이란 데이터에 의해서 모델의 성능이 결정되기 때문에 데이터가 충분히 많아야 한다. 데이터가 충분치 않은 경우, 특정 학습데이터에만 높은 성능을 가지는 과적합이 발생할 수 있기 때문에 모델을 일반화해주는 노력이 필요하다.
validation set
🔎 학습데이터셋에서도 일부를 hold out해서 validation set으로 활용해준다.cross vaildation(교차검증)
🔎 데이터셋을 k개만큼 나누어, 조각들을 돌아가면서 validation set으로 사용한다. 그 다음, k개의 성능 결과를 평균내서 모델의 성능을 추정한다.KFold
from sklearn.model_selection import cross_val_score, KFold cv = KFold(n_splits = 10, shuffle = True, random_state = 42) results = cross_val_score(model, X_train, y_train, cv = cv) fin_result = results.mean() for i, r in enumerate(results): print(f"{i}번째 교차 검증 정확도: {r}") print(f"\n교차검증 최종 정확도: {fin_result}")
Stratified KFold
: 한 validation set안에 꽃 3가지의 종류가 골고루 섞어준 후 성능을 평가한다.from sklearn.model_selection import cross_val_score, StratifiedKFold cv = StratifiedKFold(n_splits = 10, shuffle = True, random_state = 42) results = cross_val_score(model, X_train, y_train, cv = cv) fin_result = results.mean() for i, r in enumerate(results): print(f"{i}번째 교차 검증 정확도: {r}") print(f"\n교차검증 최종 정확도: {fin_result}")
Learning curve
교차검증 기법은 데이터의 양이 충분하지 않을 때 사용하는 기법인데, 이 때 데이터의 양이 충분한가에 대해서는 학습곡선을 그림으로써 판단할 수 있다.import scikitplot as skplt skplt.estimators.plot_learning_curve(model, X_train, y_train, figsize = (6,6)) plt.show() ``
모델 최적화 전략🙊
- 하이퍼파라미터 : scikit-learn에서는 알고리즘을 인스턴스화할 때 하이퍼파라미터를 설정할 수 있다.
- **GridSearchCV** 를 이용하여 하이퍼 파라미터 탐색
🔎 하이퍼 파라미터 조합에 대한 경우의 수를 모두 격자(grid)에 나열하고 모든 조합을 일일히 학습 및 성능 측정하는 기능이다.
🔎 estimator로는 알고리즘 인스턴스를 전달하고, param\_grid에너느 테스트할 하이퍼파라미터를 담은 **딕셔너리**를 전달한다.
from sklearn.model_selection import GridSearchCV
estimator = DecisionTreeClassifier()
params= {'max_depth':range(4, 13, 2),
'criterion':['gini', 'entropy'],
'splitter':['best', 'random'],
'min_weight_fraction_leaf':[0.0, 0.1, 0.2, 0.3],
'random_state':[7, 23, 42, 78, 142],
'min_impurity_decrease':[0., 0.05, 0.1, 0.2]}
model = GridSearchCV(estimator, params, cv=cv, verbose=1,
n_jobs = -1, refit=True) # validation set 10개 * 하이퍼파라미터 조합수 1600개 = 16000번
# refit : best parmaeter 학습결과를 best_estimator_ 속성에 기록해둔다.
model.fit(X_train, y_train)
print(f"Best Estimator: {model.best_estimator_}\n")
print(f"Best Params: {model.best_params_}\n")
print(f"Best Scorer: {model.best_score_}\n")
평가 지표 및 모델 평가
정확도만으로 모델을 평가/검증하는 것은 부족하기 때문에 다른 평가지표들도 알 필요가 있다.
Confusion Matrix
이진분류 : 예측을 할 때 두가지로 예측하는 경우 총 4가지의 경우가 나오게 된다.
다중분류 : 아이리스 데이터의 경우 꽃의 특징들(feature)들을 가지고 이 꽃이 setosa인지, versicolor인지, virginic인지 예측하게 된다. 이를 바탕으로 지표를 만들면 아래와 같이 된다.
아이리스 데이터셋의 confusiom matrix 코드
from sklearn.metrics import confusion_matrix pred = model.predict(X_test) confMatrix = confusin_matrix(y_test, pred) print('Confusion Matrix :\n : ', confMatrix)
scikit-plot을 이용하면 confusion matrix를 더 직관적인 heatmap으로 시각화할 수 있다.
skplt.metrics.plot_confusion_matrix(y_test, pred, figsize=(8,6))
plt.show()

Precision, Recall, Fall-out, F-score
- FP, FN, TP, TN : 앞은 예측을 맞췄는지 틀렸는지 / 뒤는 P라 예측했는지, N이라 예측했는지
- precision(정밀도)
- 예측한 클래스 중에 실제로 맞은 비율(비싼 신뢰성있는 진단기), 예를 들어 양성이라 예측한 것 중에서 실제 양성인 것의 비율.
- TP/TP+FP
- recall(재현율)(TPR)
- 실제 타겟 클래스 중에서 예측이 맞은 비율, 예를 들어 실제 양성의 개수 중에서 양성으로 예측한 것의 비율(효율적인 값싼 진단기)
- TP/TP+FN
- fall-out
- 타겟이 아닌 실제 클래스 중에서 틀린 비율.
- f-score
- 정밀도와 재현율은 trade-off관계이다.
- 정밀도와 재현율의 가중조화평균.
precs = []
rcls = []
specs = []
for i in range(3):
TP = confMatrix[i, i]
FN = confMatrix[i].sum() - TP
FP = confMatrix[:,i].sum() - TP
TN = confMatrix.sum() - TP - FN - FP
precs.append(TP/(TP+FP))
rcls.append(TP/(TP+FN))
specs.append(TN/(TN+FP))
precs = np.array(precs)
rcls = np.array(rcls)
specs = np.array(specs)
fall_outs = 1 - specs
print(precs)
print(rcls)
print(specs)
print(fall_outs)
ROC curve와 AUC
- ROC curve
- 얘는 TPR(True Positive Rate)를 y축, FPR(False Positive Rate)를 x축으로 하는 그래프이다.
- TPR은 recall이랑 같고, FPR은 fall-out과 같아서 FP/FP+TN(실제 negative인 표본개수)을 의미한다.
- 클래스 판별 기준값의 변화에 따를 재현율과 위양성율의 변화를 시각화 한 것.
skplt.metrics.plot_roc(y_test, pred_proba, figsize = (8,6))
plt.show()
- AUC
- ROC curve 밑의 면적을 계산. 거꾸로 기억자일수록 좋은 성능을 나타낸다.
최종 모델
최종모델학습
model.fit(iris.iloc[:, :-1], iris.iloc[:, -1]model.fit(iris.iloc[:, :-1], iris.iloc[:, -1]`)
모델저장
모델을 재사용 하기 위해서 모델을 저장해두자. pickle을 이용하면 모델 객체 자체를 저장할 수 있다.
import pickle
with open("final_model.pickle", "wb") as fp:
pickle.dump(model, fp)
모델 불러오기 및 예측
모델을 다시 불러올 때는 load 메서드를 이용하고 저장한 모델을 불러와서 예측값을 csv로 저장해보자.
f = open('new_model.pickle', 'rb')
model = pickle.load(f); f.close()
predicted_species = model.predict(iris.iloc[:, :-1])
iris['predicted_species'] = predicted_species #새로운 열을 만들어주기.
iris.to_csv('Final.csv', index = False)
'파이썬라이브러리&sklearn&keras' 카테고리의 다른 글
ML&DL_sklearn공부(1) << Decision Tree (0) | 2020.08.13 |
---|---|
딥러닝 >> Sequence Model과 Attention mechanism(deep learning.ai강의) (0) | 2020.07.23 |
학교 공부 >> dlib 설치 오류&해결 (0) | 2020.04.11 |
DataStructure::Segmentation fault 11 error (0) | 2019.04.24 |