python实现微分函数,两种计算方式对比,一个误区

23 篇文章 1 订阅
21 篇文章 1 订阅

v1是f(x+h)-f(x)的版本,不加后缀的版本是f(x+h)-f(x-h)的,就是所谓左右两侧更精准的那个版本,但是做对比的时候,直觉上有些问题存在,如果是f(x)=x**2,是变化的斜率,左右两侧同时计算差值是可能带来更精准的计算,但是永远都是么?f(x)=2*x呢?f(x+h)-f(x-h)和f(x+2h)-f(x)有什么区别?所以就有了v1_2版本和不加后缀版本函数的对比

#https://blog.csdn.net/huqinweI987/article/details/102858397
import numpy as np

def numerical_diff_v1(x,f):
    h = 1e-4#1e-50 useless,because of underflow
    # debug_a = f(x+h)
    # debug_b = f(x)
    return (f(x+h)-f(x)) / h
def numerical_diff_v1_2(x,f):#v1 is not fair
    h = 1e-4#-50 useless
    # debug_a = f(x+h)
    # debug_b = f(x)
    # return (f(x+2*h)-f(x)) / 2*h#wrong expression,this will multiply by h
    return (f(x+2*h)-f(x)) / (2*h)
def numerical_diff(x,f):#new
    h = 1e-4
    return (f(x+h) - f(x-h)) / (2*h)


def func(x):
    y = 2*x
    return y
def func2(x):
    y = x**2
    return y
def func3(x):
    # print(0.01*x**2)
    return 0.01*x**2 + 0.1*x



x = 5
analytic_diff = 2
analytic_diff2 = 2*x
analytic_diff3 = 0.01*x + 0.1
print('func3:',func3(1))
print('func3:',func3(2))

print('func3 diff:',numerical_diff(x,func3))#1.9999999999908982e-09   0.1999999999990898
print('func3 diff:',numerical_diff_v1(x,func3))#func3 diff: 0.20000099999917254
print('func3 diff:',numerical_diff_v1_2(x,func3))




print('################################################\nfunc2:')
diff_v1 = numerical_diff_v1(x,func2)
diff = numerical_diff(x,func2)
diff_v1_v2 = numerical_diff_v1_2(x,func2)
print('diff:'.rjust(10),diff)
print('diff_v1:'.rjust(10),diff_v1)
print('diff_v1_2:'.rjust(10),diff_v1_v2)
if np.abs(diff - analytic_diff2) < np.abs(diff_v1 - analytic_diff2):
    print('the new diff are more accuracy than diff_v1!')

elif np.abs(diff - analytic_diff2) == np.abs(diff_v1 - analytic_diff2):
    print('draw')
else:
    print('ah')

if np.abs(diff - analytic_diff2) < np.abs(diff_v1_v2 - analytic_diff2):
    print('the new diff are more accuracy than diff_v1_v2!')

elif np.abs(diff - analytic_diff2) == np.abs(diff_v1_v2 - analytic_diff2):
    print('draw')
else:
    print('ah')

print('################################################\nfunc:')

diff_v1 = numerical_diff_v1(x,func)
diff = numerical_diff(x,func)
diff_v1_v2 = numerical_diff_v1_2(x,func)

print('diff:'.rjust(10),diff)
print('diff_v1:'.rjust(10),diff_v1)
print('diff_v1_2:'.rjust(10),diff_v1_v2)
if np.abs(diff - analytic_diff) < np.abs(diff_v1 - analytic_diff):
    print('the new diff are more accuracy than diff_v1!')
elif np.abs(diff - analytic_diff) == np.abs(diff_v1 - analytic_diff):
    print('draw')
else:
    print('ah')


if np.abs(diff - analytic_diff) < np.abs(diff_v1_v2 - analytic_diff):
    print('the new diff are more accuracy than diff_v1_2!')
elif np.abs(diff - analytic_diff) == np.abs(diff_v1_v2 - analytic_diff):
    print('draw!!!!!!!!!!!!!!!!!!!!')
else:
    print('ah,reverse!!!!!!!!!!!!!!!!')
# print('np.abs(diff - analytic_diff) < np.abs(diff_v1 - analytic_diff):',np.abs(diff - analytic_diff),np.abs(diff_v1 - analytic_diff),np.abs(diff - analytic_diff) < np.abs(diff_v1 - analytic_diff))



print('################################################\nfunc3:')
diff_v1 = numerical_diff_v1(x,func3)
diff = numerical_diff(x,func3)
diff_v1_v2 = numerical_diff_v1_2(x,func3)
print('diff:'.rjust(10),diff)
print('diff_v1:'.rjust(10),diff_v1)
print('diff_v1_2:'.rjust(10),diff_v1_v2)
if np.abs(diff - analytic_diff3) < np.abs(diff_v1 - analytic_diff3):
    print('the new diff are more accuracy than diff_v1!')
elif np.abs(diff - analytic_diff3) == np.abs(diff_v1 - analytic_diff3):
    print('draw')
else:
    print('ah')
# print('np.abs(diff - analytic_diff3) * 100 < np.abs(diff_v1 - analytic_diff3):',np.abs(diff - analytic_diff3) * 100 < np.abs(diff_v1 - analytic_diff3))


if np.abs(diff - analytic_diff3) < np.abs(diff_v1_v2 - analytic_diff3):
    print('the new diff are more accuracy than diff_v1_2!')
elif np.abs(diff - analytic_diff3) == np.abs(diff_v1_v2 - analytic_diff3):
    print('draw')
else:
    print('ah')











#maybe multiply by 10 is a error,makes no sense
# print(10e-50)
# print(1e-49)
# print(10e-50 == 1e-49)
# print(np.float32(10e-50))
# print(np.float64(10e-50))
# test = 10e-50
# print(type(test))

实测是没区别的,实际结果,和diff_v1打平,和diff_v1_2比反倒不如(可能只是实现上的精度问题,暂时理解为差不多)。

func:
     diff: 1.9999999999953388
  diff_v1: 1.9999999999953388
diff_v1_2: 2.0000000000042206
draw
ah,reverse!!!!!!!!!!!!!!!!

至于f(x)=x**2,当然,仍然是新版本更精确。

 

测这个是因为,一些教材和人,在这个问题的说明上,至少是不严谨的(用2h的距离对比h的距离,至少是不公平的)。当然,这只是一个简单的验证,说明要多思考,实际上为了更广泛的适应性,肯定还是非线性的情况更多,也就是最后那个版本效果更好。

 

本文相关所有代码

https://github.com/huqinwei/python_deep_learning_introduction/

 

 

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值