返回顶部

请叫我杨先生

导航

Pytorch 2.3.4 预备知识 -积分Calculus

微积分 Calculus

关于那些求导的基础知识我就不细讲了,如果有需要的话请访问:一篇关于微积分入门的文章  So,我们直接从代码开讲

1. 绘制函数 \(y = f(x) = x^3 - \frac{1}{x}\) 和其在\(x = 1\)处切线的图像。

我们先来定义函数和切线

#求导 第一题
def f(x):
    return x**3 - 1/x  
def numerical_lim(f,x):
    return (f(x+h)-f(x))/h 
def tangent_line(f,x):
    #d就是调用numerical_diff求得在x点点导数``
    k=numerical_lim(f,x)
    # 这里直接y=kx+b求截,简单粗暴,y就是截距
    b=f(x)-k*x
    #使用lambda匿名函数,t是形参,':'后是要执行的函数表达式
    return lambda t:k*t+b #返回的是函数形式

h这里我们取0.1就好了,如果想要得到更好的精度的话就得取更小的值。但是要注意当h取到非常小的值但是数据类型不支持的时候,整个计算就会出错,返回0.(比如说我的数据长度只有8个字节,但是我的精度达到了8字节装不下的程度,这时候h=0.)

import numpy as np 
import matplotlib.pyplot as plt 

h=0.1 
x=np.arange(0.0,20.0,0.1)
y=f(x)
plt.xlabel('x')
plt.ylabel('f(x)')
#把函数作为形参时i,传入实参函数时,只要函数名即可,不用()
tf=tangent_line(f,10)
#因为tf返回的是lambda函数,所以要多调一次函数
y2=tf(x)
plt.grid()
plt.plot(x,y)
plt.plot(x,y2)
plt.show()

2. 求函数\(f(\mathbf{x}) = 3x_1^2 + 5e^{x_2}\)梯度。

#第二题
import numpy  as np 

def numerical_grandient(f,x): 
    h = 10e-4 #设置一个合适的 h 
    grad = np.zeros_like(x)      #生成和x形状相同的数组
    for idx in range(x.size):    #计算所有偏导
        tmp_val = x[idx] #第idx个参数 
        x[idx] = tmp_val + h            #要计算的那个自变量加h,其余不变
        fxh1 = f(x)                     #计算f(x+h)

        x[idx] = tmp_val - h           #计算f(x-h)
        fxh2 = f(x)

        grad[idx] = (fxh1 - fxh2) / (2*h)    #计算偏导
        x[idx] = tmp_val
    return grad  

def f(x):          #定义函数:𝑓(𝐱)=x**3+5𝑒**𝑥2
    return 3*x[0]**2 + 5*np.e**x[1]
print(
numerical_grandient(f,np.array([1.0,2.0])),
numerical_grandient(f,np.array([3.0,3.0])))

输出:array([ 6. , 36.94528665])

3. 函数\(f(\mathbf{x}) = \|\mathbf{x}\|_2\)梯度是什么?

#同第二题,只需要将第二题中的函数修改成第二范数的公式就好了 
import numpy as np 
def f(x): # L2范数的函数
    total = 0 
    for i in range(x.size):
        total += np.power(x[i],2)
    return np.power(total,1/2) 

def numerical_grandient(f,x):
    h = 10e-4
    grand = np.zeros_like(x)
    for i in range(x.size): # 计算所有的偏导数 
        tempal_value = x[i] 
        
        x[i] = h + tempal_value
        fxh1 = f(x)
        
        x[i] = tempal_value - h  
        fxh2 = f(x)
        
        grand[i] = (fxh1 - fxh2)/(2*h) 
        x[i] = tempal_value
    return grand 
    
print(numerical_grandient(f,x = np.array([1.0,1.0,3.0])))

输出:[0.30151133 0.30151133 0.90453403]

你可以写出函数\(u = f(x, y, z)\),其中\(x = x(a, b)\)\(y = y(a, b)\)\(z = z(a, b)\)链式法则吗?

import torch
x = torch.tensor(1.2)
a1 = torch.tensor(2.3, requires_grad=True)
b1 = torch.tensor(1.3)
y1 = x * a1 + b1
 
a2 = torch.tensor(2.2)
b2 = torch.tensor(1.4)
y2 = y1 * a2 + b2

a3 = torch.tensor(1.1)
b3 = torch.tensor(2.2)
y3 = y2 * a3 + b3 
 

# PyTorch自动实现链式法则的求导
# dy2_dw1 = torch.autograd.grad(y2, [w1], retain_graph=True)
# print(dy2_dw1[0])
 
# 手动用链式法则的方式求一下看看
dy3_dy2 = torch.autograd.grad(y3, [y1], retain_graph=True)
dy2_dy1 = torch.autograd.grad(y2, [y1], retain_graph=True)
dy1_dw1 = torch.autograd.grad(y1, [a1], retain_graph=True)
print(dy3_dy2[0] * dy2_dy1[0] * dy1_dw1[0])

输出: tensor(6.3888)

posted on 2021-12-12 20:32  YangShusen'  阅读(776)  评论(0编辑  收藏  举报