More supervise learning Alg

之前提到过三种简单基础的监督学习算法,但是选择还有更多种:

  • KNN(思路易于理解,熟悉其结合KD-tree来其优化算法的时间性能)
  • ADAboost
  • Random Forests

请尝试使用scikit-learn来得到各类算法的准确度,与运行时间!

KNN

KNN的思路很容易理解,简单地说就是,给定N个样本空间,一个询问点p,求距离询问点最近的K个点(最后根据这K个点的类标号中占比最大的标号,即为询问点的类标号)。

优化:使用KD-tree 这种数据结构来优化,主要过程是 建树 + 询问前k小

相关资料
- 很好懂的文章:KD树详解
- 一份KD-Tree的C++实现:HDOJ 4347

用于理解的C++代码:

//-------------------------------------------------------------
 #include <queue>
 #include <cstdio>
 #include <cstring>
 #include <algorithm>
 using namespace std;
 const int N = 55555, K = 5;
 const int inf = 0x3f3f3f3f;

 #define sqr(x) (x)*(x)
 int k,n,idx;   //k为维数,n为点数
 struct point
 {
     int x[K];
     bool operator < (const point &u) const
     {
         return x[idx] < u.x[idx];
     }
 }po[N];

 typedef pair<double,point> tp;
 priority_queue<tp> nq;

 struct kdTree
 {
     point pt[N<<2];
     int son[N<<2];

     void build(int l, int r, int rt = 1, int dep = 0)
     {
         if(l > r) return;
         son[rt] = r - l;
         son[rt*2] = son[rt*2+1] = -1;
         idx = dep % k;
         int mid = (l + r) / 2;
         nth_element(po + l, po + mid, po + r + 1);
         pt[rt] = po[mid];
         build(l, mid - 1, rt * 2, dep + 1);
         build(mid + 1, r, rt * 2 + 1, dep + 1);
     }
     void query(point p, int m, int rt = 1,int dep = 0)
     {
         if(son[rt] == -1) return;
         tp nd(0, pt[rt]);
         for(int i = 0;i < k;i ++) nd.first += sqr(nd.second.x[i] - p.x[i]);
         int dim = dep % k, x = rt * 2, y = rt * 2 + 1, fg = 0;
         if(p.x[dim] >= pt[rt].x[dim]) swap(x, y);
         if(~son[x]) query(p, m, x, dep + 1);
         if(nq.size() < m) nq.push(nd), fg = 1;
         else
         {
             if(nd.first < nq.top().first) nq.pop(), nq.push(nd);
             if(sqr(p.x[dim] - pt[rt].x[dim]) < nq.top().first) fg = 1;
         }
         if(~son[y]&&fg) query(p, m, y, dep + 1);
     }
 }kd;
 void print(point &p)
 {
     for(int j = 0;j < k;j ++) printf("%d%c",p.x[j], j == k-1 ? '\n' : ' ');
 }
 int main()
 {
     while(scanf("%d%d", &n, &k) != EOF)
     {
         for(int i = 0;i < n;i ++) for(int j = 0;j < k;j ++) scanf("%d", &po[i].x[j]);
         kd.build(0, n-1);
         int t, m;
         for(scanf("%d", &t);t --;)
         {
             point ask;
             for(int j = 0;j < k;j ++) scanf("%d", &ask.x[j]);
             scanf("%d", &m); kd.query(ask, m);
             printf("the closest %d points are:\n", m);
             point pt[20];
             for(int j = 0;!nq.empty();j ++) pt[j] = nq.top().second, nq.pop();
             for(int j = m - 1;j >= 0;j --) print(pt[j]);
         }
     }
     return 0;
 }

ADAboost

ADAboost(Adaptive boost 自适应增强),是一个不断更新迭代的过程。其算法步骤为:
(1)、初始化各个样本点的权重为1/NN为样本总数。训练得到初步的分类器: G1(x) ,计算出这个分类器的误差率:

em=i=1i=NWiI(G1(xi)!=yi)
(其中 wi指第 i个样本的权值),计算这个分类器的权重:
am=12log1emem

可以看出,对于第一次的分类,如果误差率较高,那么这个分类器所占权重 am将会比较小。
(2)、进行第 m+1(m>=1)次迭代过程:
计算每个样本的权值:
Wi,m+1=Wi,mZmeamyiGm(xi)
得到新的权值集合。接下来重新训练样本的得到分类器 Gm+1(x) ,同理按照上述的公式去计算这个费类其的误差率,以及这个分类器的权重。
(3)、组合各个分类器,得到最终的分类器:
f(x)=i=1i=MaMGM(x)

G(x)=sign(f(x))

具体详细的文章,参考:Adaboost详细过程及证明

Random Forests

随机森林(Random Forests),由多棵决策树来投票选择最终的分类结果,而每一颗决策树是怎样构成的呢?
(1)、如果训练集大小为N,对于每颗决策树来说,随机且有放回的从训练集中抽取n个样本,作为该树的训练集。
(2)、每个样本的特征维度为M随机地从M个特征维度中选择m个特征子集,构建决策树时,从这m个特征子集进行划分。
(3)、每棵树都尽最大程度的生长,并且没有剪枝过程。

思考
一开始我们提到的随机森林中的“随机”就是指的这里的两个随机性。两个随机性的引入对随机森林的分类性能至关重要。由于它们的引入,使得随机森林不容易陷入过拟合,并且具有很好得抗噪能力(比如:对缺省值不敏感)。

随机森林分类效果(错误率)与两个因素有关:

(1)、森林中任意两棵树的相关性:相关性越大,错误率越大;
森林中每棵树的分类能力:每棵树的分类能力越强,整个森林的错误率越低。
(2)、减小特征选择个数m,树的相关性和分类能力也会相应的降低;增大m,两者也会随之增大。所以关键问题是如何选择最优的m(或者是范围),这也是随机森林唯一的一个参数。

结合实例详细的文章:讲解非常清晰的RF介绍

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值