3

定義された線(3D)に沿って等間隔でn個の点(3D)を計算する必要があります。線の始点と終点を知っています。まず、使用しました

for k in range(nbin):
  step = k/float(nbin-1)
  bin_point.append(beam_entry+(step*(beamlet_intersection-beam_entry)))

次に、大きな配列に追加を使用すると時間がかかることがわかり、次のようにコードを変更しました。

bin_point = [start_point+((k/float(nbin-1))*(end_point-start_point)) for k in range(nbin)]

newaxisを使用すると時間がさらに改善されるという提案がありました。変更されたコードは次のようになります。

step      = arange(nbin) / float(nbin-1)
bin_point = start_point + ( step[:,newaxis,newaxis]*((end_pint - start_point))[newaxis,:,:] )  

しかし、newaxis関数を理解できませんでした。また、start_pointとend_pointの構造や形状を変更しても、同じコードが機能するかどうかも疑問です。同様に、newaxisを使用して次のコードをmdoifyするにはどうすればよいですか?

 for j in range(32):      # for all los
   line_dist[j] = sqrt([sum(l) for l in (end_point[j]-start_point[j])**2])

非常に不格好で申し訳ありませんが、start_pointとend_pointの構造をより明確にするために

array([ [[1,1,1],[],[],[]....[]], 
        [[],[],[],[]....[]],
        [[],[],[],[]....[]]......,
        [[],[],[],[]....[]] ])
4

3 に答える 3

2

問題の newaxis バージョンの説明: これらは行列の乗算ではありません。ndarray の乗算はブロードキャストによる要素ごとの乗算です。. step[:,newaxis,newaxis] は num_steps x 1 x 1 で、point[newaxis,:,:] は 1 x num_points x num_dimensions です。(num_steps x 1 x 1) および (1 x num_points x num_dimensions) の形状を持つ ndarray を一緒にブロードキャストすることは機能します。これは、「次元 1 の配列を他の配列の対応する次元の数だけ繰り返す」ことを意味します。これにより、非常に効率的な方法で形状 (num_steps x num_points x num_dimensions) を持つ ndarray が生成されます。i、j、k 添え字は、j 番目の線に沿った i 番目のステップの k 番目の座標になります (開始点と終了点の j 番目のペアによって与えられます)。

チュートリアル:

>>> start_points = numpy.array([[1, 0, 0], [0, 1, 0]])
>>> end_points = numpy.array([[10, 0, 0], [0, 10, 0]])
>>> steps = numpy.arange(10)/9.0
>>> start_points.shape
(2, 3)
>>> steps.shape
(10,)
>>> steps[:,numpy.newaxis,numpy.newaxis].shape
(10, 1, 1)
>>> (steps[:,numpy.newaxis,numpy.newaxis] * start_points).shape
(10, 2, 3)
>>> (steps[:,numpy.newaxis,numpy.newaxis] * (end_points - start_points)) + start_points
array([[[  1.,   0.,   0.],
        [  0.,   1.,   0.]],
       [[  2.,   0.,   0.],
        [  0.,   2.,   0.]],
       [[  3.,   0.,   0.],
        [  0.,   3.,   0.]],
       [[  4.,   0.,   0.],
        [  0.,   4.,   0.]],
       [[  5.,   0.,   0.],
        [  0.,   5.,   0.]],
       [[  6.,   0.,   0.],
        [  0.,   6.,   0.]],
       [[  7.,   0.,   0.],
        [  0.,   7.,   0.]],
       [[  8.,   0.,   0.],
        [  0.,   8.,   0.]],
       [[  9.,   0.,   0.],
        [  0.,   9.,   0.]],
       [[ 10.,   0.,   0.],
        [  0.,  10.,   0.]]])

ご覧のとおり、これで正しい答えが得られます:) この場合、(10,1,1) と (2,3) をブロードキャストすると (10,2,3) になります。あなたが持っていたのは、ブロードキャスト (10,1,1) と (1,2,3) で、これはまったく同じであり、(10,2,3) も生成します。

質問の距離部分のコードには newaxis は必要ありません。入力は num_points x num_dimensions であり、出力は num_points であるため、1 つの次元を削除する必要があります。それは実際に合計する軸です。これはうまくいくはずです:

line_dist = numpy.sqrt( numpy.sum( (end_point - start_point) ** 2, axis=1 )

ここで numpy.sum(..., axis=1) は、すべての要素ではなく、その軸のみに沿った合計を意味します: 形状 num_points x num_dimensions が axis=1 に沿って合計された ndarray は、正しい num_points の結果を生成します。

編集:ブロードキャストせずにコード例を削除しました。編集: インデックスの順序を修正しました。編集: line_dist を追加

于 2012-11-16T13:14:00.827 に答える
1

私はあなたが書いたすべてを理解しているわけではありませんが、私がすでにあなたに話すことができるいくつかのこと。多分彼らは助けます。

newaxis関数というよりはむしろマーカーです(実際、それは明白ですNone)。これは、(未使用の)ディメンションを多次元値に追加するために使用されます。これを使用すると、2D値(またはそれ以上)から3D値を作成できます。入力値にすでに存在する各ディメンションは、インデックスのコロンで表す必要があり:ます(すべての値を使用する場合、ユースケースを超えて複雑になります)。追加するディメンションはで示されnewaxisます。

例:
入力は1次元ベクトル(1D)です:1,2,3
出力は行列(2D)でなければなりません。
これを実現するには2つの方法があります。ベクトルは、それぞれ1つの値で行を埋めることができます。または、ベクトルは、行列の最初で唯一の行を埋めることができます。1つ目は、によって作成されvector[:,newaxis]、2つ目はによって作成されvector[newaxis,:]ます。この結果:

>>> array([ 7,8,9 ])[:,newaxis]
array([[7],
       [8],
       [9]])
>>> array([ 7,8,9 ])[newaxis,:]
array([[7, 8, 9]])

(多次元値の次元は、もちろん配列のネストによって表されます。)

入力にさらに多くの次元がある場合は、コロンを複数回使用します(そうでない場合、ネストされたより深い次元は単に無視されます。つまり、配列は単純な値として扱われます)。3Dおよび4D値がネストされたブラケットを使用して2Dディスプレイに書き込まれる場合、光学的な複雑さのために物事を明確にしないため、ここにこれの表現を貼り付けません。とにかく明らかになることを願っています。

于 2012-11-16T11:02:01.520 に答える
0

newaxis は、numpy を乗算するときにブロードキャストを使用するように配列を再形成します。これは、ブロードキャストに関する優れたチュートリアルです。

step[:, newaxis, newaxis]step.reshape((step.shape[0], 1, 1))(if stepis 1d)と同じです。numpy での配列の再形成は非常に安価であるため、再形成のいずれの方法も非常に高速である必要があります。特に、一度だけ実行する必要があるため、配列のビューを作成するだけです。

于 2012-11-17T03:56:12.163 に答える