决策树的训练过程

2023-10-31

决策树--------以分类有毒和无毒蘑菇为例

 

这里的原始数据是agaricus-lepiota.data文件。每一行代表一个样本,每一列代表一个特征,这里一共8024个样本,每个样本有22个特征。其中第一列是样本标签,标示有毒(p)和无毒(e)。除此之外,还有22列,代表22个特征。有些特征缺失,用?表示。下面是一部分数据的例子。

p,x,s,n,t,p,f,c,n,k,e,e,s,s,w,w,p,w,o,p,k,s,u

e,x,s,y,t,a,f,c,b,k,e,c,s,s,w,w,p,w,o,p,n,n,g

e,b,s,w,t,l,f,c,b,n,e,c,s,s,w,w,p,w,o,p,n,n,m

p,x,y,w,t,p,f,c,n,n,e,e,s,s,w,w,p,w,o,p,k,s,u

e,x,s,g,f,n,f,w,b,k,t,e,s,s,w,w,p,w,o,e,n,a,g

e,x,y,y,t,a,f,c,b,n,e,c,s,s,w,w,p,w,o,p,k,n,g

e,b,s,w,t,a,f,c,b,g,e,c,s,s,w,w,p,w,o,p,k,n,m

e,b,y,w,t,l,f,c,b,n,e,c,s,s,w,w,p,w,o,p,n,s,m

p,x,y,w,t,p,f,c,n,p,e,e,s,s,w,w,p,w,o,p,k,v,g

 

 

将这些数据创建成特征向量数据data(8024*22),标签数据responses(8024*1),丢失特征数据missing(8024*22)。用下面接口实现训练的过程。

dtree = new CvDTree;

tree->train( data, CV_ROW_SAMPLE, responses, 0, 0, var_type, missing,

                  CvDTreeParams( 8, // max depth

                                 10, // min sample count

                                 0, // regression accuracy: N/A here

                                 true, // compute surrogate split, as we have missing data

                                 15, // max number of categories (use sub-optimal algorithm for larger numbers)

                                 10, // the number of cross-validation folds

                                 true, // use 1SE rule => smaller tree

                                 true, // throw away the pruned tree branches

                                 priors // the array of priors, the bigger p_weight, the more attention

                                        // to the poisonous mushrooms

                                        // (a mushroom will be judjed to be poisonous with bigger chance)

                                 ));

 

 

 

 

 

 

下面详细讲解一下训练的过程。

(1)train核心是使用do_train函数

bool CvDTree::do_train( const CvMat* _subsample_idx )

 

(2)do_train函数核心是使用try_split_node函数

void CvDTree::try_split_node( CvDTreeNode* node )

{

    CvDTreeSplit* best_split = 0;

    int i, n = node->sample_count, vi;

    bool can_split = true;

    double quality_scale;

 

calc_node_value( node );//修改CvDTree中的成员变量CvDTreeTrainData* data

//统计每一类的样本个数,并将其写入data的counts成员变量中,counts为矩阵

 

//节点的样本个数小于参数的最小样本数或者节点的深度大于最大深度,此函数返回

//否则,不断进行分裂

    if( node->sample_count <= data->params.min_sample_count ||

        node->depth >= data->params.max_depth )

        can_split = false;

 

    if( can_split && data->is_classifier )

    {

        // check if we have a "pure" node,

        // we assume that cls_count is filled by calc_node_value()

//如nz=1,则该节点纯净度为0,即不再需要分裂

int* cls_count = data->counts->data.i;

        int nz = 0, m = data->get_num_classes();

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

            nz += cls_count[i] != 0;

        if( nz == 1 ) // there is only one class

            can_split = false;

    }

    else if( can_split )

    {

        if( sqrt(node->node_risk)/n < data->params.regression_accuracy )

            can_split = false;

    }

 

    if( can_split )

    {

        best_split = find_best_split(node);//find_best_split是核心

        // TODO: check the split quality ...

        node->split = best_split;

    }

    if( !can_split || !best_split )

    {

        data->free_node_data(node);

        return;

    }

 

    quality_scale = calc_node_dir( node );

    if( data->params.use_surrogates )

    {

        // find all the surrogate splits

        // and sort them by their similarity to the primary one

       。。。。。。。缺失特征的处理

    }

    split_node_data( node );//根据最优分裂的特征进行分裂

    try_split_node( node->left );//左分支继续递归

    try_split_node( node->right );//右分支继续递归

}

 

      try_split_node函数本质就是不断递归的过程,不断对新分裂的左右节点分别继续分裂,直至节点纯度为0,或者节点的样本数达到最小标准或者节点的深度达到最大深度的条件。

