文章目录
神经网络(补充)(第五章)
感知机
感知机是神经网络(深度学习)的起源算法,所以我们从感知机起步,进入深度学习的世界。
主要使用的Python库:
-
感知机接收多个输入信号,输出一个信号
-
水流向前流动,向前方输送水
-
电流向前流动,向前方输送电子
-
感知机的信号也会向前流动,向前方输送信息
-
不同的是,感知机的信号只有“流”和“不流”两种情况,如分别用1和0表示
示意图如下:
与门
与门(AND gate)的真值表如下:
x1 | x2 | y |
---|---|---|
0 | 0 | 0 |
1 | 0 | 0 |
0 | 1 | 0 |
1 | 1 | 1 |
思考:如何用感知机实现与门呢?什么样的权重与阈值是合适的呢?
代码实现:
def AND(x1,x2):
w1,w2,theta = 0.5,0.5,0.7
tmp = x1*w1 + x2*w2
if tmp <= theta:
return 0
elif tmp > theta:
return 1
使用numpy:
import numpy as np
def AND(x1,x2):
x = np.array([x1,x2])
w = np.array([0.5,0.5])
b = -0.7
tmp = np.sum(w*x) + b
if tmp <= 0:
return 0
else:
return 1
与非门
与非门(NAND gate)颠倒了与门的输出,起英文NAND就是Not AND 的
其真值表如下所示:
x1 | x2 | y |
---|---|---|
0 | 0 | 1 |
1 | 0 | 1 |
0 | 1 | 1 |
1 | 1 | 0 |
只要把与门的符号取反,即可实现与非门
import numpy as np
def NAND(x1,x2):
x = np.array([x1,x2])
w = np.array([-0.5,-0.5])
b = 0.7
tmp = np.sum(w*x) + b
if tmp <= 0:
return 0
else:
return 1
或门
其真值表如下:
x1 | x2 | y |
---|---|---|
0 | 0 | 0 |
1 | 0 | 1 |
0 | 1 | 1 |
1 | 1 | 1 |
import numpy as np
def OR(x1,x2):
x = np.array([x1,x2])
w = np.array([0.5,0.5])
b = -0.2
tmp = np.sum(w*x) + b
if tmp <= 0:
return 0
else:
return 1
感知机的局限:异或门
到这里,我们已经知道,使用感知机可以实现与门、与非门、或门三中逻辑电路
现在我们来思考一下异或门(XOR gate)
异或门的真值表如下:
x1 | x2 | y |
---|---|---|
0 | 0 | 0 |
1 | 0 | 1 |
0 | 1 | 1 |
1 | 1 | 0 |
下面我们用多层感知机来实现异或门:
总结:先得到与非门和或门,最后用与门即可得到异或门的输出。
异或门代码:(调用上方已有的方法)
def XOR(x1,x2):
s1 = NAND(x1,x2) #与非门
s2 = OR(x1,x2) #或门
y = AND(s1,s2) #与门
return y
好了,感知机已经基本上理解,接下来神经网络开始!
神经网络开始
激活函数引入
阶跃函数
阶跃函数代码实现:
def step_function(x):
if x > 0:
return 1
else:
return 0
修改后的代码:
import numpy as np
def step_function2(x):
y = x > 0
return y.astype(np.int)
调用:
import numpy as np
x = np.array([-1.0,1.0,2.0])
x
array([-1.0,1.0,2.0])
y = x > 0
y
array([False,True,True])
y_int = y.astype(np.int)
y_int
array([0,1,1])
#调用:
step_function2(x)
array([0,1,1])
看一下阶跃函数的图像:
import numpy as np
import matplotlib.pylab as plt
def step_function(x):
y = x > 0
return y.astype(np.int)
x = np.arange(-5.0,5.0,0.1) #x的取值[-5,5),精度0.1,你可以自己查看x是什么
y = step_function(x)
plt.plot(x,y)
plt.ylim(-0.1,1.1) #指定y轴的范围
plt.show()
如果将激活函数从阶跃函数切换成其他函数,就可以进入神经网络的世界了!
sigmoid函数
sigmoid函数的实现:
import numpy as np
def sigmoid(x):
return 1/(1 + np.exp(-x))
测试能不能适用于数组:
import numpy as np
x = np.array([-1.0,1.0,2.0])
print(x)
sigmoid(x)
#输出:
[-1.,1.,2.]
array([0.26894142,0.73105858,0.88079708])
sigmoid函数的图像:
import numpy as np
import matplotlib.pylab as plt
x = np.arange(-5.0,5.0,0.1)
y1 = sigmoid(x)
plt.plot(x,y1)
plt.ylim(-0.1,1.1)
plt.show()
sigmoid函数与阶跃函数的比较
代码示例:
import numpy as np
import matplotlib.pylab as plt
def sigmoid(x):
return 1/(1 + np.exp(-x))
def step_function(x):
return np.array(x > 0,dtype=np.int)
x = np.arange(-5.0,5.0,0.1)
y1 = sigmoid(x)
y2 = step_function(x)
plt.plot(x,y1)
plt.plot(x,y2,'k--')
plt.ylim(-0.1,1.1)
plt.show()
Relu函数
relu函数的实现:
def relu(x):
return np.maximum(0,x)
relu函数的图像:
x = np.arange(-5.0,5.0,0.1)
y = relu(x)
plt.plot(x,y)
plt.ylim(-1,6)
plt.show()
三层神经网络的实现
从第0层到第1层:(即输入层到第一层)
使用numpy多维数组来实现:
import numpy as np
#定义X,W1,B1
X = np.array([1.0,0.5])
W1 = np.array([[0.1,0.3,0.5],[0.2,0.4,0.6]])
B1 = np.array([0.1,0.2,0.3])
#查看X,W1,B1的形状
print(X.shape)
print(W1.shape)
print(B1.shape)
#输出:
(2,)
(2,3)
(3,)
#线性代数,矩阵相乘
np.dot(X,W1)
#输出:
array([0.2,0.5,0.8])
A1 = np.dot(X,W1) + B1
A1
#输出:
array([0.3,0.7,1.1])
def sigmoid(x):
return 1/(1 + np.exp(-x))
Z1 = sigmoid(A1)
Z1
array([0.57444252,0.66818777,0.75026011])
位置如下图红坨坨圈起来的部分:
从第1层到第2层:
#定义W2,B2
W2 = np.array([[0.1,0.4],[0.2,0.5],[0.3,0.6]])
B2 = np.array([0.1,0.2])
#查看W2,B2的形状
print(X.shape)
print(W1.shape)
print(B1.shape)
A2 = np.dot(Z1,W2) + B2
Z2 = sigmoid(A2)
Z2
#输出:
(3,2)
(2,)
array([0.62624937,0.7710107])
从第2层到第3层:(即第2层到输出层的信号传递)
与之前类似,只不过激活函数有所不同
#定义恒等函数
def identity_function(x):
return x
#定义W3,B3
W3 = np.array([[0.1,0.3],[0.2,0.4]])
B3 = np.array([0.1,0.2])
A3 = np.dot(Z2,W3) + B3
Y = identity_function(A3)
Y
#输出:
array([0.31682708,69627909])
代码总结
输出层的激活函数softmax
代码实现:
import numpy as np
#softmax函数的代码实现
a = np.array([0.3,2.9,4.0])
exp_a = np.exp(a) #指数函数
print(exp_a)
[1.34985881,18.17414537,54.59815003]
sum_exp_a = np.sum(exp_a)
print(sum_exp_a)
[74.1221542101633]
y = exp_a/sum_exp_a
y
array([0.01821127,0.24519181,0.73659691])
将softmaxt整合成一个函数:
def softmax(a):
exp_a = np.exp(a)
sum_exp_a = np.sum(exp_a)
y = exp_a/sum_exp_a
return y
图片来自另一个博客:https://blog.csdn.net/weixin_44478378/article/details/100569046
重新定义一下函数:
def softmax(a):
c = np.max(a) #取出输入信号的最大值
exp_a = np.exp(a - c) #减去这个常数
sum_exp_a = np.sum(exp_a)
y = exp_a/sum_exp_a
return y
比较一下二分类与多分类:
def sigmoid(x):
return 1/(1 + np.exp(-x))
#二分类
import numpy as np
import matplotlib.pylab as plt
x = np.arange(10)
e = softmax(x)
f = x/np.sum(x)
plt.plot(x,e,color='red',marker='o',linestyle='solid')
plt.plot(x,f,color='blue',marker='o',linestyle='solid')
plt.show()
def softmax(a):
c = np.max(a) #取出输入信号的最大值
exp_a = np.exp(a - c) #减去这个常数
sum_exp_a = np.sum(exp_a)
y = exp_a/sum_exp_a
return y
#多分类
import numpy as np
import matplotlib.pylab as plt
x = np.array([1,2])
y = sigmoid(x)
plt.plot(x,y,color='red',marker='o',linestyle='solid')
plt.plot(x,x,color='blue',marker='o',linestyle='solid')
plt.show()
ok,到这里先结束一下吧,这里补充的比较基础,是看的b站一学习大佬的深度学习入门视频做的学习笔记,视频链接如下,感谢大佬的讲解:
https://www.bilibili.com/video/BV12t411N748