开发者社区> 关爱单身狗> 正文

JS简单实现决策树(ID3算法)

简介: 推荐阅读:ID3算法 wiki决策树算法及实现 完整示例代码:JS简单实现决策树(ID3算法)_demo.html 决策树算法代码实现 1.
+关注继续查看
img_876d970d8d4b0c5624b8cbd30239d9b4.png

推荐阅读:
ID3算法 wiki
决策树算法及实现

完整示例代码:
JS简单实现决策树(ID3算法)_demo.html

决策树算法代码实现

1.准备测试数据

这里我假设公司有个小姐姐相亲见面为例
得到以下是已经见面或被淘汰了的数据(部分数据使用mock.js来生成的):

var data =
        [
            { "姓名": "余夏", "年龄": 29, "长相": "帅", "体型": "瘦", "收入": "高", 见面: "见" },
            { "姓名": "豆豆", "年龄": 25, "长相": "帅", "体型": "瘦", "收入": "高", 见面: "见" },
            { "姓名": "帅常荣", "年龄": 26, "长相": "帅", "体型": "胖", "收入": "高", 见面: "见" },
            { "姓名": "王涛", "年龄": 22, "长相": "帅", "体型": "瘦", "收入": "高", 见面: "见" },
            { "姓名": "李东", "年龄": 23, "长相": "帅", "体型": "瘦", "收入": "高", 见面: "见" },
            { "姓名": "王五五", "年龄": 23, "长相": "帅", "体型": "瘦", "收入": "低", 见面: "见" },
            { "姓名": "王小涛", "年龄": 22, "长相": "帅", "体型": "瘦", "收入": "低", 见面: "见" },
            { "姓名": "李缤", "年龄": 21, "长相": "帅", "体型": "胖", "收入": "高", 见面: "见" },
            { "姓名": "刘明", "年龄": 21, "长相": "帅", "体型": "胖", "收入": "低", 见面: "不见" },
            { "姓名": "红鹤", "年龄": 21, "长相": "不帅", "体型": "胖", "收入": "高", 见面: "不见" },
            { "姓名": "李理", "年龄": 32, "长相": "帅", "体型": "瘦", "收入": "高", 见面: "不见" },
            { "姓名": "周州", "年龄": 31, "长相": "帅", "体型": "瘦", "收入": "高", 见面: "不见" },
            { "姓名": "李乐", "年龄": 27, "长相": "不帅", "体型": "胖", "收入": "高", 见面: "不见" },
            { "姓名": "韩明", "年龄": 24, "长相": "不帅", "体型": "瘦", "收入": "高", 见面: "不见" },
            { "姓名": "小吕", "年龄": 28, "长相": "帅", "体型": "瘦", "收入": "低", 见面: "不见" },
            { "姓名": "李四", "年龄": 25, "长相": "帅", "体型": "瘦", "收入": "低", 见面: "不见" },
            { "姓名": "王鹏", "年龄": 30, "长相": "帅", "体型": "瘦", "收入": "低", 见面: "不见" },
        ];

2.搭建决策树基本函数

代码:

function DecisionTree(config) {
    if (typeof config == "object" && !Array.isArray(config)) this.training(config);
};
DecisionTree.prototype = {
    //分割函数
    _predicates: {},
    //统计属性值在数据集中的次数
    countUniqueValues(items, attr) {},
    //获取对象中值最大的Key  假设 counter={a:9,b:2} 得到 "a" 
    getMaxKey(counter) {},
    //寻找最频繁的特定属性值
    mostFrequentValue(items, attr) {},
    //根据属性切割数据集 
    split(items, attr, predicate, pivot) {},
    //计算熵
    entropy(items, attr) {},
    //生成决策树
    buildDecisionTree(config) {},
    //初始化生成决策树
    training(config) {},
    //预测 测试
    predict(data) {},
};

var decisionTree = new DecisionTree();

3.实现函数功能

由于部分函数过于简单我就不进行讲解了
可前往 JS简单实现决策树(ID3算法)_demo.html查看完整代码
里面包含注释,与每个函数的测试方法

这里的话我主要讲解下:计算熵的函数、生成决策树函数(信息增益)、与预测函数的实现

ID3算法 wiki 中解释了计算熵信息增益的公式

