深度学习入门5——为什么神经网络可以学习?

在理解神经网络的可学习性之前,需要先从数学中的导数、数值微分、偏导数、梯度等概念入手,从而理解为什么神经网络具备学习能力。

1.数值微分的定义

先从导数出发理解什么是梯度。某一点的导数直观理解就是在该点的切线的斜率。在数学中导数表示某个瞬时的变化量,如下公式表示:

\frac{\mathrm{d}f(x)}{\mathrm{d}x}=\lim\limits_{h\to0}\frac{f(x+h)-f(x)}{h}\\

上述利用微小的差分求导数的过程称为数值微分(numerical differentiation),公式(1)表示的是前向差分(f(x+h)-f(x)),因为h无法无限趋近于0,所以存在误差(如下图所示)。为了减小这种数值微分误差,可以用中心差分(f(x+h)-f(x-h))减小误差。

2.数值微分的例子

以下面这个二次函数为例,对其数在x = 5和x = 10处进行求导。

y=0.01x^{2}+0.1x\\

import numpy as np
import matplotlib.pylab as plt

def numerical_diff(f, x):
    h = 1e-4 # 0.0001
    return (f(x+h) - f(x-h)) / (2*h)  # 中心差分

def function_1(x):
    return 0.01*x**2 + 0.1*x 

def tangent_line(f, x):
    d = numerical_diff(f, x)
    print(d)  # 0.1999999999990898  0.2999999999986347
    y = f(x) - d*x
    return lambda t: d*t + y
    #该函数首先调用numerical_diff函数来计算函数f在点x处的导数d,然后根据切线的方程 y = ax + b 中的斜率和截距来计算切线的斜率d和截距y。最后返回一个匿名函数,该函数接受一个参数 t,并返回切线上在 t 处的函数值。
x = np.arange(0.0, 20.0, 0.1)
y = function_1(x)
plt.xlabel("x")
plt.ylabel("f(x)")

tf1 = tangent_line(function_1, 5)  # x=5处的切线方程
tf2 = tangent_line(function_1, 10)  #  x=10处的切方程
y1 = tf1(x)
y2 = tf2(x)

plt.plot(x, y)
plt.plot(x, y1)
plt.plot(x, y2)
plt.show()

3.偏导数和梯度

下式表示的是包含两个变量的函数,可以看为计算平面内点的坐标的平方和函数:

f(x_{1},x_{2})=x_{1}^{2}+x_{2}^{2}\\

求某个变量的偏导数时,需要将多个变量中的某一个变量定为目标变量,并将其他变量固定为某个值才能求解。下面是该函数(由全部变量的偏导数汇总而成的向量)梯度(gradient)的可视化。

4.梯度法

机器学习的主要任务是在学习时寻找最优参数,而神经网络也必须在学习时找到最优的参数(权重和偏置)。上面介绍的函数其梯度指向的是函数最小值的方向,但是在复杂函数也就是一般的情况下,梯度下降的方向不一定是指向函数最小值,因为还可能存在鞍点(极小值、局部极值)。一般来说,损失函数很复杂,参数空间庞大,不知道它在何处能取得最小值,因此可以利用梯度求最小值。梯度法中,函数的取值从当前位置沿着梯度方向前进一定距离,然后在新的地方重新求梯度,再沿着新梯度方向前进,如此反复,不断地沿梯度方向前进。通过不断地沿梯度方向前进,逐渐减小函数值的过程就是梯度法。其中寻找最小值的梯度法称为梯度下降法,寻找最大值的梯度法称为梯度上升法。一般情况下,在神经网络中主要指的是梯度下降法,要最小化损失函数,最终得到最小值处对应的神经网络的权重和偏置,此时神经网络就被训练好了

def gradient_descent(f, init_x, lr=0.01, step_num=100):
    x = init_x
    for i in range(step_num):
        grad = numerical_gradient(f, x)
        x -= lr * grad
    return x

 def function_2(x):
        return x[0]**2 + x[1]**2
   
