sparkml下实现的多分类adaboost+naivebayes算法在文本分类上的应用

野路子程序员 野路子程序员     2022-09-10     105

关键词:

1. Naive Bayes算法

朴素贝叶斯算法算是生成模型中一个最经典的分类算法之一了,常用的有Bernoulli和Multinomial两种。在文本分类上经常会用到这两种方法。在词袋模型中,对于一篇文档$d$中出现的词$w_0,w_1,...,w_n$, 这篇文章被分类为$c$的概率为$$p(c|w_0,w_1,...,w_n) = frac{p(c,w_0,w_1,...,w_n)}{p(w_0,w_1,...,w_n)} = frac{p(w_0,w_1,...,w_n|c)*p(c)}{p(w_0,w_1,...,w_n)}$$ 对于一篇给定文章,分母为常数,基于朴素贝叶斯的各词在一篇文章中出现独立性假设,最后我们需要比较的就是在不同类别$c$下$p(w_0|c)*p(w_1|c)*...*p(w_n|c)*p(c)$的大小。

naive bayes模型的参数就是在每个类别$c$下各词出现的概率的$p(w_0|c),p(w_1|c),...,p(w_n|c))$和该类别出现的概率$p(c)$,参数的估计通常就是根据训练样本进行词频的统计并计算相应概率,其中$$p(c) = frac{count(c)}{count(doc)}$$,即为训练数据中c类别文章的总数量除以训练集中文章的总数量。针对$p(w_i|c)$的估计,Bernoulli和Multinomial略有不同。

  • Bernoulli

  文章中某词$ w_i$出现过,则记为1,所以$$p(w_i|c) = frac{count(w_i,c)}{count(c)}$$ 即为在类别为c的训练集文章中出现词$w_i$的文章数量除以训练集中为别为c的文章总数量

  • Multinomial

  这种情况下文章的词并不是非0即1的one hot特征,而是带有权重的数值特征,通常可以使用tf或者tf-idf值。$$p(w_i|c) = frac{T_{ci}}{sum_{t}{T_{ct}}}$$ 其中$T_{ci}$为类别c的训练文章中词$w_i$的所有权重和,$sum_{t}{T_{ct}}$为类别c的文章中所有词的权重之和。预测的时候对于词$w_i$计算该词在该文章中的权重$T_i$,使用$p(w_i|c)^{T_i}$作为连乘部分的概率。不过实际上经常使用对数概率,所以可以将指数运算变为乘法运算,在代码中就可以利用矩阵相乘直接计算。

还有一些细节问题,例如数据稀疏,平滑处理等因为不是本文的重点,这里就不详细解释了。

2. Adaboost算法

作为一种boosting方法,adaboost在很多算法上都有着不俗的表现。不过在基于naive bayes的文档分类领域,貌似实际效果很一般。在stack overflow上也看到有人讨论,说adaboost对于多个弱分类器的提升效果很不错,但是naive bayes的文档分类通常已经有很不错的表现了,提升效果一般。不过不管效果提升怎么样,实现一下试试也没什么坏处,顺便还可以熟悉一下spark的相关操作。经典的adaboost算法适用于二分类的情况,但是我们的文本是多分类的情况,依靠多个二分类器表决不失为一种方法,但是比较麻烦,好在找到了介绍多分类adaboost算法的论文,照着论文依葫芦画瓢也不难。下面先分别多分类和二分类的adaboost

2.1 二分类adaboost

