1. 简介
之前我们学习了线性回归,但是我们发现线性回归往往不能够很好的做分类问题,此时就需要引出另一个回归模型即是逻辑回归
2. sigmoid 函数作为模型
在逻辑回归中分类0和1往往是最常见的,sigmoid函数的引入可以很好的将函数拟合在0~1之间
g
(
z
)
=
1
1
+
e
−
z
=
1
1
+
e
−
(
w
⃗
x
⃗
+
b
)
=
P
(
y
=
k
∣
x
;
w
⃗
,
b
)
g(z) = \frac{1}{1+e^{-z}} = \frac{1}{1+e^{-{(\vec w\vec x + b)}}} = P(y=k|x;\vec w,b)
g(z)=1+e−z1=1+e−(wx+b)1=P(y=k∣x;w,b)其中
z
=
w
⃗
x
⃗
+
b
z=\vec w\vec x + b
z=wx+b代表F函数,等式最右边表示在变量
w
⃗
,
b
\vec w,b
w,b条件下x使得y=k(
k
=
0
o
r
1
k = 0 \ or \ 1
k=0 or 1)的概率
如下图所示,通过该函数可以很直观的根据决策边界辨认出0/1
3. 代价函数(cost function)
在线性回归中学到的平方损失函数并不能用到逻辑回归模型中,因为数据的差异导致用平方损失函数会导致代价函数有多个局部最值,如下图所示效果并不好!!可能到达一个局部最小值就返回了…
这是我们就引入一个专门针对于0/1问题的损失函数,如下所示
l
o
s
s
(
f
w
,
b
(
x
(
i
)
)
,
y
(
i
)
)
=
{
−
log
(
f
w
,
b
(
x
(
i
)
)
)
if
y
(
i
)
=
1
−
log
(
1
−
f
w
,
b
(
x
(
i
)
)
)
if
y
(
i
)
=
0
loss(f_{\mathbf{w},b}(\mathbf{x}^{(i)}), y^{(i)}) = \begin{cases} - \log\left(f_{\mathbf{w},b}\left( \mathbf{x}^{(i)} \right) \right) & \text{if $y^{(i)}=1$}\\ -\log \left( 1 - f_{\mathbf{w},b}\left( \mathbf{x}^{(i)} \right) \right) & \text{if $y^{(i)}=0$} \end{cases}
loss(fw,b(x(i)),y(i))={−log(fw,b(x(i)))−log(1−fw,b(x(i)))if y(i)=1if y(i)=0
得到损失函数后,套用之前的代价函数,这里由于不再是平方损失了所以不需要考虑求导后多一个2的问题,即可以直接除以m。其中损失函数这里做了一个合并因为
y
(
i
)
y^(i)
y(i)无非就是0和1,选择其中一项都会导致另外一项变成0!!
J
(
w
,
b
)
=
1
m
∑
i
=
0
m
−
1
[
l
o
s
s
(
f
w
,
b
(
x
(
i
)
)
,
y
(
i
)
)
]
=
1
m
∑
i
=
0
m
−
1
[
−
y
(
i
)
log
(
f
w
,
b
(
x
(
i
)
)
)
−
(
1
−
y
(
i
)
)
log
(
1
−
f
w
,
b
(
x
(
i
)
)
)
]
J(\mathbf{w},b) = \frac{1}{m} \sum_{i=0}^{m-1} \left[ loss(f_{\mathbf{w},b}(\mathbf{x}^{(i)}), y^{(i)}) \right] \\ =\frac{1}{m} \sum_{i=0}^{m-1} \left[-y^{(i)} \log\left(f_{\mathbf{w},b}\left( \mathbf{x}^{(i)} \right) \right) - \left( 1 - y^{(i)}\right) \log \left( 1 - f_{\mathbf{w},b}\left( \mathbf{x}^{(i)} \right) \right) \right]
J(w,b)=m1i=0∑m−1[loss(fw,b(x(i)),y(i))]=m1i=0∑m−1[−y(i)log(fw,b(x(i)))−(1−y(i))log(1−fw,b(x(i)))]
而式子中的
f
w
,
b
f_{w,b}
fw,b 就是开始讲到的
g
(
z
)
g(z)
g(z) ,下面用代码实现上述公式:
#计算g(z)
def sigmoid(z):
"""
Compute the sigmoid of z
Parameters
----------
z : array_like
A scalar or numpy array of any size.
Returns
-------
g : array_like
sigmoid(z)
"""
z = np.clip( z, -500, 500 ) # protect against overflow
g = 1.0/(1.0+np.exp(-z))
return g
#计算代价函数
def compute_cost_logistic(X, y, w, b):
"""
Computes cost
Args:
X (ndarray (m,n)): Data, m examples with n features
y (ndarray (m,)) : target values
w (ndarray (n,)) : model parameters
b (scalar) : model parameter
Returns:
cost (scalar): cost
"""
m = X.shape[0]
cost = 0.0
for i in range(m):
z_i = np.dot(X[i],w) + b
f_wb_i = sigmoid(z_i)
cost += -y[i]*np.log(f_wb_i) - (1-y[i])*np.log(1-f_wb_i)
cost = cost / m
return cost
4.梯度下降
逻辑回归的梯度下降公式实际上跟线性回归长得是一样的
repeat until convergence:
{
w
j
=
w
j
−
α
∂
J
(
w
,
b
)
∂
w
j
for j := 0..n-1
b
=
b
−
α
∂
J
(
w
,
b
)
∂
b
}
\begin{align*} &\text{repeat until convergence:} \; \lbrace \\ & \; \; \;w_j = w_j - \alpha \frac{\partial J(\mathbf{w},b)}{\partial w_j} \; & \text{for j := 0..n-1} \\ & \; \; \; \; \;b = b - \alpha \frac{\partial J(\mathbf{w},b)}{\partial b} \\ &\rbrace \end{align*}
repeat until convergence:{wj=wj−α∂wj∂J(w,b)b=b−α∂b∂J(w,b)}for j := 0..n-1其中求偏导的部分公式展开如下所示,只是这里的
f
(
w
,
b
)
=
g
(
z
)
f(w,b) = g(z)
f(w,b)=g(z)在上面有提到过
∂
J
(
w
,
b
)
∂
w
j
=
1
m
∑
i
=
0
m
−
1
(
f
w
,
b
(
x
(
i
)
)
−
y
(
i
)
)
x
j
(
i
)
∂
J
(
w
,
b
)
∂
b
=
1
m
∑
i
=
0
m
−
1
(
f
w
,
b
(
x
(
i
)
)
−
y
(
i
)
)
\begin{align*} \frac{\partial J(\mathbf{w},b)}{\partial w_j} &= \frac{1}{m} \sum\limits_{i = 0}^{m-1} (f_{\mathbf{w},b}(\mathbf{x}^{(i)}) - y^{(i)})x_{j}^{(i)} \\ \frac{\partial J(\mathbf{w},b)}{\partial b} &= \frac{1}{m} \sum\limits_{i = 0}^{m-1} (f_{\mathbf{w},b}(\mathbf{x}^{(i)}) - y^{(i)}) \end{align*}
∂wj∂J(w,b)∂b∂J(w,b)=m1i=0∑m−1(fw,b(x(i))−y(i))xj(i)=m1i=0∑m−1(fw,b(x(i))−y(i))
梯度下降的代码实现
def compute_gradient_logistic(X, y, w, b):
"""
Computes the gradient for linear regression
Args:
X (ndarray (m,n): Data, m examples with n features
y (ndarray (m,)): target values
w (ndarray (n,)): model parameters
b (scalar) : model parameter
Returns
dj_dw (ndarray (n,)): The gradient of the cost w.r.t. the parameters w.
dj_db (scalar) : The gradient of the cost w.r.t. the parameter b.
"""
m,n = X.shape
dj_dw = np.zeros((n,)) #(n,)
dj_db = 0.
for i in range(m):
f_wb_i = sigmoid(np.dot(X[i],w) + b) #(n,)(n,)=scalar
err_i = f_wb_i - y[i] #scalar
for j in range(n):
dj_dw[j] = dj_dw[j] + err_i * X[i,j] #scalar
dj_db = dj_db + err_i
dj_dw = dj_dw/m #(n,)
dj_db = dj_db/m #scalar
return dj_db, dj_dw
5.如何解决过拟合
过拟合往往导致预测曲线异常复杂,且时间耗费十分的大、预测结果对新节点不友好,如下右图
我们要做到的是泛化(generalization)即是近似拟合恰到好处,如下左图
那我们应该如何解决呢?
- 初始训练的数据集尽可能的多
- 减少特征值的选择,但是可能会导致模型不能很好的反应整体的趋势
- 正则化,即使不减少原有的特征值,而是设定某些效果不显著的特征值对应的w小一点,达到减少其影响又不改变整体模型所反应的问题的目的