img_2efae1bec3a63509d5e1beb8b3fec9ce.jpe
截图

3.1.计算熵(entropy)函数

根据公式:


img_7417a48f0189e3816498d3e305fafc14.png
公式

我们可以知道计算H(S)(也就是熵)需要得到 p(x)=x/总数量 然后进行计算累加就行了
代码:

//......略
//统计属性值在数据集中的次数
countUniqueValues(items, attr) {
    var counter = {}; // 获取不同的结果值 与出现次数
    for (var i of items) {
        if (!counter[i[attr]]) counter[i[attr]] = 0;
        counter[i[attr]] += 1;
    }
    return counter;
},
//......略
//计算熵
entropy(items, attr) {
    var counter = this.countUniqueValues(items, attr); //计算值的出现数
    var p, entropy = 0; //H(S)=entropy=∑(P(Xi)(log2(P(Xi))))
    for (var i in counter) {
        p = counter[i] / items.length; //P(Xi)概率值
        entropy += -p * Math.log2(p); //entropy+=-(P(Xi)(log2(P(Xi))))
    }
    return entropy;
},
//......略
var decisionTree = new DecisionTree();
console.log("函数 countUniqueValues 测试:");
console.log("   长相", decisionTree.countUniqueValues(data, "长相")); //测试
console.log("   年龄", decisionTree.countUniqueValues(data, "年龄")); //测试
console.log("   收入", decisionTree.countUniqueValues(data, "收入")); //测试
console.log("函数 entropy 测试:");
console.log("   长相", decisionTree.entropy(data, "长相")); //测试
console.log("   年龄", decisionTree.entropy(data, "年龄")); //测试
console.log("   收入", decisionTree.entropy(data, "收入")); //测试
3.2.信息增益
img_b009e09dc33b1a21074149f83cb556d5.png
公式

根据公式我们知道要得到信息增益的值需要得到:

  • H(S) 训练集熵
  • p(t)分支元素的占比
  • H(t)分支数据集的熵

其中t我们就先分 match(合适的)on match(不合适),所以H(t):

  • H(match) 分割后合适的数据集的熵
  • H(on match) 分割后不合适的数据集的熵

所以信息增益G=H(S)-(p(match)H(match)+p(on match)H(on match))
因为p(match)=match数量/数据集总项数量
信息增益G=H(S)-((match数量)xH(match)+(on match数量)xH(on match))/数据集总项数量

//......略
buildDecisionTree(config){
    var trainingSet = config.trainingSet;//训练集 
    var categoryAttr = config.categoryAttr;//用于区分的类别属性
    //......略
    //初始计算 训练集的熵
    var initialEntropy = this.entropy(trainingSet, categoryAttr);//<===H(S)
    //......略
    var alreadyChecked = [];//标识已经计算过了
    var bestSplit = { gain: 0 };//储存当前最佳的分割节点数据信息
    //遍历数据集
    for (var item of trainingSet) {
        // 遍历项中的所有属性
        for (var attr in item) {
            //跳过区分属性与忽略属性
            if ((attr == categoryAttr) || (ignoredAttributes.indexOf(attr) >= 0)) continue;
            var pivot = item[attr];// 当前属性的值 
            var predicateName = ((typeof pivot == 'number') ? '>=' : '=='); //根据数据类型选择判断条件
            var attrPredPivot = attr + predicateName + pivot;
            if (alreadyChecked.indexOf(attrPredPivot) >= 0) continue;//已经计算过则跳过
            alreadyChecked.push(attrPredPivot);//记录
            var predicate = this._predicates[predicateName];//匹配分割方式
            var currSplit = this.split(trainingSet, attr, predicate, pivot);
            var matchEntropy = this.entropy(currSplit.match, categoryAttr);//  H(match) 计算分割后合适的数据集的熵
            var notMatchEntropy = this.entropy(currSplit.notMatch, categoryAttr);// H(on match) 计算分割后不合适的数据集的熵
             //计算信息增益: 
             // IG(A,S)=H(S)-(∑P(t)H(t))) 
             // t为分裂的子集match(匹配),on match(不匹配)
             // P(match)=match的长度/数据集的长度
             // P(on match)=on match的长度/数据集的长度
             var iGain = initialEntropy - ((matchEntropy * currSplit.match.length
                        + notMatchEntropy * currSplit.notMatch.length) / trainingSet.length);
              //不断匹配最佳增益值对应的节点信息
              if (iGain > bestSplit.gain) {
                  //......略
              }
        }
    } 
    //......递归计算分支
}