对于给定的二类分类的训练数据集$$T = {(x_1, y_2),(x_2, y_2)...,(x_N, y_N)}$$ 其中每个$x$是一个样本的特征向量,$yin{-1, +1}$,算法流程如下:

  1. 初始化各个样本的权重为$$D_1 = (w_{11}, w_{12}, ... , w_{1i}, ... , w_{1N}),  w_{1i} = frac{1}{N}, i = 1, 2, ... , N$$
  2. 对于第m次迭代,$m = 1, 2, ..., M$:
    • 每次迭代使用带有当前权重$D_m$的样本进行训练,得到一个基本分类器$G_m(x)$
    • 计算在分类器$D_m$下,训练样本分类结果的误差率$$e_m = sum^{N}_{i = 1}{w_{mi}I(G_m{x_i} eq{y_i})}$$,因为每一步权重都做了归一化,所以分母不用再除以样本权重之和
    • 根据误差率$e_m$计算分类器$D_m$的系数 $$alpha_m = logfrac{1-e_m}{e_m}$$
    • 根据系数$alpha_m$更新各样本的权重$$D_{m+1} = {w_{m+1, 1}, w_{m+1, 2}, ... , w_{m+1, N}}$$ $$w_{m+1, i} = w_{m, i} * exp(alpha_m * I(G_m{x_i} eq{y_i}))$$
    • 对$D_{m+1}$做归一化处理,使$sum_{i = 1}^{N}{w_{m+1, i}} = 1$
  3. 最后对多个分类器$D_m$的结果进行加权表决,$$c(x) = argmax_ksum_{m = 1}^{M}{alpha_m*I(D_m(x) = k)}$$

注意到对于二分类的adaboost需要每次的分类误差率$e_m leq{frac{1}{2}}$,否则的话将会导致$alpha_m < 0$,然后样本权重的更新将会朝着反方向进行。

2.2 多分类adaboost

对于K分类的情况,算法基本与二分类的情况一致。但是要求每次的分类误差率$e_m leq{frac{1}{2}}$是非常困难的,联系到二分类误差率阈值选择$frac{1}{2}$,K分类的情况选择误差率为$frac{K-1}{K}$,然后$alpha_m$的计算改为 $$alpha_m = log(frac{1-e_m}{e_m}) + log(K-1)$$ 容易验证只要$e_m leq{frac{K-1}{K}}$,则有$alpha_m geq{log(frac{1-frac{K-1}{K}}{frac{K-1}{K}}) + log(K-1)} = log(frac{1}{K-1}) + log(K-1) = 0$,这种情况下,多分类adaboost对于被误分的样本的侧重加大了,因为$alpha_m$因为添加了正项$log(K-1)$而增大了。

 

adaboost的一种解释是模型为加法模型,损失函数为指数函数,学习算法为前向分步算法的分类算法,这个以后再另外写一篇。这里给出一个比较直观好懂的解释:

  • 迭代过程中误差率小的模型具有大的模型系数,也就是说表现好的子模型在最后加权的时候具有更大的“话语权”
  • 迭代过程中上一次被误分的样本在下一次训练时将会具有更大的权重,更容易被分类正确

3. Spark ML的使用

提到Spark ml就不得不提Spark mllib,两者的区别主要在于ml面向的数据是Dataset,而mllib面向的是rdd,Dataset相当于在底层rdd的基础上做了进一步的优化。而且ml中一系列算法更适合创建包含从数据清洗到特征工程再到模型训练等一系列工作的ML pipelines,这个类似于sklearn中的pipeline,非常简洁好用。

pipeline中的Transformer,Estimator,Stage等概念官方文档上写的很清楚,而且还有事例,就不在这里解释了。这里以naive bayes为例简单介绍一下怎么利用spark ml的pipelines进行机器学习模型的训练和预测。

首先是pipelines的创建:

 1   // pipeline for train
 2   def createPipiline(dataset: Dataset[_]): Pipeline = {
 3     // step 1 sentence 拆成 words
 4     val tokenizer = new RegexTokenizer().setInputCol("sentence").setOutputCol("words").setPattern(",")
 5     // step 2 label 转化为以0开始的labelIndex 为了适应spark.ml
 6     val indexer = new StringIndexer().setInputCol("label").setOutputCol("labelIndex").fit(dataset)
 7     // step3 统计tf词频
 8     val countModel = new CountVectorizer().setInputCol("words").setOutputCol("rawFeatures")
 9     // step4 tf-idf
10     val idfModel = new IDF().setInputCol("rawFeatures").setOutputCol("features")
11     // step5 normalize tf-idf vector
12     val normalizer = new Normalizer().setInputCol("features").setOutputCol("normalizedFeatures")
13     // step6 naive bayes model
14     val naiveBayes = new NaiveBayes().setFeaturesCol("normalizedFeatures").setLabelCol("labelIndex").setWeightCol("obsWeights").setPredictionCol("prediction").setModelType("multinomial").setSmoothing(1.0)
15     // step7 predict label to real label
16     val labelConverter = new IndexToString().setInputCol("prediction").setOutputCol("predictedLabel").setLabels(indexer.labels)
17 
18     new Pipeline().setStages(Array(tokenizer, indexer, countModel, idfModel, normalizer, naiveBayes, labelConverter))
19   }

 

