1

複数のグループを持つ 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

列は

  1. tick - 時間ステップ
  2. ensingAgentId - センシングを行うエージェントの ID
  3. sensedAgentId - 感知されているエージェントの ID
  4. detRange - 2 つのエージェント間のメートル単位の範囲
  5. 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 を使用してみましたが、ほとんど違いはありませんでした。

4

1 に答える 1

2

N=~2k のエージェントがいる場合、すべての目撃情報をサイズ NxN の numpy 配列に入れることをお勧めします。これは簡単にメモリに収まります (整数の場合は約 16 メガバイト)。目撃が発生した場所に 1 を格納するだけです。

配列があるとしますsightings。最初の座標は Sensing で、2 番目の座標は Sensed です。どのエージェントがどちらの側にいるかをリストする 1 次元インデックス配列もあるとします。この方法で、サイド A ごとにサイド B の目撃数を取得できます。

sideAseesB = sightings[sideAindices, sideBindices]
sideAseesBcount = numpy.logical_or.reduce(sideAseesB, axis=0).sum()

最初のステップで使用する必要がある可能性はありますsightings.take(sideAindices, axis=0).take(sideBindices, axis=1)が、私はそれを疑っています.

于 2009-12-31T20:57:20.647 に答える