void RunEvaluationOneHidden(FunctionPtr evalFunc, const DeviceDescriptor& device) { const std::wstring inputNodeName = L"features"; const std::wstring outputNodeName = L"out.z_output"; Variable inputVar; if (!GetInputVariableByName(evalFunc, inputNodeName, inputVar)) { fprintf(stderr, "Input variable %S is not available.\n", inputNodeName.c_str()); throw("Input variable not found error."); } Variable outputVar; if (!GetOutputVaraiableByName(evalFunc, outputNodeName, outputVar)) { fprintf(stderr, "Output variable %S is not available.\n", outputNodeName.c_str()); throw("Output variable not found error."); } // Evaluate the network in several runs size_t iterationCount = 4; size_t numSamples = 3; for (size_t t = 0; t < iterationCount; ++t) { std::vector<float> inputData(inputVar.Shape().TotalSize() * numSamples); for (size_t i = 0; i < inputData.size(); ++i) { inputData[i] = static_cast<float>(i % 255); } NDShape inputShape = inputVar.Shape().AppendShape({1, numSamples}); ValuePtr inputValue = MakeSharedObject<Value>(MakeSharedObject<NDArrayView>(inputShape, inputData, true)); ValuePtr outputValue; std::unordered_map<Variable, ValuePtr> outputs = {{outputVar, outputValue}}; evalFunc->Forward({{inputVar, inputValue}}, outputs, device); outputValue = outputs[outputVar]; NDShape outputShape = outputVar.Shape().AppendShape({1, numSamples}); std::vector<float> outputData(outputShape.TotalSize()); NDArrayViewPtr cpuArrayOutput = MakeSharedObject<NDArrayView>(outputShape, outputData, false); cpuArrayOutput->CopyFrom(*outputValue->Data()); assert(outputData.size() == outputVar.Shape()[0] * numSamples); fprintf(stderr, "Evaluation result:\n"); size_t dataIndex = 0; auto outputDim = outputVar.Shape()[0]; for (size_t i = 0; i < numSamples; i++) { fprintf(stderr, "Iteration:%lu, Sample %lu:\n", t, i); fprintf(stderr, "Ouput:"); for (size_t j = 0; j < outputDim; j++) { fprintf(stderr, "%f ", outputData[dataIndex++]); } fprintf(stderr, "\n"); } } }
void RunEvaluationClassifier(FunctionPtr evalFunc, const DeviceDescriptor& device) { const std::wstring inputNodeName = L"features"; Variable inputVar; if (!GetInputVariableByName(evalFunc, inputNodeName, inputVar)) { fprintf(stderr, "Input variable %S is not available.\n", inputNodeName.c_str()); throw("Input variable not found error."); } // Evaluate the network in several runs size_t iterationCount = 4; unsigned int randSeed = 2; srand(randSeed); size_t numSamples = 3; std::vector<float> inputData(inputVar.Shape().TotalSize() * numSamples); for (size_t t = 0; t < iterationCount; ++t) { for (size_t i = 0; i < inputData.size(); ++i) { inputData[i] = ((float)rand()) / RAND_MAX; } // Create input data shape. Adding sequence length and numSamples as axes. // Todo: remove sequence length when only numSamples is supported. // Todo: add convenience APIs to simplify data preparation here. NDShape inputShape = inputVar.Shape().AppendShape({1, numSamples}); ValuePtr inputValue = MakeSharedObject<Value>(MakeSharedObject<NDArrayView>(inputShape, inputData, true)); // Define output. ValuePtr outputValue; auto outputVar = evalFunc->Output(); std::unordered_map<Variable, ValuePtr> outputs = {{outputVar, outputValue}}; // Evaluate the model evalFunc->Forward({{inputVar, inputValue}}, outputs, device); // Get output value outputValue = outputs[outputVar]; // Todo: remove sequence length when only numSamples is supported. // Todo: add convenience APIs to simplify retrieval of output results. NDShape outputShape = outputVar.Shape().AppendShape({1, numSamples}); std::vector<float> outputData(outputShape.TotalSize()); NDArrayViewPtr cpuArrayOutput = MakeSharedObject<NDArrayView>(outputShape, outputData, false); cpuArrayOutput->CopyFrom(*outputValue->Data()); assert(outputData.size() == outputVar.Shape()[0] * numSamples); fprintf(stderr, "Evaluation result:\n"); size_t dataIndex = 0; auto outputDim = outputVar.Shape()[0]; for (size_t i = 0; i < numSamples; i++) { fprintf(stderr, "Iteration:%lu, Sample %lu:\n", t, i); fprintf(stderr, " "); dataIndex = i * outputDim; for (size_t j = 0; j < std::min((size_t)10, outputDim); j++) { fprintf(stderr, "%f ", outputData[dataIndex++]); } if (outputDim > 10) { fprintf(stderr, "..."); } fprintf(stderr, "\n"); } } }
void TestReduceSum(size_t sampleRank, const DeviceDescriptor& device) { size_t numSequences = 7; size_t maxAllowedSequenceLength = 11; size_t maxDimSize = 23; NDShape inputShape(sampleRank); for (size_t i = 0; i < sampleRank; ++i) inputShape[i] = (rand() % maxDimSize) + 1; auto sequenceLengths = GenerateSequenceLengths(numSequences, maxAllowedSequenceLength); auto sequences = GenerateSequences<float>(sequenceLengths, inputShape); ValuePtr sequencesValue = Value::Create(inputShape, sequences, device, true); // Test ReduceSum along a static axis { auto testReduceSum = [&sequences, &sequenceLengths, inputShape, sequencesValue, device, sampleRank](int reductionAxis, bool useNegativeAxisIndex) { size_t maxActualSequenceLength = sequencesValue->Shape()[inputShape.Rank()]; size_t numSequences = sequencesValue->Shape()[inputShape.Rank() + 1]; auto inputVar = InputVariable(inputShape, DataType::Float, L"input"); FunctionPtr reduceSumFunc; bool reduceAll = (reductionAxis < 0); if (reduceAll) reduceSumFunc = ReduceSum(inputVar); else reduceSumFunc = ReduceSum(inputVar, Axis(useNegativeAxisIndex ? (reductionAxis - (int)sampleRank) : reductionAxis)); NDShape outputShape = reduceSumFunc->Output().Shape(); NDShape outputDataShape = outputShape; if (!reduceAll) outputDataShape = outputDataShape.AppendShape({ maxActualSequenceLength, numSequences }); std::vector<float> outputData(outputDataShape.TotalSize()); ValuePtr outputValue = MakeSharedObject<Value>(MakeSharedObject<NDArrayView>(outputDataShape, outputData, false), reduceAll ? nullptr : sequencesValue->Mask()->DeepClone()); std::unordered_map<Variable, ValuePtr> outputs = { { reduceSumFunc->Output(), outputValue } }; reduceSumFunc->Forward({ { inputVar, sequencesValue } }, outputs, device); std::vector<size_t> inputShapeStrides = GetStrides(inputShape); std::vector<size_t> outputShapeStrides = GetStrides(outputShape); std::vector<float> expectedPerFrameTotals(outputShape.TotalSize() * maxActualSequenceLength * numSequences, 0.0f); float expectedTotal = 0.0f; for (size_t i = 0; i < numSequences; ++i) { size_t currentSequenceLength = sequenceLengths[i]; for (size_t j = 0; j < currentSequenceLength; ++j) { for (size_t k = 0; k < inputShape.TotalSize(); ++k) { auto inputIdx = UnflattenedShape(k, inputShapeStrides); auto outputIdx = inputIdx; if (!reduceAll) outputIdx[reductionAxis] = 0; else outputIdx = {}; auto flatOutputIdx = FlattenedIndex(outputIdx, outputShapeStrides); float value = sequences[i][(j * inputShape.TotalSize()) + k]; expectedPerFrameTotals[(((i * maxActualSequenceLength) + j) * outputShape.TotalSize()) + flatOutputIdx] += value; expectedTotal += value; } } } if (reduceAll) FloatingPointVectorCompare(outputData, std::vector<float>({ expectedTotal }), "testReduceSum: Forward prop results do not match expected results"); else FloatingPointVectorCompare(outputData, expectedPerFrameTotals, "testReduceSum: Forward prop results do not match expected results"); }; // Reduce over all axes testReduceSum(-1, false); int reductionAxis = 0; testReduceSum(reductionAxis, true); if (reductionAxis < (inputShape.Rank() - 1)) reductionAxis++; testReduceSum(reductionAxis, false); if (reductionAxis < (inputShape.Rank() - 1)) reductionAxis++; testReduceSum(reductionAxis, true); } // Test ReduceSum along a dynamic axis { auto testReduceSum = [&sequences, &sequenceLengths, inputShape, sequencesValue, device](const Axis& axis) { if (!axis.IsDynamicAxis()) RuntimeError("Called the dynamic axis ReduceSum test with a static axis"); size_t maxActualSequenceLength = sequencesValue->Shape()[inputShape.Rank()]; size_t numSequences = sequencesValue->Shape()[inputShape.Rank() + 1]; auto inputVar = InputVariable({ inputShape }, DataType::Float, L"input"); FunctionPtr reduceSumFunc = ReduceSum(inputVar, axis); NDShape maskShape = { ((axis == Axis::DefaultBatchAxis()) ? maxActualSequenceLength : 1), ((axis == Axis::DefaultBatchAxis()) ? 1 : numSequences) }; NDShape outputShape = reduceSumFunc->Output().Shape(); auto outputDataShape = outputShape.AppendShape(maskShape); std::vector<float> outputData(outputDataShape.TotalSize()); auto maskPtr = MakeSharedObject<NDMask>(maskShape, device); ValuePtr outputValue = MakeSharedObject<Value>(MakeSharedObject<NDArrayView>(outputDataShape, outputData, false), maskPtr); std::unordered_map<Variable, ValuePtr> outputs = { { reduceSumFunc->Output(), outputValue } }; reduceSumFunc->Forward({ { inputVar, sequencesValue } }, outputs, device); std::vector<float> expectedTotals(outputDataShape.TotalSize(), 0.0f); for (size_t i = 0; i < numSequences; ++i) { size_t currentSequenceLength = sequenceLengths[i]; for (size_t j = 0; j < currentSequenceLength; ++j) { for (size_t k = 0; k < inputShape.TotalSize(); ++k) { float value = sequences[i][(j * inputShape.TotalSize()) + k]; if (axis == Axis::DefaultBatchAxis()) expectedTotals[(j * inputShape.TotalSize()) + k] += value; else expectedTotals[(i * inputShape.TotalSize()) + k] += value; } } } FloatingPointVectorCompare(outputData, expectedTotals, "testReduceSum: Forward prop results do not match expected results"); }; testReduceSum(Axis::DefaultDynamicAxis()); } }