本文实例为大家分享了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