3.3.预测功能

预测功能的话就只要将要预测的值传入,循环去寻找符合条件的分支,直到找到最后的所属分类为止,这里就不详细解释了
代码:

 //......略
//预测 测试
predict(data) {
    var attr, value, predicate, pivot;
    var tree = this.root;
    while (true) {
        if (tree.category) {
            return tree.category;
        }
        attr = tree.attribute;
        value = data[attr];
        predicate = tree.predicate;
        pivot = tree.pivot;
        if (predicate(value, pivot)) {
            tree = tree.match;
        } else {
            tree = tree.notMatch;
        }
    }
}
//......略

4.最后测试

img_a5b67b4bb67c52863414145317bd7a2a.gif

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
基于Django 框架搭建算法学习系统,包含KNN、ID3、C4.5、SVM、朴素贝叶斯、BP神经网络 毕业设计附完整代码
基于Django 框架搭建算法学习系统,包含KNN、ID3、C4.5、SVM、朴素贝叶斯、BP神经网络 毕业设计附完整代码
24 0
决策树ID3算法和C4.5算法实战
决策树ID3算法和C4.5算法实战
15 0
【机器学习-决策树模块-基础算法-1)ID3算法】
【机器学习-决策树模块-基础算法-1)ID3算法】
37 0
前端开发:JS中关于八皇后算法的使用
在前端开发过程中,关于算法的使用也是非常常见的操作,尤其是处理一些复杂的业务场景,还有就是前端获取到后端返回的复杂结构的数据,所以说前端开发中处处都有算法使用的场景。开发者从接触编程开发开始,就与算法脱不了干系了,算法又和数学分不开,总归到底还是对逻辑思维和数学计算知识的使用。但是大部分开发者没有去深度的针对算法领域去深入,而且有时候太深奥的算法也不常用,往往就忽略了。但是作为程序开发人员,无算法无编程,经典的算法还是要掌握的,本篇博文就来分享一下关于八皇后算法在前端领域的运用,记录一下,方便后期查阅使用。
23 0
js 最小生成图的问题 普利姆算法
js 最小生成图的问题 普利姆算法
18 0
【数据挖掘】数据挖掘算法 组件化思想 示例分析 ( 组件化思想 | Apriori 算法 | K-means 算法 | ID3 算法 )
【数据挖掘】数据挖掘算法 组件化思想 示例分析 ( 组件化思想 | Apriori 算法 | K-means 算法 | ID3 算法 )
97 0
决策树笔记:使用ID3算法
决策树笔记:使用ID3算法 决策树笔记:使用ID3算法 机器学习 先说一个偶然的想法:同样的一堆节点构成的二叉树,平衡树和非平衡树的区别,可以认为是“是否按照重要度逐渐降低”的顺序来分叉的。 其实这个也不一定局限于平衡树的解释。
663 0
《机器学习实战》决策树(ID3算法)的分析与实现
============================================================================================ 《机器学习实战》系列博客是博主阅读《机器学习实战》这本书的笔记,包含对其中算法的理解和算法的Pyt...
1102 0
ID3算法 决策树 C++实现
人工智能课的实验。 数据结构:多叉树 这个实验我写了好久,开始的时候从数据的读入和表示入手,写到递归建树的部分时遇到了瓶颈,更新样例集和属性集的办法过于繁琐; 于是参考网上的代码后重新写,建立决策树类,把属性集、样例集作为数据成员加入类中,并设立访问数组,这样每次更新属性集、样例集时只是标记访问数组的对应元素即可,不必实际拷贝。
1207 0
+关注
关爱单身狗
简书:https://www.jianshu.com/u/f19e29243ff6
文章
问答
文章排行榜
最热
最新
相关电子书
更多
网易云音乐音视频算法处理的 Serverless 探索之路
立即下载
阿里技术参考图册-算法篇
立即下载
阿里千亿特征深度学习算法XNN实践
立即下载