【感知机学习】

统计学-感知机的学习

感知机原理

1.假设输入空间(特征空间)是 X ⊆ R n X\subseteq R^n XRn输出空间是 y = ( + 1 , − 1 ) y={{(+1, -1)}} y=(+1,1)表示实例的特征向量,对应于输入空间(特征空间)的点;输出 y ∈ Y y\in Y yY
模型:公式表达如下:
f ( x ) = s i g n ( w x + b ) f(x)=sign(wx+b) f(x)=sign(wx+b)2.1
公式2.1称为感知机。其中w和b为感知机模型参数,。 w ∈ R n w\in R^n wRn叫做权值(weight)或权值向量(weight vector), b ∈ R b\in R bR叫作偏置(bias), w ∗ x w*x wx 表示w 和 x的内积。sign是符号函数,即:
s i g n ( x ) = { + 1 x ≥ 0 − 1 x < 0 sign(x)=\left\{ \begin{array}{rcl} +1 & & x ≥ 0\\ -1 & & {x< 0} \end{array} \right. sign(x)={+11x0x<0
2.感知机模型的性质
感知机是一种线性分类模型,属于判别模型。
3 感知机学习策略
3.1 数据集的线性可分性
  给定数据集 T = ( x 1 , y 1 ) , ( x 2 , y 2 ) , ⋯ , ( x N , y N ) ,其中 x i ∈ X = R n , y i ∈ Y = { + 1 , − 1 } , i = 1 , 2 , ⋯ , N T={(x_1,y_1),(x_2,y_2),⋯,(x_N,y_N)},其中xi∈X=R^n, y_i∈Y=\{+1,−1\},i=1,2,⋯,N T=(x1,y1),(x2,y2),,(xN,yN),其中xiX=Rn,yiY={+1,1},i=1,2,,N,如果存在某个超平面 S 满足: w ⋅ x + b = 0 w⋅x+b=0 wx+b=0
  能将数据集的正实例点和负实例点完全正确地划分到超平面的两侧,即对所有$ y_i=+1$ 的实例 x i x_i xi,有$ w⋅xi+b>0$ ;对所有 y i = − 1 y_i=−1 yi=1 的实例 x i x_i xi,有 w ⋅ x i + b < 0 w⋅xi+b<0 wxi+b<0,则 称数据集 T 为线性可分数据集 ;否则,称数据集 T 线性 不可分。
  在学习感知机模型中,需要确保数据集线性可分,才能够找到一个完全将正实例点和负实例点正确分开的分离超平面,即才能够确定感知机模型参数 w , b w,b w,b

习题2.1

题目:Minsky 与 Papert 指出:感知机因为是线性模型,所以不能表示复杂的函数,如异或 (XOR)。验证感知机为什么不能表示异或。

1.列出异或函数(XOR)的输入和输出;
2.使用图例法证明异或问题是线性不可分的;
3.使用反证法证明感知机无法表示异或。
4.解题步骤
(1)异或函数(XOR)的输入和输出
(2)对于异或函数(XOR),全部的输入与对应的输出如下:

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
# 使用Dataframe表示异或的输入与输出数据
x1 = [0, 0, 1, 1]
x2 = [0, 1, 0, 1]
y = [-1, 1, 1, -1]
x1 = np.array(x1)
x2 = np.array(x2)
y = np.array(y)
data = np.c_[x1, x2, y]
data = pd.DataFrame(data, index=None, columns=['x1', 'x2', 'y'])
data.head()
# 获取正类别(y=1)的数据
positive = data.loc[data['y'] == 1]
# 获取负类别(y=-1)的数据
negative = data.loc[data['y'] == -1]
plt.xlim(-0.5, 1.5)
plt.ylim(-0.5, 1.5)
plt.xticks([-0.5, 0, 1, 1.5])
plt.yticks([-0.5, 0, 1, 1.5])
plt.xlabel("x1")
plt.ylabel("x2")
# 绘制正、负样本点
plt.plot(positive['x1'], positive['x2'], "ro")
plt.plot(negative['x1'], negative['x2'], "bx")

plt.legend(['Positive', 'Negative'])
plt.show()

输出结果如下:
在这里插入图片描述
从上图可以看出,无法使用一条直线将两类样本分开,所以异或问题是线性不可分的

 下一步,使用感知机模型进行测试 w , b w,b wb

from sklearn.linear_model import Perceptron
import numpy as np
X_train = np.array([[1, 1], [1, 0], [0, 1], [0, 0]])
y = np.array([-1, 1, 1, -1])
perceptron_model = Perceptron()
perceptron_model.fit(X_train, y)
print("感知机模型的参数:w=", perceptron_model.coef_[
      0], "b=", perceptron_model.intercept_[0])

输出结果如下:
感知机模型的参数:w= [0. 0.] b= 0.0
反证法:
s i g n ( x ) = { + 1 x ≥ 0 − 1 x < 0 sign(x)=\left\{ \begin{array}{rcl} +1 & & x ≥ 0\\ -1 & & {x< 0} \end{array} \right. sign(x)={+11x0x<0
假设咸知机模型可以表示异或问题,即满足异或函数(XOR)输入与输出的情况(见第 1 步 1 步 1步 )。假设 x 向量只有两个维度 x 1 , x 2 x 1 , x 2 x 1 , x 2 x _1 , x_ 2 x_{1}, x_{2} x _1 ,x _2 x1,x2x1,x2x1,x2 :
根据 x 1 = 0 , x 2 = 0 , f ( x ) = − 1 则 w ⋅ x + b < 0 可得 b < 0 根据 x 1 = 0 , x 2 = 0 , f ( x ) = − 1 则 w ⋅ x + b < 0 可得b<0 根据x1=0,x2=0,f(x)=1wx+b<0可得b<0
2. 根据 x 1 = 0 , x 2 = 1 , f ( x ) = 1 , 则 w 2 + b > 0 结合 b < 0 , 可得: w 2 > − b > 0 2.根据x _1 =0,x _2 =1,f(x)=1,则w _2 +b>0 结合b<0 ,可得:w_2>−b>0 2.根据x1=0,x2=1,f(x)=1,w2+b>0结合b<0,可得:w2>b>0
所以假设不成立,原命题成立,即感知机模型不能表示异或

习题2.2

解题步骤在上面的iris数据中已经体现。

import numpy as np
from matplotlib import pyplot as plt
%matplotlib tk


class Perceptron:
    def __init__(self, X, Y, lr=0.001, plot=True):
        """
        初始化感知机
        :param X: 特征向量
        :param Y: 类别
        :param lr: 学习率
        :param plot: 是否绘制图形
        """
        self.X = X
        self.Y = Y
        self.lr = lr
        self.plot = plot
        if plot:
            self.__model_plot = self._ModelPlot(self.X, self.Y)
            self.__model_plot.open_in()

    def fit(self):
        # (1)初始化weight, b
        weight = np.zeros(self.X.shape[1])
        b = 0
        # 训练次数
        train_counts = 0
        # 分类错误标识
        mistake_flag = True
        while mistake_flag:
            # 开始前,将mistake_flag设置为False,用于判断本次循环是否有分类错误
            mistake_flag = False
            # (2)从训练集中选取x,y
            for index in range(self.X.shape[0]):
                if self.plot:
                    self.__model_plot.plot(weight, b, train_counts)
                # 损失函数
                loss = self.Y[index] * (weight @ self.X[index] + b)
                # (3)如果损失函数小于0,则该点是误分类点
                if loss <= 0:
                    # 更新weight, b
                    weight += self.lr * self.Y[index] * self.X[index]
                    b += self.lr * self.Y[index]
                    # 训练次数加1
                    train_counts += 1
                    print("Epoch {}, weight = {}, b = {}, formula: {}".format(
                        train_counts, weight, b, self.__model_plot.formula(weight, b)))
                    # 本次循环有误分类点(即分类错误),置为True
                    mistake_flag = True
                    break
        if self.plot:
            self.__model_plot.close()
        # (4)直至训练集中没有误分类点
        return weight, b

    class _ModelPlot:
        def __init__(self, X, Y):
            self.X = X
            self.Y = Y

        @staticmethod
        def open_in():
            # 打开交互模式,用于展示动态交互图
            plt.ion()

        @staticmethod
        def close():
            # 关闭交互模式,并显示最终的图形
            plt.ioff()
            plt.show()

        def plot(self, weight, b, epoch):
            plt.cla()
            # x轴表示x1
            plt.xlim(0, np.max(self.X.T[0]) + 1)
            # y轴表示x2
            plt.ylim(0, np.max(self.X.T[1]) + 1)
            # 画出散点图,并添加图示
            scatter = plt.scatter(self.X.T[0], self.X.T[1], c=self.Y)
            plt.legend(*scatter.legend_elements())
            if True in list(weight == 0):
                plt.plot(0, 0)
            else:
                x1 = -b / weight[0]
                x2 = -b / weight[1]
                # 画出分离超平面
                plt.plot([x1, 0], [0, x2])
                # 绘制公式
                text = self.formula(weight, b)
                plt.text(0.3, x2 - 0.1, text)
            plt.title('Epoch %d' % epoch)
            plt.pause(0.01)

        @staticmethod
        def formula(weight, b):
            text = 'x1 ' if weight[0] == 1 else '%d*x1 ' % weight[0]
            text += '+ x2 ' if weight[1] == 1 else (
                '+ %d*x2 ' % weight[1] if weight[1] > 0 else '- %d*x2 ' % -weight[1])
            text += '= 0' if b == 0 else ('+ %d = 0' %
                                          b if b > 0 else '- %d = 0' % -b)
            return text
X = np.array([[3, 3], [4, 3], [1, 1]])
Y = np.array([1, 1, -1])
model = Perceptron(X, Y, lr=1)
weight, b = model.fit()

输出结果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值