![](/img/trans.png)
[英]Recommendations for Low Discrepancy (e.g. Sobol) quasi-random sequences in Python/SciPy?
[英]Generating low discrepancy quasi-random sequences in python/numpy/scipy?
我認為 Python 中低差異序列的最佳替代方案是 Sensitivity Analysis Library (SALib):
https://github.com/SALib/SALib
我認為這是一個活躍的項目,您可以聯系作者檢查您需要的功能是否已經實現。 如果這不能解決您的問題,Corrado Chisari 將在 Matlab(由 John Burkardt)中制作的 SOBOL 版本移植到 Python,您可以在此處訪問它:
http://people.sc.fsu.edu/~jburkardt/py_src/sobol/sobol.html
有人清理了這些源中的注釋,並將它們放入文檔字符串的格式中。 它更具可讀性,您可以在此處訪問它:
Scipy 現在有這個選項http://scipy.github.io/devdocs/generated/scipy.stats.qmc.Sobol.html
PyTorch 還證明了生成 sobol 隨機數的選項。 它允許高達 ~1k 的維度,並且可以選擇開啟加擾。 https://pytorch.org/docs/stable/generated/torch.quasirandom.SobolEngine.html
我認為現在最簡單的方法(從 SciPy 版本 >= 1.7.1 開始)就是我在這里的做法。 注意我是為期權定價寫的; 它適用於多達 21,201 個維度,因為他們實現了 Joe 和 Kuo 算法,這是您無需支付商業(非開源)版本即可獲得的最大維度數。 https://web.maths.unsw.edu.au/~fkuo/sobol/請注意,此例程可能非常緩慢(由於 ndtri,或點到沖擊的逆正態分布轉換),尤其是在高維度中。 無論如何,這至少可以讓您直接在 Python 代碼中生成點。 所以我正在做一些你的用例可能不需要的事情(我還沒有找到一種邏輯方法來從生成的 Owen 加擾 Sobol 點中刪除/替換 0 和 1,所以我只是用數字替換它們的序列這不會導致生成 -Inf 或 Inf,這會發生在許多高維度的 RQMC 點上 - 這些數字在我選擇它們的方式中是任意的;基本上我生成了一個具有 65,536 個模擬和“高”維度的 RQMC 序列,然后檢查了最小值和最大值的加擾點,這些點與這些值最接近,但略接近 0 或 1,因此它是“有點”邏輯選擇)。 另外,在 QMCgenerate 例程中,我跳過了第一點(即 0)——雖然這很常見,但有些論文建議不要這樣做(但我還沒有看到好的替代方案,如果你有的話,請隨意評論)。 我轉置它們只是為了稍后將它們粘貼到 Excel 中並檢查生成的沖擊。 不管怎樣,希望那些需要這個算法的人發現它有用。
from scipy.stats import qmc # needs SciPy >= 1.7.1
from scipy.special import ndtri
import numpy as np
import timeit
Total_periods = 252
N_assets = 12
# need a pow(2,m) loop to run until pow(2,m) >= sims IF using base2
sims = 8096
dimensions = N_assets*Total_periods
def RQMCgenerate (dimensions, sims, seed):
m=10 # start at 1024 sims
#sims = pow(2,m) # RQMC Sobol needs a power of 2 for simulations
while pow(2,m) < sims: #m = 17 # 131,072 sims; M = 16 # 65,536 sims
m = m+1
start_time = timeit.default_timer()
RQMCgenerator = qmc.Sobol(dimensions, scramble=True, seed=seed)
RQMCsamples = RQMCgenerator.random_base2(m)
print('\n' + 'Time after sample generation RQMC:', (timeit.default_timer() - start_time), 'seconds');
#clean up outliers for 0, 1 where normsinv(0) = -Inf and normsinv(1) = Inf
RQMCsamples[RQMCsamples<=0]=0.000001 #arbitrary point change
RQMCsamples[RQMCsamples>=1]=0.999999 #arbitrary point change
#END clean up outliers for 0, 1
sobol = ndtri(RQMCsamples).T # get normsinv(points) and transpose to dimensions * sims
del RQMCsamples
print('\n' + 'Time after ndtri (normsinv) of', sims,'sims x dimensions', dimensions, 'Randomized Sobol points): ', (timeit.default_timer() - start_time), 'seconds');
return sobol
def QMCgenerate(dimensions, sims):
start_time = timeit.default_timer()
QMCgenerator = qmc.Sobol(dimensions, scramble=False)
QMCgenerator.fast_forward(1) #skip first point where normsinv(0) = -Inf
QMCsamples = QMCgenerator.random(sims) #this generates points not having to be powers of 2
print('\n' + 'Time after sample generation QMC:', (timeit.default_timer() - start_time), 'seconds');
sobol = ndtri(QMCsamples).T # get normsinv(points) and transpose to dimensions * sims
del QMCsamples
print('\n' + 'Time after ndtri (normsinv) of', sims,'sims x dimensions', dimensions, 'Sobol points):', (timeit.default_timer() - start_time), 'seconds');
return sobol
RQMCsobol = RQMCgenerate(dimensions, sims, seed=0)
sobol = QMCgenerate(dimensions, sims)
樣本生成 RQMC 后的時間:0.4269224999952712 秒
ndtri (normsinv) of 8096 sims x 維度 3024 Randomized Sobol 點之后的時間:1.0048970999996527 秒
樣本生成 QMC 后的時間:0.0630135999963386 秒
8096 sims x 尺寸 3024 Sobol 點的 ndtri (normsinv) 之后的時間:0.5444753999981913 秒
這在更高維度上變得更慢:
樣本生成后的時間 RQMC:2.1779929000040283 秒
ndtri (normsinv) of 131072 sims x 維度 3024 Randomized Sobol 點之后的時間:10.617904700004146 秒
樣本生成 QMC 后的時間:1.079756200000702 秒
131072 sims x 尺寸 3024 Sobol 點的 ndtri (normsinv) 之后的時間:9.545934699999634 秒
我認為現在最簡單的方法(從 SciPy 版本 >= 1.7.1 開始)就是我在這里的做法。 由於他們實現了 Joe 和 Kuo 算法,因此最多可支持 21,201 個維度,這是您可以獲得的最大維度數(開源)。 https://web.maths.unsw.edu.au/~fkuo/sobol/
在這里,我展示了如何使用 base2 方法(使用 Owen Scrambling)和隨機方法(從序列中生成任意數量的點),以及如何跳過第一個點。
請注意,此例程可能非常慢(由於 ndtri 或點到沖擊的逆正態分布轉換),尤其是在高維度 + 高模擬計數中。 Sobol 序列本身的點生成速度非常快,但對於大多數 Monte Carlo 模擬,您將它們轉換為沖擊(您可能使用標准正態分布以外的其他分布)。 這至少可以讓您直接在 Python 代碼中生成點。
另外,在 QMCgenerate 例程中,我跳過了第一點(即 0)——雖然這很常見,但有些論文建議不要這樣做(但我還沒有看到好的替代方案,如果你有的話,請隨意評論)。 我轉置它們只是為了稍后將它們粘貼到 Excel 中並檢查生成的沖擊。 不管怎樣,希望那些需要這個算法的人發現它有用。
from scipy.stats import qmc # needs SciPy >= 1.7.1
from scipy.special import ndtri
import numpy as np
import timeit
time_periods = 252
factors = 12
# IF using base2 generation, need a pow(2,m)
sims = 8092
dimensions = factors*time_periods
def RQMCgenerate (dimensions, sims, seed):
start_time = timeit.default_timer()
m=10 # start at 1024 sims
while pow(2,m) < sims: #m = 17 # 131,072 sims; M = 16 # 65,536 sims
m = m+1
RQMCgenerator = qmc.Sobol(dimensions, scramble=True, seed=seed)
RQMCsamples = RQMCgenerator.random_base2(m)
print('\n' + 'Time after sample generation RQMC:', (timeit.default_timer() - start_time), 'seconds');
sobol = ndtri(RQMCsamples).T # get normsinv(points) and transpose to dimensions * sims
del RQMCsamples
print('\n' + 'Time after ndtri (normsinv) of', sims,'sims x dimensions', dimensions, 'Randomized Sobol points): ', (timeit.default_timer() - start_time), 'seconds');
return sobol
def QMCgenerate(dimensions, sims):
start_time = timeit.default_timer()
QMCgenerator = qmc.Sobol(dimensions, scramble=False)
QMCgenerator.fast_forward(1) #skip first point where normsinv(0) = -Inf
QMCsamples = QMCgenerator.random(sims) #this generates points not having to be powers of 2
print('\n' + 'Time after sample generation QMC:', (timeit.default_timer() - start_time), 'seconds');
sobol = ndtri(QMCsamples).T # get normsinv(points) and transpose to dimensions * sims
del QMCsamples
print('\n' + 'Time after ndtri (normsinv) of', sims,'sims x dimensions', dimensions, 'Sobol points):', (timeit.default_timer() - start_time), 'seconds');
return sobol
RQMCsobol = RQMCgenerate(dimensions, sims, seed=0) #note sims changed with pow(2,m) if a power of 2 was not passed
sobol = QMCgenerate(dimensions, sims)
樣本生成 RQMC 后的時間:0.4269224999952712 秒
ndtri (normsinv) of 8092 sims x 維度 3024 Randomized Sobol 點之后的時間:1.0048970999996527 秒
樣本生成 QMC 后的時間:0.0630135999963386 秒
8092 sims x 尺寸 3024 Sobol 點的 ndtri (normsinv) 之后的時間:0.5444753999981913 秒
這在更高的 sims*dimensions 中變得更慢,盡管我沒有發現比 Python 中的 ndtri 更快的點到正態分布沖擊的轉換:
樣本生成后的時間 RQMC:2.1779929000040283 秒
ndtri (normsinv) of 131072 sims x 維度 3024 Randomized Sobol 點之后的時間:10.617904700004146 秒
樣本生成 QMC 后的時間:1.079756200000702 秒
131072 sims x 尺寸 3024 Sobol 點的 ndtri (normsinv) 之后的時間:9.545934699999634 秒
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.