728x90

분류

- 주어진 데이터가 어느 카테고리에 속하는지 판단하는 일

- 나이브 베이즈, 로지스틱 회귀, 결정 트리, SVM, 앙상블, 신경망, 최근접 등

- 영상, 음성 등 대용량 비정형 데이터 -> 딥러닝

- 정형 데이터 -> 머신러닝. 최근 앙상블 기법이 애용

 

 

앙상블

- 여러 알고리즘들의 활용(앙상블)

- 약 분류기들을 결합하여 상호 보완

- 배깅/부스팅

 

 

결정 트리 decision tree

- 데이터의 규칙을 트리 형태로 분할해 나가는 모델

- 장점 : 피처 스케일링이나 정규화 필요가 없음

- 단점 : 과적합으로 성능이 떨어짐. 트리 크기 제한 필요.

 

 

사이킷런의 결정트리

- CART Classification And Regression Tree 알고리즘 기반(ref : throwexception.tistory.com/1030?category=857655)

- DecisionTreeClassifier/Regressor 제공

- 다음 파라미터가 있음

 1. min_samples_split : 노드 분할을 위한 최소 샘플 데이터 수, 과적합 제어용. 작을수록 과적합 가능성 증가

 2. min_samples_leaf : 리프 노드가 되기위한 최소 샘플 데이터수. 과적합 제어용. 작을수록 좋음

 3. max_features : 최적 분할을 위해 다룰 최대 피터 갯수. 기본값 "None" 모든 피처 고려

 4. max_depth : 최대 깊이. 기본값 "None"는 완전 분할될때까지 분할 or 리프 노드 최소 샘플까지 분할

 

 

 

결정 트리 과적합 개선하기 

- min_samples_leaf : 리프 노드(말단 노드)가 되는 하한 데이터 갯수를 높이면 과적합 문제가 개선됨.

1. datasets 모듈의 make_classification 함수로 데이터 셋 생성

 - make_classification() : 분류를 위한 데이터 셋 생성 함수

from sklearn.tree import DecisionTreeClassifier
from sklearn.datasets import make_classification
import seaborn as sns
import matplotlib.pyplot as plt


X, y = make_classification(n_features=2, n_informative=2, n_redundant=0,
                          n_classes=3, n_clusters_per_class=1, random_state=0)


plt.scatter(X[:,0],X[:,1], c=y)

2. min_samples_leaf 디폴트(None) 인 상태에서의 성능

- 훈련용 데이터에는 100% 정확하나, 테스트 데이터는 85% 정확도를 보임

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)

df = DecisionTreeClassifier()
df.fit(X_train, y_train)

print("train_score : {} ".format(df.score(X_train, y_train)))
print("test_score : {} ".format(df.score(X_test, y_test)))

 

 

 

 

3. min_samples_leaf=6일때 성능

- 훈련 데이터 정확도는 떨어졋으나, 테스트 정확도는 90%로 증가함

df = DecisionTreeClassifier(min_samples_split=6)
df.fit(X_train, y_train)

print("train_score : {} ".format(df.score(X_train, y_train)))
print("test_score : {} ".format(df.score(X_test, y_test)))

 

 

4. GridSearchCV로 최적 하이퍼 파라미터 찾아보기

- 결정 트리 파라미터를 다음과 같이 다양하게 주었을때, 최적 분류기의 파라미터와 성능 보기

 => 훈련 점수는 0.8875로 떨어졋으나, 테스트 점수가 1.0으로 상승했다..?

 * max_depth=4, min_samples_leaf=1, min_samples_split=2 일때,

from sklearn.model_selection import GridSearchCV

param={
    "min_samples_leaf":[1, 2, 3, 4, 5, 6, 7, 8, 9],
    "max_depth":[2, 3, 4, 5, 6, None],
    "min_samples_split":[2, 3, 4, 5, 6, 7, 8, 9, 10]
}

df = DecisionTreeClassifier()
gs = GridSearchCV(df, param_grid=param, cv=5, refit=True)

gs.fit(X, y)

df = gs.best_estimator_
print("train_score : {} ".format(df.score(X_train, y_train)))
print("test_score : {} ".format(df.score(X_test, y_test)))
print(gs.best_score_)
print(gs.best_params_)

300x250
728x90

대표적인 분류 문제로 피마 인디언 당뇨병 여부를 예측(분류)를 해보자

 

링크는 www.kaggle.com/uciml/pima-indians-diabetes-database

 

 

잠깐 소개 문구를 읽어보면

 

당뇨병,  소화, 신장 질환 등을 연구하는 국립 연구소에서 얻은 데이터고

 

이 데이터셋으로 우리가 할일은 환자가 당뇨병을 가지고 있는지 예측하면 된다.

 

 

내용물은 여러개의 독립변수와 한개의 목표 변수(Outcome)

 

독립 변수는 환자의 임신 횟수, BMI, 인슐린, 나이 등이 있다고 한다.

 

 

 

우리가 할일은 뭐더라

 

일단 이 문제가 당뇨병 여부인지를 판단하는 것이므로 

 

분류 문제임을 알았다.

 

 

 

 

머신러닝 알고리즘을 활용하는 과정은

 

0. 데이터 훑어보기

1. 탐색적 데이터 분석

2. 전처리

3. 모델 학습

4. 성능 평가

 

정도로 분류할수 있을거 같구.

 

 

 

 

 

지금까지 학습한 내용들을 전부 활용해서 해보면

 

탐색적 데이터 분석에서는

 

시본으로 페어플롯이나 다양한 플롯들을 그리면서 분석할 예정

 

 

전처리 단계에서는 

 

결측치 처리, 라벨 인코딩, 열 드롭 등 할거고

 

 

모델 학습 단계에서는

 

분류기 모델들 설정,

 

gridsearchcv로 하이퍼 파라미터별 최적 추정기를 구하고자 한다.

 

 

 

성능 평가 단계에서는 조금전에 확인한

 

성능 평가지표들을 구하여 비교해보자

 

 

 

 

0. 빠르게 훑어보기

- 평소 하던데로 기본 라이브러리 임포트와 데이터 프레임 조회

- 기초 통계량, 데이터 형태 등을 확인해봄.

* 위 설명대로 당뇨병 여부인 목표변수 Outcome과 이를 설명하기 위한 Pregenancies, BMI, Insulin 등이 있다.

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns

df = pd.read_csv("res/pima/diabetes.csv")
df.info()

 

 

 

 

 

 

 

1. 탐색적 데이터 분석

- 데이터를 전처리 하기에 앞서 데이터간 의미를 한번 살펴보고자 한다.

