【TensorFlow学习笔记:神经网络优化(6讲)】

目录

  • 【1】NN复杂度
  • 【2】指数衰减学习率
  • 【3】激活函数
    • 优秀激活函数所具有的特点
    • 常见的激活函数
    • 对于初学者的建议
  • 【4】损失函数
  • 【5】缓解过拟合——正则化
  • 【6】参数优化器
    • 【1】SGD
    • 【2】SGDM(SGD基础上增加了一阶动量)
    • 【3】Adagrade(SGD基础上增加了二阶动量)
    • 【4】RMSProp(SGD基础上增加了二阶动量)
    • 【5】Adam(同时结合SGDM一阶动量和RMSProp的二节动量)
    • 优化器对比总结

【1】NN复杂度

空间复杂度:
层数:隐藏层层数+输出层
总参数:总w+总b
时间复杂度:
乘加运算次数
以下图为例:总参数=3x4+4(第一层) +4x2+2(第二层)=26
乘加运算次数=3x4+4x2=20

【2】指数衰减学习率

已知:学习率过小,收敛速度慢。学习率过大导致不收敛。
可以先用较大的学习率,快速得到较优解,然后逐步减小学习率,使模型在训练后期稳定,例如指数衰减学习率。

指数衰减学习率=初始学习率*学习率衰减率^(当前轮数/多少轮衰减一次)

epoch = 40
LR_BASE = 0.2  # 最初学习率
LR_DECAY = 0.99  # 学习率衰减率
LR_STEP = 1  # 喂入多少轮BATCH_SIZE后,更新一次学习率
for epoch in range(epoch):  # for epoch 定义顶层循环,表示对数据集循环epoch次,此例数据集数据仅有1个w,初始化时候constant赋值为5,循环100次迭代。lr = LR_BASE * LR_DECAY ** (epoch / LR_STEP)

【3】激活函数

对于线性函数,即使有多个神经元首尾相接构成深层神经网络,依旧是线性组合,模型表达力不够。

MP模型比简化模型多了一个激活函数,它的加入加强了模型的表达力,使得深层网络不再是输入x的线性组合,而且随着层数增加提升表达力。

优秀激活函数所具有的特点

非线性:激活函数非线性时,多层神经网络可以逼近所有函数
可微性:优化器大多用梯度下降更新参数
单调性:当激活函数是单调的,能保证单层网络的损失函数是凸函数
近似恒等性:f(x)约等于x,当参数初始化为随机小值时,神经网络更稳定

激活函数输出值的范围:
1、激活函数输出为有限值时,权重对于特征的影响会更显著,基于梯度的优化方法更稳定
2、激活函数输出为无限值时,参数的初始值对模型的影响特别大,要使用更小的学习率

常见的激活函数

1、sigmoid函数:
函数公式、函数图像与导数图像:

调用方法:tf.nn.sigmoid(x)
特点:
1、易造成梯度消失(输入的值较大时,梯度就约等于0了)
2、输出非0均值,收敛慢(我们希望输入每层网络的特征是以0为均值的小数)
3、幂运算复杂,训练时间长

神经网络最初兴起的时候,sigmoid函数作为激活函数用的很多,但是近年来用sigmoid函数的网络已经很少了。
因为,深层神经网络更新参数时,需要从输出层到输入层逐层进行链式求导,而sigmoid函数导数的输出范围是(0,0.25],链式求导需要多层导数连续相乘,这样最终导致输出为0,造成梯度消失,参数无法继续更新。

2、Tanh函数:
调用方法:tf.math.tanh(x)
特点:
1、易造成梯度消失
2、输出0均值
3、幂运算复杂,训练时间长
函数公式、函数图像与导数图像:

3、Relu函数:
函数公式、函数图像与导数图像:

调用方法:tf.nn.relu(x) 优点: 1、在正区间解决了梯度消失的问题 2、只需要判断输入是否大于0,计算速度快 3、收敛速度远快于sigmoid和tanh 4、具备近似恒等性 缺点: 1、输出非0均值,瘦收敛慢 2、Dead ReIU问题,某些神经元可能永远无法被激活,导致相应的参数永远无法更新

