前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >写给开发者的机器学习指南(十三)

写给开发者的机器学习指南(十三)

作者头像
哒呵呵
发布2018-08-06 17:40:06
5230
发布2018-08-06 17:40:06
举报
文章被收录于专栏:鸿的学习笔记鸿的学习笔记

Using Support Vector Machines (SVM's)

在我们实际使用支持向量机(SVM)之前,我先简要介绍一下SVM是什么。 基本SVM是一个二元分类器,它通过选取代表数据点之间最大间隔的超平面将数据集分成2部分。 SVM采用所谓的“校正率”值。 如果没有完美分割,校正速率允许拾取仍然在该误差率内分裂的超平面。因此,即使在线上存在一些点时,校正速率也允许超平面拟合。 这意味着我们不能为每个案例提出“标准”纠正率。 然而,当数据中没有重叠时,较低的值应该比较高的值更好。

我只是解释了基本的SVM,这是一个二元分类器,但这个相同的想法也可以用于更多的类。但是,现在我们将坚持使用2个类,因为只有2个类已经足够了。在这个例子中,我们将通过几个小例子,表示支持向量机(SVM)将优于其他分类算法,如KNN。 这种方法不同于前面的例子,但将帮助你理解如何使用SVM。

对于每个子示例,我们将提供代码,绘图,在SVM上使用不同参数的几个测试运行以及结果的说明。在第一个例子中,我们将使用GaussianKernel,但是在Smile中有很多其他的内核。 在GaussianKernel旁边,我们将解决PolynomialKernel,因为它与高斯函数有很大不同。我们将为每个示例使用以下基础代码,每个示例只更改filePath和svm结构。

代码语言:javascript
复制
object SupportVectorMachine extendsSimpleSwingApplication {
  def top = newMainFrame {
    title ="SVM Examples"
    //File path(this changes per example)
    valtrainingPath =  "/users/.../ExampleData/SVM_Example_1.csv"
    val testingPath=  "/users/.../ExampleData/SVM_Example_1.csv"
    //Loading ofthe test data and plot generation stays the same
    valtrainingData = getDataFromCSV(new File(path))
    val testingData = getDataFromCSV(newFile(path))
    val plot =ScatterPlot.plot(    trainingData._1, 
                                   trainingData._2, 
                                    '@', 
                                   Array(Color.blue, Color.green)
                                )
   peer.setContentPane(plot)
    //Here we doour SVM fine tuning with possibly different kernels
    val svm = newSVM[Array[Double]](new GaussianKernel(0.01), 1.0,2)
   svm.learn(trainingData._1, trainingData._2)
    svm.finish()
    //Calculate howwell the SVM predicts on the training set
    val predictions= testingData
        ._1
        .map(x=> svm.predict(x))
       .zip(testingData._2)
    val falsePredictions= predictions
        .map(x=> if (x._1 == x._2) 0 else 1 )
   println(falsePredictions.sum.toDouble / predictions.length  
                   * 100 + " % false predicted")
    size = newDimension(400, 400)
  }
  defgetDataFromCSV(file: File): (Array[Array[Double]], Array[Int]) = {
    val source =scala.io.Source.fromFile(file)
    val data =source
        .getLines()
        .drop(1)
        .map(x=> getDataFromString(x))
        .toArray
    source.close()
    val dataPoints= data.map(x => x._1)
    valclassifierArray = data.map(x => x._2)
    return(dataPoints, classifierArray)
  }
  defgetDataFromString(dataString: String): (Array[Double], Int) = {
    //Split thecomma separated value string into an array of strings
    val dataArray:Array[String] = dataString.split(',')
    //Extract thevalues from the strings
    valcoordinates  = Array(dataArray(0).toDouble, dataArray(1).toDouble)
    val classifier:Int = dataArray(2).toInt
    //And returnthe result in a format that can later 
    //easily beused to feed to Smile
    return(coordinates, classifier)
  }

例一:(Gaussian Kernel)

在这个例子中,我们提出了SVM最常用的内核,即高斯内核。 这个例子背后的想法是帮助在这个内核上找到好的输入参数。我们用于这个例子的数据可以在这里下载。

从该图可以清楚地看出,线性回归不起作用。 相反,我们将使用SVM进行预测。在我们给出的第一个代码中,高斯内核的σ为0.01,余量为1.0,类数为2,传递给SVM。 该内核表示SVM将在系统中的数据点对上计算相似性的方式。对于高斯核,使用欧几里得距离的方差。 选择高斯核的具体原因是因为数据不包含诸如线性,多项式或双曲线函数的清楚的结构。 相反,数据聚集在3个组中。

我们在GaussianKernel的构造函数中传递的参数是sigma。 该σ值表示内核的平滑度值。 我们将展示更改此参数会如何影响预测。 作为边际惩罚,我们通过1。该参数定义系统中的向量的余量,因此使得该值更低从而导致更多的边界向量。 我们将展示一组运行和他们的结果在实践中有什么样的效果。注意,s:表示西格玛,c:表示校正惩罚。 百分比表示预测中的误差率,其仅仅是训练后对相同数据集的假预测的百分比。

c, s->

0.001

0.01

0.1

0.2

0.5

1.0

2.0

3.0

10.0

0.001

48.4%

48.4%

48.4%

48.4%

48.4%

48.4%

48.4%

48.4%

48.4%

0.01

48.4%

48.4%

40%

43.8%

48.4%

48.4%

48.4%

48.4%

48.4%

0.1

48.4%

48.4%

12.4%

14.2%

17.4%

48.4%

48.4%

48.4%

48.4%

0.2

48.4%

45.6%

9.1%

10.1%

12.3%

48.4%

48.4%

48.4%

48.4%

0.5

47.5%

3.4%

6.3%

7.2%

7%

8.9%

48.4%

48.4%

48.4%

1.0

0%

1.6%

5.1%

5.7%

5.6%

5.6%

48.4%

48.4%

48.4%

2.0

0%

1%

5.2%

5%

5.4%

5.7%

13.1%

48.4%

51.6%

3.0

0%

1.2%

6.4%

5.8%

5.7%

7.4%

18%

51.6%

51.6%

10.0

0%

1.5%

7.5%

6.4%

7.7%

12.9%

26.2%

51.6%

51.6%

100.0

0%

1.5%

10.1%

12.8%

14.6%

18.3%

41.6%

51.6%

51.6%

不幸的是,没有为每个数据集找到正确的sigma的金科玉律。 可能是最好的方法之一是计算您的数据的sigma,这是√(方差),然后步步逼近该值,看看哪个sigma表现良好。由于该数据的方差在0.2和0.5之间,我们将其作为中心,并在该中心的每一侧探索几个值,以在我们的情况下看到具有高斯内核的SVM的性能。当我们观察结果表及其假预测百分比时,表明最佳性能是以非常低的西格马(0.001)和1.0及以上的校正率。 然而,如果我们在实践中使用这个模型与新数据,它可能过拟合。 这就是为什么在根据自己的训练数据测试模型时应该始终小心。更好的方法是执行交叉验证或验证未来的数据。

例二 (Polynomial Kernel)

高斯内核并不总是最好的选择,即使它是最常用的被选择的内核。 这就是为什么在这个例子中,我们将展示一个多项式内核优于高斯内核的情况。注意,即使构造了这种情况的示例数据,也可以在字段中找到类似的数据(具有更多的噪声)。 我们用于这个例子的训练数据可以在这里下载,测试数据在这里。对于示例数据,我们创建了2个具有多项式次数为3的类,并生成了测试和训练数据文件。 训练数据包含x轴上的前500个点,而测试数据包含x轴上从500到1000的点。 为了看到为什么多项式内核将工作,我们绘制数据。 左图是训练数据,右图是测试数据。

对基本代码做一下替换:

val trainingPath = "/users/.../ExampleData/SVM_Example_2.csv"

val testingPath = "/users/.../ExampleData/SVM_Example_2_Test_data.csv"

并得到以下结果:

c, s->

0.01

0.1

0.2

0.5

1.0

2.0

3.0

10.0

100.0

0.001

50%

50%

50%

50%

50%

50%

50%

50%

50%

0.01

50%

50%

50%

50%

50%

50%

50%

50%

39.8%

0.1

50%

50%

50%

50%

50%

49.4%

49.1%

47.5%

35.4%

0.2

50%

50%

50%

50%

49.4%

49.2%

48.8%

47.1%

34.3%

0.5

50%

49.9%

49.8%

49.5%

49.3%

48.9%

48.6%

46.8%

33.1%

1.0

50%

49.8%

49.7%

49.4%

49.4%

48.9%

48.6%

46.2%

50%

2.0

50%

49.8%

49.7%

49.4%

49.3%

49.2%

48.8%

45.7%

31.7%

3.0

50%

49.8%

49.7%

49.8%

49.5%

49%

48.8%

46.2%

27.4%

10.0

50%

49.8%

49.7%

49.4%

49.3%

49%

48.4%

46.7%

33.2%

100.0

50%

49.8%

49.7%

49.4%

49.3%

49.1%

48.6%

46.7%

32.2%

我们看到,即使在最好的情况下,仍有27.4%的测试数据被错误地分类。这很有趣,因为当我们看看图形时,可以在两个类之间找到一个非常清晰的区别。 我们可以微调sigma和校正率,但是当预测点非常远(x为100000)时,sigma和校正率将达到很高的水平,以达到良好的性能(时间和预测)。

修改内核:

val svm = new SVM[Array[Double]](new PolynomialKernel(2),1.0,2)

注意我们如何在PolynomialKernel的构造函数中传递2。 这2表示它试图适应的特征的程度。 如果我们不仅对于2度执行运行,而且对于2,3,4,5度执行运行,并且对于校正率再次从0.001变化到100,我们得到以下结果:

degree: 2

degree: 3

degree: 4

degree: 5

c: 0.001

49.7%

0%

49.8%

0%

c: 0.01

49.8%

0%

49.8%

0%

c: 0.1

49.8%

0%

49.8%

0%

c: 0.2

49.8%

0%

49.8%

0%

c: 0.5

49.8%

0%

50%

0%

c: 1.0

49.9%

0%

50%

0%

c: 2.0

50%

0%

47.9%

0%

c: 3.0

38.4%

0%

50%

0%

c: 10.0

49.5%

0%

49.5%

0%

c: 100.0

49.5%

0%

49.5%

0%

在这里,我们看到测试数据,其中不包含与训练数据的单个重叠点,获得100%准确度为3和5.这是一个惊人的性能相比,高斯内核与27.4%的最佳情况。 请注意,这个示例数据是构造的,因此不包含很多噪声。 这就是为什么所有“校正率”的误差率为0%的原因。 如果你增加噪声,将需要微调这种校正率。关于支持向量机的部分到此结束。

完结撒花!

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2016-11-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 鸿的学习笔记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档