The predominant approach to preventing injuries currently is to provide athletes with a professional trainer who provides real time feedback while observing the execution of certain exercises. The objective of this work is to determine whether it will be possible to classify errors during the execution of movement based on data obtained from motion traces recorded using on-body sensors. We used regression as our tool to create predictive models on the HAR weight lifting exercises dataset. We classified errors and correct execution of lifting barbells with high accuracy, sensitivity and specificity.
Six male participants aged between 20-28 years, were asked to perform one set of 10 repetitions of Unilateral Dumbbell Biceps Curl using a 1.25 dumbbell in different fashions: exactly according to the specified execution of the exercise (Class A), throwing the elbows to the front (Class B), lifting the dumbbell only halfway (Class C), lowering the dumbbell only halfway (Class D) and throwing the hips to the front (Class E). Mounted sensors in the users’ glove, armband, lumbar belt and dumbbell collected data on the Euler angles (roll, pitch and yaw), as well as the raw accelerometer, gyroscope and magnetometer readings. More information is available from the website http://groupware.les.inf.puc-rio.br/har.
The data for this project come from this source: http://groupware.les.inf.puc-rio.br/har.
training_url <- "https://d396qusza40orc.cloudfront.net/predmachlearn/pml-training.csv"
testing_url <- "https://d396qusza40orc.cloudfront.net/predmachlearn/pml-testing.csv"
download.file(training_url, destfile = "training.csv")
download.file(testing_url, destfile = "testing.csv")
dateDownloaded <- date()
dateDownloaded
## [1] "Tue Apr 05 07:09:58 2016"
library(caret)
library(ggplot2)
training <- read.csv("training.csv", header = TRUE, na.strings = c("NA", "#DIV/0!", ""), stringsAsFactors = FALSE)
testing <- read.csv("testing.csv", header = TRUE, na.strings = c("NA", "#DIV/0!", ""), stringsAsFactors = FALSE)
sumVar_index <- grepl("^min|^max|^kurtosis|^skewness|^avg|^var|^stddev|^amplitude", names(training))###identifying summary variables
sumVar <- names(training)[!sumVar_index]
my_df <- training[, sumVar]### removing summary variables
all_na_index <- sapply(my_df, function(x)sum(is.na(x)))
my_df2 <- my_df[, -c(1:7)]### removing housekeeping variables
The features of the data may be classified into measurement, summary, and housekeeping variables. The summary variables (beginning with: min, max, kurtosis, skewness, avg, stddev, and amplitude) apply summary statisitics on the measurement variables (beginning with: roll, pitch, yaw, total, gyros, magnet, and accel). It would have been preferred to use the summary variables for our model as they immensely reduce the number of observations and processing time and yet contain the gist of the measurement variables. However, it was impossible to make predictions based on the summary variables on the testing dataset as this contain only missing values. We will be removing the housekeeping variables that contain the row numbers (x), timestamps (raw_timestamp_part_1, raw_timestamp_part_2, cvtd_timestamp), and measurement intervals (new_window and num_window).
The downloaded training dataset contains 160 variables and 19622 rows while the testing dataset contains 160 variables and 160 rows.
We need to set the variables into its correct class to avoid errors.
my_df2$total_accel_belt <- as.numeric(my_df2$total_accel_belt)
my_df2$accel_belt_x <- as.numeric(my_df2$ accel_belt_x)
my_df2$accel_belt_y <- as.numeric(my_df2$accel_belt_y)
my_df2$accel_belt_z <- as.numeric(my_df2$accel_belt_z)
my_df2$magnet_belt_x <- as.numeric(my_df2$magnet_belt_x)
my_df2$magnet_belt_y <- as.numeric(my_df2$magnet_belt_y)
my_df2$magnet_belt_z <- as.numeric(my_df2$magnet_belt_z)
my_df2$total_accel_arm <- as.numeric(my_df2$total_accel_arm)
my_df2$accel_arm_x <- as.numeric(my_df2$accel_arm_x)
my_df2$accel_arm_y <- as.numeric(my_df2$accel_arm_y)
my_df2$accel_arm_z <- as.numeric(my_df2$accel_arm_z)
my_df2$magnet_arm_x <- as.numeric(my_df2$magnet_arm_x)
my_df2$magnet_arm_y <- as.numeric(my_df2$magnet_arm_y)
my_df2$magnet_arm_z <- as.numeric(my_df2$magnet_arm_z)
my_df2$total_accel_dumbbell <- as.numeric(my_df2$total_accel_dumbbell)
my_df2$total_accel_dumbbell <- as.numeric(my_df2$total_accel_dumbbell)
my_df2$accel_dumbbell_x <- as.numeric(my_df2$ accel_dumbbell_x)
my_df2$accel_dumbbell_y <- as.numeric(my_df2$ accel_dumbbell_y)
my_df2$accel_dumbbell_z <- as.numeric(my_df2$ accel_dumbbell_z)
my_df2$magnet_dumbbell_x <- as.numeric(my_df2$ magnet_dumbbell_x)
my_df2$magnet_dumbbell_y <- as.numeric(my_df2$ magnet_dumbbell_y)
my_df2$total_accel_forearm <- as.numeric(my_df2$total_accel_forearm)
my_df2$accel_forearm_x <- as.numeric(my_df2$accel_forearm_x)
my_df2$accel_forearm_y <- as.numeric(my_df2$accel_forearm_y)
my_df2$accel_forearm_z <- as.numeric(my_df2$accel_forearm_z)
my_df2$magnet_forearm_x <- as.numeric(my_df2$magnet_forearm_x)
my_df2$classe <- as.factor(my_df2$classe)
###Checking for variables that contain only zeroes
all_zero_index <- sapply(my_df2[,-53], sum)
all_zero_vars <- which(all_zero_index == 0)
We partition the data into a train set and two test sets with 60, 30, and 10 percent composition. A testing set was downloaded earlier as a final validation of the model’s accuracy.
library(caret)
set.seed(107)
intrain <- createDataPartition(y = my_df2$classe, p = 0.6, list = FALSE)
train_set <- my_df2[intrain, ]
validation_set <- my_df2[-intrain, ]
intrain2 <- createDataPartition(y = validation_set$classe, p = 0.75, list = FALSE)
test_set1 <- validation_set[intrain2, ]
test_set2 <- validation_set[-intrain2, ]
The final training dataset contains 53 variables and 11776 rows. The first test set has 53 variables and 5886 rows. The second test set has 53 variables and 1960 rows.
We generate a random forest model on the training dataset using the caret and rf package. The variable classe will be our dependent variable. It contains the classification of whether the movement was performed correctly or not and what error was commited as discussed earlier.We included a 5-fold cross validation to improve our model repeated twice.
ctrl <- trainControl(method="repeatedcv", number=5, repeats=2)
rfor_fitall = train(classe ~ ., data=train_set, method="rf", trControl=ctrl)
We examine the model for its accuracy and we find it to be very accurate.
library(knitr)
print(kable(rfor_fitall$results))
| mtry | Accuracy | Kappa | AccuracySD | KappaSD |
|---|---|---|---|---|
| 2 | 0.9890880 | 0.9861952 | 0.0016867 | 0.0021348 |
| 27 | 0.9891732 | 0.9863023 | 0.0034669 | 0.0043881 |
| 52 | 0.9816579 | 0.9767923 | 0.0048224 | 0.0061066 |
pred_Vset <- predict(rfor_fitall, newdata = test_set1)
out_of_SampleErr <- table(pred_Vset, test_set1$classe)
Model_accuracy <- confusionMatrix(pred_Vset, test_set1$classe)
The table below shows which predictions on the training dataset were correct and which were not. The non-diagonal elements are the errors. it misclassified only 91 out of a possible 11,776 entries for an overall misclassification rate of 0.77%. The misclassification rate for individual classes can be seen at the last column. The overall accuracy is 99.23%.
in_SamplErr <- rfor_fitall$finalModel$confusion
print(kable(in_SamplErr))
| A | B | C | D | E | class.error | |
|---|---|---|---|---|---|---|
| A | 3344 | 2 | 2 | 0 | 0 | 0.0011947 |
| B | 16 | 2255 | 8 | 0 | 0 | 0.0105309 |
| C | 0 | 16 | 2031 | 7 | 0 | 0.0111977 |
| D | 0 | 1 | 24 | 1903 | 2 | 0.0139896 |
| E | 0 | 3 | 3 | 7 | 2152 | 0.0060046 |
The prediction on the the first test dataset was 99.41% accurate. it misclassified only 35 out of a possible 5,886 entries for an overall misclassification rate of 0.59%.
print(kable(out_of_SampleErr))
| A | B | C | D | E | |
|---|---|---|---|---|---|
| A | 1673 | 5 | 0 | 0 | 0 |
| B | 1 | 1130 | 7 | 0 | 0 |
| C | 0 | 4 | 1017 | 9 | 3 |
| D | 0 | 0 | 2 | 955 | 3 |
| E | 0 | 0 | 0 | 1 | 1076 |
The confusion matrix summarize the accuracy, sensitivity, specificity, and other parameters of our model’s prediction by class on the first test set.
print(kable(Model_accuracy$byClass))
| Sensitivity | Specificity | Pos Pred Value | Neg Pred Value | Prevalence | Detection Rate | Detection Prevalence | Balanced Accuracy | |
|---|---|---|---|---|---|---|---|---|
| Class: A | 0.9994026 | 0.9988129 | 0.9970203 | 0.9997624 | 0.2844037 | 0.2842338 | 0.2850832 | 0.9991078 |
| Class: B | 0.9920983 | 0.9983147 | 0.9929701 | 0.9981045 | 0.1935100 | 0.1919810 | 0.1933401 | 0.9952065 |
| Class: C | 0.9912281 | 0.9967078 | 0.9845111 | 0.9981455 | 0.1743119 | 0.1727829 | 0.1755012 | 0.9939679 |
| Class: D | 0.9896373 | 0.9989839 | 0.9947917 | 0.9979700 | 0.1639484 | 0.1622494 | 0.1630989 | 0.9943106 |
| Class: E | 0.9944547 | 0.9997918 | 0.9990715 | 0.9987523 | 0.1838260 | 0.1828067 | 0.1829766 | 0.9971233 |
The plot below shows the relationship between the number of randomly selected predictors and the accuracy. Accuracy is highest when mtry, the number of variables available for splitting at each tree node is 27. mtry is the tuning parameter for the package rf in caret.
plot(rfor_fitall)
We now check which features are important for our model to reduce the number of features in our model to improve the processing time of our model and improve scalability and interpretability.
varImpPlot(rfor_fitall$finalModel, n.var = 27)
We compare the more important features to those which are highly correlated and decide which features to keep.
cor_mat <- cor(train_set[,-53])
Cor_Sum <- summary(cor_mat[upper.tri(cor_mat)])
highcor <- findCorrelation(cor_mat, cutoff = .75)
highcor_Vars <- as.data.frame(names(train_set)[highcor])
print(kable(highcor_Vars))
accel_belt_z
roll_belt
accel_belt_y
accel_arm_y
total_accel_belt
accel_dumbbell_z
accel_belt_x
pitch_belt
magnet_dumbbell_x
accel_dumbbell_y
magnet_dumbbell_y
accel_dumbbell_x
accel_arm_x
accel_arm_z
magnet_arm_y
magnet_belt_z
accel_forearm_y
gyros_arm_x
Can we do just as well with 20 features?
ctrl <- trainControl(method="repeatedcv", number=5, repeats=2)
rfor_fit20 = train(classe ~ yaw_belt + pitch_forearm + magnet_dumbbell_z + pitch_belt + magnet_belt_y + gyros_belt_z + magnet_belt_x + gyros_arm_y + gyros_dumbbell_y + yaw_arm + accel_belt_z + accel_dumbbell_z + accel_dumbbell_y + gyros_forearm_y + accel_forearm_x + gyros_belt_x + magnet_arm_z + gyros_dumbbell_z + magnet_belt_z + magnet_dumbbell_y, data=train_set, method="rf", trControl=ctrl)
pred_Vset20 <- predict(rfor_fit20, newdata = test_set1)
Model_accuracy20 <- confusionMatrix(pred_Vset20, test_set1$classe)
print(kable(Model_accuracy20$byClass))
| Sensitivity | Specificity | Pos Pred Value | Neg Pred Value | Prevalence | Detection Rate | Detection Prevalence | Balanced Accuracy | |
|---|---|---|---|---|---|---|---|---|
| Class: A | 0.9970131 | 0.9985755 | 0.9964179 | 0.9988126 | 0.2844037 | 0.2835542 | 0.2845736 | 0.9977943 |
| Class: B | 0.9903424 | 0.9972614 | 0.9886065 | 0.9976818 | 0.1935100 | 0.1916412 | 0.1938498 | 0.9938019 |
| Class: C | 0.9863548 | 0.9948560 | 0.9758920 | 0.9971128 | 0.1743119 | 0.1719334 | 0.1761808 | 0.9906054 |
| Class: D | 0.9813472 | 0.9987807 | 0.9937041 | 0.9963511 | 0.1639484 | 0.1608902 | 0.1619096 | 0.9900639 |
| Class: E | 0.9972274 | 0.9997918 | 0.9990741 | 0.9993758 | 0.1838260 | 0.1833163 | 0.1834862 | 0.9985096 |
we achieved the same accuracy,sensitivity, and specificity with fewer features. We probably can reduce it some more.
Let’s try a model with 8 features
ctrl <- trainControl(method="repeatedcv", number=5, repeats=2)
rfor_fit8 = train(classe ~ yaw_belt + pitch_forearm + magnet_dumbbell_z + pitch_belt + magnet_dumbbell_y + gyros_belt_z + magnet_belt_x + yaw_arm, data=train_set, method="rf", trControl=ctrl)
pred_testset8 <- predict(rfor_fit8, newdata = test_set1)
Model_accuracy8 <- confusionMatrix(pred_testset8, test_set1$classe)
print(kable(Model_accuracy8$byClass))
| Sensitivity | Specificity | Pos Pred Value | Neg Pred Value | Prevalence | Detection Rate | Detection Prevalence | Balanced Accuracy | |
|---|---|---|---|---|---|---|---|---|
| Class: A | 0.9940263 | 0.9964387 | 0.9910661 | 0.9976230 | 0.2844037 | 0.2827047 | 0.2852531 | 0.9952325 |
| Class: B | 0.9640035 | 0.9957868 | 0.9821109 | 0.9914010 | 0.1935100 | 0.1865443 | 0.1899422 | 0.9798952 |
| Class: C | 0.9853801 | 0.9921811 | 0.9637750 | 0.9968989 | 0.1743119 | 0.1717635 | 0.1782195 | 0.9887806 |
| Class: D | 0.9865285 | 0.9979679 | 0.9896050 | 0.9973599 | 0.1639484 | 0.1617397 | 0.1634387 | 0.9922482 |
| Class: E | 0.9907579 | 0.9987510 | 0.9944341 | 0.9979201 | 0.1838260 | 0.1821271 | 0.1831464 | 0.9947544 |
The results are still impressive. If you recall the plot above, 2 randomly selected predictors was able to achieve a slightly lower accuracy compared to one with 27.
Let’s try a model with 4 features.
rfor_fit4 = train(classe ~ yaw_belt + pitch_forearm + magnet_dumbbell_z + yaw_arm, data=train_set, method="rf", trControl=ctrl)
pred_testset4 <- predict(rfor_fit4, newdata = test_set1)
Model_accuracy4 <- confusionMatrix(pred_testset4, test_set1$classe)
print(kable(Model_accuracy4$byClass))
| Sensitivity | Specificity | Pos Pred Value | Neg Pred Value | Prevalence | Detection Rate | Detection Prevalence | Balanced Accuracy | |
|---|---|---|---|---|---|---|---|---|
| Class: A | 0.9689367 | 0.9883666 | 0.9706762 | 0.9876631 | 0.2844037 | 0.2755691 | 0.2838940 | 0.9786516 |
| Class: B | 0.8858648 | 0.9772488 | 0.9033124 | 0.9727406 | 0.1935100 | 0.1714237 | 0.1897723 | 0.9315568 |
| Class: C | 0.8927875 | 0.9777778 | 0.8945312 | 0.9773756 | 0.1743119 | 0.1556235 | 0.1739721 | 0.9352827 |
| Class: D | 0.9316062 | 0.9784597 | 0.8945274 | 0.9864782 | 0.1639484 | 0.1527353 | 0.1707441 | 0.9550329 |
| Class: E | 0.9574861 | 0.9931307 | 0.9691300 | 0.9904505 | 0.1838260 | 0.1760109 | 0.1816174 | 0.9753084 |
Specificity and sensitivity dipped a bit but a model with 4 features has better interpretability, scalability and faster processing.
we now compare the model with all the variables and the one with 4 only on the second test set.
pred_testsetall_2 <- predict(rfor_fitall, newdata = test_set2)
Model_accuracyall_2 <- confusionMatrix(pred_testsetall_2, test_set2$classe)
pred_testset4_2 <- predict(rfor_fit4, newdata = test_set2)
Model_accuracy4_2 <- confusionMatrix(pred_testset4_2, test_set2$classe)
print(kable(Model_accuracyall_2$byClass))
| Sensitivity | Specificity | Pos Pred Value | Neg Pred Value | Prevalence | Detection Rate | Detection Prevalence | Balanced Accuracy | |
|---|---|---|---|---|---|---|---|---|
| Class: A | 0.9964158 | 0.9985735 | 0.9964158 | 0.9985735 | 0.2846939 | 0.2836735 | 0.2846939 | 0.9974946 |
| Class: B | 0.9947230 | 0.9981025 | 0.9921053 | 0.9987342 | 0.1933673 | 0.1923469 | 0.1938776 | 0.9964127 |
| Class: C | 0.9853801 | 0.9950556 | 0.9768116 | 0.9969040 | 0.1744898 | 0.1719388 | 0.1760204 | 0.9902179 |
| Class: D | 0.9781931 | 0.9981696 | 0.9905363 | 0.9957395 | 0.1637755 | 0.1602041 | 0.1617347 | 0.9881814 |
| Class: E | 0.9972222 | 0.9993750 | 0.9972222 | 0.9993750 | 0.1836735 | 0.1831633 | 0.1836735 | 0.9982986 |
print(kable(Model_accuracy4_2$byClass))
| Sensitivity | Specificity | Pos Pred Value | Neg Pred Value | Prevalence | Detection Rate | Detection Prevalence | Balanced Accuracy | |
|---|---|---|---|---|---|---|---|---|
| Class: A | 0.9784946 | 0.9843081 | 0.9612676 | 0.9913793 | 0.2846939 | 0.2785714 | 0.2897959 | 0.9814014 |
| Class: B | 0.8786280 | 0.9784946 | 0.9073569 | 0.9711237 | 0.1933673 | 0.1698980 | 0.1872449 | 0.9285613 |
| Class: C | 0.8801170 | 0.9796044 | 0.9011976 | 0.9747847 | 0.1744898 | 0.1535714 | 0.1704082 | 0.9298607 |
| Class: D | 0.9314642 | 0.9823063 | 0.9115854 | 0.9865196 | 0.1637755 | 0.1525510 | 0.1673469 | 0.9568852 |
| Class: E | 0.9583333 | 0.9887500 | 0.9504132 | 0.9906074 | 0.1836735 | 0.1760204 | 0.1852041 | 0.9735417 |
Sensitivity suffered a bit, particularly in predicting class B and C errors, but Specificity is still up there. Reducing the number of predictors from 52 to 4 increased bias, which reduced our capacity to predict accurately.
Model_perf <- data.frame(Model_52Pred= c(getTrainPerf(rfor_fitall)[,1], Model_accuracy$overall[1], Model_accuracyall_2$overall[1]), Model_4Pred= c(getTrainPerf(rfor_fit4)[,1], Model_accuracy4$overall[1], Model_accuracy4_2$overall[1]))
rownames(Model_perf) <- c("training_dtset", "testing_set1", "testing_set2")
Model_perf$Model_52Pred <- round(Model_perf$Model_52Pred*100, 2)
Model_perf$Model_4Pred <- round(Model_perf$Model_4Pred*100, 2)
names(Model_perf) <- c("Model_52Accuracy(%)", "Model_4Accuracy(%)")
print(kable(Model_perf))
| Model_52Accuracy(%) | Model_4Accuracy(%) | |
|---|---|---|
| training_dtset | 98.92 | 92.27 |
| testing_set1 | 99.41 | 93.14 |
| testing_set2 | 99.13 | 93.06 |
Based on our model’s performance on the second test set, the estimated prediction error for our model with 52 predictors is 0.87%. For the model with 4 predictors, 6.94%.
Predictive models on the HAR weight lifting exercises dataset classified errors and correct execution of lifting barbells with high accuracy, sensitivity and specificity. It has to be pointed out however, that the errors in movement were performed purposefully. Different results may be obtained when the errors are committed without intent to commit the error.
correctall <- pred_testsetall_2 == test_set2$classe
qplot(pitch_forearm,magnet_dumbbell_z,colour=correctall,data=test_set2)
pred_testset20_2 <- predict(rfor_fit20, newdata = test_set2)
Model_accuracy20_2 <- confusionMatrix(pred_testset20_2, test_set2$classe)
correct20 <- pred_testset20_2 == test_set2$classe
qplot(pitch_forearm,magnet_dumbbell_z,colour=correct20,data=test_set2)
pred_testset8_2 <- predict(rfor_fit8, newdata = test_set2)
Model_accuracy8_2 <- confusionMatrix(pred_testset8_2, test_set2$classe)
correct8 <- pred_testset8_2 == test_set2$classe
qplot(pitch_forearm,magnet_dumbbell_z,colour=correct8,data=test_set2)
correct4 <- pred_testset4_2 == test_set2$classe
qplot(pitch_forearm,magnet_dumbbell_z,colour=correct4,data=test_set2)
We now use our different models to predict on the downloaded test set. The results are the same for all models.
testing_proc <- testing[ , which(names(testing) %in% names(train_set))]
pred_Testset <- predict(rfor_fitall, newdata = testing)
print(pred_Testset)
[1] 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
pred_Testset20 <- predict(rfor_fit20, newdata = testing)
print(pred_Testset20)
[1] 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
pred_Testset8 <- predict(rfor_fit8, newdata = testing)
print(pred_Testset8)
[1] 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
pred_Testset4 <- predict(rfor_fit4, newdata = testing)
print(pred_Testset8)
[1] 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
ctrl <- trainControl(method="repeatedcv", number=5, repeats=2)
pls_fitall = train(classe ~ ., data=train_set, method="pls", preProc = c("center", "scale"), tunelength = 15, trControl=ctrl)
We examine the model for its accuracy on the training set and the testing set1.
library(knitr)
print(kable(pls_fitall$results))
| ncomp | Accuracy | Kappa | AccuracySD | KappaSD |
|---|---|---|---|---|
| 1 | 0.3287191 | 0.1112857 | 0.0062185 | 0.0078111 |
| 2 | 0.3419235 | 0.1318052 | 0.0074621 | 0.0093767 |
| 3 | 0.3698202 | 0.1795564 | 0.0043800 | 0.0058132 |
print(kable(getTrainPerf(pls_fitall)))
| TrainAccuracy | TrainKappa | method |
|---|---|---|
| 0.3698202 | 0.1795564 | pls |
plspred_Vset <- predict(pls_fitall, newdata = test_set1)
plsModel_accuracyall_1 <- confusionMatrix(plspred_Vset, test_set1$classe)
print(kable(plsModel_accuracyall_1$overall))
| Accuracy | 0.3722392 |
| Kappa | 0.1826228 |
| AccuracyLower | 0.3598707 |
| AccuracyUpper | 0.3847345 |
| AccuracyNull | 0.2844037 |
| AccuracyPValue | 0.0000000 |
| McnemarPValue | 0.0000000 |
print(kable(table(plspred_Vset, test_set1$classe)))
| A | B | C | D | E | |
|---|---|---|---|---|---|
| A | 1279 | 523 | 584 | 197 | 252 |
| B | 123 | 315 | 63 | 165 | 252 |
| C | 83 | 90 | 210 | 91 | 206 |
| D | 28 | 64 | 0 | 65 | 50 |
| E | 161 | 147 | 169 | 447 | 322 |
The pls model performed poorly on the training set and the the testing set1.
ctrl <- trainControl(method="repeatedcv", number=5, repeats=2)
multinom_fitall = train(classe ~ ., data=train_set, method="multinom", trControl=ctrl)
We examine the model for its accuracy on the training set and the testing set1.
library(knitr)
print(kable(multinom_fitall$results))
| decay | Accuracy | Kappa | AccuracySD | KappaSD |
|---|---|---|---|---|
| 0e+00 | 0.6361228 | 0.5376890 | 0.0137046 | 0.0174132 |
| 1e-04 | 0.6360804 | 0.5376353 | 0.0136478 | 0.0173401 |
| 1e-01 | 0.6360804 | 0.5376353 | 0.0136478 | 0.0173401 |
print(kable(getTrainPerf(multinom_fitall)))
| TrainAccuracy | TrainKappa | method |
|---|---|---|
| 0.6361228 | 0.537689 | multinom |
multinompred_Vset <- predict(multinom_fitall, newdata = test_set1)
multinomModel_accuracyall_1 <- confusionMatrix(multinompred_Vset, test_set1$classe)
print(kable(multinomModel_accuracyall_1$overall))
| Accuracy | 0.6629290 |
| Kappa | 0.5701510 |
| AccuracyLower | 0.6506893 |
| AccuracyUpper | 0.6750070 |
| AccuracyNull | 0.2844037 |
| AccuracyPValue | 0.0000000 |
| McnemarPValue | 0.0000000 |
print(kable(table(multinompred_Vset, test_set1$classe)))
| A | B | C | D | E | |
|---|---|---|---|---|---|
| A | 1446 | 211 | 188 | 107 | 118 |
| B | 59 | 648 | 83 | 50 | 126 |
| C | 30 | 84 | 572 | 116 | 101 |
| D | 89 | 106 | 83 | 627 | 128 |
| E | 50 | 90 | 100 | 65 | 609 |
ctrl <- trainControl(method="repeatedcv", number=5, repeats=2)
nb_fitall = train(classe ~ ., data=train_set, method="nb", trControl=ctrl)
We examine the model for its accuracy on the training set and the testing set1.
library(knitr)
print(kable(nb_fitall$results))
| usekernel | fL | Accuracy | Kappa | AccuracySD | KappaSD |
|---|---|---|---|---|---|
| FALSE | 0 | 0.5527360 | 0.4355056 | 0.0129700 | 0.0158605 |
| TRUE | 0 | 0.7366274 | 0.6687874 | 0.0117819 | 0.0146712 |
print(kable(getTrainPerf(nb_fitall)))
| TrainAccuracy | TrainKappa | method |
|---|---|---|
| 0.7366274 | 0.6687874 | nb |
nbpred_Vset <- predict(nb_fitall, newdata = test_set1)
nbModel_accuracyall_1 <- confusionMatrix(nbpred_Vset, test_set1$classe)
print(kable(nbModel_accuracyall_1$overall))
| Accuracy | 0.7505946 |
| Kappa | 0.6863954 |
| AccuracyLower | 0.7393338 |
| AccuracyUpper | 0.7616066 |
| AccuracyNull | 0.2844037 |
| AccuracyPValue | 0.0000000 |
| McnemarPValue | 0.0000000 |
print(kable(table(nbpred_Vset, test_set1$classe)))
| A | B | C | D | E | |
|---|---|---|---|---|---|
| A | 1214 | 87 | 58 | 69 | 29 |
| B | 61 | 815 | 71 | 5 | 121 |
| C | 186 | 154 | 871 | 169 | 57 |
| D | 206 | 75 | 24 | 680 | 37 |
| E | 7 | 8 | 2 | 42 | 838 |
ctrl <- trainControl(method="repeatedcv", number=5, repeats=2)
nnet_fitall = train(classe ~ ., data=train_set, method="nnet", trControl=ctrl)
We examine the model for its accuracy on the training set and the testing set1.
library(knitr)
print(kable(nnet_fitall$results))
| size | decay | Accuracy | Kappa | AccuracySD | KappaSD |
|---|---|---|---|---|---|
| 1 | 0e+00 | 0.3227755 | 0.1195081 | 0.0201697 | 0.0494054 |
| 1 | 1e-04 | 0.3321170 | 0.1318785 | 0.0229701 | 0.0422658 |
| 1 | 1e-01 | 0.3347498 | 0.1243856 | 0.0190209 | 0.0490659 |
| 3 | 0e+00 | 0.3673161 | 0.2003524 | 0.0312514 | 0.0384186 |
| 3 | 1e-04 | 0.3648140 | 0.1806105 | 0.0415416 | 0.0754668 |
| 3 | 1e-01 | 0.3679883 | 0.1772609 | 0.0317326 | 0.0687148 |
| 5 | 0e+00 | 0.3924926 | 0.2185783 | 0.0313944 | 0.0560151 |
| 5 | 1e-04 | 0.4060816 | 0.2403058 | 0.0363172 | 0.0517884 |
| 5 | 1e-01 | 0.4075182 | 0.2475214 | 0.0388828 | 0.0579223 |
print(kable(getTrainPerf(nnet_fitall)))
| TrainAccuracy | TrainKappa | method |
|---|---|---|
| 0.4075182 | 0.2475214 | nnet |
nnetpred_Vset <- predict(nnet_fitall, newdata = test_set1)
nnetModel_accuracyall_1 <- confusionMatrix(nnetpred_Vset, test_set1$classe)
print(kable(nnetModel_accuracyall_1$overall))
| Accuracy | 0.4235474 |
| Kappa | 0.2735395 |
| AccuracyLower | 0.4108797 |
| AccuracyUpper | 0.4362909 |
| AccuracyNull | 0.2844037 |
| AccuracyPValue | 0.0000000 |
| McnemarPValue | 0.0000000 |
print(kable(table(nnetpred_Vset, test_set1$classe)))
| A | B | C | D | E | |
|---|---|---|---|---|---|
| A | 972 | 126 | 274 | 129 | 125 |
| B | 145 | 435 | 36 | 111 | 339 |
| C | 444 | 226 | 657 | 328 | 211 |
| D | 78 | 295 | 57 | 367 | 345 |
| E | 35 | 57 | 2 | 30 | 62 |
ctrl <- trainControl(method="repeatedcv", number=5, repeats=2)
lda_fitall = train(classe ~ ., data=train_set, method="lda", trControl=ctrl, preProc = c("center", "scale"))
We examine the model for its accuracy on the training set and the testing set1.
library(knitr)
print(kable(lda_fitall$results))
| parameter | Accuracy | Kappa | AccuracySD | KappaSD |
|---|---|---|---|---|
| none | 0.6951 | 0.6139345 | 0.0113555 | 0.0143503 |
print(kable(getTrainPerf(lda_fitall)))
| TrainAccuracy | TrainKappa | method |
|---|---|---|
| 0.6951 | 0.6139345 | lda |
ldapred_Vset <- predict(nnet_fitall, newdata = test_set1)
ldaModel_accuracyall_1 <- confusionMatrix(ldapred_Vset, test_set1$classe)
print(kable(ldaModel_accuracyall_1$overall))
| Accuracy | 0.4235474 |
| Kappa | 0.2735395 |
| AccuracyLower | 0.4108797 |
| AccuracyUpper | 0.4362909 |
| AccuracyNull | 0.2844037 |
| AccuracyPValue | 0.0000000 |
| McnemarPValue | 0.0000000 |
print(kable(table(ldapred_Vset, test_set1$classe)))
| A | B | C | D | E | |
|---|---|---|---|---|---|
| A | 972 | 126 | 274 | 129 | 125 |
| B | 145 | 435 | 36 | 111 | 339 |
| C | 444 | 226 | 657 | 328 | 211 |
| D | 78 | 295 | 57 | 367 | 345 |
| E | 35 | 57 | 2 | 30 | 62 |
We determine if there is a statistically significant difference between the three models performance.
resampls = resamples(list(RF = rfor_fit4, PLS = pls_fitall, MULTINOM = multinom_fitall, NB = nb_fitall, NNET = nnet_fitall, LDA = lda_fitall))
print(kable(summary(resampls)[3]))
|
print(kable(summary(diff(resampls))[3], caption = "P values and mean difference between models"))
|
bwplot(resampls,metric="Accuracy")
The random forest model achieved a accuracy of more than 90% on first testing set. The multinomial, naive Bayes, and linear discriminatory analysis models performed moderately well with 60% -80% accuracy. The neural network and partial least squares model peformed poorly at around 40%.
sessionInfo()
## R version 3.2.4 (2016-03-10)
## Platform: i386-w64-mingw32/i386 (32-bit)
## Running under: Windows 10 (build 10586)
##
## locale:
## [1] LC_COLLATE=English_United States.1252
## [2] LC_CTYPE=English_United States.1252
## [3] LC_MONETARY=English_United States.1252
## [4] LC_NUMERIC=C
## [5] LC_TIME=English_United States.1252
##
## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
##
## other attached packages:
## [1] nnet_7.3-12 pls_2.5-0 randomForest_4.6-12
## [4] knitr_1.12.3 caret_6.0-64 ggplot2_2.1.0
## [7] lattice_0.20-33
##
## loaded via a namespace (and not attached):
## [1] codetools_0.2-14 digest_0.6.9 htmltools_0.3
## [4] minqa_1.2.4 splines_3.2.4 MatrixModels_0.4-1
## [7] scales_0.3.0 grid_3.2.4 stringr_1.0.0
## [10] e1071_1.6-7 lme4_1.1-11 munsell_0.4.3
## [13] highr_0.5.1 labeling_0.3 foreach_1.4.3
## [16] iterators_1.0.8 mgcv_1.8-12 Matrix_1.2-4
## [19] MASS_7.3-45 plyr_1.8.3 stats4_3.2.4
## [22] stringi_1.0-1 pbkrtest_0.4-6 magrittr_1.5
## [25] car_2.1-1 reshape2_1.4.1 rmarkdown_0.9.5
## [28] evaluate_0.8.3 gtable_0.2.0 colorspace_1.2-6
## [31] yaml_2.1.13 tools_3.2.4 parallel_3.2.4
## [34] nloptr_1.0.4 nlme_3.1-126 quantreg_5.21
## [37] class_7.3-14 formatR_1.3 Rcpp_0.12.4
## [40] SparseM_1.7