送入激活函数的输入特征是负数时,激活函数输出是0,反向传输梯度是0,经过relu函数的负数特征过多导致神经元死亡,我们可以改进随机初始化,避免过多负数特征传入,也可以通过设置更小的学习率,减少参数分布的巨大变化,避免训练中产生过多负数特征

4、Leaky Relu函数:
函数公式、函数图像与导数图像:

调用方法:tf.nn.leaky_relu(x)
理论上来说,leaky relu具有relu的所有优点,外加不会有deadrelu问题,但是在实际操作中,并没有完全证明leaky relu总好于relu

对于初学者的建议

1、首选relu激活函数
2、学习率设置较小值
3、输入特征标准化,让输入特征满足以0为均值,1为标准差的正态分布
4、初始参数中心化,让随机生成的参数满足0位均值,sqrt(2/当前层输入特征个数)为标准差的正态分布

【4】损失函数

NN优化目标:loss最小
常用三种损失函数:1、mse(均方差)2、自定义3、ce(交叉熵)
1、mse(均方差)
mse调用方式:

loss_mse =tf.reduce_mean(tf.square(y_-y))

预测酸奶代码:

import tensorflow as tf
import numpy as npSEED = 23455rdm = np.random.RandomState(seed=SEED)  # 生成[0,1)之间的随机数
x = rdm.rand(32, 2)
y_ = [[x1 + x2 + (rdm.rand() / 10.0 - 0.05)] for (x1, x2) in x]  # 生成噪声[0,1)/10=[0,0.1); [0,0.1)-0.05=[-0.05,0.05)
x = tf.cast(x, dtype=tf.float32)w1 = tf.Variable(tf.random.normal([2, 1], stddev=1, seed=1))epoch = 15000
lr = 0.002for epoch in range(epoch):with tf.GradientTape() as tape:y = tf.matmul(x, w1)loss_mse = tf.reduce_mean(tf.square(y_ - y))grads = tape.gradient(loss_mse, w1)w1.assign_sub(lr * grads)if epoch % 500 == 0:print("After %d training steps,w1 is " % (epoch))print(w1.numpy(), "\n")
print("Final w1 is: ", w1.numpy())

生成的系数确实约等于1
2、自定义损失函数
以销量预测为例:
均方误差损失函数默认认为销量预测多了、少了,造成的损失是一样的,其实不然。
预测多了:损失成本
预测少了:损失利润
若利润不等于成本,则mse产生的loss无法利益最大化!
可以把损失定义为一个分段函数
在这里插入图片描述
loss_zdy=tf,reduce_sum(tf.where(tf.greater(y,y_),COST(y-y_),PROFIT(y_-y)))
如:预测酸奶销量,酸奶成本(COST)1元,酸奶利润(PROFIT)99元。
预测少了损失利润99元,大于预测多了损失成本1元。
预测少了损失大,希望生成的预测函数往多了预测。
预测酸奶代码:(修改损失函数)

import tensorflow as tf
import numpy as npSEED = 23455
COST = 1
PROFIT = 99rdm = np.random.RandomState(SEED)
x = rdm.rand(32, 2)
y_ = [[x1 + x2 + (rdm.rand() / 10.0 - 0.05)] for (x1, x2) in x]  # 生成噪声[0,1)/10=[0,0.1); [0,0.1)-0.05=[-0.05,0.05)
x = tf.cast(x, dtype=tf.float32)w1 = tf.Variable(tf.random.normal([2, 1], stddev=1, seed=1))epoch = 10000
lr = 0.002for epoch in range(epoch):with tf.GradientTape() as tape:y = tf.matmul(x, w1)loss = tf.reduce_sum(tf.where(tf.greater(y, y_), (y - y_) * COST, (y_ - y) * PROFIT))grads = tape.gradient(loss, w1)w1.assign_sub(lr * grads)if epoch % 500 == 0:print("After %d training steps,w1 is " % (epoch))print(w1.numpy(), "\n")
print("Final w1 is: ", w1.numpy())# 自定义损失函数
# 酸奶成本1元, 酸奶利润99元
# 成本很低,利润很高,人们希望多预测些,生成模型系数大于1,往多了预测

生成的系数确实都大于1
3、ce(交叉熵)
调用方式:tf.losses.categorical_crossentropy(y_, y)

