向量机
介绍:
解决的问题:怎样的决策边界最好
决策边界:Large Margin :使两种分开距离最远的地方
红色的就是决策边界,两个红点是距决策边界最近的点
原理
注意要标准化,使横竖轴观察更加直观
1、目标函数:
1、求点到决策边界的距离
求两个类之间最远的分类,那么就要找两个距分类最近的点,找他们之间的最远分类距离
设x是最近的一点,任取决策边界上的一点x‘
x到决策边界的距离,就是|x-x’|在决策边界上方向向量w投影:
2、数据集(X,Y):
Y为样本类别:X为正,Y=1;X为负,Y=-1
总体来说:XY>0,可以用来表示距离恒大于0
决策方程:Y(X)=W.T*Φ(X)+b
Φ(X)是对x进行了转换,可以先看做X
3、优化目标:
找到一条线,使得距该线最近的点之间的距离能够最远
距离简化为
4、进行化简:
1、进行放缩,原为XY>0,现在XY>1
2、所求符号化表示:
3、最终优化目标为:
由于,所以子需要考虑
2、第一次拉格朗日
1、当求最大时,常规思路是将最大值转换成最小值:
2、带着条件,用拉格朗日求极值:
分别对w,b求偏导:
再代入原始:
3、第二次拉格朗日
1、继续对α求极大值:
条件:2、常规思路转换成最小值:
3、代入实例计算:
取的三个点,正例x1(3,3),x2(4,3),负例x3(1,1)
求解:
条件:
代入得:
化简为:
对α1,α2再求偏导为0,满足条件α>0,得α1=0.25,α2=0,α3=0.25
代入:W=(0.25,0.25)
平面方程:0.5x1+0.5x2-2=0
4、总结:
真正发挥作用的是,α不为0的点(最近的点)
4、代码解释:
使用iris数据集,选择其中的两个特征
from sklearn.svm import SVC
from sklearn import datasets
iris = datasets.load_iris()
X = iris['data'][:,(2,3)]
y = iris['target']
setosa_or_versicolor = (y==0)|(y==1)
X = X[setosa_or_versicolor]
y = y[setosa_or_versicolor]
svm_clf = SVC(kernel='linear')
svm_clf.fit(X,y)
画图显示:
def plot_svc_decision_boundary(svm_clf, xmin, xmax,sv=True):
w = svm_clf.coef_[0]
b = svm_clf.intercept_[0]
print ("svm_clf.coef_:",svm_clf.coef_)
print("svm_clf.intercept_:",svm_clf.intercept_)
x0 = np.linspace(xmin, xmax, 200)#已知x0
decision_boundary = - w[0]/w[1] * x0 - b/w[1]#求解x1
margin = 1/w[1]#优化目标的距离
gutter_up = decision_boundary + margin
gutter_down = decision_boundary - margin
if sv:
svs = svm_clf.support_vectors_#支持向量
print("svs:",svs)
plt.scatter(svs[:,0],svs[:,1],s=180,facecolors='#FFAAAA')
plt.plot(x0,decision_boundary,'r-',linewidth=2)
plt.plot(x0,gutter_up,'k--',linewidth=2)
plt.plot(x0,gutter_down,'k--',linewidth=2)
plot_svc_decision_boundary(svm_clf, 0, 5.5)
plt.plot(X[:,0][y==1],X[:,1][y==1],'bs')
plt.plot(X[:,0][y==0],X[:,1][y==0],'ys')
plt.axis([0,5.5,0,2])
升级:
1、软间隔:
1、介绍:
考虑到数据中有一些噪声点,要放宽一下约束条件,引入了松弛因子:ξ
以及超参数C
2、C的使用:
当C大时,就小,1-
就大,那么分类就更加严格;
当C小时,就大,1-
就小,那么分类就更加宽松
画图对比C
import numpy as np
from sklearn import datasets
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.svm import LinearSVC
iris=datasets.load_iris()
X = iris["data"][:,(2,3)] # petal length, petal width
y = (iris["target"] == 2).astype(np.float64) # Iris-Viginica
svm_clf = Pipeline((
('std',StandardScaler()),
('linear_svc',LinearSVC(C=1))
))
svm_clf.fit(X,y)
scaler = StandardScaler()
svm_clf1 = LinearSVC(C=1,random_state = 42)
svm_clf2 = LinearSVC(C=100,random_state = 42)
scaled_svm_clf1 = Pipeline((
('std',scaler),
('linear_svc',svm_clf1)
))
scaled_svm_clf2 = Pipeline((
('std',scaler),
('linear_svc',svm_clf2)
))
scaled_svm_clf1.fit(X,y)
scaled_svm_clf2.fit(X,y)
#画图时要将标准化的数据再转回来(具体为什么,我还需要再想想)
b1 = svm_clf1.decision_function([-scaler.mean_ / scaler.scale_])
b2 = svm_clf2.decision_function([-scaler.mean_ / scaler.scale_])
w1 = svm_clf1.coef_[0] / scaler.scale_
w2 = svm_clf2.coef_[0] / scaler.scale_
svm_clf1.intercept_ = np.array([b1])
svm_clf2.intercept_ = np.array([b2])
svm_clf1.coef_ = np.array([w1])
svm_clf2.coef_ = np.array([w2])
plt.figure(figsize=(14,4.2))
plt.subplot(121)
plt.plot(X[:, 0][y==1], X[:, 1][y==1], "g^", label="Iris-Virginica")
plt.plot(X[:, 0][y==0], X[:, 1][y==0], "bs", label="Iris-Versicolor")
plot_svc_decision_boundary(svm_clf1, 4, 6,sv=False)
plt.xlabel("Petal length", fontsize=14)
plt.ylabel("Petal width", fontsize=14)
plt.legend(loc="upper left", fontsize=14)
plt.title("$C = {}$".format(svm_clf1.C), fontsize=16)
plt.axis([4, 6, 0.8, 2.8])
plt.subplot(122)
plt.plot(X[:, 0][y==1], X[:, 1][y==1], "g^")
plt.plot(X[:, 0][y==0], X[:, 1][y==0], "bs")
plot_svc_decision_boundary(svm_clf2, 4, 6,sv=False)
plt.xlabel("Petal length", fontsize=14)
plt.title("$C = {}$".format(svm_clf2.C), fontsize=16)
plt.axis([4, 6, 0.8, 2.8])
结果展示:
2、核变换:
解决:低微不可分的问题
低维不可分的情况下,就映射到高维上
x==>Φ(X),就是由低微转换到了高维
预处理(转换至高维)
设置degree不同值,对比分类效果
degree越大,分类越清楚,越易过拟合
分类:画决策边界
1、数据
from sklearn.datasets import make_moons
X, y = make_moons(n_samples=100, noise=0.15, random_state=42)
def plot_dataset(X, y, axes):
plt.plot(X[:, 0][y==0], X[:, 1][y==0], "bs")
plt.plot(X[:, 0][y==1], X[:, 1][y==1], "g^")
plt.axis(axes)
plt.grid(True, which='both')
plt.xlabel(r"$x_1$", fontsize=20)
plt.ylabel(r"$x_2$", fontsize=20, rotation=0)
plot_dataset(X, y, [-1.5, 2.5, -1, 1.5])
plt.show()
2、决策边界的划分
def plot_predictions(clf,axes):
x0s = np.linspace(axes[0],axes[1],100)
x1s = np.linspace(axes[2],axes[3],100)
x0,x1 = np.meshgrid(x0s,x1s)#构建棋盘
X = np.c_[x0.ravel(),x1.ravel()]#进行拼接
y_pred = clf.predict(X).reshape(x0.shape)#必须与原始形状相同
plt.contourf(x0,x1,y_pred,cmap=plt.cm.brg,alpha=0.2)
3、训练模型,设置不同的degree
from sklearn.datasets import make_moons
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import PolynomialFeatures
from sklearn.svm import SVC
poly_kernel_svm_clf = Pipeline([
("scaler", StandardScaler()),
("svm_clf", SVC(kernel="poly", degree=3, coef0=1, C=5))
])
poly_kernel_svm_clf.fit(X, y)
poly100_kernel_svm_clf = Pipeline([
("scaler", StandardScaler()),
("svm_clf", SVC(kernel="poly", degree=10, coef0=1, C=5))
])
#coef0偏置值,影响不大
poly100_kernel_svm_clf.fit(X, y)
4、画图展示:
plt.figure(figsize=(11, 4))
plt.subplot(121)
plot_predictions(poly_kernel_svm_clf, [-1.5, 2.5, -1, 1.5])
plot_dataset(X, y, [-1.5, 2.5, -1, 1.5])
plt.title(r"$d=3, r=1, C=5$", fontsize=18)
plt.subplot(122)
plot_predictions(poly100_kernel_svm_clf, [-1.5, 2.5, -1, 1.5])
plot_dataset(X, y, [-1.5, 2.5, -1, 1.5])
plt.title(r"$d=10, r=100, C=5$", fontsize=18)
plt.show()