这里注意到我在创建这个pipeline的时候还传入了训练数据,但是一般情况下训练数据是在拟合模型而不是在模型建立的时候就提前传入的。这里是因为最后面那个labelConverter的transformer需要使用indexer.labels这个参数,而indexer要获取这个参数就要提前拟合训练数据,也就是indexer的创建发生在整个pipeline的拟合之前,所以我就先穿入了训练数据集。注意到这里训练数据就相当于被训练了两次,所以可以先cache()操作一下。

pipeline创建好以后的使用就相对简单多了,传入数据就可以了。

1 val pipeline = ModelUsage.createPipeline(dataRDDTrain)
2 // train and test
3 val combinedModel = pipeline.fit(dataRDDTrain)
4 val predictResult = combinedModel.transform(dataRDDTest).select("predictedLabel", "label").rdd.map(row => (row.getDouble(0), row.getDouble(1)))
5 val evaluator = new MulticlassMetrics(predictResult)
6 
7 println("confusionMatrix:")
8 println(evaluator.confusionMatrix)
9 println(evaluator.accuracy)

注意到ML拟合的结果都是Double类型的,比如说我一个label是55但是输出是55.0,评估模型准确度的时候注意一下就好,影响不大。

Spark ML的一个好处是数据dataset像水一样通过预先创建好的pipeline,可以指定每一个stage处理的column名,再添加生成的数据到新的一列。自始至终,这些中间数据都在结果的dataset里,想要哪些数据指定列名就可以了。这样的话就避免了每次都要处理数据使它们符合中间模型的输入结构,而且最后还要自己再整合需要的字段到一起。

由于我们的文章数据特点比较鲜明,没有任何参数调优,在4w(80% train 20% test)的四分类数据上就已经有了95%的正确率了。

4. 自定义扩展Spark ML

既然直接用现有naive bayes模型就已经有了95%的正确率,那要是加上adaboost呢?

直接实现adaboost算法很简单,但是毕竟spark ml的pipeline这么好用,而dataset这么好的封装加上这么多现有的类似StringIndxer等工具类transformer总不能全部重写吧。所以就想到怎么去自定义一个跟Spark ML兼容的model,上网查了查发现了以下几篇比较有用的文章。

Extend Spark ML for your own model/transformer types

spark的NaiveBayes实现源码

结合这两篇文章的内容,在已有的naivebayes模型基础上进行了改进实现了与Spark ML兼容的adaboost naivebayes model。

注意:

1. 由于我们的模型需要先拟合训练数据得到模型,随后才能使用模型,这里面分别涉及到estimator和transformer,因此我们需要分别实现这两个部分。

2. 我要实现的adaboost+naivebayes模型是一个概率模型,因此我的Estimator和Transformer分别继承自ProbabilisticClassifier和ProbabilisticClassificationModel,而不是最原始的Estimator和Transformer,这样就减少了很多不必要的代码重写,但是如果是想玩玩整整自己实现一个模型的话就要从最基本的一点点开始写了,可以参照上面第一篇文章所讲,这里就不多细说了。

当然可能会有疑问,既然可以继承ProbabilisticClassifier,那为什么不直接集成NaiveBayes不是更简单么?我一开始也是这样想的,但是发现Spark ML里NaiveBayes里大部分方法和属性都是私有或者受保护的,我要改就得修改Spark源码,但是我的Spark程序是在公司服务器运行的,总不能每次都让公司用我改过之后的Spark包吧。。。

4.1 模型参数

