* NumPy 是Python语言的一个扩充程序库。支持高级大量的维度数组与矩阵运算,此外也针对数组运算提供大量的数学函数库。
二、单层神经元
1. 问题描述
问题
- 假设在一群人中,我们只能获得每个人的三个特征:
- 特征1:长发(1)还是短发(0)
- 特征2:衣服颜色是红色(1)还是不是红色(0)
- 特征3:身高大于178cm(1)还是不超过178(0)
样本信息如下:
头发 | 衣服 | 身高 | 性别 |
---|---|---|---|
0 | 0 | 1 | 0 |
1 | 1 | 1 | 1 |
1 | 0 | 1 | 1 |
0 | 1 | 1 | 0 |
2. 简单的单层神经网络
用X表示输入的特征向量,由于每个样本有三个特征,一共有四个样本,所以我们定义一个4X3的矩阵,每一行代表一个样本
1
2
3
4
5
6
7#import numpy
import numpy as np
# input dataset
X = np.array([[0, 0, 1],
[0, 1, 1],
[1, 0, 1],
[1, 1, 1]])- 而四个样本对应输出(分类结果)我们用一个1X4的矩阵表示。
.T
为转置函数,转置后变成了4X1的矩阵。
- 同我们的输入一致,每一行是一个训练实例,而每一列(仅有一列)对应一个输出节点。
1
y = np.array([[0, 0, 1, 1]]).T
- 初始化神经网络的权重
- 由于输入层有三个神经元,而输出结果只有一个神经元,所以权重矩阵为3x1。
- 由于一般初始化权重是随机选择的,因此要为随机数设定产生的种子(如下代码所示)
- 这样可以使每次训练开始时,得到的训练随机数都是一致的。这样便于观察策略变动是如何影响网络训练的,消除初始权重的影响。
1 | np.random.seed(1) |
- 由于我们要将随机初始化的权重矩阵均值设定为0,因此要计算syn0(第一层网络间的权重矩阵)
1 | syn0 = 2*np.random.random((3,1)) - 1 |
- sigmoid函数
- 定义为:
- 特点:其导数可以用其自身表示出来,在计算的时候,我们只需要计算出其函数值,就可以计算出其导数值,从而可以减少浮点运算次数,提高效率
- 导数为:
python中代码实现
1
2
3
4
5# sigmoid function
def nonlin(x,deriv=False):
if(deriv==True):
return x*(1-x)
return 1/(1+np.exp(-x))其中,deriv参数表示是否计算的是其导数值:
3. 开始训练神经网络
- 迭代10000次,每一次迭代可描述如下
- 计算输入层的加权和,即用输入矩阵L0乘以权重矩阵syn0,并通过sigmid函数进行归一化。得到输出结果l1;
- 计算输出结果L1与真实结果y之间的误差L1_error;
- 计算权重矩阵的修正L1_delta,即用误差乘以sigmoid在L处的导数;(阶梯下降法)
- 用L1_delta更新权重矩阵syn0
1
2
3
4
5
6
7
8
9
10
11
12
13
14for iter in range(10000):
# forward propagation
l0 = X
l1 = nonlin(np.dot(l0,syn0))
# how much did we miss?
l1_error = y - l1
# multiply how much we missed by the
# slope of the sigmoid at the values in l1
l1_delta = l1_error * nonlin(l1,True)
# update weights
syn0 += np.dot(l0.T,l1_delta)
4. 一次训练过程的参数更新如下图所示:
批量循环训练
5.结果
1 | Output syn0 After Training: |
- 从syn0迭代后的输出可看出
- yn0的第一个元素,也就是第一个输入特征(长发)的权重最大,而第二个和第三个特征都很小
- 所以神经网络学习的结果是加重第一个特征的权重,而其他两个特征对于是女性这个推测的贡献较小,所以减小其权重。
- 为了验证训练结果,我们加入两组新数据,(短头发,红衣服,矮个子),(长头发,不是红衣服,矮个子),并用神经网络来进行分类:
1 | X_new = np.array([[0,1,0], |
- 计算结果如下:
1
2
3Predicte With syn0:
[[-0.2078435 ]
[ 9.67299303]]