The following explores Human Activity Recognition (HAR) data (Velloso, et al. 2013) and provides an overview of three machine learning algorithms to predict how well subjects under study performed various exercises. Methods include:
Classification trees were selected for interpretability, while the latter methods were selected for accuracy. Classification tree and GBM models employ k-folds cross-validation for increased accuracy, despite added computational expense. Model accuracies are compared and the final model, random forest, is used to predict 20 holdout instances for validation.
This work uses both R and RStudio with the following versions:
Preprocessing involves loading required R packages, retrieving the HAR dataset, brief exploratory data analysis (EDA), setting a seed for reproducibility, partitioning into training, test, and validation sets, and removal of features both highly correlative and at or near zero variance. Additional features are removed a priori with rationale provided.
Required libraries have been automatically installed and loaded.
The following loads and caches the HAR datasets via their respective URLs:
url_train <- "https://d396qusza40orc.cloudfront.net/predmachlearn/pml-training.csv"
url_valid <- "https://d396qusza40orc.cloudfront.net/predmachlearn/pml-testing.csv"
total_data <- read_csv(file = url_train)
validation <- read_csv(file = url_valid)
A glimpse() of the data structure reveals that the majority of the 19622 variables are of class integer and numeric, with an exceptional amount of NA (missing) values which will prove problematic. See Figure 1 in the Appendix for the full output of glimpse().
glimpse(total_data)
The variable to predict, classe, is roughly distributed, barring outcome A.
table(total_data$classe)
##
## A B C D E
## 5580 3797 3422 3216 3607
A set.seed() at 716 is initialized for reproducibility.
set.seed(716)
Due to its size (\(n = 20\)), the second dataset will be used as holdout: validation. Dataset total_data, with 19622 instances, will be partitioned into new training and testing sets, training and testing, at 75% and 25% or 14,718 and 4,904 instances, respectively.
in_train <- createDataPartition(y = total_data$classe,
p = .75, list = FALSE)
training <- total_data[ in_train, ]
testing <- total_data[-in_train, ]
Near-Zero Variance (NZV): Features with little or no variance, detected by nearZeroVar(), are removed. These features provide little explanatory value for predictive models, and reduce potential features from 160 variables to 124.
training <- training[, -nearZeroVar(x = training)]
Principle Components Analysis (PCA): Highly-correlative features may be redundant in terms of predictive value. Principle Components Analysis (PCA), another dimension reduction technique, was attempted. However, the prevalence of NA (missing) values make this impossible.
Omitting Missing Values: In light of the prevalence of NA (missing) values, the following eliminates features in which 95% or more of instances are NA (missing). Omitting features with NA values may create information loss, but this markedly high threshold removes features in which robust imputation is impossible, while still remaining highly discriminatory.
training <- training[, which(colSums(is.na(training)) / nrow(training) < .95)]
Summary Omissions: Model selection will not account for intervals of time, by design, while omission of arbitrary features, e.g. instance number and user_name, will prove less problematic downstream, particularly in classification trees.
training[2, 6]
## # A tibble: 1 x 1
## num_window
## <int>
## 1 11
These features are therefore removed:
training <- select(training, -(X1:num_window))
Both the classification tree and GBM models employ k-folds cross-validation, which partitions subsets of training data into equally-sized test sets. By default, trainControl() creates 10 folds. However, due to computational expense (using GBM in particular), 7 folds are partitioned. While more efficient, this introduces more bias and variance in trade.
cv_folds <- trainControl(method = "cv", number = 7)
This section focuses on model building for classification trees, random forest, and GBM methods, prediction, and accuracy via confusion matrices.
The following fits a classification tree model using k-folds cross-validation (\(k=7\)), omitting instances with NA (missing) values. A performance overview and confusion matrix are provided, as well as visualizations of both the dendrogram and confusion matrix.
dt_fit <- train(form = classe ~ ., data = training, method = "rpart",
na.action = "na.omit", trControl = cv_folds)
fancyRpartPlot(dt_fit$finalModel, sub = NULL)
dt_pred <- predict(object = dt_fit, newdata = testing)
dt_conmat <- confusionMatrix(as.factor(testing$classe), dt_pred)
plot(dt_conmat$table, main = "Classification Tree Confusion Matrix", color = "skyblue")
dt_conmat$overall[1:4]
## Accuracy Kappa AccuracyLower AccuracyUpper
## 0.5503670 0.4355954 0.5363157 0.5643584
Conclusions: While preserving feature X1 (row number) ensures accuracy greater than 90%, it was omitted due to being contrived and unrealistic for out-of-sample prediction. This model exhibits poor predictive performance, with test set accuracy at ~55%. It does have advantage in ease of interpretability, but ultimately proves a poor choice.
The followng fits a random forest model sans k-folds cross-validition, foregone due to computational expense. Instances with NA (missing) values are omitted. A performance overview is provided and confusion matrix visualized.
rf_fit <- randomForest(as.factor(classe) ~ ., data = training, na.action = "na.omit")
rf_pred <- predict(object = rf_fit, newdata = testing)
rf_conmat <- confusionMatrix(as.factor(testing$classe), rf_pred)
plot(rf_conmat$table, main = "Random Forest Confusion Matrix", color = "lightgreen")
rf_conmat$overall[1:4]
## Accuracy Kappa AccuracyLower AccuracyUpper
## 0.9961256 0.9950993 0.9939562 0.9976658
Conclusions: Random forest was selected due to its competitive reputation for accuracy. At the expense of interpretability, the accuracy of the random forest model, 99.6%, is vastly superior to the classification tree, at ~55%. A comparison with the ensuing GBM model accuracy will decide the final model.
The following fits and caches a generalized boosted model (GBM) with k-folds cross-validation (\(k=7\)). Instances with NA (missing) values are omitted. A performance overview is provided, as well as two visualizations: (1) A confusion matrix, and (2)
gbm_fit <- train(form = as.factor(classe) ~ ., data = training, method = "gbm", na.action = "na.omit", trControl = cv_folds)
gbm_pred <- predict(object = gbm_fit, newdata = testing)
gbm_conmat <- confusionMatrix(as.factor(testing$classe), gbm_pred)
plot(gbm_conmat$table, main = "GBM Confusion Matrix", color = "tomato")
gbm_conmat$overall[1:4]
## Accuracy Kappa AccuracyLower AccuracyUpper
## 0.9596248 0.9489271 0.9537334 0.9649606
Conclusions: Like the above random forest model, a GBM was selected a priori due to its competitive reputation for accuracy but also comes at the expense of interpretability. Accuracy is nearly as high as random forest, but only slightly less.
The following provides an overview of model performance for the classification tree, random forest, and GBM methods. It selects the most accurate model, random forest, and applies it to the holdout data: validation (\(n=20\)).
Both random forest and GBM perform extraordinarily well, at 99.6% and 95.9%, respectively, while the classification tree is left wanting at 55%. Therefore, the final model will be random forest: rf_fit. Given 99.6% accuracy, we can expect out-of-sample error to be negligible, with at least 19 of 20 correct predictions.
## Classification Tree Random Forest Boosting
## Accuracy 0.5503670 0.9961256 0.9596248
## Kappa 0.4355954 0.9950993 0.9489271
## AccuracyLower 0.5363157 0.9939562 0.9537334
## AccuracyUpper 0.5643584 0.9976658 0.9649606
predict(object = rf_fit, newdata = validation)
## 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
## B A B A A E D B A A B C B A E E A B B B
## Levels: A B C D E
The final validation test awaits, though we can reasonably assume out-of-sample error is, in all probability, negligible to nonexistent.
Function glimpse() provides the dimensions, classes, and initial instances in total_data.
glimpse(total_data)
## Observations: 19,622
## Variables: 160
## $ X1 <int> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12...
## $ user_name <chr> "carlitos", "carlitos", "carlitos", "...
## $ raw_timestamp_part_1 <int> 1323084231, 1323084231, 1323084231, 1...
## $ raw_timestamp_part_2 <int> 788290, 808298, 820366, 120339, 19632...
## $ cvtd_timestamp <chr> "05/12/2011 11:23", "05/12/2011 11:23...
## $ new_window <chr> "no", "no", "no", "no", "no", "no", "...
## $ num_window <int> 11, 11, 11, 12, 12, 12, 12, 12, 12, 1...
## $ roll_belt <dbl> 1.41, 1.41, 1.42, 1.48, 1.48, 1.45, 1...
## $ pitch_belt <dbl> 8.07, 8.07, 8.07, 8.05, 8.07, 8.06, 8...
## $ yaw_belt <dbl> -94.4, -94.4, -94.4, -94.4, -94.4, -9...
## $ total_accel_belt <int> 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3...
## $ kurtosis_roll_belt <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ kurtosis_picth_belt <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ kurtosis_yaw_belt <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ skewness_roll_belt <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ skewness_roll_belt.1 <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ skewness_yaw_belt <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ max_roll_belt <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ max_picth_belt <int> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ max_yaw_belt <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ min_roll_belt <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ min_pitch_belt <int> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ min_yaw_belt <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ amplitude_roll_belt <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ amplitude_pitch_belt <int> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ amplitude_yaw_belt <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ var_total_accel_belt <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ avg_roll_belt <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ stddev_roll_belt <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ var_roll_belt <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ avg_pitch_belt <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ stddev_pitch_belt <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ var_pitch_belt <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ avg_yaw_belt <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ stddev_yaw_belt <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ var_yaw_belt <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ gyros_belt_x <dbl> 0.00, 0.02, 0.00, 0.02, 0.02, 0.02, 0...
## $ gyros_belt_y <dbl> 0.00, 0.00, 0.00, 0.00, 0.02, 0.00, 0...
## $ gyros_belt_z <dbl> -0.02, -0.02, -0.02, -0.03, -0.02, -0...
## $ accel_belt_x <int> -21, -22, -20, -22, -21, -21, -22, -2...
## $ accel_belt_y <int> 4, 4, 5, 3, 2, 4, 3, 4, 2, 4, 2, 2, 4...
## $ accel_belt_z <int> 22, 22, 23, 21, 24, 21, 21, 21, 24, 2...
## $ magnet_belt_x <int> -3, -7, -2, -6, -6, 0, -4, -2, 1, -3,...
## $ magnet_belt_y <int> 599, 608, 600, 604, 600, 603, 599, 60...
## $ magnet_belt_z <int> -313, -311, -305, -310, -302, -312, -...
## $ roll_arm <dbl> -128, -128, -128, -128, -128, -128, -...
## $ pitch_arm <dbl> 22.5, 22.5, 22.5, 22.1, 22.1, 22.0, 2...
## $ yaw_arm <dbl> -161, -161, -161, -161, -161, -161, -...
## $ total_accel_arm <int> 34, 34, 34, 34, 34, 34, 34, 34, 34, 3...
## $ var_accel_arm <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ avg_roll_arm <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ stddev_roll_arm <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ var_roll_arm <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ avg_pitch_arm <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ stddev_pitch_arm <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ var_pitch_arm <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ avg_yaw_arm <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ stddev_yaw_arm <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ var_yaw_arm <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ gyros_arm_x <dbl> 0.00, 0.02, 0.02, 0.02, 0.00, 0.02, 0...
## $ gyros_arm_y <dbl> 0.00, -0.02, -0.02, -0.03, -0.03, -0....
## $ gyros_arm_z <dbl> -0.02, -0.02, -0.02, 0.02, 0.00, 0.00...
## $ accel_arm_x <int> -288, -290, -289, -289, -289, -289, -...
## $ accel_arm_y <int> 109, 110, 110, 111, 111, 111, 111, 11...
## $ accel_arm_z <int> -123, -125, -126, -123, -123, -122, -...
## $ magnet_arm_x <int> -368, -369, -368, -372, -374, -369, -...
## $ magnet_arm_y <int> 337, 337, 344, 344, 337, 342, 336, 33...
## $ magnet_arm_z <int> 516, 513, 513, 512, 506, 513, 509, 51...
## $ kurtosis_roll_arm <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ kurtosis_picth_arm <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ kurtosis_yaw_arm <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ skewness_roll_arm <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ skewness_pitch_arm <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ skewness_yaw_arm <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ max_roll_arm <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ max_picth_arm <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ max_yaw_arm <int> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ min_roll_arm <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ min_pitch_arm <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ min_yaw_arm <int> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ amplitude_roll_arm <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ amplitude_pitch_arm <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ amplitude_yaw_arm <int> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ roll_dumbbell <dbl> 13.05217, 13.13074, 12.85075, 13.4312...
## $ pitch_dumbbell <dbl> -70.49400, -70.63751, -70.27812, -70....
## $ yaw_dumbbell <dbl> -84.87394, -84.71065, -85.14078, -84....
## $ kurtosis_roll_dumbbell <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ kurtosis_picth_dumbbell <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ kurtosis_yaw_dumbbell <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ skewness_roll_dumbbell <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ skewness_pitch_dumbbell <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ skewness_yaw_dumbbell <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ max_roll_dumbbell <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ max_picth_dumbbell <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ max_yaw_dumbbell <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ min_roll_dumbbell <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ min_pitch_dumbbell <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ min_yaw_dumbbell <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ amplitude_roll_dumbbell <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ amplitude_pitch_dumbbell <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ amplitude_yaw_dumbbell <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ total_accel_dumbbell <int> 37, 37, 37, 37, 37, 37, 37, 37, 37, 3...
## $ var_accel_dumbbell <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ avg_roll_dumbbell <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ stddev_roll_dumbbell <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ var_roll_dumbbell <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ avg_pitch_dumbbell <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ stddev_pitch_dumbbell <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ var_pitch_dumbbell <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ avg_yaw_dumbbell <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ stddev_yaw_dumbbell <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ var_yaw_dumbbell <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ gyros_dumbbell_x <dbl> 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0...
## $ gyros_dumbbell_y <dbl> -0.02, -0.02, -0.02, -0.02, -0.02, -0...
## $ gyros_dumbbell_z <dbl> 0.00, 0.00, 0.00, -0.02, 0.00, 0.00, ...
## $ accel_dumbbell_x <int> -234, -233, -232, -232, -233, -234, -...
## $ accel_dumbbell_y <int> 47, 47, 46, 48, 48, 48, 47, 46, 47, 4...
## $ accel_dumbbell_z <int> -271, -269, -270, -269, -270, -269, -...
## $ magnet_dumbbell_x <int> -559, -555, -561, -552, -554, -558, -...
## $ magnet_dumbbell_y <int> 293, 296, 298, 303, 292, 294, 295, 30...
## $ magnet_dumbbell_z <int> -65, -64, -63, -60, -68, -66, -70, -7...
## $ roll_forearm <dbl> 28.4, 28.3, 28.3, 28.1, 28.0, 27.9, 2...
## $ pitch_forearm <dbl> -63.9, -63.9, -63.9, -63.9, -63.9, -6...
## $ yaw_forearm <dbl> -153, -153, -152, -152, -152, -152, -...
## $ kurtosis_roll_forearm <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ kurtosis_picth_forearm <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ kurtosis_yaw_forearm <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ skewness_roll_forearm <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ skewness_pitch_forearm <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ skewness_yaw_forearm <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ max_roll_forearm <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ max_picth_forearm <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ max_yaw_forearm <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ min_roll_forearm <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ min_pitch_forearm <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ min_yaw_forearm <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ amplitude_roll_forearm <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ amplitude_pitch_forearm <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ amplitude_yaw_forearm <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ total_accel_forearm <int> 36, 36, 36, 36, 36, 36, 36, 36, 36, 3...
## $ var_accel_forearm <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ avg_roll_forearm <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ stddev_roll_forearm <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ var_roll_forearm <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ avg_pitch_forearm <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ stddev_pitch_forearm <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ var_pitch_forearm <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ avg_yaw_forearm <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ stddev_yaw_forearm <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ var_yaw_forearm <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ gyros_forearm_x <dbl> 0.03, 0.02, 0.03, 0.02, 0.02, 0.02, 0...
## $ gyros_forearm_y <dbl> 0.00, 0.00, -0.02, -0.02, 0.00, -0.02...
## $ gyros_forearm_z <dbl> -0.02, -0.02, 0.00, 0.00, -0.02, -0.0...
## $ accel_forearm_x <int> 192, 192, 196, 189, 189, 193, 195, 19...
## $ accel_forearm_y <int> 203, 203, 204, 206, 206, 203, 205, 20...
## $ accel_forearm_z <int> -215, -216, -213, -214, -214, -215, -...
## $ magnet_forearm_x <int> -17, -18, -18, -16, -17, -9, -18, -9,...
## $ magnet_forearm_y <int> 654, 661, 658, 658, 655, 660, 659, 66...
## $ magnet_forearm_z <int> 476, 473, 469, 469, 473, 478, 470, 47...
## $ classe <chr> "A", "A", "A", "A", "A", "A", "A", "A...
Velloso, E.; Bulling, A.; Gellersen, H.; Ugulino, W.; Fuks, H. Qualitative Activity Recognition of Weight Lifting Exercises. Proceedings of 4th International Conference in Cooperation with SIGCHI (Augmented Human ’13) . Stuttgart, Germany: ACM SIGCHI, 2013.