Я пытаюсь использовать C ++ API CNTK
достичь онлайн обучения. При чтении исходного кода модульных тестов и CNTKLibrary.h
заголовок, я видел только Trainer.TrainMinibatch
метод обучения модели. Можно ли использовать этот метод для передачи одной точки ввода-вывода? Если это возможно, какой самый простой способ сделать это?
Я пытался использовать CNTK::Value::CreateSequence
метод для создания последовательности, которую я тогда хотел использовать в TrainMinibatch
функционировать, но не работает так, как я ожидал:
Я пытался портировать это python
код для C ++:
num_hidden_layers = 2
num_output_classes = 2
input_dim = 1
hidden_layers_dim = 400
input_var = C.input_variable(input_dim)
label_var = C.input_variable(num_output_classes)
def create_model(features):
with C.layers.default_options(init = C.glorot_uniform(), activation=C.ops.relu):
h = features
for _ in range(num_hidden_layers):
h = C.layers.Dense(hidden_layers_dim, activation=C.sigmoid)(h)
r = C.layers.Dense(num_output_classes, activation=None)(h)
return r
z = create_model(input_var)
loss = C.cross_entropy_with_softmax(z, label_var)
label_error = C.classification_error(z, label_var)
learning_rate = 0.2
lr_schedule = C.learning_rate_schedule(learning_rate, C.UnitType.minibatch)
learner = C.sgd(z.parameters, lr_schedule)
trainer = C.Trainer(z, (loss, label_error), [learner])
input_map = { label_var : None, input_var : None}
training_progress_output_freq = 500
for i in range(0, 10000):
input_map[input_var] = np.array([np.random.randint(0,2)], dtype=np.float32);
if input_map[input_var] == 0:
input_map[label_var] = np.array([1,0], dtype=np.float32)
else:
input_map[label_var] = np.array([0, 1], dtype=np.float32)
trainer.train_minibatch(input_map)
Я закончил с этим кодом C ++:
const size_t inputDim = 1;// 28 * 28;
const size_t numOutputClasses = 2;// 10;
const size_t hiddenLayerDim = 400;
const size_t numHiddenLayers = 2;
//build the model
auto input = InputVariable({ inputDim }, DataType::Float, L"features");
FunctionPtr classifierOutput = input;
for (int i = 0; i < numHiddenLayers; i++)
{
classifierOutput = FullyConnectedDNNLayer(classifierOutput, hiddenLayerDim, device, std::bind(Sigmoid, _1, L""));
}
classifierOutput = FullyConnectedLinearLayer(classifierOutput, 2, device);
auto labels = InputVariable({ numOutputClasses }, DataType::Float, L"labels");
auto trainingLoss = CrossEntropyWithSoftmax(classifierOutput, labels, L"lossFunction");
auto prediction = Minus(Constant::Scalar(1.0f, device), ClassificationError(classifierOutput, labels, L"classificationError"));
LearningRatePerMinibatchSchedule learningRatePerSample = 0.2;
auto trainer = CreateTrainer(classifierOutput, trainingLoss, prediction,
{ SGDLearner(classifierOutput->Parameters(), learningRatePerSample) }
);
std::cout << "Starting to train...\n";
size_t outputFrequencyInMinibatches = 500;
for (size_t i = 0; i < 10000; ++i)
{
//input data
std::vector<float> inputData(1);
inputData[0] = ((float)rand()) / RAND_MAX;
//output data
std::vector<float> outputData(2);
outputData[0] = inputData[0] > 0.5 ? 1.0 : 0.0;
outputData[1] = 1.0 - outputData[0];
ValuePtr inputSequence = CNTK::Value::CreateSequence(NDShape({ 1 }), inputData, device);
ValuePtr outputSequence = CNTK::Value::CreateSequence(NDShape({ 2 }), outputData, device);
std::unordered_map<Variable, ValuePtr> map = {{ input, inputSequence }, { labels, outputSequence } };
trainer->TrainMinibatch(map, device);
}
Я могу скомпилировать код и запустить его, но потери в версии C ++ не сходятся к 0; в версии Python после нескольких сотен итераций потеря более или менее равна 0 …
Похоже, что входные данные для Python 0 или 1:
input_map[input_var] = np.array([np.random.randint(0,2)], dtype=np.float32);
в то время как в коде C ++ это число между 0 и 1
//input data
std::vector<float> inputData(1);
inputData[0] = ((float)rand()) / RAND_MAX;
Пожалуйста, измените их на одинаковые и проверьте, отличаются ли скорости сходимости.
Других решений пока нет …