针对每个节点分裂为两个子节点时,总是要寻找最优的分裂组合,即find_best_split实现这个过程。以蘑菇为例,该函数找出当前节点下,选取22个特征的最优组合,每个特征选出其取值的最优组合。

 

(3)try_split_node函数重点是使用find_best_split函数,下面着重介绍一下find_best_split函数,find_best_split函数通过下面这句命令,实现此过程。

cv::parallel_reduce(cv::BlockedRange(0, data->var_count), finder);

 

实际上,parallel_reduce是调用body函数,其中重载了操作符()。即实际上是执行下面的函数。

void DTreeBestSplitFinder::operator()(const BlockedRange& range)

{

int vi, vi1 = range.begin(), vi2 = range.end();//上面的data->var_count为特

//征的总个数,对应于蘑菇的例子,特征总数为22,所以这里的vi1= 0,vi2 =22

int n = node->sample_count;//n为node中样本的个数,蘑菇例子中,如果是根节点,

//n为8124,下一级左边节点为4364

    CvDTreeTrainData* data = tree->get_data();

    AutoBuffer<uchar> inn_buf(2*n*(sizeof(int) + sizeof(float)));

 

    //蘑菇的22个特征依次循环,找到最优的分裂特征

    for( vi = vi1; vi < vi2; vi++ )

    {

        CvDTreeSplit *res;

        int ci = data->get_var_type(vi);

        if( node->get_num_valid(vi) <= 1 )

            continue;

 

        if( data->is_classifier )

        {

            if( ci >= 0 )

                res = tree->find_split_cat_class( node, vi, bestSplit->quality, split, (uchar*)inn_buf );

           。。。。。//分类回归调用不同的接口,这里先只看分类

        }

 

// bestSplit为DTreeBestSplitFinder的成员变量,保存最优的分裂特征

        if( res && bestSplit->quality < split->quality )

                memcpy( (CvDTreeSplit*)bestSplit, (CvDTreeSplit*)split, splitSize );

    }

}

 

4重点是find_split_cat_class函数,该函数能够找到指定的某个特征vi对应的最优分裂的值域组合。比如指定的特征vi对应着颜色特征,该特征的值域有红,黄,蓝三个,find_split_cat_class就会找出最优的值域组合,使得分裂后不纯度最小,如(红,蓝)为左边分支,黄为右边分支。

 

CvDTreeSplit* CvDTree::find_split_cat_class( CvDTreeNode* node, int vi, 

float init_quality,CvDTreeSplit* _split, uchar* _ext_buf )

