简体   繁体   English

用C++实现无库分类的SVM

[英]Implementation of SVM for classification without library in c++

I'm studying Support Vector Machine last few weeks.我最近几周正在学习支持向量机。 I understand the theoretical concept how I can classify a data into two classes.我了解如何将数据分为两类的理论概念。 But its unclear to me how to select support vector and generate separating line to classify new data using C++.但是我不清楚如何选择支持向量并生成分隔线以使用 C++ 对新数据进行分类。

Suppose, I have two training data set for two classes假设,我有两个类的两个训练数据集

在此处输入图片说明

After plotting data, I get the following feature space with vector and here, separating line is also clear.绘制数据后,我得到以下带有向量的特征空间,在这里,分隔线也很清晰。

在此处输入图片说明

How to implement this in C++ without library functions.如何在没有库函数的情况下在 C++ 中实现这一点。 It will help me to clear my implementation concept about SVM.它将帮助我明确我关于 SVM 的实现概念。 I need to be clear about implementation as I'm going to apply SVM in opinion mining for my native language.我需要明确实施,因为我将在我的母语的意见挖掘中应用 SVM。

I will join to most people's advice and say that you should really consider using a library.我会加入大多数人的建议,并说你真的应该考虑使用图书馆。 SVM algorithm is tricky enough to add the noise if something is not working because of a bug in your implementation.如果由于您的实现中的错误而导致某些内容无法正常工作,SVM 算法会非常棘手,可以添加噪音。 Not even talking about how hard is to make an scalable implementation in both memory size and time.甚至没有谈论在内存大小和时间上实现可扩展的实现有多困难。

That said and if you want to explore this just as a learning experience, then SMO is probably your best bet.也就是说,如果您想将其作为一种学习体验来探索,那么 SMO 可能是您最好的选择。 Here are some resources you could use:以下是您可以使用的一些资源:

The Simplified SMO Algorithm - Stanford material PDF简化的 SMO 算法 - 斯坦福材料 PDF

Fast Training of Support Vector Machines - PDF支持向量机的快速训练 - PDF

The implementation of Support Vector Machines using the sequential minimal optimization algorithm - PDF 使用顺序最小优化算法实现支持向量机 - PDF

Probably the most practical explanation that I have found is the one on the chapter 6 of the book Machine Learning in action by Peter Harrington.可能我找到的最实用的解释是 Peter Harrington 所著《机器学习实战》一书第 6 章中的解释。 The code itself is on Python but you should be able to port it to C++.代码本身在 Python 上,但您应该能够将其移植到 C++。 I don't think it is the best implementation but it might be good enough to have an idea of what is going on.我不认为这是最好的实现,但它可能足以了解正在发生的事情。

The code is freely available:代码是免费提供的:

https://github.com/pbharrin/machinelearninginaction/tree/master/Ch06 https://github.com/pbharrin/machinelearninginaction/tree/master/Ch06

Unfortunately there is not sample for that chapter but a lot of local libraries tend to have this book available.不幸的是,该章节没有样本,但许多当地图书馆倾向于提供这本书。

Most cases SVM is trained with SMO algorithm -- a variation of coordinate descent that especially suits the Lagrangian of the problem.大多数情况下 SVM 是用 SMO 算法训练的——一种坐标下降的变体,特别适合问题的拉格朗日。 It is a bit complicated, but if a simplified version will be ok for your purposes, I can provide a Python implementation.这有点复杂,但如果简化版本适合您的目的,我可以提供 Python 实现。 Probably, You will be able to translate it to C++可能,您将能够将其翻译为 C++

class SVM:
  def __init__(self, kernel='linear', C=10000.0, max_iter=100000, degree=3, gamma=1):
    self.kernel = {'poly'  : lambda x,y: np.dot(x, y.T)**degree,
                   'rbf'   : lambda x,y: np.exp(-gamma*np.sum((y - x[:,np.newaxis])**2, axis=-1)),
                   'linear': lambda x,y: np.dot(x, y.T)}[kernel]
    self.C = C
    self.max_iter = max_iter

  def restrict_to_square(self, t, v0, u):
    t = (np.clip(v0 + t*u, 0, self.C) - v0)[1]/u[1]
    return (np.clip(v0 + t*u, 0, self.C) - v0)[0]/u[0]

  def fit(self, X, y):
    self.X = X.copy()
    self.y = y * 2 - 1
    self.lambdas = np.zeros_like(self.y, dtype=float)
    self.K = self.kernel(self.X, self.X) * self.y[:,np.newaxis] * self.y
    
    for _ in range(self.max_iter):
      for idxM in range(len(self.lambdas)):
        idxL = np.random.randint(0, len(self.lambdas))
        Q = self.K[[[idxM, idxM], [idxL, idxL]], [[idxM, idxL], [idxM, idxL]]]
        v0 = self.lambdas[[idxM, idxL]]
        k0 = 1 - np.sum(self.lambdas * self.K[[idxM, idxL]], axis=1)
        u = np.array([-self.y[idxL], self.y[idxM]])
        t_max = np.dot(k0, u) / (np.dot(np.dot(Q, u), u) + 1E-15)
        self.lambdas[[idxM, idxL]] = v0 + u * self.restrict_to_square(t_max, v0, u)
    
    idx, = np.nonzero(self.lambdas > 1E-15)
    self.b = np.sum((1.0 - np.sum(self.K[idx] * self.lambdas, axis=1)) * self.y[idx]) / len(idx)
  
  def decision_function(self, X):
    return np.sum(self.kernel(X, self.X) * self.y * self.lambdas, axis=1) + self.b

In simple cases it works not much worth than sklearn.svm.SVC, comparison shown below在简单的情况下,它的作用并不比 sklearn.svm.SVC 值多少,比较如下所示在此处输入图片说明

For more elaborate explanation with formulas you may want to refer to this ResearchGate preprint .有关公式的更详细解释,您可能需要参考此 ResearchGate 预印本 Code for generating images can be found on GitHub .可以在GitHub 上找到生成图像的代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM