深度学习笔记---梯度法简单介绍与实现

# 1.导入

偏导数

详细介绍参考百度百科https://baike.baidu.com/item/%E5%81%8F%E5%AF%BC%E6%95%B0/5536984?fr=aladdin

求f(x0,x1,x2)关于x0的偏导数,就是将x1,x2看作常数再对x0求导。

利用定义求偏导可用如下数学式表示

深度学习笔记---梯度法简单介绍与实现_第1张图片

这也就是数值微分。数值微分就是利用微小的差分求导数的过程。

梯度

详细介绍参考百度百科https://baike.baidu.com/item/%E6%A2%AF%E5%BA%A6/13014729?fr=aladdin

求f(x0,x1,x2)的梯度,就是求由x0,x1,x2(全部变量)的偏导数汇总而成的向量,即如下图所示的向量

深度学习笔记---梯度法简单介绍与实现_第2张图片

根据高等数学,我们可知梯度指示的方向是各点处的函数值减小最多的方向。(这有利于我们找到使损失函数值最小的权重参数)

求梯度函数的实现如下:

import numpy as np

# 计算梯度的函数
def numerical_gradient_1d(f,x):              # 入口参数为待求导函数f和变量数组x  (所求梯度就是一个由函数f关于各个变量的偏导数组成的数组)
	h = 1e-4                             # 定义微小值h为0.0001(便于直接使用定义求偏导数)
	grad = np.zeros_like(x)              # 生成和x形状相同且所有元素都为0的数组grad 
    
	for idx in range(x.size):            # 依次取每一个变量的数组下标
	    tmp_val = x[idx]                 # 记录第idx个元素的数值,存放在tmp_val变量中

	    x[idx] = tmp_val + h             # 将x[idx]修改为tmp_val+h
	    fxh1 = f(x)                      # 对当前x数组求f函数值,得到函数值fxh1(表示f(x+h),实际上这里的x+h表示仅x[idx]加了h后得到的数组)
        
	    x[idx] = tmp_val - h             # 将x[idx]修改为tmp_val-h
	    fxh2 = f(x)                      # 对当前x数组求f函数值,得到函数值fxh2(表示f(x-h),实际上这里的x-h表示仅x[idx]减了h后得到的数组)
        
	    grad[idx] = (fxh1 - fxh2)/(2*h)  # 求得x[idx]的偏导数,放入梯度数组第idx单元
	    x[idx] = tmp_val                 # 将x[idx]恢复原值,为求下一个变量的偏导数做准备
  
	return grad

 

# 2.梯度法的具体介绍

梯度法就是通过巧妙地使用梯度来寻找函数取得最小值(或者尽可能小的值)时对应的参数。


具体而言使用梯度法就是指通过不断地沿梯度方向前进,逐渐减小函数值的过程。(由于梯度指示方向不一定是函数最小值,所以需要不断重复(根据参数求梯度,根据梯度更新参数)这个过程)

梯度法的数学式表示

深度学习笔记---梯度法简单介绍与实现_第3张图片

其中的η表示学习率,它决定在一次学习中应该学习多少(即在多大程度上更新参数)。学习率是个超参数,是需要人为设定的。

梯度下降法的实现如下:

from numerical_gradient import numerical_gradient_1d

def gradient_descent(f, init_x, lr=0.01, step_num=100):     # 入口参数中,f表示待求梯度函数,init_x表示参数初始值,lr=0.01表示学习率默认设定为0.01,step_num=100表示参数学习次数默认设定为100
	x = init_x
	
	for i in range(step_num):                # i从0到99,进行100次循环(学习)
		grad = numerical_gradient_1d(f,x)    # 根据参数,求梯度
		x -= lr*grad                         # 根据梯度,更新参数
	
	return x    #返回学习到的参数

举个例子:请用梯度法求使f(x0+x1) = x0^2 + x1^2取到最小值时的参数x0,x1

代码实现如下:

import numpy as np
from gradient_descent import gradient_descent

def function1(x):   # 入口参数为一个含两个元素的一维数组,该函数表示x0^2+x1^2
	return x[0]**2 + x[1]**2
	
init_x = np.array([-3.0,4.0])  # 定义参数初始值
x = gradient_descent(function1,init_x=init_x,lr=0.1,step_num=100) # 利用梯度下降法,得到学习到的参数
print(x)

运行结果如下:

最终结果是(-6.1e-10,8.1e-10),即x0为-6.1乘以10的-10次,x1为8.1乘以10的-10次,非常接近正确结果(0,0)了。

 

# 本博客参考了《深度学习入门——基于Python的理论与实现》(斋藤康毅著,陆宇杰译),特在此声明。

 

你可能感兴趣的:(python与深度学习)