Wu Enda 471 기계 학습 입문 과정 2주 4 - 결정 트리


의사 결정 트리를 처음부터 구현하고 버섯이 식용인지 독성인지를 분류하는 작업에 적용합니다.

가이드 패키지 1개

import numpy as np
import matplotlib.pyplot as plt
from public_tests import *
%matplotlib inline

2 문제 설명

야생 버섯을 재배하고 판매하는 사업을 시작한다고 가정해 보겠습니다. 모든 버섯이 먹을 수 있는 것은 아니므로 해당 버섯의 물리적 특성에 따라 해당 버섯이 먹을 수 있는지 독성이 있는지 구분할 수 있기를 원합니다. 이 작업에 사용할 수 있는 기존 데이터가 있습니다. 판매하기에 안전한 버섯을 결정하는 데 이 데이터를 사용할 수 있습니까? 참고: 사용된 데이터 세트는 설명 목적으로만 사용됩니다. 이것은 식용 버섯을 식별하기 위한 지침이 아닙니다.

원-핫 인코딩된 데이터 세트 3개

갈색 모자 가늘어지는 줄기 모양 외로운 먹을 수 있는
1 1 1 1
1 0 1 1
1 0 0 0
1 0 0 0
1 1 1 1
0 1 1 0
0 0 0 0
1 0 1 1
0 1 0 1
1 0 0 0
그러므로,
  • X_train각 샘플에 대한 세 가지 기능 포함

    • 모자 색상(갈색 모자 1의 , 0빨간색 모자의 값)
    • 스템 수축("테이퍼형" 스템 1의 , 0"확장된" 스템의 값)
    • 혼자( 1예 , 0아니요 값)
  • y_train버섯은 먹을 수 있습니까?

    • y = 1식용을 의미
    • y = 0유독함을 나타냅니다.
X_train = np.array([[1,1,1],[1,0,1],[1,0,0],[1,0,0],[1,1,1],[0,1,1],[0,0,0],[1,0,1],[0,1,0],[1,0,0]])
y_train = np.array([1,1,0,0,1,0,0,1,1,0])
X_train[:5]
array([[1, 1, 1],
       [1, 0, 1],
       [1, 0, 0],
       [1, 0, 0],
       [1, 1, 1]])

4개의 결정 트리

이 실습에서는 제공된 데이터 세트를 기반으로 의사 결정 트리를 구축합니다.

  • 의사 결정 트리를 구축하는 단계를 상기하십시오.

    • 루트 노드에서 시작하는 모든 샘플 사용
    • 가능한 모든 특징을 기준으로 분할 시 정보 획득을 계산하고 정보 획득이 가장 높은 특징 선택
    • 선택한 기능을 기반으로 데이터 세트를 분할하고 트리의 왼쪽 및 오른쪽 분기를 만듭니다.
    • 중지 기준이 충족될 때까지 분할 프로세스를 계속 반복합니다.
  • 이 실습에서는 정보 이득이 가장 높은 기능을 사용하여 노드를 왼쪽 및 오른쪽 분기로 분할하는 다음 기능을 구현합니다.

    • 노드의 엔트로피 계산
    • 주어진 기능을 기반으로 노드에서 데이터 세트를 왼쪽 및 오른쪽 분기로 분할
    • 주어진 기능을 분할할 때 정보 이득을 계산합니다.
    • 정보 획득을 극대화하는 기능 선택
  • 그런 다음 구현한 도우미 기능을 사용하여 중지 기준이 충족될 때까지 분할 프로세스를 반복하여 의사 결정 트리를 구축합니다.

    • 이 실험에서 우리가 선택한 중지 기준은 최대 깊이를 2로 설정하는 것이었습니다.

4.1 엔트로피 계산

