机器学习之支持向量机

本文详细介绍了支持向量机的基本原理,包括线性与非线性分类、支持向量的概念、间隔优化、核函数的选择(如线性、多项式、高斯核)以及在实际任务中的应用,如手写识别和鸢尾花数据集分析。通过实例展示了如何在数据预处理和模型训练中使用SVM提高分类精度和效率。
摘要由CSDN通过智能技术生成
支持向量机

其本质就是找到正确分类的一组线,也就是寻找一条y = kx+b的直线,使得这条直线距离最接近的点距离最远

  1. 距离最接近的数据点称为支持向量(support vector),支持向量定义的沿着分割线的区域称为间隔(margin)
    在这里插入图片描述

    以上所述只是二维下的情况,如果遇到三维、四维、五维或者更高维的更复杂问题,那么我们据需要找到一个超平面,使得它能够尽可能多的将两类数据点正确的分开,同时使分开的两类数据点距离分类面最远。

  2. 由于支持向量机在分类的时候可能将分割线划分在一定的范围内分割效果会更好,但是此范围内包含不同种类的数据,所以支持向量机存在一个参数叫 允许误差,也就是在划分错误个数允许的的范围内求分割线。(第一个允许误差最大,所以其分割线范围就很大,反之,最后一个允许误差最小)
    在这里插入图片描述

  3. 非线性可分:并不是所有的数据都是可以直接使用二维空间的一条直线进行分割,有时可能需要对其进行升维,在更高维度可能会有更适合的分类办法。有时候二维线性不可分的数据,在更高维度可以找到线性可分的办法。但是,在更高维度分类完成之后一定要映射回数据原本的维度,映射回二维后的分割线称为分类超平面。虽然常常会用到映射到高维空间的做法,但是如果凡是遇到线性不可分的数据,一律都映射到高维空间(如果二维不可分,映射到三维,三维不可分再映射到四维,然后再依次向上映射),那么这个维度的大小会高到可怕。

  4. 核函数:它虽然也是将特征进行从低维到高维的转换,但是核函数事先在低维上进行计算,而将实质上的分类效果表现到了高维上,也就避免了直接在高维空间中的复杂计算,但其能这样做必须有两个先决条件:

    • 定义的核函数能够对应于特征空间中的内积(内积就是点积)

    • 识别方法中不需要计算特征空间中的矢量本身,只需算特征空间中两个矢量的内积

    几类常用的核函数:
    1. 线性核函数:
      在这里插入图片描述

    2. 多项式核函数:
      在这里插入图片描述
      在这里插入图片描述

    3. 高斯核函数:是一种鲁棒径向基核,对于数据中的噪音有着较好的抗干扰能力
      在这里插入图片描述
      在这里插入图片描述

  5. 支持向量机的时间过程:

未调整参数的支持向量机在分类精度上不及Knn算法,但是在速度上相对于Knn算法快很多,下面是用支持向量机对手写字识别进行的运算:

# -*- coding: utf-8 -*-
# @Time    : 2021/7/22 12:42
# @Author  : wcc
# @FileName: SkLearnTest.py
# @Software: PyCharm
# @Blog    :https://blog.csdn.net/qq_41575517?spm=1000.2115.3001.5343

# 导入库
from sklearn import svm
import HandwritingRecognition as hw

training_dir_name = 'trainingDigits'
trainingSet, trainingLabelSet = hw.HwRecognition(dir_name=training_dir_name).pretreatment()

test_dir_name = 'testDigits'
testSet, testLabelSet = hw.HwRecognition(dir_name=test_dir_name).pretreatment()

# 模型定义
model = svm.SVC()

# 模型函数,参数为样本数据和数据标签
model.fit(trainingSet, trainingLabelSet)

# 模型测试,predict()方法为预测方法
result = model.predict(testSet)

# 错误条数
errorCount = 0
# 错误记录
errorRecords = {}
# 错误值与正确值的比对
correctRecords = {}

