mirror of
https://github.com/saymrwulf/pytorch.git
synced 2026-05-15 21:00:47 +00:00
Summary: This diff adds shape inference for the SoftmaxWithLoss Operator Differential Revision: D4565835 fbshipit-source-id: 1c2db398524c765977ec4d8a22c9b986bf9faf82
238 lines
7.5 KiB
Python
238 lines
7.5 KiB
Python
import unittest
|
|
|
|
import numpy as np
|
|
from caffe2.proto import caffe2_pb2
|
|
from caffe2.python import core, workspace, test_util, cnn
|
|
|
|
|
|
class TestShapeInference(test_util.TestCase):
|
|
|
|
def testShapeInferenceSimpleFC(self):
|
|
m = cnn.CNNModelHelper()
|
|
|
|
m.FC("data", "fc1", dim_in=96, dim_out=32)
|
|
m.FC("fc1", "fc2", dim_in=32, dim_out=55)
|
|
|
|
(shapes, types) = workspace.InferShapesAndTypes(
|
|
[m.param_init_net, m.net],
|
|
{'data': [64, 96]}
|
|
)
|
|
|
|
self.assertEquals(shapes['data'], [64, 96])
|
|
self.assertEquals(shapes['fc1_w'], [32, 96])
|
|
self.assertEquals(shapes['fc1_b'], [32])
|
|
self.assertEquals(shapes['fc1'], [64, 32])
|
|
self.assertEquals(shapes['fc2_w'], [55, 32])
|
|
self.assertEquals(shapes['fc2_b'], [55])
|
|
self.assertEquals(shapes['fc2'], [64, 55])
|
|
|
|
def testShapeInferencDistances(self):
|
|
model = cnn.CNNModelHelper()
|
|
model.SquaredL2Distance(["x", "y"], "zsq")
|
|
model.CosineSimilarity(["x", "y"], "zcos")
|
|
model.DotProduct(["x", "y"], "zdot")
|
|
|
|
workspace.FeedBlob("x", np.random.rand(10).astype(np.float32))
|
|
workspace.FeedBlob("y", np.random.rand(10).astype(np.float32))
|
|
self.InferTensorRunAndCompare(model)
|
|
|
|
def testShapeInferenceConvNet(self):
|
|
model = cnn.CNNModelHelper(name="convtest", order="NCHW")
|
|
model.NHWC2NCHW("data", "data_nchw")
|
|
model.Conv("data_nchw", 'conv1', 3, 64,
|
|
weight_init=("MSRAFill", {}), kernel=7,
|
|
stride=2, pad=3, no_bias=0)
|
|
model.SpatialBN('conv1', 'conv1_spatbn_relu', 64, epsilon=1e-3)
|
|
model.Relu('conv1_spatbn_relu', 'conv1_spatbn_relu')
|
|
model.MaxPool('conv1_spatbn_relu', 'pool1', kernel=3, stride=2)
|
|
model.FC('pool1', 'fc', dim_in=(64 * 56 * 56), dim_out=100)
|
|
model.Sigmoid('fc', 'fc_sigm')
|
|
model.Softmax('fc_sigm', 'softmax')
|
|
|
|
workspace.FeedBlob(
|
|
"data",
|
|
np.random.rand(16, 227, 227, 3).astype(np.float32),
|
|
)
|
|
# Then do automatic comparison test: run the next once to
|
|
# initialize everything
|
|
self.InferTensorRunAndCompare(model)
|
|
|
|
def testShapeInferenceTranspose(self):
|
|
model = cnn.CNNModelHelper()
|
|
|
|
workspace.FeedBlob(
|
|
"tensor",
|
|
np.random.rand(4, 2, 3, 3, 5).astype(np.float32)
|
|
)
|
|
|
|
# Testing with axes undefined
|
|
model.Transpose(
|
|
["tensor"],
|
|
"transpose",
|
|
)
|
|
self.InferTensorRunAndCompare(model)
|
|
|
|
# Testing with axes defined
|
|
model.Transpose(
|
|
["tensor"],
|
|
"transpose",
|
|
axes=np.random.permutation(5)
|
|
)
|
|
|
|
return self.InferTensorRunAndCompare(model)
|
|
|
|
def testShapeInferencePad(self):
|
|
model = cnn.CNNModelHelper(name="padtest")
|
|
model.PadImage("data", 'padded', pad_t=100, pad_l=37, pad_b=28,
|
|
pad_r=20, mode="constant", order="NCHW")
|
|
|
|
workspace.FeedBlob(
|
|
"data",
|
|
np.random.rand(16, 3, 228, 228).astype(np.float32),
|
|
)
|
|
|
|
self.InferTensorRunAndCompare(model)
|
|
|
|
def testShapeInferencePadZero(self):
|
|
model = cnn.CNNModelHelper(name="padtest")
|
|
model.PadImage("data", 'padded', pad=0, mode="constant",
|
|
order="NCHW")
|
|
|
|
workspace.FeedBlob(
|
|
"data",
|
|
np.random.rand(16, 3, 228, 228).astype(np.float32),
|
|
)
|
|
|
|
self.InferTensorRunAndCompare(model)
|
|
|
|
def testShapeInferenceMatMul(self):
|
|
model = cnn.CNNModelHelper()
|
|
|
|
model.MatMul(["x", "y"], "MatMul")
|
|
|
|
workspace.FeedBlob("x", np.random.rand(10, 5).astype(np.float32))
|
|
workspace.FeedBlob("y", np.random.rand(5, 10).astype(np.float32))
|
|
|
|
self.InferTensorRunAndCompare(model)
|
|
|
|
def testShapeInferenceSoftmaxWithLoss(self):
|
|
model = cnn.CNNModelHelper()
|
|
|
|
model.SoftmaxWithLoss(
|
|
["logits", "labels"],
|
|
["softmax", "loss"],
|
|
)
|
|
|
|
# 2D Shape of [batch_size, num_classes]
|
|
workspace.FeedBlob(
|
|
"logits",
|
|
np.random.rand(4, 3).astype(np.float32),
|
|
)
|
|
|
|
# Shape of size batch_size with all values [0, num_classes)
|
|
workspace.FeedBlob(
|
|
"labels",
|
|
np.random.randint(low=0, high=3, size=(4, 1)).astype(np.int32),
|
|
)
|
|
self.InferTensorRunAndCompare(model)
|
|
|
|
# Testing with 1D labels arg
|
|
workspace.FeedBlob(
|
|
"logits",
|
|
np.random.rand(4, 3).astype(np.float32),
|
|
)
|
|
|
|
workspace.FeedBlob(
|
|
"labels",
|
|
np.random.randint(low=0, high=3, size=4).astype(np.int32),
|
|
)
|
|
self.InferTensorRunAndCompare(model)
|
|
|
|
# Testing with weight_tensor
|
|
model.SoftmaxWithLoss(
|
|
["logits", "labels", "weight_tensor"],
|
|
["softmax", "loss"],
|
|
)
|
|
|
|
workspace.FeedBlob(
|
|
"logits",
|
|
np.random.rand(4, 3).astype(np.float32),
|
|
)
|
|
|
|
workspace.FeedBlob(
|
|
"labels",
|
|
np.random.randint(low=0, high=3, size=4).astype(np.int32),
|
|
)
|
|
|
|
workspace.FeedBlob(
|
|
"weight_tensor",
|
|
np.random.rand(4).astype(np.float32),
|
|
)
|
|
self.InferTensorRunAndCompare(model)
|
|
|
|
def InferTensorRunAndCompare(self, model):
|
|
'''
|
|
Runs shape inference, and then the model to check
|
|
that the inferred shapes agree with the actual ones
|
|
'''
|
|
(shapes, types) = workspace.InferShapesAndTypes(
|
|
[model.param_init_net, model.net],
|
|
)
|
|
|
|
# .. Create net
|
|
workspace.RunNetOnce(model.param_init_net)
|
|
workspace.CreateNet(model.net)
|
|
workspace.RunNet(model.Proto().name)
|
|
|
|
# ... and then check the shapes mismatch
|
|
correct_shapes = {}
|
|
correct_types = {}
|
|
for b in workspace.Blobs():
|
|
arr = workspace.FetchBlob(b)
|
|
correct_shapes[b] = arr.shape
|
|
if type(arr) is np.ndarray:
|
|
if arr.dtype == np.dtype('float64'):
|
|
correct_types[b] = caffe2_pb2.TensorProto.DOUBLE
|
|
elif arr.dtype == np.dtype('float32'):
|
|
correct_types[b] = caffe2_pb2.TensorProto.FLOAT
|
|
elif arr.dtype == np.dtype('int32'):
|
|
correct_types[b] = caffe2_pb2.TensorProto.INT32
|
|
elif arr.dtype == np.dtype('int64'):
|
|
correct_types[b] = caffe2_pb2.TensorProto.INT64
|
|
else:
|
|
correct_types[b] = "unknown {}".format(np.dtype)
|
|
else:
|
|
correct_types[b] = str(type(arr))
|
|
|
|
for b in correct_shapes:
|
|
self.assertTrue(
|
|
np.array_equal(
|
|
np.array(shapes[b]).astype(np.int32),
|
|
np.array(correct_shapes[b]).astype(np.int32)
|
|
),
|
|
"Shape {} mismatch: {} vs. {}".format(
|
|
b, shapes[b], correct_shapes[b]
|
|
)
|
|
)
|
|
self.assertFalse(
|
|
b not in types and b in correct_types,
|
|
"Type for {} not defined".format(b),
|
|
)
|
|
|
|
# BUG: Workspace blob type not being set correctly T16121392
|
|
if correct_types[b] == caffe2_pb2.TensorProto.INT32:
|
|
continue
|
|
|
|
self.assertEqual(
|
|
types[b],
|
|
correct_types[b],
|
|
"Type {} mismatch: {} vs. {}".format(
|
|
b, types[b], correct_types[b],
|
|
)
|
|
)
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
import unittest
|
|
unittest.main()
|