Synopsis

This Report is a course project of the Practical Machine Learning Course of Data Science Specialization by Johns Hopkins University on Coursera. Aim of this project is to choose and apply machine learning algorithm to the 20 test cases in the course.The data for this project come from this source: http://groupware.les.inf.puc-rio.br/har

Background Using devices such as Jawbone Up, Nike FuelBand, and Fitbit it is now possible to collect a large amount of data about personal activity relatively inexpensively. These type of devices are part of the quantified self movement – a group of enthusiasts who take measurements about themselves regularly to improve their health, to find patterns in their behavior, or because they are tech geeks. One thing that people regularly do is quantify how much of a particular activity they do, but they rarely quantify how well they do it. In this project, the goal is to use the data from accelerometers on the belt, forearm, arm, and dumbell of 6 participants. They were asked to perform barbell lifts correctly and incorrectly in 5 different ways. More information is available from the website here: http://web.archive.org/web/20161224072740/http:/groupware.les.inf.puc-rio.br/har

Loading the Data

trainingData<-read.csv(url("https://d396qusza40orc.cloudfront.net/predmachlearn/pml-training.csv"),header = TRUE)
testingData<-read.csv(url("https://d396qusza40orc.cloudfront.net/predmachlearn/pml-testing.csv"),header = TRUE)

Exploring the Data

str(trainingData)
## 'data.frame':    19622 obs. of  160 variables:
##  $ X                       : int  1 2 3 4 5 6 7 8 9 10 ...
##  $ user_name               : chr  "carlitos" "carlitos" "carlitos" "carlitos" ...
##  $ 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          : chr  "05/12/2011 11:23" "05/12/2011 11:23" "05/12/2011 11:23" "05/12/2011 11:23" ...
##  $ new_window              : chr  "no" "no" "no" "no" ...
##  $ 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      : chr  "" "" "" "" ...
##  $ kurtosis_picth_belt     : chr  "" "" "" "" ...
##  $ kurtosis_yaw_belt       : chr  "" "" "" "" ...
##  $ skewness_roll_belt      : chr  "" "" "" "" ...
##  $ skewness_roll_belt.1    : chr  "" "" "" "" ...
##  $ skewness_yaw_belt       : chr  "" "" "" "" ...
##  $ 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            : chr  "" "" "" "" ...
##  $ 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            : chr  "" "" "" "" ...
##  $ 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      : chr  "" "" "" "" ...
##  $ 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       : chr  "" "" "" "" ...
##  $ kurtosis_picth_arm      : chr  "" "" "" "" ...
##  $ kurtosis_yaw_arm        : chr  "" "" "" "" ...
##  $ skewness_roll_arm       : chr  "" "" "" "" ...
##  $ skewness_pitch_arm      : chr  "" "" "" "" ...
##  $ skewness_yaw_arm        : chr  "" "" "" "" ...
##  $ 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  : chr  "" "" "" "" ...
##  $ kurtosis_picth_dumbbell : chr  "" "" "" "" ...
##  $ kurtosis_yaw_dumbbell   : chr  "" "" "" "" ...
##  $ skewness_roll_dumbbell  : chr  "" "" "" "" ...
##  $ skewness_pitch_dumbbell : chr  "" "" "" "" ...
##  $ skewness_yaw_dumbbell   : chr  "" "" "" "" ...
##  $ 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        : chr  "" "" "" "" ...
##  $ 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        : chr  "" "" "" "" ...
##  $ amplitude_roll_dumbbell : num  NA NA NA NA NA NA NA NA NA NA ...
##   [list output truncated]
  • The set has 19622 observation and 160 variables. Many columns seems to contain numerous empty "" and NA elements. Before analysis, it will be wise to clear the data for easier analysis.

Data Cleaning

#training Data 
EmptyCols<-which(colSums(is.na(trainingData)| trainingData=="")>0.9*dim(trainingData)[1])
trainingData<-trainingData[,-EmptyCols]
# removing unwanted columns
trainingData<-trainingData[,-c(1:7)]

# testing Data
EmptyCols<-which(colSums(is.na(testingData)| testingData=="")>0.9*dim(testingData)[1])
testingData<-testingData[,-EmptyCols]
# removing unwanted columns
testingData<-testingData[,-c(1:7)]
dim(trainingData)
## [1] 19622    53
dim(testingData)
## [1] 20 53

Data Splitting

suppressMessages(library(caret)); 
## Warning: package 'caret' was built under R version 4.3.2
inTrain <- createDataPartition(trainingData$classe,
                              p=0.7, list=FALSE)
# Training Data
training <- trainingData[inTrain,]
# Test Data
testing <- trainingData[-inTrain,]
dim(training)
## [1] 13737    53

Model Selection

  1. To predict the outcome, we will use three different methods to model regression.
  2. The Random Forest Model rf, Gradient Boosting Model gbm and Decision Tree Model rpart algorithms are used for accuracy comparison.
  3. k-fold cross validation method is used to reduce risk of overfitting.Number of folds are chosen to be 5 to reduce the training time.

Random Forests Model

  • fitting the training data to Random Forest Model
set.seed(33833)
# cross validation 
train.control<-trainControl(method = "cv",number=5)
# Random Forest
model_rf<-train(classe~.,method="rf",data=training,trControl =train.control,verbose=FALSE)

