2

numpy に次のデータセットがあります

indices | real data (X)    |targets (y)
        |                  |
0   0   | 43.25 665.32 ... |2.4      } 1st block
0   0   | 11.234           |-4.5     }
0   1     ...               ...      } 2nd block
0   1                                } 
0   2                                } 3rd block
0   2                                }
1   0                                } 4th block
1   0                                }
1   0                                }
1   1                       ...
1   1                       
1   2
1   2
2   0
2   0 
2   1
2   1
2   1
...

論文は私の変数です

idx1 = data[:,0]
idx2 = data[:,1]
X = data[:,2:-1]
y = data[:,-1]

W3D 配列である変数もあります。

コードで行う必要があるのは、データセット内のすべてのブロックをループ処理し、計算後に各ブロックのスカラー値を返し、すべてのスカラーを合計して という変数に格納することですcost。問題は、ループの実装が非常に遅いことです。そのため、可能であればベクトル化しようとしています。これが私の現在のコードです。numpy の for ループなしでこれを行うことは可能ですか?

IDX1 = 0
IDX2 = 1

# get unique indices
idx1s = np.arange(len(np.unique(data[:,IDX1])))
idx2s = np.arange(len(np.unique(data[:,IDX2])))

# initialize global sum variable to 0
cost = 0
for i1 in idx1s:
    for i2 in idx2:

        # for each block in the dataset
        mask = np.nonzero((data[:,IDX1] == i1) & (data[:,IDX2] == i2))

        # get variables for that block
        curr_X = X[mask,:]
        curr_y = y[mask]
        curr_W = W[:,i2,i1]

        # calculate a scalar  
        pred = np.dot(curr_X,curr_W)
        sigm = 1.0 / (1.0 + np.exp(-pred))
        loss = np.sum((sigm- (0.5)) * curr_y)

        # add result to global cost
        cost += loss

ここにいくつかのサンプルデータがあります

data = np.array([[0,0,5,5,7],
                 [0,0,5,5,7],
                 [0,1,5,5,7],
                 [0,1,5,5,7],
                 [1,0,5,5,7],
                 [1,1,5,5,7]])
W = np.zeros((2,2,2))
idx1 = data[:,0]
idx2 = data[:,1]
X = data[:,2:-1]
y = data[:,-1]
4

3 に答える 3

3

それはトリッキーでした...実際、あなたのブロックは、対応するを実行するためWの適切なスライスを取得することを除けば、かなり無関係です。そのため、次のように配列を作成する簡単な方法を使用しました。Wnp.dotXaligned_W

aligned_W = W[:, idx2, idx1]

これは形状の配列で(2, rows)rowsはデータ セットの行数です。次のように、for ループなしで計算全体を実行できるようになりました。

from numpy.core.umath_tests import inner1d
pred = inner1d(X, aligned_W.T)
sigm = 1.0 / (1.0 + np.exp(-pred))
loss = (sigm - 0.5) * curr_y
cost = np.sum(loss)
于 2013-04-09T15:34:47.027 に答える
2

私の推測では、コードが遅い主な理由は次の行です。

mask = np.nonzero((data[:,IDX1] == i1) & (data[:,IDX2] == i2))

入力配列を繰り返しスキャンして、関心のある少数の行を探すためです。したがって、次のことを行う必要があります。

ni1 = len(np.unique(data[:,IDX1]))
ni2 = len(np.unique(data[:,IDX2]))
idx1s = np.arange(ni1)                         
idx2s = np.arange(ni2)

key = data[:,IDX1] * ni2 + data[:,IDX2] # 1D key to the rows

sortids = np.argsort(key) #indices to the sorted key

次に、代わりにループ内

mask=np.nonzero(...)

あなたがする必要があります

curid = i1 * ni2 + i2
left = np.searchsorted(key, curid, 'left', sorter=sortids)
right=np.searchsorted(key, curid, 'right', sorter=sortids)
mask = sortids[left:right]
于 2013-04-09T15:43:12.120 に答える
1

for ループを使用せずに異なるサイズの numpy 配列を比較する方法はないと思います。次のようなものの出力の意味と形状を判断するのは難しいでしょう

[0,1,2,3,4] == [3,4,2]

私があなたにできる唯一の提案は、次を使用して for ループの 1 つを取り除くことですitertools.product

import itertools as it

[...]

idx1s = np.unique(data[:,IDX1])
idx2s = np.unique(data[:,IDX2])

# initialize global sum variable to 0
cost = 0
for i1, i2 in it.product(idx1s, idx2):

    # for each block in the dataset
    mask = np.nonzero((data[:,IDX1] == i1) & (data[:,IDX2] == i2))

    # get variables for that block
    curr_X = X[mask,:]
    curr_y = y[mask]
    [...]

maskブール配列として保持することもできます

mask = (data[:,IDX1] == i1) & (data[:,IDX2] == i2)

出力は同じで、とにかくメモリを使用して bool 配列を作成する必要があります。このようにすることで、メモリと関数の評価を節約できます

編集

インデックスに穴がない、または穴がほとんどないことがわかっている場合は、定義する部分を削除し、for ループを次のように変更idx1sする価値があります。idxs2

max1, max2 = data[:,[IDX1, IDX2]].max(axis=0)
for i1, i2 in it.product(xrange(max1), xrange(max2)):
    [...]

xrangeとはどちらit.productも反復子であるため、必要なときにだけ作成i1します。i2

ps: python3.x を使用している場合は、range代わりにxrange

于 2013-04-09T15:16:26.863 に答える