机器学习初级入门-感知机

204 阅读5分钟

理解:感知机是分类模型,其单个特征向量最终训练结果是{+1,-1}。(这里不用输入空间,输出空间等术语).

函数:y=sign(wx+b)

参数解析:w和b是感知机的模型参数(不了解不要紧,往下看),w是权值(权值向量,x是个特征向量),b是偏置。sign(x)是一个函数,当x>=0时为+1,否则为-1。

几何解释:线性方程wx+b=0对应于空间中的一个超平面S,其中w是法向量,b是截距。这个超平面将空间划分为两部分,分别是正负两类。

咱们建立模型的时候就是求w和b。

x0到S的距离:y0=|wx0+b|/||w|| 这里||w||是w的L2范数

L0范数是指向量中非0的元素的个数。(L0范数很难优化求解)

L1范数是指向量中各个元素绝对值之和

L2范数是指向量各元素的平方和然后求平方根

L1范数可以进行特征选择,即让特征的系数变为0.

L2范数可以防止过拟合,提升模型的泛化能力,有助于处理 condition number不好下的矩阵(数据变化很小矩阵求解后结果变化很大)

(核心:L2对大数,对outlier离群点更敏感!)

下降速度:最小化权值参数L1比L2变化的快

模型空间的限制:L1会产生稀疏 L2不会。

L1会趋向于产生少量的特征,而其他的特征都是0,而L2会选择更多的特征,这些特征都会接近于0。 ———————————————— 版权声明:本文为CSDN博主「rocling」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:blog.csdn.net/rocling/art…

那么我们很容易的就知道了,损失函数等于所有分类错误的点的y0之和。 损失函数: ==L(w,b)=∑|wx0+b|/||w||=-∑y0|wx0+b|/||w||(此时y0<0)==

那么大家说,咱们做这个感知机算法,是不是损失函数越小越好? 答案是肯定的,那么咱们就需要得到,min L(w,b)

怎么找呢? 用梯度下降法。

“梯度下降算法的解释:梯度下降算法最速下降法又称为梯度法,它是解析法中最古老的一种,其他解析方法或是它的变形,或是受它的启发而得到的,因此它是最优化方法的基础。作为一种基本的算法,他在最优化方法中占有重要地位。”

咱们把所有的y0,x0看称矩阵,Y,X.那么这个损失函数可以看称 L(w,b)=-Y(wX+b) 咱们要求的是w和b(X,Y已知),分开求,咱们要求的是L(w,b)的最小值,所以把。所以对w和b分别求导。 dL/dw=-YX dL/db=-Y

然后我们每算一次w和b的梯度(斜率或者是导数)就对w,b更新: w->w+αxiyi b->b+αyi α步长,也就是学习率(梯度下降每次的变化程度),(xi,yi)是随机的误分类点。我们期望损失函数一直减小,直到我们满意。

算法的收敛性:经过有限次迭代可以得到一个完全正确划分数据集的超平面(感知机模型)。为了方便推导我们将偏置b并入权重w,记作w^^=(w^T^,b)^T^ 同样也将输入的向量扩充,加进常数1,记作x^^=(x^T^,1)^T^。 此时x^^w^^=wx+b

Novikoff定理: 在这里插入图片描述 有兴趣就记一下,不会的话我可以给解释的。(笔写拍照)

感知机学习算法的对偶形式:将w,b表示为xi和yi的线性组合形式,通过求其系数而求w和b,不失一般性,对误分类点(xi,yi)通过: w+αxiyi->w b+αyi->b 来逐步修改w,b,设修改n次,w,b的增量为βiyixi和βiyi,βi=αini 那么最后的w,b为(第一次w0=b0=0) w=∑βiyixi b=∑βiyi 那么Y=sign(∑βiyixiX+b)

于是出现算法: 在这里插入图片描述 为了方便我们可以把Gram矩阵先求出来: G=[xi*X] 其实看不懂没关系,看下面这个你就懂了。 在这里插入图片描述 代码:(建议自己跟着写写) 原始形式的感知机:

import random
import numpy as np
import matplotlib.pyplot as plt  
def sign(x):
    if x>0:
        return 1
    else:
        return 0
