支持向量机
SVM是一种分类算法,侧重于模式识别方面,使用SVM可提高分类的准确性。比如实际问题中大多是线性不可分的,SVM思想就是将线性不可分问题转化为线性可分的问题,具体方法是将空间映射到多维空间(例如将二维空间映射到三维空间),以增加维数来减少方程的次数。
SVM基本思想是求解能够正确划分训练数据集并且几何间隔最大的分离超平面。
支持向量:一般认为,超平面在平移过程中,遇到第一个点后就停止平移,则这个点就是支持向量
数据集有几个分类就会有几个支持向量。
训练完成后,大部分的训练样本都不需要保留,最终模型仅与支持向量有关
线性SVM
-
输入:训练数据集T={(x1,y1),(xn,yn),…,xN,yN},yi∈{+1,-1}
-
输出:分离超平面和分类决策函数
- 选择惩罚参数C>0,构造并求解凸二次规划问题
min α 1 2 ∑ i = 1 N ∑ j = 1 N α i α j y i y j ( x i ⋅ x j ) − ∑ i = 1 N α i s.t. ∑ i = 1 N α i y i = 0 0 ≤ α i ≤ C , i = 1 , 2 , … , N \begin{array}{ll} \min _{\boldsymbol{\alpha}} & \frac{1}{2} \sum_{i=1}^{N} \sum_{j=1}^{N} \alpha_{i} \alpha_{j} y_{i} y_{j}\left(\boldsymbol{x}_{\boldsymbol{i}} \cdot \boldsymbol{x}_{\boldsymbol{j}}\right)-\sum_{i=1}^{N} \alpha_{i} \\ \text { s.t. } \quad & \sum_{i=1}^{N} \alpha_{i} y_{i}=0 \\ & 0 \leq \alpha_{i} \leq C, i=1,2, \ldots, N \end{array} minα s.t. 21∑i=1N∑j=1Nαiαjyiyj(xi⋅xj)−∑i=1Nαi∑i=1Nαiyi=00≤αi≤C,i=1,2,…,N
得到最优解 α ∗ = ( α 1 ∗ , α 2 ∗ , … , α N ∗ ) T \boldsymbol{\alpha}^{*}=\left(\alpha_{1}^{*}, \alpha_{2}^{*}, \ldots, \alpha_{N}^{*}\right)^{T} α∗=(α1∗,α2∗,…,αN∗)T- 计算 w ∗ = ∑ i = 1 N α i ∗ y i x i \boldsymbol{w}^{*}=\sum_{i=1}^{N} \alpha_{i}^{*} y_{i} \boldsymbol{x}_{i} w∗=i=1∑Nαi∗yixi b ∗ = y j − ∑ i = 1 N α i ∗ y i ( x i ⋅ x j ) b^{*}=y_{j}-\sum_{i=1}^{N} \alpha_{i}^{*} y_{i}\left(\boldsymbol{x}_{\boldsymbol{i}} \cdot \boldsymbol{x}_{j}\right) b∗=yj−i=1∑Nαi∗yi(xi⋅xj)
- 求分离超平面 w ∗ ⋅ x + b ∗ = 0 \boldsymbol{w}^{*} \cdot \boldsymbol{x}+b^{*}=0 w∗⋅x+b∗=0
分离决策函数
f ( x ) = sign ( w ∗ ⋅ x + b ∗ ) f(\boldsymbol{x})=\operatorname{sign}\left(\boldsymbol{w}^{*} \cdot \boldsymbol{x}+b^{*}\right) f(x)=sign(w∗⋅x+b∗)
非线性SVM
在线性支持向量机学习的对偶问题中,用核函数K(x,z)替代内积,求解到的就是非线性支持向量机
- 输入:训练数据集T={(x1,y1),(xn,yn),…,xN,yN},yi∈{+1,-1}
- 输出:分离超平面和分类决策函数
- 选取适当的核函数K(x,z)和惩罚参数C>0,构造并求解凸二次规划问题
min α 1 2 ∑ i = 1 N ∑ j = 1 N α i α j y i y j K ( x i , x j ) − ∑ i = 1 N α i s.t. ∑ i = 1 N α i y i = 0 0 ≤ α i ≤ C , i = 1 , 2 , … , N \begin{array}{ll} \min _{\boldsymbol{\alpha}} & \frac{1}{2} \sum_{i=1}^{N} \sum_{j=1}^{N} \alpha_{i} \alpha_{j} y_{i} y_{j}K\left(\boldsymbol{x}_{i}, \boldsymbol{x}_{j}\right)-\sum_{i=1}^{N} \alpha_{i} \\ \text { s.t. } \quad & \sum_{i=1}^{N} \alpha_{i} y_{i}=0 \\ & 0 \leq \alpha_{i} \leq C, i=1,2, \ldots, N \end{array} minα s.t. 21∑i=1N∑j=1NαiαjyiyjK(xi,xj)−∑i=1Nαi∑i=1Nαiyi=00≤αi≤C,i=1,2,…,N
得到最优解 α ∗ = ( α 1 ∗ , α 2 ∗ , … , α N ∗ ) T \boldsymbol{\alpha}^{*}=\left(\alpha_{1}^{*}, \alpha_{2}^{*}, \ldots, \alpha_{N}^{*}\right)^{T} α∗=(α1∗,α2∗,…,αN∗)T- 计算 b ∗ = y j − ∑ i = 1 N α i ∗ y i K ( x i , x j ) b^{*}=y_{j}-\sum_{i=1}^{N} \alpha_{i}^{*} y_{i}K\left(\boldsymbol{x}_{i}, \boldsymbol{x}_{j}\right) b∗=yj−i=1∑Nαi∗yiK(xi,xj)
- 分类决策函数 f ( x ) = sign ( ∑ i = 1 N α i ∗ y i K ( x , x i ) + b ∗ ) f(x)=\operatorname{sign}\left(\sum_{i=1}^{N} \alpha_{i}^{*} y_{i} K\left(x, x_{i}\right)+b^{*}\right) f(x)=sign(i=1∑Nαi∗yiK(x,xi)+b∗)
常见核函数
线性核函数、多项式核函数、径向基核函数、Sigmoid核函数
- 线性核函数 K(x,z)=x·z
- 多项式核函数 K(x,z)=(γx·z+r)d
- 径向基核函数 也称为高斯核函数,是libsvm默认的核函数,也是scikit-learn默认的核函数。 K(x,z)=exp(-γ||x-z||2)
- Sigmoid核函数 K(x,z)=tanh(γx·z+r)
通过比较不同核函数的分类的准确率来选择合适的核函数。在实际处理中,分别计算几种核函数的分类性能,将准确率最高的核函数作为最终用于预测分类的核函数。
实验
利用SVM预测升学率
读取数据并绘制相关系数矩阵:
# -*- coding: utf-8 -*-
import csv
from sklearn import svm
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns
from sklearn.model_selection import train_test_split
# 读取数据
f = pd.read_csv("Admission_Predict_Ver1.1.csv",sep = ",")
# 绘制相关系数矩阵
fig,ax = plt.subplots(figsize=(10, 10))
sns.heatmap(f.corr(), ax=ax, annot=True, cmap = 'Blues')
plt.show()
去除不需要的参数列:
df = f.drop(['Serial No.'], axis = 1)
x = df.drop(["Chance of Admit "],axis = 1)
y = df['Chance of Admit '].values
划分数据集:
train,test,train_labels,test_labels = train_test_split(x,y,test_size=0.2,random_state=42)
用SVM预测升学率:
from sklearn import svm
from sklearn import metrics
svr = svm.SVR()
svr.fit(train,train_labels)
pred_svr = svr.predict(test)
print("预测的入学率为:{}".format(pred_svr))
测试是否归一化、是否降维等对模型的影响
上图为未进行归一化且未进行降维的升学率。
对数据进行归一化:
# 数据预处理
from sklearn.preprocessing import MinMaxScaler
# 数据归一化
scaleX = MinMaxScaler(feature_range=(0,1))
# 训练模型前进行数据归一化
train[train.columns] = scaleX.fit_transform(train[train.columns])
test[test.columns] = scaleX.fit_transform(test[test.columns])
得到进行归一化且未进行降维的升学率:
对数据使用pca降维:
from sklearn.decomposition import PCA
pca = PCA(n_components='mle',whiten=True)
X_train_reduced = pca.fit_transform(train)
X_test_reduced = pca.transform(test)
得到未进行归一化且进行降维的升学率:
同时操作,得到进行归一化且进行降维的升学率:
测试多个模型,如多元线性、svm、决策树等
线性:
# LR
from sklearn.linear_model import LinearRegression
lr = LinearRegression()
lr.fit(X_train_reduced,train_labels)
pred_lr = lr.predict(X_test_reduced)
print("预测的入学率为:{}".format(pred_lr))
决策树:
# DTR
from sklearn.tree import DecisionTreeRegressor
dtr = DecisionTreeRegressor(random_state=42)
dtr.fit(X_train_reduced,train_labels)
pred_dtr = dtr.predict(X_test_reduced)
print("预测的入学率为:{}".format(pred_dtr))