首先,对于任何一个模型模型的训练,我们一般都会需要传递一些参数,这里利用scala的trait实现一个参数接口。

 1 trait AdaboostNaiveBayesParams extends Params {
 2   // 进行adaboost时的最高迭代次数
 3   final val maxIter: IntParam = new IntParam(this, "maxIter", "max number of iterations")
 4   def getMaxIter: Int = $(maxIter)
 5   // 进行adaboost时准确率变化小于某个阈值时迭代提前终止
 6   final val threshold: DoubleParam = new DoubleParam(this, "threshold", "improvement threshold among iterations")
 7   def getThreshold: Double = $(threshold)
 8   // 朴素Bayes的平滑系数
 9   final val smoothing : DoubleParam = new DoubleParam(this, "smoothing", "naive bayes smooth")
10   def getSmoothing : Double = $(smoothing)
11   // 朴素Bayes类型"multinomial"(default) and "bernoulli"
12   final val modelType : Param[String] = new Param[String](this, "modelType", "naive bayes model type")
13   def getModelType : String = $(modelType)
14 }

这一部分没什么解释的,都是一些模型常用参数。

4.2 模型Estimator

这一部分可以说是最重要的部分,Estimator拟合好了,Transformer基本属于调用一下就好了。先贴代码,再一行行解释。

  1 class AdaboostNaiveBayes(override val uid: String)
  2   extends ProbabilisticClassifier[Vector, AdaboostNaiveBayes, AdaboostNaiveBayesModel]
  3   with AdaboostNaiveBayesParams {
  4 
  5   def this() = this(Identifiable.randomUID("AdaboostNaiveBayes"))
  6 
  7   // model parameters assignment
  8   def setMaxIter(value: Int): this.type = set(maxIter, value)
  9   def setThreshold(value: Double): this.type = set(threshold, value)
 10   def setSmoothing(value: Double): this.type = set(smoothing, value)
 11   def setModelType(value: String): this.type = set(modelType, value)
 12 
 13   setMaxIter(20)
 14   setThreshold(0.02)
 15   setSmoothing(1.0)
 16   setModelType("multinomial")
 17 
 18   // method used by fit()
 19   override protected def train(dataset: Dataset[_]): AdaboostNaiveBayesModel = {
 20 
 21     val datasetSize = dataset.count().toInt
 22     val labelSize = dataset.select("label").distinct().count()
 23 
 24     // 各子模型及其权重
 25     val modelWeights = new Array[Double]($(maxIter))
 26     val modelArray = new Array[NaiveBayesModel]($(maxIter))
 27 
 28     var alpha = 0.0
 29     // 初始化各样本等权重
 30     val dataWeight: (Double, Double, Double) => Double = (obsWeight: Double, labelIndex: Double, prediction: Double) => {
 31       if (labelIndex == prediction) {
 32         obsWeight
 33       }
 34       else {
 35         obsWeight * math.exp(alpha)
 36       }
 37     }
 38     val sqlfunc = udf(dataWeight)
 39     // 初始化还没有prediction
 40     var temp = dataset.withColumn("obsWeights", lit(1.0))
 41     var i = 0
 42     var error1 = 2.0
 43     var error2 = 1.0// && (error1 - error2) > $(threshold)
 44     var weightSum = datasetSize.toDouble*datasetSize
 45 
 46     while (i < $(maxIter)) {
 47       val naiveBayes = new NaiveBayes().setFeaturesCol($(featuresCol)).setLabelCol($(labelCol)).setWeightCol("obsWeights")
 48         .setPredictionCol($(predictionCol)).setModelType($(modelType)).setSmoothing($(smoothing)).fit(temp)
 49       temp = naiveBayes.transform(temp).cache() 
 50 
 51       var error = temp.select("labelIndex", "prediction", "obsWeights").rdd.map(row => {
 52         if (row(0) != row(1))
 53           row.getDouble(2)
 54         else
 55           0.0
 56       }
 57       ).sum()/(datasetSize)
 58       val t5 = System.nanoTime()
 59       error1 = error2
 60       error2 = error
 61       alpha = Math.log((labelSize - 1) * (1 - error) / error)
 62 
 63       modelWeights(i) = alpha
 64       modelArray(i) = naiveBayes
 65       // 更新权重
 66       temp = temp.withColumn("obsWeights", sqlfunc(col("obsWeights"), col($(labelCol)), col($(predictionCol))));
 67       weightSum = temp.select("obsWeights").rdd.map(row => (row.getDouble(0))).sum()
 68       temp = temp.drop($(predictionCol), $(rawPredictionCol), $(probabilityCol))
 69       temp = temp.withColumn("obsWeights", col("obsWeights")/(weightSum/datasetSize)) 70 
 71       i += 1
 72     }
 73 
 74     new AdaboostNaiveBayesModel(uid, i, modelWeights, modelArray)
 75   }
 76 
 77   override def copy(extra: ParamMap): AdaboostNaiveBayes = defaultCopy(extra)
 78 }

