ToB企服应用市场:ToB评测及商务社交产业平台

标题: 相识大数据中的决策树 [打印本页]

作者: 怀念夏天    时间: 2024-11-19 18:22
标题: 相识大数据中的决策树
目次
前言
一、决策树原理及构建
原理
构建步调

二、决策树的典范算法
ID3算法
C4.5算法
CART算法
三.决策树的算法实现示例
ID3算法代码示例
C4.5算法代码示例
CART算法代码示例(回归树)
总结








前言

决策树(Decision Tree)是一种类似于流程图的树形结构,每个内部节点表现在一个属性上的测试,每个分支代表一个属性输出,而每个叶节点代表类或类分布。决策树通过树状结构,基于数据特性与目标变量之间的关系,将数据集划分为不同的子集,以逐步构建决策规则。其工作原理是从根节点开始,根据输入特性的取值,沿着相应的分支向下移动,直到到达一个叶节点,叶节点的值即为终极分类或预测效果,递归地选择最优特性进行分裂,构建出完整的决策树。

一、决策树原理及构建

原理

决策树的概念泉源于统计学和决策论,能够直观地模拟人类的决策过程。它通过递归地将数据集划分为多个子集,形成树状结构,以表现数据的分布和分类规则。每个内部节点代表一个特性的决策,每个叶子节点则是决策效果(分类或回归值)。决策树的构建主要基于“信息增益”(Information Gain)或“基尼不纯度”(Gini Impurity)等指标。其核心思想是逐步选择最佳的特性来划分数据集,从而构建出能够最好地分类或回归的树。
信息增益:表现某个特性对分类效果的不确定性的淘汰量。信息增益越大,表现该特性越能有效淘汰不确定性,从而更好地划分数据。
基尼不纯度:用于衡量一个数据集在某特性下的不纯度。基尼不纯度越低,数据集越“纯”。
构建步调

决策树的构建过程是一个递归选择最优特性,并根据特性的不同取值对数据进行划分的过程,直到满足停止条件为止。以下是构建步调:
①预备数据:将数据集划分成练习集和测试集,进行缺失值处理和特性选择。
②选择最优特性:对于数据集中的每个特性,盘算其对数据集的信息增益或基尼不纯度,选择信息增益最大或基尼不纯度最小的特性作为本次分类的特性。
③划分数据集:根据选择的特性,将数据集划分成若干子集,每个子集包含特性一致的一部分数据。
④递归构建决策树:对于每个子集,重复上述选择最优特性和划分数据集的过程,直到子集中的数据属于同一类别或者到达肯定的停止条件为止。常见的停止条件包括:所有样本属于同一类别、特性集为空、或者样本数量小于预设的阈值。
⑤测试模型:将测试集中的数据输入到构建好的模型中,盘算模型的分类准确度和召回率等评估指标。
⑥优化模型:对于分类错误的样本,可以通过调整参数(如决策树的最大深度、最小样本数等)和增加样原来优化模型。此外,为了防止决策树过拟合,还可以进行剪枝操作,即去除不须要的分支,保留告急的决策节点,从而进步模型的泛化能力。



二、决策树的典范算法

ID3算法

概念:ID3(Iterative Dichotomiser 3)算法是决策树学习算法的一种经典方法,它根据信息增益来选择每个节点的分裂属性。

C4.5算法


CART算法


ID3、C4.5和CART是决策树的典范算法,它们各有特点,适用于不同的应用场景。在现实应用中,可以根据详细问题的需求和数据的特性选择合适的算法。
三.决策树的算法实现示例

