이해하기 쉬운 기계 학습 - Python은 간단한 의사 결정 트리를 수동으로 구현합니다.

이 글은 금창조의 길을 시작하는 '신인창조식' 행사에 참여하게 되었습니다.

소개

의사 결정 트리는 머신 러닝의 일반적인 알고리즘 모델입니다.이 기사에서는 간단한 이산 간격 분류 문제에서 의사 결정 트리의 설정 프로세스를 분석하고 파이썬을 사용하여 간단한 의사 결정 트리를 수동으로 구현합니다.

배경

이 예제는 인터뷰를 배경으로 985인지 여부, 교육 및 프로그래밍 언어의 세 가지 지표를 선택하여 입학 가능 여부를 판단합니다.

의사결정 트리 구축 프로세스

1) 지표 목록에 모든 지표 추가

2) 인덱스 목록에 있는 각 인덱스의 엔트로피를 계산하고 엔트로피가 가장 작은 인덱스에 따라 나눕니다.

3) 성공적으로 분할될 수 있으면 결과를 직접 가져오고, 그렇지 않으면 지표 목록에서 지표를 제거하고 2)단계를 수행하고 결과를 의사결정 트리에 추가합니다.

참고: 이 기사에서는 사전을 사용하여 트리(다중 포크 트리)의 구조를 나타냅니다.

종속성 패키지

import numpy as np
from collections import Counter
from math import log2
复制代码

손실 계산

정보 엔트로피

def entropy(y_label):
    counter = Counter(y_label)
    ent = 0.0
    for num in counter.values():
        p = num / len(y_label)
        ent += -p * log2(p)
    return ent
复制代码

여기서 정보 엔트로피를 사용하는 것 외에도 지니 계수를 대신 사용할 수도 있습니다.

지니계수

def geni(y_label):
    counter = Counter(y_label)
    g = 1
    for num in counter.values():
        p = num / len(y_label)
        g -= p * p
    return g
复制代码

의사 결정 트리 정의

class DecisionTree:
    def __init__(self):
        self.tree = {}
    #训练决策树
    def fit(self,X,y):
        cols = list(range(X.shape[1]))
        #对X得每一列数据,计算分割后得信息熵
        self.tree = self._genTree(cols, X, y)
    #递归生成决策树

    def _genTree(self, cols, X, y):
        # 计算最小信息熵得特征
        imin = cols[0] # 最下熵得列
        emin = 100 # 最小熵值
        for i in cols:
            coli = X[:,i]#拿到第i个特征数据
            enti = sum([entropy(y[coli==d]) for d in set(coli)]) # (也可以使用基尼系数计算,下同)
            if enti < emin:
                imin = i
                emin = enti
        #根据最小熵特征有几个值,就生成几个新的子树分支   
        newtree={}
        mincol = X[:,imin]
        cols.remove(imin)
        #针对这个特征得每个值,进一步划分树
        for d in set(mincol):
            entd = entropy(y[mincol==d])  # 计算信息熵
            if entd <1e-10:#已经完全分开
                newtree[d] = y[mincol==d][0]
            else:#还需要进一步细分
                newtree[d] = self._genTree(cols.copy(), X[mincol==d, :], y[mincol==d])
        return {imin: newtree}#将列号作为索引,返回新生成的树

    #预测新样本
    def predict(self, X):
        X = X.tolist()
        y = [None for i in range(len(X))]
        for i in range(len(X)):
            predictDict = self.tree
            while predictDict != 'Yes' and predictDict != 'No':
                col = list(predictDict.keys())[0]
                predictDict = predictDict[col]
                predictDict = predictDict[X[i][col]]
            else:
                y[i] = predictDict
        return y
复制代码

테스트

X=np.array([['Yes985','本科','C++'],
            ['Yes985','本科','Java'],
            ['No985' ,'硕士','Java'],
            ['No985' ,'硕士','C++'],
            ['Yes985','本科','Java'],
            ['No985' ,'硕士','C++'],
            ['Yes985','硕士','Java'],
            ['Yes985','博士','C++'],
            ['No985' ,'博士','Java'],
            ['No985' ,'本科','Java']])
y=np.array(['No','Yes','Yes','No','Yes','No','Yes','Yes','Yes','No'])

dt = DecisionTree()
dt.fit(X, y)
print(dt.tree)
print(dt.predict(X))
复制代码

시험 결과훈련 데이터에 대한 테스트 결과가 매우 좋은 것을 알 수 있으며, 일부 데이터를 생성하여 직접 테스트할 수 있습니다.

코드 설명

엔트로피 함수: 정보 엔트로피를 계산하는 데 사용됩니다. 여기서 Counter는 다른 범주의 수를 계산하는 데 사용되며 각 범주의 수를 전체 수로 나누어 확률을 구한 다음 정보 엔트로피는 확률로 계산합니다. DecisonTree.fit: 모델 학습을 위해 이 함수에서 트리의 루트 노드를 설정합니다. DecisonTree._genTree: 트리를 빌드합니다. 빌드 프로세스는 위에서 설명한 대로입니다. DecisonTree.predict: 예측을 합니다. 의사결정 트리에서 마지막 예측 결과만 리프 노드입니다. 예측 프로세스: 1) 지표 선택 2) 선택한 지표에 따라 지표의 하위 노드 및 데이터에 해당하는 값에 따라 새로운 하위 노드를 설정하고 선택합니다. 3) 하위 노드가 지시자, 지시자를 이용하여 과정 2)를 반복하고, 서브노드가 지시자일 때 지시자를 이용하여 과정 2)를 반복한다. 노드가 예측 결과일 때 예측이 종료된다

рекомендация

отjuejin.im/post/7077352935834779685