一、感知机模型
在一个n维空间中,存在一个超平面,可以将特征向量分为+1和-1两个类别。(具体内容可以参考李航《统计学习方法》一书)。
二、代码实现
import numpy as np
def perceptron_algorithm_01(x_input, y_input, lr=1.0, weight_init='zeros', bias_init='zeros', max_iteration=1000):
'''
:param x_input:输入的特征向量,x∈R^n。
:param y_input: ,欸一个特征向量对应的类别,y∈{-1, +1}。
:param lr: 学习率,默认为1.0。
:param weight_init: 权重初始化方法,是['zeros', 'ones', 'random']三个中的一个。
:param bias_init: 偏置初始化方法,是['zeros', 'ones', 'random']三个中的一个。
:param max_iteration: 最大迭代次数,默认为1000。
:return: 权重weight和偏置bias
'''
assert len(x_input) == len(y_input)
if weight_init not in ['zeros', 'ones', 'random']:
raise ValueError("""Please choose weight_init parameter correctly!\n
weight_init: one of these choices:'zeros', 'ones', 'random'""")
if bias_init not in ['zeros', 'ones', 'random']:
raise ValueError("""Please choose bias_init parameter correctly!\n
bias_init: one of these choices:'zeros', 'ones', 'random'""")
x_input = np.array(x_input)
y_input = np.array(y_input)
if weight_init == 'zeros':
weight = np.zeros(shape=[x_input.shape[1]])
elif weight_init == 'ones':
weight = np.ones(shape=[x_input.shape[1]])
elif weight_init == 'random':
weight = np.random.random(size=(x_input.shape[1]))
if bias_init == 'zeros':
bias = 0
elif bias_init == 'ones':
bias = 1
elif bias_init == 'random':
bias = np.random.random()
iteration = 0
while True:
x, y = None, None
for i, j in zip(x_input, y_input):
if j * (sum(weight * i) + bias) <= 0:
x = i
y = j
break
if x is not None and y is not None and iteration < max_iteration:
weight += lr * y * x
bias += lr * y
iteration += 1
else:
break
return weight, bias
def perceptron_algorithm_02(x_input, y_input, lr=1.0, alpha_init='zeros', bias_init='zeros', max_iteration=1000):
'''
:param x_input:输入的特征向量,x∈R^n。
:param y_input: ,欸一个特征向量对应的类别,y∈{-1, +1}。
:param lr: 学习率,默认为1.0。
:param alpha_init: 权重初始化方法,是['zeros', 'ones', 'random']三个中的一个。
:param bias_init: 偏置初始化方法,是['zeros', 'ones', 'random']三个中的一个。
:param max_iteration: 最大迭代次数,默认为1000。
:return: 权重weight和偏置bias
'''
assert len(x_input) == len(y_input)
x_input = np.array(x_input)
y_input = np.array(y_input)
if alpha_init not in ['zeros', 'ones', 'random']:
raise ValueError("""Please choose alpha_init parameter correctly!\n
alpha_init: one of these choices:'zeros', 'ones', 'random'""")
if bias_init not in ['zeros', 'ones', 'random']:
raise ValueError("""Please choose bias_init parameter correctly!\n
bias_init: one of these choices:'zeros', 'ones', 'random'""")
if alpha_init == 'zeros':
alpha = np.zeros(shape=[x_input.shape[0]])
elif alpha_init == 'ones':
alpha = np.ones(shape=[x_input.shape[0]])
elif alpha_init == 'random':
alpha = np.random.random(size=(x_input.shape[0]))
if bias_init == 'zeros':
bias = 0
elif bias_init == 'ones':
bias = 1
elif bias_init == 'random':
bias = np.random.random()
gram_matrix = np.zeros(shape=[x_input.shape[0], x_input.shape[0]])
for i in range(x_input.shape[0]):
for j in range(i, x_input.shape[0]):
gram_matrix[i][j] = gram_matrix[j][i] = sum(x_input[i]*x_input[j])
iteration = 0
while True:
pos = -1
for i in range(len(x_input)):
if y_input[i] * (sum(alpha[j] * y_input[j] * gram_matrix[i][j] for j in range(len(x_input))) + bias) <= 0:
pos = i
break
if pos != -1 and iteration < max_iteration:
alpha[pos] += lr
bias += lr * y_input[pos]
iteration += 1
else:
break
weight = np.sum((alpha[i] * y_input[i] * x_input[i] for i in range(len(x_input))), axis=0)
return weight, bias
if __name__ == '__main__':
x = [[3, 3], [4, 3], [1, 1]]
y = [1, 1, -1]
w, b = perceptron_algorithm_01(x, y, lr=1.0, weight_init='zeros', bias_init='zeros')
print('感知机学习算法的原始形式:')
print('所得权重:', w)
print('所得偏置:', b)
w, b = perceptron_algorithm_02(x, y, lr=1.0, alpha_init='zeros', bias_init='zeros')
print('感知机学习算法的对偶形式:')
print('所得权重:', w)
print('所得偏置:', b)
结果如下:
感知机学习算法的原始形式:
所得权重: [1. 1.]
所得偏置: -3.0
感知机学习算法的对偶形式:
所得权重: [1. 1.]
所得偏置: -3.0
三、结论
感知机是一种极为简单的机器学习模型,对初始值敏感,在实际中较少用到。