- 우선 데이터나 변수도 많지 않고, 편하게 seaborn의 pairplot을 사용해보자.

* 사진이 잘 안보이므로 따로 다운로드 받아서 확대해서 보면 수월하다.

- 회귀 문제가 아니다 보니 출력 변수와 타 변수간의 상관관계를 알아보기가 힘들다.

sns.pairplot(df)

- 회귀 문제가 아니다 보니 출력 변수와 타 변수간의 상관관계를 알아는데는 pairplot은 좋지 않아보인다.

 

 

- 한번 임신 횟수에 대한 박스 플롯을 보자

 -> 평균 임신 횟수가 약 3회 정도가 되나 13회를 넘어가는 아웃라이어들이 존재한다.

 -> 한개의 박스 플롯으로 의미있는 정보를 보기 힘드니 여러개를 띄워보자

sns.boxplot(y="Pregnancies", data=df)

- 당뇨병 여부에 따른 임신 횟수를 살펴봣더니, 임신 횟수가 적을 수록 당뇨병 발병이 적은걸 알수 있다.

sns.boxplot(x="Outcome", y="Pregnancies", data=df)

- 나머지 변수들도 비슷한 결과를 보이고 있다.

- 나이대별 발병 여부는 어떨까?

 -> 젊은 층보다 중고령층인 경우 발병확률이 높음을 알 수 있다.

plt.figure(figsize=(12,6))
sns.barplot(x="Age", y="Outcome", data=df)

- 임신 횟수별  발병율을 바 플롯으로 본 결과. 횟수가 많을수록 유병율이 높은걸 확인할수 있다.

plt.figure(figsize=(12,6))
sns.barplot(x="Pregnancies", y="Outcome", data=df)

대강 탐색적 데이터 분석은 여기까지 하고

 

 

2. 전처리

이제 전처리 과정을 생각해보려고 한다.

 

전처리 과정에서 할일은 이렇게 정리할수 있을것같다.

 

1. 결측치 처리

2. 데이터 분할

3. 인코딩

4. 스케일링/정규화

5. 아웃라이어 처리

 

 

 

2. 1 우선 결측치 부터 처리하자

- 전처리 단계서 사용할 라이브러리 임포트

- 결측치를 확인해보니 존재하지 않는다.

from sklearn.preprocessing import LabelEncoder
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split

df.isnull().sum()

 

 

 

2.2 아웃라이어 처리

- 데이터프레임의 기초 통계량들을 보자

- 값 > 평균 + 3 * 표준편차들은 아웃라이어로 보고 좀 생각해보자

 

- 전체 768 행 데이터 중에서 아웃라이어들 갯수를 다 합쳐도 40개쯤 되는거 같다. 

 -> 이 아웃라이어가 존재하는 행들은 다 제거해주자.

cols = df.columns
print(df.shape)
for col in cols:
    mean = df[col].mean()
    std = df[col].std()
    threshold = mean + 3 * std
    n_outlier = np.sum(df[col] > threshold)
    print(col + ". num of outlier : "+str(n_outlier))

 

- 위 조건을 넘는 값을 아웃라이어로 판단하고, 제거하였다.

 -> 제거한 결과 768개 에서 727개로 줄어듦. 이제 스케일링 처리를 수행하자.

cols = df.columns
print("before drop outlier : {}".format(df.shape))
for col in cols:
    mean = df[col].mean()
    std = df[col].std()
    threshold = mean + 3 * std
    n_outlier = np.sum(df[col] > threshold)
    #print(df[df[col] > threshold])
    df.drop(df[df[col] > threshold].index[:], inplace=True)

df.dropna()
print("after drop outlier : {}".format(df.shape))

 

 

 

2.3 피처 스케일링

- 가우시안 커널을 사용하는 머신러닝 기법들은 특징들이 가우시안 분포를 따르는 경우 잘 동작된다고 한다.

- 모든 피쳐 데이터들을 표준화 시켜주기 위해 Standard Scaler를 사용해보자

 -> 모든 데이터들이 표준 정규분포를 따르는 값들로 변환이 되었다.

X = df.loc[:, df.columns != "Outcome"]
y = df.loc[:, df.columns == "Outcome"]
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)

print(X_scaled[:,:6])

 

 

 

 

 

 

3. 모델링 

 

 

결측치는 없고,

아웃라이어 제거했고,

스케일링도했고,

라벨링 할 값도 존재하지 않는다.

 

이제 전처리 과정은 끝났으니 모델 구성, 학습을 해보자

 

 

내가 사용할 분류기는

 

1. Logistic Regression

 

2. SVM

 

3. Decision Tree

 

4. Random Forest

 

이 내가지를 사용하고자 한다.

 

 

여기서 grid seacrh cv를 사용하고자 하는데 사용할 파라미터들을 정리해야한다.

 

다큐먼트를 참고하여 설정할 파라미터들

 

1. Logistic Regression

 -> penalty : "l1", "l2", "elasticnet", "none"   default "l2"

 

2. SVM.svc

 -> kernel{‘linear’, ‘poly’, ‘rbf’, ‘sigmoid’}, default=’rbf’

 

3. Decision Tree

4. Random Forest

 트리는 max_depth와 min_samples_split을 사용하자.

 

 

 

 

하이퍼 파라미터에 따른 각 분류기들별 최적 성능과 최적의 파라미터를 구한 결과

 

대부분 비슷비슷하나

 

로지스틱 회귀에서 0.7917로 가장 좋은 성능이 나왔다.

 

 

 

 

from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import GridSearchCV


def fit_clasifiers(gs_clfs, X, y):
    for clf in gs_clfs:
        print(X.shape)
        clf.fit(X, y)
    
def show_gridsearch_result(gs_clfs):
    estimators = []
    scores = []
    params = []
    for clf in gs_clfs:
        estimators.append(str(clf.estimator))
        scores.append(clf.best_score_)
        params.append(clf.best_params_)


    for i, val in enumerate(estimators):
        print(val)
        print(scores[i])
        print(params[i])
        
X_train, X_test, y_train, y_test = train_test_split(X_scaled, y, test_size=0.2)

lr = LogisticRegression()
svc = SVC(probability=True)
dt = DecisionTreeClassifier()
rf = RandomForestClassifier()

param_lr = {"penalty":["l1", "l2", "elasticnet", "none"]}
param_svc = {"kernel":["linear", "poly", "rbf", "sigmoid"]}
param_tree = {
    "max_depth" : [3, 4, 5, 6],
    "min_samples_split" : [2, 3]
}