{

    。。。。。

    int m = data->get_num_classes();//m 为分类的种类,如有毒和无毒两种蘑菇,m=2

    int _mi = data->cat_count->data.i[ci], mi = _mi;//mi为特征vi对应值的种类个数,//如蘑菇的颜色特征有红黄蓝绿紫黑六种,则mi=6

   。。。。。。

    //以下均以2类问题为例

    int* lc = (int*)base_buf;//lc为1*2的数组,存储左边分支的正负样本数目

    int* rc = lc + m; //rc为1*2的数组,存储右边分支的正负样本数目

int* _cjk = rc + m*2, *cjk = _cjk; //cjk为6*2的数组,存储所有样本按照颜色特

//征取不同值时,相应的正负样本数目。

 

// c_weights为6*1的数组,存储所有样本按照颜色特征取不同值时,相应的样本权重

//个数。即为cjk数组的每一行求和,即某个特征的某个特征取值对应的正负样本个数

//分别与其权重乘积之后求和

double* c_weights = (double*)alignPtr(cjk + m*mi, sizeof(double)); 

 

// labels为所有样本颜色特征的对应值,为8124的数组,数组的每个值对应一个样本

//相应的颜色取值,如0~5中的一个

// responses为所有样本对应的正负标签,为8124的数组,数组的每个值对应一个样本

//为正样本,还是负样本

    int* labels_buf = (int*)ext_buf;

    const int* labels = data->get_cat_var_data(node, vi, labels_buf);

    int* responses_buf = labels_buf + n;

    const int* responses = data->get_class_labels(node, responses_buf);

 

   。。。。。。。。。。。

    double L = 0, R = 0;

    double best_val = init_quality;

    int prevcode = 0, best_subset = -1, subset_i, subset_n, subtract = 0;

    const double* priors = data->priors_mult->data.db;

 

    // init array of counters:

    // c_{jk} - number of samples that have vi-th input variable = j and response //= k.

//cjk为6*2的数组,存储所有样本按照颜色特征取不同值时,相应的正负样本数目。

//即特征vi取值为j时,对应的k样本的数目(k为正或者负两种取值)

 

    for( j = -1; j < mi; j++ )

        for( k = 0; k < m; k++ )

            cjk[j*m + k] = 0;

 

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

    {

       j = ( labels[i] == 65535 && data->is_buf_16u) ? -1 : labels[i];

       k = responses[i];

       cjk[j*m + k]++;

    }

 

    if( m > 2 )

    {

       。。。。。。。。聚类

    }

    else

{

        //将int_ptr按照样本数目大小排序,数目大的排在上面,以便后面循环找特征值//,按照int_ptr的顺序寻找最优分裂,int_ptr的某一行对应着cjk的某一行

        assert( m == 2 );

        int_ptr = (int**)(c_weights + _mi);

        for( j = 0; j < mi; j++ )

int_ptr[j] = cjk + j*2 + 1;// int_ptr为cjk矩阵中的行指针+1,即指向

//负样本数目,假设cjk第一列为正样本数目,第二列为负样本数目

        icvSortIntPtr( int_ptr, mi, 0 );

        subset_i = 0;

        subset_n = mi;//寻找最优值域需要的尝试次数,次数为值域的个数,即为6

    }

 

//lc为1*2的数组,存储右边分支的正负样本数目,这里初始化为0,

//后面每取出颜色特//征的一个某取值时,lc将加上其正负样本数目,

//即lc为选用颜色特征的某个值域时,左边分支的正负样本数目,

//左边分支的样本的颜色特征是属于这个值域的。

 

//rc为1*2的数组,存储右边分支的正负样本数目,这里分别初始化为所有的正样本数目//和负样本数目,后面每取出颜色特征的一个某取值时,rc将减去其正负样本数目

//即rc为选用颜色特征的某个取值时,右边分支的正负样本数目

//右边分支的样本的颜色特征是不属于这个值域的。

    for( k = 0; k < m; k++ )

    {

        int sum = 0;

        for( j = 0; j < mi; j++ )

            sum += cjk[j*m + k];

        rc[k] = sum;

        lc[k] = 0;

    }

 

 

// c_weights为6*1的数组,存储所有样本按照颜色特征取不同值时,相应的样本权重//个数。即为cjk数组的每一行求和,即某个特征的某个特征取值对应的正负样本个数/ //分别与其权重乘积之后求和

 

// L存储左边分支的正负样本个数与其权重乘积之后的累积和,这里初始化为0

//后面每取出颜色特征的一个某取值时,L将加上其对应的样本权重数目,即加上//c_weights的对应值

//即L为选用颜色特征的某个取值时,左边分支的样本权重数目

//左边分支的样本的颜色特征是属于这个值域的。

 

// R存储右边分支的正负样本个数与其权重乘积之后的累积和,这里初始化为

//c_weights的累积和,即为所有样本的个数和其权重乘积之和

//后面每取出颜色特征的一个某取值时,R将减去其对应的样本权重数目,即减去//c_weights的对应值

//即R为选用颜色特征的某个取值时,右边分支的样本权重数目

//右边分支的样本的颜色特征是不属于这个值域的。

    for( j = 0; j < mi; j++ )

    {

        double sum = 0;

        for( k = 0; k < m; k++ )

            sum += cjk[j*m + k]*priors[k];

        c_weights[j] = sum;

        R += c_weights[j];

    }

 

    //6次尝试,寻找最优值域组合,6为颜色特征的取值种类数。

//理论上讲,应该进行2的6次方减2次尝试,但是2分类问题,可以采用这种方法简化

    for( ; subset_i < subset_n; subset_i++ )

    {

        double weight;

        int* crow;

        double lsum2 = 0, rsum2 = 0;

 

        if( m == 2 )

            idx = (int)(int_ptr[subset_i] - cjk)/2; //idx为cjk的某一行,这里为0~5

        else

        {

            。。。。。。

        }

 

        crow = cjk + idx*m;  //crow为cjk的行指针,cjk的某一行对应着指定特征的

//某一个取值,如0行代表红色的正负样本数,1行代表蓝色的正负样本数,等等

        weight = c_weights[idx];//特征的某个取值对应的正负样本数的权重累计和。

        if( weight < FLT_EPSILON )

            continue;

 

        //

        if( !subtract )

        {

            for( k = 0; k < m; k++ )

            {

int t = crow[k]; //crow为指定特征的某一个取值对应的

//正样本数,负样本数

int lval = lc[k] + t;// lval为指定特征的某一个取值之前的所有取

//值(包含该取值)对应的正样本个数,负样本个数

int rval = rc[k] - t; // rval为指定特征的某一个取值之前的所有取//值(包含该取值)对应的正样本个数,负样本个数的补集,即不满足指

//定的特征取值的正样本个数,负样本个数

double p = priors[k], p2 = p*p;//p为正样本的权重(1/11)和负样

//本的权重(10/11)

sum2 += p2*lval*lval;// lsum2为指定特征的某一个取值之前的所有

//取值(包含该取值)对应的正样本个数的权重累积和与负样本个数权重

//累积和之和

rsum2 += p2*rval*rval; // rsum2为指定特征的某一个取值之前的所有//取值(包含该取值)对应的正样本个数的权重累积和的补集与负样本个

//数权重累积和的补集只和

 

                lc[k] = lval; rc[k] = rval;

            }

            L += weight;

            R -= weight;

        }

        else

        {

           。。。。。

        }

 

        if( L > FLT_EPSILON && R > FLT_EPSILON )

        {

            //找出纯度最小,即val最大的分类

            double val = (lsum2*R + rsum2*L)/((double)L*R);

            if( best_val < val )

            {

                best_val = val;

                best_subset = subset_i;

            }

        }

    }

 

    CvDTreeSplit* split = 0;

    if( best_subset >= 0 )

    {

        split = _split ? _split : data->new_split_cat( 0, -1.0f );

        split->var_idx = vi;// split->var_idx用来标识该分裂使用哪个特征

        split->quality = (float)best_val;

        memset( split->subset, 0, (data->max_c_count + 31)/32 * sizeof(int));

        //每个特征取值对应subset的一位,其对应关系和cjk中的取值排列顺序一致

        //每个int为32位,每个subset最多对应32个取值种类数

if( m == 2 )

        {

            //设置分裂的特征值域为best_subset之前对应的所有取值

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

            {

                //idx是cjk排序后的特征值对应的顺序

idx = (int)(int_ptr[i] - cjk) >> 1;      

 

//1左移idx位( 当idx<32),即为2的idx次方

//即split->subset用每一位表示是否使用颜色特征的这个值,1表示

//使用,0表示未使用

//如果cjk的第一行为红色,第二行为蓝色,第三行为绿色,。。。。。

//则split->subset第一位为红色,第二位为蓝色,第三位为绿色。。。。

//这里位的顺序是按照从右往左计算的

split->subset[idx >> 5] |= 1 << (idx & 31);

            }

        }

        else

        {

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

            {

                idx = cluster_labels ? cluster_labels[i] : i;

                if( best_subset & (1 << idx) )

                    split->subset[i >> 5] |= 1 << (i & 31);

            }

        }

    }

    return split;

}

 

