如何“扁平化”变量

时间:2018-02-08 20:38:22

标签: c# cntk

有时,通常在卷积层之后,可以找到形状(宽度,高度,深度)的形状,其中深度是来自卷积操作的多个滤波器。

我想重现GoogleNet初始模块并“压缩”(宽度,高度,深度)到(宽度,高度,f(深度)),其中f会产生标量值。

我知道有CNTKLib.Splice,但这不是我需要的。我需要得到列中所有值的加权和(x,y)坐标。

如何在C#API中完成?

编辑: 添加了代码示例

    public static void PrintOutputDims(Function source)
    {
        var shape = source.Output.Shape;

        var sb = new string[shape.Rank];
        for (var i = 0; i < shape.Rank; ++i)
        {
            sb[i] = ($"dim{i}: {shape[i]}");
        }

        Console.WriteLine(string.Join(", ", sb));
    }

    static void Main(string[] args)
    {
        var variable = CNTKLib.InputVariable(NDShape.CreateNDShape(new[] { 100, 100, 20 }), DataType.Float, "source");
        PrintOutputDims(variable); // dim0: 100, dim1: 100, dim2: 20
        var squished = Squish(variable);
        PrintOutputDims(variable); // dim0: 100, dim1: 100, dim2: 1
    }

如何实施Squish功能?

2 个答案:

答案 0 :(得分:2)

您可以使用ReduceSum / ReduceLogSum / ReduceMean / etc.轴= 2

答案 1 :(得分:2)

答案是这样的:

    public static Function SpatialReduceWeightedSum(this Function source, DeviceDescriptor device)
    {
        var sourceShape = source.Output.Shape;
        if (sourceShape.Rank != 3)
        {
            throw new ArgumentException("exected rank = 3 but was: " + sourceShape.Rank);
        }

        var sourceDimensions = sourceShape.Dimensions;
        var blocksCount = sourceDimensions[0] * sourceDimensions[1];
        var temporaryDimensions = new[]
                                      {
                                          blocksCount,
                                          sourceDimensions[2]
                                      };
        var temporatyShape = NDShape.CreateNDShape(temporaryDimensions);
        var reshaped = CNTKLib.Reshape(source, temporatyShape);

        var initializer = CNTKLib.ConstantInitializer(1d);
        var axis0 = new Axis(0);
        var axis1 = new Axis(1);
        var axisVector = new AxisVector() { axis0 };
        var weightedSums = new Variable[blocksCount];
        for (var i = 0; i < blocksCount; i++)
        {
            var beginIndex = new IntVector() { i };
            var endIndex = new IntVector() { i + 1 };
            var block = CNTKLib.Slice(reshaped, axisVector, beginIndex, endIndex);
            var blockShape = NDShape.CreateNDShape(block.Output.Shape.Dimensions.Reverse());
            var blockParameters = new Parameter(blockShape, DataType.Float, initializer, device);

            var weightedBlock = CNTKLib.Times(block, blockParameters);
            weightedSums[i] = CNTKLib.ReduceSum(weightedBlock, axis1);
        }

        var combined = CNTKLib.Splice(new VariableVector(weightedSums), axis0);

        var flatShapeDimensions = new[]
                                      {
                                          sourceDimensions[0],
                                          sourceDimensions[1],
                                          1
                                      };
        var flatShape = NDShape.CreateNDShape(flatShapeDimensions);

        return CNTKLib.Reshape(combined, flatShape);
    }