gs_lr = GridSearchCV(lr, param_grid=param_lr, cv=5, refit=True)
gs_svc = GridSearchCV(svc, param_grid=param_svc, cv=5, refit=True)
gs_dt = GridSearchCV(dt, param_grid=param_tree, cv=5, refit=True)
gs_rf = GridSearchCV(rf, param_grid=param_tree, cv=5, refit=True)

gs_clfs = [gs_lr, gs_svc, gs_dt, gs_rf]
fit_clasifiers(gs_clfs, X_train, y_train)
show_gridsearch_result(gs_clfs)


 

 

 

 

 

5. 평가지표들 살펴보기

- l2 패널티를 준 로지스틱 회귀 모델에서

- 혼동 행렬, 정확도, 재현률, 정밀도, roc curve와 roc_auc score 등을 살펴보자

- 정확도는 77.39, 정밀도는 0.8이나 재현율이 0.56으로 크게 떨어지고 있다.

- 임계치 0.3 부근에서 교차하므로 이지점을 기준으로 분류가 필요해보인다.

 

from sklearn.metrics import accuracy_score, confusion_matrix, roc_auc_score
from sklearn.metrics import recall_score, precision_score,roc_curve
from sklearn.metrics import precision_recall_curve

def show_metrics(y_test, y_pred):
    confusion = confusion_matrix(y_test, y_pred)
    accuracy = accuracy_score(y_test, y_pred)
    precision = precision_score(y_test, y_pred)
    recall = recall_score(y_test, y_pred)
    print(confusion)
    print("Acc : {}".format(accuracy))
    print("precision : {}".format(precision))
    print("recall : {}".format(recall))

def show_precision_recall_curve(y_test,prob_positive_pred):
    precisions, recalls, thresholds = precision_recall_curve(y_test, prob_positive_pred)
    print("th val : {}".format(thresholds[:4]))
    print("precision val : {}".format(precisions[:4]))
    print("recalls val : {}".format(recalls[:4]))

    df = {
        "thresholds":thresholds, 
          "precisions":precisions[:-1], 
          "recalls":recalls[:-1]
    }
    df = pd.DataFrame.from_dict(df)

    sns.lineplot(x="thresholds", y="precisions", data=df)
    sns.lineplot(x="thresholds", y="recalls", data=df)

    


y_pred = gs_lr.predict(X_test)
pred_prob = gs_lr.predict_proba(X_test)
show_metrics(y_test, y_pred)
y_pred = np.concatenate([pred_prob, y_pred.reshape(-1, 1)], axis=1)
prob_positive_pred = y_pred[:, 1]

show_precision_recall_curve(y_test,prob_positive_pred)

 

- roc cuv

 -> roc_auc 값은 0.8188

 

 

def show_roc_curve(y_test,prob_positive_pred):
    fpr, tpr, thresholds = roc_curve(y_test,prob_positive_pred)

    print("fpr val : {}".format(fpr[:4]))
    print("tpr val : {}".format(tpr[:4]))
    print("thresholds val : {}".format(thresholds[:4]))

    df = {"threshold":thresholds, "fpr":fpr, "tpr":tpr}
    df = pd.DataFrame.from_dict(df)
    sns.lineplot(x="fpr", y="tpr", data=df)

    roc_score = roc_auc_score(y_test, prob_positive_pred)
    print(roc_score)

show_roc_curve(y_test,prob_positive_pred)

 

 

 

 

 

 

 

 

6. 수정

 

이 문제를 풀면서 이상하게

 

정확도가 떨어지는지 보니

 

아웃라이어 처리때 상한 아웃라이어만 처리하고

 

하한 아웃라이어들은 처리하지 않았더라

 

 

하한 아웃라이어의 값들을 살펴보았다.

 

 

6.1 하한 아웃라이어

 

- 하한 아웃라이어들은 대부분 0으로 나오길래, 실제 값이 0인 데이터들의 갯수를 확인하였다.

- 임신 여부는 0일수도 있으니 넘어가더라도 SkinThickness와 insulin의 0이 너무 많다고 나오고 있다.

   =>다른 열의 0행들은 제거하면 되지만, 많은 부분을 차지하는 행은 평균 값을 삽입해주자.

def show_lower_outlier(df, stdev=3, show_total=False):

    # lower bound outliers
    cols = df.columns
    print(df.shape)
    for col in cols:
        #std
        mean = df[col].mean()
        std = df[col].std()
        threshold = mean - stdev * std
        n_outlier = np.sum(df[col] < threshold)
        print(col + ". mean : "+str(round(mean,3))+", num of outlier : "+str(n_outlier))
        if (show_total == True) & (n_outlier != 0):
            print(df.loc[(df[col] < threshold),col][:5])
        
        print("   -> cnt of zero : " + str(np.sum(df[col] == 0))+"\n")

show_lower_outlier(df,show_total=True)

 

- 인슐린, 피부두께, 혈압에 평균을 대입

df.loc[ df.loc[:, "Insulin"] == 0 , "Insulin"] = df["Insulin"].mean()
df.loc[ df.loc[:, "SkinThickness"] == 0 , "SkinThickness"] = df["SkinThickness"].mean()
df.loc[ df.loc[:, "BloodPressure"] == 0 , "BloodPressure"] = df["SkinThickness"].mean()

show_lower_outlier(df,show_total=True)

 

 

- outcome을 제외한 타 컬럼들의 0값은 Nan으로 변환후 제거

 -> 768행에서 752행으로 줄었다.

 * 그냥 outcome을 진작에 떄놓고 할걸 ..  떗따 붙엿다 힘들다. 

print("before drop: "+ str(df.shape))

dfi = df.loc[:, (df.columns != "Outcome") & (df.columns != "Pregnancies")]
dfi[dfi[:] == 0] = np.NaN
dfi = dfi.dropna()
df.iloc[:,:-1] = dfi

show_lower_outlier(df,show_total=True)

 

 

 

 

 

 

너무 이문제에서 삽질 많이 했는데

 

 

매번 바뀌긴 하지만 결과를 정리하면

 

 

다음 전처리만 한 경우

- 상한 : 평균 + 3 * std 제거

=> acc : 0.753. , ROC AUC = 0.8119

전처리 추가시

- 하한 : 평균 - 3 * std제거,   일부 변수 0값 평균 대입, 0제거

=> ACC = 0.82119, ROC AUC = 0.8947

 

 

여러번 실행하면서 결과가 달라지다보니

 

하한 전처리를 추가했다고 항상 성능이 개선되지는 않았다.

 

 

300x250
728x90

머신러닝 성능 평가 지표