init_x = np.array([-3.0, 4.0])
gradient_descent(function_2, init_x=init_x, lr=0.1, step_num=100)  # 得到损失函数最小值对应的坐标点(0, 0),array([ -6.11110793e-10, 8.14814391e-10])

f是要进行最优化的函数,,init_x是初始值,lr是学习率learning rate,step_num是梯度法的重复次数。在上面的例子中,学习率设置为0.1。学习率设置的过大或过小对于损失函数的收敛都不利,因此选取合适的学习率也是神经网络超参数的一个重要部分。与神经网络的权重和偏置不同,学习率需要人为设定。如何理解学习率过大过小对损失函数收敛的影响呢?现在我们将损失函数想象成一口大铁锅,锅底的位置就是损失函数达到最小值的地方。当学习率设置的过小时,此时可以看成是放了一只小蚂蚁在锅的外边缘,步子很小,它需要走很多步才能走到底部,耗时长且效率慢,而且有可能陷入“局部最优”。而学习率过大则可以想象成是跳蚤,它每次向前运动的幅度很大,仅略小于锅的尺寸,它会在锅的侧壁来回弹跳,而到达不了锅底。

5.神经网络的梯度

神经网络在学习的过程中也要进行梯度的计算。以一个只有一个形状为2 × 3的权重W的神经网络为例,它的损失函数用L表示,那么梯度

\frac{\partial L}{\partial W}\\

可表示为如下:

\begin{gathered} \boldsymbol{W} \left.=\left(\begin{array}{ccc}w_{11}&w_{12}&w_{13}\\w_{21}&w_{22}&w_{23}\end{array}\right.\right) \\ \begin{aligned}\frac{\partial L}{\partial\boldsymbol{W}}\end{aligned} \left.=\left(\begin{array}{ccc}\frac{\partial L}{\partial w_{11}}&\frac{\partial L}{\partial w_{12}}&\frac{\partial L}{\partial w_{13}}\\\frac{\partial L}{\partial w_{21}}&\frac{\partial L}{\partial w_{22}}&\frac{\partial L}{\partial w_{23}}\end{array}\right.\right)  \end{gathered} \\

求梯度代码实现:

import sys, os
import numpy as np

def softmax(x):
    if x.ndim == 2:
        x = x.T
        x = x - np.max(x, axis=0)
        y = np.exp(x) / np.sum(np.exp(x), axis=0)
        return y.T 

    x = x - np.max(x) # 溢出对策
    return np.exp(x) / np.sum(np.exp(x))

def cross_entropy_error(y, t):
    if y.ndim == 1:
        t = t.reshape(1, t.size)
        y = y.reshape(1, y.size)
        
    # 监督数据是one-hot-vector的情况下,转换为正确解标签的索引
    if t.size == y.size:
        t = t.argmax(axis=1)
             
    batch_size = y.shape[0]
    return -np.sum(np.log(y[np.arange(batch_size), t] + 1e-7)) / batch_size

def numerical_gradient(f, x):
    h = 1e-4 # 0.0001
    grad = np.zeros_like(x)
    
    it = np.nditer(x, flags=['multi_index'], op_flags=['readwrite'])
    while not it.finished:
        idx = it.multi_index
        tmp_val = x[idx]
        x[idx] = float(tmp_val) + h
        fxh1 = f(x) # f(x+h)
        
        x[idx] = tmp_val - h 
        fxh2 = f(x) # f(x-h)
        grad[idx] = (fxh1 - fxh2) / (2*h)
        
        x[idx] = tmp_val # 还原值
        it.iternext()   
        
    return grad

class simpleNet:
    def __init__(self):
        self.W = np.random.randn(2,3)

    def predict(self, x):
        return np.dot(x, self.W)

    def loss(self, x, t):
        z = self.predict(x)
        y = softmax(z)
        loss = cross_entropy_error(y, t)

        return loss

x = np.array([0.6, 0.9])
t = np.array([0, 0, 1])

net = simpleNet()

f = lambda w: net.loss(x, t)
dW = numerical_gradient(f, net.W)

print(dW)

结果:

6.神经网络学习的实现流程

