The goal of this project is to predict the manner in which participants perform fitness exercises using raw accelerator data collected from devices such as belt, forearm, arm, and dumbell of the participants. There are five classifications for how the exercises are performed. The classifications are identified by A, B, C, D, and E.
In this analysis, a machine learning model algorithm is built using a cross validated training data and out of sample error rate is calculated. Additional validation is performed using a separate test data set that is provided.
The data for this project is downloaded from http://groupware.les.inf.puc-rio.br/har
First download the training and testing data files and read them in as csv files.
library(caret);
library(randomForest);
# load data files
if(!file.exists("trainData.csv"))
{
download.file("https://d396qusza40orc.cloudfront.net/predmachlearn/pml-training.csv",
destfile= "./trainData.csv")
}
if(!file.exists("testData.csv"))
{
download.file("https://d396qusza40orc.cloudfront.net/predmachlearn/pml-testing.csv",
destfile= "./testData.csv")
}
trainData = read.csv("trainData.csv", na.strings = c('NA','#DIV/0!',''), stringsAsFactors=FALSE)
testData = read.csv("testData.csv", na.strings = c('NA','#DIV/0!',''), stringsAsFactors=FALSE )
In order to reduce unnecessary complexity of the model, irrelevant or erroneous features are dropped from the data set.
In the data set, only data items with the feature new_window == “no”, which indicates that it is a sensor reading and not statistical derivations of the reading, are selected as prediction features.
trainData = trainData[trainData$new_window == "no", ]
Next, select features that have high variance in the data set. Using nearZeroVar() features with very low variance are identified and the corresponding columns are noted to ignore.
nZeroVar = nearZeroVar(trainData, saveMetrics=TRUE)
ignoreColumns = row.names(nZeroVar[nZeroVar$nzv==TRUE, ])
Additionally, data features which have no intrinsic value to the experiment are identified. They are “X”, “user_name”, “raw_timestamp_part_1”, “raw_timestamp_part_2”, “cvtd_timestamp”, and “num_window”. These columns do not quantify how the participants are performing the exercises.
ignoreColumns = append(ignoreColumns, c("X", "user_name", "raw_timestamp_part_1", "raw_timestamp_part_2", "cvtd_timestamp", "num_window"))
The data columns that are identified to ignore are dropped from both training data and the testing data.
trainData = trainData[, -which(names(trainData) %in% ignoreColumns)]
testData = testData[, -which(names(testData) %in% ignoreColumns)]
trainData$classe <-as.factor(trainData$classe)
dim(trainData)
## [1] 19216 53
In order to cross validate, training data is sliced into two subsets: train subset and test subset. This is done to get an idea of what is the out of sample error in the model before the validation with final test data set. Since training data set can be qualified as a low to medium sized data set, using the rules of thumb for prediction study design as describe in the class lecture, 60% of training data is partition for training and 40% for the testing.
set.seed(643216)
inTrain <- createDataPartition (y= trainData$classe, p=0.6, list = FALSE)
trainData.training = trainData[inTrain,]
trainData.testing = trainData[-inTrain,]
The size of the train and test subsets are as follows:
dim(trainData.training)
## [1] 11532 53
dim(trainData.testing)
## [1] 7684 53
Random Forrest machine learning algorithm is selected as the model to train the data because the algorithm is known to be very accurate and has bootstrap capability. In order to save the computational time, trainControl() is used to set the number of cross validation to 3.
trainCtrl = trainControl(method = "cv", number = 3)
if (file.exists("rf.model")) {
load( "rf.model" )
} else {
modelRf <- train(classe~., method="rf", trControl=trainCtrl, data=trainData.training, prox=TRUE)
save(file="rf.model", "modelRf")
}
Training test subset is used to predict results and get estimate out of sample error rate. Using the confusionMatrix, accuracy measure of the prediction is obtained. The estimate for out of sample error rate is defined as 1-Accuracy.
p = predict(modelRf, trainData.testing)
cm = confusionMatrix(p, trainData.testing$classe)
cm
## Confusion Matrix and Statistics
##
## Reference
## Prediction A B C D E
## A 2183 2 0 0 0
## B 4 1485 0 0 0
## C 0 0 1338 3 2
## D 0 0 2 1255 1
## E 1 0 0 0 1408
##
## Overall Statistics
##
## Accuracy : 0.998
## 95% CI : (0.997, 0.999)
## No Information Rate : 0.285
## P-Value [Acc > NIR] : <2e-16
##
## Kappa : 0.998
## Mcnemar's Test P-Value : NA
##
## Statistics by Class:
##
## Class: A Class: B Class: C Class: D Class: E
## Sensitivity 0.998 0.999 0.999 0.998 0.998
## Specificity 1.000 0.999 0.999 1.000 1.000
## Pos Pred Value 0.999 0.997 0.996 0.998 0.999
## Neg Pred Value 0.999 1.000 1.000 1.000 1.000
## Prevalence 0.285 0.194 0.174 0.164 0.184
## Detection Rate 0.284 0.193 0.174 0.163 0.183
## Detection Prevalence 0.284 0.194 0.175 0.164 0.183
## Balanced Accuracy 0.999 0.999 0.999 0.999 0.999
Therefore, the out of sample error rate is 0.002.
Using the provided test data, the following are the result of prediction.
test.predict = predict(modelRf, testData)
test.predict
## [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