(此笔记是基于《深度学习入门》这本书的重点知识汇总。)
第一周任务主要了解了:
感知机是什么?
多个输入,一个输出。改变权重w可以实现与、与非和或门。(构造相同,只是权重参数不一样)
图1-1 感知机原理(用的激活函数是阶跃函数)
1、用感知机原理实现一个与门
def AND(x1,x2):
x = np.array([0,1])
w = np.array([0.5,0.5])
b = -0.7
tmp = x*w + b
if tmp > 0:
return 1
elif tmp <= 0:
return 0
2、用 -b 代替 θ,用NumPy实现感知机
>>> import numpy as np
>>> x = np.array([0, 1]) # 输入
>>> w = np.array([0.5, 0.5]) # 权重
>>> b = -0.7 # 偏置
>>> w*x
array([ 0. , 0.5])
>>> np.sum(w*x)
0.5
>>> np.sum(w*x) + b
-0.19999999999999996 # 大约为-0.2(由浮点小数造成的运算误差)
单层感知机的缺点:
如何改进:叠加层。
其实异或门可由 与、与非、或门 组合而成。所以异或是多层结构的神经网络(两层)。(一层不行,咱就叠加层)(一顿火锅解决不了,咱就再来一顿!)
而且两层感知机运作过程好比流水线作业,一层层传递
总结:单层感知机(线性)通过叠加层可进行非线性的表示
多层感知机 = 神经网络
感知机与神经网络的区别:激活函数不同!
np.ndim(A) :获取数组的维数,维数由最小的行或者列来确定
A.shape :获取数组的形状(几行几列),返回元组(tuple)
A.shape[0] 代表第一个维度,即行;
A.shape[1] 代表第二个维度,即列
二维数组 = 矩阵
比如:
A = [[1,2],
[3,4],
[5,6]]
行 = 第一个维度(第0维) = A.shape[0] = 有三个元素(有三行)
列 = 第二个维度(第1维) = A.shape[1] = 有两个元素(有两列)
np.dot():矩阵乘法
接收两个NumPy数组作为参数,并返回数组的乘积。
前向传播的实现(即假设已经知道了参数的值,进行分类任务)
= 假设我们已经学习到了参数,进行推理任务,也就是对输入数据进行分类,这就是前向传播的过程。
即 前向传播 = 此处的推理处理
三层前向传播的神经网络的实现
# 三层前向传播的神经网络的实现
import numpy as np
import matplotlib.pylab as plt
def sigmoid(x):
return 1 / (1 + np.exp(-x))
# 初始化神经网络,给w,b具体值,用字典存储起来
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
# 前向传播算法,输入x,w,b;加激活函数sigmoid,输出y
# 将输入信号转化为输出信号的处理过程
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 = a3
return y
# 1、调用init_network()初始化神经网络的w,b;
# 2、给x具体值;
# 3、调用forward前向传播算法,输出y
network = init_network()
x = np.array([1.0,0.5])
y = forward(network,x)
print(y)
[ 0.31682708 0.69627909]
《深度学习入门》:一般而言,回归问题用恒等函数,分类问题用softmax函数。
感知机就是用的阶跃函数去激活的,那么用其他激活函数的就是神经网络了!
1、Python实现阶跃函数
def step_function(x):
if x > 0:
return 1
else:
return 0
2、用NumPy实现阶跃函数(输入为正,输出1;输入为负,输出0)
def step_function(x):
y = x > 0
return y.astype(np.int)
# 把数组y的元素类型从布尔型转换为 int型
# 直接如下也对
def step_function(x):
np.array(x > 0, dtype=np.int)
3、画出阶跃函数
import numpy as np
import matplotlib.pylab as plt
# 阶跃函数的实现
def step_function(x):
return np.array(x > 0, dtype=np.int)
x = np.arange(-5.0,5.0,0.1) # 设置x轴范围、步进,创建创建array数组
y = step_function(x) # 给出x,y的关系
plt.plot(x,y) # 画图函数plot
plt.ylim(-0.1,1.1) # 设定y坐标轴的范围
plt.show() # 显示结果
1、sigmoid函数的实现
# sigmoid函数的实现
def sigmoid(x): # x 可以是NumPy数组
return 1/(1+np.exp(-x))
2、画出sigmoid函数
# 画出sigmoid函数
x = np.arange(-5.0,5.0,0.1)
y =sigmoid(x)
plt.plot(x,y)
plt.ylim(-0.1,1.1)
plt.show()
sigmoid函数的平滑性对神经网络的学习具有重要意义。
1、ReLU函数的实现
def ReLU(x):
return np.maximum(0,x)
2、画出ReLU函数
x = np.arange(-5.0,5.0,0.1)
y =ReLU(x)
plt.plot(x,y)
plt.ylim(-1.0,5.0)
plt.show()
输出层使用的激活函数选择要根据求解问题的性质决定。
回归问题:用恒等函数,直接输出
分类问题:
二元分类问题:用sigmoid函数
多元分类问题:用softmax函数(下节讨论)
softmax函数实现
softmax激活函数实现,一般用于多元分类
def softmax(a): # 传入数组a
exp_a = np.exp(a)
exp_sum = np.sum(exp_a)
y = exp_a / exp_sum
return y
遇到指数函数要当心
防止溢出,加个或减去个C,结果不变
softmax激活函数改善,防止溢出,加个或减去个C
def softmax(a): # 传入数组a
c = np.max(a)
exp_a = np.exp(a - c)
exp_sum = np.sum(exp_a)
y = exp_a / exp_sum
return y
softmax函数的输出值的总和是1,所以可以把softmax函数的输出解释为“概率”。
# function.py
# 一般用于多分类任务的激活函数
def softmax(x):
if x.ndim == 2:
x = x.T
x = x - np.max(x, axis=0) # 列方向
y = np.exp(x) / np.sum(np.exp(x), axis=0)
return y.T
x = x - np.max(x) # 溢出对策
return np.exp(x) / np.sum(np.exp(x))
axis = 1 行方向
axis = 0 列方向
注意:矩阵的第0维是列方向,第1维是行方向。
比如:
参数 axis=1。这指定了在100 × 10的数组中,沿着第1维方向(以第1维为轴)找到值最大的元素的索引(第0维对应第1个维度)
损失函数是表示神经网络性能的“有多坏(恶劣程度)”的指标,即当前的神经网络对监督数据(训练数据)在多大程度上不拟合,在多大程度上不一致。恶劣程度越小,越好。
神经网络以某个指标作为线索寻找最优权重参数,这个指标就是 损失函数(loss function)
损失函数一般用均方误差和交叉熵误差等。
当使用sigmoid作为激活函数的时候,常用交叉熵损失函数而不用均方误差损失函数。
python实现均方误差
def mean_squared_error(y, t):
return 0.5 * np.sum((y-t)**2)
python实现交叉熵误差
def cross_entropy_error(y, t):
delta = 1e-7
return -np.sum(t * np.log(y + delta))
# 可以同时处理单个数据和批量数据(数据作为batch集中输入)两种情况的函数
def cross_entropy_error(y, t):
if y.ndim == 1:
t = t.reshape(1, t.size)
y = y.reshape(1, y.size)
batch_size = y.shape[0]
return -np.sum(t * np.log(y + 1e-7)) / batch_size
def cross_entropy_error(y, t):
if y.ndim == 1:
t = t.reshape(1, t.size)
y = y.reshape(1, y.size)
batch_size = y.shape[0]
return -np.sum(np.log(y[np.arange(batch_size), t] + 1e-7)) / batch_size