来源:原始 Jupyter Notebook。内容已转换为网页阅读格式;下载原文件

梯度下降法

根据上一节得到的参数 w 和 b 的更新公式,和线性回归一样,为了保证求值稳定,我们在求和的基础上乘以 1n\frac{1}{n}

w:=wηlossw=w+η1ni=1n(yiπ(xi))xi w := w - \eta \frac{\partial loss}{\partial w} = w + \eta \frac{1}{n} \sum_{i=1}^n (y_i - \pi(x_i))x_i b:=bηlossb=b+η1ni=1n(yiπ(xi)) b := b - \eta \frac{\partial loss}{\partial b} = b + \eta \frac{1}{n} \sum_{i=1}^n (y_i - \pi(x_i))

我们就可以用代码实践一把了。首先把最开始的例子散点图画出来:

import numpy as np
import matplotlib.pyplot as plt

plt.xlim(50, 100)
plt.ylim(-0.5, 1.5)

X = np.array([80, 85, 74, 63, 90, 70])
Y = np.array([1, 1, 0, 0, 1, 0])
plt.scatter(X, Y)

plt.show()

运行结果

Notebook 运行结果

然后定义 π(x)\pi(x) 函数和参数 w 和 b 的更新公式:

def pi(x, w, b):
    return np.exp(w*x+b) / (1 + np.exp(w*x+b))

# 参数 w 的更新公式
def update_w(X, Y, w, b, eta):
    s = 0
    for i in range(X.size):
        s += (Y[i] - pi(X[i], w, b))*X[i]
    return w + eta * s * (1./Y.size)

# 参数 b 的更新公式
def update_b(X, Y, w, b, eta):
    s = 0
    for i in range(X.size):
        s += (Y[i] - pi(X[i], w, b))
    return b - eta * s * (1./Y.size)

我们选取参数的初始值 (w,b)=(0,0)(w, b) = (0, 0),并令学习率 η=0.01\eta = 0.01,然后进行第一次迭代:

w = 0
b = 0
eta = 0.001

w_new = update_w(X, Y, w, b, eta)
b_new = update_b(X, Y, w, b, eta)
print("w = {0}, b = {1}".format(w_new, b_new))

x = np.linspace(60, 100, 10)
y = 1.0 / (1 + np.exp(w_new*x+b_new))
plt.plot(X, Y, 'k.')
plt.plot(x, y, 'g-')
plt.show()

运行结果

w = 0.004, b = 0.0

运行结果

Notebook 运行结果

显然,一次迭代并不能得到很好的分类效果,我们把这个过程继续执行 10 万遍,直到参数收敛:

for i in range(100000):
    w_new = update_w(X, Y, w, b, eta)
    b_new = update_b(X, Y, w, b, eta)
    w = w_new
    b = b_new
    
print("w = {0}, b = {1}".format(w_new, b_new))

x = np.linspace(60, 100, 10)
y = 1.0 / (1 + np.exp(w_new*x+b_new))
plt.plot(X, Y, 'k.')
plt.plot(x, y, 'g-')
plt.show()

运行结果

w = -1.2710404934301518, b = 102.07895720830781

运行结果

Notebook 运行结果

根据上面的参数 w 和 b,令:

wx+b=0 wx+b = 0

所以有 x=80.31x = 80.31,这就是该问题的分类决策边界,可以看出一元分类问题的决策边界就是一个点,接下来我们看看多元分类问题。