如何"flatten"变量
How to "flatten" variable
有时,通常在卷积层之后,可以找到形式为(宽度,高度,深度)的形状,其中深度是卷积操作的过滤器数量。
我想将 GoogleNet 初始模块和 "squish"(宽度、高度、深度)重现为(宽度、高度、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
功能?
您可以使用 ReduceSum/ReduceLogSum/ReduceMean/etc。轴 = 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);
}
有时,通常在卷积层之后,可以找到形式为(宽度,高度,深度)的形状,其中深度是卷积操作的过滤器数量。
我想将 GoogleNet 初始模块和 "squish"(宽度、高度、深度)重现为(宽度、高度、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
功能?
您可以使用 ReduceSum/ReduceLogSum/ReduceMean/etc。轴 = 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);
}