본문 바로가기
## 오래된 게시글 (미관리) ##/Python (Linux)

44. Python - 6장 연습문제

by #Glacier 2019. 2. 12.
반응형

1. 백만 개의 샘플을 가진 훈련 세트에서 (규제 없이) 훈련시킨 결정 트리의 깊이는 대략 얼마일까요?

#

m개의 리프 노드를 포함한 균형이 잘 잡힌 이진 트리의 깊이는 을 반올림 한 것과 같습니다.

이진 결정 트리를 제한을 두지 않고 훈련시키면, 훈련 샘플마다 하나의 리프 노드가 되므로, 어느 정도 균형이 잘 잡힌 트리가 됩니다. 따라서 훈련 세트에 백만 개 샘플이 있다면, 결정 트리의 깊이는 이 될 것입니다.

(실제로는 완벽하게 균형 잡힌 트리가 만들어지지 않기 때문에 조금 더 늘어납니다.


2. 한 노드의 지니 불순도가 보통 그 부모 노드보다 작을까요? 클까요?

   일반적으로 작거나 클까요? 아니면 항상 작거나 클까요?

#

한 노드의 지니 불순도는 일반적으로 부모의 불순도보다 낮습니다.

이는 자식의 지니 불순도의 가중치 합이 최소화되는 방향으로 각 노드를 분할하는 CART 알고리즘의 비용 함수 때문입니다. 그러나, 다른 자식 노드의 지니 불순도 감소량이 어느 노드의 불순도 증가량보다 큰 경우라면, 부모의 불순도보다 큰 노드가 생길 수 있습니다.


3. 결정 트리에 훈련 세트가 과대적합되었다면, max_depth를 줄이는 것이 좋을까요?

#

결정 트리가 훈련 세트에 과대적합되었다면, 모델에 제약을 가해 규제해야 하므로 max_depth를 낮추는게 좋습니다.


4. 결정 트리가 훈련 세트에 과소적합되었다면, 입력 특성의 스케일을 조정하는 것이 좋을까요?

#

결정 트리는 훈련 데이터의 스케일이나 원점에 맞추어져있는지 상관하지 않습니다.


5. 백만 개의 샘플을 가진 훈련 세트에 결정 트리를 훈련시키는 데 한 시간이 걸렸다면,

   천만 개의 샘플을 가진 훈련 세트는 얼마나 걸릴까요?

#

결정 트리 훈련의 계산 복잡도는 입니다. 

그러므로 훈련 세트의 크기에 10을 곱하면 훈련 시간은

배 늘어납니다.

만약 m = 100,000이면, K = 11.7 정도가 되므로, 대략 11.7 시간이 걸릴 것으로 예상할 수 있습니다.


6. 십만 개의 샘플을 가진 훈련 세트가 있다면, presort=True로 지정하는 것이 훈련 속도를 높일까요?

#

데이터셋의 샘플 수가 수천 개 미만일 때, 훈련 세트를 사전에 정렬하면 훈련 속도를 높일 수 있지만,

그 이상이라면 매우 느려집니다.


7. moons 데이터셋에 결정 트리를 훈련시키고, 세밀하게 튜닝해보세요.


1) make_moons(n_samples =1000, noise = 0.4)를 사용해 데이터셋을 생성합니다.


from sklearn.datasets import make_moons


X, y = make_moons(n_samples=10000, noise=0.4, random_state=42)


2) 이를 train_test_split()을 사용해 훈련 세트와 테스트 세트로 나눕니다.


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, random_state=42)


3) DecisionTreeClassifier의 최적 매개변수를 찾기 위해 교차 검증과 함께 그리드 탐색을 사용합니다. (GridSearchCV)

   힌트 = 여러 가지 max_leaf_nodes 값을 시도해보세요.


from sklearn.model_selection import GridSearchCV


params = {'max_leaf_nodes' : list(range(2, 100)), 'min_samples_split' : [2,3,4]}

grid_search_cv = GridSearchCV(DecisionTreeClassifier(random_state=42), params, cv=3, n_jobs=-1 , verbose=1)

grid_search_cv.fit(X_train, y_train)

Fitting 3 folds for each of 294 candidates, totalling 882 fits
[Parallel(n_jobs=-1)]: Using backend LokyBackend with 4 concurrent workers.
[Parallel(n_jobs=-1)]: Done 253 tasks      | elapsed:    1.9s
[Parallel(n_jobs=-1)]: Done 882 out of 882 | elapsed:    3.7s finished
GridSearchCV(cv=3, error_score='raise-deprecating',
       estimator=DecisionTreeClassifier(class_weight=None, criterion='gini', max_depth=None,
            max_features=None, max_leaf_nodes=None,
            min_impurity_decrease=0.0, min_impurity_split=None,
            min_samples_leaf=1, min_samples_split=2,
            min_weight_fraction_leaf=0.0, presort=False, random_state=42,
            splitter='best'),
       fit_params=None, iid='warn', n_jobs=-1,
       param_grid={'max_leaf_nodes': [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99], 'min_samples_split': [2, 3, 4]},
       pre_dispatch='2*n_jobs', refit=True, return_train_score='warn',
       scoring=None, verbose=1)


