人工智能数据基础之微积分入门-学习篇

Zorione 2024-09-17 17:07:01 阅读 82

目录

导数概念常见导数和激活导数python代码绘制激活函数微分概念和法则、积分概念微积分切线切面代码生成案例链式求导法则反向传播算法(重要)

一、概念

在这里插入图片描述

二、常见导数及激活导数

在这里插入图片描述

常见激活函数及其导数公式:

在神经网络中,激活函数用于引入非线性因素,使得神经网络能够拟合更加复杂的数据分布。没有激活函数的神经网络本质上只是一个线性模型,而添加了非线性激活函数后,神经网络可以表示非线性的决策边界。使得网络能够解决复杂的非线性问题。

在这里插入图片描述

在这里插入图片描述

三、python绘制以上激活函数

sigmoid函数:

Sigmoid函数将输入值映射到(0, 1)之间,常用于二分类问题的输出层。然而,它容易出现梯度消失问题,特别是在输入值接近0或1时,梯度接近于0,导致网络训练缓慢。

<code>import numpy as np

import matplotlib.pyplot as plot

#sigmoid公式

def sigmoid(x):

return 1/(1+np.exp(-x))

#绘制图形方法 func数学公式,可变参数x,图形标题title

def plot_activation_function(func,x,title):

y = func(x)

plot.plot(x,y) #传入x 和y

plot.title(title) #设置标题

plot.xlabel('x') #x轴

plot.ylabel('y') #y轴

plot.grid() #网格线

plot.show()

x_value = np.arange(-10,10,0.1) #x取值范围,-10 - 10 步长0.1

plot_activation_function(sigmoid,x_value,'sigmoid')

运行如下:

在这里插入图片描述

tanh函数:

Tanh函数将输入值映射到(-1, 1)之间,输出均值为0,有助于中心化数据。与Sigmoid函数类似,它也容易出现梯度消失问题,但程度相对较轻。

<code>import numpy as np

import matplotlib.pyplot as plot

#tanh公式 双曲正切函数(Tanh函数)

def tanh(x):

return np.tanh(x)

#绘制图形方法 func数学公式,可变参数x,图形标题title

def plot_activation_function(func,x,title):

y = func(x)

plot.plot(x,y) #传入x 和y

plot.title(title) #设置标题

plot.xlabel('x') #x轴

plot.ylabel('y') #y轴

plot.grid() #网格线

plot.show()

x_value = np.arange(-10,10,0.1) #x取值范围,-10 - 10 步长0.1

plot_activation_function(tanh,x_value,'tanh')

结果如下:

在这里插入图片描述

ReLU函数:

ReLU函数简单高效,能够解决梯度消失问题(在正数区域)。然而,它存在神经元“死亡”问题,即当输入小于0时,梯度为0,导致神经元无法更新。

<code>import numpy as np

import matplotlib.pyplot as plot

#ReLU函数(Rectified Linear Unit)

def relu(x):

return np.maximum(0, x)

#绘制图形方法 func数学公式,可变参数x,图形标题title

def plot_activation_function(func,x,title):

y = func(x)

plot.plot(x,y) #传入x 和y

plot.title(title) #设置标题

plot.xlabel('x') #x轴

plot.ylabel('y') #y轴

plot.grid() #网格线

plot.show()

x_value = np.arange(-10,10,0.1) #x取值范围,-10 - 10 步长0.1

plot_activation_function(relu,x_value,'ReLU')

执行如下:

在这里插入图片描述

Leaky ReLU函数:

Leaky ReLU函数通过引入一个小的斜率α,解决了ReLU函数中的“死亡”问题。它保留了ReLU函数的优点,同时避免了神经元无法更新的问题。

alpha=0.01是可变的,值可以根据实际情况定义

<code>import numpy as np

import matplotlib.pyplot as plot

# Leaky ReLU函数

def leaky_relu(x,alpha=0.01):

return np.where(x > 0, x, x*alpha) #x >0时,返回x,否则 x*0.01

#绘制图形方法 func数学公式,可变参数x,图形标题title

def plot_activation_function(func,x,title):

y = func(x)

plot.plot(x,y) #传入x 和y

plot.title(title) #设置标题

plot.xlabel('x') #x轴

