이번 글에서는 머신러닝의 기본 개념을 알아보고, 주로 사용되는 머신러닝 기술, 이를 이용한 실습을 해보겠습니다.
먼저, 머신러닝이랑 인공지능의 하위 분야입니다. 명시적인 프로그램이 없어도 컴퓨터가 학습 할 수 있는 능력을 주는 방법이라고 할 수 있겠네요. 컴퓨터가 직접 데이터를 학습해 특징들을 추출하고 알고리즘을 연구하거나 구축한다는 개념이라고 알면 되겠습니다.
머신러닝의 카테고리로는 크게 교사(supervised)학습, 비교사(unsupervised)학습으로 나눠집니다. 교사학습이란 학습하는 데이터의 정확한 클래스를 알고 있을 때 학습하는 것을 말합니다. 비교사학습은 눈치 채셨겠지만, 학습 데이터의 클래스가 알려져 있지 않을 때 학습하는 것을 뜻합니다. 이외에 반교사학습, 강화학습등도 있습니다.
머신러닝 기술의 적용분야는 분류(classification), 군집(clustering), 회귀(regression)이 있습니다.
먼저 분류란, 미리 정의된 카테고리로 데이터를 분류합니다. 데이터로는 텍스트, 이미지 등이 있죠. 분류의 가장 대중적인 알고리즘은 나이브 베이즈(Naive bayes)분류기가 있습니다. 학습데이터를 각각 확률을 계산해서 카테고리를 만들어 분류를 시키고 학습을 하여 정의된 카테고리에 해당할 확률을 구합니다.
다음으로 군집이란 서로 더 비슷한 개체 집합을 동일한 그룹으로 그룹화 하는 작업입니다. 이렇게 그룹화된 것을 군집이라고 하는 것입니다. 예를 들어, 1반과 2반으로 구성된 학교라고 한다면 1반과 2반 또는 남자 여자 이러한 카테고리로 군집화 할 수 있겠네요. 가장 대중적인 알고리즘으로는 k-means군집과 계층적 군집이 있습니다.
마지막으로 회귀란 하나의 변수 평균값과 다른 변수의 해당 값 간의 관계를 측정한 것이라 할 수 있습니다. 즉, 변수간의 관계를 추정하기 위한 통계적인 방법이죠. 회귀를 하는 이유는 학습데이터를 통해 결과값을 예측하기 위함입니다. 주식시장을 예측하는 것 또한 회귀라고 볼 수 있습니다. 가장 대중적인 회귀는 로지스틱 회귀가 있습니다.
머신러닝은 결과적으로 예측을 하기 위해 훈련을 시키는 것입니다. 그래서 데이터를 통해 훈련시키고 테스트를 해봄으로써 성능을 평가합니다. 이때에 데이터 셋을 구성해야 합니다. 데이터 셋의 구성은 Training set, Validation set, Test set으로 나뉩니다. Training set은 말 그대로 모델 훈련에 사용하느 데이터 셋입니다. Validation set은 모델 훈련에 적절한 지점을 찾기 위해 사용하는 데이터 셋으로 과적합(over fitting), 또는 과소적합(under fitting)을 방지하기 위한 stopping point를 찾습니다. 마지막으로 test set은 모델의 성능을 평가하기 위해 사용하는 데이터 셋입니다.
데이터 셋을 어떻게 구분하는지에 대한 방법들도 있습니다. Holdout, Random subsampling, k fold Cross validation, Stratified sampling, Bootstrap이 있습니다.
Holdout은 데이터 셋을 train set, test set 두 셋으로 나누는 방법입니다. train set, test set의 일정 비율을 설정하게 됩니다. 만약 train set이 작으면 모델 정확도의 분산이 커지게 되고, train set이 커지면 test set으로부터 측정한 정확도의 신뢰도가 하락하게 됩니다. 이와 같은 단점을 극복하기 위해 나온 것이 Random subsampling 방법입니다.
Random subsampling은 Holdout을 반복적으로 실행하는 방법입니다. 먼저 k개의 부분 데이터 셋을 사용하게 되는데 각 부분 데이터 셋은 랜덤하게 정해집니다. 최종성능은 각 실험 성능의 평균으로 도출하게 됩니다.
k fold Cross validation은 data set을 k개의 fold로 나누어 사용하는 방식인데요. K번의 실험을 진행하며, k-1개fold는 training set, 1개 fold는 test set으로 사용하게 됩니다. Random subsampling과 유사하지만, k-fold cross validation을 사용할 경우 모든 데이터를 train과 test에 적용할 수 있습니다. 최종성능은 k번의 실험성능의 평균으로 도출하게 됩니다.
Stratified sampling은 데이터를 클래스에 따라 각 그룹으로 분리 후, 각 그룹으로부터 일정 비율의 샘플을 무작위 로 추출하는 방법입니다. 전체 데이터에서 무작위로 샘플을 추출할 경우 표본이 특정 클래스에 편중될 수 있다는 단점도 존재합니다. 이러한 단점을 보완하기 위해서 이 방법을 통해 샘플의 대표성을 높이는 것입니다.
마지막으로 Bootstrap 방법입니다. Bootstrap 방법은 샘플 추출 시각 데이터의 중복 추출을 허용합니다. 전체데이터에서 n개의 샘플을 추출 하는데, 다음 시도에서 기존에 추출했던 샘플이 다시 추출될 수 있으며, 중복을 허용한 추출이 반복적으로 시행되게 됩니다. 역시 최종 성능은 실행된 실험 성능들의 평균으로 도출됩니다.
이러한 방법들로 훈련을 시키고 테스트를 했다면 이렇게 나온 결과들의 성능을 평가해야합니다. 이때에 쓰이는 개념들을 소개하겠습니다. 바로 Confusion matrix, Accracy, Precision, Recall, F-measure, ROC curve, RMSE가 있습니다.
먼저 Confusion matrix란 모델이 예측한 데이터의 카테고리가 실제와 같은지를 보여주는 일종의 표입니다. 총 4가지로 구분지어집니다.
TP(True Positive): 실제 yes 카테고리의 데이터 중 모델이 yes 카테고리로 예측한 데이터의 건수
FN(False Negative): 실제 yes 카테고리의 데이터 중 모델이 no 카테고리로 예측한 데이터의 건수
FP(False Positive): 실제 no 카테고리의 데이터 중 모델이 yes 카테고리로 예측한 데이터의 건수
TN (True Negative): 실제 no 카테고리의 데이터 중 모델이 no 카테고리로 예측한 데이터의 건수
이러한 건수들을 활용해 성능을 알아 볼 수 있습니다.
그 다음, Accuracy(정확도)는 모델이 정확하게 분류 또는 예측하는 데이터의 비율입니다. 하지만 정확도가 높다고 꼭 좋다고는 할 수 없는 상황도 있습니다. 바로 정확도의 단점인데요. 예를 들어 2 class 문제에서 class yes에 해당하는 데이터는 9900건, class no에 해당하는 데이터는 100건이 존재할 경우, 모델이 모든 데이터를 class yes로 예측할 경우에도 즉, class no를 예측하지 못했음에도 불구하고 accuracy는9900/10000=99%가 되게 됩니다. 이러한 경우가 있어서 정확도가 곧 모델의 성능이다 라고 말하긴 어렵습니다.
Precision(정밀도)이란 모델이 검출한 데이터 중 올바르게 검출된 데이터의 비율입니다. Recall(재현율)이란 실제 해당 데이터 중 모델이 올바르게 검출한 데이터의 비율입니다. 모델의 성능을 측정할 때 precision과 recall의 균형을 유지해야 합니다.
F-measure은 precision과 recall은 모델의 성능을 객관적으로 판단하기에 부족합니다. 두 수치의 trade-off 관계를 통합해 하나의 수치로 정확도를 도출하는 방법입니다.
ROC 커브(Receiver Operating Characteristic)란 Y축에 TP, X축에 FP수치를 입력해 두 수치의 균형을 살펴볼 수 있는 커브입니다. 먼저 ROC를 이해하기 위해서 TPR(True Positive Rate), FPR(False Positive Rate)을 알아야 합니다. TPR이란 실제 yes클래스 데이터 중 모델이 예측한 yes클래스 데이터의 비율을 뜻 합니다. 민감도라고도 말하며 recall과 같은 개념이라고 이해하면 되겠습니다. 모델이 yes클래스를 정확하게 예측할수록 값이 높아집니다. FPR이란 실제 no클래스 데이터 중 모델이 yes클래스로 예측한 데이터의 비율입니다.
ROC 커브의 아래 면적을 AUC(Area Under Curve)라고 하는데 이것의 면적이 1에 가까워질수록 모델이 yes클래스를 예측하는 정확도가 높습니다.
RMSE를 이해하기전에 먼저 이해해야 할 개념이 있습니다. 바로 잔차(residuals)입니다. 회귀 분석 모델의 예측 값과 실제 값의 차이, 즉 오차를 잔차라고 부르는데요. 이 잔차를 이용한 개념이 MSE(Mean squared error)입니다. 평균제곱오차라고도 하는데요, 회귀선과 모델 예측값 사이의 잔차를 사용합니다. 잔차를 제곱한 값들의 평균입니다. 이 MSE에 루트를 적용한 값이 RMSE입니다. RMSE는 예측값의 오차정도를 통해서 결과값이 유의미한지를 나타내는 지표 정도로 이해하시면 될 것 같습니다. 이외에도 RMSE의 단점들을 보완하기 위한 MAPE, MASE등이 있지만 지금은 다루지 않도록 하겠습니다.
□실습
이제 Scikit learn에서 제공하는 toy data를 이용하여 실습을 해보겠습니다. Scikit learn에서 제공하는 위스콘신의 유방암 데이터 셋을 이용할 건데요. 이 데이터는 총 596건의 데이터로 악성(real, 0, 212건), 양성(positive, 1, 357건) 두 개의 클래스로 이루어져 있습니다.
from sklearn import datasets
from sklearn.tree import DecisionTreeClassifier
먼저 scikit learn에서 제공하는 dataset들을 불러오고 decision tree 머신러닝 모델을 사용하기위한 모듈도 불러옵니다. decisiontree에 대해서는 뒤에 또 다루도록 하겠습니다.
from sklearn.model_selection import train_test_split
from sklearn.model_selection import StratifiedKFold
from sklearn.model_selection import cross_val_score
그 다음, 데이터 셋을 train과 test로 나누기 위한 모듈과 stratified k fold cross validation을 사용하기 위한 모듈을 불러옵니다. 그냥 kfold모듈과는 다르게 각 fold내 데이터의 클래스 비율을 일정하게 유지해줍니다. 그리고 결과의 정확도를 측정하기 위한 모듈도 불러옵니다.
from sklearn.metrics import confusion_matrix
from sklearn.metrics import accuracy_score
from sklearn.metrics import classification_report
from sklearn.metrics import roc_auc_score
from sklearn.metrics import mean_squared_error
그리고 confusionmatrix를 추출하기 위한 모듈, 정확도, recall, precosion, f-measure를 측정하기 위한 모듈, roc곡선의 아래 넓이를 구하기 위한 모듈, MSE를 구하기 위한 모듈들을 불러옵니다.
data = datasets.load_breast_cancer()
X = data.data
y = data.target
데이터 셋에서 load_breast_cancer함수를 사용하여 유방암 데이터를 가져와 변수 data에 저장하고, 속성 데이터를 변수x, 클래스 데이터를 변수 y에 저장합니다.
Holdout시작¶
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
이제 train_test_split 함수를 사용해 train set과 test set을 분리하는데 저는 전체 데이터 중 test set을 20%로 설정하겠습니다.
clf = DecisionTreeClassifier()
clf.fit(X_train, y_train)
clf
머신러닝을 사용하기 위해 불러왔던 deicisiontreeclassifier모델을 변수 clf에 할당하고, train데이터와 fit 함수를 사용해 모델을 훈련시킵니다.
y_pred = clf.predict(X_test)
Predict 함수를 사용해 test 데이터(X_test)에 대한 예측값을 구하고 변수 y_pred에 저장합니다.
print('Confusion Matrix')
print(confusion_matrix(y_test, y_pred))
test 데이터의 실제 값인 y_test와 예측 결과값 y_pred를 confusion_matrix 함수에 입력해 matrix를 출력합니다. 결과를 보시면 실제 총114건 중 yes와 no를 맞게 예측한 값이 105건인 것을 확인할 수 있습니다.
print('Accuracy')
print(accuracy_score(y_test, y_pred, normalize=True))
y_test와 y_pred 값을 비교해 정확도를 출력하합니다. normalize를 false로 하게 되면 올바르게 분류된 데이터 건수를 출력하고, true로 하면 비율을 출력합니다.
print('Classification Report')
print(classification_report(y_test, y_pred))
classification_report 함수를 사용해 각 클래스(0과 1)에 대한 precision과 recall, f-measure, 데이터 건수를 출력합니다. 클래스 0과 1은 유방암에 결렸다, 걸리지 않았다의 구분에 따라 나눠진 클래스입니다. 총 114 건에 대해 92퍼 정도의 정확도를 보여줍니다.
print('AUC')
print(roc_auc_score(y_test, y_pred))
ROC 곡선의 아래 면적도 출력해 보겠습니다. 1에 가까울 수록 정확도가 높은 모델이라고 했는데 0.92정도면 아주 높은 수치라고 볼 수 있습니다.
print('Mean Squared Error')
print(mean_squared_error(y_test, y_pred))
MSE의 결과도 보겠습니다.
k fold cross validation¶
skf = StratifiedKFold(n_splits=10)
skf.get_n_splits(X, y)
print(skf)
이번엔 StratifiedKFold 모듈을 사용해 10 cross validation 모듈을 skf로 생성했습니다. k fold corss validation에 대해서는 앞서 설명했듯, 총 k 번의 실험을 진행하는 것인데 저는 그 횟수를 10번으로 지정한 것입니다. 여기에 Stratified sampling 샘플을 추출할때에 한 개의 클래스에 편중되지 않도록 하는 것입니다.
for train_index, test_index in skf.split(X, y) :
print('Train set: ', train_index[0])
print('Test set: ', test_index[0])
10번의 실험을 위한 데이터 셋 구성을 살펴봅니다. 저는 편의를 위해 첫번째만 프린트해 보았는데 저 부분을 제외한 모든 값을 보시면 이해가 빠르실 것입니다.
clf = DecisionTreeClassifier()
scores = cross_val_score(clf, X, y, cv=skf)
print('K Fold Cross Validation Score')
print(scores)
print("Average Accuracy")
print(scores.mean())
마찬가지로 decisiontree를 이용하여 모델을 생성하고 정확도를 출력하여 10개 결과의 평균을 내보겠습니다. 약 0.92정도의 정확도를 보여주는 것을 알 수 있습니다.
k fold cross validation - shuffle¶
skf_sh = StratifiedKFold(n_splits=10, shuffle=True)
skf_sh.get_n_splits(X, y)
print(skf_sh)
이번엔 위의 과정과 동일하지만 shuffle을 이용하여 데이터를 섞은 후 데이터 셋을 구성하게 하여 동일한 테스트를 진행해 보겠습니다.
for train_index, test_index in skf_sh.split(X, y) :
print('Train set: ', train_index[0])
print('Test set: ', test_index[0])
전체 결과를 확인해보시면 shuffle전과 index가 섞여 있는 것을 확인해 보실 수 있습니다.
clf = DecisionTreeClassifier()
scores = cross_val_score(clf, X, y, cv=skf_sh)
print('K Fold Cross Validation Score')
print(scores)
print("Average Accuracy")
print(scores.mean())
shuffle을 하니까 정확도가 오른 것을 확인해 볼 수 있습니다. 이렇게 해서 머신러닝에 대한 기초적인 내용들을 다뤄봤습니다. 관련된 내용들은 추가로 올리도록 하겠습니다. :)
'데이터분석 및 프로젝트' 카테고리의 다른 글
Folium 지도에 heatmap을 이용하여 빈도수를 표현해보자 :) (0) | 2020.01.19 |
---|---|
수열을 통해 마코프 체인의 단서를 얻어보자 :) (0) | 2020.01.15 |
위도 경도 값을 이용하여 거리를 구하고 그래프를 그려보자 :) (0) | 2020.01.15 |
LZW 알고리즘과 허프만 부호화 방법을 서로 비교하여 분석해보자. (0) | 2020.01.08 |
기사를 크롤링하여 워드클라우드를 만들어보자. (0) | 2020.01.08 |