[怕难?]支持向量机SVM基础实战篇(一)

[怕难?]支持向量机SVM基础实战篇(一)

​ 这几篇SVM介绍是从0到1慢慢学会支持向量机,将是满满的干货,都是我亲自写的,没有搬运,可以随我一起从头了解SVM,并在短期内能使用SVM做到想要的分类或者预测~我也将附上自己基础训练的完整代码,建议同我一样初学者们,自己从头到尾打一遍,找找手感,代码不能光看看,实践出真知!

​ 基本上每本机器学习书籍和资料都会介绍SVM算法,但是更多的书籍是原理类型的,就正如我上一篇文章一样,然而这是远远不够的,尤其是计算机专业而言,动手操练是最重要的,不过您要是已经是这方面的大佬了,就请略过~ SVM可以做分类和预测,相对做分类的会比较多,尤其是在CV和NLP方向,好下面让我们由浅到深,一步一步熟悉SVM吧!


一、代码实现SVM原理:

这个代码比较长,我只能贴一小部分出来了,这将是真正代码实现SVM原理,下面会使用SK-learn及其他的库对SVM的封装,也就是待会咱们再做掉包侠,先搞懂原理实现~(原理图解在上一章)

首先我们随机模拟数据,比如分布点:x和y坐标:(第一第二列)第三列是label 两类:-1和1

有训练数据和验证数据如图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ajMOTQmy-1587631206529)(D:\CSDN\pic\支持向量机SVM基础实战篇\支持向量机SVM基础实战篇.png)]

接下来是部分关键代码实现(需要源码的私聊联系我):

# 定义数据结构体,用于缓存,提高运行速度
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

其余代码暂略,下面看分类结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-r1hnf9pg-1587631206531)(D:\CSDN\pic\支持向量机SVM基础实战篇\1587290152050.png)]

这个是线性分类器,接下来我们继续深入:

与上文一样的数据:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IXv5W6Sy-1587631206534)(D:\CSDN\pic\支持向量机SVM基础实战篇\1587290810761.png)]

​ 代码实现分类:

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’等,这些核函数原理,使用,特点,和比较,我会在下两期介绍

结果显示如图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qZPBC2j1-1587631206538)(D:\CSDN\pic\支持向量机SVM基础实战篇\1587291783423.png)]

左边为原始数据,右边为使用linear核函数做的分类;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AUak1d08-1587631206541)(D:\CSDN\pic\支持向量机SVM基础实战篇\1587291944656.png)]

这是 :precision精确率 recall召回率,和他们的组合计算公式:f1的分数(分别在linear的训练集和数据集的比较)

接下来使用poly核函数:degree = 3 说明是三阶,同样可以往上加,不过越多越花时间多,但是拟合程度也会很高(过拟合除外)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IaCI5Wp7-1587631206543)(D:\CSDN\pic\支持向量机SVM基础实战篇\1587292217550.png)]

下面是他的精确率等:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gYX1yglr-1587631206546)(D:\CSDN\pic\支持向量机SVM基础实战篇\1587292269928.png)]

一比较大家就能知道使用非线性算法accuracy = 0.88 比线性算法高, 因为我的数据是非线性的,使用线性算法分类既容易产生过拟合,准确率还差,使用非线性算法会比较好,真实世界中的处理数据,不仅仅是非线性这么简单了,还有多维和噪音,脏数据等等,要考虑的方面也会更多。


接下来再介绍一下解决类型数据不平衡问题:

数据换了一套,代码改动不大,篇幅问题,暂不赘述,需要的评论区见~

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5fm4Us1B-1587631206548)(D:\CSDN\pic\支持向量机SVM基础实战篇\1587293076377.png)]

这里的两种类别的数据差别很大的,如果您不想降维的话:也就是说您想保留这部分数据,让其参与训练中,不会被丢弃(降维)降掉,就可以使用以下参数

'kernel': 'linear', 'class_weight': 'balanced'

便可以解决不平衡问题:

如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NAQTIsWE-1587631206549)(D:\CSDN\pic\支持向量机SVM基础实战篇\1587293272693.png)]

这是使用参数前的,也就是class - 0这一类是0 的精确率(被丢掉了)

然后使用balanced参数以后(以前版本叫auto):
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5UMdaEbi-1587631206553)(D:\CSDN\pic\支持向量机SVM基础实战篇\1587293348903.png)]

但还是有一些的误差,这个还是用很大的进步空间的,以后会慢慢介绍~

今天就介绍这么多,下面还有很多基础训练,大家可以跟着打一下代码一起熟悉一下,关注博主,下期咱们做交通流量地估计。

不知不觉又打了这么多字,自己也渐渐的把写博客养成了习惯,博客奉献他人的同时,其实也是为了自己,加深学习知识的印象,然后可以更好的掌握知识,就当是日记写了,然后大家看到了这里,别忘记关注了,为小博主,在线求关~自己的排版和语言风格也还不是很好地体现,我是一个很乐观幽默地人,希望以后能在文章中欢乐大家,在玩中学!

最后,欢迎大家加入我的Python,机器学习,算法,视觉,NLP交流群,群名《往死里学》,联系我的微信,直接私聊我即可!

上海第二工业大学18智能A1 周小夏(CV调包侠)

发布了6 篇原创文章 · 获赞 56 · 访问量 8055

猜你喜欢

转载自blog.csdn.net/qq_46098574/article/details/105711311