当前位置:   article > 正文

第五章:神经网络

第五章:神经网络

目录

5.1神经元模型

5.2感知机与多层网络

5.3 误差逆传播算法

5.4 全局最小与局部极小

5.5 其他常见神经网络

5.6 深度学习

二、实验

1. 感知机的实现

 2.对偶形式

3. BP神经网络

4. 径向基网络

5.1神经元模型

"神经网络是由具有适应性的简单单元组成的广泛并行互连的网络,它的组织能够模拟生物神经系统对真实世界物体所作出的交互反应”

神经网络是一个很大的学科领域,本课程仅讨论神经网络与机器学习的交集,即“神经网络学习”亦称“连接主义(connectionism)”学习

M-P神经神经元模型:(如下图所示)

图5.1 M-P神经元模型

神经元会接收外界的n个输入信号,这些输入会与权重相结合,再通过“激活函数”对信号进行一定的修改,以得到我们自己想要的数据

权重:决定模型如何根据输入数据产生输出,可通过优化算法进行调整,最小化模型预测与实际结果之间的差异。

作用:

  • 提高模型性能
  • 加速训练过程
  • 改善泛化能力
  • 避免过拟合

理想激活函数:阶跃函数,0表示抑制神经元而1表示激活神经元

阶跃函数具有不连续、不光滑等不好的性质,常用的是 Sigmoid函数

图5.2.1 神经元激活函数

 (a)函数是理想情况,对于小于0的信号直接过滤掉,(b)函数则是对小于0的信号进行过滤,而在0的信号,则为一定的值。

把许多个这样的神经元按一定的层次结构连接起来,就得到了神经网络.、

5.2感知机与多层网络

感知机:由两层神经元组成,如图5.2所示,输入层接收外界输入信号后传递给输出层,输出层是M-P神经元,亦称“阈值逻辑单元”.

图5.2 感知机

更一般地,给定训练数据集,权重w_i(i= 1,2,...,n)以及阈值\theta可通过学习得到.

感知机的学习:

                                                \Delta w_i=\eta (y-\widehat{y})x_i,  w_i\leftarrow w_i+\Delta w_i

 \eta是学习率,若感知机对训练样例(x, y)预测正确,即y=\widehat{y},则感知机不发生变化,否则将根据错误的程度进行权重调整.

感知机只有输出层神经元进行激活函数处理,即只拥有一层功能神经元,其学习能力非常有限,只能处理线性问题,对于非线性问题,学习过程会发生振荡,w难以稳定下来,求不出解

要解决非线性可分问题,需使用多层功能神经元.

多层神经元:简单的两层感知机,输出层与输入层之间的一层神经元,被称为隐层或隐含层(hidden layer),隐含层和输出层神经元都是拥有激活函数的功能神经元.

图5.2.2 多层馈神经网络

多层前馈神经网络:常见的神经网络是形如图5.2.2所示的层级结构,每层神经元与下一层神经元全互连,神经元之间不存在同层连接,也不存在跨层连接.这样的神经网络结构通常称为“多层前馈神经网络”

多层前馈网络有强大的表示能力(“万有逼近性”)

仅需一个包含足够多神经元的隐层,多层前馈神经网络就能以任意精度逼近任意复杂度的连续函数

5.3 误差逆传播算法

误差逆传播算法(BP算法):迄今最成功、最常用的神经网络算法,可用于多种任务(不仅限于分类)

给定训练集D=\left \{(x_1,y_1),(x_2,y_2),...(x_m,,y_m), \right \},x_i\in R^d,y_i\in R^l

图5.3 BP网络及算法中的变量符号

输入:d维特征向量输出:l个输出值

隐层:假定使用q个隐层神经元

假定功能单元均使用Sigmoid函数

对于训练例(x_k,y_k),假定网络的实际输出为\widehat{y}_k=(\widehat{y}_1^k,\widehat{y}_2^k,...\widehat{y}_l^k)

\widehat{y}_j^k=f(\beta _j-\theta _j)

则网络在(x_k,y_k)上的均方误差为:

E_k=\frac{1}{2}\sum_{j=1}^{1}(\widehat{y}_j^k-y_j^k)^2

需通过学习确定的参数数目:(d+l+ 1)q+l
BP是一个迭代学习算法,在迭代的每一轮中采用广义感知机学习规则:

v\leftarrow v+\Delta v

BP算法基于梯度下降策略,以目标的负梯度方向对参数进行调整,以w_{hj}为例,对误差E_k给定学习率\eta,有:

\Delta w_{hj}=-\eta \frac{\partial E_k}{\partial w_{hj}}

注意到w_{hj}先影响到\beta _j,再影响到\widehat{y}_j^k,,然后才影响到E_k.,有:

