zoukankan      html  css  js  c++  java
  • 程序员训练机器学习 SVM算法分享

    http://www.csdn.net/article/2012-12-28/2813275-Support-Vector-Machine

    摘要:支持向量机(SVM)已经成为一种非常受欢迎的算法。本文主要阐述了SVM是如何进行工作的,同时也给出了使用Python Scikits库的几个示例。SVM作为一种训练机器学习的算法,可以用于解决分类和回归问题,还使用了kernel trick技术进行数据的转换,再根据转换信息在可能的输出之中找到一个最优的边界。

    【CSDN报道】支持向量机(Support Vector Machine)已经成为一种非常受欢迎的算法。在这篇文章里,Greg Lamp简单解释了它是如何进行工作的,同时他也给出了使用Python Scikits库的几个示例。所有代码在Github上都是可用的,Greg Lamp以后还会对使用Scikits以及Sklearn的细节问题进行更深一步的阐述。CSDN对本篇技术性文章进行了编译整理:

    SVM是什么?

    SVM是一种训练机器学习的算法,可以用于解决分类和回归问题,同时还使用了一种称之为kernel trick的技术进行数据的转换,然后再根据这些转换信息,在可能的输出之中找到一个最优的边界。简单来说,就是做一些非常复杂的数据转换工作,然后根据预定义的标签或者输出进而计算出如何分离用户的数据。

    是什么让它变得如此的强大?

    当然,对于SVM来说,完全有能力实现分类以及回归。在这篇文章中,Greg Lamp主要关注如何使用SVM进行分类,特别是非线性的SVM或者SVM使用非线性内核。非线性SVM意味着该算法计算的边界没有必要是一条直线,这样做的好处在于,可以捕获更多数据点集之间的复杂关系,而无需靠用户自己来执行困难的转换。其缺点就是由于更多的运算量,训练的时间要长很多。

    什么是kernel trick?

    kernel trick对接收到的数据进行转换:输入一些你认为比较明显的特征进行分类,输出一些你完全不认识的数据,这个过程就像解开一个DNA链。你开始是寻找数据的矢量,然后把它传给kernel trick,再进行不断的分解和重组直到形成一个更大的数据集,而且通常你看到的这些数据非常的难以理解。这就是神奇之处,扩展的数据集拥有更明显的边界,SVM算法也能够计算一个更加优化的超平面。

    其次,假设你是一个农场主,现在你有一个问题——你需要搭建一个篱笆来防止狼对牛群造成伤害。但是篱笆应该建在哪里呢?如果你是一个以数据为驱动的农场主,那么你就需要在你的牧场上,依据牛群和狼群的位置建立一个“分类器”,比较这几种(如下图所示)不同的分类器,我们可以看到SVM完成了一个很完美的解决方案。Greg Lamp认为这个故事漂亮的说明了使用非线性分类器的优势。显而易见,逻辑模式以及决策树模式都是使用了直线方法。

    实现代码如下:farmer.py  Python 

    1. import numpy as np 
    2. import pylab as pl 
    3. from sklearn import svm 
    4. from sklearn import linear_model 
    5. from sklearn import tree 
    6. import pandas as pd 
    7.   
    8.   
    9. def plot_results_with_hyperplane(clf, clf_name, df, plt_nmbr): 
    10.     x_min, x_max = df.x.min() - .5, df.x.max() + .5 
    11.     y_min, y_max = df.y.min() - .5, df.y.max() + .5 
    12.   
    13.     # step between points. i.e. [0, 0.02, 0.04, ...] 
    14.     step = .02 
    15.     # to plot the boundary, we're going to create a matrix of every possible point 
    16.     # then label each point as a wolf or cow using our classifier 
    17.     xx, yy = np.meshgrid(np.arange(x_min, x_max, step),
    18. np.arange(y_min, y_max, step)) 
    19.     Z = clf.predict(np.c_[xx.ravel(), yy.ravel()]) 
    20.     # this gets our predictions back into a matrix 
    21.     ZZ = Z.reshape(xx.shape) 
    22.   
    23.     # create a subplot (we're going to have more than 1 plot on a given image) 
    24.     pl.subplot(2, 2, plt_nmbr) 
    25.     # plot the boundaries 
    26.     pl.pcolormesh(xx, yy, Z, cmap=pl.cm.Paired) 
    27.   
    28.     # plot the wolves and cows 
    29.     for animal in df.animal.unique(): 
    30.         pl.scatter(df[df.animal==animal].x, 
    31.                    df[df.animal==animal].y, 
    32.                    marker=animal, 
    33.                    label="cows" if animal=="x" else "wolves", 
    34.                    color='black', 
    35.                    c=df.animal_type, cmap=pl.cm.Paired) 
    36.     pl.title(clf_name) 
    37.     pl.legend(loc="best") 
    38.   
    39.   
    40. data = open("cows_and_wolves.txt").read() 
    41. data = [row.split(' ') for row in data.strip().split(' ')] 
    42.   
    43. animals = [] 
    44. for y, row in enumerate(data): 
    45.     for x, item in enumerate(row): 
    46.         # x's are cows, o's are wolves 
    47.         if item in ['o', 'x']: 
    48.             animals.append([x, y, item]) 
    49.   
    50. df = pd.DataFrame(animals, columns=["x", "y", "animal"]) 
    51. df['animal_type'] = df.animal.apply(lambda x: 0 if x=="x" else 1) 
    52.   
    53. # train using the x and y position coordiantes 
    54. train_cols = ["x", "y"] 
    55.   
    56. clfs = { 
    57.     "SVM": svm.SVC(), 
    58.     "Logistic" : linear_model.LogisticRegression(), 
    59.     "Decision Tree": tree.DecisionTreeClassifier(), 
    60.   
    61. plt_nmbr = 
    62. for clf_name, clf in clfs.iteritems(): 
    63.     clf.fit(df[train_cols], df.animal_type) 
    64.     plot_results_with_hyperplane(clf, clf_name, df, plt_nmbr) 
    65.     plt_nmbr += 1 
    66. pl.show() 
    67.  

    让SVM做一些更难的工作吧!

    诚然,如果自变量和因变量之间的关系是非线性的,是很难接近SVM的准确性。如果还是难以理解的话,可以看看下面的例子:假设我们有一组数据集,它包含了绿色以及红色的点集。我们首先标绘一下它们的坐标,这些点集构成了一个具体的形状——拥有着红色的轮廓,周围充斥着绿色(看起来就像孟加拉国的国旗)。如果因为某些原因,我们丢失了数据集当中1/3的部分,那么在我们恢复的时候,我们就希望寻找一种方法,最大程度地实现这丢失1/3部分的轮廓。

    那么我们如何推测这丢失1/3的部分最接近什么形状?一种方式就是建立一种模型,使用剩下接近80%的数据信息作为一个“训练集”。Greg Lamp选择三种不同的数据模型分别做了尝试:

    • 逻辑模型(GLM)
    • 决策树模型(DT)
    • SVM 

    Greg Lamp对每种数据模型都进行了训练,然后再利用这些模型推测丢失1/3部分的数据集。我们可以看看这些不同模型的推测结果:

    实现代码如下:svmflag.py Python

    1. import numpy as np 
    2. import pylab as pl 
    3. import pandas as pd 
    4.   
    5. from sklearn import svm 
    6. from sklearn import linear_model 
    7. from sklearn import tree 
    8.   
    9. from sklearn.metrics import confusion_matrix 
    10.   
    11. x_min, x_max = 0, 15 
    12. y_min, y_max = 0, 10 
    13. step = .1 
    14. # to plot the boundary, we're going to create a matrix of every possible point 
    15. # then label each point as a wolf or cow using our classifier 
    16. xx, yy = np.meshgrid(np.arange(x_min, x_max, step), np.arange(y_min, y_max, step)) 
    17.   
    18. df = pd.DataFrame(data={'x': xx.ravel(), 'y': yy.ravel()}) 
    19.   
    20. df['color_gauge'] = (df.x-7.5)**2 + (df.y-5)**2 
    21. df['color'] = df.color_gauge.apply(lambda x: "red" if x <= 15 else "green") 
    22. df['color_as_int'] = df.color.apply(lambda x: 0 if x=="red" else 1) 
    23.   
    24. print "Points on flag:" 
    25. print df.groupby('color').size() 
    26. print 
    27.   
    28. figure = 
    29.   
    30. # plot a figure for the entire dataset 
    31. for color in df.color.unique(): 
    32.     idx = df.color==color 
    33.     pl.subplot(2, 2, figure) 
    34.     pl.scatter(df[idx].x, df[idx].y, colorcolor=color) 
    35.     pl.title('Actual') 
    36.   
    37.   
    38. train_idx = df.x 10 
    39.   
    40. train = df[train_idx] 
    41. test = df[-train_idx] 
    42.   
    43.   
    44. print "Training Set Size: %d" % len(train) 
    45. print "Test Set Size: %d" % len(test) 
    46.   
    47. # train using the x and y position coordiantes 
    48. cols = ["x", "y"] 
    49.   
    50. clfs = { 
    51.     "SVM": svm.SVC(degree=0.5), 
    52.     "Logistic" : linear_model.LogisticRegression(), 
    53.     "Decision Tree": tree.DecisionTreeClassifier() 
    54.   
    55.   
    56. # racehorse different classifiers and plot the results 
    57. for clf_name, clf in clfs.iteritems(): 
    58.     figure += 1 
    59.   
    60.     # train the classifier 
    61.     clf.fit(train[cols], train.color_as_int) 
    62.   
    63.     # get the predicted values from the test set 
    64.     test['predicted_color_as_int'] = clf.predict(test[cols]) 
    65.     test['pred_color'] 
    66. = test.predicted_color_as_int.apply(lambda x: "red" if x==0 else "green") 
    67.      
    68.     # create a new subplot on the plot 
    69.     pl.subplot(2, 2, figure) 
    70.     # plot each predicted color 
    71.     for color in test.pred_color.unique(): 
    72.         # plot only rows where pred_color is equal to color 
    73.         idx = test.pred_color==color 
    74.         pl.scatter(test[idx].x, test[idx].y, colorcolor=color) 
    75.   
    76.     # plot the training set as well 
    77.     for color in train.color.unique(): 
    78.         idx = train.color==color 
    79.         pl.scatter(train[idx].x, train[idx].y, colorcolor=color) 
    80.   
    81.     # add a dotted line to show the boundary between the training and test set 
    82.     # (everything to the right of the line is in the test set) 
    83.     #this plots a vertical line 
    84.     train_line_y = np.linspace(y_min, y_max) #evenly spaced array from 0 to 10 
    85.     train_line_x = np.repeat(10, len(train_line_y))
    86.  #repeat 10 (threshold for traininset) n times 
    87.     # add a black, dotted line to the subplot 
    88.     pl.plot(train_line_x, train_line_y, 'k--', color="black") 
    89.      
    90.     pl.title(clf_name) 
    91.   
    92.     print "Confusion Matrix for %s:" % clf_name 
    93.     print confusion_matrix(test.color, test.pred_color) 
    94. pl.show() 

    结论:

    从这些实验结果来看,毫无疑问,SVM是绝对的优胜者。但是究其原因我们不妨看一下DT模型和GLM模型。很明显,它们都是使用的直线边界。Greg Lamp的输入模型在计算非线性的x, y以及颜色之间的关系时,并没有包含任何的转换信息。假如Greg Lamp它们能够定义一些特定的转换信息,可以使GLM模型和DT模型能够输出更好的效果,他们为什么要浪费时间呢?其实并没有复杂的转换或者压缩,SVM仅仅分析错了117/5000个点集(高达98%的准确率,对比而言,DT模型是51%,而GLM模型只有12%!)

    局限性在哪里?

    很多人都有疑问,既然SVM这么强大,但是为什么不能对一切使用SVM呢?很不幸,SVM最神奇的地方恰好也是它最大的软肋!复杂的数据转换信息和边界的产生结果都难以进行阐述。这也是它常常被称之为“black box”的原因,而GLM模型和DT模型刚好相反,它们很容易进行理解。(编译/@CSDN王鹏,审校/仲浩)

    本文为CSDN编译整理,未经允许不得转载。如需转载请联系market@csdn.net

  • 相关阅读:
    A Year Of Books
    Spring Boot 之 RESRful API 权限控制
    Git回滚远程版本
    初探设计:Java接口和抽象类何时用?怎么用?
    深入浅出: Java回调机制(异步)
    深入浅出: 大小端模式
    Java IO 之 FileInputStream & FileOutputStream源码分析
    Java IO 之 OutputStream源码
    软件测试--安装软件
    Mybatis 中$与#的区别
  • 原文地址:https://www.cnblogs.com/DjangoBlog/p/4206921.html
Copyright © 2011-2022 走看看