for i in range(int(testSet.shape[0])):
    if testLabelSet[i] != result[i]:
        errorCount += 1
        errorRecords[i] = result[i]
        correctRecords[i] = testLabelSet[i]


print('错误个数:')
print(errorCount)
print('错误位置及错误值:')
print(errorRecords)
print('相应位置的正确值:')
print(correctRecords)
print("正确率:%f%%" % ((1-errorCount / int(testSet.shape[0]))*100))

鸢尾花数据集用向量机进行处理:

# -*- coding: utf-8 -*-
# @Time    : 2021/7/16 21:45
# @Author  : wcc
# @FileName: KnnIris.py
# @Software: PyCharm
# @Blog    :https://blog.csdn.net/qq_41575517?spm=1000.2115.3001.5343

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from sklearn import svm

class Iris:
    def __init__(self, file_name, data_set, labels_set, normal_data_set,  data_division):
        self.fileName = file_name
        self.dataMat = data_set
        self.labelsMat = labels_set
        self.normalDataSet = normal_data_set
        self.dataDivision = data_division

    # 数据预处理
    def iris_processData(self):
        fr = open(self.fileName)
        numOfLines = len(fr.readlines())

        # 此处一定记得要把标签排除在外
        dataMat = np.zeros((numOfLines, 4))

        # 标签单独成一列
        labelsMat = []

        fr.seek(0, 0)
        index = 0

        for line in fr.readlines():
            line = line.strip()
            listLine = line.split(',')
            dataMat[index, :] = listLine[0:4]
            if listLine[-1] == 'Iris-setosa':
                labelsMat.append(1)
            if listLine[-1] == 'Iris-versicolor':
                labelsMat.append(2)
            if listLine[-1] == 'Iris-virginica':
                labelsMat.append(3)
            index += 1
        labelsMat = np.array(labelsMat)
        self.dataMat = dataMat
        self.labelsMat = labelsMat

    # 数据归一化(0-1归一化)
    def iris_normal(self):
        colDataMax = self.dataMat.max(0)
        colDatamin = self.dataMat.min(0)

        normalDataSet = np.zeros(self.dataMat.shape)
        normalDataSet = (self.dataMat - colDatamin)/(colDataMax - colDatamin)
        self.normalDataSet = normalDataSet

    # 支持向量机对测试集进行测试
    def iris_vector(self):
        totSize = int(self.normalDataSet.shape[0])
        trainSize = int(self.normalDataSet.shape[0]*self.dataDivision)
        testSize = int(self.normalDataSet.shape[0]*(1-self.dataDivision))

        result = []
        errorCount = 0
        errorRecords = {}
        correctRecords = {}
        index = 0

        # 使用支持向量机进行运算
        # 模型定义
        model = svm.SVC()

        # 模型函数,参数为样本数据和数据标签
        model.fit(self.normalDataSet[0:trainSize, :], self.labelsMat[0:trainSize])

        # 模型测试,predict()方法为预测方法
        result = model.predict(self.normalDataSet[trainSize:totSize, :])

        for i in range(int(testSize)):
            if self.labelsMat[trainSize + i] != result[i]:
                errorCount += 1
                errorRecords[i] = result[i]
                correctRecords[i] = self.labelsMat[trainSize + i]


        print('错误个数:')
        print(errorCount)
        print('错误位置及错误值:')
        print(errorRecords)
        print('相应位置的正确值:')
        print(correctRecords)
        print('正确率:%f%%' % ((1-errorCount/testSize)*100))

if __name__ == '__main__':
    fileName = 'iris.txt' # 'datingTestSet.txt'# 文件路径
    dataMat = [] # 数据集(自己读取)
    labelsMat = [] # 标签集(自己读取)
    normalDataSet = [] #归一化后的数据集
    dataDivision = 0.8 # 数据集中训练集和测试集的划分比例
    iris = Iris(file_name=fileName, data_set=dataMat, labels_set=labelsMat, normal_data_set=normalDataSet, data_division=dataDivision)
    iris.iris_processData()
    iris.iris_normal()
    iris.iris_vector()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱吃小巴掌

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值