1-3行是继承ProbabilisticClassifer和实现前面我们自己定义的AdaboostNaiveBayesParam参数接口,ProbabilisticClassifer的继承使用看看源码里NaiveBayes是怎么做的就可以照着学了。

5行是一个最基本的构造函数,分配给对象一个id值

77行是一个拷贝构造函数,这个必须要实现,最简单的可以直接像这里一样调用defaultCopy函数就好了。这个函数用来在引入新的参数的时候复制当前stage返回加入新参数后的一个新模型

8-11行是给模型设定初始参数用的,这几个函数没有定义在AdaboostNaiveBayesParam里是因为这些参数的传入只发生在模型拟合前,在预测的时候是不能设定的,所以对后面的Transformer应该是不可见的,因此只在这里定义。注意到这些函数的返回类型和模型类型一致,其实就是每一步都返回一个加入的参数的新的模型,这里就利用了之前的拷贝构造函数。

13-16行是给模型设定默认参数。

19行开始的train函数就是我们在对模型调用fit方法时使用的函数。返回的是一个AdaboostNaiveBayesModel,是我们随后需要定义的跟AdaboostNaiveBayes这个Estimator对应的Transformer。

21-22行分别获取数据集的数量和其中label的数量

25-26是初始化所有子模型及其权重,因为adaboost每一次迭代都会生成一个新的模型并计算该模型在最终结果投票时的权重。

30-38是一个自定义udf函数,对每个样本计算预测的label和真实label,并根据该样本的现有权重obsWeight进行更新,可以理解为如果分类正确,其权重不变,否则增大其权重。

40行 初始化所有样本为等权重,如果样本数据非常不平衡的话,可以尝试在这一步就引入偏差权重,我由于使用的数据各个类之间数量是一样的,所以全部初始话为1

41-44行初始化一些错误率等参数

46行开始进行adaboost迭代过程。

47-49行是在当前样本权重情况下调用普通的NaiveBayes进行训练的到当前迭代下的子模型

49行这个cache一定不能少,否则迭代的速度只能呵呵了,毕竟temp用到了非常多次的action。

51-57行是计算该模型的错误率

59-61行是更新误差,并计算该模型的权重alpha

63-64行是保存当前子模型和权重

66-69行是利用之前定义的udf函数更新所有样本的权重并对其进行归一化

74 行是利用计算得到的参数去构建一个AdaboostNaiveBayesModel,这里传入所有的子模型及其权重,i表示的是总迭代次数,就是子模型的数量。

4.3 模型Transformer

这里要实现的AdaboostNaiveBayesModel是从ProbabilisticClassificationModel,因此要手动实现对应的必须要的几个方法。

代码如下:

 1 class AdaboostNaiveBayesModel(override val uid: String, val iternums: Int, val modelWeights: Array[Double], val modelArray: Array[NaiveBayesModel])
 2   extends ProbabilisticClassificationModel[Vector, AdaboostNaiveBayesModel]
 3   with AdaboostNaiveBayesParams {
 4 
 5   override val numClasses = modelArray(0).pi.size
 6 
 7   private def multinomialCalculation(features: Vector): Vector = {
 8     val result: Vector = new DenseVector(new Array(numClasses))
 9     for (i <- 0 until iternums) {
10       val prob: Vector = modelArray(i).theta.multiply(features)
11       prob.foreachActive { (index, value) => {
12         prob.toArray(index) = value + modelArray(i).pi(index)
13         }
14       }
15       result.toArray(prob.argmax) = result(prob.argmax) + modelWeights(i)
16     }
17     result
18   }
19 
20   override def predictRaw(features: Vector): Vector = {
21     multinomialCalculation(features)
22   }
23 
24   override def raw2probabilityInPlace(rawPrediction: Vector): Vector = {
25     rawPrediction match {
26       case dv: DenseVector =>
27         var i = 0
28         val size = dv.size
29         val maxLog = dv.values.max
30         for (i <- 0 until size) {
31           dv.values(i) = math.exp(dv.values(i) - maxLog)
32         }
33         val probSum = dv.values.sum
34 
35         for (i <- 0 until size) {
36           dv.values(i) = dv.values(i) / probSum
37         }
38         dv
39       case sv: SparseVector =>
40         throw new RuntimeException("Unexpected error in AdaboostNaiveBayesModel:" +
41         " raw2probabilityInPlace encountered SparseVector")
42     }
43   }
44  override def copy(extra: ParamMap) = {
45   defaultCopy(extra)
46  }
47 }

