caffeとpytorchの結果の一貫性をテストする
目次
caffeとpytorchの結果の一貫性をテストする
最も簡単なボリュームを例に挙げます.
caffeモデル
name: "conv_test"
layer {
name: "data"
type: "Input"
top: "data"
input_param { shape: { dim: 1 dim: 32 dim: 21 dim: 21 } }
}
layer {
name: "conv1"
type: "Convolution"
bottom: "data"
top: "conv1"
convolution_param {
num_output: 64
kernel_size: 3
stride: 1
}
}
pytorchモデルとコンシステンシテストコード
import torch
import caffe
import numpy as np
class TorchConv(torch.nn.Module):
def __init__(self):
super(TorchConv, self).__init__()
self.layer1 = torch.nn.Conv2d(32, 64, (3, 3))
def forward(self, x):
out = self.layer1(x)
return out
def torch_conv_layer_test():
#
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
net = TorchConv().to(device).eval()
#
np_weight = np.random.seed(1)
#
weight = net.layer1.weight
bias = net.layer1.bias
np_weight = np.random.randn(*weight.shape)
net.layer1.weight = torch.nn.Parameter(torch.from_numpy(np_weight).to(device))
np_bias = np.random.randn(*bias.shape)
net.layer1.bias = torch.nn.Parameter(torch.from_numpy(np_bias).to(device))
#
input_tonsor = torch.from_numpy(np.random.randn(1, 32, 21, 21)).to(device)
#
output = net(input_tonsor)
output_np = output.detach().cpu().numpy()
return output_np
def caffe_conv_layer_test():
#
net = caffe.Net('consistency/conv.prototxt', caffe.TEST)
#
np_weight = np.random.seed(1)
#
conv_layer_params = list(net.params.values())[0]
weight = conv_layer_params[0].data
weight[...] = np.random.randn(*weight.shape)
bias = conv_layer_params[1].data
bias[...] = np.random.randn(*bias.shape)
#
input_data = net.blobs[net.inputs[0]].data
input_data[...] = np.random.randn(1, 32, 21, 21)
#
output = net.forward()
output_np = np.array(output[net.outputs[0]])
return output_np
def main():
caffe_out = caffe_conv_layer_test()
torch_out = torch_conv_layer_test()
print()
#
mse = np.square(torch_out - caffe_out).mean(axis=None)
print("MSE is", mse)
if __name__ == "__main__":
main()
要素の平均二乗誤差を用いて差異を測定し,最終的な印刷結果はMSE is 2.7442352745900254e-11
であり,差は小さい.
name: "conv_test"
layer {
name: "data"
type: "Input"
top: "data"
input_param { shape: { dim: 1 dim: 32 dim: 21 dim: 21 } }
}
layer {
name: "conv1"
type: "Convolution"
bottom: "data"
top: "conv1"
convolution_param {
num_output: 64
kernel_size: 3
stride: 1
}
}
import torch
import caffe
import numpy as np
class TorchConv(torch.nn.Module):
def __init__(self):
super(TorchConv, self).__init__()
self.layer1 = torch.nn.Conv2d(32, 64, (3, 3))
def forward(self, x):
out = self.layer1(x)
return out
def torch_conv_layer_test():
#
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
net = TorchConv().to(device).eval()
#
np_weight = np.random.seed(1)
#
weight = net.layer1.weight
bias = net.layer1.bias
np_weight = np.random.randn(*weight.shape)
net.layer1.weight = torch.nn.Parameter(torch.from_numpy(np_weight).to(device))
np_bias = np.random.randn(*bias.shape)
net.layer1.bias = torch.nn.Parameter(torch.from_numpy(np_bias).to(device))
#
input_tonsor = torch.from_numpy(np.random.randn(1, 32, 21, 21)).to(device)
#
output = net(input_tonsor)
output_np = output.detach().cpu().numpy()
return output_np
def caffe_conv_layer_test():
#
net = caffe.Net('consistency/conv.prototxt', caffe.TEST)
#
np_weight = np.random.seed(1)
#
conv_layer_params = list(net.params.values())[0]
weight = conv_layer_params[0].data
weight[...] = np.random.randn(*weight.shape)
bias = conv_layer_params[1].data
bias[...] = np.random.randn(*bias.shape)
#
input_data = net.blobs[net.inputs[0]].data
input_data[...] = np.random.randn(1, 32, 21, 21)
#
output = net.forward()
output_np = np.array(output[net.outputs[0]])
return output_np
def main():
caffe_out = caffe_conv_layer_test()
torch_out = torch_conv_layer_test()
print()
#
mse = np.square(torch_out - caffe_out).mean(axis=None)
print("MSE is", mse)
if __name__ == "__main__":
main()