This report predicts the five exercise-execution classes
(classe) from accelerometers worn on the belt, forearm,
arm, and dumbbell. A random forest was selected because the sensor
relationships are nonlinear and may interact. Model choice was checked
against a single classification tree. Five-fold cross-validation on a
development set estimated random-forest accuracy at
99.32%; an untouched validation set produced
99.61% accuracy and 0.39% error. The
final model predicts the 20 quiz cases as shown below.
The training data contain 19622 observations. The outcome has five levels: A denotes the correct lift; B–E denote four distinct errors. I removed row identifiers, participant names, timestamps, and window bookkeeping fields. These fields describe data collection rather than body movement and could let a model memorize participants or recording order. I also removed variables observed in fewer than 95% of rows. This left 52 complete sensor predictors and avoided imputing columns that are almost entirely missing.
training_raw <- read.csv("pml-training.csv",
na.strings = c("NA", "#DIV/0!", ""), check.names = FALSE)
metadata <- c("X", "user_name", "raw_timestamp_part_1",
"raw_timestamp_part_2", "cvtd_timestamp", "new_window", "num_window")
candidate <- setdiff(names(training_raw), c(metadata, "classe", ""))
predictors <- candidate[vapply(training_raw[candidate],
function(x) mean(!is.na(x)), numeric(1)) >= 0.95]
model_data <- training_raw[c(predictors, "classe")]
model_data$classe <- factor(model_data$classe)
Figure 1. Exercise classes are reasonably represented, supporting stratified resampling.
I used a fixed seed and stratified the observations by
classe, assigning 75% to development and 25% (4907 rows) to
final validation. All model comparison occurred within the development
set. Five stratified folds provided out-of-sample predictions for every
development observation. This separation prevents the final validation
result from benefiting from model selection.
The candidates were (1) a classification tree, which is easy to
interpret but unstable, and (2) a random forest, which averages many
decorrelated trees. The forest used mtry = floor(sqrt(52)),
a conventional classification default. The cross-validation comparison
strongly favored the forest.
for (k in 1:5) {
rf <- randomForest(classe ~ ., data = development[fold != k, ],
ntree = 250, mtry = floor(sqrt(length(predictors))))
rf_prediction <- predict(rf, development[fold == k, ])
cv_accuracy[k] <- mean(rf_prediction == development$classe[fold == k])
}
Figure 2. Five-fold cross-validation accuracy by candidate model.
The forest’s mean cross-validation accuracy was 0.9932 (fold SD 0.0012), versus 0.7390 (SD 0.0148) for the single tree. Thus the substantive conclusion is sensitive to choosing a sufficiently flexible model, but the forest result itself is stable across folds.
After selection, I refit both candidates on the complete development set and evaluated them once on the held-out validation set. The random forest achieved 0.9961 accuracy, compared with 0.7281 for the single tree.
| A | B | C | D | E | |
|---|---|---|---|---|---|
| A | 1392 | 2 | 0 | 0 | 1 |
| B | 1 | 947 | 2 | 0 | 0 |
| C | 0 | 5 | 850 | 1 | 0 |
| D | 0 | 0 | 4 | 799 | 1 |
| E | 0 | 0 | 0 | 2 | 900 |
The held-out error estimate is 0.39%. A 95% Wilson interval places the underlying accuracy between 99.40% and 99.75%, equivalent to an error interval from 0.25% to 0.60%. Five-fold cross-validation implies 0.68% error, while the final forest’s out-of-bag estimate is 0.27%. These independent estimates all indicate an expected out-of-sample error below 1%, although performance on new people could be lower because the random split includes measurements from the same six participants in both sets.
Figure 3. Ten most influential predictors in the final forest.
No manual interaction terms were added. A forest already models interactions through successive splits—for example, a forearm orientation threshold can lead to different rules depending on belt acceleration. Enumerating pairwise terms for 52 inputs would add 1,326 candidates and make a linear expansion difficult to validate. The strong, consistent resampling performance supports the automatic treatment, while the weaker single tree confirms that one simple partition is insufficient.
The close agreement among five-fold cross-validation (99.32% accuracy), held-out validation (99.61%), and the final forest’s out-of-bag estimate supports the stability of the selected model. The single tree reached only 72.81% validation accuracy. This difference is plausible because one tree relies on a limited sequence of splits and is sensitive to small changes in the data, whereas a random forest averages many decorrelated trees. Averaging reduces variance while retaining nonlinear thresholds and interactions among belt, arm, forearm, and dumbbell measurements.
Only 19 of 4,907 validation observations were misclassified. The largest off-diagonal counts involved class C being predicted as B and class D being predicted as C. These errors suggest that some incorrect lifting patterns produce similar sensor signatures, but no class showed a broad systematic failure. Agreement across the three error estimates is more informative than relying on a single accuracy value.
The main limitation is the row-level split: observations from the
same six participants can occur in development and validation, and
nearby measurements may be correlated. The estimated error therefore
applies most directly to similar participants and recording conditions.
A stricter follow-up would use leave-one-participant-out validation,
tune mtry inside nested cross-validation, and report
class-specific sensitivity in addition to overall accuracy. More
participants would also be needed before claiming that performance
generalizes to a wider population. Finally, the 20 quiz cases have no
supplied labels, so their prediction chart describes the output
distribution rather than proving test-set accuracy.
The selected random forest was refit to all 19622 labeled rows with
750 trees. The following are the requested predictions, ordered by
problem_id.
| Problem ID | Predicted classe |
|---|---|
| 1 | B |
| 2 | A |
| 3 | B |
| 4 | A |
| 5 | A |
| 6 | E |
| 7 | D |
| 8 | B |
| 9 | A |
| 10 | A |
| 11 | B |
| 12 | C |
| 13 | B |
| 14 | A |
| 15 | E |
| 16 | E |
| 17 | A |
| 18 | B |
| 19 | B |
| 20 | B |
Figure 4. Distribution of predicted exercise classes across the 20 test cases.
This figure summarizes the prediction mix; the quiz cases have no supplied labels, so it does not represent test-set accuracy.
This analysis met the project objective by predicting the five exercise-quality classes from wearable-sensor measurements. The random forest was selected because it substantially outperformed the interpretable single-tree benchmark and remained stable across cross-validation, held-out validation, and out-of-bag assessment. It achieved 99.61% accuracy on the untouched validation set, corresponding to an estimated out-of-sample error of 0.39%. After selection, the model was refit on all 19,622 labeled observations and produced the required predictions for all 20 quiz cases. These results provide strong evidence for performance under similar recording conditions, while participant-level validation would be required to make a stronger claim about completely new users.
This HTML document was knitted from the accompanying R Markdown file. The complete fitting script, fixed random seeds, source CSV files, saved results, and quiz-output files are included in the project directory. Package and session versions appear below.
sessionInfo()
## R version 4.6.1 (2026-06-24 ucrt)
## Platform: x86_64-w64-mingw32/x64
## Running under: Windows 11 x64 (build 26200)
##
## Matrix products: default
## LAPACK version 3.12.1
##
## locale:
## [1] LC_COLLATE=Dutch_Netherlands.utf8 LC_CTYPE=Dutch_Netherlands.utf8
## [3] LC_MONETARY=Dutch_Netherlands.utf8 LC_NUMERIC=C
## [5] LC_TIME=Dutch_Netherlands.utf8
##
## time zone: Europe/Amsterdam
## tzcode source: internal
##
## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
##
## loaded via a namespace (and not attached):
## [1] digest_0.6.39 R6_2.6.1 fastmap_1.2.0 xfun_0.60
## [5] cachem_1.1.0 knitr_1.51 htmltools_0.5.9 rmarkdown_2.31
## [9] lifecycle_1.0.5 cli_3.6.6 sass_0.4.10 jquerylib_0.1.4
## [13] compiler_4.6.1 rstudioapi_0.19.0 tools_4.6.1 evaluate_1.0.5
## [17] bslib_0.12.0 yaml_2.3.12 otel_0.2.0 jsonlite_2.0.0
## [21] rlang_1.3.0
The data were provided by the Pontifical Catholic University of Rio de Janeiro’s Weight Lifting Exercise Dataset. The course copies of the training data and 20 test cases are retained unchanged.