Я использую CNTK, и мне нужно получить матрицу градиента Якоби для входа. Но CNTK автоматически уменьшает матрицу градиента. Как получить необработанную матрицу Якобиана?
Это демонстрация C ++, демонстрирующая проблему, похожую демонстрацию в Python можно легко восстановить:
NDShape shape({ 3, 2 });
Variable W = InputVariable(shape, DataType::Float, true);
auto data = make_shared<vector<float>>(3, float(2));
for (int j = 0; j < shape[0]; j++)
{
data->push_back(2 + 1);
}
auto val = MakeSharedObject<Value>(MakeSharedObject<NDArrayView>(shape, data->data(), data->size(), DeviceDescriptor::CPUDevice()));
// | 2 2 2 | when transposed after
// | 3 3 3 |
Variable x = InputVariable(NDShape({ 3, 1 }), DataType::Float, true);
auto datax = make_shared<vector<float>>(3, float(1));
auto valx = MakeSharedObject<Value>(MakeSharedObject<NDArrayView>(NDShape({ 3, 1 }), datax->data(), datax->size(), DeviceDescriptor::CPUDevice()));
// [1 1 1]
auto left = Transpose(W);
auto op = Times(left, x);
std::unordered_map<Variable, ValuePtr> outputValues = { { op->Output(), nullptr } };
auto back = op->Forward({ {W, val}, {x, valx} }, outputValues, DeviceDescriptor::UseDefaultDevice(), { op->Output() });
auto outVal = outputValues[op->Output()];
wcout << outVal->AsString() << "\n";
printMatrix(outVal->Data()->DeepClone(DeviceDescriptor::CPUDevice()));
fflush(stdout);
//prints out correctly [6 9]
Но после, при расчете градиента:
ValuePtr rootGrad = MakeSharedObject<Value>(MakeSharedObject<NDArrayView>(DataType::Float, op->Output().Shape(), DeviceDescriptor::UseDefaultDevice()));
rootGrad->Data()->SetValue(1.0f);
unordered_map<Variable, ValuePtr> gradientOut = { { x, nullptr } };
op->Backward(back, { { op->Output(), rootGrad } }, gradientOut);
auto outGrad = gradientOut[x];
wcout << outGrad->AsString() << "\n";
printMatrix(outGrad->Data()->DeepClone(DeviceDescriptor::CPUDevice()));
fflush(stdout);
// prints out:
// [5 5 5] !!!
// and not
// |2 2 2|
// |3 3 3| !!!
Какие-либо предложения? Спасибо!
Задача ещё не решена.
Других решений пока нет …