- confusion matrix 오차 행렬

- accuracy 정확도

- recall 재현률

- precision 정밀도

- f1 score

- roc auc

 

 

오차 행렬 confusion matrix

  True False
Positive TP FP
Negative TN TF

- TP : 예측기 긍정, 실제 긍정

- FP : 예측기 긍정, 실제 부정

- TN : 예측기 부정, 실제 부정

- FN : 예측기 부정, 실제 긍정

 => 예측기것을 먼저 보고, T이면 예측기와 실제가 동일/F이면 실제값이 예측기와 다름

 

정확도 accuracy

- (TP + TN)/전체

- 예측기가 실제 긍정 부정을 찾을 비율

 

재현율 recall

- 예측기가 없마나 실제 긍정에서 참긍정을 잘 재현하는가?

- 참긍정/(참긍정 + 거짓부정 ) => TP/(TP + FN)

- 민감도 sensitify, TPR tru Postiive Rate라고도 함.

- 실제 참을 부정으로 판단 시 중요 지표. -> 양성 환자를 음성으로 판단시 위험

 

 

정밀도

- 참긍정/(참긍정 + 거짓긍정) => TP/(TP + FP)

- 예측기가 참을 얼마나 정밀하게 구하는가

- 부정 데이터를 긍정으로 잘못 예측 시 큰 영향을 받는 경우 중요 지표 -> 스팸 메일을 긍정으로 판단시 지장

 

 

 

 

 

 

Confusion_matrix, accuracy, recall, precision 보기

- sklearn.metrics 모듈에서 confusion_matrix, accuracy_score, recall_score, precision_score 제공

- 아래와 같이 전처리 한 경우에 대한 성능 평가 지표들

from sklearn.metrics import precision_recall_curve
from sklearn.metrics import accuracy_score, precision_score, recall_score, confusion_matrix
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelEncoder

def get_categroy(age):
    cat = ""
    if age <= -1: cat = "Unknown"
    elif age <= 5: cat = "Baby"
    elif age <= 12: cat = "Child"
    elif age <= 18: cat = "Teenager"
    elif age <= 25: cat = "Student"
    elif age <= 35: cat = "Young Adult"
    elif age <= 60: cat = "Adult"
    else : cat = "Elderly"
    return cat

def feature_tf(df):
    enc_feature = ["Sex", "AgeGroup"]
    drop_feature = ["Name", "Embarked", "Ticket", "Cabin", "Age"]
    df["AgeGroup"] = df["Age"].apply(lambda x : get_categroy(x))
    df.drop(columns = drop_feature, inplace=True)
    for feature in enc_feature:
        enc = LabelEncoder()
        df[feature] = enc.fit_transform(df[feature])
    return df

def show_metrics(y_test, y_pred):
    confusion = confusion_matrix(y_test, y_pred)
    accuracy = accuracy_score(y_test, y_pred) 
    precision = precision_score(y_test, y_pred)
    recall = recall_score(y_test, y_pred)
    print(confusion)
    print("Acc : {}".format(accuracy))
    print("precision : {}".format(precision))
    print("recall : {}".format(recall))

df = pd.read_csv("res/titanic/train.csv")
X = df.iloc[:, df.columns != "Survived"]
y = df.iloc[:, df.columns == "Survived"]
feature_tf(X)

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)


lr = LogisticRegression()
lr.fit(X_train, y_train)
y_pred = lr.predict(X_test)
show_metrics(y_test, y_pred)

 

 

 

예측 레이블 확률 구하기 Estimator.predict_proba(X)

- 학습 완료된 추정기에 테스트 데이터를 주면, 해당 데이터에 대한 예측 확률 제공

- np.concatenate로 probability와 y_pred 값을 이은 결과는 아래와 같음

y_pred = lr.predict(X_test)
prob = lr.predict_proba(X_test)
res = np.concatenate([prob, y_pred.reshape(-1, 1)], axis=1)
res

 

 

분류기 임계치에 따른 정밀도, 재현율 변화 Classifier.precision_recall_curve(y_true, prob_positive_pred)

- 실제 값과 긍정 예측 확률이 주어질때 임계치별 정밀도와 재현율의 변화를 보여줌

- 반환 값 : 정밀도, 재현율, 임계치

 

prob_positive_pred = lr.predict_proba(X_test)[:, 1]

precisions, recalls, thresholds = precision_recall_curve(y_test, prob_positive_pred)

print("th val : {}".format(thresholds[:4]))
print("precision val : {}".format(precisions[:4]))
print("recalls val : {}".format(recalls[:4]))

 

 

시각화하기

- 세 변수들 -> dict -> df -> seaborn으로 시각화

- 임계치 0.4부근에서 정밀도와 재현률의 교차점이 존재

df = {"thresholds":thresholds, "precisions":precisions[:-1], "recalls":recalls[:-1]}
df = pd.DataFrame.from_dict(df)
sns.lineplot(x="thresholds", y="precisions", data=df)
sns.lineplot(x="thresholds", y="recalls", data=df)

 

 

 

 

F1 Score

- 정밀도와 재현율을 결합하여 만들어진 지표.

- 둘중 하나에 치우쳐지지 않아야 높은 값을 가짐.

 

ROC Curve (Receiver Operation Characteristic Curve)

- 통신 장비 성능 평가를 위해 고안됨,

-  X 축 : FPR(False Positive Rate), Y : TPR(True Positive Rate)

- TPR = TP/(TP + FN) 재현율, 민감도로 참 긍정/전체 참

- FPR : FP/(FP + TN) 거짓 긍정/전체 거짓

 

 

ROC Curve 모듈과 시각화

- from sklearn.metrics import roc_curve

- roc_curve(y_true, prob_pred_positive) -> FPR, TPR, thresholds

- 곡선은 1에 가까울수록 좋음. 

from sklearn.metrics import roc_curve

fpr, tpr, thresholds = roc_curve(y_test,prob_positive_pred)

print("fpr val : {}".format(fpr[:4]))
print("tpr val : {}".format(tpr[:4]))
print("thresholds val : {}".format(thresholds[:4]))

df = {"threshold":thresholds, "fpr":fpr, "tpr":tpr}
df = pd.DataFrame.from_dict(df)
sns.lineplot(x="fpr", y="tpr", data=df)

 

 

ROC AUC Score

- ROC 곡선의 AUC(Area under Curve).

- 곡선 아래의 넓이로 1에 가까울 수록 좋음. 

from sklearn.metrics import roc_auc_score
roc_score = roc_auc_score(y_test, prob_positive_pred)
print(roc_score)

 

 

