机器学习入门之机器学习算法:AdaBoost
小标 2019-03-26 来源 : 阅读 1619 评论 0

摘要:本文主要向大家介绍了机器学习入门之机器学习算法:AdaBoost,通过具体的内容向大家展现,希望对大家学习机器学习入门有所帮助。

本文主要向大家介绍了机器学习入门之机器学习算法:AdaBoost,通过具体的内容向大家展现,希望对大家学习机器学习入门有所帮助。

机器学习入门之机器学习算法:AdaBoost

AdaBoost算法(Adaptive Boost)的核心思想是:如果一个弱分类器的分类效果不好,那么就构建多个弱分类器,综合考虑它们的分类结果和权重来决定最终的分类结果。很多人认为AdaBoost是监督学习中最强大的两种算法之一(另一个是支持向量机SVM)。


AdaBoost的训练过程如下:

为每个训练样本初始化相同的权重;

针对训练样本及权重,找到一个弱分类器;

计算出这个弱分类器的错误率ε与权重α;

对正确分类的样本,降低其权重,对错误分类的样本,提升其权重;

返回2不断迭代,直至弱分类器数量足够;


其中错误率ε定义为分错的样本数除以总样本数。权重α定义为:

权重提升与降低的公式如下:

对未知样本分类时,用每个弱分类器进行分类,将结果乘以这个分类器的权重α,累加到一起得到一个猜测值,根据其正负决定最终输出1还是-1。注意AdaBoost只能解决二分类问题,如果多于2个分类,需要做一定变通。


在AdaBoost中,广泛使用单层决策树(Decision Stump)作为弱分类器。之前研究ID3算法的决策树时,样本特征是离散型数据,这回研究连续型数据,因此之前的方法就不可用了,需要基于边界比较来确定分类。另外需要注意要同时考虑权重D来决定最佳切分方式。基本思路如下:

foreach(每一个维度)
{
    在此维度最大最小值之间切出N个边界
    foreach(每一个边界)
    {
        针对"<="与">"两种情况
        {
            获取此条件下的分类结果(满足记为1,不满足记为-1)
            foreach(每一个结果)
            {
                if(猜测错误)
                    累加加权错误率
            }
            保留最小加权错误率的切分方式
        }
    }
}

由于只在一个维度上切分一次,可以想像单层决策树的错误率应该相当高,是典型的弱分类器。但是综合考虑它们的结果及权重,最终的分类错误率可以做到大大低于单个单层决策树。上完整C#版AdaBoost的实现代码:


首先是DataVector,之前Label一直是字符串,这回要出现1和-1了,因此改造一下,使Label的类型可定义:

using System;

namespace MachineLearning
{
    /// <summary>
    /// 数据向量
    /// </summary>
    /// <typeparam name="TData">特征类型</typeparam>
    /// <typeparam name="TLabel">标签数据</typeparam>
    public class DataVector<TData, TLabel>
    {
        /// <summary>
        /// N维数据
        /// </summary>
        public TData[] Data { get; private set; }
        /// <summary>
        /// 分类标签
        /// </summary>
        public TLabel Label { get; set; }
        /// <summary>
        /// 构造
        /// </summary>
        /// <param name="dimension">数据维度</param>
        public DataVector(int dimension)
        {
            Data = new TData[dimension];
        }
        /// <summary>
        /// 维度数量
        /// </summary>
        public int Dimension
        {
            get { return this.Data.Length; }
        }
    }
}

然后是一个存储单层决策树的结构:

using System;
using System.Collections.Generic;

namespace MachineLearning
{
    /// <summary>
    /// 单层决策树
    /// </summary>
    public class DecisionStump
    {
        /// <summary>
        /// 分类器权重
        /// </summary>
        public double Alpha { get; set; }
        /// <summary>
        /// 加权错误率
        /// </summary>
        public double Error { get; set; }
        /// <summary>
        /// 在哪个维度上切分
        /// </summary>
        public int Dimension { get; set; }
        /// <summary>
        /// 切分边界
        /// </summary>
        public double Boundary { get; set; }
        /// <summary>
        /// 是否按大于来切分
        /// </summary>
        public bool GreaterThan { get; set; }
        /// <summary>
        /// 此分类器在训练数据集上的分类结果
        /// </summary>
        public List<int> Results { get; set; }
    }
}


最后是AdaBoost:

using System;
using System.Collections.Generic;
using System.Linq;