compute_entropy먼저 노드에서 엔트로피(불순도 측정)를 계산하는 엔트로피(불순도 측정)라는 도우미 함수를 작성해야 합니다 .

  • y이 함수는 이 노드의 예가 식용( 1)인지 독성( 0) 인지를 나타내는 numpy 배열( )을 허용합니다.

다음 기능을 완료하십시오 compute_entropy().

  • p 1 p_1 계산1, 이는 식용 예의 비율 입니다 (즉, y값 = in1
  • 그런 다음 엔트로피를 계산하십시오.

H ( p 1 ) = − p 1 log 2 ( p 1 ) − ( 1 − p 1 ) log 2 ( 1 − p 1 ) H(p_1) = -p_1 \text{log}_2(p_1) - (1- p_1) \text{로그}_2(1- p_1)H ( 1)=- 1통나무2( 1)-( 1-1) 로그2( 1-1)

  • 알아채다
    • 로그는 밑수 2 2를 사용합니다.2
    • 편의상 0 log 2 ( 0 ) = 0 0\text{log}_2(0) = 00 로그2( 0 )=0 . 즉, ifp_1 = 0또는p_1 = 1이면 엔트로피를 다음으로 설정합니다.0
    • 노드의 데이터가 비어 있지 않은지(ie ) 확인하고 len(y) != 0비어 있으면 반환합니다.0
def compute_entropy(y):
    entropy = 0
    if len(y) != 0:
        p1 = len(y[y==1])/len(y)
        if p1 != 0 and p1 !=1:
            entropy = -p1 * np.log2(p1)-(1-p1)*np.log2(1-p1)
        else:
            entropy = 0
    return entropy

4.2 데이터셋 나누기

다음으로, 노드에서 데이터와 분할할 기능을 split_dataset가져와 . 실습 후반부에서 분할이 얼마나 잘 작동하는지 계산하는 코드를 구현합니다.

  • 이 함수는 학습 데이터, 이 노드에 있는 데이터 포인트의 인덱스 목록 및 분할할 기능을 사용합니다.
  • 데이터를 분할하고 왼쪽 및 오른쪽 분기에 대한 인덱스의 하위 집합을 반환합니다.
  • 예를 들어 루트 노드에서 시작하고(따라서 node_indices = [0,1,2,3,4,5,6,7,8,9]) 분할 기능을 로 선택한다고 가정합니다 0. 즉, 예제에 갈색 모자가 있는지 여부입니다.
    • 그러면 함수의 출력은, left_indices = [0,1,2,3,4,7,9],right_indices = [5,6,8]
색인 갈색 모자 축소 핸들 모양 독립적인 먹을 수 있는
0 1 1 1 1
1 1 0 1 1
2 1 0 0 0
1 0 0 0
4 1 1 1 1
5 0 1 1 0
6 0 0 0 0
7 1 0 1 1
8 0 1 0 1
9 1 0 0 0
def split_dataset(X,node_indices,feature):
    Lnode_indices = []
    Rnote_indices = []
    for i in node_indices:
        if X[i][feature] ==1:
            Lnode_indices.append(i)
        else:
            Rnote_indices.append(i)
    return Lnode_indices,Rnote_indices

다음으로 훈련 데이터, 노드의 인덱스 및 분할할 기능을 information_gain가져와서 .

계산하려면 아래에 표시된 compute_information_gain()함수를

정보 이득 = H ( p 1 노드 ) − ( w 왼쪽 H ( p 1 왼쪽 ) + w 오른쪽 H ( p 1 오른쪽 ) ) \text{정보 이득} = H(p_1^\text{노드})- (w^ {\text{왼쪽}}H(p_1^\text{왼쪽}) + w^{\text{오른쪽}}H(p_1^\text{오른쪽}))정보 획득=H ( 1노드)-( 왼쪽 H(p1왼쪽)+오른쪽 H(p1오른쪽))

안에:

  • H ( p 1 노드 ) H(p_1^\text{노드})H ( 1노드) 는 노드의 엔트로피입니다.
  • H ( p 1 왼쪽 ) H(p_1^\text{왼쪽})H ( 1왼쪽)H ( p 1 오른쪽 ) H(p_1^\text{오른쪽})H ( 1오른쪽) 는 분할 후 왼쪽 및 오른쪽 가지의 엔트로피입니다.
  • w 왼쪽 w^{\text{왼쪽}}왼쪽w 오른쪽 w^{\text{오른쪽}}오른쪽 은 각각 왼쪽 및 오른쪽 분기의 예 비율입니다.

알아채다:

  • 위에서 구현한 compute_entropy()함수를
  • 이전에 구현한 split_dataset()함수를
def compute_information_gain(X,y,node_indices,feature):
    L_indices,R_indices = split_dataset(X,node_indices,feature)

    X_node, y_node = X[node_indices],y[node_indices]
    X_left, y_left = X[L_indices], y[L_indices]
    X_right, y_right = X[R_indices], y[R_indices]

    node_entropy = compute_entropy(y_node)
    L_entropy = compute_entropy(y_left)
    R_entropy = compute_entropy(y_right)

    left_w = len(X_left)/len(X_node)
    rigth_w = len(X_right)/len(X_node)

    w_entropy = left_w*L_entropy +rigth_w*R_entropy
    information_gain = node_entropy - w_entropy
    return information_gain

이제 위에서 했던 것처럼 각 특징에 대한 정보 이득을 계산하여 가장 좋은 분할 특징을 얻고 가장 큰 정보 이득을 주는 특징을 반환하는 함수를 작성해 봅시다.

아래 표시된 get_best_split()기능을 .

  • 이 함수는 훈련 데이터와 노드에서 데이터 포인트의 인덱스를 받아들입니다.
  • 기능의 출력은 가장 큰 정보 이득을 제공하는 기능입니다.
    • 기능을 반복하고 compute_information_gain()함수를
def get_best_split(X,y,node_indices):
    num = X.shape[1]
    best_feature = -1
    max_info_gain = 0
    for feature in range(num):
        info_gain = compute_information_gain(X,y,node_indices,feature)
        if info_gain > max_info_gain:
            max_info_gain = info_gain
            best_feature = feature
    return best_feature

5 나무 만들기

이 섹션에서는 위에서 구현한 함수를 사용하여 중지 조건(최대 깊이 2)에 도달할 때까지 분할할 최상의 기능을 순차적으로 선택하여 의사 결정 트리를 생성합니다.

tree = []
root_indices = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
def build_tree_recursive(X, y, node_indices, branch_name, max_depth, current_depth):
    if current_depth == max_depth:
        formatting = " "*current_depth + "-"*current_depth
        print(formatting, "%s leaf node with indices" % branch_name, node_indices)
        return


    best_feature = get_best_split(X, y, node_indices)
    tree.append((current_depth, branch_name, best_feature, node_indices))

    formatting = "-"*current_depth
    print("%s Depth %d, %s: Split on feature: %d" % (formatting, current_depth, branch_name, best_feature))

    # Split the dataset at the best feature
    left_indices, right_indices = split_dataset(X, node_indices, best_feature)

    # continue splitting the left and the right child. Increment current depth
    build_tree_recursive(X, y, left_indices, "Left", max_depth, current_depth+1)
    build_tree_recursive(X, y, right_indices, "Right", max_depth, current_depth+1)
build_tree_recursive(X_train, y_train, root_indices, "Root", max_depth=2, current_depth=0)
 Depth 0, Root: Split on feature: 2
- Depth 1, Left: Split on feature: 0
  -- Left leaf node with indices [0, 1, 4, 7]
  -- Right leaf node with indices [5]
- Depth 1, Right: Split on feature: 1
  -- Left leaf node with indices [8]
  -- Right leaf node with indices [2, 3, 6, 9]

추천

출처blog.csdn.net/fayoung3568/article/details/131196724