\frac{\partial E_k}{\partial w_{hj}}=\frac{\partial E_k}{\partial \widehat{y}_j^k}\cdot \frac{\partial \widehat{y}_j^k,}{\partial \beta _j}\cdot \frac{\partial \beta _j}{\partial w_{hj}}

根据\beta _j的定义,显然有

\frac{\partial \beta _j}{\partial w_{hj}}=b_h

Sigmoid函数有一个很好的性质:

f' (x)= f(x)(1 - f (x)) ,

于是有

g_j=\widehat{y}_j^k(1-\widehat{y}_j^k)({y}_j^k-\widehat{y}_j^k)

\Delta w_{hj}=-\eta \frac{\partial E_k}{\partial w_{hj}}=\eta g_jb_h

类似地,有:

\Delta \theta=- \eta g_j

\Delta v_{ih}=\eta e_hx_i

\Delta \gamma h=-\eta e_h

其中:

e_h=b_h(1-b_h)\sum_{j=1}^{1}w_{hj}g_j

学习率\eta不能太大,也不能太小。

推导出基于累积误差最小化的更新规则,就得到了累积误差逆传播算法.

所以只需一个包含足够多神经元的隐层,多层前馈网络就能以任意精度逼近任意复杂度的连续函数.然而,如何设置隐层神经元的个数仍是个未决问题,实际应用中通常靠“试错法”(trial-by-error)调整.

正是由于其强大的表示能力,BP神经网络经常遭遇过拟合,其训练误差持续降低,但测试误差却可能上升.

缓解过拟合:

“早停”:

  • 若训练误差连续a轮的变化小于b,则停止训练
  • 使用验证集:若训练误差降低、验证误差升高,则停止训练

正则化:

  • 在误差目标函数中增加一项描述网络复杂度

E=\lambda \frac{1}{m}\sum_{k=1}^{m}E_k+(1-\lambda)\sum_{i}w_i^2

5.4 全局最小与局部极小

神经网络的训练过程可看作一个参数寻优过程,即在参数空间中,寻找一组最优参数使得E最小.

“最优”:

  • “局部极小”(local minimum)
  • “全局最小”(global minimum)

对w*和\theta*,若存在\varepsilon >0使得

\forall (w;\theta )\in \left \{ (w;\theta)|(w;\theta)-(w^*;\theta^*) \leqslant \varepsilon \right \}

局部极小解: 都有E(w;\theta)\geqslant E(w^*;\theta^*)成立

全局最小解: 若对参数空间中的任意(w;\theta)都有E(w;\theta)\geqslant E(w^*;\theta^*)

参数寻优方法:基于梯度的搜索

  • 从某些初始解出发,迭代寻找最优参数值.每次迭代中,我们先计算误差函数在当前点的梯度,然后根据梯度确定搜索方向.
  • 例如,由于负梯度方向是函数值下降最快的方向,因此梯度下降法就是沿着负梯度方向搜索最优解.若误差函数在当前点的梯度为零,则已达到局部极小,更新量将为零,这意味着参数的迭代更新将在此停止.
  • 然而,如果误差函数具有多个局部极小,则不能保证找到的解是全局最小.

可以采取以下策略解决只能找到一个“局部极小”的问题:

  • 以多组不同参数值初始化多个神经网络,按标准方法训练后,取其中误差最小的解作为最终参数.这相当于从多个不同的初始点开始搜索,这样就可能陷入不同的局部极小,从中进行选择有可能获得更接近全局最小的结果.
  • 使用“模拟退火”(simulated annealing)技术[Aarts and Korst,1989].模拟退火在每一步都以一定的概率接受比当前解更差的结果,从而有助于“跳出”局部极小.在每步迭代过程中,接受“次优解”的概率要随着时间的推移而逐渐降低,从而保证算法稳定.
  • 使用随机梯度下降.与标准梯度下降法精确计算梯度不同,随机梯度下降法在计算梯度时加入了随机因素.于是,即便陷入局部极小点,它计算出的梯度仍可能不为零,这样就有机会跳出局部极小继续搜索.

5.5 其他常见神经网络

  • RBF网络
  • ART网络
  • SOM网络
  • 级联相关网络
  • Elman网络
  • Boltzmann机

5.6 深度学习

复杂模型的训练效率低,易陷入过拟合,因此难以受到人们青睐.而“深度学习”是一种优秀的复杂模型

深度学习模型:深层的神经网络

通过增加隐层数量来提升模型性能,但BP算法不适用于此,不能够“收敛”

无监督逐层训练:多隐层网络训练的有效手段,

基本思想:“预训练+微调”

每次训练一层隐结点,训练时将上一层隐结点的输出作为输入,而本层隐结点的输出作为下一层隐结点的输入,这称为“预训练”(pre-training);在预训练全部完成后,再对整个网络进行“微调”(fine-tuning)训练.各层预训练完成后,再利用BP算法等对整个网络进行训练.

