8

私はNumPyを始めたばかりなので、いくつかのコアコンセプトが欠けている可能性があります...

値がリストである辞書から NumPy 配列を作成する最良の方法は何ですか?

このようなもの:

d = { 1: [10,20,30] , 2: [50,60], 3: [100,200,300,400,500] }

次のようになります。

data = [
  [10,20,30,?,?],
  [50,60,?,?,?],
  [100,200,300,400,500]
]

各行でいくつかの基本的な統計を実行します。たとえば、次のようになります。

deviations = numpy.std(data, axis=1)

質問:

  • 辞書から numpy.array を作成するための最良/最も効率的な方法は何ですか? 辞書は大きいです。それぞれ約 20 のアイテムを持つ数百万のキー。

  • 各「行」の値の数は異なります。numpy が均一なサイズを望んでいることを正しく理解していれば、不足しているアイテムを std() を幸せにするために何を記入すればよいでしょうか?

更新: 言い忘れたことの 1 つ - Python の手法は合理的ですが (たとえば、数百万のアイテムをループするのは高速です)、単一の CPU に制限されます。Numpy 操作はハードウェアに合わせて適切にスケーリングされ、すべての CPU にヒットするため、魅力的です。

4

3 に答える 3

8

numpy.std() を呼び出すために numpy 配列を作成する必要はありません。ディクショナリのすべての値に対してループで numpy.std() を呼び出すことができます。リストはオンザフライで numpy 配列に変換され、標準偏差が計算されます。

この方法の欠点は、メイン ループが C ではなく Python になることです。しかし、これは十分に高速であると思います。C の速度で std を計算し、多くのメモリを節約できます。可変サイズの配列がある場合は、0 の値を格納する必要があります。

  • これをさらに最適化する場合は、値を numpy 配列のリストに格納して、python リスト -> numpy 配列の変換を 1 回だけ行うことができます。
  • それでも遅すぎる場合は、psycho を使用して python ループを最適化してみてください。
  • それでも遅すぎる場合は、Cythonを numpy モジュールと一緒に使用してみてください。このチュートリアルでは、画像処理の速度が大幅に向上したと主張しています。または、Cython で std 関数全体を単純にプログラムします (合計関数を使用したベンチマークと例については、これを参照してください)。
  • Cython の代わりにnumpy.iでSWIGを使用することもできます。
  • numpy のみを使用し、すべてを C レベルで計算する場合は、同じサイズのすべてのレコードを異なる配列にグループ化し、それぞれに対して numpy.std() を呼び出してみてください。次の例のようになります。

O(N) の複雑さの例:

import numpy
list_size_1 = []
list_size_2 = []
for row in data.itervalues():
    if len(row) == 1:
      list_size_1.append(row)
    elif len(row) == 2:
      list_size_2.append(row)
list_size_1 = numpy.array(list_size_1)
list_size_2 = numpy.array(list_size_2)
std_1 = numpy.std(list_size_1, axis = 1)
std_2 = numpy.std(list_size_2, axis = 1)
于 2009-03-02T08:02:56.287 に答える
2

ここにはすでにかなり合理的なアイデアがいくつかありますが、次のことは言及する価値があると思います.

欠損データをデフォルト値で埋めると、統計的特性 (std など) が損なわれます。明らかにそれが、Mapad が同じサイズのレコードをグループ化する素晴らしいトリックを提案した理由です。それに関する問題 (レコード長に関する先験的なデータが手元にない場合) は、単純な解決策よりもさらに多くの計算が必要になることです。

  1. 効果的なアルゴリズムでソートするための少なくともO(N*logN) 'len' 呼び出しと比較
  2. O(N)は、リストの 2 番目の方法をチェックしてグループを取得します (「垂直」軸の開始インデックスと終了インデックス)。

Psyco を使用することをお勧めします (非常に使いやすいので、ぜひ試してみてください)。

最適な方法は、リスト全体を生成するのではなく、各行を numpy.array に変換して必要な計算を実行する辞書を反復処理するという変更を加えて、箇条書き #1 で Mapad によって説明されている戦略を取ることです。このような:

for row in data.itervalues():
    np_row = numpy.array(row)    
    this_row_std = numpy.std(np_row)
    # compute any other statistic descriptors needed and then save to some list

いずれにせよ、Python での数百万回のループは、予想されるほど長くはかかりません。その上、これは日常的な計算のようには見えないので、たまに実行されたり、1 回だけ実行されたりすると、余分な秒/分がかかるかどうかは誰にもわかりません。


Mapad によって提案されたものの一般化されたバリアント:

from numpy import array, mean, std

def get_statistical_descriptors(a):
    if ax = len(shape(a))-1
    functions = [mean, std]
    return f(a, axis = ax) for f in functions


def process_long_list_stats(data):
    import numpy

    groups = {}

    for key, row in data.iteritems():
        size = len(row)
        try:
            groups[size].append(key)
        except KeyError:
            groups[size] = ([key])

    results = []

    for gr_keys in groups.itervalues():             
        gr_rows = numpy.array([data[k] for k in gr_keys])       
        stats = get_statistical_descriptors(gr_rows)                
        results.extend( zip(gr_keys, zip(*stats)) )

    return dict(results)
于 2009-03-02T20:36:03.230 に答える
0

numpy 辞書

構造化配列を使用して、ディクショナリのように、numpy オブジェクトをキーでアドレス指定する機能を保持できます。

import numpy as np


dd = {'a':1,'b':2,'c':3}
dtype = eval('[' + ','.join(["('%s', float)" % key for key in dd.keys()]) + ']')
values = [tuple(dd.values())]
numpy_dict = np.array(values, dtype=dtype)

numpy_dict['c']

出力されるようになりました

array([ 3.])
于 2012-07-23T20:11:50.730 に答える