本文参考了以下几篇文章
1.BP神经网络算法 python实现 BP神经网络算法 python实现 - 人工智能 - 电子发烧友网
2.一个简单神经网络的代码实现一个简单神经网络的代码实现_神童i的博客-CSDN博客
3.深度学习基础之-5.1非线性分类-二分类深度学习基础之-5.1非线性分类-二分类 神经元解决异或问题 _Susan Wong-CSDN博客
本文主要描述解决XoR问题 以及简单的表格内容预测问题
二、两层神经网络实现线性分类问题 1. 采用算法预测下表结果 线性Inputs
Output
0
0
1
0
1
1
1
0
1
0
1
1
0
1
1
1
给定已知表格 尝试输入前三列数据去预测第四列数值 其中行为样本。
Input为输入样本 Output为实际结果值
先叠加两层神经网络 采用sigmod函数对数据进行激活
sigmod函数如图所示
sigmoid函数可以将任何值都映射到位于0到1范围内的值 通过它可以将任何值映射到位于0-1的范围内 可以令我们的实数值转化为概率值。同时sigmod函数的求导值也是很好求得 导数值为 out * (1 - out )得到 十分高效的。
# 两层神经元 import numpy as np # 激活函数 sigmod 将任何值变为0 - 1概率值 def sigmod(x, deriv False): # 求导True if True deriv: return x * (1 - x) # sigmod的导数形式 return 1/(1 np.exp(-x)) # 训练数据 初始化为numpy矩阵 每行对应实例 每列代表输入节点 train_data np.array([ [0,0,1], [0,1,1], [1,0,1], [1,1,1]]) y np.array([[0,0,1,1]]).T # 设计输出 np.random.seed(1) # 权重初始集分布都是完全一致的 weights np.random.random((3,1)) #权重矩阵w1 #print(weights) weights 2 * weights -1 # 随机数进行处理 类似正态分布 #print(weights) for iter in range(10000): # 变化数据只有weight l1 l0 train_data # 训练数据 l1 sigmod(np.dot(l0,weights)) # 训练数据与三个随机权重相乘 激活 预测值 loss y - l1 # 错误率 print( loss ,loss) # l1_delta 是一个变化率选项 l1_delta loss * sigmod(l1, True) # 求导 - a * dw/dl1# weights np.dot(l0.T, l1_delta) # 权重进行更新 print( weights ,weights) print( n ) print( times ,iter) print( pre_l1 n ,l1)
运行10000次后结果如图所示 发现两层神经元可以逼近线性结果。
2. 修改表格为非线性后无法预测Inputs
Output
0
0
1
0
1
1
1
1
1
0
1
1
0
1
1
0
我们对output数值进行修改后发现 预测的数据竟然是0.5 无法判断 原因是此类数据已经属于非线性无法用两层网络进行拟合。
# 两层神经元 import numpy as np # 激活函数 sigmod 将任何值变为0 - 1概率值 def sigmod(x, deriv False): # 求导True if True deriv: return x * (1 - x) # sigmod的导数形式 return 1/(1 np.exp(-x)) # 训练数据 初始化为numpy矩阵 每行对应实例 每列代表输入节点 train_data np.array([ [0,0,1], [0,1,1], [1,0,1], [1,1,1]]) y np.array([[0,1,1,0]]).T # 设计输出 np.random.seed(1) # 权重初始集分布都是完全一致的 weights np.random.random((3,1)) #权重矩阵w1 #print(weights) weights 2 * weights -1 # 随机数进行处理 类似正态分布 #print(weights) for iter in range(10000): # 变化数据只有weight l1 l0 train_data # 训练数据 l1 sigmod(np.dot(l0,weights)) # 训练数据与三个随机权重相乘 激活 预测值 loss y - l1 # 错误率 print( loss ,loss) # l1_delta 是一个变化率选项 l1_delta loss * sigmod(l1, True) # 求导 - a * dw/dl1# weights np.dot(l0.T, l1_delta) # 权重进行更新 print( weights ,weights) print( n ) print( times ,iter) print( pre_l1 n ,l1)
解决方法也很简单 再加一层神经元 可以更近一步拟合出具体函数。
三、三层神经网络实现非线性分类问题 1. 采用算法预测下表结果 非线性Inputs
Output
0
0
1
0
1
1
1
1
1
0
1
1
0
1
1
0
第二组数据无法预测是因为非线性 关系复杂一些 但多添加一层线性网络就能处理。
import numpy as np # 第一步设定激活函数sigmod def sigmod(x, deriv False): # 求导True if True deriv: return x * (1 - x) # sigmod的导数形式 return 1/(1 np.exp(-x)) train_data np.array([ [0,0,1], [0,1,1], [1,0,1], [1,1,1]]) y np.array([[0], [1], [1], [0]]) np.random.seed(1) weights1 2 * np.random.random((3, 4)) - 1 weights2 2 * np.random.random((4, 1)) - 1 for cnt in range(1000000): l0 train_data # [4, 3] 第一层 输入层 l0为我们的训练数据 l1 sigmod(np.dot(l0, weights1)) # [4, 4] l2 sigmod(np.dot(l1, weights2)) # [4, 1] l2_loss y - l2 # [4, 1] l2_delta l2_loss * sigmod(l2, True) l1_loss l2_delta.dot(weights2.T) l1_delta l1_loss * sigmod(l1, True) weights1 l0.T.dot(l1_delta) weights2 l1.T.dot(l2_delta) acc ((l2[0] l2[3]) ((1-l2[1]) (1-l2[2])))/4 print( cnt ,cnt) print( acc ,acc) print(l2)
具体结果如上图所示
2. XoR问题的分类讨论Inputs
Inputs
Output
0
0
0
1
1
0
1
0
1
0
1
1
异或 英文为exclusive OR 缩写成eor
异或 eor 是一个数学运算符。它应用于逻辑运算。异或的数学符号为“⊕” 计算机符号为“eor”。其运算法则为 a⊕b (¬a ∧ b) ∨ (a ∧¬b)
如果a、b两个值不相同 则异或结果为1。如果a、b两个值相同 异或结果为0。
分类的曲线可以理解为下图所示的非线性函数。
编写代码时要注意矩阵对齐 因为XoR分类与之前的表格分类列数上变化一小部分。
import numpy as np # 第一步设定激活函数sigmod def sigmod(x, deriv False): # 求导True if True deriv: return x * (1 - x) # sigmod的导数形式 return 1/(1 np.exp(-x)) train_data np.array([[0, 0], [0, 1], [1, 0], [1, 1]]) # 与之前相比 输入数据少了一列 预测起来更简单 y np.array([[0], [1], [1], [0]]) # y为预测值 np.random.seed(1) # 固定随机种子 weights1 2 * np.random.random((2, 4)) - 1 # 随机分布w权重 weights2 2 * np.random.random((4, 1)) - 1 for cnt in range(1000000): l0 train_data # [4, 2] 第一层 输入层 l0为我们的训练数据 l1 sigmod(np.dot(l0, weights1)) # [4, 4] l2 sigmod(np.dot(l1, weights2)) # [4, 1] l2_loss y - l2 # [4, 1] l2_delta l2_loss * sigmod(l2, True) # 每次权重要变化的大小 l1_loss l2_delta.dot(weights2.T) l1_delta l1_loss * sigmod(l1, True) weights1 l0.T.dot(l1_delta) # 权重进行更新 weights2 l1.T.dot(l2_delta) acc ((l2[0] l2[3]) ((1-l2[1]) (1-l2[2])))/4 # 预测精准度评定 print( cnt ,cnt) # 计数 print( acc ,acc) # 精度 print(l2)3. 拓展讨论
下一步选择完成4层的神经网络



