matrix::Matrix standardize(const matrix::Matrix& input)
{
    auto means = apply(reduce(input, {1}, matrix::Add()), matrix::Divide(input.size()[1]));

    auto inputMeanSubtracted = broadcast(input, means, {1}, matrix::Subtract());

    auto stddevs = apply(reduce(apply(inputMeanSubtracted,
        matrix::SquareAndScale(1.0 / input.size()[1])), {1}, matrix::Add()), matrix::Sqrt());

    std::cout << stddevs.toString();

    return broadcast(inputMeanSubtracted, stddevs, {1}, matrix::Divide());
}
void compare(const matrix::Matrix& predictions, const matrix::Matrix& reference)
{
    size_t samples = predictions.size()[1];

    auto differences = apply(predictions, reference, matrix::Subtract());
    auto squareDifferences = apply(differences, matrix::Square());
    auto normalizedSquareDifferences = apply(squareDifferences, matrix::Divide(samples));

    double cost = std::sqrt(reduce(normalizedSquareDifferences, {}, matrix::Add())[0]);

    std::cout << "Total RMS error was " << cost << "\n";

    if(cost < 15.0)
    {
        std::cout << "Test Passed\n";
    }
    else
    {
        std::cout << "Test Failed\n";
    }
}