将大量参数分组,对每组先找到局部看来比较好的设置,然后再基于这些局部较优的结果联合起来进行全局寻优.这样就在利用了模型大量参数所提供的自由度的同时,有效地节省了训练开销.

“权共享”(weight sharing):让一组神经元使用相同的连接权,另一种节省训练开销的策略

无论是DBN还是CNN,都是通过多层处理,逐渐将初始的“低层”特征表示转化为“高层”特征表示后,用“简单模型”即可完成复杂的分类等学习任务.由此可将深度学习理解为进行“特征学习”(feature learning)或“表示学习”(representation learning).

“特征工程”:描述样本的特征由人类专家来设计

二、实验

1. 感知机的实现

利用Python实现感知机算法的原始形式。

  1. import numpy as np
  2. import matplotlib.pyplot as plt
  3. def perception(data,label,n,inter):
  4. raw,col = np.shape(data)
  5. w = np.random.randn(1,col)
  6. b = np.random.randn(1)
  7. x1 = -1
  8. y1 = (-1/w[:,1])*(np.dot(w[:,0],x1)+b)
  9. x2 = 2
  10. y2 = (-1/w[:,1])*(np.dot(w[:,0],x2)+b)
  11. plt.plot([x1,x2],[y1,y2],color='red')
  12. plt.scatter(data[1:15,0],data[1:15,1],color='blue',marker='x')
  13. plt.scatter(data[16:,0],data[16:,1],color='red',marker='o')
  14. plt.show()
  15. for times in range(inter):
  16. for i in range(raw):
  17. if -label[i-1]*(np.dot(w,(data[:][i-1]))+b) < 0:
  18. w -= n*label[i-1]*data[:][i-1]
  19. b -= n*label[i-1]
  20. elif -label[i-1]*(np.dot(w,(data[:][i-1]))+b) == 0:
  21. break
  22. return w,b
  23. if __name__ == '__main__':
  24. data = np.array([
  25. [-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]])
  26. 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])
  27. w,b = perception(data,label,0.5,1000)
  28. x1 = -2
  29. y1 = (-1/w[:,1])*(np.dot(w[:,0],x1)+b)
  30. x2 = 3
  31. y2 = (-1/w[:,1])*(np.dot(w[:,0],x2)+b)
  32. plt.plot([x1,x2],[y1,y2],color='red')
  33. plt.scatter(data[1:15,0],data[1:15,1],color='blue',marker='x')
  34. plt.scatter(data[16:,0],data[16:,1],color='red',marker='o')
  35. plt.show()
学习前
学习后

 2.对偶形式

  1. import numpy as np
  2. import matplotlib.pyplot as plt
  3. def perception_an(data,label,n,inter):
  4. a = np.random.randn(len(data))
  5. b = 0
  6. Gram = np.dot(data,data.T)
  7. for k in range(inter):
  8. for i in range(len(data)):
  9. tmp = 0
  10. for j in range(len(data)):
  11. tmp += a[j]*label[j]*Gram[i][j]
  12. tmp += b
  13. if (label[i]*tmp <= 0):
  14. a[i] += n
  15. b += n*label[i]
  16. w = 0
  17. for i in range(len(a)):
  18. w += a[i]*label[i]*data[i,:]
  19. return w,b
  20. if __name__ == '__main__':
  21. data = np.array([
  22. [-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]])
  23. 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])
  24. w,b = perception_an(data,label,0.5,1)
  25. x1 = -2
  26. y1 = (-1/w[1])*(np.dot(w[0],x1)+b)
  27. x2 = 3
  28. y2 = (-1/w[1])*(np.dot(w[0],x2)+b)
  29. plt.plot([x1,x2],[y1,y2],color='red')
  30. plt.scatter(data[1:15,0],data[1:15,1],color='blue',marker='x')
  31. plt.scatter(data[16:,0],data[16:,1],color='red',marker='o')
  32. plt.show()

