决策树 value_大数据算法之决策树(ID3实现)

421a7fe0d67a23d1822c159bc6fef8e0.png

决策树就是一步步做出决策,然后到达相应的叶子节点。(有点简略。。。之后填坑)

相关知识:

  • 信息熵
  • 条件熵
  • 信息增益
import numpy as np

# 计算熵
def calcInfoEntropy(label):
    '''
    input:
        label(narray):样本标签
    output:
        InfoEntropy(float):熵
    '''
    sv = {}
    for v in label:
        if v in sv:
            sv[v] += 1
        else:
            sv[v] = 1
    InfoEntropy = 0
    for v in sv:
        InfoEntropy -= (sv[v]/len(label)) *  np.log2( sv[v]/len(label) )
    return InfoEntropy

#计算条件熵
def calcHDA(feature,label,index,value):
    '''
    input:
        feature(ndarray):样本特征
        label(ndarray):样本标签
        index(int):需要使用的特征列索引
        value(int):index所表示的特征列中需要考察的特征值
    output:
        HDA(float):信息熵
    '''
    count = 0
    # sub_feature和sub_label表示根据特征列和特征值分割出的子数据集中的特征和标签
    sub_feature = feature[feature[:,index] == value , :]
    sub_label = label[ feature[:,index] == value ]
    count = feature[feature[:,index] == value , :].shape[0]
    pHA = count / len(feature)
    e = calcInfoEntropy(sub_label)
    HDA = pHA * e
    return HDA


#计算信息增益
def calcInfoGain(feature, label, index):
    '''
    input:
        feature(ndarry):测试用例中字典里的feature
        label(ndarray):测试用例中字典里的label
        index(int):测试用例中字典里的index,即feature部分特征列的索引。该索引指的是feature中第几个特征,如index:0表示使用第一个特征来计算信息增益。
    output:
        InfoGain(float):信息增益
    '''
    base_e = calcInfoEntropy(label)
    f = np.array(feature)
    # 得到指定特征列的值的集合
    f_set = set(f[:, index])
    sum_HDA = 0
    # 计算条件熵
    for value in f_set:
        sum_HDA += calcHDA(feature, label, index, value)
    # 计算信息增益
    InfoGain = base_e - sum_HDA
    return InfoGain

# 获得信息增益最高的特征
def getBestFeature(feature, label):
    '''
    input:
        feature(ndarray):样本特征
        label(ndarray):样本标签
    output:
        best_feature(int):信息增益最高的特征
    '''
    t = ""
    maxn = -100
    for i in range(feature.shape[1]):
        tmp = calcInfoGain(feature , label , i)
        if tmp > maxn:
            t = i
            maxn = tmp
    best_feature = t
    return best_feature

#创建决策树
def createTree(feature, label):
    '''
    input:
        feature(ndarray):训练样本特征
        label(ndarray):训练样本标签
    output:
        tree(dict):决策树模型    
    '''
    # 样本里都是同一个label没必要继续分叉了
    if len(set(list(label))) == 1:
        return label[0]
    # 样本s中只有一个特征或者所有样本的特征都一样的话就看哪个label的票数高
    equ = False
    tmps = []
    for i in feature:
        tmps.append(str(i))
    tmps = np.array(tmps)

    if feature[0].shape[0] == 1 or  tmps[tmps == tmps[0]].shape == tmps.shape :
        return np.where(np.bincount(label) == max(np.bincount(label)))[0]
    # 根据信息增益拿到特征的索引
    bf = getBestFeature(feature  ,label)
    tree = {bf : {}}
    # 拿到bestfeature的所有特征值
    fvalue = list(set(feature[:,bf]))
    # 构建对应特征值的子样本集sub_feature, sub_label
    for v in fvalue:
        sub_feature = feature[ feature[:,bf] == v, : ]
        sub_label = label[ feature[:,bf] == v ]
        # 递归
        tree[bf][v] = createTree(sub_feature , sub_label)
    return tree

def pred(tree , feature):
    if not isinstance(tree , dict):
        return tree
    f = list(tree.keys())[0]
    return pred(tree[ f ][feature[ f ]] , feature)

#决策树分类
def dt_clf(train_feature,train_label,test_feature):
    '''
    input:
        train_feature(ndarray):训练样本特征
        train_label(ndarray):训练样本标签
        test_feature(ndarray):测试样本特征
    output:
        predict(ndarray):测试样本预测标签     
    '''
    #创建决策树
    tree = createTree(train_feature , train_label)
    #根据tree与特征进行分类
    predict = []
    for f in test_feature:
        predict.append( pred(tree , f) )
    return predict
好的,下面是用 Python 实现 ID3 决策树算法的代码示例: ```python import math from collections import Counter def find_entropy(data): """ 计算数据集的信息熵 """ # 统计数据集中每个类别的样本数 class_counts = Counter(data["label"]) # 计算每个类别样本数占总数的比例 class_probs = [class_count / len(data["label"]) for class_count in class_counts.values()] # 计算信息熵 entropy = sum([-class_prob * math.log(class_prob, 2) for class_prob in class_probs]) return entropy def find_best_split(data, features): """ 找到最佳分裂特征和特征值 """ # 计算数据集的信息熵 entropy = find_entropy(data) # 初始化最佳分裂特征和特征值 best_feature, best_value = None, None # 初始化最小信息增益 min_info_gain = float("inf") # 遍历每个特征 for feature in features: # 找到该特征的所有取值 values = set(data[feature]) # 遍历每个取值 for value in values: # 将数据集分成两部分 left_data = data[data[feature] == value] right_data = data[data[feature] != value] # 如果分裂后的数据集不为空 if len(left_data) > 0 and len(right_data) > 0: # 计算分裂后的信息熵 left_entropy = find_entropy(left_data) right_entropy = find_entropy(right_data) split_entropy = (len(left_data) / len(data)) * left_entropy + (len(right_data) / len(data)) * right_entropy # 计算信息增益 info_gain = entropy - split_entropy # 如果信息增益更大,则更新最佳分裂特征和特征值 if info_gain < min_info_gain: best_feature, best_value = feature, value min_info_gain = info_gain # 返回最佳分裂特征和特征值 return best_feature, best_value def build_tree(data, features): """ 构建决策树 """ # 如果数据集为空,则返回 None if len(data) == 0: return None # 如果数据集中所有样本都属于同一类别,则返回该类别 if len(set(data["label"])) == 1: return data["label"].iloc[0] # 如果没有可用特征,则返回数据集中样本数最多的类别 if len(features) == 0: return Counter(data["label"]).most_common(1)[0][0] # 找到最佳分裂特征和特征值 best_feature, best_value = find_best_split(data, features) # 如果信息增益小于等于 0,则返回数据集中样本数最多的类别 if best_feature is None or best_value is None: return Counter(data["label"]).most_common(1)[0][0] # 创建节点 node = {"feature": best_feature, "value": best_value, "left": None, "right": None} # 将数据集分成两部分 left_data = data[data[best_feature] == best_value] right_data = data[data[best_feature] != best_value] # 递归构建左子树和右子树 node["left"] = build_tree(left_data, [feature for feature in features if feature != best_feature]) node["right"] = build_tree(right_data, [feature for feature in features if feature != best_feature]) # 返回节点 return node ``` 该代码实现ID3 决策树算法,其中 `find_entropy` 函数用于计算数据集的信息熵,`find_best_split` 函数用于找到最佳分裂特征和特征值,`build_tree` 函数用于构建决策树
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值