import tensorflow as tfloss_ce1 = tf.losses.categorical_crossentropy([1, 0], [0.6, 0.4])
loss_ce2 = tf.losses.categorical_crossentropy([1, 0], [0.8, 0.2])
print("loss_ce1:", loss_ce1)
print("loss_ce2:", loss_ce2)# 交叉熵损失函数

一般来说,输出先通过softmax函数使之符合概率分布,再计算y与y_的交叉熵损失函数,TensorFlow提供了同时计算的函数
tf.nn.softmax_cross_entropy_with_logits(y_, y)

# softmax与交叉熵损失函数的结合
import tensorflow as tf
import numpy as npy_ = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1], [1, 0, 0], [0, 1, 0]])
y = np.array([[12, 3, 2], [3, 10, 1], [1, 2, 5], [4, 6.5, 1.2], [3, 6, 1]])
y_pro = tf.nn.softmax(y)
loss_ce1 = tf.losses.categorical_crossentropy(y_,y_pro)
loss_ce2 = tf.nn.softmax_cross_entropy_with_logits(y_, y)print('分步计算的结果:\n', loss_ce1)
print('结合计算的结果:\n', loss_ce2)

【5】缓解过拟合——正则化

为什么正则化可以化解过拟合,先看看下面两个视频和讲解吧:
过拟合
正则化如何运行
正则化不舍弃特征,而是减少了特征变量的量级,从而简化假设模型。由于变量过多,我们事先并不知晓每个变量对结果的相关程度,也就是说我们不知道该缩小哪些参数,我们选择缩小所有参数,也就是给所有参数加上惩罚项(除了theta0变量)。
在这里插入图片描述
正则化参数λ用来控制两个不同目标之间的取舍:
1、更好地拟合训练数据
2、保持参数尽量地小
λ过大同样也会造成欠拟合的现象。

欠拟合解决方法:
1、增加输入特征项
2、增加网络参数
3、减少正则化参数
过拟合的解决方法:
1、数据清洗
2、增大训练集
3、采用正则化
4、增大正则化参数

在这里插入图片描述
示例:利用神经网络区分蓝色点和红色点
在这里插入图片描述

思路:
1、先用神经网络拟合出数据x1,x2,y_c的函数关系
2、生成网格覆盖这些点
3、将网格中坐标送入训练好的神经网络
4、网络为每个坐标输出一个预测值
5、将神经网络输出为0.5的预测值的线标出颜色,这线就是区分线
分别输出不正则化和正则化的效果,观察效果

左侧是正则化之前的,右侧是正则化之后的。

1层隐藏层,4个神经元
1层隐藏层,4个神经元
1层隐藏层,22个神经元
1层隐藏层,22个神经元
1层隐藏层,40个神经元
1层隐藏层,40个神经元

很明显地可以看出,加入L2正则化后的曲线更加平缓。有效缓解了过拟合。

【6】参数优化器

推荐链接
【基础算法】神经网络参数优化器https://zhuanlan.zhihu.com/p/97873519
MOOC神经网络参数优化器
参数优化器总体公式:
在这里插入图片描述

【1】SGD

公式:在这里插入图片描述
code:

# 实现梯度更新 w1 = w1 - lr * w1_grad    b = b - lr * b_grad
w1.assign_sub(lr * grads[0])  # 参数w1自更新
b1.assign_sub(lr * grads[1])  # 参数b自更新

【2】SGDM(SGD基础上增加了一阶动量)

公式:
在这里插入图片描述
mt表示各时刻梯度方向的指数滑动平均值,表征了过去一段时间的平均值。β是接近1的超参数,一般等于0.9
code:

m_w, m_b = 0, 0
beta = 0.9# sgd-momentun  
m_w = beta * m_w + (1 - beta) * grads[0]
m_b = beta * m_b + (1 - beta) * grads[1]
w1.assign_sub(lr * m_w)
b1.assign_sub(lr * m_b)

【3】Adagrade(SGD基础上增加了二阶动量)

公式:
在这里插入图片描述
code:

v_w, v_b = 0, 0
# adagrad
v_w += tf.square(grads[0])
v_b += tf.square(grads[1])
w1.assign_sub(lr * grads[0] / tf.sqrt(v_w))
b1.assign_sub(lr * grads[1] / tf.sqrt(v_b))

【4】RMSProp(SGD基础上增加了二阶动量)

公式:
在这里插入图片描述

