基于np.arange與np.linspace細微區(qū)別(數(shù)據(jù)溢出問題)
太長不看的簡潔版本
1.x = np.arange(start, end, steps)
Values are generated within the half-open interval [start, stop)
(in other words, the interval including start but excluding stop).
- 即區(qū)間是左閉右開的,不包含end的取值
2.x = np.linspace(start, end, num, endpoint=True)
There are num equally spaced samples in the closed interval [start, stop] or the half-open interval [start, stop) (depending on whether endpoint is True or False).
- 即endpoint=True區(qū)間是左閉右閉的,包含end的取值
- 即endpoint=False區(qū)間是左閉右開的,不包含end的取值
最終結(jié)論:
- 當(dāng)linspace函數(shù)指定參數(shù)endpoint=False時,兩個函數(shù)的效果等價。
- 當(dāng)steps和num指定參數(shù)都是整數(shù)時,arrange會返回numpy.int32數(shù)據(jù)類型,
- 而linspace會返回numpy.float數(shù)據(jù)類型,對應(yīng)于 C 語言數(shù)據(jù)類型,每種“整數(shù)”有自己的區(qū)間,會遇到數(shù)據(jù)溢出的問題,數(shù)值分析中函數(shù)繪制曲線將得不到正確的答案。
解決方案:
- 使用 np.linspace比np.arange好,可以預(yù)防數(shù)據(jù)溢出的問題
- 使用np.arange時,將步長steps設(shè)置為小數(shù),比如1.0
繪制曲線代碼:
x = np.arange(0,100,1.0) #自變量的范圍 x = np.linspace(0, 100, 100,endpoint=False) # 兩者效果等價 y = alpha*(T-x) + beta*(T**4-x**4) + gamma*(u**2) #因變量 plt.plot(x, y, y*0.0) #曲線繪制
問題前夕
數(shù)值分析課程作業(yè)用python的matplotlib一直得不到正確的曲線圖,后用Matlab就可以,明明是一樣的函數(shù),但是兩者繪制出來的曲線圖顯示零點不一致,差距很大。
作為一枚不會matlab的學(xué)渣,為了得到正確的答案,難道真的必須啃下matlab的語法嗎…又問了一下同門,他居然用python得出了正確的答案,排查兩個小時一無所獲轉(zhuǎn)戰(zhàn)Matlab的我留下了羨慕的淚水,趕緊要來了他的代碼進行對比實驗,終于找出了問題的關(guān)鍵了,預(yù)知后事如何請繼續(xù)往下看…
我的代碼
u = 21.0 T = 293.15 alpha = 50.0 beta = 2*(10**(-7)) gamma = 800.0 x = np.arange(0,10000,1) #自變量的范圍 y = alpha*(T-x) + beta*(T**4-x**4) + gamma*(u**2) #因變量 plt.plot(x, y, y*0.0)
效果圖
從圖中可以看出函數(shù)的零點在[7000,8000]這個范圍。
那么問題來了,為什么表達式不是一次函數(shù)繪制出來的圖形卻是一條直線,x^4怎么也不能是一條直線吧???帶著這個疑惑,我找了同學(xué)要了他的答案來對照,發(fā)現(xiàn)零點只有一個,在[1000,1200]這個范圍內(nèi)。我仔細對照了函數(shù)方程,苦苦思索了兩個小時也沒找到答案。
同門的代碼
u = 21.0 T = 293.15 alpha = 50.0 beta = 2*(10**(-7)) gamma = 800.0 start = 1000 end = 1500 step = 1 num = (end - start) // step x = np.linspace(start, end, num) y = alpha*(T-x) + beta*(T**4-x**4) + gamma*(u**2) fig = plt.figure(figsize=(6, 6)) plt.plot(x, y, label='Numerical Analysis') plt.grid(True) plt.xlim((800, 1500)) # 顯示的x的范圍(不設(shè)置則由程序自動設(shè)置) plt.ylim((-10, 10)) # 顯示的y的范圍 plt.legend() # 顯示旁注 plt.show(fig) # 沒有輸入值默認展示所有對象
效果圖
從圖中可以看出同門的代碼跑出來的結(jié)果是正確的,并且這條線還是彎的…我以為是plt疊加導(dǎo)致的buff加成,然后我把作圖的代碼copy到我的代碼里,仍然是錯誤的?。?!在逐步分析后,我發(fā)現(xiàn)導(dǎo)致這個現(xiàn)象的原因居然只是一行代碼的差距?。?!展示如下:
代碼對比【區(qū)別只體現(xiàn)在自變量x】
u = 21.0 T = 293.15 alpha = 50.0 beta = 2*(10**(-7)) gamma = 800.0 x = np.arange(1000,1500,1) #區(qū)別只體現(xiàn)在自變量x所用的函數(shù) #x = np.linspace(1000, 1500, 500) #區(qū)別只體現(xiàn)在自變量x所用的函數(shù) y = alpha*(T-x) + beta*(T**4-x**4) + gamma*(u**2) plt.plot(x, y)
x = np.arange(1000,1500,1)的效果圖
[<matplotlib.lines.Line2D at 0x29e40ceff10>]
x = np.linspace(1000, 1500, 500)的效果圖
[<matplotlib.lines.Line2D at 0x29e40da97c0>]
x = np.arange(1000,1500,0.1)的效果圖
咦,此時我不禁疑惑,我使用的np.arange也是1000-1500,以1為間隔,自變量取值為
[1000, 1001, 1002,…, 1499]
使用的np.linspace也是把1000-1500切分為500份,
[1000, 1001.00200401, 1002.00400802, …, 1498.99799599, 1500]
效果理應(yīng)是差不多的。
但是為什么我用arange函數(shù)的時候需要將精度設(shè)為0.1,才能實現(xiàn)linspace精度為1的效果呢???
官方API解析
x = np.arange(0,10,1) #輸出: [0 1 2 3 4 5 6 7 8 9] x1 = np.linspace(0, 10, 10, endpoint=False) #輸出:[0. 1. 2. 3. 4. 5. 6. 7. 8. 9.] x1 = np.linspace(0, 10, 10) #輸出:[ 0. 1.11111111 2.22222222 3.33333333 4.44444444 5.55555556 6.66666667 7.77777778 8.88888889 10. ]
上面的例子表明:當(dāng)指定endpoint為False時,兩個函數(shù)的效果等價。此時,我似乎發(fā)現(xiàn)了一點不對勁,一個輸出的是整數(shù),一個輸出的是小數(shù)???會不會這個對結(jié)果造成了影響呢?懷著想都不敢想的夢想,我嘗試了一下將整數(shù)設(shè)置為浮點數(shù)…
x = np.arange(1000,1500,1.0)的效果圖
我的天呀,居然把取樣間隔從1設(shè)置為1.0效果居然有這么大的不同,此時我的疑惑非但沒有減輕,反而更加疑惑了,整數(shù)和浮點數(shù)作圖效果的天差地別,又是什么原因?qū)е碌哪??我想了想,畢竟我學(xué)的這門課叫做《數(shù)值分析》啊,那我畢竟也得有點這方面的一點見解?…也許這個表達式太過于復(fù)雜,整數(shù)輸進去再經(jīng)過七七七八八的加減乘除后,自變量為整型+1、-1差別很細微可以忽略不計。最主要是我的因變量的范圍是10^5,微小的變化也許體現(xiàn)不出來???但是我的常量設(shè)置的時候特地全都設(shè)置為浮點數(shù)了。
通過MATLAB已知零點在[1118,1119]之間,我特地打印出x=1118和x=1119對應(yīng)因變量的值:
x1 = 1118; ? ? ?#對應(yīng)因變量y=572.5297745541902 x2 = 1119; ? ? ?#對應(yīng)因變量y=-596.9030544458074 x = np.arange(1110,1120,1.0) ?
輸出:
[9820.44892975 8674.86472155 7526.31814255 6374.80385755 5220.31652655
4062.85080475 2902.40134255 1738.96278555 572.52977455 -596.90305445]
x = np.arange(1110,1120,1)
輸出:
[313045.14002735 313617.54273755 313327.98961775 313035.46879195
313598.96837935 313300.49611675 312999.04011375 312694.59501595
313246.14892335 312935.70955355]
由x1,x2可以看出零點確實在這個范圍內(nèi),但是自變量為整型時,很有可能是溢出了,導(dǎo)致計算值與真實值天差地別。不但正數(shù)數(shù)值不對,而且零點也消失了。但是我單獨輸入1119也是整型,為什么可以得到正確值?python最新版本對整型沒有限制了,原來能表示的最大整型為9223372036854775807。Numpy 中的整數(shù)類型對應(yīng)于 C 語言的數(shù)據(jù)類型,每種“整數(shù)”有自己的區(qū)間,要解決數(shù)據(jù)溢出問題,需要指定更大的數(shù)據(jù)類型(dtype)?。?!
原來我單獨輸入x的值,此時用的是python的版本表示的整型,是源碼里自帶了溢出防止辦法,所以函數(shù)值能正確輸出,但是x = np.arange(1110,1120,1),對應(yīng)的每一個自變量的類型輸出為:
<class ‘numpy.int32’>
只能表示數(shù)據(jù)范圍整數(shù)(-2147483648 to 2147483647),當(dāng)x取值為10^3時,對應(yīng)四次方結(jié)果為1000000000000,已經(jīng)超出可以表示的范圍了。到這里已經(jīng)把我的坑解釋的很清楚了。
解決辦法
大家以后要作圖繪制曲線最好使用np.linspace,會自動把自變量取值設(shè)置為浮點型,或者np.arange(start,end,1.0),步長設(shè)置為浮點型?。?!這樣的話才不會出現(xiàn)溢出等問題?。。。?/p>
花了半天的時間終于把這個坑給解決了,給自己
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Keras中Sequential模型和Functional模型的區(qū)別及說明
這篇文章主要介紹了Keras中Sequential模型和Functional模型的區(qū)別及說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-12-12使用python處理題庫表格并轉(zhuǎn)化為word形式的實現(xiàn)
這篇文章主要介紹了使用python處理題庫表格并轉(zhuǎn)化為word形式的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-04-04