1. 程式人生 > >感知機PLA演算法實現[轉載]

感知機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],否則會報錯。