记7(激活函数+多层神经网络+梯度下降法及其优化

embedded/2025/2/2 17:44:08/

目录

  • 1、激活函数
    • 1.1、sigmoid函数:2端饱和,下面2个函数都要幂运算,运算速度会比较慢
    • 1.2、ReLU函数(Rectified Linear Unit,修正线性单元)
    • 1.3、PReLU函数(Parameteric Rectified Linear Unit,参数化修正线性单元)
    • 1.4、RReLU函数(Randomized Leaky Rectified Linear Unit,随机纠正线性单元):
  • 2、鸢尾花分类——实现多层神经网络
  • 3、梯度下降法
  • 4、优化

1、激活函数

激活函数:为了模拟非线性问题,又不能使得问题过于复杂,可以设计神经元对输入信号进行线性处理,得到的线性结果再输入非线性激活函数

  • 激活函数的特点:包含充分的梯度信息;能够识别阈值

在这里插入图片描述

1.1、sigmoid函数:2端饱和,下面2个函数都要幂运算,运算速度会比较慢

  • 对数几率函数logistic是典型的sigmoid函数:但是它不是以0为中的,在多层神经网络中可能产生偏移,可能使得梯度下降的速度变慢(可以使用双曲正切函数代替)
    在这里插入图片描述
  • 双曲正切函数Tanh
    在这里插入图片描述
  • 上述logistic函数的导函数,可见:

    梯度消失问题:例如在logistic函数的导函数取值在00.25之间,神经网络每一层都会将多个00.25相乘,误差在每一层不断衰减,网络层数较深时梯度值趋近于0,参数更新几乎停滞。
    在这里插入图片描述

1.2、ReLU函数(Rectified Linear Unit,修正线性单元)

  • 优点:z>0时,导数=1,缓解了梯度消失问题(只有z≤0时才会饱和);
  • 缺点:输出不是以0为均值;z≤0时,梯度=0,神经元死亡(无法更新)(可以使用Leaky-ReLU函数)
    在这里插入图片描述

1.3、PReLU函数(Parameteric Rectified Linear Unit,参数化修正线性单元)

y = { z z≥0 a z z<0 ,a:可训练参数 y= \begin{cases} z& \text{z≥0}\\ az& \text{z<0 ,a:可训练参数} \end{cases} y={zazz≥0z<0 ,a:可训练参数

1.4、RReLU函数(Randomized Leaky Rectified Linear Unit,随机纠正线性单元):

类比上一个,不同在与

  • 训练阶段:z<0部分的斜率是随机分配的,服从均匀分布
  • 测试阶段:z<0部分的斜率 是固定的,取训练阶段所有a的平均值

2、鸢尾花分类——实现多层神经网络

(单层的见机器学习笔记6“鸢尾花数据集——单层前馈型神经网络”)

  • 增加一个隐含层并设定隐含层有16个节点
  • 从输入层到隐含层:B1的shape=(16,),又因为输入有4个节点(鸢尾花的4个属性),所以W1的shape=(4,16)
  • 从隐含层到输出层:因为输出层有3个输出节点,所以B2.shape=(3,),W2.shape=(16,3)
  • 隐含层激活函数:relu函数;输出层激活函数:softmax函数;损失函数:交叉熵损失函数
    在这里插入图片描述
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
#读取文件,详见Python笔记10
train_path=tf.keras.utils.get_file("iris.csv", origin=None)   #获取文件的绝对路径
df_iris=pd.read_csv(train_path,header=0)        #结果是panda的二维数据表
iris=np.array(df_iris)        #将二维数据表类型转化为二维数组类型,shape=(150,6),与视频中不一样,索引号为0的是序号
x=iris[:,1:5]         #索引号1~4列属性:花瓣长度和宽度,x.shape=(150, 2)
y=iris[:,5]          #train_y.shape=(150,)x_svv=np.concatenate((np.stack(x[y=='setosa']),  #选取2种花,以及其前2种属性np.stack(x[y=='versicolor']),np.stack(x[y=='virginica'])),axis=0)
y_svv=np.concatenate((np.zeros(np.where(y=='setosa')[0].size),   #元组只有一个元素(数组)np.ones(np.where(y=='versicolor')[0].size),2*np.ones(np.where(y=='virginica')[0].size),),axis=0)np.random.seed(612)
iris_rand=np.concatenate((x_svv,np.expand_dims(y_svv,axis=1)),axis=1)
np.random.shuffle(iris_rand)        #打乱数组,并选前面120条数据为训练集,后面30条做测试集
x_train=tf.constant(iris_rand[:120,0:4],dtype=tf.float32)       #转化为float32张量
y_train=tf.constant(iris_rand[:120,4],dtype=tf.int64)           #转化为int32张量
x_test=tf.constant(iris_rand[120:,0:4],dtype=np.float32)
y_test=tf.constant(iris_rand[120:,4],dtype=tf.int64)X_train=x_train-tf.reduce_mean(x_train,axis=0)      #中心化, x_train.dtype=dtype('O'),是object
X_test=x_test-tf.reduce_mean(x_test,axis=0)
Y_train=tf.one_hot(y_train,3)                       #转化为独热编码Y_train.shape=TensorShape([120, 3])
Y_test=tf.one_hot(y_test,3)learn_rate=0.5                                  #超参数——学习率
iter=50                                         #迭代次数
display_step=10                                 #设置每迭代10次输出结果,方便查看
np.random.seed(612)
W1=tf.Variable(np.random.randn(4,16),dtype=tf.float32)    #W1列向量,4行16列
B1=tf.Variable(np.zeros([16]),dtype=tf.float32)           #B1列向量,长度为16的一维张量
W2=tf.Variable(np.random.randn(16,3),dtype=tf.float32)    #W2列向量,16行3列
B2=tf.Variable(np.zeros([3]),dtype=tf.float32)            #B2列向量,长度为3的一维张量cce_train=[]       #保存交叉熵损失
cce_test=[]
acc_train=[]      #保存准确率
acc_test=[]#训练模型
for i in range(0,iter+1):with tf.GradientTape() as tape:#relu函数和softmax函数,Hidden_train是120*16的张量,每行16个元素表示隐含层16个节点(就是输入层的输出端有16个),同理PRED_train是16*3Hidden_train=tf.nn.relu(tf.matmul(X_train,W1)+B1)    #shape=TensorShape([120, 16])PRED_train=tf.nn.softmax(tf.matmul(Hidden_train,W2)+B2)    #shape=TensorShape([16, 3])Loss_train=tf.reduce_mean(tf.keras.losses.categorical_crossentropy(y_true=Y_train, y_pred=PRED_train))Hidden_test=tf.nn.relu(tf.matmul(X_test,W1)+B1)    #shape=TensorShape([120, 16])PRED_test=tf.nn.softmax(tf.matmul(Hidden_test,W2)+B2)    #shape=TensorShape([16, 3])Loss_test=tf.reduce_mean(tf.keras.losses.categorical_crossentropy(y_true=Y_test, y_pred=PRED_test))#准确率,求PRED_train的每一行3个元素的max,即属于对应标签的概率最大,再与真实值y_train比较,求得准确率Accuracy_train=tf.reduce_mean(tf.cast(tf.equal(tf.argmax(PRED_train,axis=1),y_train),tf.float32))Accuracy_test=tf.reduce_mean(tf.cast(tf.equal(tf.argmax(PRED_test,axis=1),y_test),tf.float32))   cce_train.append(Loss_train)cce_test.append(Loss_test)acc_train.append(Accuracy_train)acc_test.append(Accuracy_test)grads=tape.gradient(Loss_train,[W1,B1,W2,B2])W1.assign_sub(learn_rate*grads[0])B1.assign_sub(learn_rate*grads[1])W2.assign_sub(learn_rate*grads[2])B2.assign_sub(learn_rate*grads[3])if i%display_step==0:print("i:%i,\tTrainAcc:%f,TrainLoss:%f\tTestAcc:%f,TestLoss:%f" %(i,Accuracy_train,Loss_train,Accuracy_test,Loss_test))#可视化,图1准确率,图2损失函数
plt.figure(figsize=(10,3))
plt.subplot(121)
plt.plot(cce_train,color="blue",label="train")
plt.plot(cce_test,color="red",label="test")
plt.xlabel("Iteration")
plt.ylabel("Loss")
plt.subplot(122)
plt.plot(acc_train,color="blue",label="train")
plt.plot(acc_test,color="red",label="test")
plt.xlabel("Iteration")
plt.ylabel("Accuracy")
plt.tight_layout()      #自动调整子图
plt.show()输出:
i:0,	TrainAcc:0.466667,TrainLoss:2.097793	TestAcc:0.266667,TestLoss:2.108944
i:10,	TrainAcc:0.933333,TrainLoss:0.204642	TestAcc:0.833333,TestLoss:0.344889
i:20,	TrainAcc:0.966667,TrainLoss:0.141266	TestAcc:0.866667,TestLoss:0.294079
i:30,	TrainAcc:0.958333,TrainLoss:0.110132	TestAcc:0.833333,TestLoss:0.286544
i:40,	TrainAcc:0.966667,TrainLoss:0.090271	TestAcc:0.833333,TestLoss:0.290193
i:50,	TrainAcc:0.966667,TrainLoss:0.076929	TestAcc:0.800000,TestLoss:0.305203

在这里插入图片描述

3、梯度下降法

批量梯度下降(前面介绍 的梯度下降法就是这个)(Batch Gradient Descent, BGD)

  • 每次迭代都使用所有样品来计算偏导数:
    在这里插入图片描述
  • 每一步都是准确地朝着极值点趋近,迭代次数少,但每次迭代的计算量大,训练时间长,因而不适合大规模数据集
  • 可以利用向量运算进行并行计算
  • 收敛于全局或局部极小值点

随机梯度下降(Stochastic Gradient Descent, SGD):

  • 每次迭代只选择一个样本训练模型,直到将所有样本都训练一遍,这叫做“一轮”。一轮后对最后一个样品的误差很少,但是后一个样本更新可能导致对上一个样品的效果变差
  • 反复训练多轮,直到神经网络对所有样本的误差足够小
  • 参数更新非常频繁,训练轮数多,无法快速收敛

小批量梯度下降(Mini-Batch Gradient Descent, MBGD)

  • 也叫小批量随机梯度下降(Mini-Batch SGD)
  • 把数据集分为多个小批量,每次迭代使用一个小批量来训练模型,参数更新公式:
    在这里插入图片描述
  • 将训练集划分为多个小批量,每次迭代只选择一个小批量训练模型,直到将所有样本都训练一遍,这叫做“一轮”。(固定数目的小批量=1个样品–>随机梯度下降)需要多轮
  • 每次迭代的训练样本数固定,与整个训练集的样本数量无关(假设每个小批量200个样本,那么若有2000个样本就分为10批,若有20000个样本就分为100批)
  • 并行,大规模数据集
  • 小批量的选取是基于抽样,存在偏差,就好像噪声,一定程度上提高模型的泛化能力

4、优化

  • 打乱样品
  • 并行时,采用2的幂数作为批量大小,如32、64、128…,可以充分利用处理器资源
  • 动态调整学习率:学习率衰减(Learning Rate Decay)/学习率退火(Learning Rate Annealing)

周期性地增大学习率
自适应调整学习率(统一调整各个参数的学习率)
自适应调整每个参数的学习率:

  • AdaGrad算法:
    先全局学习率η,各个参数的学习率表达式如下,将每次迭代的梯度取平方累加,再加上ε(保证分母非0),再开方,用全局学习率除以这个根号。
    学习率随着 迭代次数增加而减少。
    当某参数梯度比较大,则学习率衰减比较快(学习率变得更小了),当梯度比较小,则学习率衰减比较慢
    η ∑ r = 1 t ( g r a d r ) 2 + ε \dfrac{\eta}{\sqrt{\sum ^t_{r=1}(grad_r)^2+\varepsilon }} r=1t(gradr)2+ε η
  • RMSprop算法和AdaDelta算法是对AdaGrad算法的改进,各个参数的学习率不是单调递减的
  • 梯度估计:(如果小批量的样品中含有较多的噪声,那么梯度更新就会十分不稳定

动量梯度下降法(Momentum):

  • 动量=质量×速度
  • 小球下山模型:下山坡度比较大,那么速度积累比较大,如果坡度比较小甚至坡度上升,那么小球速度就变慢
  • 在更新参数时,可以在一定程度上保留之前的更新方向
  • 参数更新公式:以前的梯度会累积,但是会以α衰减
    在这里插入图片描述
    但是最低点时动量过大,会使得一下子越过最小值,到达其他局部最小值
  • 牛顿加速梯度算法(Nesterov Accelerated Gradient, NAG)
    (就是先预计下一步的参数,到了下一步再对之前的估计进行修正)

根据当前更新方向,估算下一步的梯度方向(是计算超前梯度,而不是计算当前的梯度,再用超前梯度修正当前的梯度,提高了算法的遇见能力,避免大幅震荡)
在新位置计算梯度,修正上面估计的梯度方向
在这里插入图片描述

  • Adam:
    可以看做是RMSprop+Momentum,而Nadam=Adam+NAG

http://www.ppmy.cn/embedded/158964.html

相关文章

国内flutter环境部署(记录篇)

设置系统环境变量 export PUB_HOSTED_URLhttps://pub.flutter-io.cn export FLUTTER_STORAGE_BASE_URLhttps://storage.flutter-io.cn使用以下命令下载flutter镜像 git clone -b stable https://mirror.ghproxy.com/https://github.com/<github仓库地址>#例如flutter仓…

PHP Mail:高效邮件发送解决方案详解

PHP Mail&#xff1a;高效邮件发送解决方案详解 引言 在互联网时代&#xff0c;邮件作为最常用的沟通方式之一&#xff0c;已经成为企业和个人不可或缺的通讯工具。PHP作为一种流行的服务器端脚本语言&#xff0c;在邮件发送方面具有天然的优势。本文将详细介绍PHP Mail&…

攻防世界 simple_php

&#xfeff;<?php show_source(__FILE__);//显示 PHP 文件的源码 include("config.php");// 包含了一个config.php文件 $a$_GET[a];//获取GET 参数 a 和 b $b$_GET[b]; if($a0 and $a) {echo $flag1; } if(is_numeric($b))//防止数字输入 {exit(); } if($b>1…

解锁豆瓣高清海报(二) 使用 OpenCV 拼接和压缩

解锁豆瓣高清海报(二): 使用 OpenCV 拼接和压缩 脚本地址: 项目地址: Gazer PixelWeaver.py pixel_squeezer_cv2.py 前瞻 继上一篇“解锁豆瓣高清海报(一) 深度爬虫与requests进阶之路”成功爬取豆瓣电影海报之后&#xff0c;本文将介绍如何使用 OpenCV 对这些海报进行智…

机器学习:支持向量机

支持向量机&#xff08;Support Vector Machine&#xff09;是一种二类分类模型&#xff0c;其基本模型定义为特征空间上的间隔最大的广义线性分类器&#xff0c;其学习策略便是间隔最大化&#xff0c;最终可转化为一个凸二次规划问题的求解。 假设两类数据可以被 H x : w T x…

Python3 + Qt5:实现AJAX异步更新UI

使用 Python 和 Qt5 开发时异步加载数据的方法 在开发使用 Python 和 Qt5 的应用程序时&#xff0c;为了避免在加载数据时界面卡顿&#xff0c;可以采用异步加载的方式。以下是几种实现异步加载的方法&#xff1a; 1. 使用多线程&#xff08;QThread&#xff09; 通过将数据…

【Rust自学】18.1. 能用到模式(匹配)的地方

喜欢的话别忘了点赞、收藏加关注哦&#xff08;加关注即可阅读全文&#xff09;&#xff0c;对接下来的教程有兴趣的可以关注专栏。谢谢喵&#xff01;(&#xff65;ω&#xff65;) 18.1.1. 什么是模式 模式(pattern) 是Rust里的一种特殊的语法&#xff0c;用于匹配复杂和简…

C++中的类型转换

文章目录 一、概述二、隐式类型转换&#xff08;Implicit Conversion&#xff09;三、显式类型转换&#xff08;Explicit Conversion&#xff09;四、C 风格类型转换 一、概述 C 提供了多种类型转换&#xff08;Type Conversion&#xff09;方式&#xff0c;以便在不同类型的数…