Skip to content

huang104160/decision-tree-algorithm

Repository files navigation

decision tree algorithm

决策树代码简单实现


前言

产生本文的缘由

大三时,居然要来写大一的课设,倒霉透了,简单的又不想写,难点的,也就这个了,唉。


以下是本篇文章正文内容

一、决策树例子

1.假设

对于一个天气系统,假设我们有天况 温度 湿度 风况 四个参数,每个参数对应于不同的情况。
==天况对应于 晴 多云 雨 晴 多云 雨 分别对应于 1 2 3
分类结果中 Y表示好天气 N表示坏天气==

1	天况  晴  多云  雨   1 2 3
2	温度  热 中  冷      1 2 3
3	湿度  大 正常        1 2
4	风况  无 有          1 2
	分类  N   Y          0 1

2.训练集

在这里插入图片描述 在这里插入图片描述 对应的数据如下:
天况 温度 湿度 风况 分类结果==分别对应右侧5列==

data_01:	1	1	1	1	0
data_02:	1	1	1	2	0
data_03:	2	1	1	1	1
data_04:	3	2	1	1	1
data_05:	3	3	2	1	1
data_06:	3	3	2	2	0
data_07:	2	3	2	2	1
data_08:	1	2	1	1	0
data_09:	1	3	2	1	1
data_10:	3	2	2	1	1
data_11:	1	2	2	2	1
data_12:	2	2	1	2	1
data_13:	2	1	2	1	1
data_14:	3	2	1	2	0

3.决策树

下面就是一颗经过仅仅只有16个样本,训练得到的决策树。 在这里插入图片描述


4.由决策树进行测试案例

比如说,我们拿训练集的第一条数据进行测试: 在这里插入图片描述 首先,根节点是1,就看天况,是晴天 那么就从==1号节点,由分支1,走到3号节点==

然后,此时的根节点是3,就看湿度,是大 那么就从==3号节点,由分支1,找到分类结果0,也就是分类为N==

可以看出,咱的决策树很牛逼,分类是正确的。


二、关键公式和代码

1.原理

原理
决策树通过使用称为 信息增益的统计属性 来决定当前节点的最佳属性。
增益是衡量给定属性将训练示例分离到各自目标类的程度。
增益最高的被选中,增益越高,树就越短。
为了定义增益,首先定义
熵是属性中可用信息量的度量。

2.熵

公式 Entropy(S) = - ∑ ( p(i) * log2 p(i) )

代码实现

// 返回与特定属性的给定attrval匹配的行数
// 例如 v是数据集 attrnum 是天况  	attrval 是 天况可能的类型 晴
vector<vector<int>> newDataSet(vector<vector<int>> &v, int attrnum, int attrval)
{
	vector<vector<int>> dstemp;
	for (int i = 0; i < v.size(); ++i)
	{
		if (v[i][attrnum] == attrval)
		{
			dstemp.push_back(v[i]); // 保存对应的训练项
		}
	}
	return dstemp;
}

// 计算一个特定集合的熵
// Entropy(S) =  - ∑ (p(i) * log2 p(i))    i~[0-1],两种分类情况
float calcEntropy(vector<vector<int>> &v)
{

	float e = 0;
	// 在v初始化的时候,v[0]表示分类
	// newDataSet(v, 0, 0),其实是对应于newDataSet(v, 分类 , 0)
	float a0 = newDataSet(v, 0, 0).size(); // 后续计算(p(0) * log2 p(0))中的p0的分子 , 表示v中分类为0的项数

	// newDataSet(v, 0, 1),其实是对应于newDataSet(v, 分类 , 1)
	float a1 = newDataSet(v, 0, 1).size(); // 后续计算(p(1) * log2 p(1))中的p1的分子 , 表示v中分类为1的项数

	//一般情况下 a0 + a1 == v.size()
	if (a0 == 0 || a1 == 0)
		return 0;
	e = -(((a0 / v.size()) * (log(a0 / v.size()) / log(2))) + ((a1 / v.size()) * (log(a1 / v.size()) / log(2))));
	return e; // Entropy(S) =  - ∑ (p(i) * log2 p(i))
}

3.增益

公式 Gain(S, A) = Entropy(S) - ∑((|Sv| / |S|) * Entropy(Sv)

代码实现

float calcGain(vector<vector<int>> &v, int attrnum)
{
	float g;
	float calc = 0;
	vector<vector<int>> ds1;
	for (int i = 1; i <= attrs_new[attrnum].size(); ++i)
	{
		// ds1中包含了传过来的训练集中v的所有与attrnum相关的i的属性的训练项
		/*
		例如:
			newDataSet(v, 1 , 1)
			即为
			newDataSet(v, 天况 , 1)

			下面是传过来的v
			分类 天况 温度 湿度 风况
			0	1	1	1	1
			0	1	1	1	2
			1	2	1	1	1

			那么ds1就是只包含下面两项,因为天况对应的第三项是2,不是1
			0	1	1	1	1
			0	1	1	1	2
		*/
		ds1 = newDataSet(v, attrnum, i); // Sv
		float gaina = ds1.size();		 //   |Sv|
		float ab = calcEntropy(ds1);	 //  Entropy(Sv)
		calc += (gaina / v.size()) * ab; // ∑((|Sv| / |S|) * Entropy(Sv)
	}
	g = calcEntropy(v) - calc; // Gain(S, A) = Entropy(S) - ∑((|Sv| / |S|) * Entropy(Sv)
	return g;
}

三、决策树超形象示例

如下图,很清晰

在这里插入图片描述 在这里插入图片描述 在这里插入图片描述

四、决策树预测

在这里插入图片描述 预测初始文件:

  测试集的文件输入到二维向量中类似但是predictingdata.txt中的分类结果默认为N也就是最右边的列全0后期调用predict函数预测时写入到output-pre.txt文件中

data_01:	1	1	2	1	0
data_02:	1	1	2	2	0
data_03:	3	1	2	1	0
data_04:	1	2	2	1	0
data_05:	1	3	1	2	0
data_06:	1	3	1	1	0

成功预测文件:

data_01:	1	1	2	1	Y
data_02:	1	1	2	2	Y
data_03:	3	1	2	1	Y
data_04:	1	2	2	1	Y
data_05:	1	3	1	2	N
data_06:	1	3	1	1	N

About

决策树代码简单实现

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy