<jupyter_start><jupyter_text>算法 2.1（感知机学习算法的原始形式）- 测试数据：例2.1- w和b的计算过程值与书中一致- loss的值书中未给出，这里仅供参考<jupyter_code>import numpy as np

def classify(xi, yi, w, b):
    # 【p29，算法2.1第（3）】分类函数
    result = yi*(np.squeeze(np.dot(np.transpose(w), xi)) + b)
    return result

def loss(x, y, w, b):
    # 【p27，公式2.4】损失函数L(w, b)
    distances = np.squeeze(np.dot(np.transpose(w), x) + b) # 为了省事儿，这里用了向量相乘的形式
    distances_y = np.transpose(y)*distances
    losses = 0
    for d in distances_y:
        if d < 0: # 损失函数是所有误分类样本的损失的总和
            losses += d
    result = - losses
    return result

def data_generator(x, y):
    # 用于持续生成数据
    index = 0
    while True:
        # x[:, index]切片的结果是一个行向量，需要reshape成列向量
        xi = x[:, index].reshape(x.shape[0], 1)
        yield xi, y[index]
        index = index + 1
        index = index % len(y)

# 初始化
x = np.array([[3, 4, 1],
              [3, 3, 1]])
y = np.array([1, 1, -1])

w = np.zeros((2, 1))
b = 0
eta = 1

# 保存每个迭代损失函数的损失
losses = []
# 数据生成器
gen = data_generator(x, y)


count = 0 # 累计连续正确分类样本的次数
while True:
    xi, yi = next(gen)
    # 【p29，算法2.1第（3）步】分类
    result = classify(xi, yi, w, b)
    if result <= 0:
        # 【p29，算法2.1第（3）步】更新w，b
        w = w + eta*yi*xi
        b = b + eta*yi
        print(w, b)
        # 额外计算一下损失函数
        losses.append(loss(x, y, w, b))
        count = 0 # 如果有无分类的样本，计数清零
    else:
        count += 1
    if count == len(y): # 算法第4步，当这个累计次数等于样本总数时，说明全部的样本点都被正确分类了
        break

print('最后结果：')
print('w：', w)
print('b：', b)
print('loss：', losses)<jupyter_output>[[ 3.]
 [ 3.]] 1
[[ 2.]
 [ 2.]] 0
[[ 1.]
 [ 1.]] -1
[[ 0.]
 [ 0.]] -2
[[ 3.]
 [ 3.]] -1
[[ 2.]
 [ 2.]] -2
[[ 1.]
 [ 1.]] -3
最后结果：
w： [[ 1.]
 [ 1.]]
b： -3
loss： [7.0, 4.0, 1.0, 4.0, 5.0, 2.0, 0]