zoukankan      html  css  js  c++  java
  • 感知机PLA算法实现[转载]

    转自:https://blog.csdn.net/u010626937/article/details/72896144#commentBox

    1.实现原始形式

    import numpy as np
    import matplotlib.pyplot as plt
    
    #1、创建数据集
    def createdata():
        samples=np.array([[3,-3],[4,-3],[1,1],[1,2]])#4行2列
        labels=[-1,-1,1,1]
        return samples,labels
    
    #训练感知机模型
    class Perceptron:
        def __init__(self,x,y,a=1):
            self.x=x
            self.y=y
            self.w=np.zeros((x.shape[1],1))#初始化权重,w1,w2均为0
            self.b=0
            self.a=1#学习率
            self.numsamples=self.x.shape[0]
            self.numfeatures=self.x.shape[1]
    
        def sign(self,w,b,x):
            y=np.dot(x,w)+b
            return int(y)
    
        def update(self,label_i,data_i):
            tmp=label_i*self.a*data_i
            tmp=tmp.reshape(self.w.shape)#转换成w的形状。
            #更新w和b
            self.w=tmp+self.w
            self.b=self.b+label_i*self.a
    
        def train(self):
            isFind=False
            while not isFind:
                count=0
                for i in range(self.numsamples):
                    tmpY=self.sign(self.w,self.b,self.x[i,:])
                    if tmpY*self.y[i]<=0:#如果是一个误分类实例点
                        print ('误分类点为:',self.x[i,:],'此时的w和b为:',self.w,self.b)
                        count+=1
                        self.update(self.y[i],self.x[i,:])#更新
                if count==0:
                    print ('最终训练得到的w和b为:',self.w,self.b)
                    isFind=True
            return self.w,self.b
    
    #画图描绘
    class Picture:
        def __init__(self,data,w,b):
            self.b=b
            self.w=w
            plt.figure(1)
            plt.title('Perceptron Learning Algorithm',size=14)
            plt.xlabel('x0-axis',size=14)
            plt.ylabel('x1-axis',size=14)
    
            xData=np.linspace(0,5,100)#start stop 要生成的样本数,是一个array
            yData=self.expression(xData)#
            plt.plot(xData,yData,color='r',label='sample data')
    
            plt.scatter(data[0][0],data[0][1],s=50)
            plt.scatter(data[1][0],data[1][1],s=50)
            plt.scatter(data[2][0],data[2][1],s=50,marker='x')
            plt.scatter(data[3][0],data[3][1],s=50,marker='x')
            plt.savefig('2d.png',dpi=75)
    
        def expression(self,x):#只是为了画出这一条直线。
            y=(-self.b-self.w[0]*x)/self.w[1]#注意在此,把x0,x1当做两个坐标轴,把x1当做自变量,x2为因变量
            return y
    
        def Show(self):
            plt.show()
    
    
    if __name__ == '__main__':
        samples,labels=createdata()
        myperceptron=Perceptron(x=samples,y=labels)
        weights,bias=myperceptron.train()
        Picture=Picture(samples,weights,bias)
        Picture.Show()

    运行结果:

    误分类点为: [ 3 -3] 此时的w和b为: [[0.]
     [0.]] 0
    误分类点为: [1 1] 此时的w和b为: [[-3.]
     [ 3.]] -1
    最终训练得到的w和b为: [[-2.]
     [ 4.]] 0

    //真是太厉害了。

     2.实现对偶形式

    import numpy as np
    import matplotlib.pyplot as plt
    
    #1、创建数据集
    def createdata():
        samples=np.array([[3,-3],[4,-3],[1,1],[1,2]])
        labels=np.array([-1,-1,1,1])
        return samples,labels
    
    #训练感知机模型
    class Perceptron:
        def __init__(self,x,y,a=1):
            self.x=x
            self.y=y
            self.w=np.zeros((1,x.shape[0]))#1行4列
            self.b=0
            self.a=1#学习率
            self.numsamples=self.x.shape[0]
            self.numfeatures=self.x.shape[1]
            self.gMatrix=self.cal_gram(self.x)
    
        def cal_gram(self,x):
            gMatrix=np.zeros((self.numsamples,self.numsamples))
            for i in range(self.numsamples):
                for j in range(self.numsamples):
                    gMatrix[i][j]=np.dot(self.x[i,:],self.x[j,:])
            return gMatrix
    
        def sign(self,w,b,key):
            y=np.dot(w*self.y,self.gMatrix[:,key])+b
            return int(y)
    
        def update(self,i):
            print(i,'@@@iii')
            self.w[:,i]=self.w[:,i]+self.a
            self.b=self.b+self.y[i]*self.a
    
        def cal_w(self):
            w=np.dot(self.w*self.y,self.x)
            return w
    
        def train(self):
            isFind=False
            while not isFind:
                count=0
                for i in range(self.numsamples):
                    tmpY=self.sign(self.w,self.b,i)
                    if tmpY*self.y[i]<=0:#如果是一个误分类实例点
                        print('误分类点为:',self.x[i,:],'此时的w和b为:',self.cal_w(),',',self.b)
                        count+=1
                        self.update(i)
                if count==0:
                    print ('最终训练得到的w和b为:',self.cal_w(),',',self.b)
                    print(self.w)
                    isFind=True
            weights=self.cal_w()
            return weights,self.b
    
    #画图描绘
    class Picture:
        def __init__(self,data,w,b):
            self.b=b
            self.w=w
            plt.figure(1)
            plt.title('Perceptron Learning Algorithm',size=14)
            plt.xlabel('x0-axis',size=14)
            plt.ylabel('x1-axis',size=14)
    
            xData=np.linspace(0,5,100)
            yData=self.expression(xData)
            plt.plot(xData,yData,color='r',label='sample data')
    
            plt.scatter(data[0][0],data[0][1],s=50)
            plt.scatter(data[1][0],data[1][1],s=50)
            plt.scatter(data[2][0],data[2][1],s=50,marker='x')
            plt.scatter(data[3][0],data[3][1],s=50,marker='x')
            plt.savefig('2d.png',dpi=75)
    
        def expression(self,x):
            y=(-self.b-self.w[:,0]*x)/self.w[:,1]
            return y
    
        def Show(self):
            plt.show()
    
    
    if __name__ == '__main__':
    
        samples,labels=createdata()
        myperceptron=Perceptron(x=samples,y=labels)
        weights,bias=myperceptron.train()
        Picture=Picture(samples,weights,bias)
        Picture.Show()

    //注:原博主的update的函数有误,应该是对w的列+a,而不是行。。。现在已经更改。 结果也是正确的结果。

    运行结果:

    误分类点为: [ 3 -3] 此时的w和b为: [[0. 0.]] , 0
    0 @@@iii
    误分类点为: [1 1] 此时的w和b为: [[-3. 3.]] , -1
    2 @@@iii
    最终训练得到的w和b为: [[-2. 4.]] , 0
    [[1. 0. 1. 0.]]   

    注:最后一行是——w。

    讨论:

     转:https://blog.csdn.net/qq_28618765/article/details/78083179

    dot()函数是矩阵乘,而*则表示逐个元素相乘

    以及关于这个向量和矩阵乘法的问题:

    array对于这种shape函数结果是(3,)类型的,它在运算时是十分灵活的,既可以作为列向量,也可以作为行向量。

    import numpy as np
    
    x=[[1,2,3],[4,5,6]]
    y=[1,2,3]
    xy=np.dot(x,y)
    print(xy,xy.shape)
    
    z=[1,2]
    xy2=np.dot(z,x)
    print(xy2,xy2.shape)

    结果:

    [14 32] (2,)
    [ 9 12 15] (3,)

    对于y右乘x,是作为列向量处理了;对于z坐成x,是作为行向量处理了。

    3.关于矩阵运算的一些坑试跳

    import numpy as np
    
    x=[[1,1,1,1]]
    #print(x.shape)
    #报错:AttributeError: 'list' object has no attribute 'shape'
    
    y=[1,1,1,1]
    #print(y.shape)
    #报错:AttributeError: 'list' object has no attribute 'shape'
    
    z=np.array([1,1,1,1])
    print(z.shape)
    #输出:(4,)
    
    z[2,]=z[2,]+1
    print(z)
    #输出:[1 1 2 1]
    
    u=np.matrix([1,2,3,4])
    print(u.shape)
    #输出:(1, 4)
    
    u[:,1]=u[:,1]+1
    print(u)
    #输出:[[1 3 3 4]]
    
    #u[1,]=u[1,]+10
    #print(u)
    #输出:IndexError: index 1 is out of bounds for axis 0 with size 1
    
    print(u[0,])
    #输出:[[1 3 3 4]]
    
    u[:,1]=u[:,1]+10
    print(u)
    #输出:[[ 1 13  3  4]]
    
    print(u[0])
    #输出:[[ 1 13  3  4]]
    #说明:取矩阵的一行是可以使用u[1]或者u[1,]的
    #但是取矩阵的一列必须使用:,u[:,1],否则会报错。
  • 相关阅读:
    用C#编写获取远程IP,MAC的方法
    创建 TransactSQL 作业步骤
    S3C2440系统时钟
    C# 跟年月日判断星期几
    嵌入式系统启动例程
    使用HTML5和CSS3来创建幻灯片
    巧解Android时区加载过慢的问题
    HTML5之美
    C#如何取硬件标志
    S3C2440看门狗定时器(Watchdog)
  • 原文地址:https://www.cnblogs.com/BlueBlueSea/p/10065114.html
Copyright © 2011-2022 走看看