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;   
    } 
    复制代码
     
     
     
    标签: 网络编程
  • 相关阅读:
    AutoFac (控制反转IOC 与依赖注入DI)
    【干货】利用MVC5+EF6搭建博客系统(一)EF Code frist、实现泛型数据仓储以及业务逻辑
    Log4.Net 在Winfrom、MVC、ashx程序里的使用,ashx程序里使用异步
    触发器
    游标的使用
    sql数据库快照与恢复 规则绑定
    磁盘恢复
    修改sql数据库名称
    MVC学习笔记
    NuGet包和功能
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/3448615.html
Copyright © 2011-2022 走看看