plot.ylabel('y') #y轴

plot.grid() #网格线

plot.show()

x_value = np.arange(-10,10,0.1) #x取值范围,-10 - 10 步长0.1

plot_activation_function(leaky_relu,x_value,'leaky_relu')

返回结果:

在这里插入图片描述

#ELU函数(Exponential Linear Unit):

ELU函数融合了ReLU和Leaky ReLU的优点,具有负数饱和区域,对噪声有一定的鲁棒性。然而,其计算量相对较大,因为包含指数运算。

<code>import numpy as np

import matplotlib.pyplot as plot

#ELU函数(Exponential Linear Unit)

def elu(x,alpha=1):

return np.where(x > 0, x, alpha*(np.exp(x) - 1))

#绘制图形方法 func数学公式,可变参数x,图形标题title

def plot_activation_function(func,x,title):

y = func(x)

plot.plot(x,y) #传入x 和y

plot.title(title) #设置标题

plot.xlabel('x') #x轴

plot.ylabel('y') #y轴

plot.grid() #网格线

plot.show()

x_value = np.arange(-10,10,0.1) #x取值范围,-10 - 10 步长0.1

plot_activation_function(elu,x_value,'elu')

结果如下:

在这里插入图片描述

四:微分、积分

1. 微分的定义:

微分是求函数在某一点的变化率。

在这里插入图片描述

2. 微分的三个法则:

在微积分中,微分(导数)的加法法则、乘法法则和除法法则(也称为商的导数法则)是求解复合函数导数的基本工具。这些法则允许我们将复杂的函数分解为更简单的部分,并分别求导,然后再以特定的方式组合起来。

在这里插入图片描述

3. 积分

在这里插入图片描述

定积分

在这里插入图片描述

的值就是这个封闭图形的面积。

在这里插入图片描述

五、微积分切线切面代码生成案例

1. 用Python展示二维图像的切线

用代码绘制x^2的函数图像,并绘制函数在x=1处的切线

在这里插入图片描述

Python代码如下

<code>import numpy as np

import matplotlib.pyplot as plt

#定义一个函数f(x) 求x平方的函数

def f(x):

return x ** 2

#定义函数的导数

def df(x):

return 2 * x

#绘制原始函数 定义x的取值范围,中间均匀拆分出100个点

x = np.linspace(-3,3,100)

y = f(x) #y是要求导的这条曲线

#设置画面大小 8 * 6 的尺寸比例

plt.figure(figsize=(8,6))

#绘制图像添加标注

plt.plot(x,y,label='f(x) = x^2')code>

#计算x = 1时的导数和切线

x1 = 1

y1 = f(x1)

scope = df(x1) #导数

#切线方程 y = m(x-x1) + y1

def tangent_line(x,x1,y1,scope):

return scope * (x - x1) + y1

#在切点附近绘制切线

x_tangent = np.linspace(x1 -1,x1 + 1,10) #限定切线x轴的范围

y_tangent = tangent_line(x_tangent,x1,y1,scope) #切线y轴的范围

#绘制切线图像,添加标题

plt.plot(x_tangent,y_tangent,label='tangent at x = 1',color='red')code>

plt.scatter([x1],[y1],color='black') #定义标注切点颜色code>

#设置图像

plt.legend() #展示图线的label

plt.xlabel("x") #定义x轴名称

plt.ylabel("f(x)") #y轴名称

plt.title("Function and Tangent Line at a Point") #图片标题

plt.grid(True) #显示网格

plt.show()

2. 展示三维函数切面

用代码绘制以下三维图像,并绘制出三维图像的切面

在这里插入图片描述

Python代码如下:

<code>import matplotlib.pyplot as plt

import numpy as np

#创建x,y数据点

# -5 - 5,中间拆分成100段

x = np.linspace(-5,5,100)

y = np.linspace(-5,5,100)

#把x,y放入meshgrid,生成网格坐标矩阵

x,y = np.meshgrid(x,y)

#定义三维函数

def f(x,y):

return x ** 2 + y ** 2

#计算z的值 z是三维图形的高度

z = f(x,y)

#创建图形和轴

fig = plt.figure() #创建一个图形

#111代表在图像的第一行第一列第一个位置添加一个图,在这个图上画三维图像