300x250
728x90

타이타닉 생존자 예측에 있어서 할 일은 대강 다음으로 정리할수 있을것 같다.

- 전처리 

- 모델 선정

- 교차검증, 하이퍼 파라미터 조정

- 시각화

 

 

 

1. 라이브러리 임포트

- 대강 생각나는 라이브러리들

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.preprocessing import StandardScaler
from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import GridSearchCV
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier

 

2. 데이터 읽고 훑어보기

 

train_df = pd.read_csv("res/titanic/train.csv")
test_df = pd.read_csv("res/titanic/test.csv")

train_df.head()

 

- info로 보니 891 x 12 형태

- 기초 통계량

- 결측치 조회 및 삭제

* Cabin의 경우 결측치가 687개라 그냥 결측치를 삭제하는경우 891개 중 687개가 삭제되어버렸다.

 => Cabin과 Age의 결측치는 삭제하지 말고, fillna()로 채워주자

print(train_df.isnull().sum())
train_df = train_df.dropna()
print()
print(train_df.isnull().sum())
print(train_df.info())

- 결측치 채우고, 나머지 삭제

 -> "age"는 나이 평균, "cabin"은 N으로 대체

train_df = pd.read_csv("res/titanic/train.csv")

train_df["Age"].fillna(train_df["Age"].mean(), inplace=True)
train_df["Cabin"].fillna("N", inplace=True)
train_df = train_df.dropna()
print()
print(train_df.isnull().sum())
print(train_df.info())

 

 

탐색적 데이터 분석

1. 단순 확인

- 일단 각 컬럼 별 분포를 해보자

- 우선 해당 데이터프레임의 컬럼 조회

- 아까 결측치를 채운 카빈부터 보자

 -> 호실이다보니 수가 적은 경우가 많아보인다.

- 남여 비율과 생존여부, 등급

2. 그룹별 조회

- 성별에 따른 생존 여부

train_df.groupby(["Sex", "Survived"])["Survived"].count()

- 선실등급별 생존여부

train_df.groupby(["Pclass", "Survived"])["Survived"].count()

- 나이별 생존여부.

   * 나이의 경우 나이대별로 보지않다보니 힘들다. 그룹화가 필요해보이고, 이번에 시각화해서 보자

train_df.groupby(["Age", "Survived"])["Survived"].count()

 

 

 

3. 시각화

- 성별에 따른 생존여부

sns.barplot(x="Sex", y="Survived",data=train_df)

- 성별과 선실 등급에 따른 생존여부

sns.barplot(x="Sex", y="Survived", hue="Pclass", data=train_df)

 

 

* DataFrame.apply() 함수를 이용한 나이대별 그룹화

 -> 25 ~ 35인 Young Adult가 가장 많은걸 확인할 수 있음. 

 (아마 아까 Age의 결측치를 평균으로 채운 영향으로보임)

def get_categroy(age):
    cat = ""
    if age <= -1: cat = "Unknown"
    elif age <= 5: cat = "Baby"
    elif age <= 12: cat = "Child"
    elif age <= 18: cat = "Teenager"
    elif age <= 25: cat = "Student"
    elif age <= 35: cat = "Young Adult"
    elif age <= 60: cat = "Adult"
    else : cat = "Elderly"
    return cat

train_df["AgeGroup"] = train_df["Age"].apply(lambda x : get_categroy(x))
train_df["AgeGroup"].value_counts()

- 나이대 그룹과 성별에 따른 생존 여부를 살펴보자

 -> 아기, 어린이와 여성의 경우 생존률이 높게 나옴

sns.barplot(x="AgeGroup", y="Survived", hue="Sex", data=train_df)

- 선실 등급과 나이 그룹에 대해서도 살펴보면 -> 1등실 사람일수록 생존률이 높음

- 다른 변수로 Parch(탑승 부모, 어린이인원), SibSp(탑승 형재, 배우자 인원)도 살펴보면 

 -> PClass, Age에 비하여 균등하게 나옴 => 좋은 변수는 아님

 

 

4. 인코딩 하기

- 아까 Sex, Cabin, Embarked 변수가 문자열로 되어있는걸 보았으니 인코딩이 필요

 

def encoding(df):
    features = ["Cabin", "Sex", "Embarked"]

    for feature in features:
        encoder = LabelEncoder()
        df[feature] = encoder.fit_transform(df[feature])
    
    return df

train_df = encoding(train_df)
train_df.head()

 

* 아까 잊었는데 값이 고유한 변수들은 삭제해주자

 -> Age, Ticket 는 삭제

train_df.drop(["Name", "Ticket"], axis=1, inplace=True)
train_df.head()

 

 

 

 

GridSearchCV를 이용한 최적의 분류기와 하이퍼 파라미터 찾기

- 데이터는 loc로 X, y  선택

- random forest와 결정 트리 사용

X = train_df.loc[:,train_df.columns != "Survived"]
y = train_df.loc[:,train_df.columns == "Survived"]

rf_clf = RandomForestClassifier()
dt_clf = DecisionTreeClassifier()

param = {
    "max_depth" : [3, 4, 5, 6],
    "min_samples_split" :[2, 3, 4, 5]
}

rf_gs = GridSearchCV(rf_clf, param_grid=param, cv=5, refit=True)
dt_gs = GridSearchCV(dt_clf, param_grid=param, cv=5, refit=True)

rf_gs.fit(X, y)
dt_gs.fit(X, y)

print("Random Forest")
print(rf_gs.best_score_)
print(rf_gs.best_params_)
print("\n\ndecision tree")
print(dt_gs.best_score_)
print(dt_gs.best_params_)

- 최적의 성능과 하이퍼 파라미터는 아래의 사진과 같음

 -> 랜덤 포레스트로 깊이 5, min_sample_split이 2일때 0.829로 좋았음.

 

 

 

 

 

 

300x250
728x90

데이터 전처리

- sklearn의 머신러닝 알고리즘을 사용하기전에 결손치나 문자열 값을 처리해주어야 함

-> 결손치 제거

-> 문자열을 카테고리(인코딩하여)나, 벡터화

* PK로 사용할수 있는 값(주민번호, 아이디)은 제거하는 것이 좋음

 

 

 

 

데이터 인코딩

- 라벨 인코딩, 원핫 인코딩 

- 라벨 인코딩 LabelEncoding : 카테고리형 문자열 변수에 클래스 할당

  * sklearn.preprocessing에서 제공 

from sklearn.preprocessing import LabelEncoder

items = ["한국", "미국", "미국", "중국", "러시아", "호주"]

