第五章:神经网络

目录

5.1神经元模型

5.2感知机与多层网络

[5.3 误差逆传播算法](#5.3 误差逆传播算法)

[5.4 全局最小与局部极小](#5.4 全局最小与局部极小)

[5.5 其他常见神经网络](#5.5 其他常见神经网络)

[5.6 深度学习](#5.6 深度学习)

二、实验

[1. 感知机的实现](#1. 感知机的实现)

2.对偶形式

[3. BP神经网络](#3. BP神经网络)

[4. 径向基网络](#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 感知机

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

感知机的学习:

,

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

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

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

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

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

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

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

5.3 误差逆传播算法

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

给定训练集
图5.3 BP网络及算法中的变量符号

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

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

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

对于训练例,假定网络的实际输出为

则网络在上的均方误差为:

需通过学习确定的参数数目:(d+l+ 1)q+l

BP是一个迭代学习算法,在迭代的每一轮中采用广义感知机学习规则:

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

注意到先影响到,再影响到,然后才影响到.,有:

根据的定义,显然有

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

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

于是有

类似地,有:

其中:

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

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

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

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

缓解过拟合:

"早停":

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

正则化:

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

5.4 全局最小与局部极小

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

"最优":

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

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

局部极小解: 都有成立

全局最小解: 若对参数空间中的任意(w;)都有

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

  • 从某些初始解出发,迭代寻找最优参数值.每次迭代中,我们先计算误差函数在当前点的梯度,然后根据梯度确定搜索方向.

  • 例如,由于负梯度方向是函数值下降最快的方向,因此梯度下降法就是沿着负梯度方向搜索最优解.若误差函数在当前点的梯度为零,则已达到局部极小,更新量将为零,这意味着参数的迭代更新将在此停止.

  • 然而,如果误差函数具有多个局部极小,则不能保证找到的解是全局最小.
    可以采取以下策略解决只能找到一个"局部极小"的问题:

  • 以多组不同参数值初始化多个神经网络,按标准方法训练后,取其中误差最小的解作为最终参数.这相当于从多个不同的初始点开始搜索,这样就可能陷入不同的局部极小,从中进行选择有可能获得更接近全局最小的结果.

  • 使用"模拟退火"(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实现感知机算法的原始形式。

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

学习前
学习后

2.对偶形式

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

3. BP神经网络

# 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神经网络在某些情况下比单纯的线性分类器的效果要好的多

4. 径向基网络

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

第二步,利用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()
相关推荐
hunteritself1 分钟前
AI Weekly『12月16-22日』:OpenAI公布o3,谷歌发布首个推理模型,GitHub Copilot免费版上线!
人工智能·gpt·chatgpt·github·openai·copilot
IT古董1 小时前
【机器学习】机器学习的基本分类-强化学习-策略梯度(Policy Gradient,PG)
人工智能·机器学习·分类
centurysee1 小时前
【最佳实践】Anthropic:Agentic系统实践案例
人工智能
mahuifa1 小时前
混合开发环境---使用编程AI辅助开发Qt
人工智能·vscode·qt·qtcreator·编程ai
四口鲸鱼爱吃盐1 小时前
Pytorch | 从零构建GoogleNet对CIFAR10进行分类
人工智能·pytorch·分类
落魄君子1 小时前
ELM分类-单隐藏层前馈神经网络(Single Hidden Layer Feedforward Neural Network, SLFN)
神经网络·分类·数据挖掘
蓝天星空1 小时前
Python调用open ai接口
人工智能·python
睡觉狂魔er1 小时前
自动驾驶控制与规划——Project 3: LQR车辆横向控制
人工智能·机器学习·自动驾驶
scan7241 小时前
LILAC采样算法
人工智能·算法·机器学习
leaf_leaves_leaf1 小时前
win11用一条命令给anaconda环境安装GPU版本pytorch,并检查是否为GPU版本
人工智能·pytorch·python