第5行是读取一下总的标签个数以供后面使用

44-46行是拷贝构造函数

20-22行是对一个输入计算它在各个label下的得分,这个得分的大小表示的是判断到该标签概率的大小,但是并不是概率值,因为我们的BayesModel模型参数是做了log变换的

24-43行是怎么讲结果向量转化为和为1的概率值,30-32行是个小技巧,我一开始好奇为什么一定要减掉maxLog,因为这个按理说并不会影响到后面的计算结果,后来发现这样能避免浮点数的问题,因为不减的话,会出现求完math.exp后值约为零的情况,导致后面的计算出现问题

这样就完成了概率模型需要的几个方法了,可以对一个输入给出一个概率向量,每个维度代表在这个类的概率。

5. 写在最后

利用自定义的adaboost+naivebayes模型,测试准确率从95%增加到了96.5%左右。由于训练数据比较好,95%已经很不错了,这里主要是通过写一个自定义模型学习一下Spark ML方面的知识。之前都只是听说过,从来没用过,学习一下还是很有必要的,毕竟不能总指望着单机就能搞定所有问题。

不过注意到这里我并不是从0开始造轮子,我是从ProbabilisticClassification继承过来加以修改的,如果想要做其他模型的修改还是推荐看上面的两篇文章,然后多看看Spark ML源码里类似的模型并根据自己的需要进行修改。

然后scala也是为了用Spark ML现学的,代码可以优化的地方估计很多。

这是本人第一篇博客,希望以后可以坚持写,作为对自己工作学习的总结笔记。

 

adaboost对实际数据分类的julia实现

写在前面AdaBoost是机器学习领域一个很重要很流行的算法,而Julia是一门新兴的发展迅速的科学计算语言。本文将从一个实际例子出发,展示如何用Julia语言实现AdaBoost算法。什么是AdaBoost这方面的资料有很多,我将基于Hastie和Tibsh... 查看详情

机器学习——提升方法adaboost算法,推导过程