(5)需要指出上面计算分裂不纯度是用下面的程序实现的:

double val = (lsum2*R + rsum2*L)/((double)L*R);

然后找出是val最大时对应的取值。

 

理论上讲,不纯度是使用下面的公式:

其中pi为某类样本出现的概率,二类问题分别对应着正样本的概率和负样本的概率。

最优分裂是不纯度最小时对应得分裂。

 

上面之所以求val最大值,即求的是不纯度公式中的求和这一项。

上面的公式是某个节点的不纯度,当分裂后,会变成两个节点,此时该特征的某值域对应的分裂的不纯度中求和项为:

 

 

由于某次分裂中,(L+R)是固定值,对应着分裂前所有正负样本的权重累积和。当寻找某个特征对应的最优分裂值域时,使用的样本是一样的,因此在某个节点的最优分裂的比较中,L+R是一个定值。因此计算的val如下:

double val = (lsum2*R + rsum2*L)/((double)L*R);

 


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

决策树的训练过程 的相关文章

  • 掌握Python的X篇_4+5_开发工具ipython与vscode的安装使用,作业

    本篇将会介绍两个工具的安装及使用来提高Python的编程效率 ipython 比python更好用的交互式开发环境 vscode 本身是文本编辑器 通过安装相关的插件vscode可以作为python集中开发环境使用 掌握Python的X篇
  • 【Servlet】HTTP的Servlet实现

    在JavaEE的Servlet规范中 实现HTTP协议由 javax servlet http HttpServlet类 实现 该类封装了一系列的请求和响应操作 使得开发者直接实现功能逻辑 而不必关乎网络连接 错误处理等 对于该类的众多AP
  • kafka集群搭建和使用Java写kafka生产者消费者

    转载自 http chengjianxiaoxue iteye com blog 2190488 1 kafka集群搭建 Java代码 1 zookeeper集群 搭建在110 111 112 2 kafka使用3个节点110 111 11
  • 数据挖掘背景知识2——数据挖掘可以做到什么 带给我们什么?

    本文是数据挖掘学习课堂笔记的一个补充 是一个了解级别的文章 欢迎各位大佬指出不足的地方 文章目录 数据挖掘的定义 数据挖掘与数据分析的区别 数据挖掘的应用场景 1 教育领域 2 风控领域 3 医疗领域 数据挖掘存在的问题 本文参考了CSDN
  • 什么是网络安全?

    一 什么是网络安全 1 网络安全 网络安全指网络系统中的硬件 软件以及系统中的数据受到保护 不因偶然或恶意的原因而遭到破坏 更改 泄露 系统连续可靠正常地运行 网络服务不中断 网络安全包括 网络设备安全 网络软件安全和网络信息安全 凡是涉及
  • js如何实现一个简单的节流函数?

    聚沙成塔 每天进步一点点 专栏简介 实现简单的节流函数 写在最后 专栏简介 前端入门之旅 探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅 这个专栏是为那些对Web开发感兴趣 刚刚踏
  • 解读startx

    X 的虚拟终端下的蜂鸣声可通过 xset b off 关闭 此命令 可放在 startx 的配置文件 HOME xinitrc 中 X 的虚拟终端下的蜂鸣声可通过 xset b off 关闭 此命令 可放在 startx 的配置文件 HOM
  • 07. 实战:Python正则法抓取某网站2022必看片迅雷种子

    目录 前言 URL 在评论区 URL 在评论区 URL 在评论区 目的 URL 在评论区 URL 在评论区 URL 在评论区 思路 URL 在评论区 URL 在评论区 URL 在评论区 代码实现 第一步 先导包 第二步 请求源代码 第三步
  • iwebsec靶场 SQL注入漏洞通关笔记7- 空格过滤绕过

    系列文章目录 iwebsec靶场 SQL注入漏洞通关笔记1 数字型注入 mooyuan的博客 CSDN博客 iwebsec靶场 SQL注入漏洞通关笔记2 字符型注入 宽字节注入 mooyuan的博客 CSDN博客 iwebsec靶场 SQL
  • Linux实验:Shell编程

    对思考题4 8 进行编辑 然后执行 功能 输入的所有参数逆序输出显示 对思考题 4 14 进行编辑 然后执行 功能 显示裴波那契数列前10项及它们的和 对思考题4 18 进行编辑 然后执行 功能 输出输入字符串中抽取的第n个字符至第m个字符
  • 【python】考前复习,python基础语法知识点整理

    文章目录 1 常量与表达式 2 变量和数据类型 创建变量 数据类型 动态类型 数据类型的转换 3 注释 4 字符串 字符串的定义方式 字符串的拼接 字符串的格式化 字符串格式化的精度控制 字符串的格式化 对表达式进行格式化 5 从控制台输入
  • 【Android Jetpack】新一代导航管理——Navigation

    目录 前言 使用Navigation 创建导航视图 添加页面 添加导航 添加导航宿主 实现导航 原理解析 NavHostFragment 支持ToolBar 总结 前言 不知道小伙伴们是否注意到 用AS创建一个默认的新项目后 MainAct
  • 软件测试——性能测试

    性能测试基础 为什么要进行性能测试 WHY 最重要 应用程序是否能够很快的响应用户的要求 应用程序是否能处理预期的用户负载并有盈余能力 应用程序是否能处理业务所需要的事务数量 在预期和非预期的用户负载下 应用程序是否稳定 是否能够确保用户在
  • ISAAC WORKSPACE FILE

    Copyright 2019 NVIDIA CORPORATION All rights reserved NVIDIA CORPORATION and its licensors retain all intellectual prope
  • [需求管理-2]:什么是需求以及需求的收集与识别

    作者主页 文火冰糖的硅基工坊 文火冰糖 王文兵 的博客 文火冰糖的硅基工坊 CSDN博客 本文网址 需求管理 2 什么是需求以及需求的收集与识别 文火冰糖的硅基工坊的博客 CSDN博客 目录 第1章 什么是需求识别 第2章 需求的来源 2
  • 算法题 货仓选址(Python)

    题目 在一条数轴上有 N 家商店 它们的坐标分别为 A1 AN 现在需要在数轴上建立一家货仓 每天清晨 从货仓到每家商店都要运送一车商品 为了提高效率 求把货仓建在何处 可以使得货仓到每家商店的距离之和最小 输入格式 第一行输入整数N 第二
  • File类读取文件---本地文件和网络文件

    读取本地文件 File file new File resource audio 5 mp3 InputStream in null try 一次读多个字节 byte tempbytes new byte 100 int byteread
  • Vue项目开发环境安装、项目构建运行、打包部署详解

    Vue项目开发环境安装 项目构建运行 打包部署详解 背景 Vue工程化项目环境配置还是比较麻烦的 本篇来详细的记录下从0开始的安装 构建 打包 运行全过程 整体步骤 第一 安装Node js 这个是前端工程化项目运行的基础环境 第二 安装V
  • Java 网络编程 —— RMI 框架

    概述 RMI 是 Java 提供的一个完善的简单易用的远程方法调用框架 采用客户 服务器通信方式 在服务器上部署了提供各种服务的远程对象 客户端请求访问服务器上远程对象的方法 它要求客户端与服务器端都是 Java 程序 RMI 框架采用代理

