优化函数:
对于线性回归的损失函数,我们有:
C
o
s
t
(
h
θ
(
x
)
,
y
)
=
y
i
l
o
g
(
h
θ
(
x
i
)
)
−
(
1
−
y
i
)
(
1
−
l
o
g
(
1
−
h
θ
(
x
i
)
)
)
Cost(h_\theta(x),y) = y^{i}log(h_\theta(x^{i})) - (1-y^{i})(1-log(1-h_\theta(x^{i})))
Cost(hθ(x),y)=yilog(hθ(xi))−(1−yi)(1−log(1−hθ(xi)))
当y=1时,我们有:
C
o
s
t
(
h
θ
(
x
)
,
y
)
=
l
o
g
(
1
1
+
e
−
θ
T
x
)
Cost(h_\theta(x), y) = log(\frac{1}{1+e^{-\theta^Tx}})
Cost(hθ(x),y)=log(1+e−θTx1)
它的函数图像如图:
令
θ
T
x
=
z
\theta^T x = z
θTx=z,当z较小时,我们函数图像则可以近似成一条直线我们取某一个临界值,左边使用斜率相当的直线代替,右边则取零来代替原损失函数,这样就可以将损失函数简化,那么当y=0时,我们同理可以得出相同的结论。我们使用
c
o
s
t
1
(
z
)
cost_1(z)
cost1(z)和
c
o
s
t
0
(
z
)
cost_0(z)
cost0(z)来代替两边。由此得出我们的新损失函数:
∑
i
=
1
m
y
(
i
)
c
o
s
t
1
(
z
)
+
(
1
−
y
(
i
)
)
c
o
s
t
0
(
z
)
+
λ
2
m
∑
i
=
0
n
θ
j
2
\sum_{i=1}^m y^{(i)}cost_1(z)+(1-y^{(i)})cost_0(z)+\frac{\lambda}{2m}\sum_{i=0}^n \theta_j^2
i=1∑my(i)cost1(z)+(1−y(i))cost0(z)+2mλi=0∑nθj2
一般我们将m省略(约定俗成),这样对最小化参数并没有影响。在svm中,我们更关心前面一项的优化,因此我们改变参数限制
C
∑
i
=
1
m
y
(
i
)
c
o
s
t
1
(
z
)
+
(
1
−
y
(
i
)
)
c
o
s
t
0
(
z
)
+
1
2
∑
i
=
0
n
θ
j
2
C\sum_{i=1}^m y^{(i)}cost_1(z)+(1-y^{(i)})cost_0(z)+\frac{1}{2}\sum_{i=0}^n \theta_j^2
Ci=1∑my(i)cost1(z)+(1−y(i))cost0(z)+21i=0∑nθj2
上面就是我们的优化目标。与线性回归不同的是,svm并不会输出概率来表示这是1还是0,它会直接得出这是1还是0
大间隔:
由上,当y = 1时,如果我们想让损失函数足够的小,我们只需要保证Z > N(大约在1左右),此时损失函数就是比较小的情况了。
当我们做线性回归时,可能有如下的情况:
对于这样的分类问题我们有很多种分法,例如:


相较起来明显是后者更佳,因为有更好的区分度,或者说距离样本的间隔足够的远。我们称为大间隔。
只有在正则化参数非常大的时候,才会有大间隔,此时对异常点会有异常的敏感。
大间隔的推导:
为什么会产生大间隔呢?在这里我们对它进行一次推导:
对于如图的两个向量,我们要计算
u
T
v
u^Tv
uTv,有如下的公式:
u
T
v
=
p
×
∥
u
∥
u^Tv = p \times \|u \|
uTv=p×∥u∥
其中p为v在u上的投影,
∥
u
∥
\| u\|
∥u∥为u向量的范数。
那么对于上述的内容推导,我们有,当y = 1时,有
θ
T
x
≥
1
\theta^Tx \ge 1
θTx≥1时满足损失函数最小,结合上述公式:
θ
T
x
=
x
×
∥
θ
∥
≥
1
\theta^Tx = x \times \| \theta\| \ge 1
θTx=x×∥θ∥≥1
如若出现以下情况:

