一瞬雹、簡(jiǎn)介
支持向量機(jī)(SVM)是經(jīng)典的監(jiān)督學(xué)習(xí)模型,這篇博文中哈打,將通過線性規(guī)劃(cvxopt包)展示SVM求解時(shí)的過程塔逃。數(shù)據(jù)集采用鳶尾花數(shù)據(jù)集進(jìn)行二分類任務(wù)。
import matplotlib
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
from cvxopt import matrix, solvers
from sklearn.datasets import load_iris
iris = load_iris()
iris_df = pd.DataFrame(data= np.c_[iris["data"], iris["target"]], columns= iris["feature_names"] + ["target"])
# 二分類
iris_df = iris_df[iris_df["target"].isin([0,1])] ##找出0-1類
iris_df["target"] = iris_df[["target"]].replace(0,-1) ##0替換為-1
#選兩個(gè)特征
iris_df = iris_df[["petal length (cm)", "petal width (cm)", "target"]]
##將數(shù)據(jù)轉(zhuǎn)為numpy 可視化
X = iris_df[["petal length (cm)", "petal width (cm)"]].to_numpy()
y = iris_df[["target"]].to_numpy()
x_min = 0
x_max = 5.5
y_min = 0
y_max = 2
plt.figure(figsize=(8, 8))
colors = ["steelblue", "orange"]
plt.scatter(X[:, 0], X[:, 1], c=y.ravel(), alpha=0.5, cmap=matplotlib.colors.ListedColormap(colors), edgecolors="black")
plt.xlim(x_min, x_max)
plt.ylim(y_min, y_max)
plt.show()
數(shù)學(xué)來了
-
SVM最終的表達(dá)式化簡(jiǎn)如下
-
由拉格朗日定理料仗,引入拉格朗日乘子α
- 因?yàn)镴(w,b,α)是凸的湾盗,我們對(duì)其中的變量求微分如下
- 兩個(gè)微分結(jié)果帶入可得:
-
還是由微分結(jié)果,第二項(xiàng)為0了立轧,最終結(jié)果如下:
-
我們用線性規(guī)劃重新定義上試格粪,定義一個(gè)矩陣H,Hij = yiyjxixj, 最終結(jié)果可改寫成如下形式:
#取n個(gè)訓(xùn)練樣本氛改,定義矩陣H
n = X.shape[0]
H = np.dot(y*X, (y*X).T)
##第二項(xiàng)我們定于-1的列向量
q = np.repeat([-1.0], n)[..., None]
##第一個(gè)約束條件帐萎,我們定義A是1×n的矩陣,種類只有2類胜卤,令b=0
A = y.reshape(1, -1)
b = 0.0
##第二個(gè)約束條件疆导,我們構(gòu)造一個(gè)n×n單位矩陣G,和零向量h
G = np.negative(np.eye(n))
h = np.zeros(n)
##所有條件轉(zhuǎn)為CVXOPT對(duì)象
P = matrix(H)
q = matrix(q)
G = matrix(G)
h = matrix(h)
A = matrix(A)
b = matrix(b)
##調(diào)用線性規(guī)劃求解器
sol = solvers.qp(P, q, G, h, A, b)
alphas = np.array(sol["x"]) ##求出α
微分求解結(jié)果
我們定義支持向量,加入松弛因子,松弛因子的作用就是讓約束條件不要太過絕對(duì)化葛躏。澈段。。舰攒。
兩個(gè)公式代碼如下:
w = np.dot((y * alphas).T, X)[0]
S = (alphas > 1e-5).flatten()
b = np.mean(y[S] - np.dot(X[S], w.reshape(-1,1)))
##打印下結(jié)果
print("W:", w)
print("b:", b)
##可視化一下
xx = np.linspace(x_min, x_max)
a = -w[0]/w[1]
yy = a*xx - (b)/w[1]
margin = 1 / np.sqrt(np.sum(w**2))
yy_neg = yy - np.sqrt(1 + a**2) * margin
yy_pos = yy + np.sqrt(1 + a**2) * margin
plt.figure(figsize=(8, 8))
plt.plot(xx, yy, "b-")
plt.plot(xx, yy_neg, "m--")
plt.plot(xx, yy_pos, "m--")
colors = ["steelblue", "orange"]
plt.scatter(X[:, 0], X[:, 1], c=y.ravel(), alpha=0.5, cmap=matplotlib.colors.ListedColormap(colors), edgecolors="black")
plt.xlim(x_min, x_max)
plt.ylim(y_min, y_max)
plt.show()
第二方法調(diào)Sklearn包就很簡(jiǎn)單了
from sklearn import svm
clf = svm.SVC(kernel="linear", C=10.0)
clf.fit(X, y.ravel())
w = clf.coef_[0]
b = clf.intercept_
print("W:", w)
print("b:", b)
#W: [1.29411744 0.82352928]
#b: [-3.78823471]
完整代碼如下:
import matplotlib
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
from cvxopt import matrix, solvers
from sklearn.datasets import load_iris
iris = load_iris()
iris_df = pd.DataFrame(data= np.c_[iris["data"], iris["target"]], columns= iris["feature_names"] + ["target"])
# 二分類
iris_df = iris_df[iris_df["target"].isin([0,1])] ##找出0-1類
iris_df["target"] = iris_df[["target"]].replace(0,-1) ##0替換為-1
#選兩個(gè)特征
iris_df = iris_df[["petal length (cm)", "petal width (cm)", "target"]]
##將數(shù)據(jù)轉(zhuǎn)為numpy 可視化
X = iris_df[["petal length (cm)", "petal width (cm)"]].to_numpy()
y = iris_df[["target"]].to_numpy()
x_min = 0
x_max = 5.5
y_min = 0
y_max = 2
plt.figure(figsize=(8, 8))
colors = ["steelblue", "orange"]
plt.scatter(X[:, 0], X[:, 1], c=y.ravel(), alpha=0.5, cmap=matplotlib.colors.ListedColormap(colors), edgecolors="black")
plt.xlim(x_min, x_max)
plt.ylim(y_min, y_max)
plt.show()
#取n個(gè)訓(xùn)練樣本败富,定義矩陣H
n = X.shape[0]
H = np.dot(y*X, (y*X).T)
##第二項(xiàng)我們定于-1的列向量
q = np.repeat([-1.0], n)[..., None]
##第一個(gè)約束條件,我們定義A是1×n的矩陣摩窃,種類只有2類兽叮,令b=0
A = y.reshape(1, -1)
b = 0.0
##第二個(gè)約束條件,我們構(gòu)造一個(gè)n×n單位矩陣G猾愿,和零向量h
G = np.negative(np.eye(n))
h = np.zeros(n)
##所有條件轉(zhuǎn)為CVXOPT對(duì)象
P = matrix(H)
q = matrix(q)
G = matrix(G)
h = matrix(h)
A = matrix(A)
b = matrix(b)
##調(diào)用線性規(guī)劃求解器
sol = solvers.qp(P, q, G, h, A, b)
alphas = np.array(sol["x"]) ##求出α
w = np.dot((y * alphas).T, X)[0]
S = (alphas > 1e-5).flatten()
b = np.mean(y[S] - np.dot(X[S], w.reshape(-1,1)))
##打印下結(jié)果
print("W:", w)
print("b:", b)
##可視化一下
xx = np.linspace(x_min, x_max)
a = -w[0]/w[1]
yy = a*xx - (b)/w[1]
margin = 1 / np.sqrt(np.sum(w**2))
yy_neg = yy - np.sqrt(1 + a**2) * margin
yy_pos = yy + np.sqrt(1 + a**2) * margin
plt.figure(figsize=(8, 8))
plt.plot(xx, yy, "b-")
plt.plot(xx, yy_neg, "m--")
plt.plot(xx, yy_pos, "m--")
colors = ["steelblue", "orange"]
plt.scatter(X[:, 0], X[:, 1], c=y.ravel(), alpha=0.5, cmap=matplotlib.colors.ListedColormap(colors), edgecolors="black")
plt.xlim(x_min, x_max)
plt.ylim(y_min, y_max)
plt.show()
##sklearn方法
from sklearn import svm
clf = svm.SVC(kernel="linear", C=10.0)
clf.fit(X, y.ravel())
w = clf.coef_[0]
b = clf.intercept_
print("W:", w)
print("b:", b)
#W: [1.29411744 0.82352928]
#b: [-3.78823471]