static NeuralNetwork createNeuralNetwork(size_t xPixels, size_t yPixels,
    size_t colors, std::default_random_engine& engine)
{
    NeuralNetwork network;

    // 5x5 convolutional layer
    network.addLayer(FeedForwardLayer(xPixels, yPixels * colors, yPixels * colors));

    // 2x2 pooling layer
    //network.addLayer(Layer(1, xPixels, xPixels));

    // final prediction layer
    network.addLayer(FeedForwardLayer(1, network.getOutputCount(), 1));

    network.initializeRandomly(engine);

    return network;
}
static void createModel(ClassificationModel& model, const Parameters& parameters,
	std::default_random_engine& engine)
{
	NeuralNetwork featureSelector;
	
	size_t totalPixels = parameters.xPixels * parameters.yPixels * parameters.colors;

	// derive parameters from image dimensions 
	const size_t blockSize = std::min(parameters.xPixels, parameters.blockX) *
		std::min(parameters.yPixels, parameters.blockY) * parameters.colors;
	const size_t blocks    = totalPixels / blockSize;
	const size_t blockStep = blockSize / parameters.blockStep;

	size_t reductionFactor = 4;

	// convolutional layer
	featureSelector.addLayer(Layer(blocks, blockSize, blockSize / reductionFactor, blockStep));
	
	// pooling layer
	featureSelector.addLayer(
		Layer(1,
			blocks * featureSelector.back().getOutputBlockingFactor(),
			blocks * featureSelector.back().getOutputBlockingFactor()));
	
	// contrast normalization
	//featureSelector.addLayer(Layer(featureSelector.back().blocks(),
	//	featureSelector.back().getOutputBlockingFactor(),
	//	featureSelector.back().getOutputBlockingFactor()));

	featureSelector.initializeRandomly(engine);
	minerva::util::log("TestFirstLayerFeatures")
		<< "Building feature selector network with "
		<< featureSelector.getOutputCount() << " output neurons\n";

	featureSelector.setUseSparseCostFunction(true);

	model.setNeuralNetwork("FeatureSelector", featureSelector);
}