zoukankan      html  css  js  c++  java
  • 机器学习——支持向量机(Support Vector Machines)

    使用SVM时的注意事项:

    1.支持向量机本身不能较好的支持非标准化数据。建议将数据标准化

    SVM实现详细过程
    https://blog.csdn.net/qq_30189255/article/details/54571370?utm_source=blogxgwz5

    一、大体内容

    给简短的文字实现分类。两种方法:

    1.sklearn:自己提取特征采用朴素贝叶斯(NaiveBayes)、

      逻辑回归(LogisticRegression)、支持向量机(SupportVectorMechine)

    2.使用liblinera工具

      直接把分词之后的所有词作为特征,甚至每一个字作为特征。近似于数据挖掘构造特征。

    二、特征选择的方法

    TF-IDF  

      词频-逆文档频率。TFIDF的主要思想是:如果某个词或短语在一篇文章中出现的频率TF高,并且在其他文章中很少出现,则认为此词或者短语具有很好的类别区分能力,适合用来分类。需要注意的是每个词在不同的文章中有不同的TF-IDF值,我的处理方式是每个文本中取值最大的三个词,然后把这些词做去重操作。

    卡方检验CHI

      在文本分类的特征选择阶段中,我们主要关心一个问题:词条t与类别C是否相互独立1)相互独立,说明词条t对类别c完全没有表征能。2)不独立,说明词条t对类别c有一定的表征能力。而这个公式就是在假设词条与类别c相互独立地情况下算出来的误差函数,误差越大说明越不独立,也就和此类别越相关。

      

      • N:训练数据集文档总数
      • A:包词词条t,同时属于类别c的文档的数量
      • B:包含词条t,但是不属于类别c的文档的数量
      • C:属于类别c,但是不包含词条t的文档的数量
      • D:不属于类别c,同时也不包含词条t的文档的数

    事非做不知道,如此小的一个知识点我实现了一遍就发现了好几个问题

    1. 公式还可以进一步化简,比如A+C,为属于类别c的文档数量,对于每一个词条来说都是固定的,也就没必要计算。
    2. 卡方的缺点是夸大了低频词的重要性,比如一个词,只在此类文章中出现了一次,跟在文章中出现了100次的词的作用性是相同的。
    3. 如果词在此类文章中出现的次数为0,那么卡方值会是一个固定值。
    4. 每个词在不同类中的卡方值是不同的,取最高的,最后一起排序去重。

    卡房检验的代码

    三、使用sklearn中的算法实现多分类

    利用上面的方法提取了10000个特征,不要利用sklearn自带的方法去将文档变成向量,那样内存会爆掉。我的方法是将特征存入列表,遍历文档的每一行,遍历词的列表,如果文本中包含这个词,则将向量值置为tfidf值或者1,前者要好一点,然后写入txt文本。在调用方法进行计算的时候,再从文本中读取向量。

    分类结果

    这里主要关注NB、LR和SVM的准确度和速度。

    准确度:SVM>LR>NB

    训练速度:NB>LR>>SVM

    svm是否使用了核函数,怎么选择的

    核函数是在数据线性不可分的情况下使用的,当样本的数量远大于特征的数量的时候就要考虑核函数了,本次实验样本数量1700w,特征数量1w。显然应该考虑使用核函数,但是当样本数量远大于特征数量的时候应该考虑线性核,因为非线性核的计算量太大了。

      • 当数据量足够庞大时,feature足够多时,所有的分类算法最终的效果都差不多。
      • 当训练集不大,feature比较多的时候,用线性的核。因为多feature的情况下就已经可以给线性的核提供不错的variance去fit训练集。
      • 当训练集相对可观,而feature比较少,用非线性的核。因为需要算法提供更多的variance去fit训练集。
      • feature少,训练集非常大,用线性的核。因为非线性的核需要的计算量太大了。而庞大的训练集,本身就可以给非线性的核提供很好的分类效果。

    如果选用核函数,如何调参的

    SVM过度依赖参数,除了过度依赖合适的核函数外,SVM还过度的依赖当前核函数下的具体参数。

    sklearn.svm.SVC(C=1.0, kernel='rbf', degree=3, gamma='auto', coef0=0.0, shrinking=True, probability=False,tol=0.001, cache_size=200, class_weight=None, verbose=False, max_iter=-1, decision_function_shape=None,random_state=None)

    主要调节的参数有:C、kernel、gamma。使用交叉验证来选择最优参数。

    model = svm.SVC(kernel='rbf')
    c_can = np.logspace(-2, 2, 10)
    gamma_can = np.logspace(-2, 2, 10)
    svc = GridSearchCV(model, param_grid={'C': c_can, 'gamma': gamma_can}, cv=5)
    svc.fit(x, y)
    print '验证参数:
    ', svc.best_params_

    liblinear还是libsvm

    在原理和实现上存在差别,libsvm是一套完整的svm实现,既包含基础的线性svm,也包含核函数方式的非线性svm;liblinear则是针对线性场景而专门实现和优化的工具包,同时支持线性svm和线性Logistic Regression模型。由于libsvm支持核函数方式实现非线性分类器,理论上,libsvm具有更强的分类能力,应该能够处理更复杂的问题。

    但是,libsvm的训练速度是个很大的瓶颈,按一般经验,在样本量过万后,libsvm就比较慢了,样本量再大一个数量级,通常的机器就无法处理了;而liblinear设计初衷就是为了解决大数据量的问题,正因为只需要支持线性分类,liblinear可以采用与libsvm完全不一样的优化算法,在保持线性svm分类时类似效果的同时,大大降低了训练计算复杂度和时间消耗。

    同时,在大数据背景下,线性分类和非线性分类效果差别不大,尤其是在特征维度很高而样本有限的情况下,核函数方式有可能会错误地划分类别空间,导致效果反而变差。林智仁老师也给出过很多实际例子证明,人工构造特征+线性模型的方式可以达到甚至超过kernel SVM的表现,同时大大降低训练的时间和消耗的资源。

    在本次试验中文本数量是800w,特征数量5w。用libsvm时间太费时间,所以采用liblinear。

    SVM如何处理多分类问题?

    一般有两种做法:一种是直接法,直接在目标函数上修改,将多个分类面的参数求解合并到一个最优化问题里面。看似简单但是计算量却非常的大。

    另外一种做法是间接法:对训练器进行组合。其中比较典型的有一对一,和一对多。

    一对多,就是对每个类都训练出一个分类器,由svm是二分类,所以将此而分类器的两类设定为目标类为一类,其余类为另外一类。这样针对k个类可以训练出k个分类器,当有一个新的样本来的时候,用这k个分类器来测试,那个分类器的概率高,那么这个样本就属于哪一类。这种方法效果不太好,bias比较高。liblinear采用这种方法。

    svm一对一法(one-vs-one),针对任意两个类训练出一个分类器,如果有k类,一共训练出C(2,k) 个分类器,这样当有一个新的样本要来的时候,用这C(2,k) 个分类器来测试,每当被判定属于某一类的时候,该类就加一,最后票数最多的类别被认定为该样本的类。libsvm采用这种方法。

    Liblinear说明

    考虑到训练效率,本次选用的为多线程并行版liblinear,实际为liblinear-multicore-2.1-4,首先直接给出其train命令所支持的各模式说明,各模式选择不仅与我们使用liblinear工具直接相关,也对我们理解liblinear很有帮助,下面即主要围绕这些模式展开。

    ParallelLIBLINEAR is only available for -s0, 1, 2, 3, 11 now

    Usage:train [options] training_set_file[model_file]

    options:

    -s type : set typeof solver (default 1)

    formulti-class classification (dual对偶的, primal 原始的)

    0 -- L2-regularized logisticregression (primal) ---逻辑回归

    1 -- L2-regularized L2-losssupport vector classification (dual) ---线性svm

    2 -- L2-regularized L2-loss supportvector classification (primal)--与1对应

    3-- L2-regularized L1-loss support vector classification (dual)

    4-- support vector classification by Crammer and Singer

    5-- L1-regularized L2-loss support vector classification

    6-- L1-regularized logisticregression

    7-- L2-regularized logistic regression (dual)

    forregression

    11-- L2-regularized L2-loss support vector regression (primal)

    12-- L2-regularized L2-loss support vector regression (dual)

    13-- L2-regularized L1-loss support vector regression (dual)

    具体solver的选择?线性svm还是logistic regression/L1正则化项还是L2正则化项

    liblinear支持多种solver模式,以下直接列举liblinear支持的几种典型solver模式对应的结构风险函数(结构风险函数由损失函数和正则化项/罚项组合而成,实际即为求解结构风险函数最小值的最优化问题),以方便说明和理解。

    L2-regularized L1-loss Support VectorClassification

     

    L2-regularized L2-loss Support Vector Classification

    L1-regularized L2-loss Support Vector Classification

    L2-regularized Logistic Regression

    L1-regularized Logistic Regression

    Liblinear中同时支持线性svm和logisticregression,两者最大区别即在于损失函数(loss function)不同,损失函数是用来描述预测值f(X)与实际值Y之间差别的非负实值函数,记作L(Y, f(X)),即上述公式中的项。

    另一个重要选择是正则化项。正则化项是为了降低模型复杂度,提高泛化能力,避免过拟合而引入的项。当数据维度很高/样本不多的情况下,模型参数很多,模型容易变得很复杂,表面上看虽然极好地通过了所有样本点,但实际却出现了很多过拟合,此时则通过引入L1/L2正则化项来解决。

    一般情况下,L1即为1范数,为绝对值之和;L2即为2范数,就是通常意义上的模。L1会趋向于产生少量的特征,而其他的特征都是0,即实现所谓的稀疏,而L2会选择更多的特征,这些特征都会接近于0。

    对于solver的选择,作者的建议是:一般情况下推荐使用线性svm,其训练速度快且效果与lr接近;一般情况下推荐使用L2正则化项,L1精度相对低且训练速度也会慢一些,除非想得到一个稀疏的模型(个人注:当特征数量非常大,稀疏模型对于减少在线预测计算量比较有帮助)。

    primal还是dual

    primal和dual分别对应于原问题和对偶问题的求解,对结果是没有影响的,但是对偶问题可能比较慢。作者有如下建议:对于L2正则-SVM,可以先尝试用dual求解,如果非常慢,则换用primal求解。

    网上另一个可参考的建议是:对于样本量不大,但是维度特别高的场景,如文本分类,更适合对偶问题求解;相反,当样本数非常多,而特征维度不高时,如果采用求解对偶问题,则由于Kernel Matrix过大,求解并不方便。反倒是求解原问题更加容易。

    训练数据是否要归一化

    对于这点,作者是这样建议的:在他们文档分类的应用中,归一化不但能大大减少训练时间,也能使得训练效果更好,因此我们选择对训练数据进行归一化。同时在实践中,归一化使得我们能直接对比各特征的公式权重,直观地看出哪些特征比较重要。

    特征值归一化的方法

    min-max标准化(Min-Max Normalization)

    也称为离差标准化,是对原始数据的线性变换,使结果值映射到[0 - 1]之间。转换函数如下:

    其中max为样本数据的最大值,min为样本数据的最小值。这种方法有个缺陷就是当有新数据加入时,可能导致max和min的变化,需要重新定义。

    参考文档

    https://www.cnblogs.com/XDU-Lakers/p/11698303.html

    https://zhuanlan.zhihu.com/p/27939167

    https://sklearn.apachecn.org/docs/0.21.3/5.html

  • 相关阅读:
    PHP 速度测试函数
    ajax的简单应用之快速入门
    PHP漏洞详解
    jQuery Ajax 实例 全解析
    2007年最后的一天
    近来心情格外的郁闷
    使用 Ajax 实现 lightbox
    GridView删除,编辑应用
    完美的wsus客户端注册表文件
    VISTA桌面显示Internet Explorer
  • 原文地址:https://www.cnblogs.com/StarZhai/p/12213319.html
Copyright © 2011-2022 走看看