原题如下:
下面我们尝试使用Perceptron(感知机)算法学习XOR函数。
对于XOR函数,当输入是(0,0)或者(1,1)时,输出为0;当输入是(0,1)或者(1,0)时,输出是1. 我们知道,这不是线性可分的函数,所以感知机算法学习不了。
现在我们给每一个输入增加一维,输出不变;所以现在是
(0,0,a)>>0
(0,1,b)>>1
(1,0,c)>>1
(1,1,d)>>0
其中a,b,c,d均从{0,1}中独立取值。在这16种可能组合中,要求把最后误差为0的组合总数和各个组合给打印出来。
代码如下
from numpy import array, random, dot
from random import choice
# activate function
step_function = lambda x: 0 if x < 0 else 1
# training set,随意指定a,b,c,d的初始值
training_dataset = [
(array([0,0,1]), 0),
(array([0,1,0]), 1),
(array([1,0,0]), 1),
(array([1,1,1]), 0),
]
def training(training_dataset):
# 设置随机数种子
random.seed(1)
weights = random.rand(3)
# 配置learning rate
learning_rate = 0.2
# 设置训练次数为150
n = 150
b = 0
for j in range(n):
# 从数据集中随机选取一个子集作为训练集
x, expected = choice(training_dataset)
# 预测结果
result = dot(weights, x)+b
err = expected - step_function(result)
# 更新权重
weights += learning_rate * err * x
b = b + learning_rate * err
err_array = []
#计算误差向量
for x, y in training_dataset:
result = dot(x, weights)+b
err_val = y - step_function(result)
err_array.append(err_val)
# 输出误差向量
return err_array
output = 0
for i in [0,1]:
for j in [0,1]:
for l in [0,1]:
for k in [0,1]:
#列出所增加维度即a,b,c,d的所有可能结果,并分别进行训练
a = [i,j,k,l]
for t in range(4):
training_dataset[t][0][2] = a[t]
err_array = training(training_dataset)
#如果误差均为0,则a值可用
if err_array == [0,0,0,0]:
output += 1
# 返回a值
print(a)
print('线性可分的总组数为:{}'.format(output))
# 注:在循环次数为100的运行过程中,曾经出现过组数为9的情况;更换为150后,在目前的调试中,总组数均为10