深度学习入门(一):神经网络(阶跃函数,sigmoid,ReLU,softmax,激活函数)

从感知机到神经网络

感知机

感知机接受多个输入信号,输出一个信号。这里说的信号可以想象成电流或河流具备“流动性”的东西。但是,和实际的电流不同的是,感知机的信号只有“流/不流”(1/0)两种取值。

深度学习入门(一):神经网络(阶跃函数,sigmoid,ReLU,softmax,激活函数)_第1张图片
如图:是一个接受两个输入信号的感知机。x1、x2是输入信号,y是输出信号,w1,w2是权重。 θ \theta θ被称为阈值。b是被称为偏置的参数,用于控制各个信号的重要性。
y = { 0 , b + w 1 x 1 + w 2 x 2 ≤ θ 1 , b + w 1 x 1 + w 2 x 2 > θ y = \begin{cases} 0, & \text {$b+w_1x_1 + w_2x_2\leq\theta$} \\ 1, & \text {$b+w_1x_1 + w_2x_2>\theta$} \end{cases} y={ 0,1,b+w1x1+w2x2θb+w1x1+w2x2>θ
深度学习入门(一):神经网络(阶跃函数,sigmoid,ReLU,softmax,激活函数)_第2张图片

y = h ( b + w 1 x 1 + w 2 x 2 ) y = h(b+w_1x_1+w_2x_2) y=h(b+w1x1+w2x2)
h ( x ) = { 0 , x ≤ 0 1 , x > 0 h(x) = \begin{cases} 0, & \text {$x\leq0$} \\ 1, & \text {$x>0$} \end{cases} h(x)={ 0,1,x0x>0

激活函数

上面介绍的h(x)将输入信号的总和转换为输出信号,这种函数一般被称为激活函数。上面表示的激活函数以阈值为界,一旦输入超过阈值,就切换输出。这样的函数被称为“阶跃函数”。

sigmoid函数

h ( x ) = 1 1 + e x p ( − x ) h(x)=\frac{1}{1+exp(-x)} h(x)=1+exp(x)1

阶跃函数的实现

def step_function(x):
	if x > 0:
		return 1;
	else:
		return 0;

上述代码参数x只能接受实数,不能接受numpy数组

def step_function(x):
	y = x > 0
	return y.astype(np.int)

对numpy数组进行不等号运算后,会生成一个布尔型数组。然后通过np.int将布尔型转换为int型

阶跃函数的图形

import numpy as np
import matplotlib.pylab as plt

def step_function(x):
    return np.array(x > 0, dtype=int)

x = np.arange(-5.0, 5.0, 0.1)
y = step_function(x)
plt.plot(x, y)
plt.ylim(-0.1,1.1) # 指定y轴的范围
plt.show()

深度学习入门(一):神经网络(阶跃函数,sigmoid,ReLU,softmax,激活函数)_第3张图片

sigmoid函数的实现

def sigmoid(x):
	return 1 / (1 + np.exp(-x))
x = np.arange(-5.0, 5.0, 0.1)
y = sigmoid(x)
plt.plot(x, y)
plt.ylim(-0.1,1.1) # 指定y轴的范围
plt.show()

深度学习入门(一):神经网络(阶跃函数,sigmoid,ReLU,softmax,激活函数)_第4张图片

sigmoid 函数和阶跃函数的比较

不同点:

  • “平滑性”的不同。sigmoid函数的输出随着输入发生连续性的变化。而阶跃函数以0为界发生急剧性的变化。
  • 相对于阶跃函数只能返回0或1,sigmoid 函数可以返回实数。

相同点:

  • 如果从宏观角度上观察,它们具有相同的形状。当输入信号是重要信息时,这两种函数都会输出较大的值;当输入信号为不重要的值的信息时,两者都输出较小的值。
  • 不管输入信号有多小,或者有多大,输出信号的值都在0到1之间。
  • 都属于非线性函数

非线性函数

神经网络的激活函数必须使用非线性函数。
线性函数的问题在于,不管如何加深层数,总是存在与之等效的“无隐藏层的神经网络”。
更直观,我们将 h ( x ) = c x h(x) = cx h(x)=cx 作为激活函数,把 y = h ( h ( h ( x ) ) ) y=h(h(h(x))) y=h(h(h(x)))的运算对应3层神经网络,但是同样的处理可以由 y = a x y=ax y=ax 注意 a = c 3 a = c^3 a=c3这一次乘法运算来表示。因此为了发挥叠加层所带来的优势,激活函数必须使用非线性函数。

ReLU函数

ReLU函数在输入大于0时,直接输出该值,在输入小于等于0时,输出0
h ( x ) = { 0 , x ≤ 0 x , x > 0 h(x) = \begin{cases} 0, & \text {$x\leq0$} \\ x, & \text {$x>0$} \end{cases} h(x)={ 0,x,x0x>0

def relu(x):
    return np.maximum(0, x)

numpy的maximum函数。maximum函数会从输入的数值中选择较大的那个值进行输出。
深度学习入门(一):神经网络(阶跃函数,sigmoid,ReLU,softmax,激活函数)_第5张图片

三层神经网络的实现

深度学习入门(一):神经网络(阶跃函数,sigmoid,ReLU,softmax,激活函数)_第6张图片
输入层到第1层的信号传递

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])

print(W1.shape) # (2, 3)
print(B1.shape) # (3, )
print(X.shape)  # (2,)

A1 = np.dot(X, W1) + B1
Z1 = sigmoid(A1)

print(A1) # [0.3, 0.7, 1.1]
print(Z1) # [0.57444252 0.66818777 0.75026011]

从第1层到第2层的信号传递

W2 = np.array([[0.1, 0.4],[0.2, 0.5],[0.3, 0.6]])
B2 = np.array([0.1, 0.2])

print(W2.shape) # (3, 2)
print(B2.shape) # (2,)
print(Z1.shape) # (3,)

A2 = np.dot(Z1, W2) + B2
Z2 = sigmoid(A2)

从第2层到输出层的信号传递

def identity_function(x):
    return x

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)

identity_function()函数(也称为“恒等函数”)。并将其作为输出层的激活函数。输出层使用的激活函数,要根据求解问题的性质决定。一般地,回归问题可以使用恒等函数,二分类问题可以使用sigmoid函数,多元分类问题可以使用softmax函数。
代码小结:

def init_network():
    network = {
     }
    network['w1'] = np.array([[0.1, 0.3, 0.5], [0.2, 0.4, 0.6]])
    network['b1'] = np.array([0.1, 0.2, 0.3])
    network['w2'] = np.array([[0.1, 0.4],[0.2, 0.5],[0.3, 0.6]])
    network['b2'] = np.array([0.1, 0.2])
    network['w3'] = np.array([[0.1, 0.3], [0.2, 0.4]])
    network['b3'] = np.array([0.1, 0.2])
    return network

def forward(network, x):
    w1, w2, w3 = network['w1'],network['w2'],network['w3']
    b1, b2, b3 = network['b1'],network['b2'],network['b3']

    a1 = np.dot(x, w1) + b1
    z1 = sigmoid(a1)
    a2 = np.dot(z1, w2) + b2
    z2 = sigmoid(a2)
    a3 = np.dot(z2, w3) + b3
    y = identity_function(a3)

    return y
network = init_network()
x = np.array([1.0, 0.5])
y = forward(network, x)
print(y) #[0.31682708 0.69627909]

这里出现了forward(前向)一词,它表示从输入到输出方向的传递处理。

输出层的设计

回归问题可以使用恒等函数,二分类问题可以使用sigmoid函数,多元分类问题可以使用softmax函数

恒等函数和softmax函数

恒等函数会将输入按原样输出,对于输入的信息,不加以任何改动地直接输出。
softmax函数可以用
y k = e x p ( a k ) ∑ i = 1 n e x p ( a i ) y_k = \frac{exp(a_k)}{\sum^{n}_{i=1}exp(a_i)} yk=i=1nexp(ai)exp(ak)
输出层的各个神经元都受到所有输入信号的影响。

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
print(y) # [0.01821127 0.24519181 0.73659691]
def softmax(a):
	exp_a = np.exp(a)
	sum_exp_a = np.sum(exp_a)
	y = exp_a / sum_exp_a
	
	return y

实现softmax函数时的注意事项

由于在softmax函数中涉及到指数运算,所以容易出现溢出的问题。
所以,我们将softmax的实现进行改进
深度学习入门(一):神经网络(阶跃函数,sigmoid,ReLU,softmax,激活函数)_第7张图片

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

通过减去输入信号中的最大值,来使得指数运算不会溢出。

softmax函数的特征

  • softmax函数的输出是0.0到1.0之间的实数。
  • softmax函数的输出值的总和为1。

由于此函数的输出值的总和为1,故我们可以把输出值看出概率。

输出层的神经元数量

输出层的神经元数量需要根据待解决的问题来决定。对于分类问题,输出层的神经元数量一般设定为类别的数量。

说明

此为本人学习《深度学习入门》的学习笔记,详情请阅读原书

你可能感兴趣的:(深度学习,神经网络,python,深度学习,算法)