[英]Implementation of SVM for classification without library in c++
我最近几周正在学习支持向量机。 我了解如何将数据分为两类的理论概念。 但是我不清楚如何选择支持向量并生成分隔线以使用 C++ 对新数据进行分类。
假设,我有两个类的两个训练数据集
绘制数据后,我得到以下带有向量的特征空间,在这里,分隔线也很清晰。
如何在没有库函数的情况下在 C++ 中实现这一点。 它将帮助我明确我关于 SVM 的实现概念。 我需要明确实施,因为我将在我的母语的意见挖掘中应用 SVM。
我会加入大多数人的建议,并说你真的应该考虑使用图书馆。 如果由于您的实现中的错误而导致某些内容无法正常工作,SVM 算法会非常棘手,可以添加噪音。 甚至没有谈论在内存大小和时间上实现可扩展的实现有多困难。
也就是说,如果您想将其作为一种学习体验来探索,那么 SMO 可能是您最好的选择。 以下是您可以使用的一些资源:
可能我找到的最实用的解释是 Peter Harrington 所著《机器学习实战》一书第 6 章中的解释。 代码本身在 Python 上,但您应该能够将其移植到 C++。 我不认为这是最好的实现,但它可能足以了解正在发生的事情。
代码是免费提供的:
https://github.com/pbharrin/machinelearninginaction/tree/master/Ch06
不幸的是,该章节没有样本,但许多当地图书馆倾向于提供这本书。
大多数情况下 SVM 是用 SMO 算法训练的——一种坐标下降的变体,特别适合问题的拉格朗日。 这有点复杂,但如果简化版本适合您的目的,我可以提供 Python 实现。 可能,您将能够将其翻译为 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
在简单的情况下,它的作用并不比 sklearn.svm.SVC 值多少,比较如下所示
有关公式的更详细解释,您可能需要参考此 ResearchGate 预印本。 可以在GitHub 上找到生成图像的代码。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.