
优点:计算复杂度不高,输出结果易于理解,对中间值缺失不敏感,可以处理不相关特征数据。
缺点:可能会产生过度匹配问题。
适用数据类型:数值型和标称型。
1.信息增益
划分数据集的目的是:将无序的数据变得更加有序。组织杂乱无章数据的一种方法就是使用信息论度量信息。通常采用信息增益,信息增益是指数据划分前后信息熵的减少值。信息越无序信息熵越大,获得信息增益最高的特征就是最好的选择。
熵定义为信息的期望,符号xi的信息定义为:
其中p(xi)为该分类的概率。
熵,即信息的期望值为:
计算信息熵的代码如下:
def calcShannonEnt(dataSet):
numEntries = len(dataSet)
labelCounts = {}
for featVec in dataSet:
currentLabel = featVec[-1]
if currentLabel not in labelCounts:
labelCounts[currentLabel] = 0
labelCounts[currentLabel] += 1
shannonEnt = 0
for key in labelCounts:
shannonEnt = shannonEnt - (labelCounts[key]/numEntries)*math.log2(labelCounts[key]/numEntries)
return shannonEnt
可以根据信息熵,按照获取最大信息增益的方法划分数据集。
2.划分数据集
划分数据集就是将所有符合要求的元素抽出来。
def splitDataSet(dataSet,axis,value):
retDataset = []
for featVec in dataSet:
if featVec[axis] == value:
newVec = featVec[:axis]
newVec.extend(featVec[axis+1:])
retDataset.append(newVec)
return retDataset
3.选择最好的数据集划分方式
信息增益是熵的减少或者是信息无序度的减少。
def chooseBestFeatureToSplit(dataSet):
numFeatures = len(dataSet[0]) - 1
bestInfoGain = 0
bestFeature = -1
baseEntropy = calcShannonEnt(dataSet)
for i in range(numFeatures):
allValue = [example[i] for example in dataSet]#列表推倒,创建新的列表
allValue = set(allValue)#最快得到列表中唯一元素值的方法
newEntropy = 0
for value in allValue:
splitset = splitDataSet(dataSet,i,value)
newEntropy = newEntropy + len(splitset)/len(dataSet)*calcShannonEnt(splitset)
infoGain = baseEntropy - newEntropy
if infoGain > bestInfoGain:
bestInfoGain = infoGain
bestFeature = i
return bestFeature
4.递归创建决策树
结束条件为:程序遍历完所有划分数据集的属性,或每个分支下的所有实例都具有相同的分类。
当数据集已经处理了所有属性,但是类标签还不唯一时,采用多数表决的方式决定叶子节点的类型。
def majorityCnt(classList):
classCount = {}
for value in classList:
if value not in classCount: classCount[value] = 0
classCount[value] += 1
classCount = sorted(classCount.items(),key=operator.itemgetter(1),reverse=True)
return classCount[0][0]
生成决策树:
def createTree(dataSet,labels):
classList = [example[-1] for example in dataSet]
labelsCopy = labels[:]
if classList.count(classList[0]) == len(classList):
return classList[0]
if len(dataSet[0]) == 1:
return majorityCnt(classList)
bestFeature = chooseBestFeatureToSplit(dataSet)
bestLabel = labelsCopy[bestFeature]
myTree = {bestLabel:{}}
featureValues = [example[bestFeature] for example in dataSet]
featureValues = set(featureValues)
del(labelsCopy[bestFeature])
for value in featureValues:
subLabels = labelsCopy[:]
myTree[bestLabel][value] = createTree(splitDataSet(dataSet,bestFeature,value),subLabels)
return myTree
5.测试算法——使用决策树分类
同样采用递归的方式得到分类结果。
def classify(inputTree,featLabels,testVec):
currentFeat = list(inputTree.keys())[0]
secondTree = inputTree[currentFeat]
try:
featureIndex = featLabels.index(currentFeat)
except ValueError as err:
print('yes')
try:
for value in secondTree.keys():
if value == testVec[featureIndex]:
if type(secondTree[value]).__name__ == 'dict':
classLabel = classify(secondTree[value],featLabels,testVec)
else:
classLabel = secondTree[value]
return classLabel
except AttributeError:
print(secondTree)
6.完整代码如下
import numpy as np
import math
import operator
def createDataSet():
dataSet = [[1,1,'yes'],
[1,1,'yes'],
[1,0,'no'],
[0,1,'no'],
[0,1,'no'],]
label = ['no surfacing','flippers']
return dataSet,label
def calcShannonEnt(dataSet):
numEntries = len(dataSet)
labelCounts = {}
for featVec in dataSet:
currentLabel = featVec[-1]
if currentLabel not in labelCounts:
labelCounts[currentLabel] = 0
labelCounts[currentLabel] += 1
shannonEnt = 0
for key in labelCounts:
shannonEnt = shannonEnt - (labelCounts[key]/numEntries)*math.log2(labelCounts[key]/numEntries)
return shannonEnt
def splitDataSet(dataSet,axis,value):
retDataset = []
for featVec in dataSet:
if featVec[axis] == value:
newVec = featVec[:axis]
newVec.extend(featVec[axis+1:])
retDataset.append(newVec)
return retDataset
def chooseBestFeatureToSplit(dataSet):
numFeatures = len(dataSet[0]) - 1
bestInfoGain = 0
bestFeature = -1
baseEntropy = calcShannonEnt(dataSet)
for i in range(numFeatures):
allValue = [example[i] for example in dataSet]
allValue = set(allValue)
newEntropy = 0
for value in allValue:
splitset = splitDataSet(dataSet,i,value)
newEntropy = newEntropy + len(splitset)/len(dataSet)*calcShannonEnt(splitset)
infoGain = baseEntropy - newEntropy
if infoGain > bestInfoGain:
bestInfoGain = infoGain
bestFeature = i
return bestFeature
def majorityCnt(classList):
classCount = {}
for value in classList:
if value not in classCount: classCount[value] = 0
classCount[value] += 1
classCount = sorted(classCount.items(),key=operator.itemgetter(1),reverse=True)
return classCount[0][0]
def createTree(dataSet,labels):
classList = [example[-1] for example in dataSet]
labelsCopy = labels[:]
if classList.count(classList[0]) == len(classList):
return classList[0]
if len(dataSet[0]) == 1:
return majorityCnt(classList)
bestFeature = chooseBestFeatureToSplit(dataSet)
bestLabel = labelsCopy[bestFeature]
myTree = {bestLabel:{}}
featureValues = [example[bestFeature] for example in dataSet]
featureValues = set(featureValues)
del(labelsCopy[bestFeature])
for value in featureValues:
subLabels = labelsCopy[:]
myTree[bestLabel][value] = createTree(splitDataSet(dataSet,bestFeature,value),subLabels)
return myTree
def classify(inputTree,featLabels,testVec):
currentFeat = list(inputTree.keys())[0]
secondTree = inputTree[currentFeat]
try:
featureIndex = featLabels.index(currentFeat)
except ValueError as err:
print('yes')
try:
for value in secondTree.keys():
if value == testVec[featureIndex]:
if type(secondTree[value]).__name__ == 'dict':
classLabel = classify(secondTree[value],featLabels,testVec)
else:
classLabel = secondTree[value]
return classLabel
except AttributeError:
print(secondTree)
if __name__ == "__main__":
dataset,label = createDataSet()
myTree = createTree(dataset,label)
a = [1,1]
print(classify(myTree,label,a))
7.编程技巧
extend与append的区别
newVec.extend(featVec[axis+1:])
retDataset.append(newVec)
extend([]),是将列表中的每个元素依次加入新列表中
append()是将括号中的内容当做一项加入到新列表中
列表推到
创建新列表的方式
allValue = [example[i] for example in dataSet]
提取列表中唯一的元素
allValue = set(allValue)
列表/元组排序,sorted()函数
classCount = sorted(classCount.items(),key=operator.itemgetter(1),reverse=True)
列表的复制
labelsCopy = labels[:]
以上就是本文的全部内容,希望对大家的学习有所帮助.
数据分析咨询请扫描二维码
若不方便扫码,搜微信号:CDAshujufenxi
在数据成为新时代“石油”的今天,几乎每个职场人都在焦虑: “为什么别人能用数据驱动决策、升职加薪,而我面对Excel表格却无从 ...
2025-10-18数据清洗是 “数据价值挖掘的前置关卡”—— 其核心目标是 “去除噪声、修正错误、规范格式”,但前提是不破坏数据的真实业务含 ...
2025-10-17在数据汇总分析中,透视表凭借灵活的字段重组能力成为核心工具,但原始透视表仅能呈现数值结果,缺乏对数据背景、异常原因或业务 ...
2025-10-17在企业管理中,“凭经验定策略” 的传统模式正逐渐失效 —— 金融机构靠 “研究员主观判断” 选股可能错失收益,电商靠 “运营拍 ...
2025-10-17在数据库日常操作中,INSERT INTO SELECT是实现 “批量数据迁移” 的核心 SQL 语句 —— 它能直接将一个表(或查询结果集)的数 ...
2025-10-16在机器学习建模中,“参数” 是决定模型效果的关键变量 —— 无论是线性回归的系数、随机森林的树深度,还是神经网络的权重,这 ...
2025-10-16在数字化浪潮中,“数据” 已从 “辅助决策的工具” 升级为 “驱动业务的核心资产”—— 电商平台靠用户行为数据优化推荐算法, ...
2025-10-16在大模型从实验室走向生产环境的过程中,“稳定性” 是决定其能否实用的关键 —— 一个在单轮测试中表现优异的模型,若在高并发 ...
2025-10-15在机器学习入门领域,“鸢尾花数据集(Iris Dataset)” 是理解 “特征值” 与 “目标值” 的最佳案例 —— 它结构清晰、维度适 ...
2025-10-15在数据驱动的业务场景中,零散的指标(如 “GMV”“复购率”)就像 “散落的零件”,无法支撑系统性决策;而科学的指标体系,则 ...
2025-10-15在神经网络模型设计中,“隐藏层层数” 是决定模型能力与效率的核心参数之一 —— 层数过少,模型可能 “欠拟合”(无法捕捉数据 ...
2025-10-14在数字化浪潮中,数据分析师已成为企业 “从数据中挖掘价值” 的核心角色 —— 他们既要能从海量数据中提取有效信息,又要能将分 ...
2025-10-14在企业数据驱动的实践中,“指标混乱” 是最常见的痛点:运营部门说 “复购率 15%”,产品部门说 “复购率 8%”,实则是两者对 ...
2025-10-14在手游行业,“次日留存率” 是衡量一款游戏生死的 “第一道关卡”—— 它不仅反映了玩家对游戏的初始接受度,更直接决定了后续 ...
2025-10-13分库分表,为何而生? 在信息技术发展的早期阶段,数据量相对较小,业务逻辑也较为简单,单库单表的数据库架构就能够满足大多数 ...
2025-10-13在企业数字化转型过程中,“数据孤岛” 是普遍面临的痛点:用户数据散落在 APP 日志、注册系统、客服记录中,订单数据分散在交易 ...
2025-10-13在数字化时代,用户的每一次行为 —— 从电商平台的 “浏览→加购→购买”,到视频 APP 的 “打开→搜索→观看→收藏”,再到银 ...
2025-10-11在机器学习建模流程中,“特征重要性分析” 是连接 “数据” 与 “业务” 的关键桥梁 —— 它不仅能帮我们筛选冗余特征、提升模 ...
2025-10-11在企业的数据体系中,未经分类的数据如同 “杂乱无章的仓库”—— 用户行为日志、订单记录、商品信息混杂存储,CDA(Certified D ...
2025-10-11在 SQL Server 数据库操作中,“数据类型转换” 是高频需求 —— 无论是将字符串格式的日期转为datetime用于筛选,还是将数值转 ...
2025-10-10