此时我们作一条辅助垂直线,最靠近边界线的那个样本必然在垂直线上的投影极其小,又因为 θ T x ≥ 1 \theta^Tx \ge 1 θTx≥1
故 ∥ θ ∥ \| \theta\| ∥θ∥必须要极其大,这有悖于我们缩小 θ \theta θ的初衷,因此支持向量机会构建出一个大间隔的决策界限.
核函数:
对于较复杂的回归问题,我们可能需要构造比较复杂的非线性曲线去拟合数据,在这里我们推导如何通过核函数构造一个比较好的非线性函数。
我们如何构建呢,我们假设函数形式如下:
x
=
f
1
+
f
2
+
f
3
(
忽
略
x
0
)
x = f_1+f_2+f_3(忽略x_0)
x=f1+f2+f3(忽略x0)
我们根据特征项选取三个标签点:
我们定义
f
=
K
(
x
)
f = K(x)
f=K(x),
K
(
x
)
K(x)
K(x)如下:
e
−
∥
x
−
l
∥
2
2
σ
2
e^{-\frac{\|x - l \|^2}{2 \sigma^2}}
e−2σ2∥x−l∥2
这是一个高斯核函数,当x距离标记点l较远时,整个值就趋于0,当x距离标记点较近时,则值趋于1,又根据上述的内容我们有
θ
0
+
θ
1
f
1
+
θ
2
f
2
+
θ
3
f
3
≥
0
\theta_0+\theta_1f_1+\theta_2f_2+\theta_3f_3 \ge 0
θ0+θ1f1+θ2f2+θ3f3≥0
这样我们就能构建出一个较好的非线性曲线出来。即,距离越远那么该值就越小。
svm demo
载入数据:
def loadData(filename):
data = sci.loadmat(filename)
return data
def reshapeData(data):
x = data["X"]
y = data["y"]
return x, y.flatten() # 一维化
绘制曲线:
def plotData(x, y):
pos = x[y == 1]
neg = x[y == 0]
plt.scatter(pos[:, 0], pos[:, 1], marker="+", label="y==1")
plt.scatter(neg[:, 0], neg[:, 1], marker="o", label="y==0")
plt.legend()
主函数代码
data = loadData("ex6data1.mat")
x, y = reshapeData(data)
plotData(x, y)
plt.show()
如图:

线性svm训练:
model = SVC(C=1, kernel="linear") # from sklearn.svm import SVC
model.fit(x, y)
线性化并绘制曲线:
def visualizeBoundaryLinear(x, y, model):
w = model.coef_
b = model.intercept_
xp = np.linspace(0.08640, max(x[:, 1]), 100) # 生成
yp = -(w[0][0] * xp + b) / w[0][1]
plotData(x, y)
plt.plot(xp, yp, "-b")
主函数代码
visualizeBoundaryLinear(x, y, model)
plt.show()
如图

更改C为1再运行一遍

可以看出明显的区别,C比较大时,样本对于曲线的影响越大
高斯核函数:
def gaussianKernel(x1, x2, sigma):
x1 = x1.flatten()
x2 = x2.flatten()
x = x1 - x2
sim = np.exp(-np.dot(x, x) / (2 * sigma * sigma))
return sim
主函数测试:
x1 = np.array([1, 2, 1])
x2 = np.array([0, 4, -1])
sigma = 2
sim = gaussianKernel(x1, x2, sigma)
# 结果应该接近0.32465246735834974
更换数据:
data = loadData("ex6data2.mat")
x, y = reshapeData(data)
plotData(x, y)
plt.show()

训练模型:
c = 1
sigma = 0.1
model = SVC(gamma=np.power(sigma, -2)) # 默认则为RBF高斯核函数,gamma为核函数系数
model.fit(x, y)
边界处理:
def visualizeBoundary(x_min, x_max, y_min, y_max, x, y, model):
h = 0.02
plotData(x, y)
xx, yy = np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h))
z = model.predict(np.c_[xx.ravel(), yy.ravel()])
z = z.reshape(xx.shape)
plt.contour(xx, yy, z, level=[-1, 0, 1], colors='r')
主函数:
visualizeBoundary(0, 1, 0.4, 1.0, x, y, model)
plt.show()
结果:

更换数据与RBF
步骤与上面大致相同,这里就直接粘代码了
data = loadData("ex6data3.mat")
x, y = reshapeData(data)
plotData(x, y)
model = SVC(C=c, kernel='rbf', gamma=np.power(sigma, -2))
model.fit(x, y)
visualizeBoundary(-0.6, 0.3, -0.8, 0.6, x, y, model)
plt.show()
结果如图:

