本文实例为大家分享了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
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
|
# -*- coding: utf-8 -*- import numpy as np class Perceptron( object ): """ 感知器:用于二分类 参照改写 https://blog.csdn.net/simple_the_best/article/details/54619495 属性: w0:偏差 w:权向量 learning_rate:学习率 threshold:准则阈值 """ def __init__( self ,learning_rate = 0.01 ,threshold = 0.001 ): self .learning_rate = learning_rate self .threshold = threshold def train( self ,x,y): """训练 参数: x:样本,维度为n*m(样本有m个特征,x输入就是m维),样本数量为n y:类标,维度为n*1,取值1和-1(正样本和负样本) 返回: self:object """ self .w0 = 0.0 self .w = np.full(x.shape[ 1 ], 0.0 ) k = 0 while ( True ): k + = 1 dJw0 = 0.0 dJw = np.zeros(x.shape[ 1 ]) err = 0.0 for i in range ( 0 ,x.shape[ 0 ]): if not (y[i] = = 1 or y[i] = = - 1 ): print ( "类标只能为1或-1!请核对!" ) break update = self .learning_rate * 0.5 * (y[i] - self .predict(x[i])) dJw0 + = update dJw + = update * x[i] err + = np. abs ( 0.5 * (y[i] - self .predict(x[i]))) self .w0 + = dJw0 self .w + = dJw if np. abs (np. sum ( self .learning_rate * dJw))< self .threshold or k> 500 : print ( "迭代次数:" ,k, " 错分样本数:" ,err) break return self def predict( self ,x): """预测类别 参数: x:样本,1*m维,1个样本,m维特征 返回: yhat:预测的类标号,1或者-1,1代表正样本,-1代表负样本 """ if np.matmul( self .w,x.T) + self .w0> 0 : yhat = 1 else : yhat = - 1 return yhat def predict_value( self ,x): """预测值 参数: x:样本,1*m维,1个样本,m维特征 返回: y:预测值 """ y = np.matmul( self .w,x.T) + self .w0 return y |
然后为Iris数据集创建一个Iris类,用于产生5折验证所需要的数据,并且能产生不同样本数量的数据集。
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
|
# -*- coding: utf-8 -*- """ Author:CommissarMa 2018年5月23日 16点52分 """ import numpy as np import scipy.io as sio class Iris( object ): """Iris数据集 参数: data:根据size裁剪出来的iris数据集 size:每种类型的样本数量 way:one against the rest || one against one 注意: 此处规定5折交叉验证(5-cv),所以每种类型样本的数量要是5的倍数 多分类方式:one against the rest """ def __init__( self ,size = 50 ,way = "one against the rest" ): """ size:每种类型的样本数量 """ data = sio.loadmat( "C:\\Users\\CommissarMa\\Desktop\\模式识别\\课件ppt\\PR实验内容\\iris_data.mat" ) iris_data = data[ 'iris_data' ] #iris_data:原数据集,shape:150*4,1-50个样本为第一类,51-100个样本为第二类,101-150个样本为第三类 self .size = size self .way = way self .data = np.zeros((size * 3 , 4 )) for r in range ( 0 ,size * 3 ): self .data[r] = iris_data[ int (r / size) * 50 + r % size] def generate_train_data( self ,index_fold,index_class,neg_class = None ): """ index_fold:5折验证的第几折,范围:0,1,2,3,4 index_class:第几类作为正类,类别号:负类样本为-1,正类样本为1 """ if self .way = = "one against the rest" : fold_size = int ( self .size / 5 ) #将每类样本分成5份 train_data = np.zeros((fold_size * 4 * 3 , 4 )) label_data = np.full((fold_size * 4 * 3 ), - 1 ) for r in range ( 0 ,fold_size * 4 * 3 ): n_class = int (r / (fold_size * 4 )) #第几类 n_fold = int ((r % (fold_size * 4 )) / fold_size) #第几折 n = (r % (fold_size * 4 )) % fold_size #第几个 if n_fold<index_fold: train_data[r] = self .data[n_class * self .size + n_fold * fold_size + n] else : train_data[r] = self .data[n_class * self .size + (n_fold + 1 ) * fold_size + n] label_data[fold_size * 4 * index_class:fold_size * 4 * (index_class + 1 )] = 1 elif self .way = = "one against one" : if neg_class = = None : print ( "one against one模式下需要提供负类的序号!" ) return else : fold_size = int ( self .size / 5 ) #将每类样本分成5份 train_data = np.zeros((fold_size * 4 * 2 , 4 )) label_data = np.full((fold_size * 4 * 2 ), - 1 ) for r in range ( 0 ,fold_size * 4 * 2 ): n_class = int (r / (fold_size * 4 )) #第几类 n_fold = int ((r % (fold_size * 4 )) / fold_size) #第几折 n = (r % (fold_size * 4 )) % fold_size #第几个 if n_class = = 0 : #放正类样本 if n_fold<index_fold: train_data[r] = self .data[index_class * self .size + n_fold * fold_size + n] else : train_data[r] = self .data[index_class * self .size + (n_fold + 1 ) * fold_size + n] if n_class = = 1 : #放负类样本 if n_fold<index_fold: train_data[r] = self .data[neg_class * self .size + n_fold * fold_size + n] else : train_data[r] = self .data[neg_class * self .size + (n_fold + 1 ) * fold_size + n] label_data[ 0 :fold_size * 4 ] = 1 else : print ( "多分类方式错误!只能为one against one 或 one against the rest!" ) return return train_data,label_data def generate_test_data( self ,index_fold): """生成测试数据 index_fold:5折验证的第几折,范围:0,1,2,3,4 返回值: test_data:对应于第index_fold折的测试数据 label_data:类别号为0,1,2 """ fold_size = int ( self .size / 5 ) #将每类样本分成5份 test_data = np.zeros((fold_size * 3 , 4 )) label_data = np.zeros(fold_size * 3 ) for r in range ( 0 ,fold_size * 3 ): test_data[r] = self .data[ int ( int (r / fold_size) * self .size) + int (index_fold * fold_size) + r % fold_size] label_data[ 0 :fold_size] = 0 label_data[fold_size:fold_size * 2 ] = 1 label_data[fold_size * 2 :fold_size * 3 ] = 2 return test_data,label_data |
然后我们进行训练测试,先使用one against the rest策略:
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
|
# -*- coding: utf-8 -*- from perceptron import Perceptron from iris_data import Iris import numpy as np if __name__ = = "__main__" : iris = Iris(size = 50 ,way = "one against the rest" ) correct_all = 0 for n_fold in range ( 0 , 5 ): p = [Perceptron(),Perceptron(),Perceptron()] for c in range ( 0 , 3 ): x,y = iris.generate_train_data(index_fold = n_fold,index_class = c) p[c].train(x,y) #训练完毕,开始测试 correct = 0 x_test,y_test = iris.generate_test_data(index_fold = n_fold) num = len (x_test) for i in range ( 0 ,num): maxvalue = max (p[ 0 ].predict_value(x_test[i]),p[ 1 ].predict_value(x_test[i]), p[ 2 ].predict_value(x_test[i])) if maxvalue = = p[ int (y_test[i])].predict_value(x_test[i]): correct + = 1 print ( "错分数量:" ,num - correct, "错误率:" ,(num - correct) / num) correct_all + = correct print ( "平均错误率:" ,(num * 5 - correct_all) / (num * 5 )) |
然后使用one against one 策略去训练测试:
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
|
# -*- coding: utf-8 -*- from perceptron import Perceptron from iris_data import Iris import numpy as np if __name__ = = "__main__" : iris = Iris(size = 10 ,way = "one against one" ) correct_all = 0 for n_fold in range ( 0 , 5 ): #训练 p01 = Perceptron() #0类和1类比较的判别器 p02 = Perceptron() p12 = Perceptron() x,y = iris.generate_train_data(index_fold = n_fold,index_class = 0 ,neg_class = 1 ) p01.train(x,y) x,y = iris.generate_train_data(index_fold = n_fold,index_class = 0 ,neg_class = 2 ) p02.train(x,y) x,y = iris.generate_train_data(index_fold = n_fold,index_class = 1 ,neg_class = 2 ) p12.train(x,y) #测试 correct = 0 x_test,y_test = iris.generate_test_data(index_fold = n_fold) num = len (x_test) for i in range ( 0 ,num): vote0 = 0 vote1 = 0 vote2 = 0 if p01.predict_value(x_test[i])> 0 : vote0 + = 1 else : vote1 + = 1 if p02.predict_value(x_test[i])> 0 : vote0 + = 1 else : vote2 + = 1 if p12.predict_value(x_test[i])> 0 : vote1 + = 1 else : vote2 + = 1 if vote0 = = max (vote0,vote1,vote2) and int (vote0) = = int (y_test[i]): correct + = 1 elif vote1 = = max (vote0,vote1,vote2) and int (vote1) = = int (y_test[i]): correct + = 1 elif vote2 = = max (vote0,vote1,vote2) and int (vote2) = = int (y_test[i]): correct + = 1 print ( "错分数量:" ,num - correct, "错误率:" ,(num - correct) / num) correct_all + = correct print ( "平均错误率:" ,(num * 5 - correct_all) / (num * 5 )) |
实验结果如图所示:
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。
原文链接:https://blog.csdn.net/u012343179/article/details/80433068