Firstly, the data and the necessary R packages were loaded. Then, we try to understand the nature of the data. We find out that most of the variables are numeric variables, and some variables have a lot of NA values. So, we filter the data by removing variables that have a lot of NA values or have a low variation.
Then, we partition our training data set into training set and validation set. Next, we begin training our model using random forest as our predictive algorithm on the training set. We validate our out-of-sample error rate by applying the model to predict the validation set. Low out-of-sample error rate was achieved on the validation set. Finally, we use our model to predict the test set and was able to achieve a 100% prediction accuracy.
setwd("C:/Users/User/Desktop")
training <- read.csv("pml-training.csv", na.strings = c("NA","#DIV/0!",""))
testing <- read.csv("pml-testing.csv", na.strings = c("NA","#DIV/0!",""))
library(plyr);library(dplyr);library(ggplot2); library(caret)
nc <- ncol(training)
str(training[,1:90])
'data.frame': 19622 obs. of 90 variables:
$ X : int 1 2 3 4 5 6 7 8 9 10 ...
$ user_name : Factor w/ 6 levels "adelmo","carlitos",..: 2 2 2 2 2 2 2 2 2 2 ...
$ raw_timestamp_part_1 : int 1323084231 1323084231 1323084231 1323084232 1323084232 1323084232 1323084232 1323084232 1323084232 1323084232 ...
$ raw_timestamp_part_2 : int 788290 808298 820366 120339 196328 304277 368296 440390 484323 484434 ...
$ cvtd_timestamp : Factor w/ 20 levels "02/12/2011 13:32",..: 9 9 9 9 9 9 9 9 9 9 ...
$ new_window : Factor w/ 2 levels "no","yes": 1 1 1 1 1 1 1 1 1 1 ...
$ num_window : int 11 11 11 12 12 12 12 12 12 12 ...
$ roll_belt : num 1.41 1.41 1.42 1.48 1.48 1.45 1.42 1.42 1.43 1.45 ...
$ pitch_belt : num 8.07 8.07 8.07 8.05 8.07 8.06 8.09 8.13 8.16 8.17 ...
$ yaw_belt : num -94.4 -94.4 -94.4 -94.4 -94.4 -94.4 -94.4 -94.4 -94.4 -94.4 ...
$ total_accel_belt : int 3 3 3 3 3 3 3 3 3 3 ...
$ kurtosis_roll_belt : num NA NA NA NA NA NA NA NA NA NA ...
$ kurtosis_picth_belt : num NA NA NA NA NA NA NA NA NA NA ...
$ kurtosis_yaw_belt : logi NA NA NA NA NA NA ...
$ skewness_roll_belt : num NA NA NA NA NA NA NA NA NA NA ...
$ skewness_roll_belt.1 : num NA NA NA NA NA NA NA NA NA NA ...
$ skewness_yaw_belt : logi NA NA NA NA NA NA ...
$ max_roll_belt : num NA NA NA NA NA NA NA NA NA NA ...
$ max_picth_belt : int NA NA NA NA NA NA NA NA NA NA ...
$ max_yaw_belt : num NA NA NA NA NA NA NA NA NA NA ...
$ min_roll_belt : num NA NA NA NA NA NA NA NA NA NA ...
$ min_pitch_belt : int NA NA NA NA NA NA NA NA NA NA ...
$ min_yaw_belt : num NA NA NA NA NA NA NA NA NA NA ...
$ amplitude_roll_belt : num NA NA NA NA NA NA NA NA NA NA ...
$ amplitude_pitch_belt : int NA NA NA NA NA NA NA NA NA NA ...
$ amplitude_yaw_belt : num NA NA NA NA NA NA NA NA NA NA ...
$ var_total_accel_belt : num NA NA NA NA NA NA NA NA NA NA ...
$ avg_roll_belt : num NA NA NA NA NA NA NA NA NA NA ...
$ stddev_roll_belt : num NA NA NA NA NA NA NA NA NA NA ...
$ var_roll_belt : num NA NA NA NA NA NA NA NA NA NA ...
$ avg_pitch_belt : num NA NA NA NA NA NA NA NA NA NA ...
$ stddev_pitch_belt : num NA NA NA NA NA NA NA NA NA NA ...
$ var_pitch_belt : num NA NA NA NA NA NA NA NA NA NA ...
$ avg_yaw_belt : num NA NA NA NA NA NA NA NA NA NA ...
$ stddev_yaw_belt : num NA NA NA NA NA NA NA NA NA NA ...
$ var_yaw_belt : num NA NA NA NA NA NA NA NA NA NA ...
$ gyros_belt_x : num 0 0.02 0 0.02 0.02 0.02 0.02 0.02 0.02 0.03 ...
$ gyros_belt_y : num 0 0 0 0 0.02 0 0 0 0 0 ...
$ gyros_belt_z : num -0.02 -0.02 -0.02 -0.03 -0.02 -0.02 -0.02 -0.02 -0.02 0 ...
$ accel_belt_x : int -21 -22 -20 -22 -21 -21 -22 -22 -20 -21 ...
$ accel_belt_y : int 4 4 5 3 2 4 3 4 2 4 ...
$ accel_belt_z : int 22 22 23 21 24 21 21 21 24 22 ...
$ 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 603 602 609 ...
$ magnet_belt_z : int -313 -311 -305 -310 -302 -312 -311 -313 -312 -308 ...
$ roll_arm : num -128 -128 -128 -128 -128 -128 -128 -128 -128 -128 ...
$ pitch_arm : num 22.5 22.5 22.5 22.1 22.1 22 21.9 21.8 21.7 21.6 ...
$ yaw_arm : num -161 -161 -161 -161 -161 -161 -161 -161 -161 -161 ...
$ total_accel_arm : int 34 34 34 34 34 34 34 34 34 34 ...
$ var_accel_arm : num NA NA NA NA NA NA NA NA NA NA ...
$ avg_roll_arm : num NA NA NA NA NA NA NA NA NA NA ...
$ stddev_roll_arm : num NA NA NA NA NA NA NA NA NA NA ...
$ var_roll_arm : num NA NA NA NA NA NA NA NA NA NA ...
$ avg_pitch_arm : num NA NA NA NA NA NA NA NA NA NA ...
$ stddev_pitch_arm : num NA NA NA NA NA NA NA NA NA NA ...
$ var_pitch_arm : num NA NA NA NA NA NA NA NA NA NA ...
$ avg_yaw_arm : num NA NA NA NA NA NA NA NA NA NA ...
$ stddev_yaw_arm : num NA NA NA NA NA NA NA NA NA NA ...
$ var_yaw_arm : num NA NA NA NA NA NA NA NA NA NA ...
$ gyros_arm_x : num 0 0.02 0.02 0.02 0 0.02 0 0.02 0.02 0.02 ...
$ gyros_arm_y : num 0 -0.02 -0.02 -0.03 -0.03 -0.03 -0.03 -0.02 -0.03 -0.03 ...
$ gyros_arm_z : num -0.02 -0.02 -0.02 0.02 0 0 0 0 -0.02 -0.02 ...
$ accel_arm_x : int -288 -290 -289 -289 -289 -289 -289 -289 -288 -288 ...
$ accel_arm_y : int 109 110 110 111 111 111 111 111 109 110 ...
$ accel_arm_z : int -123 -125 -126 -123 -123 -122 -125 -124 -122 -124 ...
$ magnet_arm_x : int -368 -369 -368 -372 -374 -369 -373 -372 -369 -376 ...
$ magnet_arm_y : int 337 337 344 344 337 342 336 338 341 334 ...
$ magnet_arm_z : int 516 513 513 512 506 513 509 510 518 516 ...
$ kurtosis_roll_arm : num NA NA NA NA NA NA NA NA NA NA ...
$ kurtosis_picth_arm : num NA NA NA NA NA NA NA NA NA NA ...
$ kurtosis_yaw_arm : num NA NA NA NA NA NA NA NA NA NA ...
$ skewness_roll_arm : num NA NA NA NA NA NA NA NA NA NA ...
$ skewness_pitch_arm : num NA NA NA NA NA NA NA NA NA NA ...
$ skewness_yaw_arm : num NA NA NA NA NA NA NA NA NA NA ...
$ max_roll_arm : num NA NA NA NA NA NA NA NA NA NA ...
$ max_picth_arm : num NA NA NA NA NA NA NA NA NA NA ...
$ max_yaw_arm : int NA NA NA NA NA NA NA NA NA NA ...
$ min_roll_arm : num NA NA NA NA NA NA NA NA NA NA ...
$ min_pitch_arm : num NA NA NA NA NA NA NA NA NA NA ...
$ min_yaw_arm : int NA NA NA NA NA NA NA NA NA NA ...
$ amplitude_roll_arm : num NA NA NA NA NA NA NA NA NA NA ...
$ amplitude_pitch_arm : num NA NA NA NA NA NA NA NA NA NA ...
$ amplitude_yaw_arm : int NA NA NA NA NA NA NA NA NA NA ...
$ roll_dumbbell : num 13.1 13.1 12.9 13.4 13.4 ...
$ pitch_dumbbell : num -70.5 -70.6 -70.3 -70.4 -70.4 ...
$ yaw_dumbbell : num -84.9 -84.7 -85.1 -84.9 -84.9 ...
$ kurtosis_roll_dumbbell : num NA NA NA NA NA NA NA NA NA NA ...
$ kurtosis_picth_dumbbell: num NA NA NA NA NA NA NA NA NA NA ...
$ kurtosis_yaw_dumbbell : logi NA NA NA NA NA NA ...
$ skewness_roll_dumbbell : num NA NA NA NA NA NA NA NA NA NA ...
str(training[,91:nc])
'data.frame': 19622 obs. of 70 variables:
$ skewness_pitch_dumbbell : num NA NA NA NA NA NA NA NA NA NA ...
$ skewness_yaw_dumbbell : logi NA NA NA NA NA NA ...
$ max_roll_dumbbell : num NA NA NA NA NA NA NA NA NA NA ...
$ max_picth_dumbbell : num NA NA NA NA NA NA NA NA NA NA ...
$ max_yaw_dumbbell : num NA NA NA NA NA NA NA NA NA NA ...
$ min_roll_dumbbell : num NA NA NA NA NA NA NA NA NA NA ...
$ min_pitch_dumbbell : num NA NA NA NA NA NA NA NA NA NA ...
$ min_yaw_dumbbell : num NA NA NA NA NA NA NA NA NA NA ...
$ amplitude_roll_dumbbell : num NA NA NA NA NA NA NA NA NA NA ...
$ amplitude_pitch_dumbbell: num NA NA NA NA NA NA NA NA NA NA ...
$ amplitude_yaw_dumbbell : num NA NA NA NA NA NA NA NA NA NA ...
$ total_accel_dumbbell : int 37 37 37 37 37 37 37 37 37 37 ...
$ var_accel_dumbbell : num NA NA NA NA NA NA NA NA NA NA ...
$ avg_roll_dumbbell : num NA NA NA NA NA NA NA NA NA NA ...
$ stddev_roll_dumbbell : num NA NA NA NA NA NA NA NA NA NA ...
$ var_roll_dumbbell : num NA NA NA NA NA NA NA NA NA NA ...
$ avg_pitch_dumbbell : num NA NA NA NA NA NA NA NA NA NA ...
$ stddev_pitch_dumbbell : num NA NA NA NA NA NA NA NA NA NA ...
$ var_pitch_dumbbell : num NA NA NA NA NA NA NA NA NA NA ...
$ avg_yaw_dumbbell : num NA NA NA NA NA NA NA NA NA NA ...
$ stddev_yaw_dumbbell : num NA NA NA NA NA NA NA NA NA NA ...
$ var_yaw_dumbbell : num NA NA NA NA NA NA NA NA NA NA ...
$ gyros_dumbbell_x : num 0 0 0 0 0 0 0 0 0 0 ...
$ gyros_dumbbell_y : num -0.02 -0.02 -0.02 -0.02 -0.02 -0.02 -0.02 -0.02 -0.02 -0.02 ...
$ gyros_dumbbell_z : num 0 0 0 -0.02 0 0 0 0 0 0 ...
$ accel_dumbbell_x : int -234 -233 -232 -232 -233 -234 -232 -234 -232 -235 ...
$ accel_dumbbell_y : int 47 47 46 48 48 48 47 46 47 48 ...
$ accel_dumbbell_z : int -271 -269 -270 -269 -270 -269 -270 -272 -269 -270 ...
$ magnet_dumbbell_x : int -559 -555 -561 -552 -554 -558 -551 -555 -549 -558 ...
$ magnet_dumbbell_y : int 293 296 298 303 292 294 295 300 292 291 ...
$ magnet_dumbbell_z : num -65 -64 -63 -60 -68 -66 -70 -74 -65 -69 ...
$ roll_forearm : num 28.4 28.3 28.3 28.1 28 27.9 27.9 27.8 27.7 27.7 ...
$ pitch_forearm : num -63.9 -63.9 -63.9 -63.9 -63.9 -63.9 -63.9 -63.8 -63.8 -63.8 ...
$ yaw_forearm : num -153 -153 -152 -152 -152 -152 -152 -152 -152 -152 ...
$ kurtosis_roll_forearm : num NA NA NA NA NA NA NA NA NA NA ...
$ kurtosis_picth_forearm : num NA NA NA NA NA NA NA NA NA NA ...
$ kurtosis_yaw_forearm : logi NA NA NA NA NA NA ...
$ skewness_roll_forearm : num NA NA NA NA NA NA NA NA NA NA ...
$ skewness_pitch_forearm : num NA NA NA NA NA NA NA NA NA NA ...
$ skewness_yaw_forearm : logi NA NA NA NA NA NA ...
$ max_roll_forearm : num NA NA NA NA NA NA NA NA NA NA ...
$ max_picth_forearm : num NA NA NA NA NA NA NA NA NA NA ...
$ max_yaw_forearm : num NA NA NA NA NA NA NA NA NA NA ...
$ min_roll_forearm : num NA NA NA NA NA NA NA NA NA NA ...
$ min_pitch_forearm : num NA NA NA NA NA NA NA NA NA NA ...
$ min_yaw_forearm : num NA NA NA NA NA NA NA NA NA NA ...
$ amplitude_roll_forearm : num NA NA NA NA NA NA NA NA NA NA ...
$ amplitude_pitch_forearm : num NA NA NA NA NA NA NA NA NA NA ...
$ amplitude_yaw_forearm : num NA NA NA NA NA NA NA NA NA NA ...
$ total_accel_forearm : int 36 36 36 36 36 36 36 36 36 36 ...
$ var_accel_forearm : num NA NA NA NA NA NA NA NA NA NA ...
$ avg_roll_forearm : num NA NA NA NA NA NA NA NA NA NA ...
$ stddev_roll_forearm : num NA NA NA NA NA NA NA NA NA NA ...
$ var_roll_forearm : num NA NA NA NA NA NA NA NA NA NA ...
$ avg_pitch_forearm : num NA NA NA NA NA NA NA NA NA NA ...
$ stddev_pitch_forearm : num NA NA NA NA NA NA NA NA NA NA ...
$ var_pitch_forearm : num NA NA NA NA NA NA NA NA NA NA ...
$ avg_yaw_forearm : num NA NA NA NA NA NA NA NA NA NA ...
$ stddev_yaw_forearm : num NA NA NA NA NA NA NA NA NA NA ...
$ var_yaw_forearm : num NA NA NA NA NA NA NA NA NA NA ...
$ gyros_forearm_x : num 0.03 0.02 0.03 0.02 0.02 0.02 0.02 0.02 0.03 0.02 ...
$ gyros_forearm_y : num 0 0 -0.02 -0.02 0 -0.02 0 -0.02 0 0 ...
$ gyros_forearm_z : num -0.02 -0.02 0 0 -0.02 -0.03 -0.02 0 -0.02 -0.02 ...
$ accel_forearm_x : int 192 192 196 189 189 193 195 193 193 190 ...
$ accel_forearm_y : int 203 203 204 206 206 203 205 205 204 205 ...
$ accel_forearm_z : int -215 -216 -213 -214 -214 -215 -215 -213 -214 -215 ...
$ magnet_forearm_x : int -17 -18 -18 -16 -17 -9 -18 -9 -16 -22 ...
$ magnet_forearm_y : num 654 661 658 658 655 660 659 660 653 656 ...
$ magnet_forearm_z : num 476 473 469 469 473 478 470 474 476 473 ...
$ classe : Factor w/ 5 levels "A","B","C","D",..: 1 1 1 1 1 1 1 1 1 1 ...
There are 159 predictors and 19622 observations. We observe that most predictors are numeric variables.
We can perform some simple variable selection by removing columns that have more than 1% of NA values or absolute value of coefficient of variation of less than 50% (removing variables that have low variation). Besides, the first 5 variables are not meaningful in predicting the outcome, i.e. “X”, “user_name” and the 3 “timestamp” variables.
cleandf <- function(df){
df <- df[,-c(1:5)] #remove X, user_name, and timestamp
cname <- colnames(df)
sub_cname_log <- sapply(cname, FUN = function(x){
if(x %in% "classe"){
return(T)
}else{
df[,x] <<- as.numeric(df[,x])
v <- df[,x]
tf <- sum(is.na(v))/nrow(df) < 0.01 & abs(sd(v)/mean(v)) > 0.5
return(tf)
}
})
return(df[sub_cname_log])
}
cdf.train1 <- cleandf(training); #clean the training data
df1 <- cdf.train1 #creating backup
nc2 <- ncol(cdf.train1)
nc2
## [1] 50
The resulting data frame have 49 predictors left. Now we can train our model.
First, we partition our training data into the training set and validation set, which comprises of 60% and 40% of the original training data respectively.
The training set will be used to train the model; the validation set will be used to validate the out-of-sample error rate of the model.
set.seed(123)
intrain <- createDataPartition(y = df1$classe, p = 0.6, list = F) #60% training, 40% validation set
trn0 <- df1[intrain,]; val0 <- df1[-intrain,]
Random forest is used to train the model, in favour of its prediction accuracy.
model <- "fit1.RData"
if (!file.exists(model)) { #To cache the training process
system.time({
fit1 <- train(classe ~ ., method = "rf", data = trn0) #training the model
})
save(fit1, file = "fit1.RData")
} else {
# Good model exists from previous run, load it and use it.
load(file = "fit1.RData", verbose = TRUE)
}
## Loading objects:
## fit1
pred1 <- predict(fit1, val0)
acc1 <- confusionMatrix(val0$classe, pred1)$overall[1] #Prediction accuracy
confusionMatrix(val0$classe, pred1)
Confusion Matrix and Statistics
Reference
Prediction A B C D E
A 2232 0 0 0 0
B 1 1515 2 0 0
C 0 4 1361 3 0
D 0 0 8 1278 0
E 0 0 0 1 1441
Overall Statistics
Accuracy : 0.9976
95% CI : (0.9962, 0.9985)
No Information Rate : 0.2846
P-Value [Acc > NIR] : < 2.2e-16
Kappa : 0.9969
Mcnemar's Test P-Value : NA
Statistics by Class:
Class: A Class: B Class: C Class: D Class: E
Sensitivity 0.9996 0.9974 0.9927 0.9969 1.0000
Specificity 1.0000 0.9995 0.9989 0.9988 0.9998
Pos Pred Value 1.0000 0.9980 0.9949 0.9938 0.9993
Neg Pred Value 0.9998 0.9994 0.9985 0.9994 1.0000
Prevalence 0.2846 0.1936 0.1747 0.1634 0.1837
Detection Rate 0.2845 0.1931 0.1735 0.1629 0.1837
Detection Prevalence 0.2845 0.1935 0.1744 0.1639 0.1838
Balanced Accuracy 0.9998 0.9984 0.9958 0.9978 0.9999
The prediction accuracy on the validation set is 0.9975784, hence the out-of-sample error rate is 0.0024216, which is very satisfactory. No adjustment is needed, we can proceed to predict the test set.
Finally, we apply our model to predict the 20 test cases.
pred2 <- predict(fit1, newdata = testing)
print(data.frame(pred2))
pred2
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
The printed predictions are then used to verify against the “Course Project Prediction Quiz”. 100% accuracy was obtained!