zoukankan      html  css  js  c++  java
  • 随机森林之特征选择

    随机森林之特征选择

     

    摘要:随机森林介绍中提到了随机森林一个重要特征:能够计算单个特征变量的重要性。并且这一特征在很多方面能够得到应用,例如在银行贷款业务中能否正确的评估一个企业的信用度,关系到是否能够有效地回收贷款。但是信用评估模型的数据特征有很多,其中不乏有很多噪音,所以需要计算出每一个特征的重要性并对这些特征进行一个排序,进而可以从所有特征中选择出重要性靠前的特征。

    一:特征重要性

    在随机森林中某个特征X的重要性的计算方法如下:

    1:对于随机森林中的每一颗决策树,使用相应的OOB(袋外数据)数据来计算它的袋外数据误差,记为errOOB1.

    2:  随机地对袋外数据OOB所有样本的特征X加入噪声干扰(就可以随机的改变样本在特征X处的值),再次计算它的袋外数据误差,记为errOOB2.

    3:假设随机森林中有Ntree棵树,那么对于特征X的重要性=∑(errOOB2-errOOB1)/Ntree,之所以可以用这个表达式来作为相应特征的重要性的度量值是因为:若给某个特征随机加入噪声之后,袋外的准确率大幅度降低,则说明这个特征对于样本的分类结果影响很大,也就是说它的重要程度比较高。

    二:特征选择

    在论文 Variable Selection using Random Forests中详细的论述了基于随机森林的特征选择方法,这里我们进行一些回顾。

    首先特征选择的目标有两个:

    1:找到与应变量高度相关的特征变量。

    2:选择出数目较少的特征变量并且能够充分的预测应变量的结果。

    其次一般特征选择的步骤为:

    1:初步估计和排序

    a)对随机森林中的特征变量按照VI(Variable Importance)降序排序。

    b)确定删除比例,从当前的特征变量中剔除相应比例不重要的指标,从而得到一个新的特征集。

    c)用新的特征集建立新的随机森林,并计算特征集中每个特征的VI,并排序。

    d)重复以上步骤,直到剩下m个特征。

    2:根据1中得到的每个特征集和它们建立起来的随机森林,计算对应的袋外误差率(OOB err),将袋外误差率最低的特征集作为最后选定的特征集。

     
     
    标签: 随机森林特征选择

    地址转换协议ARP

      在以太网协议中规定,同一局域网中的一台主机要和另一台主机进行直接通信,必须要知道目标主机的MAC地址。而在TCP/IP协议中,网络层和传输层只关心目标主机的IP地址。这就导致在以太网中使用IP协议时,数据链路层的以太网协议接到上层IP协议提供的数据中,只包含目的主机的IP地址。于是需要一种方法,根据目的主机的IP地址,获得其MAC地址。这就是ARP协议要做的事情。

      所谓地址解析(address resolution)就是主机在发送帧前将目标IP地址转换成目标MAC地址的过程。

    理论结构

      ARP软件可分为三部分:

    • 输出模块
      • 将高层协议地址与相应的物理地址进行绑定,返回给网络接口程序
    • 输入模块
      • 处理来自网络的ARP分组,并通过增加新的绑定来修改ARP高速缓存的内容
    • 高速缓存管理程序
      • 实现高速缓存替换策略;检测高速缓存中的所有表项,删除已达到规定时限的表项

    输出模块

      该模块主要是要接收IP数组请求,然后查找物理地址,返回。

      主要步骤为:

      1. 睡眠,直到IP软件收到IP分组。

      2. 检查高速缓存表,寻找对应于这个IP分组的项目。

      3. if ( 找到 ){

          if ( 状态为 RESOLVED ){

            提取硬件物理地址;

            将分组连同硬件物理地址一起发送到数据链路层;

                       return;

          }

          else if ( 状态为 PENDING ){

           将分组放入相应的队列;

                      return;

         }

        }

        else{

          创建一个队列;

          将分组加入到队列中;

          创建一个高速缓存项目,状态设置为 PENDING ,ATTEMPTS 为 1;

          发送ARP请求;

        }

    ARP高速缓存队列

      它是用数组来存储的。

    extern struct arpentry arptable[ARP_TSIZE]

    搜索ARP高速缓存

    复制代码
    /* arpfind.c - arpfind */   
       
    #include <conf.h>   
    #include <kernel.h>   
    #include <network.h>   
       
    /*------------------------------------------------------------------------  
     * arpfind - find an ARP entry given a protocol address and interface  
     *------------------------------------------------------------------------  
     */   
    struct arpentry *   
    arpfind(u_char *pra, u_short prtype, struct netif *pni)   
    {   
        struct arpentry *pae;   /* 定义ARP缓存结构体指针 */
        int     i;   
       
        for (i=0; i<ARP_TSIZE; ++i) {   /* 遍历ARP高速缓存 */
            pae = &arptable[i];   /* 高速缓存数组 */
            if (pae->ae_state == AS_FREE)   /* 缓存为空闲接找下一个 */
                continue;   
            if (pae->ae_prtype == prtype &&                /* 协议类型相同 */
                pae->ae_pni == pni &&                      /* 接口和协议地址相同 */
                BLKEQU(pae->ae_pra, pra, pae->ae_prlen))   /* BLKEQU的定义 #define    BLKEQU(b1, b2, len)    (!memcmp((b1), (b2), len))*/
                return pae;   
        }   
        return 0;   
    } 
    复制代码

    ARP请求分组的广播

    复制代码
    /* arpsend.c - arpsend */
    
    #include <conf.h>
    #include <kernel.h>
    #include <network.h>
    
    /*------------------------------------------------------------------------
     * arpsend - broadcast an ARP request
     *    N.B. Assumes interrupts disabled
     *------------------------------------------------------------------------
     */
    int arpsend(pae)
    struct    arpentry    *pae; //指向高速缓存的表项
    {
        struct    netif    *pni = pae->ae_pni;
        struct    ep    *pep;
        struct    arp    *parp;
        int        arplen;
    
        pep = (struct ep *) getbuf(Net.netpool); //生成ARP请求分组
        if ((int)pep == SYSERR)
            return SYSERR;
        blkcopy(pep->ep_dst, pni->ni_hwb.ha_addr, pae->ae_hwlen);
        pep->ep_type = EPT_ARP;
        pep->ep_order = EPO_NET;
        parp = (struct arp *) pep->ep_data;
        parp->ar_hwtype = hs2net(pae->ae_hwtype);
        parp->ar_prtype = hs2net(pae->ae_prtype);
        parp->ar_hwlen = pae->ae_hwlen;
        parp->ar_prlen = pae->ae_prlen;
        parp->ar_op = hs2net(AR_REQUEST);
        blkcopy(SHA(parp), pni->ni_hwa.ha_addr, pae->ae_hwlen);
        blkcopy(SPA(parp), &pni->ni_ip, pae->ae_prlen);
        bzero(THA(parp), pae->ae_hwlen);
        blkcopy(TPA(parp), pae->ae_pra, pae->ae_prlen);
        arplen = ARP_HLEN + 2*(parp->ar_hwlen + parp->ar_prlen);
        write(pni->ni_dev, pep, EP_HLEN+arplen); //发送请求分组
        return OK;
    }
    复制代码

    输入模块

        从一个队列中拿走一个分组,并连同解析出的物理地址一起发送给数据报链路层传输。

      主要步骤为

      1. 睡眠,直到ARP分组到达(请求或回答)。

      2. 检查高速缓存表,寻找对应这个ARP分组的项目。

      3. if ( 找到 ){

         if ( 状态是 RESOLVED ){

          更新项目;

          return;

         }

         else if ( 状态是 PENDING ){

          更新项目;

                     如果队列非空的话,将一个分组从队列中取出,将它与硬件地址一起发送给数据链路层;

          return;

         {

        }

        else{

        创建一个项目;

        将此项目添加到表中;

        return;

        }

      4.  如果分组是一个请求, 发送ARP回答。

    向表中增加已转换的表项

    复制代码
    /* arpadd.c - arpadd */
    
    #include <conf.h>
    #include <kernel.h>
    #include <network.h>
    
    struct arpentry *arpalloc(void);
    
    /*------------------------------------------------------------------------
     * arpadd - Add a RESOLVED entry to the ARP cache
     *     N.B. Assumes interrupts disabled
     *------------------------------------------------------------------------
     */
    struct    arpentry *
    arpadd(struct netif *pni, struct arp *parp)
    {
        struct    arpentry    *pae;
    
        pae = arpalloc(); //在高速缓存中分配一个表项
    
            /* 利用ARP分组信息填写表项 */
        pae->ae_hwtype = parp->ar_hwtype;
        pae->ae_prtype = parp->ar_prtype;
        pae->ae_hwlen = parp->ar_hwlen;
        pae->ae_prlen = parp->ar_prlen;
        pae->ae_pni = pni;
        pae->ae_queue = EMPTY;
        memcpy(pae->ae_hwa, SHA(parp), parp->ar_hwlen);
        memcpy(pae->ae_pra, SPA(parp), parp->ar_prlen);
            /* 初始化 */
        pae->ae_ttl = ARP_TIMEOUT;
        pae->ae_state = AS_RESOLVED;
        return pae;
    }
    复制代码

    发送等待发送的分组

    复制代码
    /* arpqsend.c - arpqsend */
    
    #include <conf.h>
    #include <kernel.h>
    #include <network.h>
    
    int netwrite(struct netif *, struct ep *, unsigned);
    
    /*------------------------------------------------------------------------
     * arpqsend - write packets queued waiting for an ARP resolution
     *------------------------------------------------------------------------
     */
    void
    arpqsend(struct arpentry *pae)
    {
        struct    ep    *pep;
        struct    netif    *pni;
    
        if (pae->ae_queue == EMPTY)
            return;
    
        pni = pae->ae_pni;
            /* 遍历等待发送的分组队列,调用netwrite逐个放入网络输出队列中 */
        while (pep = (struct ep *)deq(pae->ae_queue)) 
            netwrite(pni, pep, pep->ep_len);
        freeq(pae->ae_queue); //队列为空后,释放自身
        pae->ae_queue = EMPTY;
    }
    复制代码

    高速缓存管理

       高速缓存是用来存储IP地址与物理地址的。如果一个IP进行需要发送一个数据报,但其目的地址不在ARP高速缓存中,就会创建一个新的表项,然后广播相应的请求分组,并等待分组置入队列中。

      主要步骤:

    1. 睡眠,周期性的唤醒。

    2. 遍历高速缓存的每一个项目:

      if ( 状态为FREE )

               continue;

          if ( 状态为PENDING ){

        尝试次数+1;

        if ( 尝试次数达到最大次数 ){

          该项目状态->FREE;

              撤销相应的队列;

        }

        else {

          发送ARP请求;

        }

        continue;

      }

       else if( 状态为RESOLVED ){

        将超时字段的值减去已经过去的时间;

        若结果小于0,状态->FREE,撤销相应队列。

      }

     替换策略

    复制代码
    /* arpalloc.c - arpalloc */   
       
    #include <conf.h>   
    #include <kernel.h>   
    #include <proc.h>   
    #include <network.h>   
       
    void arpdq(struct arpentry *);   
       
    /*------------------------------------------------------------------------  
     * arpalloc - allocate an entry in the ARP table  
     *  N.B. Assumes interrupts DISABLED  
     *------------------------------------------------------------------------  
     */   
    struct arpentry *arpalloc()   
    {   
        static  int aenext = 0; //静态变量,保证循环  
        struct  arpentry *pae;   
        int i;   
       
        for (i=0; i<ARP_TSIZE; ++i) {   //遍历表
            if (arptable[aenext].ae_state == AS_FREE)   
                break;   
            aenext = (aenext + 1) % ARP_TSIZE;   //循环替换
        }   
        pae = & arptable[aenext];   
        aenext = (aenext + 1) % ARP_TSIZE;   
       
        if (pae->ae_state == AS_PENDING && pae->ae_queue >= 0)   
            arpdq(pae);   
        pae->ae_state = AS_PENDING;   
        return pae;   
    } 
    复制代码
     
     
     
    标签: 网络编程
  • 相关阅读:
    高级特性(4)- 数据库编程
    UVA Jin Ge Jin Qu hao 12563
    UVA 116 Unidirectional TSP
    HDU 2224 The shortest path
    poj 2677 Tour
    【算法学习】双调欧几里得旅行商问题(动态规划)
    南洋理工大学 ACM 在线评测系统 矩形嵌套
    UVA The Tower of Babylon
    uva A Spy in the Metro(洛谷 P2583 地铁间谍)
    洛谷 P1095 守望者的逃离
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/3448615.html
Copyright © 2011-2022 走看看