第五章:神经网络

目录

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()
相关推荐
尺度商业1 分钟前
纳思达更名奔图科技,一场品牌与资本市场价值的战略校准
大数据·人工智能·科技
渐儿2 分钟前
LangChain 资深开发者完全指南
人工智能
天天代码码天天2 分钟前
C# OnnxRuntime 部署 DAViD 表面法线估计
人工智能·david 表面法线估计
墨染天姬2 分钟前
【AI】2026年4月开源模型排行榜
人工智能·开源
zhexiao273 分钟前
AI提效工具使用实践 Claude Code、NEXT AI DRAW.IO、XREAD
人工智能·draw.io
wangqiaowq4 分钟前
RSA2 非对称加密签名
人工智能
踩着两条虫4 分钟前
VTJ.PRO 企业级应用开发实战指南
前端·人工智能·低代码·重构·架构
薛定猫AI6 分钟前
【深度解析】Graphify 如何为 AI 编程助手构建项目级知识图谱:降低 Token 消耗、提升代码理解效率
人工智能·知识图谱
子午6 分钟前
蔬菜识别~Python+深度学习+卷积网络算法+图像识别+2026原创+蔬菜识别
python·深度学习·算法
ok_hahaha8 分钟前
AI从头开始-黑马LongGraph-简单学习
人工智能·学习·langchain·lang graph