encoder = LabelEncoder()
encoder.fit(items)

lables = encoder.transform(items)
print(lables)
print(encoder.classes_)

- 원핫인코딩 OneHotEncoding : 각 카테고리가 고유의 컬럼을 가지고, 해당하면 1아니면 0의값을 갖도록하는방식

from sklearn.preprocessing import OneHotEncoder
lables = lables.reshape(-1,1)
print(lables)

oh = OneHotEncoder()
oh.fit(lables)
oh_lables = oh.transform(lables)

print(oh_lables.toarray())

 

 

 

 

 

피처 스케일링 feature scaling

- 다른 범위의 값들을 갖는 변수를 일정 수준으로 변환하는 작업

 ->  ex. 표준화 standardization, 정규화 normalization

- 표준화 : 특정 피처값을 표준 정규 분포의 값으로 변환. (해당 값 - 해당 피처 평균)/해당 피처 표준편차

- 정규화 : 피처 값을 0 ~ 1사이 값으로 변환.

* sklearn의 정규화 : 벡터 정규화. 새 피처값 = 해당 피처값/해당 행의 유클리디안 거리

 

 

 

StandardScaler

- sklearn.preprocess 모듈

- 가우시안 커널을 사용하는 알고리즘(SVM, 선형회귀, 로지스틱회귀)는 데이터가 가우시안 분포를 따른다고 가정

  -> 표준화가 중요

 

from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC

scaler = StandardScaler()
scaler.fit(X)
X_scaled = scaler.transform(X)
df_scaled = pd.DataFrame(data=X_scaled, columns=data.feature_names)


print("befor scaling")
print(X.mean())
print(X.var())

print("\nafter scaling")
print(df_scaled.mean())
print(df_scaled.var())

 

 

MinMaxSacler

- 0 ~ 1 사이 값으로 변환. (음수 포함시 -1 ~ 1)

from sklearn.preprocessing import MinMaxScaler

scaler = MinMaxScaler()
scaler.fit(X)
X_scaled = scaler.transform(X)

df_scaled = pd.DataFrame(data=X_scaled, columns=data.feature_names)
print(df_scaled.min())
print(df_scaled.max())

 

 

 

 

 

 

 

 

 

 

 

300x250
728x90

sklearn 모듈 개요

 

1. 데이터셋 datasets

 

2. 특징 처리

 2.1 preprocessing

  - 인코딩, 정규화, 스케일링 등

 2.2 feature_selection

  - 큰 영향을 미치는 피처 순서대로 선정

 2.3 feature_extraction

  - 피처 추출

 2.4 decomposition

  - 차원 축소 알고리즘 지원. LDA, PCA, SVD 등

3. 데이터 분할, 검증, 하이퍼 파라미터 튜닝 model_selection

 - 교차 검증, 최적 하이퍼파라미터 추출을 위한 그리드 서치 등 제공

4. 성능평가 척도 metrics

 - 정확도 accuracy, 재현율(모델 참/실제 참) recall, 정밀도(모델참/전체 참) precision, ROC-AUC, RMSE 등

 

5. 머신러닝 알고리즘

 5.1 ensemble : 랜덤 포레스트, 어댑티브부스트, 그라디언트 부스트

 5.2 linear_model : 선형 모델, 릿지, 라쏘, 로지스틱 회귀, SGD

 5.3 naive_bayes : 나이브 베이즈, 가우시안NB

 5.4 neighbors : K-NN

 5.5 svm : 서포트 벡터 머신 관련 알고리즘

 5.6 tree : 결정 트리

 5.7 cluster : k-means, dbscan 등

 

6. pipeline : 피처 처리, 학습, 예측 등을 함께 할수있는 묶음.

 

 

 

 

 

 

 

 

 

교차 검증

 

교차 검증하기

- 과적합 문제를 개선하기 위해 사용

 * 과적합 : 학습 데이터에 모델이 과도하게 맞춰져, 실제 예측시 성능이 떨어지는 현상.

- 학습 데이터를 학습, 검증 데이터로 분할하여 학습 (위의 train_test_split으로 분할하여 학습한 것과 같이)

 

 

k fold cross validation

- 데이터를 k개로 분할하여 (k-1)개로 학습, 1개로 테스트를 k번 수행하여 검증하는 방법

- model_selection의 KFold 사용

- KFold(n_split=)  -> KFold.split(X) 데이터를 n_split 만큼 분할하여 인덱스 반환

from sklearn.model_selection import KFold

kfold = KFold(n_splits=5)
num_iter = 0

cv_acc = []

for train_idx, test_idx in kfold.split(X):
    X_train, X_test = X.iloc[train_idx, :], X.iloc[test_idx, :]
    y_train, y_test = y.iloc[train_idx], y.iloc[test_idx]
    
    clf.fit(X_train, y_train)
    y_pred = clf.predict(X_test)
    num_iter = num_iter + 1
    acc = round(accuracy_score(y_test, y_pred), 10)
    
    print("{}번 검증 셋 정확도 : {} ".format(num_iter, acc))
    cv_acc.append(acc)

print("mean of accuracy : {} ".format(round(np.mean(cv_acc),7)))

 

 

stratified K fold

- 타겟 레이블의 비율이 불균형한 데이터를 위한 k fold

- 타겟 레이블의 분포도를 반영하여 인덱스 제공

- KFold와 다르게 StratifiedKFold.split(X, y)는 X와 y를 같이 제공해주어야 함.

from sklearn.model_selection import StratifiedKFold

skf = StratifiedKFold(n_splits=5)

for train_idx, test_idx in skf.split(X, y):
	...

 

 

cross_val_score

- 교차 검증과 성능 평가 척도를 한번에 하는 함수

- cross_val_score(estimator, X, y=None, scoring=None, cv=None, n_jobs=1, verbose=0, ....)

from sklearn.model_selection import cross_val_score
scores = cross_val_score(clf, X, y, scoring="accuracy", cv=5)
print(scores)
print(np.mean(scores))

 

 

 

 

 

하이퍼 파라미터 탐색

 

GridSearchCV

- GridSearchCV(estimator, param_grid, scoring, cv, refit)

 * param_grid : 하이퍼 파라미터 딕셔너리, refit : 디폴트 true, 최적 하이퍼파라미터로 재학습

 

from sklearn.model_selection import GridSearchCV


clf = DecisionTreeClassifier()
param = {
    "max_depth":[1, 2, 3, 4, 5],
    "min_samples_split":[2, 3, 4]
}

grid_clf = GridSearchCV(clf, param_grid=param, cv=5, refit=True)
grid_clf.fit(X_train, y_train)