v_w, v_b = 0, 0
beta = 0.9
# rmsprop
v_w = beta * v_w + (1 - beta) * tf.square(grads[0])
v_b = beta * v_b + (1 - beta) * tf.square(grads[1])
w1.assign_sub(lr * grads[0] / tf.sqrt(v_w))
b1.assign_sub(lr * grads[1] / tf.sqrt(v_b))

【5】Adam(同时结合SGDM一阶动量和RMSProp的二节动量)

公式:
在这里插入图片描述
code:

m_w, m_b = 0, 0
v_w, v_b = 0, 0
beta1, beta2 = 0.9, 0.999
delta_w, delta_b = 0, 0
global_step = 0
# adam
m_w = beta1 * m_w + (1 - beta1) * grads[0]
m_b = beta1 * m_b + (1 - beta1) * grads[1]
v_w = beta2 * v_w + (1 - beta2) * tf.square(grads[0])
v_b = beta2 * v_b + (1 - beta2) * tf.square(grads[1])m_w_correction = m_w / (1 - tf.pow(beta1, int(global_step)))
m_b_correction = m_b / (1 - tf.pow(beta1, int(global_step)))
v_w_correction = v_w / (1 - tf.pow(beta2, int(global_step)))
v_b_correction = v_b / (1 - tf.pow(beta2, int(global_step)))w1.assign_sub(lr * m_w_correction / tf.sqrt(v_w_correction))
b1.assign_sub(lr * m_b_correction / tf.sqrt(v_b_correction))

优化器对比总结

							                            优化器对比(lr=0.1    epoch=500    batch=32)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/378305.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

kotlin 构造函数_Kotlin程序| 主要构造函数示例

kotlin 构造函数主要建设者 (Primary Constructor) A Kotlin class have Primary constructor and one or more Secondary constructor. Kotlin类具有Primary构造函数和一个或多个Secondary构造函数。 In Kotlin, Primary Constructor is the Part of Class Header. 在Kotlin中…

把SQL Server 错误日志导出为EXCEL 并发送到指定的ftp 或者 共享盘

