这几篇SVM介绍是从0到1慢慢学会支持向量机,将是满满的干货,都是我亲自写的,没有搬运,可以随我一起从头了解SVM,并在短期内能使用SVM做到想要的分类或者预测~我也将附上自己基础训练的完整代码,建议同我一样初学者们,自己从头到尾打一遍,找找手感,代码不能光看看,实践出真知!
基本上每本机器学习书籍和资料都会介绍SVM算法,但是更多的书籍是原理类型的,就正如我上一篇文章一样,然而这是远远不够的,尤其是计算机专业而言,动手操练是最重要的,不过您要是已经是这方面的大佬了,就请略过~ SVM可以做分类和预测,相对做分类的会比较多,尤其是在CV和NLP方向,好下面让我们由浅到深,一步一步熟悉SVM吧!
一、代码实现SVM原理:
这个代码比较长,我只能贴一小部分出来了,这将是真正代码实现SVM原理,下面会使用SK-learn及其他的库对SVM的封装,也就是待会咱们再做掉包侠,先搞懂原理实现~(原理图解在上一章)
首先我们随机模拟数据,比如分布点:x和y坐标:(第一第二列)第三列是label 两类:-1和1
有训练数据和验证数据如图:
接下来是部分关键代码实现(需要源码的私聊联系我):
# 定义数据结构体,用于缓存,提高运行速度
class optStruct:
def __init__(self, dataSet, labelSet, C, toler, kTup):
self.dataMat = np.mat(dataSet) # 原始数据,转换成m*n矩阵
self.labelMat = np.mat(labelSet).T # 标签数据 m*1矩阵
self.C = C # 惩罚参数,C越大,容忍噪声度小,需要优化;反之,容忍噪声度高,不需要优化;
# 所有的拉格朗日乘子都被限制在了以C为边长的矩形里
self.toler = toler # 容忍度
self.m = np.shape(self.dataMat)[0] # 原始数据行长度
self.alphas = np.mat(np.zeros((self.m, 1))) # alpha系数,m*1矩阵
self.b = 0 # 偏置
self.eCache = np.mat(np.zeros((self.m, 2))) # 保存原始数据每行的预测值
self.K = np.mat(np.zeros((self.m, self.m))) # 核转换矩阵 m*m
for i in range(self.m):
self.K[:, i] = kernelTrans(self.dataMat, self.dataMat[i, :], kTup)
# 从文件获取特征数据,标签数据
def loadDataSet(fileName):
dataSet = [];
labelSet = []
fr = open(fileName)
for line in fr.readlines():
# 分割
print(line)
lineArr = line.strip().split(' ')
print(lineArr)
lineArr = list(map(float, lineArr))
dataSet.append([lineArr[0], lineArr[1]])
labelSet.append(lineArr[2])
return dataSet, labelSet
# 计算 w 权重系数
def calWs(alphas, dataSet, labelSet):
dataMat = np.mat(dataSet)
# 1*100 => 100*1
labelMat = np.mat(labelSet).T
m, n = np.shape(dataMat)
w = np.zeros((n, 1))
for i in range(m):
w += np.multiply(alphas[i] * labelMat[i], dataMat[i, :].T)
return w
其余代码暂略,下面看分类结果:
这个是线性分类器,接下来我们继续深入:
与上文一样的数据:
代码实现分类:
import numpy as np
import matplotlib.pyplot as plt
# from .utilities import *
# 获取数据
def load_file(input_file):
x = []
y = []
with open(input_file, "r") as f:
for line in f.readlines():
data = [float(x) for x in line.split(',')]
x.append(data[:-1])
y.append(data[-1])
X = np.array(x)
y = np.array(y)
return X, y
input_file = 'data_multivar.txt'
X, y = load_file(input_file)
class_0 = np.array([X[i] for i in range(len(X)) if y[i] == 0])
class_1 = np.array([X[i] for i in range(len(X)) if y[i] == 1])
plt.figure()
plt.scatter(class_0[:, 0], class_0[:, 1], facecolor='black', edgecolors='black',marker='s')
plt.scatter(class_1[:, 0], class_1[:, 1], facecolor='None', edgecolors='black',marker='s')
plt.title('Input data')
plt.show()
#############################################
from sklearn.svm import SVC
from sklearn.model_selection import train_test_split
# 数据可视化
def plot_classifier(classifier, X, y, title='Classifier boundaries', annotate=False):
# define ranges to plot the figure
x_min, x_max = min(X[:, 0]) - 1.0, max(X[:, 0]) + 1.0
y_min, y_max = min(X[:, 1]) - 1.0, max(X[:, 1]) + 1.0
step_size = 0.01
x_values, y_values = np.meshgrid(np.arange(x_min, x_max, step_size), np.arange(y_min, y_max, step_size))
mesh_output = classifier.predict(np.c_[x_values.ravel(), y_values.ravel()])
mesh_output = mesh_output.reshape(x_values.shape)
plt.figure()
plt.title(title)
plt.pcolormesh(x_values, y_values, mesh_output, cmap=plt.cm.gray)
plt.scatter(X[:, 0], X[:, 1], c=y, s=80, edgecolors='black', linewidth=1, cmap=plt.cm.Paired)
plt.xlim(x_values.min(), x_values.max())
plt.ylim(y_values.min(), y_values.max())
plt.xticks(())
plt.yticks(())
if annotate:
for x, y in zip(X[:, 0], X[:, 1]):
# Full documentation of the function available here:
# http://matplotlib.org/api/text_api.html#matplotlib.text.Annotation
plt.annotate(
'(' + str(round(x, 1)) + ',' + str(round(y, 1)) + ')',
xy=(x, y), xytext=(-15, 15),
textcoords='offset points',
horizontalalignment='right',
verticalalignment='bottom',
bbox=dict(boxstyle='round,pad=0.6', fc='white', alpha=0.8),
arrowprops=dict(arrowstyle='-', connectionstyle='arc3,rad=0'))
X_train, X_test, y_train, y_test = train_test_split(X, y,test_size=0.25, random_state=5)
params = {'kernel': 'linear'} # 线性分类器
# params ={'kernel': 'poly', 'degree': 3} # 非线性分类器
classfier = SVC(**params)
classfier.fit(X_train, y_train)
plot_classifier(classfier, X_train, y_train, 'Training dataset')
plt.show()
##################################################
y_test_pred = classfier.predict(X_test)
plot_classifier(classfier, X_test, y_test, 'Test dataset')
plt.show()
##################################################
from sklearn.metrics import classification_report
target_names = ['class-' + str(int(i)) for i in set(y)]
print("\nClassifier performance on training dataset\n")
print(classification_report(y_train, classfier.predict(X_train), target_names=target_names))
print("#"*30 + "\n")
print("#"*30)
print("\nClassification report on test dataset\n")
print(classification_report(y_test, y_test_pred, target_names=target_names))
print("#"*30 + "\n")
plt.show()
代码说明:
params = {'kernel': 'linear'} # 线性分类器
params ={'kernel': 'poly', 'degree': 3} # 非线性分类器
其中:kernel: poly是多项式核函数大家学过机器学习应该都学过polynomial regression吧就是多元线性回归,
这里的核函数除了可以使用linear 和poly 还可以使用sigmod和径向基核函数kernel=‘rbf’等,这些核函数原理,使用,特点,和比较,我会在下两期介绍
结果显示如图:
左边为原始数据,右边为使用linear核函数做的分类;
这是 :precision精确率 recall召回率,和他们的组合计算公式:f1的分数(分别在linear的训练集和数据集的比较)
接下来使用poly核函数:degree = 3 说明是三阶,同样可以往上加,不过越多越花时间多,但是拟合程度也会很高(过拟合除外)
一比较大家就能知道使用非线性算法accuracy = 0.88 比线性算法高, 因为我的数据是非线性的,使用线性算法分类既容易产生过拟合,准确率还差,使用非线性算法会比较好,真实世界中的处理数据,不仅仅是非线性这么简单了,还有多维和噪音,脏数据等等,要考虑的方面也会更多。
接下来再介绍一下解决类型数据不平衡问题:
数据换了一套,代码改动不大,篇幅问题,暂不赘述,需要的评论区见~
这里的两种类别的数据差别很大的,如果您不想降维的话:也就是说您想保留这部分数据,让其参与训练中,不会被丢弃(降维)降掉,就可以使用以下参数
'kernel': 'linear', 'class_weight': 'balanced'
便可以解决不平衡问题:
如下:
这是使用参数前的,也就是class - 0这一类是0 的精确率(被丢掉了)
但还是有一些的误差,这个还是用很大的进步空间的,以后会慢慢介绍~
今天就介绍这么多,下面还有很多基础训练,大家可以跟着打一下代码一起熟悉一下,关注博主,下期咱们做交通流量地估计。
不知不觉又打了这么多字,自己也渐渐的把写博客养成了习惯,博客奉献他人的同时,其实也是为了自己,加深学习知识的印象,然后可以更好的掌握知识,就当是日记写了,然后大家看到了这里,别忘记关注了,为小博主,在线求关~自己的排版和语言风格也还不是很好地体现,我是一个很乐观幽默地人,希望以后能在文章中欢乐大家,在玩中学!
最后,欢迎大家加入我的Python,机器学习,算法,视觉,NLP交流群,群名《往死里学》,联系我的微信,直接私聊我即可!
上海第二工业大学18智能A1 周小夏(CV调包侠)