2017-10-24 10 views
3

、ちょうど私がnumpyの持ついくつかの統計上のブートストラップ誤差推定を行うにしようとしています下の水平線NumPyで大規模な配列を何回も効率的にサンプリングする方法はありますか?あなたは私が実装しようとしているかの詳細については気にしない場合は

をスキップ。私は配列xを持っていて、誤差分析の通常のガウス仮説が成立しない統計量f(x)の誤差を計算したいと考えています。 xは非常に大きいです。これを行うには

、私は私の再サンプルのサイズは、交換して、元の配列の大きさであるnumpy.random.choice()を、使用してxをリサンプル:

resample = np.random.choice(x, size=len(x), replace=True)

これは私にxの新しい実現を与えます。この操作は、正確な誤差の推定値を得るために約1000回繰り返さなければならない。私がこのような性質のリサンプルを1000回生成した場合、

resamples = [np.random.choice(x, size=len(x), replace=True) for i in range(1000)]

し、各実現に統計f(x)を計算します。

results = [f(arr) for arr in resamples]

その後、私はたとえf(x)自体はガウスエラー解析、分布を用いて記述することができないということでアイデア

np.std(results)

のようなものであることをf(x)のエラーが推測されていますf(x)ランダムエラーの措置のすることができます。


これはブートストラップです。さて、私の問題は、ライン

resamples = [np.random.choice(x, size=len(x), replace=True) for i in range(1000)]

が大きな配列のため非常に遅いことです。リストの理解なしにこれを行うよりスマートな方法はありますか?第二のリストの内包表記

results = [f(arr) for arr in resamples]

は機能f(x)の内容によっては、あまりにもかなり遅くなることがあります。

+1

サブサンプルの構築を避けるために私が使ってきたアプローチは、対応するデータムがサンプルに含まれている場合は1、そうでない場合は0のフラグ配列を代わりに作成することです。サブサンプルを作成することは、フラグを置換することを意味します。サブサンプル配列の割り当てと塗りつぶしが計算時間のかなりの部分である場合、フラグを使った作業は勝利です。 –

+0

@RobertDodierありがとう!これは、以下のDivakarの答えと非常によく似ていますが、インデックス作成ではなく配列マスキングを使用しています。私はそれらのどれが速くなるかわからない - それは同じだろう、私は思うだろう。 – Anonymous

+0

はい、単にインデックスのリストを使用することは同等であり、データを含める/除外するだけの方が簡単かもしれません。私はしばしば1や0以外のウェイトを必要としていました。他のものよりもいくつかのデータ(例えば、データ内に少数の例を有するクラス)を置き換えて、または強調してサンプリングを表すために、重み> 1を使用する。 0/1以外のウェイトが必要ない場合は、インデックスのリストを使用することができます。 –

答えて

3

我々は繰り返しを許可しているので、そうのように、我々は、np.random.randintに一度のすべてのインデックスを生成し、resamples同等のものを得るために、単に指数ができ -

num_samples = 1000 
idx = np.random.randint(0,len(x),size=(num_samples,len(x))) 
resamples_arr = x[idx] 

もう一つのアプローチから乱数を生成することであろうそうのような配列の長さにnumpy.random.randとスケールとの均一な分布、 -

resamples_arr = x[(np.random.rand(num_samples,len(x))*len(x)).astype(int)] 
x 5000のelemsと

ランタイム試験 -


In [221]: x = np.random.randint(0,10000,(5000)) # Original soln In [222]: %timeit [np.random.choice(x, size=len(x), replace=True) for i in range(1000)] 10 loops, best of 3: 84 ms per loop # Proposed soln-1 In [223]: %timeit x[np.random.randint(0,len(x),size=(1000,len(x)))] 10 loops, best of 3: 76.2 ms per loop # Proposed soln-2 In [224]: %timeit x[(np.random.rand(1000,len(x))*len(x)).astype(int)] 10 loops, best of 3: 59.7 ms per loop 
600,000要素の非常に大きな配列xx

非常に大きいために、あなたは1000サンプルのためにすべてのそれらのインデックスを作成したくない場合があります。 @Divakarで示唆したように、あなたがむしろリストの内包表記を使用するよりも、リサンプリングの2次元配列を取得するためにsizeにタプルを渡すことができ

In [234]: x = np.random.randint(0,10000,(600000)) 

# Original soln 
In [235]: %timeit np.random.choice(x, size=len(x), replace=True) 
100 loops, best of 3: 13 ms per loop 

# Proposed soln-1 
In [238]: %timeit x[np.random.randint(0,len(x),len(x))] 
100 loops, best of 3: 12.5 ms per loop 

# Proposed soln-2 
In [239]: %timeit x[(np.random.rand(len(x))*len(x)).astype(int)] 
100 loops, best of 3: 9.81 ms per loop 
+0

ああ、もちろん、ありがとう。私はおそらく 'rand'を使ってこのアプローチを実装します。また、「x」は「非常に大きい」と答えました。それは600,000要素以上の長さです。だから、あなたのタイミング結果を推定することで、私は約4時間の実行時間を節約することができました – Anonymous

+0

@jphollowedこのような大きな 'x'を持つうわー、このポストで提案されているすべてのインデックスを作成することはできません。しかし、十分なシステムメモリがあれば試してみてください。 – Divakar

+0

@jphollowedまた、 '非常に大きいx'セクションもチェックしてください。 – Divakar

2

- その場合には、サンプルあたりのソリューションは、そのタイミングこのようなものを持っているでしょう。

ここで、fは他の機能ではなく単に合計であると仮定します。その後:

x = np.random.randn(100000) 
resamples = np.random.choice(x, size=(1000, x.shape[0]), replace=True) 
# resamples.shape = (1000, 1000000) 
results = np.apply_along_axis(f, axis=1, arr=resamples) 
print(results.shape) 
# (1000,) 

ここnp.apply_along_axisは確か[f(arr) for arr in resamples]ちょうど見せかけforループと等価です。あなたの質問に基づいてxのインデックスを作成する必要があるかどうかは正確には分かりません。

+0

これは非常に簡単で実質的に速く、約4倍です。リサンプリングを行う私の元のコードはループごとに16ミリ秒かかり、タプルとしてサイズを指定するのは4ms未満です – Anonymous

+0

これは唯一の問題です。つまり、 'f(x)'二次統計量であることを意味し、私が*置換せずにサンプル*したいことを意味する。希望の振る舞いは、置き換えを禁止する 'size'タプルで指定された各行*に対してですが、後続の各行に対して、前のサンプルとシェアを共有するかどうか気にすることはありません。 ValueError: 'replace = False'の場合、人口よりも大きなサンプルを取ることはできません – Anonymous

+0

単純に、このメソッドを使用してデータセットのN個のリサンプル実現を取ることはできません。各実現は置換なしでサンプリングされる。 – Anonymous

関連する問題