怎么求导来着?别费劲了,试试这个Python的通用求导法
今天的CSDN問(wèn)答專欄里出現(xiàn)了一個(gè)實(shí)戰(zhàn)中遇到的問(wèn)題:現(xiàn)有兩組數(shù)據(jù),一組是時(shí)間序列,一組是對(duì)應(yīng)時(shí)間序列的旋轉(zhuǎn)角度,請(qǐng)問(wèn)怎樣計(jì)算某一時(shí)刻的角速度呢?
| 192 | 7.085 |
| 193 | 10.497 |
| 194 | 14.019 |
| 195 | 17.683 |
| 196 | 21.487 |
| 197 | 25.403 |
| 198 | 29.402 |
| 199 | 33.467 |
顯然,這是一個(gè)求導(dǎo)即可解決的問(wèn)題。如果將時(shí)間記作t,將旋轉(zhuǎn)角度記作θ,那么θ就是t的函數(shù):
對(duì)上式求導(dǎo),就得到角速度v對(duì)時(shí)間t的函數(shù):
通常,我們把第1個(gè)公式叫做原函數(shù),把第2個(gè)公式叫做導(dǎo)函數(shù)。有了原函數(shù),利用六大基本初等函數(shù)的求導(dǎo)公式,或者應(yīng)用復(fù)合函數(shù)求導(dǎo)法則,一般都可以得到導(dǎo)函數(shù)。
然而,本問(wèn)題的原函數(shù)f(t)在哪里呢?我們手頭有的,不過(guò)是兩組離散的測(cè)量數(shù)據(jù)而已。漫說(shuō)f(t)不見(jiàn)蹤影,就算f(t)已經(jīng)存在,倘若不是基本初等函數(shù)的話,恐怕大多數(shù)程序員也早已忘記如何求導(dǎo)了吧?
看起來(lái)真的是山窮水盡無(wú)從下手了。不過(guò)呢,不用擔(dān)心,今天推薦一個(gè)通用的求導(dǎo)方法,可以幫助程序員徹底擺脫求導(dǎo)的困惑。這個(gè)通用方法有兩個(gè)步驟:第一步是通過(guò)離散數(shù)據(jù)找到原函數(shù),第二步是不依賴于求導(dǎo)公式和技巧就可以得到導(dǎo)函數(shù),無(wú)論原函數(shù)有多么復(fù)雜。
1. 尋找原函數(shù)
從兩組離散數(shù)據(jù)中找到它們之間的內(nèi)在關(guān)系,是一個(gè)回歸問(wèn)題,而數(shù)據(jù)插值就是對(duì)回歸函數(shù)的應(yīng)用。這啟發(fā)了我從scipy的插值問(wèn)題中尋找回歸函數(shù)。為了使方法更具通用性,下面的代碼用自變量x代替時(shí)間t,用因變量y代替旋轉(zhuǎn)角度θ,借助scipy模塊的一維插值函數(shù)interp1d,輕松得到了本文開(kāi)始給出的兩組數(shù)據(jù)間隱含的函數(shù)關(guān)系。
>>>?import?numpy?as?np >>>?from?scipy?import?interpolate >>>?_x?=?np.linspace(192,199,8) >>>?_y?=?np.array([7.085,10.497,14.019,17.683,21.487,25.403,29.402,33.467]) >>>?f?=?interpolate.interp1d(_x,?_y,?kind='cubic')這段代碼最后得到的f,就是旋轉(zhuǎn)角度對(duì)于時(shí)間的函數(shù),自變量的值域范圍限定在原始的時(shí)間數(shù)據(jù)的變化范圍內(nèi)。現(xiàn)在我們可以用它來(lái)計(jì)算192~199范圍內(nèi)任意時(shí)刻的旋轉(zhuǎn)角度了。
>>>?f(193.3) array(11.54026091) >>>?f(193.35) array(11.71517478) >>>?f(193.351) array(11.71867619)分別輸入193.3、193.35、193.351等時(shí)刻,簡(jiǎn)單測(cè)試了一下,看上去還都挺象那么回事兒。
2. 求解導(dǎo)函數(shù)
原函數(shù)找是找到了,卻猶抱琵琶半遮面,究竟什么模樣,我們還是不得而知。沒(méi)關(guān)系,下面這個(gè)通用的求導(dǎo)方法根本不在意原函數(shù)長(zhǎng)什么樣,只要原函數(shù)是真實(shí)存在的,就足夠了。這個(gè)方法的原理,就是令自變量x在某處有一個(gè)極小的增量dx,將因變量y的增量dy與dx之比近似視為函數(shù)在該處的導(dǎo)數(shù)。這里默認(rèn)dx=1.0X10的-10次方,如有必要,還可以將其設(shè)置為更小的數(shù)值。
>>>?def?get_derivative(f,?delta=1e-10):"""導(dǎo)函數(shù)生成器"""def?derivative(x):"""導(dǎo)函數(shù)"""return?(f(x+delta)-f(x))/deltareturn?derivative這不是一個(gè)閉包函數(shù)嗎?熟悉閉包的讀者一眼就會(huì)看出來(lái)。沒(méi)錯(cuò),導(dǎo)函數(shù)生成器就是一個(gè)閉包函數(shù),只要告訴它原函數(shù),它就返回對(duì)應(yīng)的導(dǎo)函數(shù)。用剛才得到的旋轉(zhuǎn)角度關(guān)于時(shí)間的原函數(shù)來(lái)測(cè)試一下,輕松得到其導(dǎo)函數(shù),也就是旋轉(zhuǎn)角速度關(guān)于時(shí)間的函數(shù)。
>>>?fd?=?get_derivative(f)用這個(gè)導(dǎo)函數(shù)計(jì)算一下193.5和195.8兩個(gè)時(shí)刻的角速度:
>>>?fd(193.5) 3.590830143540664 >>>?fd(195.8) 3.8961776076555026至此,問(wèn)題得解。
各位伙伴們好,詹帥本帥搭建了一個(gè)個(gè)人博客和小程序,匯集各種干貨和資源,也方便大家閱讀,感興趣的小伙伴請(qǐng)移步小程序體驗(yàn)一下哦!(歡迎提建議)
推薦閱讀
牛逼!Python常用數(shù)據(jù)類型的基本操作(長(zhǎng)文系列第①篇)
牛逼!Python的判斷、循環(huán)和各種表達(dá)式(長(zhǎng)文系列第②篇)
牛逼!Python函數(shù)和文件操作(長(zhǎng)文系列第③篇)
牛逼!Python錯(cuò)誤、異常和模塊(長(zhǎng)文系列第④篇)
總結(jié)
以上是生活随笔為你收集整理的怎么求导来着?别费劲了,试试这个Python的通用求导法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 大裁员...
- 下一篇: 又一款超酷的 Python 可视化神器: