private Layer ConvertSpaceToBatchNd(tflite.Operator op) { var inputs = op.GetInputsArray(); var input = _graph.Tensors(inputs[0]).Value; var blockShape = _graph.Tensors(inputs[1]).Value; var paddings = _graph.Tensors(inputs[2]).Value; var layer = new SpaceToBatchNd(input.GetShapeArray().ToNCHW(), _model.GetTensor <int>(blockShape), _model.GetTensor <int>(paddings)); _inputs.Add(layer.Input, inputs[0]); _outputs.Add(op.Outputs(0), layer.Output); return(layer); }
private Layer ConvertConv2d(paddle.OpDesc op) { var padding = GetAttr(op, "paddings").Ints; var strides = GetAttr(op, "strides").Ints.ToArray(); var groups = GetAttr(op, "groups").I; if (strides[0] == 0) { strides[0] = 1; } if (strides[1] == 0) { strides[1] = 1; } var input = GetParameter(op.Inputs, "Input").Arguments[0]; var weights = GetParameter(op.Inputs, "Filter").Arguments[0]; var weightsShape = GetVarShape(weights); var kernelWidth = weightsShape[3]; var kernelHeight = weightsShape[2]; var output = GetParameter(op.Outputs, "Output").Arguments[0]; if (groups == 1) { Conv2d conv2d; if (padding[0] == 1 && padding[1] == 1 && strides[0] == 2 && strides[1] == 2 && kernelWidth == 3 && kernelHeight == 3) { var space = new SpaceToBatchNd(GetVarShape(input), new[] { 1, 1 }.ToTensor(), new[, ] { { 1, 1 }, { 1, 1, } }.ToTensor()); conv2d = new Conv2d(space.Output.Dimensions, LoadVarData <float>(weights), null, Padding.Valid, strides[1], strides[0], ActivationFunctionType.Linear); conv2d.Input.SetConnection(space.Output); _inputs.Add(space.Input, input); } else { if (padding[0] != padding[1] || (padding[0] != 0 && padding[0] != 1)) { throw new NotSupportedException(); } conv2d = new Conv2d(GetVarShape(input), LoadVarData <float>(weights), null, Padding.Same, strides[1], strides[0], ActivationFunctionType.Linear); _inputs.Add(conv2d.Input, input); } _outputs.Add(output, conv2d.Output); return(conv2d); } else if (groups == weightsShape[0]) { var w = LoadVarData <float>(weights).Transpose(new[] { 1, 0, 2, 3 }); DepthwiseConv2d dwConv2d; if (padding[0] == 1 && padding[1] == 1 && strides[0] == 2 && strides[1] == 2 && kernelWidth == 3 && kernelHeight == 3) { var space = new SpaceToBatchNd(GetVarShape(input), new[] { 1, 1 }.ToTensor(), new[, ] { { 1, 1 }, { 1, 1, } }.ToTensor()); dwConv2d = new DepthwiseConv2d(space.Output.Dimensions, w, null, Padding.Valid, strides[1], strides[0], ActivationFunctionType.Linear); dwConv2d.Input.SetConnection(space.Output); _inputs.Add(space.Input, input); } else { if (padding[0] != padding[1] || (padding[0] != 0 && padding[0] != 1)) { throw new NotSupportedException(); } dwConv2d = new DepthwiseConv2d(GetVarShape(input), w, null, Padding.Same, strides[1], strides[0], ActivationFunctionType.Linear); _inputs.Add(dwConv2d.Input, input); } _outputs.Add(output, dwConv2d.Output); return(dwConv2d); } else { throw new NotSupportedException(); } }
private Layer ConvertConvolution(LayerParameter layerParam) { var input = _outputs[layerParam.Bottom[0]]; var param = layerParam.ConvolutionParam; uint[] GetDefault(Google.Protobuf.Collections.RepeatedField <uint> field) { if (field.Count == 0) { return new uint[] { 1, 1 } } ; else if (field.Count == 1) { return new[] { field[0], field[0] } } ; else { return(field.ToArray()); } } var padding = GetDefault(param.Pad); var strides = GetDefault(param.Stride); var kernelSize = param.KernelSize.Count == 1 ? new[] { param.KernelSize[0], param.KernelSize[0] } : (param.KernelSize.Count == 0 ? new[] { param.KernelH, param.KernelW } : param.KernelSize.ToArray()); var group = param.Group == 0 ? 1 : param.Group; if (group == 1) { var weights = LoadBlob(layerParam.Blobs[0]); Conv2d conv2d; if (padding[0] != 0 || padding[1] != 0) { if (padding[0] == 1 && padding[1] == 1 && strides[0] == 1 && strides[1] == 1) { conv2d = new Conv2d(input.Dimensions, weights, null, Padding.Same, 1, 1, ActivationFunctionType.Linear); conv2d.Input.SetConnection(input); } else { var space = new SpaceToBatchNd(input.Dimensions, new[] { 1, 1 }.ToTensor(), new[, ] { { (int)padding[0], (int)padding[0] }, { (int)padding[1], (int)padding[1], } }.ToTensor()); conv2d = new Conv2d(space.Output.Dimensions, weights, null, Padding.Valid, (int)strides[1], (int)strides[0], ActivationFunctionType.Linear); space.Input.SetConnection(input); conv2d.Input.SetConnection(space.Output); } } else { conv2d = new Conv2d(input.Dimensions, weights, null, Padding.Valid, (int)strides[1], (int)strides[0], ActivationFunctionType.Linear); conv2d.Input.SetConnection(input); } _outputs.Add(layerParam.Top[0], conv2d.Output); return(conv2d); } else if (group == param.NumOutput) { var weights = LoadBlob(layerParam.Blobs[0]).Transpose(new[] { 1, 0, 2, 3 }); DepthwiseConv2d dwConv2d; if (padding[0] != 0 || padding[1] != 0) { if (padding[0] == 1 && padding[1] == 1 && strides[0] == 1 && strides[1] == 1) { dwConv2d = new DepthwiseConv2d(input.Dimensions, weights, null, Padding.Same, 1, 1, ActivationFunctionType.Linear); dwConv2d.Input.SetConnection(input); } else { var space = new SpaceToBatchNd(input.Dimensions, new[] { 1, 1 }.ToTensor(), new[, ] { { (int)padding[0], (int)padding[0] }, { (int)padding[1], (int)padding[1], } }.ToTensor()); dwConv2d = new DepthwiseConv2d(space.Output.Dimensions, weights, null, Padding.Valid, (int)strides[1], (int)strides[0], ActivationFunctionType.Linear); space.Input.SetConnection(input); dwConv2d.Input.SetConnection(space.Output); } } else { dwConv2d = new DepthwiseConv2d(input.Dimensions, weights, null, Padding.Valid, (int)strides[1], (int)strides[0], ActivationFunctionType.Linear); dwConv2d.Input.SetConnection(input); } _outputs.Add(layerParam.Top[0], dwConv2d.Output); return(dwConv2d); } else { throw new NotSupportedException("Grouped conv2d is not supported."); } }