2016-08-22 16 views
0

トーチにカスタムsoftmaxレイヤーを実装すると、CPUモードで非常にうまく動作しますが、GPUモードに変更すると機能しません。順方向および逆方向の繰り返しを行った後、CPUモードでは各エポックごとに減少します。Torch:私のカスタムレイヤーがGPUで動作しない

マイカスタムソフトマックス層は

local MySoftMax, Parent = torch.class('nn.MySoftMax', 'nn.Module') 
function MySoftMax:__init() 
    Parent.__init(self) 
end 
--input = batch * 2 * 40 * 40 * 40 
--output = batch * 1 * 40 * 40 * 40 

function MySoftMax:updateOutput(input) 
    tmp_input = input:clone() 
    size_input = tmp_input:size() 
    self.output = torch.CudaTensor(size_input[1], 1, size_input[3], size_input[4], size_input[5]) 
    exp_input = tmp_input:exp() 
    for i = 1, size_input[1] do 
     tmp_output = exp_input[i][1]:clone() 
     sum_exp_input = exp_input[i][1]:add(exp_input[i][2]) 
     self.output[i][1] = tmp_output:cdiv(sum_exp_input) 
    end 
    return self.output 
end 

function MySoftMax:updateGradInput(input, gradOutput) 
    tmp_input = input:clone() 
    size_input = input:size() 
    self.gradInput = torch.CudaTensor(size_input[1], 2, size_input[3], size_input[4], size_input[5]) 
    exp_input = tmp_input:exp() 
    for i = 1, size_input[1] do 
     tmp_exp_input = exp_input[i][1]:clone() 
     add_exp = exp_input[i][1]:add(exp_input[i][2]) 
     pow_exp = add_exp:pow(2) 
     mul_exp = tmp_exp_input:cmul(exp_input[i][2]) 

     self.gradInput[i][1] = mul_exp:cdiv(pow_exp) 
     self.gradInput[i][2] = self.gradInput[i][1] 
     self.gradInput[i][2] = -self.gradInput[i][1] 
     self.gradInput[i][1]:cmul(gradOutput[i][1]) 
     self.gradInput[i][2]:cmul(gradOutput[i][1]) 
    end 
    return self.gradInput 
end 

で、GPUのトレーニングコードは次のとおりです。

model = model:cuda() 
criterion = criterion:cuda() 
inputs = torch.CudaTensor(batch_size, 1, bbx_size, bbx_size, bbx_size) 
targets = torch.CudaTensor(batch_size, 1, bbx_size, bbx_size, bbx_size) 
model:training() 
torch.manualSeed(train_size) 
shuffle = torch.randperm(train_size) 
print '==> epoch = ' 
print(epoch) 
epoch_error = 0.0 
for t = 1, train_size, batch_size do 
    xlua.progress(t, train_size) 
    for i = 1, batch_size do 
     inputs[i] = train_input[shuffle[t + i - 1]] 
     targets[i] = train_output[shuffle[t + i - 1]] 
    end 
    local feval = function(x) 
     gradParameters:zero() 
     outputs = model:forward(inputs) 
     err = criterion:forward(outputs, targets) 
     df_do = criterion:backward(outputs, targets) 
     model:backward(inputs, df_do) 
     epoch_error = epoch_error + err 
     return f, gradParameters 
    end 
    optim.sgd(feval, parameters, config) 
end 

私のモデルは次のとおりです。

cnn_state = {8, 16, 32, 64, 128} 
pool_size = 2 
filter_size = 2 
batch_size = 64 

model = nn.Sequential() 

--stage 1 
--1*40*40*40 
model:add(nn.VolumetricConvolution(1, cnn_state[1], filter_size, filter_size, filter_size)) 
model:add(nn.ReLU()) 
--8*39*39*39 
model:add(nn.VolumetricConvolution(cnn_state[1], cnn_state[2], filter_size, filter_size, filter_size)) 
model:add(nn.ReLU()) 
--16*38*38*38 
maxpool1 = nn.VolumetricMaxPooling(pool_size, pool_size, pool_size, pool_size, pool_size, pool_size) 
model:add(maxpool1) 
--16*19*19*19 

--stage 2 
--16*19*19*19 
model:add(nn.VolumetricConvolution(cnn_state[2], cnn_state[3], filter_size, filter_size, filter_size)) 
model:add(nn.ReLU()) 
--32*18*18*18 
model:add(nn.VolumetricConvolution(cnn_state[3], cnn_state[4], filter_size + 1, filter_size + 1, filter_size + 1)) 
model:add(nn.ReLU()) 
--64*16*16*16 
maxpool2 = nn.VolumetricMaxPooling(pool_size, pool_size, pool_size, pool_size, pool_size, pool_size) 
model:add(maxpool2) 
--64*8*8*8 

--stage 3 
model:add(nn.VolumetricConvolution(cnn_state[4],cnn_state[5], filter_size, filter_size, filter_size)) 
model:add(nn.ReLU()) 
--128*7*7*7 
--deconvolution 
model:add(nn.VolumetricFullConvolution(cnn_state[5], cnn_state[4], filter_size, filter_size, filter_size)) 
model:add(nn.ReLU()) 
--64*8*8*8 
model:add(nn.VolumetricMaxUnpooling(maxpool2)) 
--64*16*16*16 
model:add(nn.VolumetricFullConvolution(cnn_state[4], cnn_state[3], filter_size + 1, filter_size + 1, filter_size + 1)) 
model:add(nn.ReLU()) 
--32*18*18*18 
model:add(nn.VolumetricFullConvolution(cnn_state[3], cnn_state[2], filter_size, filter_size, filter_size)) 
model:add(nn.ReLU()) 
--16*19*19*19 
model:add(nn.VolumetricMaxUnpooling(maxpool1)) 
--16*38*38*38 
model:add(nn.VolumetricFullConvolution(cnn_state[2], cnn_state[1], filter_size, filter_size, filter_size)) 
model:add(nn.ReLU()) 
--8*39*39*39 
model:add(nn.VolumetricFullConvolution(cnn_state[1], 2, filter_size, filter_size, filter_size)) 
--2*40*40*40 
model:add(nn.MySoftMax()) 

私のモデルでは、それはだCPUモードで正常に動作しますCudaTensorの代わりにTenserを使用すると、損失が減少し、予測が良くなります。 GPUモードでは動作しません。 私の問題は、私のカスタムレイヤの実装にあるかもしれないと思うかもしれません。多分GPUでは動作しません。 GPUでレイヤーを実装する際に注意が必要なことはありますか?または私のコードに何か問題がありますか?

答えて

0

これはあなたの特定のケースで起こることはわかりませんが、通常はgradInputのような状態変数のポインタを変更しないでください。何とかバックプロンプトがそれに依存している場合もあります。

self.gradInput.copy(torch.CudaTensor(size_input[1], 2, size_input[3], size_input[4], size_input[5])) 
:この行で、この行

self.gradInput = torch.CudaTensor(size_input[1], 2, size_input[3], size_input[4], size_input[5]) 

を変更してみてください

関連する問題