ax = fig.add_subplot(111,projection='3d')code>

#绘制表面 plot_surface用来绘制三维图 颜色使用viridis alpha代表画面的透明度

surf = ax.plot_surface(x,y,z,cmap="viridis",alpha=0.5)code>

#定义要突出显示的点 曲面和切面相交的点的x轴和y轴的值

point_x,point_y = 1.0,1.0

point_z = f(point_x,point_y) #z轴的值

#绘制出该相交的点位,s=50代表点大小为50

ax.scatter(point_x,point_y,point_z,color='red',s=50)code>

#为了方便画出切面,需先算出切面的法线

normal = np.array([2*point_x,2*point_y,-1])

#定义平面上的所有点,x_plane,y_plane,z_plane

x_plane = np.linspace(-5,5,10)

y_plane = np.linspace(-5,5,10)

#把x_plane y_plane转化为网格点坐标

x_plane,y_plane = np.meshgrid(x_plane,y_plane)

#normal[0]代表x轴的变量, normal[1] y轴变量 normal[2] z轴变量

z_plane = (-normal[0] * (x_plane-point_x) - normal[1] * (y_plane-point_y) /normal[2] + point_z)

#绘制切平面

ax.plot_surface(x_plane,y_plane,z_plane,color='yellow',alpha=0.5)code>

#设置标题和坐标轴

ax.set_xlabel('x asis')

ax.set_ylabel('y asis')

ax.set_zlabel('z asis')

ax.set_title("3D Surface Plot with Tangent Plane")

plt.show()

六、链式求导法则

在这里插入图片描述

七、反向传播算法

简介

反向传播算法(Backpropagation Algorithm),简称BP算法,是一种用于训练人工神经网络(Artificial Neural Network, ANN)的常用且有效的算法。它建立在梯度下降法的基础上,通过计算网络预测与实际结果之间的误差,并将这个误差反向传播到网络中的每一层,从而调整网络中每个权重的值,以逐步优化网络的学习过程。

反向传播算法的基本原理

反向传播算法的基本原理是利用链式法则(Chain Rule)进行求导。在神经网络中,数据通过前向传播得到预测输出,然后计算预测输出与真实标签之间的损失(或误差)。接着,通过反向传播算法,将损失从输出层向输入层逐层反向传播,计算每一层权重和偏置的梯度。最后,利用这些梯度来更新网络的参数,以减小损失。

反向传播算法步骤概述

前向传播: 首先,给定一个输入样本,按照当前网络的权重和偏置,通过每一层传递这个输入,直到最后一层,得到网络的预测输出。

计算损失: 使用损失函数(如均方误差或交叉熵)计算网络预测输出与实际目标输出之间的差异。

梯度计算: 通过链式法则计算损失函数相对于每个权重的梯度。这个过程从输出层开始,向后传播到输入层。在每一步中,都会计算当前层的误差项(也称为局部梯度),然后根据当前层的权重将误差分配给前一层。

权重更新: 一旦得到了每个权重的梯度,就可以使用某种形式的梯度下降法(例如批量梯度下降、随机梯度下降或小批量梯度下降)来调整权重,使损失函数减少。

反向传播算法的关键要素

学习率(Learning Rate): 决定了参数更新的步长,过大的学习率可能导致震荡,过小的学习率可能导致收敛速度过慢。

激活函数(Activation Function): 影响神经元的输出,常见的激活函数包括sigmoid、ReLU等。

损失函数(Loss Function): 衡量网络预测输出与真实标签之间的差距,常见的损失函数包括均方误差(MSE)和交叉熵损失函数。

梯度下降(Gradient Descent): 利用梯度信息来更新网络参数的优化算法

这里我画了一个三层的神经元,x1,x2代表输入,y代表输出,z1,z2,z3代表中间变量

在这里插入图片描述

计算过程:

在这里插入图片描述

在这里插入图片描述

梯度更新计算:

在这里插入图片描述

重新进行前向传播:

在这里插入图片描述

使用Python代码实现上述神经网络的反向传播

<code>

#模型参数初始化

def param_init():

# 定义权重

w_1_11 = 0.5

w_1_12 = 0.5

w_1_13 = 0.5

w_1_21 = 0.5

w_1_22 = 0.5

w_1_23 = 0.5

w_2_11 = 1.0

w_2_21 = 1.0

w_2_31 = 1.0

layer_1_list = [w_1_11, w_1_12, w_1_13, w_1_21, w_1_22, w_1_23]

layer_2_list = [w_2_11,w_2_21,w_2_31]

return layer_1_list, layer_2_list

#前向传播的函数 输出预测输出

def forword_porpagation(layer_1_list, layer_2_list):

w_1_11, w_1_12, w_1_13, w_1_21, w_1_22, w_1_23 = layer_1_list

w_2_11, w_2_21, w_2_31 = layer_2_list

# 前向传播

z_1 = x_1 * w_1_11 + x_2 * w_1_21

z_2 = x_1 * w_1_12 + x_2 * w_1_22

z_3 = x_1 * w_1_13 + x_2 * w_1_23

y_pred = z_1 * w_2_11 + z_2 * w_2_21 + z_3 * w_2_31

return y_pred

#计算损失值 网络的输出和真实值相多少

def compute_loss(y_true, y_pred):

loss = 0.5 * (y_true - y_pred) ** 2

return loss

#反向传播

def backword_propagation(layer_1_list, layer_2_list,learning_rate):

w_1_11, w_1_12, w_1_13, w_1_21, w_1_22, w_1_23 = layer_1_list

w_2_11, w_2_21, w_2_31 = layer_2_list

z_1 = x_1 * w_1_11 + x_2 * w_1_21

z_2 = x_1 * w_1_12 + x_2 * w_1_22

z_3 = x_1 * w_1_13 + x_2 * w_1_23

# 计算输出层关于损失函数的梯度

d_loss_predictied_output = -(expected_out - y_pred)

# 计算权重关于损失函数的梯度

d_loss_w_2_11 = d_loss_predictied_output * z_1

d_loss_w_2_21 = d_loss_predictied_output * z_2

d_loss_w_2_31 = d_loss_predictied_output * z_3

d_loss_w_1_11 = d_loss_predictied_output * w_2_11 * x_1

d_loss_w_1_21 = d_loss_predictied_output * w_2_11 * x_2

d_loss_w_1_12 = d_loss_predictied_output * w_2_21 * x_1

d_loss_w_1_22 = d_loss_predictied_output * w_2_21 * x_2

d_loss_w_1_13 = d_loss_predictied_output * w_2_31 * x_1

d_loss_w_1_23 = d_loss_predictied_output * w_2_31 * x_2

# 使用梯度下降法更新权重

learning_rate = 1e-5

w_2_11 -= learning_rate * d_loss_w_2_11

w_2_21 -= learning_rate * d_loss_w_2_21

w_2_31 -= learning_rate * d_loss_w_2_31

w_1_11 -= learning_rate * d_loss_w_1_11

w_1_12 -= learning_rate * d_loss_w_1_12

w_1_13 -= learning_rate * d_loss_w_1_13

w_1_21 -= learning_rate * d_loss_w_1_21

w_1_22 -= learning_rate * d_loss_w_1_22

w_1_23 -= learning_rate * d_loss_w_1_23

layer_1_list = [w_1_11, w_1_12, w_1_13, w_1_21, w_1_22, w_1_23]

layer_2_list = [w_2_11,w_2_21,w_2_31]

return layer_1_list, layer_2_list

if __name__ == '__main__':

# 定义输入值和期望输出

x_1 = 40.0

x_2 = 80.0

expected_out = 60.0 # 期望输出值

learning_rate = 1e-5

epoch = 100

#初始化定义权重

layer_1_list, layer_2_list = param_init()

for i in range(epoch):

y_pred = forword_porpagation(layer_1_list, layer_2_list)

print(f"前向传播预测值为{ y_pred}")

loss = compute_loss(expected_out, y_pred)

print(f"当前的Loss值为{ loss}")

layer_1_list, layer_2_list = backword_propagation(layer_1_list, layer_2_list, learning_rate)

结果如下图所示:

在这里插入图片描述

一直到:

在这里插入图片描述

可以看到经过100次循环,损失值越来越小, 网络的输出和真实值相差无限接近,达到了最终的目的。



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。