赞
踩
目录
"神经网络是由具有适应性的简单单元组成的广泛并行互连的网络,它的组织能够模拟生物神经系统对真实世界物体所作出的交互反应”
神经网络是一个很大的学科领域,本课程仅讨论神经网络与机器学习的交集,即“神经网络学习”亦称“连接主义(connectionism)”学习
M-P神经神经元模型:(如下图所示)
神经元会接收外界的n个输入信号,这些输入会与权重相结合,再通过“激活函数”对信号进行一定的修改,以得到我们自己想要的数据
权重:决定模型如何根据输入数据产生输出,可通过优化算法进行调整,最小化模型预测与实际结果之间的差异。
作用:
- 提高模型性能
- 加速训练过程
- 改善泛化能力
- 避免过拟合
理想激活函数:阶跃函数,0表示抑制神经元而1表示激活神经元
阶跃函数具有不连续、不光滑等不好的性质,常用的是 Sigmoid函数
(a)函数是理想情况,对于小于0的信号直接过滤掉,(b)函数则是对小于0的信号进行过滤,而在0的信号,则为一定的值。
把许多个这样的神经元按一定的层次结构连接起来,就得到了神经网络.、
感知机:由两层神经元组成,如图5.2所示,输入层接收外界输入信号后传递给输出层,输出层是M-P神经元,亦称“阈值逻辑单元”.
更一般地,给定训练数据集,权重(i= 1,2,...,n)以及阈值可通过学习得到.
感知机的学习:
,
是学习率,若感知机对训练样例(x, y)预测正确,即,则感知机不发生变化,否则将根据错误的程度进行权重调整.
感知机只有输出层神经元进行激活函数处理,即只拥有一层功能神经元,其学习能力非常有限,只能处理线性问题,对于非线性问题,学习过程会发生振荡,w难以稳定下来,求不出解
要解决非线性可分问题,需使用多层功能神经元.
多层神经元:简单的两层感知机,输出层与输入层之间的一层神经元,被称为隐层或隐含层(hidden layer),隐含层和输出层神经元都是拥有激活函数的功能神经元.
多层前馈神经网络:常见的神经网络是形如图5.2.2所示的层级结构,每层神经元与下一层神经元全互连,神经元之间不存在同层连接,也不存在跨层连接.这样的神经网络结构通常称为“多层前馈神经网络”
多层前馈网络有强大的表示能力(“万有逼近性”)
仅需一个包含足够多神经元的隐层,多层前馈神经网络就能以任意精度逼近任意复杂度的连续函数
误差逆传播算法(BP算法):迄今最成功、最常用的神经网络算法,可用于多种任务(不仅限于分类)
给定训练集
输入:d维特征向量输出:l个输出值
隐层:假定使用q个隐层神经元
假定功能单元均使用Sigmoid函数
对于训练例,假定网络的实际输出为
则网络在上的均方误差为:
需通过学习确定的参数数目:(d+l+ 1)q+l
BP是一个迭代学习算法,在迭代的每一轮中采用广义感知机学习规则:
BP算法基于梯度下降策略,以目标的负梯度方向对参数进行调整,以为例,对误差给定学习率,有:
注意到先影响到,再影响到,然后才影响到.,有:
根据的定义,显然有
Sigmoid函数有一个很好的性质:
f' (x)= f(x)(1 - f (x)) ,
于是有
类似地,有:
其中:
学习率不能太大,也不能太小。
推导出基于累积误差最小化的更新规则,就得到了累积误差逆传播算法.
所以只需一个包含足够多神经元的隐层,多层前馈网络就能以任意精度逼近任意复杂度的连续函数.然而,如何设置隐层神经元的个数仍是个未决问题,实际应用中通常靠“试错法”(trial-by-error)调整.
正是由于其强大的表示能力,BP神经网络经常遭遇过拟合,其训练误差持续降低,但测试误差却可能上升.
缓解过拟合:
“早停”:
正则化:
神经网络的训练过程可看作一个参数寻优过程,即在参数空间中,寻找一组最优参数使得E最小.
“最优”:
对w*和*,若存在 >0使得
局部极小解: 都有成立
全局最小解: 若对参数空间中的任意(w;)都有
参数寻优方法:基于梯度的搜索
- 从某些初始解出发,迭代寻找最优参数值.每次迭代中,我们先计算误差函数在当前点的梯度,然后根据梯度确定搜索方向.
- 例如,由于负梯度方向是函数值下降最快的方向,因此梯度下降法就是沿着负梯度方向搜索最优解.若误差函数在当前点的梯度为零,则已达到局部极小,更新量将为零,这意味着参数的迭代更新将在此停止.
- 然而,如果误差函数具有多个局部极小,则不能保证找到的解是全局最小.
可以采取以下策略解决只能找到一个“局部极小”的问题:
- 以多组不同参数值初始化多个神经网络,按标准方法训练后,取其中误差最小的解作为最终参数.这相当于从多个不同的初始点开始搜索,这样就可能陷入不同的局部极小,从中进行选择有可能获得更接近全局最小的结果.
- 使用“模拟退火”(simulated annealing)技术[Aarts and Korst,1989].模拟退火在每一步都以一定的概率接受比当前解更差的结果,从而有助于“跳出”局部极小.在每步迭代过程中,接受“次优解”的概率要随着时间的推移而逐渐降低,从而保证算法稳定.
- 使用随机梯度下降.与标准梯度下降法精确计算梯度不同,随机梯度下降法在计算梯度时加入了随机因素.于是,即便陷入局部极小点,它计算出的梯度仍可能不为零,这样就有机会跳出局部极小继续搜索.
- RBF网络
- ART网络
- SOM网络
- 级联相关网络
- Elman网络
- Boltzmann机
复杂模型的训练效率低,易陷入过拟合,因此难以受到人们青睐.而“深度学习”是一种优秀的复杂模型
深度学习模型:深层的神经网络
通过增加隐层数量来提升模型性能,但BP算法不适用于此,不能够“收敛”
无监督逐层训练:多隐层网络训练的有效手段,
基本思想:“预训练+微调”
每次训练一层隐结点,训练时将上一层隐结点的输出作为输入,而本层隐结点的输出作为下一层隐结点的输入,这称为“预训练”(pre-training);在预训练全部完成后,再对整个网络进行“微调”(fine-tuning)训练.各层预训练完成后,再利用BP算法等对整个网络进行训练.
将大量参数分组,对每组先找到局部看来比较好的设置,然后再基于这些局部较优的结果联合起来进行全局寻优.这样就在利用了模型大量参数所提供的自由度的同时,有效地节省了训练开销.
“权共享”(weight sharing):让一组神经元使用相同的连接权,另一种节省训练开销的策略
无论是DBN还是CNN,都是通过多层处理,逐渐将初始的“低层”特征表示转化为“高层”特征表示后,用“简单模型”即可完成复杂的分类等学习任务.由此可将深度学习理解为进行“特征学习”(feature learning)或“表示学习”(representation learning).
“特征工程”:描述样本的特征由人类专家来设计
利用Python实现感知机算法的原始形式。
- import numpy as np
- import matplotlib.pyplot as plt
-
- def perception(data,label,n,inter):
- raw,col = np.shape(data)
- w = np.random.randn(1,col)
- b = np.random.randn(1)
- x1 = -1
- y1 = (-1/w[:,1])*(np.dot(w[:,0],x1)+b)
- x2 = 2
- y2 = (-1/w[:,1])*(np.dot(w[:,0],x2)+b)
- plt.plot([x1,x2],[y1,y2],color='red')
- plt.scatter(data[1:15,0],data[1:15,1],color='blue',marker='x')
- plt.scatter(data[16:,0],data[16:,1],color='red',marker='o')
- plt.show()
- for times in range(inter):
- for i in range(raw):
- if -label[i-1]*(np.dot(w,(data[:][i-1]))+b) < 0:
- w -= n*label[i-1]*data[:][i-1]
- b -= n*label[i-1]
- elif -label[i-1]*(np.dot(w,(data[:][i-1]))+b) == 0:
- break
- return w,b
-
- if __name__ == '__main__':
- data = np.array([
- [-0.6508, 0.1097],[-1.4492, 0.8896],[2.0850, 0.6876],[0.2626, 1.1476],[0.6418, 1.0234],[0.2569, 0.6730],[1.1155, 0.6043],[0.0914, 0.3399],[0.0121, 0.5256],[-0.0429, 0.4660],[0.4340, 0.6870],[0.2735, 1.0287],[0.4839, 0.4851],[0.4089, -0.1267],[1.4391, 0.1614],[2.9115, 2.1973],[2.3654, 2.0475],[2.2144, 2.7515],[2.2013, 2.0014],[2.6483, 2.2183],[2.1147, 2.2242],[2.7970, 2.8795],[2.0625, 2.6366],[2.5307, 2.1285],[2.2200, 2.7777],[2.3957, 2.1076],[2.1013, 2.5989],[2.4482, 2.9455],[2.0149, 2.6192],[2.2012, 2.2611]])
- label = np.array([-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1])
- w,b = perception(data,label,0.5,1000)
- x1 = -2
- y1 = (-1/w[:,1])*(np.dot(w[:,0],x1)+b)
- x2 = 3
- y2 = (-1/w[:,1])*(np.dot(w[:,0],x2)+b)
- plt.plot([x1,x2],[y1,y2],color='red')
- plt.scatter(data[1:15,0],data[1:15,1],color='blue',marker='x')
- plt.scatter(data[16:,0],data[16:,1],color='red',marker='o')
- plt.show()
- import numpy as np
- import matplotlib.pyplot as plt
-
- def perception_an(data,label,n,inter):
- a = np.random.randn(len(data))
- b = 0
- Gram = np.dot(data,data.T)
- for k in range(inter):
- for i in range(len(data)):
- tmp = 0
- for j in range(len(data)):
- tmp += a[j]*label[j]*Gram[i][j]
- tmp += b
- if (label[i]*tmp <= 0):
- a[i] += n
- b += n*label[i]
- w = 0
- for i in range(len(a)):
- w += a[i]*label[i]*data[i,:]
- return w,b
-
- if __name__ == '__main__':
- data = np.array([
- [-0.6508, 0.1097],[-1.4492, 0.8896],[2.0850, 0.6876],[0.2626, 1.1476],[0.6418, 1.0234],[0.2569, 0.6730],[1.1155, 0.6043],[0.0914, 0.3399],[0.0121, 0.5256],[-0.0429, 0.4660],[0.4340, 0.6870],[0.2735, 1.0287],[0.4839, 0.4851],[0.4089, -0.1267],[1.4391, 0.1614],[2.9115, 2.1973],[2.3654, 2.0475],[2.2144, 2.7515],[2.2013, 2.0014],[2.6483, 2.2183],[2.1147, 2.2242],[2.7970, 2.8795],[2.0625, 2.6366],[2.5307, 2.1285],[2.2200, 2.7777],[2.3957, 2.1076],[2.1013, 2.5989],[2.4482, 2.9455],[2.0149, 2.6192],[2.2012, 2.2611]])
- label = np.array([-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1])
- w,b = perception_an(data,label,0.5,1)
- x1 = -2
- y1 = (-1/w[1])*(np.dot(w[0],x1)+b)
- x2 = 3
- y2 = (-1/w[1])*(np.dot(w[0],x2)+b)
- plt.plot([x1,x2],[y1,y2],color='red')
- plt.scatter(data[1:15,0],data[1:15,1],color='blue',marker='x')
- plt.scatter(data[16:,0],data[16:,1],color='red',marker='o')
- plt.show()
- # initialize parameters randomly
- h = 100 # size of hidden layer
- W = 0.01 * np.random.randn(D,h)
- b = np.zeros((1,h))
- W2 = 0.01 * np.random.randn(h,K)
- b2 = np.zeros((1,K))
-
- # some hyperparameters
- step_size = 1e-0
- reg = 1e-3 # regularization strength
-
- # gradient descent loop
- num_examples = X.shape[0]
- for i in range(10000):
-
- # evaluate class scores, [N x K]
- hidden_layer = np.maximum(0, np.dot(X, W) + b) # note, ReLU activation
- scores = np.dot(hidden_layer, W2) + b2
-
- # compute the class probabilities
- exp_scores = np.exp(scores)
- probs = exp_scores / np.sum(exp_scores, axis=1, keepdims=True) # [N x K]
-
- # compute the loss: average cross-entropy loss and regularization
- corect_logprobs = -np.log(probs[range(num_examples),y])
- data_loss = np.sum(corect_logprobs)/num_examples
- reg_loss = 0.5 * reg * np.sum(W * W) + 0.5 * reg * np.sum(W2 * W2)
- loss = data_loss + reg_loss
- if i % 1000 == 0:
- print("iteration %d: loss %f" % (i, loss))
-
- # compute the gradient on scores
- dscores = probs
- dscores[range(num_examples),y] -= 1
- dscores /= num_examples
-
- # backpropate the gradient to the parameters
- # first backprop into parameters W2 and b2
- dW2 = np.dot(hidden_layer.T, dscores)
- db2 = np.sum(dscores, axis=0, keepdims=True)
- # next backprop into hidden layer
- dhidden = np.dot(dscores, W2.T)
- # backprop the ReLU non-linearity
- dhidden[hidden_layer <= 0] = 0
- # finally into W,b
- dW = np.dot(X.T, dhidden)
- db = np.sum(dhidden, axis=0, keepdims=True)
-
- # add regularization gradient contribution
- dW2 += reg * W2
- dW += reg * W
-
- # perform a parameter update
- W += -step_size * dW
- b += -step_size * db
- W2 += -step_size * dW2
- b2 += -step_size * db2
对图所示的非线性数据,迭代了10000次,最后的损失降低为0.249384,最后得到的精度为:0.98。可以说最终得到了比较理想的精确度,事实证明BP神经网络在某些情况下比单纯的线性分类器的效果要好的多
第一步,确定神经元中心;
第二步,利用BP算法等来确定参数。
- from scipy import *
- from scipy.linalg import norm, pinv
- from matplotlib import pyplot as plt
-
- class RBF:
- def __init__(self, indim, numCenters, outdim):
- self.indim = indim
- self.outdim = outdim
- self.numCenters = numCenters
- self.centers = [random.uniform(-1, 1, indim) for i in range(numCenters)]
- self.beta = 8
- self.W = random.random((self.numCenters, self.outdim))
-
- def _basisfunc(self, c, d):
- assert len(d) == self.indim
- return exp(-self.beta * norm(c-d)**2)
-
- def _calcAct(self, X):
- # 计算RBFs的激活函数值
- G = zeros((X.shape[0], self.numCenters), float)
- for ci, c in enumerate(self.centers):
- for xi, x in enumerate(X):
- G[xi,ci] = self._basisfunc(c, x)
- return G
-
- def train(self, X, Y):
- """ X: n x indim维的矩阵
- y: n x 1维的列向量"""
-
- # 从训练集随机选择中心向量
- rnd_idx = random.permutation(X.shape[0])[:self.numCenters]
- self.centers = [X[i,:] for i in rnd_idx]
-
- print("center", self.centers)
- # 计算RBFs的激活函数值
- G = self._calcAct(X)
- print(G)
-
- # 计算输出层的权值
- self.W = dot(pinv(G), Y)
-
- def test(self, X):
- """ X: n x indim维的矩阵 """
-
- G = self._calcAct(X)
- Y = dot(G, self.W)
- return Y
-
- if __name__ == '__main__':
- n = 100
- x = mgrid[-1:1:complex(0,n)].reshape(n, 1) #设置x的值
- y = sin(3*(x+0.5)**3 - 1) # 设置y的值
-
- rbf = RBF(1, 10, 1)
- rbf.train(x, y)
- z = rbf.test(x)
- plt.figure(figsize=(12, 8))
- plt.plot(x, y, 'k-')
- plt.plot(x, z, 'r-', linewidth=2)
-
- plt.plot(rbf.centers, zeros(rbf.numCenters), 'gs')
- for c in rbf.centers:
- cx = arange(c-0.7, c+0.7, 0.01)
- cy = [rbf._basisfunc(array([cx_]), array([c])) for cx_ in cx]
- plt.plot(cx, cy, '-', color='gray', linewidth=0.2)
- plt.xlim(-1.2, 1.2)
- plt.show()
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。