Validating the model on test Data

RF_predict<-predict(model_rf,newdata=testing);
RF_cm<- confusionMatrix(RF_predict,as.factor(testing$classe))
RF_cm
## Confusion Matrix and Statistics
## 
##           Reference
## Prediction    A    B    C    D    E
##          A 1674    6    0    0    0
##          B    0 1131    3    0    0
##          C    0    2 1022   18    0
##          D    0    0    1  945    0
##          E    0    0    0    1 1082
## 
## Overall Statistics
##                                           
##                Accuracy : 0.9947          
##                  95% CI : (0.9925, 0.9964)
##     No Information Rate : 0.2845          
##     P-Value [Acc > NIR] : < 2.2e-16       
##                                           
##                   Kappa : 0.9933          
##                                           
##  Mcnemar's Test P-Value : NA              
## 
## Statistics by Class:
## 
##                      Class: A Class: B Class: C Class: D Class: E
## Sensitivity            1.0000   0.9930   0.9961   0.9803   1.0000
## Specificity            0.9986   0.9994   0.9959   0.9998   0.9998
## Pos Pred Value         0.9964   0.9974   0.9808   0.9989   0.9991
## Neg Pred Value         1.0000   0.9983   0.9992   0.9962   1.0000
## Prevalence             0.2845   0.1935   0.1743   0.1638   0.1839
## Detection Rate         0.2845   0.1922   0.1737   0.1606   0.1839
## Detection Prevalence   0.2855   0.1927   0.1771   0.1607   0.1840
## Balanced Accuracy      0.9993   0.9962   0.9960   0.9900   0.9999
# model accuracy
RF_cm$overall['Accuracy']
##  Accuracy 
## 0.9947324

Gradient Boosting Model

  • fitting the training data to Gradient Boosting Model
model_gbm<-train(classe~.,method="gbm",data=training,trControl = train.control,verbose=FALSE)

Validating the model accuracy on test Data

gbm_predict<-predict(model_gbm,newdata=testing);
gbm_cm<- confusionMatrix(as.factor(testing$classe),gbm_predict)
gbm_cm
## Confusion Matrix and Statistics
## 
##           Reference
## Prediction    A    B    C    D    E
##          A 1648   23    3    0    0
##          B   40 1064   28    3    4
##          C    0   29  987    7    3
##          D    1    1   36  923    3
##          E    1   15   12   14 1040
## 
## Overall Statistics
##                                           
##                Accuracy : 0.9621          
##                  95% CI : (0.9569, 0.9668)
##     No Information Rate : 0.2872          
##     P-Value [Acc > NIR] : < 2.2e-16       
##                                           
##                   Kappa : 0.9521          
##                                           
##  Mcnemar's Test P-Value : 3.99e-07        
## 
## Statistics by Class:
## 
##                      Class: A Class: B Class: C Class: D Class: E
## Sensitivity            0.9751   0.9399   0.9259   0.9747   0.9905
## Specificity            0.9938   0.9842   0.9919   0.9917   0.9913
## Pos Pred Value         0.9845   0.9342   0.9620   0.9575   0.9612
## Neg Pred Value         0.9900   0.9857   0.9837   0.9951   0.9979
## Prevalence             0.2872   0.1924   0.1811   0.1609   0.1784
## Detection Rate         0.2800   0.1808   0.1677   0.1568   0.1767
## Detection Prevalence   0.2845   0.1935   0.1743   0.1638   0.1839
## Balanced Accuracy      0.9845   0.9621   0.9589   0.9832   0.9909
# model accuracy
gbm_cm$overall['Accuracy']
##  Accuracy 
## 0.9621071

Decision Tree Model

model_rpart<-train(classe~., method="rpart", data=training,trControl = train.control)
  • plotting the Decision Tree.
suppressMessages(library(rattle))
## Warning: package 'rattle' was built under R version 4.3.2
fancyRpartPlot(model_rpart$finalModel)

Validating the model accuracy on test Data.

rpart_predict<-predict(model_rpart,testing)
rpart_cm<- confusionMatrix(as.factor(testing$classe),rpart_predict)
# model accuracy
rpart_cm$overall['Accuracy']
##  Accuracy 
## 0.4992353

Comparison of results

  • Accuracies:
print(paste0("Random Forest model accuracy: ",round(RF_cm$overall['Accuracy'],3)))
## [1] "Random Forest model accuracy: 0.995"
print(paste0("Gradient Boosting Model accuracy: ",round(gbm_cm$overall['Accuracy'],3)))
## [1] "Gradient Boosting Model accuracy: 0.962"
print(paste0("Decision Tree Model accuracy: ",round(rpart_cm$overall['Accuracy'],3)))
## [1] "Decision Tree Model accuracy: 0.499"
  • The accuracy obtained form the Random Forest Model rf prediction is 0.995 which better than the Gradient Boosting Model gbm and Decision Tree Model rpart prediction with the accuracy of 0.968 and 0.501 respectively.

Implimenting the best model

  1. After comparing the accuracy rate of three models, The accuracy obtained from ’Random Forest model` is best.
  2. Implementing the Random Forest model to the testData data.
validation<-predict(model_rf,testingData)
validation
##  [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