複数のグループを持つ HDF5 ファイルがあり、各グループには 2,500 万行以上のデータ セットが含まれています。シミュレーションの各時間ステップで、各エージェントはその時間ステップで感知した他のエージェントを出力します。シナリオには約 2000 のエージェントがあり、数千のタイム ステップがあります。出力の O(n^2) の性質が膨大な数の行を説明しています。
私が計算したいのは、カテゴリ別のユニークな目撃数です。たとえば、エージェントは赤、青、緑のいずれかの側に属します。j
行 i、列 j がカテゴリ i の少なくとも 1 つのエージェントによって感知されたカテゴリのエージェントの数である 2 次元のテーブルを作成したいと考えています。(このコード例では側面を使用していますが、エージェントを他の方法で分類することもできます。たとえば、エージェントが持つ武器や運ぶセンサーによって分類できます。)
出力テーブルの例を次に示します。シミュレーションは青/青の感覚を出力しないことに注意してください。これは、大量のスペースが必要であり、それらには関心がないためです。緑緑も同様)
blue green red
blue 0 492 186
green 1075 0 186
red 451 498 26
列は
- tick - 時間ステップ
- ensingAgentId - センシングを行うエージェントの ID
- sensedAgentId - 感知されているエージェントの ID
- detRange - 2 つのエージェント間のメートル単位の範囲
- senseType - 行われたセンシングのタイプの列挙型
これを達成するために現在使用しているコードは次のとおりです。
def createHeatmap():
h5file = openFile("someFile.h5")
run0 = h5file.root.run0.detections
# A dictionary of dictionaries, {'blue': {'blue':0, 'red':0, ...}
classHeat = emptyDict(sides)
# Interested in Per Category Unique Detections
seenClass = {}
# Initially each side has seen no one
for theSide in sides:
seenClass[theSide] = []
# In-kernel search filtering out many rows in file; in this instance 25,789,825 rows
# are filtered to 4,409,176
classifications = run0.where('senseType == 3')
# Iterate and filter
for row in classifications:
sensedId = row['sensedAgentId']
# side is a function that returns the string representation of the side of agent
# with that id.
sensedSide = side(sensedId)
sensingSide = side(row['sensingAgentId'])
# The side has already seen this agent before; ignore it
if sensedId in seenClass[sensingSide]:
continue
else:
classHeat[sensingSide][sensedSide] += 1
seenClass[sensingSide].append(sensedId)
return classHeat
注: 私は Java のバックグラウンドを持っているので、これが Pythonic でない場合は申し訳ありません。これを指摘して、このコードを改善する方法を提案してください。私は Python にもっと習熟したいと思っています。
現在、これは非常に時間がかかります。この反復とメンバーシップ チェックを行うのに約 50 秒かかります。これは、メンバーシップ基準の最も制限されたセットを使用した場合です (他の検出タイプには、反復する行がさらに多くあります)。
私の質問は、作業を Python からカーネル内検索クエリに移動することは可能ですか? もしそうなら、どのように?私が見逃している明白なスピードアップはありますか? 一連の実行 (~30) の実行ごとに、および複数の基準セット (~5) に対してこの関数を実行できる必要があるため、これを高速化できれば素晴らしいことです。
最後のメモ: psyco を使用してみましたが、ほとんど違いはありませんでした。