(如有侵权,联系作者,马上删除)
一.前情提要
1.本文旨在初步了解神经网络的代码运作模式,能够理解代码即可。
2.本文与卷积神经网络无关,只是初步涉及神经网络。
3.本文代码与笔记交互,对代码有详细注释。
4.本文代码拾人牙慧,参考来自
大话神经网络,10行代码不调包,听不懂你打我!_哔哩哔哩_bilibili
理论学习可阅读
五分钟秒懂神经网络原理,机器学习入门教程_哔哩哔哩_bilibili
(注:上述文章都是快速上手,详细学习建议看作者另一篇CNN的博客推荐的博主)
二.代码
①神将网络初步学习
import numpy as np
X = np.array([[0, 0, 1], [1, 1, 1], [1, 0, 1], [1, 1, 0]])#二维数组
y = np.array([[0, 1, 1, 0]]).T#一维数组#.T是numpy中的转置操作符,用于将矩阵或数组进行转置操作。
#在这个例子中,.T被用于将y数组进行转置,即将行向量转换为列向量。原数组y为一行包含4个元素的数组,经过.T操作后,变为一列包含4个元素的数组
#数据一一对应,比如:0,0,1对应0,1,1,1对应1,如下
# [0,0,1] 0
# [1,1,1] 1
# [1,0,1] 1
# [1,1,0] 0
#设置随机权重
np.random.seed(1)
#np.random.seed(1)的作用是设置随机数种子,以确保每次运行代码时生成的随机数序列是一样的。这样可以使得实验结果具有可重复性
#当我们使用相同的种子时,可以确保每次生成的随机数序列是一样的,但是,如果我们将种子更改为不同的整数,将会生成不同的随机数序列
weights = 2 * np.random.random((3, 1)) - 1#在大小为(3, 1)的随机矩阵中,3代表着输入特征的数量,而1代表着输出节点(或神经元)的数量
#np.random.random()函数生成的随机数是在[0, 1)之间均匀分布的,这是因为该函数使用了在区间[0, 1)上均匀分布的伪随机数生成器
#在这里,权重是一个3行1列的矩阵,每个元素都是在(-1, 1)范围内均匀分布的随机数
for i in range(10000):#循环10000次
output = 1 / (1 + np.exp(-np.dot(X, weights)))
#使用了Sigmoid函数来保障我们要求的概率为0到1之间
# 在NumPy中,dot函数用于计算数组的点积。对于一维数组,它计算的是这两个数组的内积;对于二维数组,它计算的是矩阵乘法
# dot实例
# import numpy as np
# 一维数组的点积(内积)
# a = np.array([1, 2, 3])
# b = np.array([4, 5, 6])
# result = np.dot(a, b)
# print(result) # 输出 32,即 1*4 + 2*5 + 3*6
# 二维数组的矩阵乘法
# matrix1 = np.array([[1, 2], [3, 4]])
# matrix2 = np.array([[5, 6], [7, 8]])
# result = np.dot(matrix1, matrix2)
# print(result) # 输出 [[19 22]
# [43 50]]
# exp是一个数学函数,用于计算给定数组中元素的指数函数值。具体来说,它返回一个新的数组,其中每个元素的值等于e(自然对数的底数)的指数次幂。
# 例如,如果有一个数组 arr = np.array([1, 2, 3]),调用 np.exp(arr) 将返回一个新的数组,其中每个元素的值分别为 e 的 1、e 的 2 和 e 的 3 次幂
#结果
# X weight output
# X11 X12 X13 w1 o1
# X21 X22 X23 w2 o2
# X31 X32 X33 w3 o3
# X41 X42 X43
#eg: o1=X11*w1+X12*w2+X13*w3
#判断计算的和实际的误差
error = y - output
#计算增量
delta = error * output * (1 - output)
#更新权重
weights += np.dot(X.T, delta)
print(weights)
print(1 / (1 + np.exp(-np.dot(np.array([1, 0, 0]), weights))))
②神将网络初步学习部分优化
from numpy import random,dot,exp,array
def fp(input):#正向传播
z=dot(input,weights)
return 1/(1+exp(-z))
def bp(y,output):#反向传播
error = y - output
slope=output*(1-output)
return error * slope
X = array([[0, 0, 1], [0, 1, 1], [1, 0, 1], [1, 1, 1]])#二维数组
y = array([[0, 1, 1, 0]]).T
random.seed(1)
weights = 2 *random.random((3, 1)) - 1
for i in range(10000):
output=fp(X)
delta=bp(y,output)
weights += dot(X.T, delta)
print(fp([0,1,0]))#输入矩阵[1,1,0]
#此时结果较为复杂,一个神经元无法解决问题所以结果恒为0.5
③神经网络多个神经元学习
from numpy import random,dot,exp,array
def fp(input):
l1=1/(1+exp(-dot(input,w0)))
l2=1/(1+exp(-dot(l1,w1)))
return l1,l2
def bp(l1,l2,y):
error = y - l2
slope=l2*(1-l2)
l1_delta =error*slope
l0_slope = l1 * (1 - l1)
l0_error=l1_delta.dot(w1.T)
l0_delta=l0_slope*l0_error
return l0_delta,l1_delta
X = array([[0, 0, 1], [0, 1, 1], [1, 0, 1], [1, 1, 1]])
y = array([[0, 1, 1, 0]]).T
random.seed(1)
#初始化权重
w0=2 *random.random((3, 4)) - 1
w1=2 *random.random((4, 1)) - 1
for i in range(3):
l0=X
l1,l2=fp(l0)
l0_delta,l1_delta=bp(l1,l2,y)
w1+=w1+dot(l1.T,l1_delta)
w0+=w0+dot(l0.T,l0_delta)
print(fp([[0,1,0]])[1])
#定义激活函数:代码中使用了sigmoid函数作为激活函数,可以将输入的值转换成0到1之间的概率值。
#前向传播函数 fp(input):该函数接收一个输入向量,并通过两层权重矩阵的乘积和激活函数,计算出两层的输出结果 l1 和 l2。
#反向传播函数 bp(l1, l2, y):该函数接收前向传播函数的输出结果 l1、l2 和目标输出 y,根据误差和梯度计算出每一层的误差项。
#定义输入数据和目标输出数据:X 是一个 4x3 的矩阵,表示输入数据的特征,y 是一个 4x1 的矩阵,表示输入数据对应的目标输出。
#初始化权重:w0 和 w1 是两个随机初始化的权重矩阵,用于连接输入层和隐藏层以及隐藏层和输出层。
#迭代训练:通过循环迭代,进行网络的训练和权重的更新。在每一次迭代中,先进行前向传播,然后根据前向传播的结果和目标输出计算反向传播的误差项,最后根据误差项和学习率更新权重。