scores_df = pd.DataFrame(grid_clf.cv_results_)
scores_df.head()

- GridSearchCV.cv_result_로 결과 반환. 데이터프레임으로 변환 후 출력 시

 -> max_depth가 5이고, min_samples_split이 1인 경우 최적 성능

- GridSearchCV의 변수로 best_params_, best_score_, best_estimator_ 등 제공

print(grid_clf.best_params_)
print(grid_clf.best_score_)

clf = grid_clf.best_estimator_
print(clf.score(X_test, y_test))

 

 

 

 

 

 

 

300x250
728x90

sklearn

- 파이썬에서 머신러닝을 사용하기 위한 api들을 제공함.

- 전처리, 데이터셋, 군집화, 분류, 회귀 등

 

 

붓꽃 문제 다루기

 

라이브러리 import

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris

 

 

아이리스 데이터 읽기 및 확인

- sklearn의 load함수로 호출한 데이터셋은 bunch타입

- sklearn.utils.Bunch의 DESCR에서 해당 데이터셋에대한 설명 

 

 

bunch 데이터를 데이터 프레임으로 변환 및 확인

- 머신러닝 알고리즘을 적용하기위해 데이터프레임 데이터로 변환

df = pd.DataFrame(columns=data.feature_names, data=data.data)
df["label"] = data.target
df.head()

 

 

데이터 분할하기

- 훈련용 데이터와 테스트용 데이터 분할

- sklean.model_selection의 train_test_split()함수 사용

- train_test_split(X, y, test_size=None)

  -> test_size에는 전체 데이터프레임의 비율 지정. 0.2의 경우 20%

 

from sklearn.model_selection import train_test_split

X = df.iloc[:,:-1]
y = df["label"]

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)

 

 

 

학습 모델

- Estimator 클래스

  -> Classifier, Regressor 등

- Estimator.fit(X, y)

  - X, y 데이터로 학습

- Estimator.predict(X)

 - 주어진 X 데이터로 예측

 

 

학습 모델 사용하기

- 본 붓꽃 문제는 특징들을 이용한 분류 문제. 의사결정트리 사용

- 의사결정 트리는 sklearn의 tree에 있음.

 

 

from sklearn.tree import DecisionTreeClassifier
clf = DecisionTreeClassifier()

clf.fit(X_train, y_train)
y_pred = clf.predict(X_test)

 

 

 

모델 성능 척도

- 정확도, 재현률, MSE 등 존재

- 다음 경우 estimator.score()와 정확도, MSE 사용

from sklearn.metrics import accuracy_score
from sklearn.metrics import mean_squared_error


print("decision tree score using train : {}".format(clf.score(X_train, y_train)))
print("decision tree score using test : {}".format(clf.score(X_test, y_test)))
print("accuracy : {}".format(accuracy_score(y_test, y_pred)))
print("MSE : {}".format(mean_squared_error(y_test, y_pred)))

 

 

 

 

 

300x250
728x90

넘파이 개요

- 파이썬 선형대수 library

- 루프 없이 빠르게 선형대수 처리 가능

- C++에서 Eigen, Armadillo 같은 lib

- 저수준 언어 기반 호환 API 제공. -> 성능에서 중요한 부분은 C/C++로 작성. 넘파이에서 호출가능

넘파이 배열

- 생성 : arrange, zeros, eyes

- 재배치 : reshape

- 인덱싱 처리 등 내용은 생략

Pandas

  • 금융 분석가 웨스 매키니가 만든 데이터 핸들링 라이브러리
  • DBMS, Excel의 테이블과 유사한 데이터들을 다룸
  • 대표적인 자료구조로 Series와 DataFrame
  • Series : 칼람이 하나인 데이터 구조
  • DataFrame ; 칼럼이 여러개인 데이터 구조

www.kaggle.com/c/titanic/data

titanic data 보기

 

DataFrame.head()

- 해당 DataFrame의 앞 5개 데이터 확인

 

 

 

DataFrame.info()

- 해당 데이터프레임의 컬럼의 데이터 갯수와 데이터 타입조회

 

 

DataFrame.describe()

- 해당 데이터프레임의 기초통계량 조회

 

 

Series.value_counts()

- 해당 컬럼의 그룹별 갯수를 카운트

- 다음 경우 3등석이 491, 2등석이 184, 1등석이 216개임을 확인

print(type(df["Pclass"]))
df["Pclass"].value_counts()

 

 

데이터 프레임 컬럼 추가

- 다음의 경우 age_0이라는 컬럼이 추가.

- 값은 0으로 지정

df["age_0"] = 0
df.head()

 

 

데이터 프레임 컬럼 값 변경

df["age_0"] = df["age_0"] + 20
df.head()

 

데이터 프레임 열 삭제

- DataFrame.drop(labels=None, axis=0, index=None, columns=None, inplace=False)

- labels : 삭제 컬럼명 지정

- axis : 0인경우 행, 1인경우 열 지정

- inplace : 해당 DataFrame에 적용 여부. 

- 나머지는 doc 참조

- 아래의 경우 age_0 열이 삭제된것을 확인

 

df.drop(labels="age_0", axis=1, inplace=True)
df.head()

 

 

 

 

데이터프레임 인덱싱 - 1. loc (명칭 기반인덱싱)

- DataFrame.loc[키값, 열이름]

df.loc[3, "Name"]

 

 

 

데이터프레임 인덱싱 - 2. iloc (숫자 기반인덱싱)

- DataFrame.iloc[키, 열]

 

데이터 프레임 인덱싱 조합

- Pclass >=2 인 경우. 4번째까지 출력

df[df["Pclass"] >= 2][:4]

- Pclass >=2 이고, Survived=1인 경우, 4개 출력

df[(df["Pclass"] >= 2) & (df["Survived"] == 1)][:4]

 

집계함수 aggregation

- min(), max(), sum(), count()등

print(df.mean())
print(df.count())
print(df["Age"].count())
print(df[["Age","Fare"]].count())

 

 

그룹함수 groupby

- DataFrame.groupby(그룹할컬럼명)

   -> DataFrameGroupBy 객체 반환

group = df.groupby("Sex")
print(type(group))

- 해당 객체는 집계함수 사용 가능

print(group.count())

group.describe()

 

 

- 여러 컬럼으로 그룹핑 가능

group = df.groupby(["Pclass", "Sex"])
group.describe()

 

결측치 확인 - DataFrame.isnull().sum()

- DataFrame.isnull() 은 모든 행열에서 결측치 여부에 따라 true, false를 반환

 - + sum()으로 각열에 대한 결측치들을 합하여 갯수를 알려줌