0提升的基本方法  对于分类的问题,给定一个训练样本集,求比较粗糙的分类规则(弱分类器)要比求精确的分类的分类规则(强分类器)容易的多。提升的方法就是从弱分类器算法出发,反复学习,得到一系列弱分类器(... 查看详情

pythonadaboost的简单实现

初学adaboost,自己尝试着写了下adaboost的实现,这个实现以几个简单的数字作为训练样本,当然,这些数字是带标签的。然后尝试着使用adaboost对其分类。对于10个带标签的数字,分类他们只需要3个左右的弱分类器级... 查看详情

adaboost原理与理论

Adaboost是一种迭代算法,其核心思想是针对同一个训练集训练不同的分类器(弱分类器),然后把这些弱分类器集合起来,构成一个更强的最终分类器(强分类器)。其算法本身是通过改变数据分布来实现的,它根据每次训练集之中每... 查看详情

使用随机森林作为带有 adaboost 的基础分类器

】使用随机森林作为带有adaboost的基础分类器【英文标题】:usingrandomforestasbaseclassifierwithadaboost【发布时间】:2021-07-0217:33:55【问题描述】:我可以将AdaBoost与随机森林一起用作基础分类器吗?我在互联网上搜索,我没有找到任... 查看详情

6-9haar+adaboost人脸识别

...析了Haar特征的概念以及如何计算Haar特征,并介绍了Haar+Adaboost分类器它们的组合以及Adaboost分类器如何使用和训练。这节课我们将通过代码来实现一下Haar+Adaboost分类器实现的人脸识别。计算jpg图片的haar特征,不过这一步opencv已... 查看详情

adaboost算法详解(haar人脸检测)(代码片段)

Adaboost是一种迭代算法,其核心思想是针对同一个训练集训练不同的分类器(弱分类器),然后把这些弱分类器集合起来,构成一个更强的最终分类器(强分类器)。Adaboost算法本身是通过改变数据分布来实现的,它根据每次训... 查看详情

haar+adaboost制作自己的分类器过程(代码片段)

目录做haar特征的原因以下几个网站都可以学注意的点问题实现代码做haar特征的原因有些深度学习的目标检测算法有时候在物体非常相近的时候,误检率会非常高。所以我们可以先进行深度学习然后检测出大概的区域,然后再使... 查看详情

adaboost

...成。代表算法是boosting系列算法。在boosting系列算法中,Adaboost是最著名的算法之一。第二类是个体学习器之间不存在强依赖关系,一系列个体学习器可以并行生成,代表算法是bagging和随机森林(RandomForest)系列算法。。Adaboost既... 查看详情

scalascala学习资料

...现-CSDN博客学习:java设计模式—分类-飞翔荷兰人-博客园SparkMLlib分类算法之决策树学习-DamonDr-博客园【SparkMllib】决策树,随机森林——预测森林植被类型-简书Spark入门实战系列--8.SparkMLlib(下)--机器学习库SparkML 查看详情

机器学习---算法---adaboost

...自:https://blog.csdn.net/px_528/article/details/72963977写在前面说到Adaboost,公式与代码网上到处都有,《统计学习方法》里面有详细的公式原理,Github上面有很多实例,那么为什么还要写这篇文章呢?希望从一种更容易理解的角度,来为... 查看详情

利用adaboost提高分类性能

Adaboost为一种集成算法,是对其他算法进行组合的一种方式。本文将通过单层决策树分类器建立一个Adaboost优化算法,即利用多个弱分类器构建一个强分类器。弱分类器:分类器性能比随机猜测要略好,但是也不会好太多。强分... 查看详情

GentleBoost n 元分类器?

...寻找关于n-aryGentleBoost分类器的资源或实现。我见过许多Adaboost实现,Matlab的Ensemble中GentleBoost的一个实现,但它似乎总是二进制。WEKA也只有AdaBoost实现,没有GentleBoost。大家有什么建议吗-如何获 查看详情

adaboost理解

AdaBoost是一种准确性很高的分类算法,它的原理是把K个弱分类器(弱分类器的意思是该分类器的准确性较低),通过一定的组合(一般是线性加权进行组合),组合成一个强的分类器,提高分类的准确性。因此,要想使用AdaBoost,需要... 查看详情

cart(决策分类树)原理和实现

前面我们了解了决策树和adaboost的决策树墩的原理和实现,在adaboost我们看到,用简单的决策树墩的效果也很不错,但是对于更多特征的样本来说,可能需要很多数量的决策树墩或许我们可以考虑使用更加高级的弱分类器,下面... 查看详情

机器学习-分类器-adaboost原理

Adaboost原理          Adaboost(AdaptiveBoosting)是一种迭代算法,通过对训练集不断训练弱分类器,然后把这些弱分类器集合起来,构成强分类器。adaboost算法训练的过程中,初始化所有训练样例的具... 查看详情

机器学习算法-adaboost

本章内容组合类似的分类器来提高分类性能应用AdaBoost算法处理非均衡分类问题主题:利用AdaBoost元算法提高分类性能1.基于数据集多重抽样的分类器-AdaBoost长处泛化错误率低,易编码,能够应用在大部分分类器上,无需參数调整... 查看详情

关于adaboost分类器(代码片段)

我花了将近一周的时间,才算搞懂了adaboost的原理。这根骨头终究还是被我啃下来了。Adaboost是boosting系的解决方案,类似的是bagging系,bagging系是另外一个话题,还没有深入研究。Adaboost是boosting系非常流行的算法。但凡是介绍boo... 查看详情