ID3算法代码示例

  1. import numpy as np  
  2. from collections import Counter  
  3.   
  4. class DecisionTree:  
  5.     class Node:  
  6.         def __init__(self):  
  7.             self.value = None  # 内部叶节点属性  
  8.             self.feature_index = None  
  9.             self.children = {}  
  10.   
  11.         def __str__(self):  
  12.             if self.children:  
  13.                 s = '内部节点<%s>:\n' % self.feature_index  
  14.                 for fv, node in self.children.items():  
  15.                     ss = '[%s]-> %s' % (fv, node)  
  16.                     s += '\t' + ss.replace('\n', '\n\t') + '\n'  
  17.                 s = s[:-1]  
  18.             else:  
  19.                 s = '叶节点(%s)' % self.value  
  20.             return s  
  21.   
  22.     def __init__(self, gain_threshold=1e-2):  # 信息增益阈值  
  23.         self.gain_threshold = gain_threshold  
  24.   
  25.     def _entropy(self, y):  # 熵: -sum(pi*log(pi))  
  26.         c = np.bincount(y)  
  27.         p = c[np.nonzero(c)] / y.size  
  28.         return -np.sum(p * np.log2(p))  
  29.   
  30.     def _conditional_entropy(self, feature, y):  # 条件熵  
  31.         feature_values = np.unique(feature)  
  32.         h = 0.  
  33.         for v in feature_values:  
  34.             y_sub = y[feature == v]  
  35.             p = y_sub.size / y.size  
  36.             h += p * self._entropy(y_sub)  
  37.         return h  
  38.   
  39.     def _information_gain(self, feature, y):  # 信息增益 = 经验熵 - 经验条件熵  
  40.         return self._entropy(y) - self._conditional_entropy(feature, y)  
  41.   
  42.     def _select_feature(self, X, y, features_list):  # 选择信息增益最大特征  
  43.         if features_list:  
  44.             gains = np.apply_along_axis(self._information_gain, 0, X[:, features_list], y)  
  45.             index = np.argmax(gains)  
  46.             if gains[index] > self.gain_threshold:  
  47.                 return index  
  48.         return None  
  49.   
  50.     def _create_tree(self, X, y, features_list):  # 创建节点  
  51.         node = DecisionTree.Node()  
  52.         labels_count = np.bincount(y)  
  53.         node.value = np.argmax(labels_count)  # 节点值总等于数据集中样本最多的类标记  
  54.   
  55.         if np.count_nonzero(labels_count) != 1:  # 判断类标记是否全部一致  
  56.             index = self._select_feature(X, y, features_list)  
  57.             if index is not None:  
  58.                 node.feature_index = features_list.pop(index)  
  59.                 feature_values = np.unique(X[:, node.feature_index])  
  60.                 for v in feature_values:  
  61.                     idx = X[:, node.feature_index] == v  
  62.                     X_sub, y_sub = X[idx], y[idx]  
  63.                     node.children[v] = self._create_tree(X_sub, y_sub, features_list.copy())  
  64.         return node  
  65.   
  66.     def train(self, X_train, y_train):  # 训练决策树  
  67.         _, n = X_train.shape  
  68.         self.tree_ = self._create_tree(X_train, y_train, list(range(n)))  
  69.   
  70.     def predict(self, X_test):  # 对每一个测试样本, 调用_predict_one, 将收集到的结果数组返回  
  71.         return np.apply_along_axis(self._predict_one, axis=1, arr=X_test)  
  72.   
  73.     def _predict_one(self, x_test):  # 搜索决策树, 对单个样本进行预测  
  74.         node = self.tree_  
  75.         while node.children:  
  76.             child = node.children.get(x_test[node.feature_index])  
  77.             if not child:  
  78.                 break  
  79.             node = child  
  80.         return node.value  
  81.   
  82.     def __str__(self):  
  83.         if hasattr(self, 'tree_'):  
  84.             return str(self.tree_)  
  85.         return ''  
  86.   
  87. # 使用示例数据集进行分类  
  88. # 数据集加载和数据预处理部分略...  
  89. # 假设X_train和y_train是已经准备好的训练数据集  
  90. # 假设X_test是待预测的测试数据集  
  91.   
  92. tree = DecisionTree()  
  93. tree.train(X_train, y_train)  
  94. predictions = tree.predict(X_test)  
  95. print(predictions)
