2

Pythonで次の論理演算を実行しようとしていますが、メモリと時間の問題が発生しています。私はPythonを初めて使用するので、問題を最適化する方法と場所に関するガイダンスをいただければ幸いです。(次の質問はやや抽象的なものであることを理解しています)

import networkx as nx 
    dic_score = {}
    G = nx.watts_strogatz_graph(10000,10,.01) # Generate 2 graphs with 10,000 nodes using Networkx
    H = nx.watts_strogatz_graph(10000,10,.01)
    for Gnodes in G.nodes()
        for Hnodes in H.nodes ()  # i.e. For all the pair of nodes in both the graphs
           score = SomeOperation on (Gnodes,Hnodes)  # Calculate a metric 
           dic_score.setdefault(Gnodes,[]).append([Hnodes, score, -1 ]) # Store the metric in the form a Key: value, where value become a list of lists, pair in a dictionary

次に、ここで説明した基準に従って、生成された辞書のリストを並べ替えます 。sorting_criterion

私の問題/質問は次のとおりです。

1)反復にforループを使用するよりも、これにアプローチするためのより良い方法はありますか?

2)上記の問題に取り組むための最も最適化された(最も速い)方法は何ですか?辞書以外のデータ構造の使用を検討する必要がありますか?またはおそらくファイル操作?

3)10,000個の値のリストに対応する10,000個のキーを持つこのディクショナリ内のリストを並べ替える必要があるため、メモリ要件がすぐに膨大になり、不足します。

3)辞書自体の計算内に並べ替えプロセスを統合する方法はありますか?つまり、並べ替えのために別のループを実行することを避けますか?

任意の入力をいただければ幸いです!ありがとう !

4

3 に答える 3

5

1)itertoolsそのためにモジュールの関数の1つを使用できます。申し上げておきますが、マニュアルを読むか、電話でお問い合わせください。

from itertools import product
help(product)

次に例を示します。

for item1, item2 in product(list1, list2):
    pass

2)結果が大きすぎてメモリに収まらない場合は、どこかに保存してみてください。たとえば、CSVファイルに出力できます。

with open('result.csv') as outfile:
   writer = csv.writer(outfile, dialect='excel')
   for ...
       writer.write(...)

これはあなたの記憶を解放します。

3)問題を複雑にしてその場でデータを並べ替えるよりも、後で結果データを並べ替える方が良いと思います(sort関数はかなり速いため)。

代わりに、NumPy arroy / matrix操作(合計、積、または関数を各行列行にマップする)を使用できます。これらは非常に高速であるため、データのフィルタリングにはすべてを計算するよりもコストがかかる場合があります。

それでもアプリが非常に遅い場合は、アプリのプロファイリングを試して、どの操作が遅いか、または何度も実行されているかを正確に確認してください。

from cProfile import Profile
p = Profile()

p.runctx('my_function(args)', {'my_function': my_function, 'args': my_data}, {})
p.print_stats()

次の表が表示されます。

      2706 function calls (2004 primitive calls) in 4.504 CPU seconds

Ordered by: standard name

ncalls  tottime  percall  cumtime  percall filename:lineno(function)
     2    0.006    0.003    0.953    0.477 pobject.py:75(save_objects)
  43/3    0.533    0.012    0.749    0.250 pobject.py:99(evaluate)
...
于 2012-06-27T07:56:26.257 に答える
4

リストを返す関数を操作するときは、イテレータを返す関数を確認してください。

これにより、メモリ使用量が向上します。

あなたの場合、nx.nodes完全なリストを返します。参照:ノード

nodes_iterイテレータを返すので使用します。これにより、forループ内のノードを反復処理しているときに、メモリ内にノードの完全なリストがないことが保証されます。

参照:nodes_iter

いくつかの改善:

import networkx as nx 
    dic_score = {}
    G = nx.watts_strogatz_graph(10000,10,.01) 
    H = nx.watts_strogatz_graph(10000,10,.01)
    for Gnodes in G.nodes_iter() ----------------> changed from G.nodes()
        for Hnodes in H.nodes_iter()  -----------> changed from H.nodes()
           score = SomeOperation on (Gnodes,Hnodes) 
           dic_score.setdefault(Gnodes,[]).append([Hnodes, score, -1 ])

2つのイテレータがあるので、他のイディオムを使用することもできます。itertools.productsを使用します。

product(A, B) returns the same as ((x,y) for x in A for y in B). 
于 2012-06-27T07:56:03.500 に答える
1

他の人は言及しitertools.productました。それは良いことですが、あなたの場合、別の可能性があります。それは、内部ループのジェネレータ式とsorted関数です。(もちろん、コードはテストされていません。)

import networkx as nx
from operator import itemgetter 
dic_score = {}
G = nx.watts_strogatz_graph(10000,10,.01) # Generate 2 graphs with 10,000 nodes using Networkx
H = nx.watts_strogatz_graph(10000,10,.01)
for Gnodes in G.nodes():
    dic_score[Gnodes] = sorted([Hnodes, score(Gnodes, Hnodes), -1] for Hnodes in H.nodes(), key=operator.itemgetter(1)) # sort on score

内側のループはジェネレータ式に置き換えられます。また、その場で並べ替えられます(各内部リストをその場で並べ替えたいと仮定しますscore)。辞書に保存する代わりに、各内部リストをファイルに簡単に書き込むことができます。これはメモリに役立ちます。

于 2012-06-27T08:10:37.130 に答える