随机推荐

  • 【程序员面试系列】算法题练习-汇总(含华为OD机试题目)

    做个4月算法刷题集合 方便复习巩固 欢迎交流探讨 题库源于牛客网 ACM模式 语言 Java Python 题库链接 HJ1 字符串最后一个单词的长度 描述 计算字符串最后一个单词的长度 单词以空格隔开 字符串长度小于5000 注 字符串末
  • 如何修复损坏的word

    Word是许多人在日常工作中经常使用的软件 但有时它可能会出现意外的崩溃或文档损坏 这对于你正在编辑的文件和工作的进展都会产生重大影响 但是 你不需要过于担心 因为还是有一些方法可以通过修复Word文档中的损坏来解决这个问题 那么如何修复损
  • TCP三次握手,两次可以吗?

    这个问题网络上的回答超级多 众说纷纭 以 RFC 793 来回答这个问题可能更加准确 Reliability The TCP must recover from data that is damaged lost duplicated or
  • C语言——qsort()函数用法

    qsort函数简介及用法 一 qsort 函数的简介 二 qsort 函数实例 1 排序整形数组 2 排序double型数组 3 排序字符型数据 4 结构体类型数据排序 三 使用冒泡排序模拟qsort 函数 一 qsort 函数的简介 qs
  • ' requires string as left operand, not int' aria-label='TypeError: 'in ' requires string as left operand, not int'> TypeError: 'in ' requires string as left operand, not int

    报错 Traceback most recent call last File D PyCharm 5 0 3 WorkSpace 2 NLP 9 DL在NLP中的应用 4 VectorizerVisualization py line 4
  • docker和k8s的关系

    docker和k8s的关系 过去十年间 云计算的技术得到了长足的发展 越来越多的人开始了解 云原生 技术 以著名的云原生计算基金会 CNCF Cloud Native Computing Foundation 为首 各大企业和社区都开始发展
  • javascript:;与javascript:void(0)使用介绍

    最近看了好几个关于 a 标签和javascript void 0 的帖子 谨记于此 以资查阅 注 以下代码未经全面测试 但每一种方法可能会出现的情况都基本做了说明 在做页面时 如果想做一个链接点击后不做任何事情 或者响应点击而完成其他事情
  • 一文读懂CAN总线及通信协议

    CAN总线的汽车 CAN概念 CAN是控制器域网 Controller Area Network CAN 的简称 是由研发和生产汽车电子产品著称的德国BOSCH公司开发了的 并最终成为国际标准 ISO11898 是ISO国际标准化的串行通信
  • CTFSHOW web入门——web171

    首先查询有多少列 1 order by 3 然后查询库名 1 union select 1 2 database 查看ctfshow web库的表 1 union select 1 2 table name from information
  • AtomicInteger如何保证线程安全?

    1 AtomicInteger不是final类型 如何保证线程安全 先看一下AtomicInteger类局部源码 关注两个字段 U以及value public class AtomicInteger extends Number imple
  • 使用Kalibr工具线对相机+IMU离线标定

    传感器标定的准确后面做算法才会更准确 所以对Kalibr进行学习 一 Kalibr编译 1 下载kalibr包 GitHub下载地址 2 解压后放到 catkin ws src文件夹下 重新命令文件夹为kalibr 3 安装依赖库 sudo
  • wireshark抓包tcp为何没有四次挥手 而是三次挥手

    在wireshark上抓包 使用telnet直接连接baidu的ip 端口使用www p4 u1804 ping www baidu com PING www a shifen com 183 232 231 174 56 84 bytes
  • LDA(latent dirichlet allocation)的应用

    主题模型LDA latent dirichlet allocation 的应用还是很广泛的 之前我自己在检索 图像分类 文本分类 用户评论的主题词抽取等都用过 做feature 降维等 例如可以用主题维度来表示原来的字典维度 大大的降低了文
  • 最新骗局:利用支付宝快捷支付 套取手机验证码转账

    最新骗局 利用支付宝快捷支付 套取手机验证码转账 小心 骗子在你不知情的情况下 也能帮你开通支付宝快捷支付 昨天 市民王先生向媒体反映 骗子通过QQ知道他的银行账号等信息后 又通过花言巧语骗取他的手机验证码 替他开通支付宝快捷支付功能 并转
  • LeetCode-1237. 找出给定方程的正整数解【双指针,二分查找】

    LeetCode 1237 找出给定方程的正整数解 双指针 二分查找 题目描述 解题思路一 双指针 首先我们不管f是什么 即function id等于什么不管 但是我们可以调用customfunction中的f函数 然后我们遍历x y 1
  • 如何在Idea打开一个本地项目(超详细版)

    背景 网上关于Idea的介绍和使用其实很多了 但是答应了某人还是要写一个打开项目的详细教程 下载项目压缩包 从本地打开 比如说我下载一个海大校园通的项目到本地 解压后 打开Idea 在左上角点击File gt New gt Project
  • 手把手,如何搭建一个通用组件库?(文档+样式+按需打包

    之前的文章 手把手 如何搭建一个通用组件库 并发布到npm 搭建了一个简单的组件库框架 并发布到了npm 在文章结果也留了几个个坑 1 没有样式 2 文档系统也没有 3 组件也不能按需加载 我们今天来一一解决 样式系统 搭建之前 先来看看e
  • 永久设置pip指定国内镜像源(含Windows和Linux)

    永久设置pip指定国内镜像源 含Windows和Linux 前言 首先来看一下Python临时指定安装的镜像源 命令格式 sudo pip3 install 包名 i 镜像源url eg sudo pip3 install redis i
  • MySQL_第00章_MySQL数据库基础篇大纲

    第00章 写在前面 一 MySQL数据库基础篇大纲 MySQL 数据库基础篇分为 5 个篇章 1 数据库概述与MySQL安装篇 第 01 章 数据库概述 第 02 章 MySQL 环境搭建 2 SQL之SELECT使用篇 第 03 章 基本
  • 决策树的训练过程

    决策树 以分类有毒和无毒蘑菇为例 这里的原始数据是agaricus lepiota data文件 每一行代表一个样本 每一列代表一个特征 这里一共8024个样本 每个样本有22个特征 其中第一列是样本标签 标示有毒 p 和无毒 e 除此之外