感知机学习算法

机器学习的第一个作业,写完纸质还有时间,那就用Python写算法试试咯,老师说后面有真正的实验报告,先用Python写一下熟悉熟悉,回顾一下前几天学的Python吧。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#感知机原始形式算法
def ganzhiji(lst,n,w,b):
result = [-1]
while(''.join(str(result)).count('-')!=0):
result.clear()
for x in lst:
sum = x[2] * (w[0]*x[0] + w[1]*x[1] + b)
result.append(sum)
if sum > 0:
print("对({0},{1})T".format(x[0],x[1]))
print("y(wx + b) = {0}({1}*{2} + {3}*{4} + {5}) > 0".format(x[2],w[0],x[0],w[1],x[1],b), end=",")
print("({0},{1})T被正确分类".format(x[0], x[1]))
print()
else:
print("对({0},{1})T".format(x[0],x[1]))
print("y(wx + b) = {0}({1}*{2} + {3}*{4} + {5}) <= 0".format(x[2],w[0],x[0],w[1],x[1],b), end=",")
print("({0},{1})T未被正确分类,更新w和b".format(x[0], x[1]))
w[0] = w[0] + n*x[2]*(x[0])
w[1] = w[1] + n*x[2]*(x[1])
b = b + n*x[2]
print("w = ({0},{1})T, b = {2}".format(w[0],w[1],b))
print("得到线性模型:{0}x(1) + {1}x(2) + {2}".format(w[0],w[1],b))
print()

if __name__ == '__main__':
#lst = [[4,3,1],[4,4,1],[3,1,-1]]
#n = 1
w = [0,0]
b = 0

print("该算法默认权值w和偏置b都从0开始")
lst = []
while(True):
z = input("输入数据集,比如(x,y)=[3,1,-1]输入3 1 -1(回车),输入end结束:")
x_list = z.split(' ')
if ''.join(x_list) == "end":
break
for i in range(len(x_list)):
x_list[i] = int(x_list[i])
lst.append(x_list)
n = int(input("算法的学习率为(0<n<=1):"))
ganzhiji(lst,n,w,b)

上面这个是为了与手写作业保持一致,看了老师给的参考代码后发现完全不是一个样子。下面贴上参考答案以及我对代码的理解。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#利用Python实现感知机算法的原始形式
# -*- encoding:utf-8 -*-


import numpy as np
import matplotlib.pyplot as plt

#1、创建数据集
def createdata():
#np.array()的作用就是把列表转化为数组,也可以说是用来产生数组
samples=np.array([[3,-3],[4,-3],[1,1],[1,2]])
labels=[-1,-1,1,1]
return samples,labels #返回值如果是两个及以上,是以元组的形式返回

#训练感知机模型
class Perceptron:
def __init__(self,x,y,a=1):
self.x=x
self.y=y
#x.shape()=samples.shape()用来输出数组的基本信息,print(x.shape())得(4,2),表示samples中有1个4行2列的二维数组,x.shape[1]=2
#np.zeros()返回一个给定形状和类型的用0填充的数组,此处表示返回一个2行1列的值全为0的数组
self.w=np.zeros((x.shape[1],1))#初始化权重,数学化表示为(0,0)^T
self.b=0#初始化偏置为0
self.a=1#学习率
self.numsamples=self.x.shape[0]#样本数为4
self.numfeatures=self.x.shape[1]#特征值为2

def sign(self,w,b,x):
#np.dot()在这里用作向量内积
y=np.dot(x,w)+b
return int(y)

def update(self,label_i,data_i):
tmp=label_i*self.a*data_i
#reshape()用来将tmp转化成权重的格式
tmp=tmp.reshape(self.w.shape)
#更新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):
#x[i,:]表示读取x数组中的第i行所有元素
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,:])#用误分类点更新w和b
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)是新建一个名叫 Figure1的画图窗口
plt.figure(1)
#标题,横竖坐标轴的名字和字体大小为14
plt.title('Perceptron Learning Algorithm',size=14)
plt.xlabel('x0-axis',size=14)
plt.ylabel('x1-axis',size=14)

#从0-5中生成100个数,返回一个列表
xData=np.linspace(0,5,100)
yData=self.expression(xData)
#plt.plot()是在画图窗口里具体绘制横轴为xData,纵轴为yData的红线,标签为sample data
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')

#保存图片为2d.png,dpi为75
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() #将createdata的两个返回值分别赋给samples和labels
myperceptron=Perceptron(x=samples,y=labels)
weights,bias=myperceptron.train()
Picture=Picture(samples,weights,bias)
Picture.Show()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#利用Python实现感知机算法的对偶形式
# -*- encoding:utf-8 -*-



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
#返回1行4列的全0数组,即alpha=(0,0,0,0)
self.w=np.zeros((1,x.shape[0]))
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):
#生成一个4行4列的全0数组
gMatrix=np.zeros((self.numsamples,self.numsamples))
for i in range(self.numsamples):
for j in range(self.numsamples):
#从x1x1到xnxn做向量内积
gMatrix[i][j]=np.dot(self.x[i,:],self.x[j,:])
return gMatrix

def sign(self,w,b,key):
#这里的w相当于aplpha,w*y与矩阵key列的所有元素做向量内积
y=np.dot(w*self.y,self.gMatrix[:,key])+b
return int(y)

def update(self,i):
#将alpha中第i个的元素加上学习率
self.w[i,]=self.w[i,]+self.a
self.b=self.b+self.y[i]*self.a

def cal_w(self):
#最终权重w
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)
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()