完整实现参见《深度学习入门:基于python的理论与实现》第四章第五节的内容。以上是神经网路学习的所有基本概念,包括“mini-batch”、“梯度”、“梯度下降法”等概念。神经网络的学习过程为:

前提:训练数据是均匀的,即是被shuffle(打乱)过的。其次神经网络已经存在较为合适的权重和偏置。

step1:按照mini-batch的方法从训练数据中随机选出一部分数据进行训练。

step2:计算各个权重参数的梯度,梯度表示函数值减小最多的方向。

step3:将权重参数沿梯度方向进行微小更新(lr,学习率)。

step4:重复 step1、step2、step3。

上面使用的数据时从原始数据中随机选择的mini-batch数据,所以又称之为随机梯度下降法(stochastic gradient descent),即对随机选择的数据进行的梯度下降法。在很多深度学习框架中,其一般由一个名为SGD的函数进行实现。为了保证所有的训练数据都被使用,一般做法是事先将所有训练数据随机打乱,然后按指定的批次大小按序生成mini-batch。这样每个mini-batch均有一个索引号,然后用索引号可以遍历所有的mini-batch。遍历一次所有数据,就称为一个epoch

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Spring的事务步骤

一、事务处理方案: Spring框架中提供的事务处理方案:一共有两种: 1.适合中小项目使用的, 注解方案: 注解的方式做事务用起来简单,灵活,方便,中小型项目中用它比较方便&#xff0c…

白酒:酒文化的教育价值与实践

酒文化作为中国传统文化的重要组成部分,具有丰富的教育价值。云仓酒庄的豪迈白酒作为酒文化的品牌之一,在传承与发展中不断挖掘和发挥酒文化的教育价值。 首先,豪迈白酒有责任传承丰富的历史文化知识。从酒的起源、酿造技艺、酒器文化到酒礼酒…

Github上传大于100M的文件(ubuntu教程)

安装Git-lfs Git Large File Storage (LFS) 使用 Git 内部的文本指针替换音频样本、视频、数据集和图形等大文件,同时将文件内容存储在 GitHub.com 或 GitHub Enterprise 等远程服务器上。官网下载:https://git-lfs.github.com/ ./install.sh上传 比如…

教你如何安装 IntelliJ IDEA

