感知机学习总结及例题(附代码及手算过程)

感知机是一种二类分类的线性分类模型,其输入为实例的特征向量,输出为实例的类别,+1代表正类,-1代表负类,是神经网络和支持向量机的基础。

例如一个典型的二分类问题:银行卡申请问题,对于顾客,决定是否给予信用卡

对于一个顾客的信息(年龄、薪资、当前债务等等),我们可以用一个向量表示。然后每个信息条目(维度)均对是否给他信用卡有着正面或者负面的影响,决定我们是否给他信用卡。我们把这些维度加权叠加计算出来,结果若大于某个阈值就给,否则就不给。

X

=

(

x

1

,

x

2

,

.

.

.

,

x

d

)

X = (x_1,x_2,...,x_d)

X=(x1,x2,...,xd)表示客人的信息,

W

=

(

w

1

,

w

2

,

.

.

.

,

w

d

)

W=(w_1,w_2,...,w_d)

W=(w1,w2,...,wd)代表对应的权重系数。则:

{

,

if 

i

=

1

d

w

i

x

i

>

t

h

r

e

s

h

o

l

d

,

if 

i

=

1

d

w

i

x

i

<

t

h

r

e

s

h

o

l

d

\begin{cases} 给, & \text{if }\sum_{i=1}^{d}{w_i x_i} > threshold \\ 不给, & \text{if }\sum_{i=1}^{d}{w_i x_i} < threshold \end{cases}

{,,if i=1dwixi>thresholdif i=1dwixi<threshold
上式子还可以写成:

h

(

x

)

=

s

i

g

n

(

(

i

=

1

d

w

i

x

i

)

t

h

r

e

s

h

o

l

d

)

=

s

i

g

n

(

(

i

=

1

d

w

i

x

i

)

+

(

t

h

r

e

s

h

o

l

d

)

(

+

1

)

)

=

s

i

g

n

(

i

=

0

d

w

i

x

i

)

=

s

i

g

n

(

w

T

x

)

\begin{aligned} h(x) &= sign((\sum_{i=1}^{d}{w_i x_i}) - threshold) \\ &= sign((\sum_{i=1}^{d}{w_i x_i}) +(- threshold) * (+1)) \\ &= sign(\sum_{i=0}^{d}{w_i x_i})\\ &= sign(w^Tx) \end{aligned}

h(x)=sign((i=1dwixi)threshold)=sign((i=1dwixi)+(threshold)(+1))=sign(i=0dwixi)=sign(wTx)
这样就可以看成是二个向量的内积再套一个sign函数。

感知机的学习策略:

假设样本线性可分,感知机学习的目标就是求能将正负样本完全分开的分离超平面,即要寻找w,b(因为

w

x

+

b

=

0

wx+b=0

wx+b=0确定了分离超平面)。因此我们需要确定一个学习策略,即定义损失函数,并通过训练样本使其最小化。

损失函数的一个自然选择是误分类点的总数,但是,通过这种方式定义的损失函数对参数w,b来说不是连续可导函数,不易于优化。所有感知机采取的是误分类点到超平面S的总距离。损失函数的推到如下:

设训练集为

T

=

{

(

x

1

,

y

1

)

,

(

x

2

,

y

2

)

,

.

.

.

,

(

x

n

,

y

n

)

,

}

T = \{(x_1,y_1),(x_2,y_2),...,(x_n,y_n),\}

T={(x1,y1),(x2,y2),...,(xn,yn),},其中

x

i

x_i

xi就相当于我们示例中的客人信息(特征向量),

y

i

y_i

yi代表是否给信用卡(-1或+1)。则任意点

x

i

x_i

xi到超平面的距离为

d

=

w

x

i

+

b

w

d = \frac{w*x_i +b}{||w||}

d=wwxi+b

设超平面S的误分类点集合为M,则误分类点到S的总距离为:

s

=

1

w

x

i

M

y

i

(

w

x

i

+

b

)

=

x

i

M

y

i

(

w

x

i

+

b

)

,

1

w

可忽略

\begin{aligned} s &= - \frac{1}{||w||} \sum_{x_i\in M} y_i * (w * x_i + b)\\ &= - \sum_{x_i\in M} y_i * (w * x_i + b) ,\frac{1}{||w||}\text{可忽略} \end{aligned}

s=w1xiMyi(wxi+b)=xiMyi(wxi+b),w1可忽略
感知机学习问题转化为求解上述损失函数的最优化问题,这里可以通过随机梯度下降法来求解。

  1. 首先,任意选取一个超平面,然后用梯度下降法不断地极小化目标函数(损失函数)

    m

    i

    n

    L

    (

    w

    ,

    b

    )

    =

    x

    i

    M

    y

    i

    (

    w

    x

    i

    +

    b

    )

    minL(w,b) = - \sum_{x_i\in M}{} y_i * (w * x_i + b)

    minL(w,b)=xiMyi(wxi+b)。极小化过程中一次随机选取一个误分类点使其梯度下降。

  2. 随机梯度下降:

    1. 对w求偏导:$\nabla w \ L(w,b) = - \sum_{x_i\in M} y_i * x_i $

    2. 对b求偏导:

      b

       

      L

      (

      w

      ,

      b

      )

      =

      x

      i

      M

      y

      i

      \nabla b \ L(w,b) = - \sum_{x_i\in M} y_i

      b L(w,b)=xiMyi

    3. 更新w,b

      w

      w

      η

      (

      y

      i

      x

      i

      )

      b

      b

      η

      (

      y

      i

      )

      w \Longleftarrow w- \eta *(-y_i * x_i) \\ b \Longleftarrow b- \eta *(-y_i)

      wwη(yixi)bbη(yi)

  3. 判断是否还有误分类点,有则继续,没有则训练结束

举个例子,这个是上课老师布置的作业题目,我们解决下:

在这里插入图片描述

方法一:直接Python 冲了它

import numpy as np
import matplotlib.pyplot as plt
import random

# 符号函数
def sign(v):
    if v >= 0:
        return 1
    else:
        return -1

def train(train_num, train_data, lr=0.5):  # 原始训练部分
    w = [1., 1.]  # 初始化权重向量和偏置
    b = -1
    for i in range(train_num):
        #x = random.choice(train_data)
        for x in train_data:
            x1, x2, y = x
            if y * sign(x1 * w[0] + x2 * w[1] + b) <= 0:
                w[0] += lr * y * x1
                w[1] += lr * y * x2
                b += lr * y
                #print(w,b)
    return w, b

# 画散点图
def plot_points(train_data, w, b):
    plt.figure()
    x1 = np.linspace(-1.5, 1.5, 100)
    x2 = (-b - w[0] * x1) / w[1]  # 化简 w1*x1 + w2*x2 + b =0 此时x2相当于竖轴坐标
    plt.plot(x1, x2, color='r', label='y1 data')
    datas_len = len(train_data)
    for i in range(datas_len):
        if train_data[i][-1] == 1:
            plt.scatter(train_data[i][0], train_data[i][1], s=50)
        else:
            plt.scatter(train_data[i][0], train_data[i][1], marker='x', s=50)
    plt.show()

if __name__ == '__main__':
    train_data1 = [[-0.30,0.96,1],[1.49,0.25,1],[0.78,0.96,1]]  # 正样本
    train_data2 = [[-0.89,-1.62,-1], [0.06,-0.68,-1],[-1.13,0.14,-1]]  # 负样本
    data_set = train_data1 + train_data2  # 样本集
    w, b = train(100, data_set, 0.5)  # lr 学习率
    plot_points(data_set, w, b)

结果如下:

在这里插入图片描述

输出

w

=

(

0.85

,

1.48

)

 

b

=

0.5

w = (0.85, 1.48) \ b = -0.5

w=(0.85,1.48) b=0.5

方法二: 手算呗…

已知初值

w

=

(

1

,

1

)

 

b

=

1

w = (1,1) \ b = -1

w=(1,1) b=1,分别待入样本,当

x

=

0.3

,

y

=

0.96

x = -0.3,y =0.96

x=0.3,y=0.96时不符合,则更新

w

b

w和b

wb

w

=

w

+

η

(

0.3

,

0.96

)

=

(

0.85

,

1.48

)

b

=

b

+

η

(

+

1

)

=

0.5

w = w + \eta(-0.3,0.96) = (0.85,1.48) \\ b = b + \eta *(+1) = -0.5

w=w+η(0.3,0.96)=(0.85,1.48)b=b+η(+1)=0.5
之后,继续进行训练,此时可能数据比较好,均通过了训练。训练结束…


版权声明:本文为qq_42642142原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
THE END
< <上一篇
下一篇>>