def train(train_num,train_datas,lr):
    w=[0,0]
    b=0
    #第一轮w和b都设置成0
    for i in range(train_num):
        x=random.choice(train_datas)
        #随机选择一个
        x1,x2,y=x
        #拿出数据
        if(y*(w[0]*x1+w[1]*x2+b)<=0):
        #if(y*sign((w[0]*x1+w[1]*x2+b))<=0):
            #进入条件
            w[0]+=x1*y*lr
            w[1]+=x2*y*lr
            b+=lr*y
    return b,w
def plot_points(train_datas,w,b):
    plt.figure()
    #创建自定义图像
    x1 = np.linspace(0, 8, 100)
    #numpy.linspace(start,end,num)
    #在start和end之间生成均匀的num个数据
    x2 = (-b-w[0]*x1)/w[1]
    #通过咱们的公式x1w1+x2w2+b=0求分界线
    plt.plot(x1, x2, color='r', label='y1 data')
    #画直线
    datas_len=len(train_datas)
    #数据个数
    for i in range(datas_len):
        if(train_datas[i][-1]==1):
            #-1是拿第1个数据里的最后一个数据
            plt.scatter(train_datas[i][0],train_datas[i][1],s=50)  
            #画点
        else:
            plt.scatter(train_datas[i][0],train_datas[i][1],marker='x',s=50)  
    plt.show()

if __name__=='__main__':
    train_data1 = [[1, 3, 1], [2, 2, 1], [3, 8, 1], [2, 6, 1]]  # 正面
    train_data2 = [[2, 1, -1], [4, 1, -1], [6, 2, -1], [7, 3, -1]]  #反面
    train_datas = train_data1 + train_data2  #整体数据集
    b,w=train(train_num=500,train_datas=train_datas,lr=0.1)
    #train_num是训练次数,lr是步数。
    plot_points(train_datas,w,b)
    #画图,以后慢慢讲

对偶形式的感知机:

import random
import numpy as np
import matplotlib.pyplot as plt  
def train(train_num,train_datas,lr):
    w=0.0
    #下面求w会需要float64类型的变量
    b=0
    #初始化
    data_len=len(train_datas)
    #求数据个数
    alpha = [0 for i in range(data_len)]
    #创建和数据个数数量元素的alpha矩阵
    train_array = np.array(train_datas)
    gram = np.matmul(train_array[:,0:-1] , train_array[:,0:-1].T)
    #求gram看我那张图
    for index in range(train_num):
        value=0
        i = random.randint(0,data_len-1)
        #生成一个随机数范围为[0,data_len-1]
        yi=train_array[i,-1]
        for j in range(data_len):
            value+=alpha[j]*train_array[j,-1]*gram[i,j]
        value+=b
        value=yi*value
        #以上就是误分条件的左边
        if(value<=0):
            alpha[i]=alpha[i]+lr
    for i in range(data_len):
         w+=alpha[i]*train_array[i,0:-1]*train_array[i,-1]
         b+=alpha[i]*train_array[i,-1]
    return w,b,alpha,gram
def draw(train_datas,w,b):
    plt.figure()
    x1 = np.linspace(0, 8, 100)
    x2 = (-b-w[0]*x1)/w[1]
    #根据式子反推
    plt.plot(x1, x2, color='r', label='y1 data')
    datas_len=len(train_datas)
    for i in range(datas_len):
        if(train_datas[i][-1]==1):
            plt.scatter(train_datas[i][0],train_datas[i][1],s=50)  
        else:
            plt.scatter(train_datas[i][0],train_datas[i][1],marker='x',s=50)  
    plt.show()
         
if __name__=='__main__':
    train_data1 = [[1, 3, 1], [2, 2, 1], [3, 8, 1], [2, 6, 1]]  #正例
    train_data2 = [[2, 1, -1], [4, 1, -1], [6, 2, -1], [7, 3, -1]]  #反例
    train_datas = train_data1 + train_data2
    w,b,alpha,gram=train(train_num=500,train_datas=train_datas,lr=0.1)
    draw(train_datas,w,b)

需要Novikoff求导的话说一下昂,我感觉这些定理,死记硬背应该行。