精华内容
下载资源
问答
  • 算法描述

    千次阅读 2019-09-22 17:40:02
    (2)描述算法的工具:算法可用自然语言、框图或高级程序设计语言进行描述。自然语言简单但易产生二义性;框图直观但不擅长表达数据的组织结构;而高级程序设计语言则较为准确、严谨,但因需考虑细节问题而显得相对...

    1.算法、语言、程序的关系

    首先分析数据结构中算法、语言和程序的关系。

    (1)算法:描述数据对象之间的关系(包括数据逻辑关系、存储关系描述)。

    (2)描述算法的工具:算法可用自然语言、框图或高级程序设计语言进行描述。自然语言简单但易产生二义性;框图直观但不擅长表达数据的组织结构;而高级程序设计语言则较为准确、严谨,但因需考虑细节问题而显得相对繁琐。

    (3)程序是算法在计算机中的实现(与所用计算机及所用语言有关)。程序设计的实质是对实际问题选择一种好的数据结构,加之设计一个好的算法,而好的算法在很大程度上取决于描述实际问题的数据结构。

    2.设计实现算法过程的步骤

    (1)找出与求解有关的数据元素之间的关系(建立结构关系)

    (2)确定在某一数据对象上所施加的运算。

    (3)考虑数据元素的存储表示。

    (4)选择描述算法的语言。

    (5)设计实现求解的算法,并用程序语言加以描述。

    3.描述算法的语言选择

    高级语言描述算法具有严格、准确的优点,但用于描述算法,也有语言细节过多的弱点,为此可采用类语言形式。所谓类语言,是指接近于高级语言而又不是严格的高级语言,它具有高级语言的一般语句,撇掉语言中的细节,以便把注意力集中在算法处理步骤本身的描述上。

    传统的描述语言是采用Pascal语言,由于该语言语法规范严谨,非常适合于数据结构。在Windows环境下,又出现了一系列功能强大且面向对象的程序开发工具,如visual C++、Borland C++、Visual Basic等。近年来在计算机科学研究、系统开发、教学以及应用开发中,C语言的使用范围越来越广,C语言成为许多学校计算机专业与非计算机专业必修的高级程序设计语言。C语言类型丰富,执行效率高。

     

    展开全文
  • 算法描述

    千次阅读 2020-04-13 21:34:45
    算法描述</center> 注:本文为学习《C语言从入门到精通》时,部分章节的总结 1、自然语言 人们日常使用的语言,通俗易懂,但用来描述较为复杂的算法时,不是很方便。 2、流程图 流程图是一种传统的...

    <center>算法的描述</center>

    注:本文为学习《C语言从入门到精通》时,对部分章节的总结

    1、自然语言

    人们日常使用的语言,通俗易懂,但用来描述较为复杂的算法时,不是很方便。

    2、流程图

    流程图是一种传统的算法表示法,用不同的图框代表不同性质的操作,用流程线来知识执行方向。直观形象,易于理解。

    (1)、流程图符号

    正确性食指所写的算法应能安祖具体问题的要求,即对任何合法的输入,都会得到正确的结果。

    流程图使用一些图框来表示各种操作。

    a.起止框:标识算法的开始和结束;

    b.输入/输出框:标识数据任何种类的输入或输出;

    c.流程线:表示控制流的流线;

    d.判断框:用于对一个给定的条件进行判断,根据条件成立与否决定如何执行后续操作;

    e.处理框:表示在过程的一个单独的步骤;

    f.注释框:用于说明一些事项;

    g.连接点:用于将画在不同地方的流程线连接起来。

     

    :从键盘输入3个数并分别赋值给a、b、c,要求从大到小的顺序将它们打印出来。

     

    (2)、3种基本结构

    a.顺序结构:简单的线性结构;

    b.选择结构:也称为分支结构,必须至少包含一个判断框;

    c.循环结构:反复的执行一系列操作,直到条件不成立时才终止循环。按照判断条件出现的位置,可分为当型循环和直到型循环。

    3、N-S流程图

    在普通流程图的基础上去掉了流程线。

    (1)、顺序结构

     

    (2)、选择结构

     

    (3)、循环结构

    a.当型循环:

     

    b.直到型循环:

     

    展开全文
  • 算法及其描述

    千次阅读 2018-03-01 16:48:00
    算法有五个重要的特性1)有穷性 2)确定性 3)可行性 4)有输入 5)有输出算法设计应满足以下几条目标: 1)正确性 2)可使用性 3)可读性 4)健壮性 5)高效率和低存储量需求二、 算法时间复杂度分析通常有两种衡量算法效率的...

    一、算法

    数据元素之间的关系有逻辑关系物理关系,对应的操作有逻辑结构上的操作功能和具体存储结构上的操作实现。 

    通常把具体存储结构上的操作实现步骤或过程称为算法

    算法有五个重要的特性1)有穷性 2)确定性 3)可行性 4)有输入 5)有输出

    算法设计应满足以下几条目标: 1)正确性 2)可使用性 3)可读性 4)健壮性 5)高效率和低存储量需求

    二、 算法时间复杂度分析

    通常有两种衡量算法效率的方法:事后统计法和事前估算法。但是由于事后统计法必须执行后才知道算法的效率和容易受到其他因素的影响,一般使用事前估算法

    当一个算法用高级语言实现后,除了机器性能的硬件因素和软件因素,仅考虑算法本身效率高低,依赖于问题的规模

    一个算法是由控制结构(顺序、分支和循环三种)和原操作(指固有数据类型的操作,如n++等)构成的,则算法时间取决于两者的综合效果。

    为了便于比较同一问题的不同算法,通常从算法中选取一种对于所研究的问题来说是基本运算的原操作。

     算法执行时间大致为基本运算所需的时间与其运算次数(也称为频度)的乘积

    通常把算法中包含基本运算次数的多少称为算法的时间复杂度,也就是说,一个算法的时间复杂度是指该算法的基本运算次数。 算法中基本运算次数T(n)是问题规模n的某个函数f(n),记作: T(n)=O(f(n))。

    记号“O”读作“大O”,它表示随问题规模n的增大算法执行时间的增长率和f(n)的增长率相同

    “O”的形式定义为: 若f(n)是正整数n的一个函数,则T(n)=O(f(n))表示存在一个正的常数M,使得当n≥n0时都满足: |T(n)|≤M|f(n)|,也就是只求出T(n)的最高阶忽略其低阶项和常系数,这样既可简化T(n)的计算,又能比较客观地反映出当n很大时算法的时间性能。

     例如,T(n)=3n2-5n+10000=O(n2)

    一个没有循环的算法的基本运算次数与问题规模n无关,记作O(1),也称作常数阶。

    一个只有一重循环的算法的基本运算次数与问题规模n的增长呈线性增大关系,记作O(n),也称线性阶。

    各种不同数量级对应的值存在着如下关系: O(1)<O(log2n)<O(n)<O(nlog2n)<O(n2)<O(n3)<O(2n)<O(n!)

    平均复杂度:在所有可能的输入实例以等概率出现的的情况下,算法的期望运行时间与问题规模n的数量级的关系。

    例1,分析以下算法的时间复杂度:

     void func(int n) { 

        int i=0,s=0; 

        while (s<n) {

         i++; 

        s=s+i; 

        } 

    }

    解:对于while循环语句,设执行的次数为m,i从0开始递增1,直到m为止,有: s=0+1+2+…+(m-1)=m(m-1)/2, 并满足s=m(m-1)/2<n,则有m<根号n,T(n)=O(根号n)。

    所以,时间复杂度为O(根号n)。


    例2,有平方阶算法:

    int i,j, n=100;

    for(i=0;i<n;i++)

    {

         for (j=i;j<n;j++)

                printf("123");

    }

    解:从内层循环开始看,j=i,当i=0时,j循环n次,...当i=n-1时,j循环一次。

    所以内层循环总次数为n+(n-1)+(n-2)+...+1=n(n+1)/2,时间复杂度为O(n2)。


    例3,有对数阶算法:

    int i=1,n=100;

    while(i<n)

    {

        i=i*2;

    }

    解:首先看到内层语句i=i*2,又因为while循环i<n,循环得到2的i次方<n,求解取对数则为log2n

    时间复杂度为O(log2n)。


    例4,有如下算法: 

    void fun(int a[],int n,int k) //数组a共有n个元素

     { int i;

     if (k==n-1) 

        for (i=0;i<n;i++) //n次 

            printf("%d\n",a[i]); 

    else { 

        for (i=k;i<n;i++) //n-k次

             a[i]=a[i]+i*i;

             fun(a,n,k+1); 

    } 调用上述算法的语句为fun(a,n,0),求其时间复杂度。

    解:设fun(a,n,0)的时间复杂度为T(n),则fun(a,n,k)的执行时间为T1(n,k)

    由fun()算法可知: T1(n,k)=n 当k=n-1时 T1(n,k)= (n-k)+T1(n,k+1)

     其他情况 则 T(n)=T1(n,0)=n+T1(n,1)=n+(n-1)+T1(n,2) =…=n+(n-1)+…+2+T1(n,n-1) =n+(n-1)+ …+2+n =O(n2) 

    所以调用fun(a,n,0)的时间复杂度为O(n2)。

    三、算法空间复杂度分析

    空间复杂度是对一个算法在运行过程中输入数据和辅助变量的所占空间临时占用的存储空间大小的量度,一般也作为问题规模n的函数。

    以数量级形式给出,记作: S(n) = O(g(n))。

    四、数据结构名人

    N.wirth,沃思著作:数据结构+算法=程序指出:程序就是在数据的某些特定的表示方法和结构的基础上,对抽象算法的具体表述,所以说程序离不开数据结构。

    数据结构的概念由CA.R HOARE和N.writh于1966年提出

    五、存储结构对算法的影响

    主要在两方面:

    1)存储结构的存储能力。如果存储结构存储能力强、存储信息多,算法将会较好设计。反之对于过于简单的存储结构,可能就要设计一套比较复杂的算法。在这一点上,经常体现时间与空间的矛盾,往往存储能力是与所使用的空间大小成正比的。

    2)存储结构应与所选择的算法相适应。存储结构是实现算法的基础,也会影响算法的设计,其选择要充分考虑算法的各种操作,应与算法的操作相适应。


    展开全文
  • GBDT基本原理及算法描述

    万次阅读 多人点赞 2018-08-25 13:16:21
    在AdaBoost基本原理与算法描述中,我们介绍了AdaBoost的基本原理,本篇博客将介绍boosting系列算法中的另一个代表算法GBDT(Gradient Boosting Decision Tree,梯度提升树)算法。这里GBDT的学习做一个总结,也...

    一. 前言

    AdaBoost基本原理与算法描述中,我们介绍了AdaBoost的基本原理,本篇博客将介绍boosting系列算法中的另一个代表算法GBDT(Gradient Boosting Decision Tree,梯度提升树)算法。这里对GBDT的学习做一个总结,也希望对有帮助的同学能有一个帮助。

    在介绍AdaBoost的时候我们讲到了,AdaBoost算法是模型为加法模型,损失函数为指数函数,学习算法为前向分步算法时的分类问题。而GBDT算法是模型为加法模型,学习算法为前向分步算法,基函数为CART树,损失函数为平方损失函数的回归问题,为指数函数的分类问题和为一般损失函数的一般决策问题。在针对基学习器的不足上,AdaBoost算法是通过提升错分数据点的权重来定位模型的不足,而梯度提升算法是通过算梯度来定位模型的不足。

    当GBDT的损失函数是平方损失时,即L(y,f(x))=\frac{1}{2}(y-f(x))^2时,则负梯度-\frac{\partial L}{\partial f(x)}=y-f(x),而y-f(x)即为我们所说的残差,而我们的GBDT的思想就是在每次迭代中拟合残差来学习一个弱学习器。而残差的方向即为我们全局最优的方向。但是当损失函数不为平方损失时,我们该如何拟合弱学习器呢?大牛Friedman提出使用损失函数负梯度的方向代替残差方向,我们称损失函数负梯度为伪残差。而伪残差的方向即为我们局部最优的方向。所以在GBDT中,当损失函数不为平方损失时,用每次迭代的局部最优方向代替全局最优方向(这种方法是不是很熟悉?)。

    说了这么多,现在举个例子来看看GBDT是如何拟合残差来学习弱学习器的。我们可以证明,当损失函数为平方损失时,叶节点中使平方损失误差达到最小值的是叶节点中所有值的均值;而当损失函数为绝对值损失时,叶节点中使绝对损失误差达到最小值的是叶节点中所有值的中位数。相关证明将在最后的附录中给出。

    训练集是4个人,A,B,C,D年龄分别是14,16,24,26。样本中有购物金额、上网时长、经常到百度知道提问等特征。提升树的过程如下:(图片来源

    从上图可以看出,第一棵树建立的时候使用的是原始数据,而后每一棵树建立使用的是前n-1次的残差来拟合弱学习器。

    下面,我们就来简单的介绍一下GBDT的基本原理和算法描述。

    二. GBDT回归树基本模版

    梯度提升算法的回归树基本模版,如下所示:

    输入:训练数据集T=\left \{ (x{_{1},y{_{1}}}),(x{_{2}},y{_{2}}),...,(x{_{N}},y{_{N}}) \right \},损失函数为L(y,f(x))

    输出:回归树F(x)

    (1)初始化:(估计使损失函数极小化的常数值,它是只有一个根节点的树,一般平方损失函数为节点的均值,而绝对损失函数为节点样本的中位数)

                           f{_{0}}(x)=arg\underset{c}{min}\sum_{i=1}^{N}L(y{_{i}},c)

    (2)对m=1,2,...,M(M表示迭代次数,即生成的弱学习器个数):

    (a)对样本i=1,2,...N,计算损失函数的负梯度在当前模型的值将它作为残差的估计,对于平方损失函数为,它就是通常所说的残差;而对于一般损失函数,它就是残差的近似值(伪残差):

                          r{_{mi}}=-[\frac{\partial L(y{_{i}},f(x{_{i}}))}{\partial f((x{_{i}}))}]_{f(x)=f{_{m-1}}(x)}

    (b)对\left \{ (x{_{1}},r{_{m1}}),..., (x{_{N}},r{_{mN}})\right \}拟合一个回归树,得到第m棵树的叶节点区域R{_{mj}}j=1,2,...,J(J表示每棵树的叶节点个数)

    (c)对j=1,2,...,J,利用线性搜索,估计叶节点区域的值,使损失函数最小化,计算

                        c{_{mj}}=arg\underset{c}{min}\sum_{x{_{i}}\in R{_{mj}}}L(y{_{i}},f{_{m-1}}(x{_{i}}+c)))

    (d)更新

                        f{_{m}}(x)=f{_{m-1}}(x)+\sum_{J}^{j=1}c{_{mj}}I(x\in R{_{mj}})

    (3)得到最终的回归树

                                   F(x)=\sum_{m=1}^{M}\sum_{j=1}^{J}c{_{mj}}I(x\in R{_{mj}})

    三. GBDT的算法描述

    3.1 GBDT的损失函数

    在sklearn中梯度提升回归树有四种可选的损失函数,分别为'ls:平方损失','lad:绝对损失','huber:huber损失','quantile:分位数损失';而在sklearn中梯度提升分类树有两种可选的损失函数,一种是‘exponential:指数损失’,一种是‘deviance:对数损失’。下面分别介绍这几种损失函数。

    3.1.1 梯度提升回归树损失函数介绍

    (1)ls:平方损失,这是最常见的回归损失函数了,如下:

                      L(y,f(x))=(y-f(x))^2

    (2)lad:绝对损失,这个损失函数也很常见,如下:

                                 L(y,f(x))=|y-f(x)|

    对应负梯度为:

                                 r(y{_{i}},f(x{_{i}}))=sign(y{_{i}}-f(x{_{i}}))

    (3)huber:huber损失,它是平方损失和绝对损失的这种产物,对于远离中心的异常点采用绝对损失,而中心附近的点采用平方损失。这个界限一般用分位数点度量。损失函数如下:

                                L(y,f(x))=\begin{cases} \frac{1}{2}(y-f(x))^2 & \text{ if } |y-f(x)|\leq \delta \\ \delta (|y-f(x)|-\frac{\delta }{2})& \text{ if } |y-f(x)|> \delta \end{cases}

    对应的负梯度为:

                                r(y{_{i}},f(x{_{i}}))=\begin{cases} y{_{i}}-f(x{_{i}}) & \text{ if }|y{_{i}}-f(x{_{i}})|\leq \delta \\ \delta sign(y{_{i}}-f(x{_{i}})) & \text{ if } |y{_{i}}-f(x{_{i}})|> \delta \end{cases}

    (4)quantile:分位数损失,它对应的是分位数回归的损失函数,表达式如下:

                               L(y,f(x))=\sum_{y\geq f(x)}\theta |y-f(x)|+\sum_{y<f(x)}(1-\theta )|y-f(x)|

    其中θ为分位数,需要我们在回归前指定。对应的负梯度为:

                              r(y{_{i}},f(x{_{i}}))=\begin{cases} \theta & \text{ if } y{_{i}}\geq f(x{_{i}}) \\\theta-1 &\text{ if } y{_{i}}< f(x{_{i}}) \end{cases}

    对于huber损失和分位数损失主要作用就是减少异常点对损失函数的影响。

    3.1.2 梯度提升分类树损失函数介绍

    (1)exponential:指数损失,表达式如下:

                              L(y,f(x))=exp(-yf(x))

    (2)deviance:对数损失,类似于logistic回归的损失函数,输出的是类别的概率,表达式如下:

                              L(y,f(x))=ln(1+exp(-2yf(x)))

    下面我们来分别的介绍一下,这几种损失函数对应GBDT算法。

    3.2 GBDT回归算法描述

    3.2.1 平方损失GBDT算法描述

    输入:训练数据集T=\left \{ (x{_{1},y{_{1}}}),(x{_{2}},y{_{2}}),...,(x{_{N}},y{_{N}}) \right \},损失函数为L(y,f(x))=(y-f(x))^2

    输出:回归树F(x)

    (1)初始化:(可以证明当损失函数为平方损失时,节点的平均值即为该节点中使损失函数达到最小值的最优预测值,证明在最下面的附录给出)

                           f{_{0}}(x)=\bar{y}  

    (2)对m=1,2,...,M

    (a)对样本i=1,2,...N,计算伪残差(对于平方损失来说,伪残差就是真残差)

                          r{_{mi}}=-[\frac{\partial L(y{_{i}},f(x{_{i}}))}{\partial f((x{_{i}}))}]_{f(x)=f{_{m-1}}(x)}=y-f(x{_{i}})

    (b)对\left \{ (x{_{1}},r{_{m1}}),..., (x{_{N}},r{_{mN}})\right \}拟合一个回归树,得到第m棵树的叶节点区域R{_{mj}}j=1,2,...,J

    (c)对j=1,2,...,J,利用线性搜索,估计叶节点区域的值,使损失函数最小化,计算

                        c{_{mj}}=\frac{1}{K}\sum_{x{_{i}}\in R{_{mj}}}(y{_{i}}-f(x{_{i}})),K表示第m棵树的第j个节点中的样本数量

    上式表示c{_{mj}}的取值为第m棵树的第j个叶节点中伪残差的平均数

    (d)更新

                        f{_{m}}(x)=f{_{m-1}}(x)+\sum_{J}^{j=1}c{_{mj}}I(x\in R{_{mj}})

    (3)得到最终的回归树

                                   F(x)=\sum_{m=1}^{M}\sum_{j=1}^{J}c{_{mj}}I(x\in R{_{mj}})

    3.2.2 绝对损失GBDT算法描述

    输入:训练数据集T=\left \{ (x{_{1},y{_{1}}}),(x{_{2}},y{_{2}}),...,(x{_{N}},y{_{N}}) \right \},损失函数为L(y,f(x))=|y-f(x)|

    输出:回归树F(x)

    (1)初始化:(可以证明当损失函数为绝对损失时,节点中样本的中位数即为该节点中使损失函数达到最小值的最优预测值,证明在最下面的附录给出)

                           f{_{0}}(x)=median\left \{ y \right \}

    (2)对m=1,2,...,M

    (a)对样本i=1,2,...N,计算伪残差

                          r{_{mi}}=-[\frac{\partial L(y{_{i}},f(x{_{i}}))}{\partial f((x{_{i}}))}]_{f(x)=f{_{m-1}}(x)}=sign(y{_{i}}-f(x{_{i}}))

    (b)对\left \{ (x{_{1}},r{_{m1}}),..., (x{_{N}},r{_{mN}})\right \}拟合一个回归树,得到第m棵树的叶节点区域R{_{mj}}j=1,2,...,J

    (c)对j=1,2,...,Ji=1,2,...,N,计算

                        c{_{mj}}=\underset{{x{_{i}}\in R{_{mj}}}}{median}\left \{ y{_{i}}-f{_{m-1}(x{_{i}})} \right \}

    上式表示c{_{mj}}的取值为第m棵树的第j个叶节点中伪残差的中位数

    (d)更新

                        f{_{m}}(x)=f{_{m-1}}(x)+\sum_{J}^{j=1}c{_{mj}}I(x\in R{_{mj}})

    (3)得到最终的回归树

                                   F(x)=\sum_{m=1}^{M}\sum_{j=1}^{J}c{_{mj}}I(x\in R{_{mj}})

    3.2.3 huber损失GBDT算法描述

    输入:训练数据集T=\left \{ (x{_{1},y{_{1}}}),(x{_{2}},y{_{2}}),...,(x{_{N}},y{_{N}}) \right \},损失函数为L(y,f(x))=\begin{cases} \frac{1}{2}(y-f(x))^2 & \text{ if } |y-f(x)|\leq \delta \\ \delta (|y-f(x)|-\frac{\delta }{2})& \text{ if } |y-f(x)|> \delta \end{cases}

    输出:回归树F(x)

    (1)初始化:

                           f{_{0}}(x)=median\left \{ y \right \}

    (2)对m=1,2,...,M

    (a)对样本i=1,2,...N,计算

                          \delta {_{m}}=\underset{\alpha }{quantile}\left \{ y{_{i}}-f{_{m-1}(x{_{i}})} \right \}

    \delta {_{m}}表示分位数;\alpha表示将伪残差的百分之多少设为分位数,在sklearn中是需要我们自己设置的,默认为0.9

                          r{_{mj}}=\begin{cases} y{_{i}}-f(x{_{i}}) & \text{ if }|y{_{i}}-f(x{_{i}})|\leq \delta{_{m}} \\ \delta{_{m}} sign(y{_{i}}-f(x{_{i}})) & \text{ if } |y{_{i}}-f(x{_{i}})|> \delta{_{m}} \end{cases}

    (b)对\left \{ (x{_{1}},r{_{m1}}),..., (x{_{N}},r{_{mN}})\right \}拟合一个回归树,得到第m棵树的叶节点区域R{_{mj}}j=1,2,...,J

    (c)对j=1,2,...,Ji=1,2,...,N,计算

                        \bar{r}{_{mj}}=\underset{x{_{i}}\in R{_{mj}}}{median}\left \{y{_{i}}-f{_{m-1}}(x{_{i}}) \right \}

                        \tiny c{_{mj}}=\bar{r}{_{mj}}+\frac{1}{N{_{mj}}}\sum_{x{_{i}}\in R{_{mj}}}sign(y{_{i}}-f{_{m-1}(x{_{i}})}-\bar{r}{_{mj}})*min(\delta {_{m}},abs(y{_{i}}-f{_{m-1}(x{_{i}})}-\bar{r}{_{mj}}))

    (d)更新

                        f{_{m}}(x)=f{_{m-1}}(x)+\sum_{J}^{j=1}c{_{mj}}I(x\in R{_{mj}})

    (3)得到最终的回归树

                                   F(x)=\sum_{m=1}^{M}\sum_{j=1}^{J}c{_{mj}}I(x\in R{_{mj}})

    3.3 GBDT分类算法描述

    GBDT分类算法思想上和GBDT的回归算法没有什么区别,但是由于样本输出不是连续值,而是离散类别,导致我们无法直接从输出类别去拟合类别输出误差。为了解决这个问题,主要有两种方法。一是用指数损失函数,此时GBDT算法退化为AdaBoost算法。另一种方法是用类似于逻辑回归的对数似然损失函数的方法。也就是说,我们用的是类别的预测概率值和真实概率值的差来拟合损失。当损失函数为指数函数时,类似于AdaBoost算法,这里不做介绍,下面介绍损失函数为log函数时的GBDT二分类和多分类算法。

    3.3.1 log损失GBDT的二分类算法描述

    输入:训练数据集T=\left \{ (x{_{1},y{_{1}}}),(x{_{2}},y{_{2}}),...,(x{_{N}},y{_{N}}) \right \},损失函数为L(y,f(x))=ln(1+exp(-2yf(x))),y={-1,1}

    输出:分类树F(x)

    (1)初始化:

                           f{_{0}}(x)=\frac{1}{2}ln\frac{P(y=1|x)}{P(y=-1|x)}

    (2)对m=1,2,...,M

    (a)对样本i=1,2,...N,计算伪残差

                          r{_{mi}}=\frac{2y{_{i}}}{1+exp(2y{_{i}}f{_{m-1}}(x{_{i}}))}

    (b)对概率残差\left \{ (x{_{1}},r{_{m1}}),..., (x{_{N}},r{_{mN}})\right \}拟合一个分类树,得到第m棵树的叶节点区域R{_{mj}}j=1,2,...,J

    (c)对j=1,2,...,Ji=1,2,...,N,计算

                        c{_{mj}}=\frac{\sum_{x{_{i}}\in R{_{mj}}}r{_{mj}}}{\sum_{x{_{i}}\in R{_{mj}}}|r{_{mj}}|(2-|r{_{mj}}|)}

    (d)更新

                        f{_{m}}(x)=f{_{m-1}}(x)+\sum_{J}^{j=1}c{_{mj}}I(x\in R{_{mj}})

    (3)得到最终的分类树

                                   F(x)=\sum_{m=1}^{M}\sum_{j=1}^{J}c{_{mj}}I(x\in R{_{mj}})

    由于我们用的是类别的预测概率值和真实概率值的差来拟合损失,所以最后还要讲概率转换为类别,如下:

                                   P(y=1|x)=\frac{1}{1+exp(-2F(x))}

                                   P(y=-1|x)=\frac{1}{1+exp(2F(x))}

    最终输出比较类别概率大小,概率大的就预测为该类别。

    3.3.2 log损失GBDT的多分类算法描述         

    输入:训练数据集T=\left \{ (x{_{1},y{_{1}}}),(x{_{2}},y{_{2}}),...,(x{_{N}},y{_{N}}) \right \},损失函数为L(y{_{k}},f{_{k}}(x))=-\sum_{k=1}^{K}y{_{k}}lnP{_{k}}(x)y{_{k}}={0,1}表示是否属于第k类别,1表示是,0表示否。k=1,2,...,K,表示共有多少分类的类别。

    输出:分类树F(x)

    (1)初始化:

                           f{_{k0}}(x)=0k=1,2,...,K

    (2)对m=1,2,...,M

    (a)计算样本点俗属于每个类别的概率:

                        P{_{k}}(x)=exp(f{_{k}}(x))/\sum_{l=1}^{K}exp(f{_{l}}(x))

    (b)对k=1,2,...,K:

            1) r{_{ki}}=y{_{ki}}-P{_{k}}(x{_{i}})i=1,2,...,N

            2)对概率伪残差\left \{ (x{_{1}},r{_{k1}}),..., (x{_{N}},r{_{kN}})\right \}拟合一个分类树

            3)c{_{mkj}}=\frac{K-1}{K}\frac{\sum_{x{_{i}}\in R{_{mkj}}}r{_{ki}}}{\sum_{x{_{i}}\in R{_{mkj}}}|c{_{ki}}|(1-|c{_{ki}}|)}

            4)f{_{mk}}(x)=f{_{k,m-1}}(x)+\sum_{j=1}^{J}c{_{mkj}}I(x\in R{_{mkj}})

    (3)得到最终的分类树

                                   F{_{Mk}}(x)=\sum_{m=1}^{M}\sum_{j=1}^{J}c{_{mkj}}I(x\in R{_{mkj}})

    最后得到的F{_{Mk}}(x)可以被用来去得到分为第k类的相应的概率P{_{Mk}}(x)

                                   P{_{Mk}}=exp(F{_{Mk}}(x))/\sum_{l=1}^{K}exp(F{_{Ml}}(x))

    由于我们用的是类别的预测概率值和真实概率值的差来拟合损失,所以最后还要将概率转换为类别,如下:

                                   \hat{k}(x)=arg\underset{1\leq k\leq K}{min}\sum_{{k}'=1}^{K}[c(k,{k}')P{_{M{k}'}(x)}]

    \hat{k}(x)为最终的输出类别,c(k,{k}')为当真实值为{k}'时,预测为第k类时的联合代价,即概率最大的类别即为我们所预测的类别。当K=2时,该算法等价于为二分类算法。

    到这里,我们算法的描述环节已经介绍完毕。还有一个算法就是分位数回归的算法描述没有介绍,因为早期的论文里面并没有介绍到该算法,所以,这里我们也不予以介绍,感兴趣的小伙伴可以查阅相关资料或者直接看sklearn有关该算法的源码。

    最后,我们还有两个证明没有说,接下来我们证明我们在上面提到的有关损失函数为平方损失时叶节点的最佳预测为叶节点的残差均值和损失函数为绝对损失时,叶节点的最佳预测为叶节点残差的中位数。

    四. 附录

    4.1 证明:损失函数为平方损失时,叶节点的最佳预测为叶节点残差均值

    节点R中有N个样本点,假设s为切分点,R{_{1}}R{_{2}}分别为切分后的左节点和右节点,分别有节点个数为N{_{1}},N{_{2}}

    我们的目标是找到切分点s,在R{_{1}}R{_{2}}内部使平方损失误差达到最小值的c{_{1}},c{_{2}},如下:

                                  \underset{s}{min}[\underset{c{_{1}}}{min}\sum_{x{_{i}}\in R{_{1}}}(y{_{i}}-c{_{1}})^2+\underset{c{_{2}}}{min}\sum_{x{_{i}}\in R{_{2}}}(y{_{i}}-c{_{2}})^2]

    \sum_{x{_{i}}\in R{_{1}}}(y{_{i}}-c{_{1}})^2\sum_{x{_{i}}\in R{_{2}}}(y{_{i}}-c{_{2}})^2分别对c{_{1}},c{_{2}}求偏导,并令偏导等于0,得到在R{_{1}}R{_{2}}内部使平方损失误差达到最小值的c{_{1}},c{_{2}}

                                  c{_{1}}=\frac{1}{N{_{1}}}\sum_{x{_{i}}\in R{_{1}}}y{_{i}},   c{_{2}}=\frac{1}{N{_{2}}}\sum_{x{_{i}}\in R{_{2}}}y{_{i}}

    c{_{1}},c{_{2}}和即为各自叶节点中的残差的均值。

    4.2 证明:损失函数为绝对损失时,叶节点的最佳预测为叶节点残差的中位数。

    损失函数L(y{_{i}},f(x{_{i}}))=\sum_{i=1}^{N}|y{_{i}}-f(x{_{i}})|

    假设在节点中有N{_{1}}个节点使y{_{i}}-f(x{_{i}})>0,则有N-N{_{1}}个节点使y{_{i}}-f(x{_{i}})<0,那么:

                                  L(y{_{i}},f(x{_{i}}))=\sum_{x{_{i}}\in N{_{1}}}[y{_{i}}-f(x{_{i}})]+\sum_{x{_{i}}\in N-N{_{1}}}[f(x{_{i}})-y{_{i}}]

    我们的目标是是损失函数最小化,所以,上式对f(x{_{i}})求偏导,并令偏导等于0,得:

                                  \frac{\partial L}{\partial f(x{_{i}})}=\sum_{x{_{i}}\in N{_{1}}}(-1)+\sum_{x{_{i}}\in N-N{_{1}}}(1)=-N{_{1}}+(N-N{_{1}})=0

    得:

                                 N{_{1}}=\frac{N}{2}

    而N为节点中样本的总数,所以使节点的最佳预测为节点中残差的中位数。

    五. 参考文献/博文

    (1)大牛Friedman关于梯度提升的论文

    (2)《统计学习方法》第八章

    (3)关于机器学习总结比较好的博客

     

     

    展开全文
  • 算法描述语言ADL

    千次阅读 2020-12-05 12:39:40
    算法描述语言ADL书写算法的格式及规定如下: 算法<算法名>(变量i1,···,变量in.变量j,···,变量jn) // <算法的概括说明>或者/* <算法的概括说明> */ <步骤名>.[<本步骤的概括...
  • 用流程图描述算法

    万次阅读 多人点赞 2018-07-18 08:41:11
    流程图就是一种描述算法的图形化描述,用流程图可以清晰地描述算法的思路和过程。通过本篇的学习,你将了解到如何用流程图来描述算法。】   流程图是算法的图形化描述。俗话说:一张图胜过千言万语,用流程图...
  • 算法描述---伪代码

    千次阅读 2017-11-23 14:13:40
     算法描述是指设计出的算法,用一种方式进行详细的描述,以便与人交流。描述可以使用自然语言、伪代码,也可使用程序流程图,但描述的结果必须满足算法的五个特征。  使用自然语言描述算法显然很有吸引力,但是...
  • 算法

    万次阅读 2018-02-08 00:13:09
    算法(Algorithm)是指解题方案的准确而完整的描述,是一系列解决问题的清晰指令,算法代表着用系统的方法描述解决问题的策略机制。也就是说,能够一定规范的输入,在有限时间内获得所要求的输出。如果一个算法有...
  • 算法学习总结(2)——温故十大经典排序算法

    万次阅读 多人点赞 2019-08-29 14:57:51
    一序列对象根据某个关键字进行排序。 1.2、排序术语 稳定:如果a原本在b前面,而a=b,排序之后a仍然在b的前面;不稳定:如果a原本在b的前面,而a=b,排序之后a可能会出现在b的后面;内排序:所有排序操作都在...
  • 本文主要描述分治算法的一般描述和分析方法。衔接上一篇文章:【算法设计与分析】13 分治策略的设计思想 文章目录1 分治算法的一般性描述1.1 分支算法的时间分析1.2 两类常见的递推方程与求解方法2 总结 1 分治算法...
  • LibTomCtypt中为密码算法定义了一个算法描述子cipher_descriptor,可以把它理解为一个类,里面描述了密码算法应该有的变量和函数操作。密码算法描述子的详细描述可以参见tomcrypt_cipher.h   extern struct ltc_...
  • 层次聚类分为两种: (1) 凝聚的层次聚类:自底向上的策略,首先将每个对象作为一个簇,然后合并这些原子簇为更大的... AGNES(Agglomerative Nesting) 是凝聚的层次聚类算法,如果簇C1中的一个对象和簇C2中的一个
  • BRIEF描述算法学习

    千次阅读 2017-12-06 14:52:58
    一种已检测到的特征点进行描述算法,它是一种二进制编码的描述子,在图像匹配时使用BRIEF能极大的提升匹配速度。 算法步骤如下: 1、为减少噪声干扰,先图像进行高斯滤波(方差为2,高斯窗口为9x9)。 2、...
  • [密码学]DES算法过程描述

    万次阅读 多人点赞 2014-01-16 22:12:02
    DES算法曾是美国政府保护非机密的敏感数据使用的数据加密标准,虽然现在已经因为安全性不足被AES算法取代,不过作为第一个公开...本文描述了DES加密算法的整个流程和其中的细节,看完本文,读者就可以自己实现DES了: )
  • 排序算法c语言描述---希尔排序

    万次阅读 多人点赞 2013-08-10 20:33:01
    排序算法系列学习,主要描述冒泡排序,选择排序,直接插入排序,希尔排序,堆排序,归并排序,快速排序等排序进行分析。 文章规划: 一。通过自己排序算法本身的理解,每个方法写个小测试程序。 具体思路分析...
  • 数据结构算法描述和分析

    千次阅读 2018-08-17 19:25:49
    高级语言程序设计在解决某一实际问题的一般步骤是:分析实际问题、确定数学模型、设计或选择一个求解此数学模型的算法、编写程序进行调试和测试解决问题等几个步骤。 例1:已知:游泳池的长length和宽winde,求面积...
  • BRIEF描述子生成算法

    千次阅读 2017-02-03 23:07:07
    学习OpenCV关注微信公众号【OpenCV学堂】一:介绍我们知道SIFT算法通常通过每个关键点生成128个特征向量作为描述子、SURF算法通常关键点生成最少64个特征向量作为描述子。但是对于图像来说创建上千或者上万个...
  • 排序算法c语言描述---快速排序

    千次阅读 多人点赞 2013-08-14 18:15:38
    排序算法系列学习,主要描述冒泡排序,选择排序,直接插入排序,希尔排序,堆排序,归并排序,快速排序等排序进行分析。 文章规划: 一。通过自己排序算法本身的理解,每个方法写个小测试程序。 具体思路分析...
  • AdaBoost基本原理与算法描述

    万次阅读 多人点赞 2018-08-21 19:59:33
    最近在看集成学习方法,前面已经XGBoost的原理与简单实践做了介绍,这次AdaBoost算法做个学习笔记,来巩固自己所学的知识,同时也希望需要帮助的人有所帮助。 关于集成学习主要有两大分支,一种是bagging方法...
  • 排序算法c语言描述---归并排序

    万次阅读 多人点赞 2013-08-14 00:39:47
    排序算法系列学习,主要描述冒泡排序,选择排序,直接插入排序,希尔排序,堆排序,归并排序,快速排序等排序进行分析。 文章规划: 一。通过自己排序算法本身的理解,每个方法写个小测试程序。 具体思路分析...
  • 排序算法c语言描述---堆排序

    万次阅读 多人点赞 2013-08-13 21:36:27
    排序算法系列学习,主要描述冒泡排序,选择排序,直接插入排序,希尔排序,堆排序,归并排序,快速排序等排序进行分析。 文章规划: 一。通过自己排序算法本身的理解,每个方法写个小测试程序。 具体思路分析...
  • BRIEF 特征点描述算法

    千次阅读 2017-07-16 10:08:43
    一、BRIEF特征点描述算法简介   BRIEF是Binary Robust Independent Elementary Features的缩写。这个特征描述子是由EPFL的Calonder在ECCV2010上提出的。主要思路就是在特征点附近随机选取若干点,将这些点的...
  • 排序算法c语言描述---基数排序

    万次阅读 多人点赞 2013-08-14 20:25:24
    排序算法系列学习,主要描述冒泡排序,选择排序,直接插入排序,希尔排序,堆排序,归并排序,快速排序等排序进行分析。 文章规划: 一。通过自己排序算法本身的理解,每个方法写个小测试程序。 具体思路...
  • 使用通俗的语言简单回顾一下JVM GC的垃圾标记算法和垃圾收集算法。 一、什么是Garbage(辣鸡)? 通俗的认为,不被任何在用的引用所指向的资源称为垃圾。硬件资源是有限的,如何准确的标识出垃圾,让JVM来做后续...
  • static const uint32_t rcon[10] = { 0x01000000UL, 0x02000000UL, 0x04000000UL, 0x08000000UL, 0x10000000UL, 0x20000000UL, 0x40000000UL, 0x80000000UL, 0x1B000000UL, 0x36000000UL };
  • 漫水填充算法描述

    千次阅读 2015-07-07 16:22:52
    漫水填充算法描述 1.1、种子填充算法 种子填充算法是从多边形区域内部的一点开始,由此出发找到区域内的所有像素。 种子填充算法采用的边界定义是区域边界上所有像素具有某个特定的颜色值,区域内部所有...
  • 排序算法c语言描述---直接插入排序

    万次阅读 多人点赞 2013-08-10 17:59:21
    排序算法系列学习,主要描述冒泡排序,选择排序,直接插入排序,希尔排序,堆排序,归并排序,快速排序等排序进行分析。 文章规划: 一。通过自己排序算法本身的理解,每个方法写个小测试程序。 具体思路...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 971,472
精华内容 388,588
关键字:

怎样对算法进行描述