把SQL Server 错误日志导出为EXCEL 并发送到指定的ftp 或者 共享盘 /* 2005版本 和2000 版本 sql server 错误日志结果不同。 下面是 适用于 SQL2000的 其中加入了 自己编写的一个ftp小程序 用来上传 相关日志状况*/IF object_id(tempdb..#error_log) IS NOT NULLD…

c语言软件幻化,python字符串处理

字符串字符串:不可变有序序列,在python可使用 "abc" , """abc""" ,abc 的形式表示,属于一种字面常量,python3中字符均属于Unicode编码。字符串可以被迭代,遍历,切…

第十章 开箱即用

第十章 开箱即用 “开箱即用”(batteries included)最初是由Frank Stajano提出的,指的是Python丰富的标准库。 模块 使用import将函数从外部模块导入到程序中。 import math math.sin(0)#结果为:0.0模块就是程序 在文件夹中创…

博客换肤

一直以来觉得博客园里的主题不是特别好,很多模版多多少少都有些美中不足,于是今天抽了点时间把主题改改,哈。幸亏博客园支持自定义样式。 时间有限就先改到这里,今后有时间在进一步完美,呵呵。转载于:https://www.cnbl…

duration java_Java Duration类| 带示例的get()方法

duration java持续时间类get()方法 (Duration Class get() method) get() method is available in java.time package. get()方法在java.time包中可用。 get() method is used to return the value for the given unit. get()方法用于返回给定单位的值。 get() method is a non…

Openmv通过串口接收数据、发送数据与stm32通信

博主联系方式: QQ:1540984562 QQ交流群:892023501 群里会有往届的smarters和电赛选手,群里也会不时分享一些有用的资料,有问题可以在群里多问问。 目录 参考接线星瞳教程openmv传送数据STM32解码程序参考 接线 星瞳教程

c语言尹宝林答案,c程序设计导引 尹宝林

《C程序设计导引》特别适合作为计算机和非计算机专业学生学习高级语言程序设计的教材,也可供计算机等级考试者和其他各类学习者使用参考。17.40定价:44.75(3.89折)/2013-05-01《大学计算机优秀教材系列:C程序设计导引》是一本讲解C程序设计的…

从程序员到项目经理(15):项目管理三大目标

项目管理的三大目标即时间、成本和质量,实际是告诉项目经理应重点关注什么因素,项目控制应该做什么工作。三大目标虽然简单,但如果能将其真正贯彻到自己的行动中,那么对项目计划制定、过程控制等工作,均能起到引导作用…

第十一章 文件

第十一章 文件 打开文件 当前目录中有一个名为beyond.txt的文本文件,打开该文件 调用open时,原本可以不指定模式,因为其默认值就是’r’。 import io f open(beyond.txt)文件模式 值描述‘r’读取模式(默认值)‘w…

iterator与iterable

用Iterator模式实现遍历集合Iterator模式是用于遍历集合类的标准访问方法。它可以把访问逻辑从不同类型的集合类中抽象出来,从而避免向客户端暴露集合的内部结构。例如,如果没有使用Iterator,遍历一个数组的方法是使用索引: for(i…

Android中的Touch事件处理流程

1、当触摸屏幕时,最先执行的是Activity中的 publicbooleandispatchTouchEvent (MotionEvent ev) {if(ev.getAction() MotionEvent. ACTION_DOWN) {onUserInteraction();}if(getWindow().superDispatchTouchEvent(ev)) {returntrue;}returnonTouchEvent(ev);}如果某…

【TensorFlow学习笔记:神经网络八股】(实现MNIST数据集手写数字识别分类以及FASHION数据集衣裤识别分类)

课程来源:人工智能实践:Tensorflow笔记2 文章目录前言一、搭建网络八股sequential1.函数介绍2.6步法实现鸢尾花分类二、搭建网络八股class1.创建自己的神经网络模板:2.调用自己创建的model对象三、MNIST数据集1.用sequential搭建网络实现手写数字识别2.用…

c语言 在执行区域没有空格,C语言上机操作指导之TurboC.doc

C语言上机操作指导之 -------- Turbo C程序设计是实践性很强的过程,任何程序都必须在计算机上运行,以检验程序的正确与否。因此在学习程序设计中,一定要重视上机实践环节,通过上机可以加深理解 C语言的有关概念,以巩固…

java 根据类名示例化类_Java即时类| from()方法与示例

java 根据类名示例化类即时类from()方法 (Instant Class from() method) from() method is available in java.time package. from()方法在java.time包中可用。 from() method is used to return a copy of the Instant from the given TemporalAccessor object. from()方法用于…

第十二章 图形用户界面

第十二章 图形用户界面 GUI就是包含按钮、文本框等控件的窗口 Tkinter是事实上的Python标准GUI工具包 创建GUI示例应用程序 初探 导入tkinter import tkinter as tk也可导入这个模块的所有内容 from tkinter import *要创建GUI,可创建一个将充当主窗口的顶级组…

Sqlserver 2005 配置 数据库镜像:数据库镜像期间可能出现的故障:镜像超时机制

数据库镜像期间可能出现的故障 SQL Server 2005其他版本更新日期: 2006 年 7 月 17 日 物理故障、操作系统故障或 SQL Server 故障都可能导致数据库镜像会话失败。数据库镜像不会定期检查 Sqlservr.exe 所依赖的组件来验证组件是在正常运行还是已出现故障。但对于某…

江西理工大学期末试卷c语言,2016年江西理工大学信息工程学院计算机应用技术(加试)之C语言程序设计复试笔试最后押题五套卷...

一、选择题1. 设有函数定义:( )。A. B. C. D. 答:A则以下对函数sub 的调用语句中,正确的是【解析】函数的参数有两个,第一个是整型,第二个是字符类型,在调用函数时,实参必须一个是整型&#xff…

第十三章 数据库支持

第十三章 数据库支持 本章讨论Python数据库API(一种连接到SQL数据库的标准化方式),并演示如何使用这个API来执行一些基本的SQL。最后,本章将讨论其他一些数据库技术。 关Python支持的数据库清单 Python数据库API 标准数据库API…

【神经网络八股扩展】:自制数据集

课程来源:人工智能实践:Tensorflow笔记2 文章目录前言1、文件一览2、将load_data()函数替换掉2、调用generateds函数4、效果总结前言 本讲目标:自制数据集,解决本领域应用 将我们手中的图片和标签信息制作为可以直接导入的npy文件。 1、文件一览 首先看…