Table of Contents
Boosting is a highly effective and widely adopted technique in the field of machine learning, consistently producing models known for their superior predictive accuracy. This ensemble method sequentially combines numerous weak learners (typically decision trees) to form a powerful final model.
The most popular and efficient implementation of boosting today is XGBoost, which stands for “eXtreme Gradient Boosting.” XGBoost is renowned for its speed, scalability, and optimization features, making it the go-to algorithm for structured data challenges.
This comprehensive tutorial guides you through a practical, step-by-step example of how to implement XGBoost to fit a robust boosted regression model using the statistical programming language, R.
We will cover everything from data preparation and model training to hyperparameter tuning and final performance evaluation.
Step 1: Initializing the R Environment and Loading Dependencies
Before we begin the modeling process, it is essential to ensure that the necessary libraries are loaded into the R environment. These packages provide the core functionalities required for data handling and model execution.
We require two primary packages for this demonstration: the specialized xgboost package for model fitting, and the general-purpose caret package, which simplifies many data preparation and model evaluation tasks.
library(xgboost) #for fitting the xgboost model library(caret) #for general data preparation and model fitting
If these packages are not yet installed on your system, you must run the installation command (e.g., `install.packages(“xgboost”)`) before proceeding with the `library()` calls.
Step 2: Acquiring and Inspecting the Dataset
For this regression example, we will utilize the classic Boston dataset, which is conveniently housed within the MASS package. This dataset is frequently used for benchmarking regression techniques in machine learning.
The Boston dataset includes 13 distinct predictor variables, such as crime rate and proximity to employment centers, which we will use to forecast a single response variable named medv. The medv variable quantifies the median value of owner-occupied homes in thousands of dollars across various census tracts near Boston.
Loading and viewing the structure of the data is a crucial preliminary step to understand the variable types and overall dimensions.
#load the data
data = MASS::Boston
#view the structure of the data
str(data)
'data.frame': 506 obs. of 14 variables:
$ crim : num 0.00632 0.02731 0.02729 0.03237 0.06905 ...
$ zn : num 18 0 0 0 0 0 12.5 12.5 12.5 12.5 ...
$ indus : num 2.31 7.07 7.07 2.18 2.18 2.18 7.87 7.87 7.87 7.87 ...
$ chas : int 0 0 0 0 0 0 0 0 0 0 ...
$ nox : num 0.538 0.469 0.469 0.458 0.458 0.458 0.524 0.524 0.524 0.524 ...
$ rm : num 6.58 6.42 7.18 7 7.15 ...
$ age : num 65.2 78.9 61.1 45.8 54.2 58.7 66.6 96.1 100 85.9 ...
$ dis : num 4.09 4.97 4.97 6.06 6.06 ...
$ rad : int 1 2 2 3 3 3 5 5 5 5 ...
$ tax : num 296 242 242 222 222 222 311 311 311 311 ...
$ ptratio: num 15.3 17.8 17.8 18.7 18.7 18.7 15.2 15.2 15.2 15.2 ...
$ black : num 397 397 393 395 397 ...
$ lstat : num 4.98 9.14 4.03 2.94 5.33 ...
$ medv : num 24 21.6 34.7 33.4 36.2 28.7 22.9 27.1 16.5 18.9 ...
From the output structure, we confirm that the dataset comprises 506 observations (rows) and 14 total variables (columns). This setup is ideal for our regression analysis task.
Step 3: Preparing Data for XGBoost Training
To build a reliable machine learning model, we must partition the dataset into distinct training and testing sets. This step prevents overfitting the training data and allows us to rigorously evaluate the model’s generalization ability on unseen data.
We use the powerful createDataPartition() function from the caret package to perform an 80/20 stratified split, allocating 80% of the data to the training set and reserving 20% for testing.
A critical requirement for the xgboost package is that the input data must be converted into a specific format: the predictor variables must be represented as a matrix structure. We achieve this conversion using the data.matrix() function and, finally, structure the data into the specialized xgb.DMatrix object required for efficient XGBoost computation.
#make this example reproducible
set.seed(0)
#split into training (80%) and testing set (20%)
parts = createDataPartition(data$medv, p = .8, list = F)
train = data[parts, ]
test = data[-parts, ]
#define predictor and response variables in training set
train_x = data.matrix(train[, -13])
train_y = train[,13]
#define predictor and response variables in testing set
test_x = data.matrix(test[, -13])
test_y = test[, 13]
#define final training and testing sets (DMatrix format)
xgb_train = xgb.DMatrix(data = train_x, label = train_y)
xgb_test = xgb.DMatrix(data = test_x, label = test_y)
Step 4: Training the XGBoost Regression Model
With the data properly structured, we can now proceed to train the XGBoost model using the xgb.train() function. This process involves defining key hyperparameters that govern the structure and duration of the boosting process.
Two vital parameters are nrounds (the number of boosting iterations, or the number of trees to build) and max.depth. While we select 70 rounds here for simplicity, large-scale datasets often require hundreds or thousands of rounds, significantly impacting execution time. Monitoring performance across these rounds is crucial.
For max.depth, which controls the complexity of the individual decision trees, a low value (typically 2 or 3) is preferred. This constraint ensures that the individual base learners are weak, which is a foundational principle of the boosting algorithm and tends to yield more robust and accurate ensemble models. We also utilize a watchlist to monitor the performance (via RMSE) on both the training and testing sets during the iterative process.
#define watchlist
watchlist = list(train=xgb_train, test=xgb_test)
#fit XGBoost model and display training and testing data at each round
model = xgb.train(data = xgb_train, max.depth = 3, watchlist=watchlist, nrounds = 70)
[1] train-rmse:10.167523 test-rmse:10.839775
[2] train-rmse:7.521903 test-rmse:8.329679
[3] train-rmse:5.702393 test-rmse:6.691415
[4] train-rmse:4.463687 test-rmse:5.631310
[5] train-rmse:3.666278 test-rmse:4.878750
[6] train-rmse:3.159799 test-rmse:4.485698
[7] train-rmse:2.855133 test-rmse:4.230533
[8] train-rmse:2.603367 test-rmse:4.099881
[9] train-rmse:2.445718 test-rmse:4.084360
[10] train-rmse:2.327318 test-rmse:3.993562
[11] train-rmse:2.267629 test-rmse:3.944454
[12] train-rmse:2.189527 test-rmse:3.930808
[13] train-rmse:2.119130 test-rmse:3.865036
[14] train-rmse:2.086450 test-rmse:3.875088
[15] train-rmse:2.038356 test-rmse:3.881442
[16] train-rmse:2.010995 test-rmse:3.883322
[17] train-rmse:1.949505 test-rmse:3.844382
[18] train-rmse:1.911711 test-rmse:3.809830
[19] train-rmse:1.888488 test-rmse:3.809830
[20] train-rmse:1.832443 test-rmse:3.758502
[21] train-rmse:1.816150 test-rmse:3.770216
[22] train-rmse:1.801369 test-rmse:3.770474
[23] train-rmse:1.788891 test-rmse:3.766608
[24] train-rmse:1.751795 test-rmse:3.749583
[25] train-rmse:1.713306 test-rmse:3.720173
[26] train-rmse:1.672227 test-rmse:3.675086
[27] train-rmse:1.648323 test-rmse:3.675977
[28] train-rmse:1.609927 test-rmse:3.745338
[29] train-rmse:1.594891 test-rmse:3.756049
[30] train-rmse:1.578573 test-rmse:3.760104
[31] train-rmse:1.559810 test-rmse:3.727940
[32] train-rmse:1.547852 test-rmse:3.731702
[33] train-rmse:1.534589 test-rmse:3.729761
[34] train-rmse:1.520566 test-rmse:3.742681
[35] train-rmse:1.495155 test-rmse:3.732993
[36] train-rmse:1.467939 test-rmse:3.738329
[37] train-rmse:1.446343 test-rmse:3.713748
[38] train-rmse:1.435368 test-rmse:3.709469
[39] train-rmse:1.401356 test-rmse:3.710637
[40] train-rmse:1.390318 test-rmse:3.709461
[41] train-rmse:1.372635 test-rmse:3.708049
[42] train-rmse:1.367977 test-rmse:3.707429
[43] train-rmse:1.359531 test-rmse:3.711663
[44] train-rmse:1.335347 test-rmse:3.709101
[45] train-rmse:1.331750 test-rmse:3.712490
[46] train-rmse:1.313087 test-rmse:3.722981
[47] train-rmse:1.284392 test-rmse:3.712840
[48] train-rmse:1.257714 test-rmse:3.697482
[49] train-rmse:1.248218 test-rmse:3.700167
[50] train-rmse:1.243377 test-rmse:3.697914
[51] train-rmse:1.231956 test-rmse:3.695797
[52] train-rmse:1.219341 test-rmse:3.696277
[53] train-rmse:1.207413 test-rmse:3.691465
[54] train-rmse:1.197197 test-rmse:3.692108
[55] train-rmse:1.171748 test-rmse:3.683577
[56] train-rmse:1.156332 test-rmse:3.674458
[57] train-rmse:1.147686 test-rmse:3.686367
[58] train-rmse:1.143572 test-rmse:3.686375
[59] train-rmse:1.129780 test-rmse:3.679791
[60] train-rmse:1.111257 test-rmse:3.679022
[61] train-rmse:1.093541 test-rmse:3.699670
[62] train-rmse:1.083934 test-rmse:3.708187
[63] train-rmse:1.067109 test-rmse:3.712538
[64] train-rmse:1.053887 test-rmse:3.722480
[65] train-rmse:1.042127 test-rmse:3.720720
[66] train-rmse:1.031617 test-rmse:3.721224
[67] train-rmse:1.016274 test-rmse:3.699549
[68] train-rmse:1.008184 test-rmse:3.709522
[69] train-rmse:0.999220 test-rmse:3.708000
[70] train-rmse:0.985907 test-rmse:3.705192
Observing the output log, we track the testing RMSE (Root Mean Squared Error) across the 70 rounds. We notice a critical point: the minimum testing RMSE of 3.674458 is achieved specifically at round 56.
After round 56, the training RMSE continues to decrease (meaning the model fits the training data better), but the testing RMSE begins to stagnate or slightly increase. This inflection point is the classic indicator of overfitting, where the model learns noise specific to the training set rather than general patterns.
Therefore, to obtain the most generalizable model, we define our final XGBoost model using 56 rounds, employing early stopping implicitly by selecting the optimal iteration count. We also set verbose = 0 to suppress the iteration output during the final training run.
#define final model
final = xgboost(data = xgb_train, max.depth = 3, nrounds = 56, verbose = 0)Step 5: Generating Predictions and Evaluating Performance
The final stage involves leveraging our optimized boosted model to generate predictions on the previously unseen testing set. These predictions represent the model’s best estimate for the median house value of the Boston homes based on the input features.
To quantify the model’s accuracy, we calculate three standard regression metrics:
- MSE: Mean Squared Error, which penalizes larger errors more heavily.
- MAE: Mean Absolute Error, representing the average magnitude of the errors.
- RMSE: Root Mean Squared Error, the square root of MSE, which expresses the error in the same units as the response variable.
The following R code executes the prediction and calculates these three critical error measures:
mean((test_y - pred_y)^2) #mse
caret::MAE(test_y, pred_y) #mae
caret::RMSE(test_y, pred_y) #rmse
[1] 13.50164
[1] 2.409426
[1] 3.674457 The final Root Mean Squared Error value is calculated as 3.674457. Given that the medv variable is measured in thousands of dollars, this means that, on average, the model’s predictions differ from the actual observed median house values in the test set by approximately $3,674.46.
This RMSE serves as a benchmark for the model’s performance. For a comprehensive analysis, one should compare this result against other regression techniques, such as multiple linear regression, ridge regression, or principal components regression, to determine which modeling approach offers the most accurate and reliable predictions for the Boston housing market data.
The complete R source code utilized throughout this example is available for review and implementation here.
Cite this article
Mohammed looti (2025). Learning XGBoost with R: A Practical Step-by-Step Guide. PSYCHOLOGICAL STATISTICS. Retrieved from https://statistics.arabpsychology.com/xgboost-in-r-a-step-by-step-example/
Mohammed looti. "Learning XGBoost with R: A Practical Step-by-Step Guide." PSYCHOLOGICAL STATISTICS, 6 Nov. 2025, https://statistics.arabpsychology.com/xgboost-in-r-a-step-by-step-example/.
Mohammed looti. "Learning XGBoost with R: A Practical Step-by-Step Guide." PSYCHOLOGICAL STATISTICS, 2025. https://statistics.arabpsychology.com/xgboost-in-r-a-step-by-step-example/.
Mohammed looti (2025) 'Learning XGBoost with R: A Practical Step-by-Step Guide', PSYCHOLOGICAL STATISTICS. Available at: https://statistics.arabpsychology.com/xgboost-in-r-a-step-by-step-example/.
[1] Mohammed looti, "Learning XGBoost with R: A Practical Step-by-Step Guide," PSYCHOLOGICAL STATISTICS, vol. X, no. Y, ص Z-Z, November, 2025.
Mohammed looti. Learning XGBoost with R: A Practical Step-by-Step Guide. PSYCHOLOGICAL STATISTICS. 2025;vol(issue):pages.