namespace MachineLearning
{
    /// <summary>
    /// AdaBoost(基于单层决策树)
    /// </summary>
    public class AdaBoost
    {
        /// <summary>
        /// 弱分类器列表
        /// </summary>
        private List<DecisionStump> m_WeakClassifiers;
       
        /// <summary>
        /// 训练
        /// </summary>
        /// <param name="trainingSet">训练数据集</param>
        /// <param name="iterateCount">迭代次数,即弱分类器数量</param>
        public void Train(List<DataVector<double, int>> trainingSet, int iterateCount = 50)
        {
            m_WeakClassifiers = new List<DecisionStump>();
           
            var D = new List<double>();
            var gue***esults = new List<double>();
            for(int i = 0;i < trainingSet.Count;++i)
            {
                //权重初始化为1/n
                D.Add(1.0 / trainingSet.Count);
                //猜测结果初始化为0,后面累加要用
                gue***esults.Add(0.0);
            }
           
            //迭代指定次数
            for(int i = 0;i < iterateCount;++i)
            {
                //在当前权重下生成一棵错误率最低的单层决策树
                var stump = CreateDecisionStump(trainingSet, D);
               
                //计算Alpha(注意stump.Error有可能为0,要防止除0错误)
                stump.Alpha = 0.5 * Math.Log((1 - stump.Error) / Math.Max(stump.Error, 1e-16));
               
                //保存这个决策树到弱分类器
                m_WeakClassifiers.Add(stump);
               
                //根据猜测结果,重新计算下一轮的权重向量D(暂时未除以Sum(D),下一步再处理)
                for(int j = 0;j < trainingSet.Count;++j)
                {
                    if(stump.Results[j] == trainingSet[j].Label)
                        D[j] = D[j] * Math.Exp(-1.0 * stump.Alpha);
                    else
                        D[j] = D[j] * Math.Exp(stump.Alpha);
                }
               
                //保证Sum(D)==1
                double sum = D.Sum();
                for(int j = 0;j < trainingSet.Count;++j)
                {
                    D[j] = D[j] / sum;
                    gue***esults[j] += stump.Alpha * stump.Results[j];
                }
               
                //计算总错误率
                int errors = 0;
                for(int j = 0;j < trainingSet.Count;++j)
                {
                    if(Math.Sign(gue***esults[j]) != trainingSet[j].Label)
                        ++errors;
                }
               
                //如果没有错误,可以提前退出循环,但一般很难达到
                if(errors == 0)
                    break;
            }
        }
       
        /// <summary>
        /// 分类
        /// </summary>
        /// <param name="vector">待测数据</param>
        /// <returns>分类结果,1或-1</returns>
        public int Classify(DataVector<double, int> vector)
        {
            double result = 0.0;
            var dataSet = new List<DataVector<double, int>>();
            dataSet.Add(vector);
           
            //用每一个弱分类器的结果乘以相应的alpha,累加得到最终的猜测结果
            foreach(var c in m_WeakClassifiers)
            {
                var stumpResults = ClassifyByDecisionStump(dataSet, c.Dimension, c.Boundary, c.GreaterThan);
                result += stumpResults[0] * c.Alpha;
            }
           
            //根据正负决定输出1还是-1
            return Math.Sign(result);
        }
       
        /// <summary>
        /// 根据单层决策树进行一次分类
        /// </summary>
        /// <param name="dataSet">数据集</param>
        /// <param name="dimension">在哪个维度上分类</param>
        /// <param name="boundary">分类边界</param>
        /// <param name="greaterThan">是否按大于来划分数据</param>
        /// <returns>结果</returns>
        private List<int> ClassifyByDecisionStump(List<DataVector<double, int>> dataSet, int dimension, double boundary, bool greaterThan)
        {
            var result = new List<int>();
            foreach(var item in dataSet)
            {
                if(greaterThan)
                    result.Add(item.Data[dimension] > boundary ? 1 : -1);
                else
                    result.Add(item.Data[dimension] <= boundary ? 1 : -1);
            }
           
            return result;
        }
       
        /// <summary>
        /// 构建一个单层决策树
        /// </summary>
        /// <param name="dataSet">数据集</param>
        /// <param name="D">权重</param>
        /// <returns>此权重下的最佳单层决策树</returns>
        private DecisionStump CreateDecisionStump(List<DataVector<<span class="token keyword    

本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注职坐标人工智能机器学习频道!

本文由 @小标 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式AI+学习就业服务平台 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved