
目录标题一、数值微分概念二、数值微分代码三、偏导数四、梯度(基础知识在机器学习就该知道了)五、利用数值微分求梯度代码一、数值微分概念损失函数的值越小代表我们选取的参数越适合想要求得损失函数的最小值最基本的想法就是对函数求导解出导数值为 0 的点并判断它是否为极小值/最小值。然而实际的函数直接求导不容易得到解析解。这时可以用数值微分的方式来求某点处的导数这在工程上应用非常广泛。二、数值微分代码# 数值微分求导传入x时一个标量defnumerical_diff(f,x):h1e-4# 微小值 0.0001return(f(xh)-f(x-h))/(2*h)在这里我们以 x 为中心计算它两边各发生微小变化后的差分可以避免只计算单向增大时的误差。这种方法称为中心差分。另外取微小值 h 时不能太小这会导致计算机浮点数表示的精度不够出现舍入误差。利用数值微分求导测试代码函数y 0.01x^2 0.1x 在 x5 处的导数y ′ 0.02 x 0.1 y 0.02x 0.1y′0.02x0.1箭头指向0.02 x 0.02x0.02x处x 5 x 5x5importnumpyasnpimportmatplotlib.pyplotaspltfromcommon.gradientimportnumerical_diff# 原函数 y 0.01x^2 0.1xdeff(x):return0.01*x**20.1*x# 切线方程函数返回切线函数 y ax bdeftangent_line(f,x):yf(x)# 计算x处切线的斜率利用数值微分计算x处的导数anumerical_diff(f,x)print(切线斜率为: ,a)# 根据切线过(x, y)点计算截距by-a*xreturnlambdax:a*xb# 定义画图范围xnp.arange(0.0,20.0,0.1)yf(x)# 计算x5处的切线方程f_linetangent_line(f,x5)y_linef_line(x)plt.plot(x,y)# 原函数曲线plt.plot(x,y_line)# 切线# plt.show()plt.savefig(tangent_line_result.png)三、偏导数可将其中一个元素x xx看作参数此时f ff可看作关于另一元素y yy的函数。f a ( y ) x 2 x y y 2 f_a(y) x^2 xy y^2fa(y)x2xyy2在x a x axa固定的情况下可计算f x f_xfx关于y yy的导数。f a ′ ( y ) a 2 y f_a(y) a 2yfa′(y)a2y这种导数称为偏导数一般记作∂ f ∂ y ( x , y ) x 2 y \frac{\partial f}{\partial y}(x, y) x 2y∂y∂f(x,y)x2y更一般地来说一个多元函数f ( x 1 , x 2 , ⋯ , x n ) f(x_1, x_2, \cdots, x_n)f(x1,x2,⋯,xn)在点( a 1 , a 2 , ⋯ , a n ) (a_1, a_2, \cdots, a_n)(a1,a2,⋯,an)处对x i x_ixi的偏导数定义为∂ f ∂ x i ( a 1 , a 2 , ⋯ , a n ) lim Δ x i → 0 f ( a 1 , ⋯ , a i Δ x i , ⋯ , a n ) − f ( a 1 , ⋯ , a i , ⋯ , a n ) Δ x i \frac{\partial f}{\partial x_i}(a_1, a_2, \cdots, a_n) \lim_{\Delta x_i \to 0} \frac{f(a_1, \cdots, a_i \Delta x_i, \cdots, a_n) - f(a_1, \cdots, a_i, \cdots, a_n)}{\Delta x_i}∂xi∂f(a1,a2,⋯,an)Δxi→0limΔxif(a1,⋯,aiΔxi,⋯,an)−f(a1,⋯,ai,⋯,an)偏导数同样也可以用数值微分的方式来求即只改变一个自变量、其它不变做差分考察函数值的变化率。四、梯度(基础知识在机器学习就该知道了)多元函数f ( x 1 , … , x n ) f(x_1, \dots, x_n)f(x1,…,xn)关于每个变量x i x_ixi都有偏导数∂ f ∂ x i \frac{\partial f}{\partial x_i}∂xi∂f在点a aa处这些偏导数定义了一个向量。∇ f ( a ) [ ∂ f ∂ x 1 ( a ) , … , ∂ f ∂ x n ( a ) ] \nabla f(a) \left[ \frac{\partial f}{\partial x_1}(a), \dots, \frac{\partial f}{\partial x_n}(a) \right]∇f(a)[∂x1∂f(a),…,∂xn∂f(a)]这个向量称为f ff在点a aa的梯度。例如f ( x , y ) x 2 x y y 2 f(x, y) x^2 xy y^2f(x,y)x2xyy2在( 1 , 1 ) (1,1)(1,1)处的梯度为[ 3 , 3 ] [3, 3][3,3]。在函数的极小值、极大值和鞍点处梯度为 0。需要注意的是梯度代表的其实是函数值增大最快的方向在实际应用中我们需要寻找损失函数的最小值所以一般选择负梯度向量。同样地负梯度代表的是函数值减小最快的方向并不一定直接指向函数图像的最低点。五、利用数值微分求梯度代码importnumpyasnp# 数值微分求梯度传入x是一个向量# 这个函数其实是在做多元函数的数值偏导每次只针对一个维度做微小的改变其他维度保持原样# 比如传入 x [3,4,6,77] x.size 4,循环四次 以i0为例# * tmp x[0]此时 tmp 保存了 3为了后面恢复用。# * x[0] tmp h现在 x 变成了 [3 h, 4, 6, 77]。# * fxh1 f(x)算出了点 x[0] h 处的函数值。# * x[0] tmp - h现在 x 变成了 [3 - h, 4, 6, 77]。# * fxh2 f(x)算出了点 x[0] - h 处的函数值。# * grad[0] (fxh1 - fxh2) / (2 * h)用中心差分公式算出了对第一个变量 $x_1$ 的偏导数。# * x[0] tmp把 x 恢复成 [3, 4, 6, 77]。def_numerical_gradient(f,x):h1e-4gradnp.zeros_like(x)# 遍历x中的特征xi(在求偏导时候,要改变当前xi,改完要还原不防止可能影响别的偏导)foriinrange(x.size):tmpx[i]x[i]tmph fxh1f(x)x[i]tmp-h fxh2f(x)# 利用中心差分公式计算偏导数grad[i](fxh1-fxh2)/(2*h)# 恢复x[i]的值x[i]tmpreturngrad# 传入X是一个矩阵# 加入传入的是 W 是(2,4)矩阵 调用两次_numerical_gradient,每次传入向量(4,)就是一维数组里面四个权重参考_numerical_gradient的举例。# 也就说一个W (2,4)矩阵算梯度要循环8次每次执行两次前向传播defnumerical_gradient(f,X):# 判断维度ifX.ndim1:return_numerical_gradient(f,X)else:gradnp.zeros_like(X)# 遍历X中的每一行数据分别求梯度fori,xinenumerate(X):grad[i]_numerical_gradient(f,x)returngrad