安装 IntelliJ IDEA 的步骤通常如下,这里提供的是基于 Windows 系统的安装指南。 下载 IntelliJ IDEA 1. 访问 JetBrains 官方网站:[https://www.jetbrains.com/idea/download/](Download IntelliJ IDEA – The Leading Java and Kotlin IDE) 2. 选择适…

一文带你入门【论文排版】利器·LaTeX |Macos

小罗碎碎念 我在刚开始写公众号的时候,写过一期推文,详细的讲解过如何使用LaTeX快速的进行论文排版。不过当时用的是windows的系统,这一次把Mac端的教程补上。 windows系统教程 https://zhuanlan.zhihu.com/p/677481269 LaTeX是一种流行的排…

【UIDynamic-动力学-UICollisionBehavior-action Objective-C语言】

一、我们说,这个碰撞行为啊,collision,它里边还有一个属性,叫做action,它能够干什么,它能够实时的去监听, 1.实时的去监听,我们当前的这个view的一个frame的变化, 它会调用action的方法,实际上,action方法,它是一个block,然后呢,view的frame变化的时候,它会一直…

Keil生成bin文件

keil软件默认是只生成hex文件虽然也可以下载但是有时候要用到bin文件 只需要加入以下代码在keil软件中即可 fromelf.exe --bin -o “$LL.bin” “#L” 然后编译 输出信息,可以看到已经生成了bin文件

Nacos从入门到实战

一、Nacos介绍 1.什么是Nacos 官方:一个更易于构建云原生应用的动态服务发现(Nacos Discovery)、服务配置(Nacos Config)和服务管理平台 集 注册中心配置中心服务管理 平台 注册中心:把所有的服务注册进去…

第6章 设备驱动程序(3)

目录 6.5 块设备操作 6.5.1 块设备的表示 6.5.2 数据结构 6.5.3 向系统添加磁盘和分区 6.5.4 打开块设备文件 本专栏文章将有70篇左右,欢迎关注,查看后续文章。 6.5 块设备操作 特点: 随机访问任意位置。 固定块大小的传输。 块设备在内…

MySQL进阶——索引【核心】

目录 1索引概述 2索引结构 2.1 B-Tree(多路平衡查找树) 2.2 BTree 2.3 hash 3索引分类 3.1MySQL中分4类 3.2 InnoDB存储引擎分两类(SQL优化中重要) 4索引语法 4.1创建和查看索引 4.2删除索引 5 SQL性能分析 5.1 查看执…

Ubuntu安装docker 详细教程

Ubuntu安装docker,以及docker compose踩了一步一步的坑,真的特别抓马!!! 因此分享我的安装教程和踩坑,希望给大家一些帮助吧 安装详细教程 卸载docker停止 docker 运行使用以下命令来卸载 Docker 软件包及其…

国产数据库中读写分离实现机制

在数据库高可用架构下会存在1主多备的部署,备节点可以根据业务场景分发一部分流量以充分利用资源,并减轻主库的压力,因此在数据库的功能上需要读写分离来实现。 充分利用备节点的资源,提升业务的吞吐量;防止运维等非业…

助力低空经济-eVTOL/无人机ADS-B航管应答机选型指南

一、低空经济概述 “低空经济”在今年全国两会首次写入政府工作报告。近日,工业和信息化部、科学技术部、财政部、中国民用航空局印发《通用航空装备创新应用实施方案(2024—2030年)》,提出到2030年,推动低空经济形成…

c语言回顾-结构体(2)

前言 前面讲了结构体的概念,定义,赋值,访问等知识,本节内容小编将讲解结构体的内存大小的计算以及通过结构体实现位段,话不多说,直接上干货!!! 1.结构体内存对齐 说到计…

自建消息推送工具 Gotify 实现消息私有化通知

本文首发于只抄博客,欢迎点击原文链接了解更多内容。 前言 之前分享了如何通过 Webhook 将 VPS 与 NAS 上部署的应用消息推送到钉钉、飞书、企业微信,但是对于部分用户来说,可能因为以下种种原因,不方便使用常见的办公 IM 软件来进行消息推送: 消息涉及隐私敏感信息,不希…

11.6.k8s实战-节点扩缩容

目录 一,需求描述 二、集群缩容-节点下线 1,节点下线案例说明 2,查看现有节点 3,查看所有名称空间下的pod ​编辑4,驱逐下线节点的pod 5,驱逐后再次查看pod 6,驱逐pod后再次查看节点信息…

新书速览|Ubuntu Linux运维从零开始学

《Ubuntu Linux运维从零开始学》 本书内容 Ubuntu Linux是目前最流行的Linux操作系统之一。Ubuntu的目标在于为一般用户提供一个最新的、相当稳定的、主要由自由软件构建而成的操作系统。Ubuntu具有庞大的社区力量,用户可以方便地从社区获得帮助。《Ubuntu Linux运…

熟练一种编程语言再学另一种语言时,叠的是buff还是debuff?

在大多数情况下,尤其是对于广泛使用的高级编程语言,它们之间存在正向的相互促进作用,熟练使用一种语言后再去学习另一种语言,大概率能叠个buff。 首先,学习编程语言的基础是通用的,比如软硬件和网络基础、算…

iOS原生APP开发的技术难点

iOS原生APP开发的技术难点主要体现在以下几个方面,总而言之,iOS原生APP开发是一项技术难度较高的工作,需要开发者具备扎实的编程基础、丰富的开发经验和良好的学习能力。北京木奇移动技术有限公司,专业的软件外包开发公司&#xf…

shell中的条件判断

在Linux操作系统中如何是用条件判断语句, 如上图所示,先定义一个变量变量值,再使用test $a hello来判断式子的正确与否,当结果正确的时候返回0,当结果错误时候结果返回1,可以是用echo $? 来获取并打印输出…