复制代码
C4.5算法代码示例

  1. import numpy as np  
  2. from collections import Counter  
  3.   
  4. def calc_entropy(labels):  
  5.     counter = Counter(labels)  
  6.     probs = [counter[c] / len(labels) for c in counter]  
  7.     entropy = -np.sum(probs * np.log2(probs))  
  8.     return entropy  
  9.   
  10. def calc_info_gain(data, labels, feature_idx):  
  11.     feature_values = set(data[:, feature_idx])  
  12.     entropy_before = calc_entropy(labels)  
  13.     gain = entropy_before  
  14.     for value in feature_values:  
  15.         subset = data[data[:, feature_idx] == value]  
  16.         subset_labels = labels[data[:, feature_idx] == value]  
  17.         weight = len(subset_labels) / len(labels)  
  18.         gain -= weight * calc_entropy(subset_labels)  
  19.     return gain  
  20.   
  21. def choose_best_feature(data, labels):  
  22.     num_features = data.shape[1]  
  23.     best_feature = None  
  24.     best_gain = 0  
  25.     for i in range(num_features):  
  26.         info_gain = calc_info_gain(data, labels, i)  
  27.         if info_gain > best_gain:  
  28.             best_gain = info_gain  
  29.             best_feature = i  
  30.     return best_feature  
  31.   
  32. def create_decision_tree(data, labels):  
  33.     if len(set(labels)) == 1:  
  34.         return labels[0]  
  35.     if data.shape[1] == 0:  
  36.         return Counter(labels).most_common(1)[0][0]  
  37.     best_feature = choose_best_feature(data, labels)  
  38.     tree = {best_feature: {}}  
  39.     feature_values = set(data[:, best_feature])  
  40.     for value in feature_values:  
  41.         subset = data[data[:, best_feature] == value]  
  42.         subset_labels = labels[data[:, best_feature] == value]  
  43.         tree[best_feature][value] = create_decision_tree(subset, subset_labels)  
  44.     return tree  
  45.   
  46. # 使用示例数据集进行分类  
  47. data = np.array([[1, 1, 1], [1, 1, 0], [0, 1, 1], [0, 0, 1]])  
  48. labels = np.array([1, 1, 0, 0])  
  49. decision_tree = create_decision_tree(data, labels)  
  50. print(decision_tree)
复制代码
CART算法代码示例(回归树)

  1. import numpy as np  
  2. import pickle  
  3. import matplotlib.pyplot as plt  
  4. from sklearn.datasets import load_boston  
  5.   
  6. def loadDataSet(fileName):  
  7.     dataMat = []  
  8.     fr = open(fileName)  
  9.     for line in fr.readlines():  
  10.         curLine = line.strip().split('\t')  
  11.         fltLine = list(map(float, curLine))  
  12.         dataMat.append(fltLine)  
  13.     return dataMat  
  14.   
  15. def binSplitDataSet(dataSet, feature, value):  
  16.     mat0 = dataSet[dataSet[:, feature] > value]  
  17.     mat1 = dataSet[dataSet[:, feature] <= value]  
  18.     return mat0, mat1  
  19.   
  20. def regLeaf(dataSet):  
  21.     return np.mean(dataSet[:, -1])  
  22.   
  23. def regErr(dataSet):  
  24.     return np.var(dataSet[:, -1]) * len(dataSet)  
  25.   
  26. def chooseBestSplit(dataSet, leafType=regLeaf, errType=regErr, ops=(1, 4)):  
  27.     tolS = ops[0]; tolN = ops[1]  
  28.     if len(set(dataSet[:, -1].T.tolist()[0])) == 1:  
  29.         return None, leafType(dataSet)  
  30.     m, n = dataSet.shape  
  31.     S = errType(dataSet)  
  32.     bestS = float('inf'); bestIndex = 0; bestValue = 0  
  33.     for featIndex in range(n - 1):  
  34.         for splitVal in set(dataSet[:, featIndex].T.A.tolist()[0]):  
  35.             mat0, mat1 = binSplitDataSet(dataSet,
复制代码
总结

大数据决策树是一种基于树形结构的机器学习算法,特殊适用于处理和分析大规模数据集。它通过递归地将数据集分割成更小的子集,以构建出一个类似于树状的预测模型。在树的每个节点上,算法会根据某个特性属性的值来判断数据应该流向哪个分支,直到到达叶子节点,给出终极的预测效果或分类标签。
大数据决策树的上风在于其直观易懂、易于实现,而且能够有效地处理高维数据和具有缺失值的数据集。此外,它还能够自动进行特性选择和交互效应的辨认,为决策过程提供有价值的洞察。然而,随着数据量的增加,决策树可能会变得过于复杂,导致过拟合问题。因此,在现实应用中,常需要结合剪枝、集成学习等技能来优化模型性能。
总之,大数据决策树是一种强大且灵活的工具,能够帮助我们从海量数据中挖掘出有价值的规律和模式,为决策提供有力支持。


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4