Implement new Train() overloads and tests for them.
This commit is contained in:
@@ -63,8 +63,8 @@ inline double RegressionDistribution::Probability(
|
||||
const arma::vec& observation) const
|
||||
{
|
||||
arma::rowvec fitted;
|
||||
rf.Predict(observation.rows(1, observation.n_rows-1), fitted);
|
||||
return err.Probability(observation(0)-fitted.t());
|
||||
rf.Predict(observation.rows(1, observation.n_rows - 1), fitted);
|
||||
return err.Probability(observation(0) - fitted.t());
|
||||
}
|
||||
|
||||
inline void RegressionDistribution::Predict(const arma::mat& points,
|
||||
|
||||
@@ -71,14 +71,90 @@ class LinearRegression
|
||||
* regularization parameter lambda, call Lambda() or set a different value in
|
||||
* the constructor.
|
||||
*
|
||||
* This version of `Train()` is deprecated and will be removed in mlpack
|
||||
* 5.0.0. Use the version of `Train()` that specifies `lambda` before
|
||||
* `intercept` instead.
|
||||
*
|
||||
* @param predictors X, the matrix of data points to train the model on.
|
||||
* @param responses y, the responses to the data points.
|
||||
* @param intercept Whether or not to fit an intercept term.
|
||||
* @return The least squares error after training.
|
||||
*/
|
||||
mlpack_deprecated /** Will be removed in mlpack 5.0.0. */
|
||||
double Train(const arma::mat& predictors,
|
||||
const arma::rowvec& responses,
|
||||
const bool intercept = true);
|
||||
const bool intercept);
|
||||
|
||||
/**
|
||||
* Train the LinearRegression model on the given data and weights. Careful!
|
||||
* This will completely ignore and overwrite the existing model. This
|
||||
* particular implementation does not have an incremental training algorithm.
|
||||
* To set the regularization parameter lambda, call Lambda() or set a
|
||||
* different value in the constructor.
|
||||
*
|
||||
* This version of `Train()` is deprecated and will be removed in mlpack
|
||||
* 5.0.0. Use the version of `Train()` that specifies `lambda` before
|
||||
* `intercept` instead.
|
||||
*
|
||||
* @param predictors X, the matrix of data points to train the model on.
|
||||
* @param responses y, the responses to the data points.
|
||||
* @param weights Observation weights (for boosting).
|
||||
* @param intercept Whether or not to fit an intercept term.
|
||||
* @return The least squares error after training.
|
||||
*/
|
||||
mlpack_deprecated /** Will be removed in mlpack 5.0.0. */
|
||||
double Train(const arma::mat& predictors,
|
||||
const arma::rowvec& responses,
|
||||
const arma::rowvec& weights,
|
||||
const bool intercept);
|
||||
|
||||
/**
|
||||
* Train the LinearRegression model on the given data and weights. Careful!
|
||||
* This will completely ignore and overwrite the existing model. This
|
||||
* particular implementation does not have an incremental training algorithm.
|
||||
* To set the regularization parameter lambda, call Lambda() or set a
|
||||
* different value in the constructor.
|
||||
*
|
||||
* @param predictors X, the matrix of data points to train the model on.
|
||||
* @param responses y, the responses to the data points.
|
||||
* @return The least squares error after training.
|
||||
*/
|
||||
double Train(const arma::mat& predictors,
|
||||
const arma::rowvec& responses);
|
||||
|
||||
/**
|
||||
* Train the LinearRegression model on the given data and weights. Careful!
|
||||
* This will completely ignore and overwrite the existing model. This
|
||||
* particular implementation does not have an incremental training algorithm.
|
||||
* To set the regularization parameter lambda, call Lambda() or set a
|
||||
* different value in the constructor.
|
||||
*
|
||||
* @param predictors X, the matrix of data points to train the model on.
|
||||
* @param responses y, the responses to the data points.
|
||||
* @param lambda L2 regularization penalty parameter to use.
|
||||
* @return The least squares error after training.
|
||||
*/
|
||||
double Train(const arma::mat& predictors,
|
||||
const arma::rowvec& responses,
|
||||
const double lambda);
|
||||
|
||||
/**
|
||||
* Train the LinearRegression model on the given data and weights. Careful!
|
||||
* This will completely ignore and overwrite the existing model. This
|
||||
* particular implementation does not have an incremental training algorithm.
|
||||
* To set the regularization parameter lambda, call Lambda() or set a
|
||||
* different value in the constructor.
|
||||
*
|
||||
* @param predictors X, the matrix of data points to train the model on.
|
||||
* @param responses y, the responses to the data points.
|
||||
* @param lambda L2 regularization penalty parameter to use.
|
||||
* @param intercept Whether or not to fit an intercept term.
|
||||
* @return The least squares error after training.
|
||||
*/
|
||||
double Train(const arma::mat& predictors,
|
||||
const arma::rowvec& responses,
|
||||
const double lambda,
|
||||
const bool intercept);
|
||||
|
||||
/**
|
||||
* Train the LinearRegression model on the given data and weights. Careful!
|
||||
@@ -90,13 +166,49 @@ class LinearRegression
|
||||
* @param predictors X, the matrix of data points to train the model on.
|
||||
* @param responses y, the responses to the data points.
|
||||
* @param weights Observation weights (for boosting).
|
||||
* @return The least squares error after training.
|
||||
*/
|
||||
double Train(const arma::mat& predictors,
|
||||
const arma::rowvec& responses,
|
||||
const arma::rowvec& weights);
|
||||
|
||||
/**
|
||||
* Train the LinearRegression model on the given data and weights. Careful!
|
||||
* This will completely ignore and overwrite the existing model. This
|
||||
* particular implementation does not have an incremental training algorithm.
|
||||
* To set the regularization parameter lambda, call Lambda() or set a
|
||||
* different value in the constructor.
|
||||
*
|
||||
* @param predictors X, the matrix of data points to train the model on.
|
||||
* @param responses y, the responses to the data points.
|
||||
* @param weights Observation weights (for boosting).
|
||||
* @param lambda L2 regularization penalty parameter to use.
|
||||
* @return The least squares error after training.
|
||||
*/
|
||||
double Train(const arma::mat& predictors,
|
||||
const arma::rowvec& responses,
|
||||
const arma::rowvec& weights,
|
||||
const double lambda);
|
||||
|
||||
/**
|
||||
* Train the LinearRegression model on the given data and weights. Careful!
|
||||
* This will completely ignore and overwrite the existing model. This
|
||||
* particular implementation does not have an incremental training algorithm.
|
||||
* To set the regularization parameter lambda, call Lambda() or set a
|
||||
* different value in the constructor.
|
||||
*
|
||||
* @param predictors X, the matrix of data points to train the model on.
|
||||
* @param responses y, the responses to the data points.
|
||||
* @param weights Observation weights (for boosting).
|
||||
* @param lambda L2 regularization penalty parameter to use.
|
||||
* @param intercept Whether or not to fit an intercept term.
|
||||
* @return The least squares error after training.
|
||||
*/
|
||||
double Train(const arma::mat& predictors,
|
||||
const arma::rowvec& responses,
|
||||
const arma::rowvec& weights,
|
||||
const bool intercept = true);
|
||||
const double lambda,
|
||||
const bool intercept);
|
||||
|
||||
/**
|
||||
* Calculate y_i for each data point in points.
|
||||
|
||||
@@ -37,18 +37,67 @@ inline LinearRegression::LinearRegression(
|
||||
Train(predictors, responses, weights, intercept);
|
||||
}
|
||||
|
||||
mlpack_deprecated /** Will be removed in mlpack 5.0.0. */
|
||||
inline double LinearRegression::Train(const arma::mat& predictors,
|
||||
const arma::rowvec& responses,
|
||||
const bool intercept)
|
||||
{
|
||||
return Train(predictors, responses, arma::rowvec(), intercept);
|
||||
return Train(predictors, responses, arma::rowvec(), this->lambda, intercept);
|
||||
}
|
||||
|
||||
mlpack_deprecated /** Will be removed in mlpack 5.0.0. */
|
||||
inline double LinearRegression::Train(const arma::mat& predictors,
|
||||
const arma::rowvec& responses,
|
||||
const arma::rowvec& weights,
|
||||
const bool intercept)
|
||||
{
|
||||
return Train(predictors, responses, weights, this->lambda, intercept);
|
||||
}
|
||||
|
||||
inline double LinearRegression::Train(const arma::mat& predictors,
|
||||
const arma::rowvec& responses)
|
||||
{
|
||||
return Train(predictors, responses, arma::rowvec(), this->lambda,
|
||||
this->intercept);
|
||||
}
|
||||
|
||||
inline double LinearRegression::Train(const arma::mat& predictors,
|
||||
const arma::rowvec& responses,
|
||||
const double lambda)
|
||||
{
|
||||
return Train(predictors, responses, arma::rowvec(), lambda, this->intercept);
|
||||
}
|
||||
|
||||
inline double LinearRegression::Train(const arma::mat& predictors,
|
||||
const arma::rowvec& responses,
|
||||
const double lambda,
|
||||
const bool intercept)
|
||||
{
|
||||
return Train(predictors, responses, arma::rowvec(), lambda, intercept);
|
||||
}
|
||||
|
||||
inline double LinearRegression::Train(const arma::mat& predictors,
|
||||
const arma::rowvec& responses,
|
||||
const arma::rowvec& weights)
|
||||
{
|
||||
return Train(predictors, responses, weights, this->lambda, this->intercept);
|
||||
}
|
||||
|
||||
inline double LinearRegression::Train(const arma::mat& predictors,
|
||||
const arma::rowvec& responses,
|
||||
const arma::rowvec& weights,
|
||||
const double lambda)
|
||||
{
|
||||
return Train(predictors, responses, weights, lambda, this->intercept);
|
||||
}
|
||||
|
||||
inline double LinearRegression::Train(const arma::mat& predictors,
|
||||
const arma::rowvec& responses,
|
||||
const arma::rowvec& weights,
|
||||
const double lambda,
|
||||
const bool intercept)
|
||||
{
|
||||
this->lambda = lambda;
|
||||
this->intercept = intercept;
|
||||
|
||||
/*
|
||||
@@ -106,7 +155,7 @@ inline void LinearRegression::Predict(
|
||||
// Prevent underflow.
|
||||
const size_t labels = (parameters.n_rows == 0) ? size_t(0) :
|
||||
size_t(parameters.n_rows - 1);
|
||||
util::CheckSameDimensionality(points, labels, "LinearRegression::Predict()",
|
||||
util::CheckSameDimensionality(points, labels, "LinearRegression::Predict()",
|
||||
"points");
|
||||
// Get the predictions, but this ignores the intercept value
|
||||
// (parameters[0]).
|
||||
@@ -119,7 +168,7 @@ inline void LinearRegression::Predict(
|
||||
{
|
||||
// We want to be sure we have the correct number of dimensions in
|
||||
// the dataset.
|
||||
util::CheckSameDimensionality(points, parameters,
|
||||
util::CheckSameDimensionality(points, parameters,
|
||||
"LinearRegression::Predict()", "points");
|
||||
predictions = arma::trans(parameters) * points;
|
||||
}
|
||||
@@ -131,7 +180,7 @@ inline double LinearRegression::ComputeError(
|
||||
{
|
||||
// Sanity check on data.
|
||||
util::CheckSameSizes(predictors, responses, "LinearRegression::Train()");
|
||||
|
||||
|
||||
// Get the number of columns and rows of the dataset.
|
||||
const size_t nCols = predictors.n_cols;
|
||||
const size_t nRows = predictors.n_rows;
|
||||
|
||||
@@ -265,3 +265,58 @@ TEST_CASE("LinearRegressionTrainReturnObjective", "[LinearRegressionTest]")
|
||||
|
||||
REQUIRE(std::isfinite(error) == true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure all versions of Train() work correctly.
|
||||
*/
|
||||
TEST_CASE("LinearRegressionAllTrainVersionsTest", "[LinearRegressionTest]")
|
||||
{
|
||||
// The data doesn't really matter for this test; mostly we want to make sure
|
||||
// that all the Train() variants work properly.
|
||||
arma::mat predictors;
|
||||
predictors = { { 0, 1, 2, 4, 8, 16 },
|
||||
{ 16, 8, 4, 2, 1, 0 } };
|
||||
arma::rowvec responses = "0 2 4 3 8 8";
|
||||
arma::rowvec weights = "1.0 1.1 1.2 0.8 0.9 1.0";
|
||||
|
||||
LinearRegression lr1, lr2, lr3, lr4, lr5, lr6;
|
||||
|
||||
lr1.Train(predictors, responses);
|
||||
lr2.Train(predictors, responses, 0.1);
|
||||
lr3.Train(predictors, responses, 0.2, false);
|
||||
lr4.Train(predictors, responses, weights);
|
||||
lr5.Train(predictors, responses, weights, 0.3);
|
||||
lr6.Train(predictors, responses, weights, 0.4, false);
|
||||
|
||||
// We don't care about the specifics of the trained model, but we want to just
|
||||
// make sure everything appears to be correct from the sizes and
|
||||
// hyperparameters.
|
||||
REQUIRE(lr1.Lambda() == Approx(0.0).margin(1e-10));
|
||||
REQUIRE(lr1.Intercept() == true);
|
||||
REQUIRE(lr1.Parameters().n_elem == 3);
|
||||
|
||||
REQUIRE(lr2.Lambda() == Approx(0.1).margin(1e-10));
|
||||
REQUIRE(lr2.Intercept() == true);
|
||||
REQUIRE(lr2.Parameters().n_elem == 3);
|
||||
|
||||
REQUIRE(lr3.Lambda() == Approx(0.2).margin(1e-10));
|
||||
REQUIRE(lr3.Intercept() == false);
|
||||
REQUIRE(lr3.Parameters().n_elem == 2);
|
||||
|
||||
REQUIRE(lr4.Lambda() == Approx(0.0).margin(1e-10));
|
||||
REQUIRE(lr4.Intercept() == true);
|
||||
REQUIRE(lr4.Parameters().n_elem == 3);
|
||||
|
||||
REQUIRE(lr5.Lambda() == Approx(0.3).margin(1e-10));
|
||||
REQUIRE(lr5.Intercept() == true);
|
||||
REQUIRE(lr5.Parameters().n_elem == 3);
|
||||
|
||||
REQUIRE(lr6.Lambda() == Approx(0.4).margin(1e-10));
|
||||
REQUIRE(lr6.Intercept() == false);
|
||||
REQUIRE(lr6.Parameters().n_elem == 2);
|
||||
|
||||
// We can also check that the weighted model is different from the unweighted
|
||||
// model.
|
||||
REQUIRE(!arma::approx_equal(lr1.Parameters(), lr4.Parameters(), "absdiff",
|
||||
1e-5));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user