df.isnull().sum()

 

 

 

결측치 제거 - DataFrame.dropna(axis=None, how=None)

- Axis :  axis = 0인 경우 행, axis = 1인경우 열, axis=None이면 행렬 다 적용

- how : how = "any" 결측치가 하나라도 존재하면 제거, how = " all" 전체가 결측치인경우제거

df = df.dropna(axis=0)
df.isnull().sum()

 

 

 

람다식 적용하기

- DataFrame.apply(람다식) 으로 데이터프레임에 함수 적용 가능

df["NameLen"] = df["Name"].apply(lambda x : len(x))
df[["Name","NameLen"]].head()

300x250
728x90

패턴 찾기의 역사

- 데이터에서 패턴을 찾는 것은 역사적으로 오래됨

- 캐플러의 행성 운동의 법칙

 

패턴 인식이란 ?

- 데이터에서 일관성을 찾아내는 일.

- 찾아낸 일관성을 활용. 예시 : 분류

 

 

손글씨 인식의 예시

- 28 x 28 의 크기 이미지로 이에 대한 벡터 x는 784개의 수

- 목표 : 벡터 x로 숫자 인식하기.

- 훈련 집합 = {x1, ..., xn}  -> 모델의 파라미터들을 조정하는데 사용.

- 타겟 벡터 t : 결과 집합으로 x에 대한 정답.

- y(x), 모델 : 손글씨 이미지 x로 결과 y를 얻는 함수이자 모델. 훈련 과정을 통해 정의됨.

- 테스트 집합 : 훈련된 모델의 성능을 평가하기 위한 데이터

- 전처리 과정 : 입력 변수들을 패턴 인식 문제를 더 풀기 쉽게 처리하는 과정

   -> 손글씨 인식의 경우 : 구석에 있거나/회전 되었거나/작은경우 -> 이동, 회전, 스케일 변환

   * 전처리 과정을 특징 추출이라고도 함.

 

 

 

관련 용어

- 특징 feature : 데이터를 설명하는 서로 구분할수 있는 

- 분류 classification : 입력 데이터를 다양한 카테고리중 한가지로 분류

- 회귀 regression : 입력 데이터로 특정한 값을 추론

- 클러스터링 clustering : 구분 되어있지 않은 데이터들을 각각의 군집으로 분할하는 과정

 

300x250

'인공지능' 카테고리의 다른 글

파이썬머신러닝 - 2. 붓꽃 문제 다루기  (0) 2020.11.23
파이썬머신러닝 - 1. 기초  (0) 2020.11.23
인공지능 - 7. 게임 트리  (0) 2020.11.11
인공지능 - 6. 탐색 과정  (0) 2020.11.11
인공지능 - 5. 퍼지이론  (0) 2020.11.11
728x90

게임을 이용해 인공지능 연구 이유

- 문제가 잘 풀렸는지 판단하기 쉬움

- 많은 지식이 필요없이, 이기는 위치를 탐색 알고리즘으로 찾으면 됨.

- 단순 탐색 알고리즘으론 힘듬.

 

 

최대-최소 탐색 min-max search

- 나는 최대한 유리, 상대도 최대한 유리한 수를 선택한다 판단.

- 각 노드에 가치 부여

- 최대화 : 최대의 가치를 갖는 후계 노드 선택. 현재 노드는 가장 큰 후계노드의 가치를 가짐.

- 최소화 : 상대는 나에게 가장 낮은 가치를 주는 노드 선택할것. 현재 노드는 가장 낮은 후계노드의 가치를 가짐.

- 최대, 최소화를 여러 단계 거쳐 나에게 유리한 수 선택

 

 

 

 

최대 최소 탐색 트리

- 상대방의 응수를 고려하여 결정하는 경우에 대한 트리

- 내가 A를 선택시 상대는 D 선택, 나는 그나마 다른 노드의 최소에 비해 가장 큰 가치를 갖는 J를 선택 할 수 있음.

 

 

 

몬테 카를로 탐색

- 기존의 게임 트리 탐색 : 경우의 수가 방대한 경우 경험적 지식으로 평가 함수 만들기 어려움.

- 의사 결정 문제에서 활용되는 경험적 탐색 알고리즘

- 탐색 공간 무작위 표본화로 탐색 트리 구성

 

 

몬테카를로 트리 탐색 절차

1. 트리는 점증, 비대칭적 방식으로 생성.

2. 매 반복시 루트 노드서 시작하여 적절한 자식 노드를 선택하는 과정을 반복.

3. 리프노드에 도달한 다음 자식 노드를 생성하여 확장.

4. 리프토드 경로 결정 정책은 탐사, 활용을 균형적으로 설계

  * 탐사 exploration : 검사하지 않은 영역을 확인

  * 활용 exploitation : 유망 영역 확인

5. 시뮬레이션 시행 : 새 노드 가치 평가 위하여 몬테카를로 롤아웃 수행. 

  * 몬테카를로 롤아웃 : 무작위 방식으로 게임 깥까지 진행.

6. 시뮬레이션 결과 시작 리프노드에서 루프노드까지 통계치 업데이트에 활용

 => 경험적 지식을 반영한 평가 함수를 사용하지는 않음.

7. 제한에 도달할떄 까지 반복. 도달 시 우수한 행동 선택

  * 제한 : 시간, 메모리, 반복 횟수 등

 

 

 

몬테카를로 트리 탐색 알고리즘

- 노드 n_i : 게임 특정 상태. 그 노드의 현재 가치 v_i, 노드 방문 횟수 N_i 등 포함.

- 루트 노드 하나인 트리로 탐색 시작하여 4단계 수행

1. 선택 : 선택 전략에 따라 깊이 방향으로 자식 노드 선택 반복. 

2. 확장 : 선택된 노드에 추가 행동하여 트리 확장

3. 시뮬레이션 : 확장된 노드에서 게임이 끝날떄까지 게임 진행(롤아웃).

4. 역전파 : 시뮬레이션 결과 시작 노드에서 루트노드까지 선택경로를 따라 업데이트

 

 

 

 

300x250

'인공지능' 카테고리의 다른 글

파이썬머신러닝 - 1. 기초  (0) 2020.11.23
패턴인식이론 - 1. 간단  (0) 2020.11.18
인공지능 - 6. 탐색 과정  (0) 2020.11.11
인공지능 - 5. 퍼지이론  (0) 2020.11.11
인공지능 - 4. 논리기반 지식표현  (0) 2020.11.11

+ Recent posts