感知机:教你用Python一步步实现

Posted Zccccccc_tz

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了感知机:教你用Python一步步实现相关的知识,希望对你有一定的参考价值。

感知机

问题描述

感知机是二类分类的线性分类模型,输入为分类对象的特诊向量,输出为 ± 1 \\pm 1 ±1,用于判别分类对象的类型。这么说有些抽象,下面举一个例子。

就像上面这幅图,

  • 实例对应上图就是每个点
  • 实例的特征向量就是指这些点的横纵坐标,我们把他记为 ( x 1 , x 2 ) T (x_1, x_2)^T (x1,x2)T
  • 我们根据每个点的颜色,将点分别标记为 1 1 1 − 1 -1 1,也就是我们的输出 y y y

利用这些已知坐标的红蓝点,我们需要训练下面这个模型,

这个模型一共有 3 3 3个参数 ( θ 0 , θ 1 , θ 2 ) (\\theta_0, \\theta_1, \\theta_2) (θ0,θ1,θ2),使它能够实现以下功能:

  1. y = s i g n ( θ 1 x 1 + θ 2 x 2 + θ 0 ) = + 1 y=\\rm sign(\\theta_1 x_1 + \\theta_2 x_2 + \\theta_0)=+1 y=sign(θ1x1+θ2x2+θ0)=+1时,我们知道该点为红。
  2. y = s i g n ( θ 1 x 1 + θ 2 x 2 + θ 0 ) = − 1 y=\\rm sign(\\theta_1 x_1 + \\theta_2 x_2 + \\theta_0)=-1 y=sign(θ1x1+θ2x2+θ0)=1时,我们知道该点为蓝。

其中
s i g n ( x ) = + 1 , x ≥ 0 − 1 , x < 0 \\beginaligned \\rm sign(x) = \\left\\\\beginaligned +1,&x \\geq 0 \\\\ -1,&x<0 \\endaligned\\right. \\endaligned sign(x)=+1,1,x0x<0

数据集构建

开始前,我们需要自己整一个数据集用来训练。
先导入一些后面需要的包

import numpy as np
import matplotlib.pyplot as plt
import random
from typing import List, Tuple

然后就是搭建我们的数据集。

# 随机生成一些点,并根据直线将点划分为2个区域
def sample_point(w: float, b: float, num: int) -> Tuple[List[List[float]], List[float]]:
    x, y = [], []
    for _ in range(num):
        p_x1 = np.random.random_sample(1) * 20 - 10
        p_x2 = np.random.random_sample(1) * 20 - 10
        p_y = 1 if w * p_x1 + b - p_x2 > 0 else -1
        x.append([p_x1, p_x2])
        y.append(p_y)

    return x, y

# 先随机生成一条直线
w_ideal = np.random.random_sample(1) * 10 - 5
b_ideal = np.random.random_sample(1) * 10 - 5

x = np.linspace(-10, 10, 1000)
line_ideal = w_ideal * x + b_ideal
# 搭建数据集
sample_x, sample_y = sample_point(w_ideal, b_ideal, 500)

为了更加直观,我们可以将这些点用 matplotlib来可视化一下

# 可视化
plt.xlim(xmax=-10, xmin=10)
plt.ylim(ymax=-10, ymin=10)
plt.plot(x, line_ideal, 'g', linewidth=10)
for i, p_x in enumerate(sample_x):
    if sample_y[i] == 1:
        plt.scatter(p_x[0], p_x[1], c='r', alpha=0.3)
    else:
        plt.scatter(p_x[0], p_x[1], c='b', alpha=0.3)
plt.show()

我们会得到下面这张图片,

其中绿色的那条线,就是实际情况下可以区分红蓝点的直线

下面我们要做的,就是假装不知道这条直线的参数,即代码中的w_idealb_ideal,看看我们能否从数据集中获得我们估计出来的参数,即w_estb_ideal
(有人可能要问了,我们上面不是说三个参数 ( θ 0 , θ 1 , θ 2 ) (\\theta_0, \\theta_1, \\theta_2) (θ0,θ1,θ2)吗?怎么又变成估计两个参数了?不着急,后面会有介绍)。

模型训练

模型训练的理论支持

回到我们的问题,如何根据点的横纵坐标来实现点颜色的分类?

为了能够实现这个预测功能,我们知道,我们需要训练 3 3 3个参数 ( θ 0 , θ 1 , θ 2 ) (\\theta_0, \\theta_1, \\theta_2) (θ0,θ1,θ2)
假设我们现在有了这么一组参数 ( θ 0 ′ , θ 1 ′ , θ 2 ′ ) (\\theta_0',\\theta_1', \\theta_2') (θ0,θ1,θ2),如何衡量这一组参数的好坏呢?如果这一组参数还不够好,我们如何去优化这些参数呢?

于是,我们需要定义一个损失函数,用来衡量这个参数的好坏,并利用损失函数的梯度,将损失函数极小化。

损失函数的定义

直观来讲,一组好的参数应该满足不误分一个点,所以将分错点的个数作为损失函数是一个合理的想法。那么误分的点有什么特点呢?
y i ⋅ ( ∑ j = 1 θ j x i j + θ 0 ) ≤ 0 y_i \\cdot (\\sum_j=1 \\theta_j x_ij + \\theta_0) \\leq 0 yi(j=1θjxij+θ0)0
对于第 i i i个样本而言,

  • 当样本点为蓝色时, y i = − 1 y_i=-1 yi=1,却被误分为红色,也就是 ∑ j = 1 θ j x i j + θ 0 ≥ 0 \\sum_j=1 \\theta_j x_ij + \\theta_0 \\geq 0 j=1θjxij+θ00
  • 当样本点为红色时, y i = + 1 y_i=+1 yi=+1,却被误分为蓝色,也就是 ∑ j = 1 θ j x i j + θ 0 ≤ 0 \\sum_j=1 \\theta_j x_ij + \\theta_0 \\leq 0 j=1θjxij+θ00

综上,我们损失函数被定义为
L ( θ ) = − ∑ x i ∈ M y i ⋅ ( ∑ j = 1 θ j x i j + θ 0 ) = − ∑ x i

以上是关于感知机:教你用Python一步步实现的主要内容,如果未能解决你的问题,请参考以下文章

神级程序员教你用Python实现简单的导弹自动追踪!此乃装逼神技!

#yyds干货盘点# 一步步教你用taro封装一个公司库的下拉组件

一步步教你用Prometheus搭建实时监控系统系列——详细分析拉取和推送两种不同模式

一步步教你用Prometheus搭建实时监控系统系列——上帝之火,普罗米修斯的崛起

马上双十一,教你用Python实现秒杀系统

看看如何学习决策树ID3算法,手把手教你用Python实现