48790


chainerで画像認識をするためCNNを実装している際、ある２つの中間層の出力f1(サイズ(b1,c1,h1,w1))とf2(サイズ(b2,c2,h2,w2))に対して、同じバッチ内ですべてのc1,c2の組み合わせに対してその行列の要素積をとり和を取る、つまり行列の内積を計算するプログラムを実装し、動かしたところ、GPUメモリ上限を上回ってしまう以下のエラーが発生してしまいました。

[code]

    cupy.cuda.memory.OutOfMemoryError: out of memory to allocate 2684354560 bytes (total13247891968 bytes)
    
[/code]

よりメモリ効率の良いプログラムに改良したいのですが、よろしければアドバイスをいただけないでしょうか。以下に自分が実装したコードを載せます。エラーが出た部分は下から4行目の計算です。  
環境はchainerがversion4.1、pythonが3.6、GPUにはTITAN Xを使用しています。  
初質問で勝手がわからない部分もありますがよろしくお願いします。

[code]

    def make_FSPmatrix(fmap1,fmap2):
    
        b1,c1,h1,w1 = fmap1.shape
        b2,c2,h2,w2 = fmap2.shape
        if h1 > h2:
            h,w = h2,w2
            fmap1 = F.max_pooling_2d(fmap1,int(h1/h2))
        elif h2 > h1:
            h,w = h1,w1
            fmap2 = F.max_pooling_2d(fmap2,int(h2/h1))
        else:
            h,w, = h1,w1
        fm1_channel = F.transpose(fmap1,axes=(1,0,2,3))
        fm2_channel = F.transpose(fmap2,axes=(1,0,2,3))
        fsp_list = []
        #内積処理
        for i in range(len(fm2_channel)):
            fsp_list.append(fm1_channel*F.tile(fm2_channel[i][np.newaxis,:,:],(c1,1,1,1)))
        fsp_tuple = tuple(fsp_list)
        fsp = F.transpose(F.sum(F.concat(fsp_tuple,axis=0),axis=(2,3)))/(h*w)
        print(fsp.shape)
    
        return fsp
    
[/code]


CC BY-SA 4.0
2018-09-28T08:31:37.250
48788
2018-09-28T10:13:44.843
30268
question
python chainer
Chainerで２つの特徴マップ間の全チャネルに対する行列の内積を効率よく計算したい


面倒な和計算はeinsumに投げると簡単です．(少し親切でなかったので，Example Codeを書き換えました)

短く書けば以下で十分です．  
Code 1

[code]

    fsp = F.einsum("bcwh,bCwh->bwh", fmap1, fmap2)
    
[/code]

以下は検証用のコードです．

Code 2

[code]

    from chainer import functions as F
    import numpy as np
    
    
    batchsize = 3
    n_channel_feature1 = 4
    n_channel_feature2 = 5
    
    h = h_feature1 = h_feature2 = 10
    w = w_feature1 = w_feature2 = 10
    
    fmap1 = np.arange(batchsize * n_channel_feature1 * h * w, dtype=np.float32).reshape((batchsize, n_channel_feature1, h, w))
    fmap2 = np.arange(batchsize * n_channel_feature2 * h * w, dtype=np.float32).reshape((batchsize, n_channel_feature2, h, w))
    
    naive = np.empty((batchsize, h, w), dtype=np.float32)
    for b_idx in range(batchsize):
        for h_idx in range(h):
            for w_idx in range(w):
                f1 = fmap1[b_idx, :, h_idx, w_idx]
                f2 = fmap2[b_idx, :, h_idx, w_idx]
                naive[b_idx, h_idx, w_idx] = np.sum(np.dot(f1.reshape(n_channel_feature1, 1), f2.reshape(1, n_channel_feature2)))
    
    einsum = F.einsum("bchw,bChw->bhw", fmap1, fmap2)
    print((naive == einsum.array).all())
    
[/code]

Output 2

[code]

    True
    
[/code]


CC BY-SA 4.0
2018-09-28T10:00:53.933
48790
2018-09-28T10:13:44.843
2018-09-28T10:13:44.843
29620
29620
48788
answer