grid_search_cv.best_estimator_

#기본적으로 GridSearchCV는 전체 훈련 세트로 찾은 최적의 모델을 다시 훈련시킵니다.

#(refit=False로 지정해서 바꿀 수 있습니다). 그래서 별도로 작업할 필요가 없습니다. 

#모델의 정확도를 바로 평가할 수 있습니다.

DecisionTreeClassifier(class_weight=None, criterion='gini', max_depth=None,
            max_features=None, max_leaf_nodes=17,
            min_impurity_decrease=0.0, min_impurity_split=None,
            min_samples_leaf=1, min_samples_split=2,
            min_weight_fraction_leaf=0.0, presort=False, random_state=42,
            splitter='best')


4) 찾은 매개변수를 사용해 전체 훈련 세트에 대해 모델을 훈련시키고, 테스트 세트에서 성능을 측정하면 

   대략 85~87% 정도 정확도가 나올 것입니다.


from sklearn.metrics import accuracy_score


y_pred = grid_search_cv.predict(X_test)

accuracy_score(y_test, y_pred)

0.8695


8. 랜덤 포레스트를 만들어보세요.


1) 이전 연습문제에 이어서 훈련 세트의 서브셋을 1,000개 생성합니다. 

   각각은 무작위로 선택된 100개의 샘플을 담고 있습니다. (힌트 : 사이킷런의 ShuffledSplit)


from sklearn.model_selection import ShuffleSplit


n_trees = 1000

n_instances = 100

mini_sets = []

#1,000개의 서브셋으로 나누고, test_size는 8,000-100개.

rs = ShuffleSplit(n_splits = n_trees, test_size = len(X_train) - n_instances, random_state=42)


#mini_train_index = 100 , mini_test_index = 7,900


for mini_train_index, mini_test_index in rs.split(X_train) :

    X_mini_train = X_train[mini_train_index]

    y_mini_train = y_train[mini_train_index]

    mini_sets.append((X_mini_train, y_mini_train))


2) 앞에서 찾은 최적의 매개변수를 사용해 각 서브셋에 결정 트리를 훈련시킵니다.

   테스트세트로 이 1,000개의 결정 트리를 평가합니다.


from sklearn.base import clone


forest = [clone(grid_search_cv.best_estimator_) for _ in range(n_trees)]


accuracy_scores = []


for tree, (X_mini_train, y_mini_train) in zip(forest, mini_sets):

    tree.fit(X_mini_train, y_mini_train)

    

    y_pred = tree.predict(X_test)

    accuracy_scores.append(accuracy_score(y_test, y_pred))


np.mean(accuracy_scores)

0.8054499999999999

3) 각 테스트 샘플에 대해, 1,000개의 결정 트리 예측을 만들고, 다수로 나온 예측만 취합니다.

   (사이파이의 mode()함수 사용) 그러면 테스트 세트에 대한 다수결 예측(majority-vote prediction)이 만들어집니다.

Y_pred = np.empty([n_trees, len(X_test)], dtype=np.uint8)


for tree_index, tree in enumerate(forest):

    Y_pred[tree_index] = tree.predict(X_test)


from scipy.stats import mode


y_pred_majority_votes, n_votes = mode(Y_pred, axis=0)


4) 테스트 세트에서 이 예측에 대해 평가합니다.


accuracy_score(y_test, y_pred_majority_votes.reshape([-1]))

0.872


연습문제가 쉽지는 않은 것 같습니다. 봐도 촤라락 머리에 그려지지 않아서..ㅎㅎ

다음 장은 랜덤포레스트입니다.


 블로그 

출처


이 글의 상당 부분은  [핸즈온 머신러닝, 한빛미디어/오렐리앙 제롱/박해선] 서적을 참고하였습니다.


나머지는 부수적인 함수나 메서드에 대해 부족한 설명을 적어두었습니다.

학습용으로 포스팅 하는 것이기 때문에 복제보다는 머신러닝에 관심이 있다면 구매해보시길 추천합니다.


도움이 되셨다면 로그인 없이 가능한

아래 하트♥공감 버튼을 꾹 눌러주세요! 



반응형