在AI的学习过程中主要有理论课的知识讲解和实验课的实验过程,这里主要就分享我写的实验报告吧
1.实验问题:对感知机和BPNN算法的应用。
- 感知机:感知机是二分类的线性分类器,其输入为实例的特征向量,输出为实例的类别,取+1和-1二值。感知机将特征空间中的实例划分为正负两类,属于判别模型。
- 反向传播神经网络(BPNN):
- BPNN被认为是最常用的预测方法,它由输入层、隐层和输出层三层组成,其中隐层在输入层和输出层之间传递着重要的信息。
- BPNN总是由一个或多个隐藏层组成,从而允许网络对复杂功能进行建模。它主要由两个过程组成:正向信息传播和误差反向传播。
2.模型构建:
- 感知机:
x | y | XOR(x,y) |
---|---|---|
0 | 0 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 0 |
x | y | TOR(x,y) |
---|---|---|
0 | 0 | 1 |
0 | 1 | 0 |
1 | 0 | 0 |
1 | 1 | 1 |
注:TOR表示同或
同理,所有的逻辑运算都可以列出真值表,再根据真值表来设计算法
为了解决异或问题,我们通常会准备两个感知机,如下图:
- 反向传播神经网络(BPNN):
由输出层反推隐藏层
z
(
l
)
=
w
(
l
)
a
(
l
−
1
)
+
b
(
l
)
a
(
l
)
=
f
(
z
(
l
)
)
=
f
(
w
(
l
)
a
(
l
−
1
)
+
b
(
l
)
)
J
(
w
,
b
;
x
,
y
)
=
1
2
(
a
(
L
)
−
y
)
2
定
义
残
差
:
δ
i
(
l
)
=
J
(
w
,
b
;
x
,
y
)
∂
z
i
(
l
)
输
出
层
:
δ
(
l
)
=
(
a
(
L
)
−
y
)
⋅
f
′
(
z
i
(
l
)
)
其
他
层
:
δ
(
l
)
=
(
(
w
(
l
+
1
)
)
T
δ
(
l
+
1
)
)
⋅
f
′
(
z
i
(
l
)
)
梯
度
:
∂
J
(
w
,
b
;
x
,
y
)
∂
w
(
i
j
)
(
l
)
\begin{aligned} &z^{(l)} = w^{(l)}a^{(l-1)}+b^{(l)} \\ &a^{(l)} = f(z^{(l)}) = f(w^{(l)}a^{(l-1)}+b^{(l)}) \\ &J(w,b;x,y) = \frac{1}{2}(a^{(L)-y})^2 \\ &定义残差:\delta^{(l)}_i = \frac{J(w,b;x,y)}{\partial z^{(l)}_i } \\ &输出层: \delta^{(l)} = (a^{(L)-y})·f'(z^{(l)}_i) \\ &其他层: \delta^{(l)} =((w^{(l+1)})^T\delta^{(l+1)})·f'(z^{(l)}_i) \\ &梯度: \frac{\partial J(w,b;x,y)}{\partial w^{(l)}_{(ij)}} \end{aligned}
z(l)=w(l)a(l−1)+b(l)a(l)=f(z(l))=f(w(l)a(l−1)+b(l))J(w,b;x,y)=21(a(L)−y)2定义残差:δi(l)=∂zi(l)J(w,b;x,y)输出层:δ(l)=(a(L)−y)⋅f′(zi(l))其他层:δ(l)=((w(l+1))Tδ(l+1))⋅f′(zi(l))梯度:∂w(ij)(l)∂J(w,b;x,y)
3.实验过程:
感知机:
-
首先设置一个激活函数step,由于sign函数的值域为[-1,1],所以我们将其值域+1之后再/2,这样我们得到的激活函数step的值域就变成了[0,1]
-
接着设置逻辑算法,由真值表可知,只有当两个值不相同的时候,结果才为1,所以我们设计的算法是,用两个函数来保证,当x,y不同时,能生成两个为1结果,当x,y相同时生成两个为0的结果,再用与函数将其输出,得到的就是我们想要的答案
-
最后给输入x,y赋值,验证我们的算法
同理,我们可以根据此方法设计出同或等其他一般的逻辑运算
BPNN:
-
首先设置神经网络的基本属性:输入、输出、权值
-
然后设置传播函数
-
接着设置迭代次数和学习算法
-
最后输出结果并进行可视化
4.实验结果:
感知机:
- 异或问题:
- 同或问题:
- 一般逻辑问题: 例如:(a||b)&&c
BPNN:
- 解决一般的逻辑问题: 例如:(a||b)&&c
- 一层隐藏层的神经网络拟合sinx函数
- 两层隐藏层的神经网络拟合sinx函数
5.结果分析:
-
在感知机实验中,我们通过使用算法解决了基本的逻辑问题,作为最简单的分类模型算法之一,理论上我们可以用多个感知机去进行更加复杂的分类或者解决更加复杂的难题,甚至可以由此引申到神经网络中去,也就是说,感知机其实就是一个简单的神经网络模型,可以看作是由两层神经元组成的神经网络。
-
在反向传播神经网络实验中,通过简单的训练我们实现了基本逻辑语言的预测,同时也成功地拟合出了sinx函数,在实验的学习过程中,我们知道影响神经网络预测结果的主要有这么几个因素:
- 神经网络的层数; - 神经网络隐藏层的节点数; - 训练的学习率; - 训练的迭代次数。
-
在最开始的实验时,我们的神经网络只是最简单的三层神经网络,由一层输入层、一层隐藏层、一层输出层构成,在简单的神经网络下,我对节点数、学习率、迭代次数进行了多次调整,最久的一次,我将学习率调制0.001,迭代次数10000次,但是最终拟合的结果依然特别糟糕,最后还是在增加了一层隐藏层之后,才能够较好地拟合出sinx函数。
6.代码补充:
感知机:
# 感知机解决异或问题
import numpy as np
def step(x):
return (np.sign(x)+1)/2
def f1(x,y):
return step(x+y-0.5)
def f2(x,y):
return step(-x-y+1.5)
def xor(x,y):
return step(f1(x,y)+f2(x,y)-1.5)
x = np.array([0,0,1,1])
y = np.array([0,1,0,1])
z = xor(x,y)
for i in range(len(x)):
print("xor(%d,%d)=%d" % (x[i],y[i],z[i]))
# 感知机解决同或问题
import numpy as np
def step(x):
return (np.sign(x)+1)/2
def f1(x,y):
return step(x+y-0.5)
def f2(x,y):
return step(-x-y+1.5)
def Tor(x,y):
return step(-f1(x,y)-f2(x,y)+1.5)
x = np.array([0,0,1,1])
y = np.array([0,1,0,1])
z = Tor(x,y)
for i in range(len(x)):
print("Tor(%d,%d)=%d" % (x[i],y[i],z[i]))
# 感知机解决普遍逻辑问题
import numpy as np
def step(x):
return (np.sign(x)+1)/2
def f1(x,y):
return step(x+y-0.5)
def f2(x,y,c):
return step(f1(x,y)+c-1.5)
x = np.array([0,0,0,0,1,1,1,1])
y = np.array([0,1,0,1,0,1,0,1])
c = np.array([0,0,1,1,0,0,1,1])
z = f2(x,y,c)
for i in range(len(x)):
print("(a||b)&&c(%d,%d,%d)=%d" % (x[i],y[i],c[i],z[i]))
BPNN(反向传播神经网络):
# BPNN算法
import matplotlib.pyplot as plt
import numpy as np
def act(x, deriv=False):
if(deriv==True):
return x*(1-x) # x is activated a(z)
return 1/(1+np.exp(-x))
NH = 10
# 拟合sinx函数
x = np.array([np.linspace(0,3.14,20)]).T
y = np.sin(x)
# 逻辑语言运算 (a||b)&&c
#x = np.array([[0,0,0],[0,0,1],[0,1,0],[0,1,1],[1,0,0],[1,1,0],[1,0,1],[1,1,1]])
#y = np.array([[0],[0],[0],[1],[0],[0],[1],[1]])
w1 = 2*np.random.random((1,NH))-1
w2 = 2*np.random.random((NH,10))-1
w3 = 2*np.random.random((10,1))-1
def feedfoward(x):
a0 = x;
a1 = act(np.dot(a0,w1))
a2 = act(np.dot(a1,w2))
a3 = act(np.dot(a2,w3))
return (a0,a1,a2,a3)
n_epochs = 1000000
for i in range (n_epochs):
a0,a1,a2,a3 = feedfoward(x)
l3_delta = (a3-y)*act(a3, deriv=True)
l2_delta = l3_delta.dot(w3.T) * act(a2,deriv=True)
l1_delta = l2_delta.dot(w2.T) * act(a1,deriv=True)
w3 = w3-a2.T.dot(l3_delta) * 0.1
w2 = w2-a1.T.dot(l2_delta) * 0.1
w1 = w1-a0.T.dot(l1_delta) * 0.1
if(i % 10000) == 0:
loss = np.mean(np.abs(y-a3))
print("epochs %d/%d loss = %f" % (i/1e4+1, n_epochs/ 1e4, loss))
a0,a1,a2,a3 = feedfoward(x)
print ("sinx (",x,") = ",a3)
plt.plot(x,y,'r*-')
plt.plot(x,a3,'b-')
plt.show()