3. BP神经网络

  1. # initialize parameters randomly
  2. h = 100 # size of hidden layer
  3. W = 0.01 * np.random.randn(D,h)
  4. b = np.zeros((1,h))
  5. W2 = 0.01 * np.random.randn(h,K)
  6. b2 = np.zeros((1,K))
  7. # some hyperparameters
  8. step_size = 1e-0
  9. reg = 1e-3 # regularization strength
  10. # gradient descent loop
  11. num_examples = X.shape[0]
  12. for i in range(10000):
  13. # evaluate class scores, [N x K]
  14. hidden_layer = np.maximum(0, np.dot(X, W) + b) # note, ReLU activation
  15. scores = np.dot(hidden_layer, W2) + b2
  16. # compute the class probabilities
  17. exp_scores = np.exp(scores)
  18. probs = exp_scores / np.sum(exp_scores, axis=1, keepdims=True) # [N x K]
  19. # compute the loss: average cross-entropy loss and regularization
  20. corect_logprobs = -np.log(probs[range(num_examples),y])
  21. data_loss = np.sum(corect_logprobs)/num_examples
  22. reg_loss = 0.5 * reg * np.sum(W * W) + 0.5 * reg * np.sum(W2 * W2)
  23. loss = data_loss + reg_loss
  24. if i % 1000 == 0:
  25. print("iteration %d: loss %f" % (i, loss))
  26. # compute the gradient on scores
  27. dscores = probs
  28. dscores[range(num_examples),y] -= 1
  29. dscores /= num_examples
  30. # backpropate the gradient to the parameters
  31. # first backprop into parameters W2 and b2
  32. dW2 = np.dot(hidden_layer.T, dscores)
  33. db2 = np.sum(dscores, axis=0, keepdims=True)
  34. # next backprop into hidden layer
  35. dhidden = np.dot(dscores, W2.T)
  36. # backprop the ReLU non-linearity
  37. dhidden[hidden_layer <= 0] = 0
  38. # finally into W,b
  39. dW = np.dot(X.T, dhidden)
  40. db = np.sum(dhidden, axis=0, keepdims=True)
  41. # add regularization gradient contribution
  42. dW2 += reg * W2
  43. dW += reg * W
  44. # perform a parameter update
  45. W += -step_size * dW
  46. b += -step_size * db
  47. W2 += -step_size * dW2
  48. b2 += -step_size * db2

对图所示的非线性数据,迭代了10000次,最后的损失降低为0.249384,最后得到的精度为:0.98。可以说最终得到了比较理想的精确度,事实证明BP神经网络在某些情况下比单纯的线性分类器的效果要好的多 

4. 径向基网络

第一步,确定神经元中心;

第二步,利用BP算法等来确定参数。

  1. from scipy import *
  2. from scipy.linalg import norm, pinv
  3. from matplotlib import pyplot as plt
  4. class RBF:
  5. def __init__(self, indim, numCenters, outdim):
  6. self.indim = indim
  7. self.outdim = outdim
  8. self.numCenters = numCenters
  9. self.centers = [random.uniform(-1, 1, indim) for i in range(numCenters)]
  10. self.beta = 8
  11. self.W = random.random((self.numCenters, self.outdim))
  12. def _basisfunc(self, c, d):
  13. assert len(d) == self.indim
  14. return exp(-self.beta * norm(c-d)**2)
  15. def _calcAct(self, X):
  16. # 计算RBFs的激活函数值
  17. G = zeros((X.shape[0], self.numCenters), float)
  18. for ci, c in enumerate(self.centers):
  19. for xi, x in enumerate(X):
  20. G[xi,ci] = self._basisfunc(c, x)
  21. return G
  22. def train(self, X, Y):
  23. """ X: n x indim维的矩阵
  24. y: n x 1维的列向量"""
  25. # 从训练集随机选择中心向量
  26. rnd_idx = random.permutation(X.shape[0])[:self.numCenters]
  27. self.centers = [X[i,:] for i in rnd_idx]
  28. print("center", self.centers)
  29. # 计算RBFs的激活函数值
  30. G = self._calcAct(X)
  31. print(G)
  32. # 计算输出层的权值
  33. self.W = dot(pinv(G), Y)
  34. def test(self, X):
  35. """ X: n x indim维的矩阵 """
  36. G = self._calcAct(X)
  37. Y = dot(G, self.W)
  38. return Y
  39. if __name__ == '__main__':
  40. n = 100
  41. x = mgrid[-1:1:complex(0,n)].reshape(n, 1) #设置x的值
  42. y = sin(3*(x+0.5)**3 - 1) # 设置y的值
  43. rbf = RBF(1, 10, 1)
  44. rbf.train(x, y)
  45. z = rbf.test(x)
  46. plt.figure(figsize=(12, 8))
  47. plt.plot(x, y, 'k-')
  48. plt.plot(x, z, 'r-', linewidth=2)
  49. plt.plot(rbf.centers, zeros(rbf.numCenters), 'gs')
  50. for c in rbf.centers:
  51. cx = arange(c-0.7, c+0.7, 0.01)
  52. cy = [rbf._basisfunc(array([cx_]), array([c])) for cx_ in cx]
  53. plt.plot(cx, cy, '-', color='gray', linewidth=0.2)
  54. plt.xlim(-1.2, 1.2)
  55. plt.show()

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小桥流水78/article/detail/935260
推荐阅读
相关标签
  

闽ICP备14008679号