library('tidyverse')
library('caret')
library('modelr')
set.seed(303)

Part 2: Regression (40 Points)

The table below displays catalog-spending data for the first few of 200 randomly selected individuals from a very large (over 20,000 households) data base.1 The variable of particular interest is catalog spending as measured by the Spending Ratio (SpendRat). All of the catalog variables are represented by indicator variables; either the consumer bought and the variable is coded as 1 or the consumer didn’t buy and the variable is coded as 0. The other variables can be viewed as indexes for measuring assets, liquidity, and spending.

catalog<-read_csv('C:/Users/email/Downloads/catalog.csv')
catalog$CollGifts<-as_factor(catalog$CollGifts)
catalog$BricMortar<-as_factor(catalog$BricMortar)
catalog$MarthaHome<-as_factor(catalog$MarthaHome)
catalog$SunAds<-as_factor(catalog$SunAds)
catalog$ThemeColl<-as_factor(catalog$ThemeColl)
catalog$CustDec<-as_factor(catalog$CustDec)
catalog$RetailKids<-as_factor(catalog$RetailKids)
catalog$TeenWr<-as_factor(catalog$TeenWr)
catalog$Carlovers<-as_factor(catalog$Carlovers)
catalog$CountryColl<-as_factor(catalog$CountryColl)
str(catalog)
Classes ‘spec_tbl_df’, ‘tbl_df’, ‘tbl’ and 'data.frame':    200 obs. of  21 variables:
 $ SpendRat   : num  11.8 16.8 11.4 31.3 1.9 ...
 $ Age        : num  0 35 46 41 46 46 46 56 48 54 ...
 $ LenRes     : num  2 3 9 2 7 15 16 31 8 8 ...
 $ Income     : num  3 5 5 2 9 5 4 6 5 5 ...
 $ TotAsset   : num  122 195 123 117 493 138 162 117 119 50 ...
 $ SecAssets  : num  27 36 24 25 105 27 25 27 23 10 ...
 $ ShortLiq   : num  225 220 200 222 310 340 230 300 250 200 ...
 $ LongLiq    : num  422 420 420 419 500 450 430 440 430 420 ...
 $ WlthIdx    : num  286 430 290 279 520 440 360 400 360 230 ...
 $ SpendVol   : num  503 690 600 543 680 440 690 500 610 660 ...
 $ SpenVel    : num  285 570 280 308 100 50 180 10 0 0 ...
 $ CollGifts  : Factor w/ 2 levels "0","1": 2 1 2 2 1 1 2 2 2 1 ...
 $ BricMortar : Factor w/ 2 levels "0","1": 1 2 1 1 2 2 1 2 1 2 ...
 $ MarthaHome : Factor w/ 2 levels "0","1": 1 2 1 1 2 2 1 2 2 1 ...
 $ SunAds     : Factor w/ 2 levels "0","1": 2 1 2 2 1 1 2 1 1 1 ...
 $ ThemeColl  : Factor w/ 2 levels "0","1": 1 1 2 2 1 1 1 2 2 1 ...
 $ CustDec    : Factor w/ 2 levels "0","1": 2 2 2 1 2 2 1 2 2 1 ...
 $ RetailKids : Factor w/ 2 levels "0","1": 2 2 2 1 1 1 1 2 1 1 ...
 $ TeenWr     : Factor w/ 2 levels "0","1": 2 1 1 1 1 1 1 2 1 2 ...
 $ Carlovers  : Factor w/ 2 levels "0","1": 1 1 1 1 1 2 1 2 1 1 ...
 $ CountryColl: Factor w/ 2 levels "0","1": 2 1 2 2 1 1 2 1 2 1 ...
 - attr(*, "spec")=
  .. cols(
  ..   SpendRat = col_double(),
  ..   Age = col_double(),
  ..   LenRes = col_double(),
  ..   Income = col_double(),
  ..   TotAsset = col_double(),
  ..   SecAssets = col_double(),
  ..   ShortLiq = col_double(),
  ..   LongLiq = col_double(),
  ..   WlthIdx = col_double(),
  ..   SpendVol = col_double(),
  ..   SpenVel = col_double(),
  ..   CollGifts = col_double(),
  ..   BricMortar = col_double(),
  ..   MarthaHome = col_double(),
  ..   SunAds = col_double(),
  ..   ThemeColl = col_double(),
  ..   CustDec = col_double(),
  ..   RetailKids = col_double(),
  ..   TeenWr = col_double(),
  ..   Carlovers = col_double(),
  ..   CountryColl = col_double()
  .. )

Data Cleaning

The goal of this section is to explore the data set and get it ready for analysis. There are no missing values in the data set, but there are some incorrect entries that must be identified and removed before completing the analysis. Income is coded as an ordinal value, ranging from 1 to 12. Age can be regarded as quantitative, and any value less than 18 is invalid. Length of residence (LenRes) is a value ranging from zero to someone’s age. LenRes should not be higher than Age. You should create a simple 1-2 paragraph summary of this section. Be sure to fully explain the reasoning behind transforming any columns and removing any rows. Campbell told me to is not sufficient. Justify why it makes sense not to include any rows whose age is less than 18 or why we shouldn’t use rows in which length of residence is larger than age.

cat.clean<-filter(catalog,Age>=18,LenRes<=Age)

Basic Summary

Provide a basic summary of the cleaned data set. Include a table of univariate statistics to summarize each variable. Choose meaningful summary statistics for each type of variable. You should also include a basic summary of the catalog spending (SpendRat) including an appropriate graphical display.

dim(cat.clean)
[1] 184  21
summary(cat.clean)
    SpendRat            Age            LenRes          Income         TotAsset     
 Min.   :  0.080   Min.   :21.00   Min.   : 0.00   Min.   :1.000   Min.   :  5.00  
 1st Qu.:  6.077   1st Qu.:44.75   1st Qu.: 8.00   1st Qu.:4.000   1st Qu.: 94.75  
 Median : 18.805   Median :53.00   Median :11.00   Median :5.000   Median :150.00  
 Mean   : 43.792   Mean   :54.71   Mean   :14.58   Mean   :4.473   Mean   :184.67  
 3rd Qu.: 50.273   3rd Qu.:63.00   3rd Qu.:19.00   3rd Qu.:5.000   3rd Qu.:222.50  
 Max.   :401.420   Max.   :89.00   Max.   :46.00   Max.   :9.000   Max.   :999.00  
   SecAssets        ShortLiq        LongLiq         WlthIdx         SpendVol        SpenVel     
 Min.   :  0.0   Min.   :160.0   Min.   :400.0   Min.   : 90.0   Min.   :  0.0   Min.   :  0.0  
 1st Qu.: 19.0   1st Qu.:210.0   1st Qu.:420.0   1st Qu.:300.0   1st Qu.:532.0   1st Qu.: 40.0  
 Median : 28.0   Median :230.0   Median :430.0   Median :360.0   Median :610.0   Median :160.0  
 Mean   : 40.9   Mean   :240.6   Mean   :439.5   Mean   :367.1   Mean   :568.4   Mean   :219.5  
 3rd Qu.: 42.0   3rd Qu.:260.0   3rd Qu.:440.0   3rd Qu.:430.0   3rd Qu.:670.0   3rd Qu.:310.0  
 Max.   :999.0   Max.   :999.0   Max.   :999.0   Max.   :880.0   Max.   :780.0   Max.   :999.0  
 CollGifts BricMortar MarthaHome SunAds  ThemeColl CustDec RetailKids TeenWr Carlovers
 0:94      0:131      0:117      0:105   0:111     0:120   0:119      0:89   0:133    
 1:90      1: 53      1: 67      1: 79   1: 73     1: 64   1: 65      1:95   1: 51    
                                                                                      
                                                                                      
                                                                                      
                                                                                      
 CountryColl
 0:107      
 1: 77      
            
            
            
            
cat.clean %>%
  ggplot(aes(x=log(SpendRat))) + geom_histogram()

Modeling

We are interested in developing a model to predict spending ratio. Find a multiple regression model for predicting the amount of money that consumers will spend on catalog shopping, as measured by spending ratio. Your goal is to identify the best model you can. In your write-up be sure to justify your choice of model, discuss any transformation you make to the variables, discuss your model fit, and discuss the effect of the significant predictors using both hypothesis tests and confidence intervals. Remember to check the conditions for inference as you evaluate your models. The data set is much too small to split into training and test data sets, so use cross validation in all your models

## Set up Repeated k-fold Cross Validation
train_control <- trainControl(method="repeatedcv", number=10, repeats=3)

a. Fit a linear model using least squares on the training set, and report the CV error obtained.

lm.fit<-train(log(SpendRat)~., data=cat.clean, trControl=train_control,method='lm')
print(lm.fit)
Linear Regression 

184 samples
 20 predictor

No pre-processing
Resampling: Cross-Validated (10 fold, repeated 3 times) 
Summary of sample sizes: 167, 167, 165, 165, 165, 166, ... 
Resampling results:

  RMSE      Rsquared   MAE     
  1.394231  0.3002504  1.067814

Tuning parameter 'intercept' was held constant at a value of TRUE

b. Fit a ridge regression model on the training set, with \(\lambda\) chosen by cross-validation. Report the CV error obtained.

y_train=log(cat.clean$SpendRat)
X_train=model_matrix(cat.clean,log(SpendRat)~Age+LenRes+Income+TotAsset+SecAssets+ShortLiq+LongLiq+WlthIdx+SpendVol+SpenVel+CollGifts+BricMortar+MarthaHome+SunAds+ThemeColl+CustDec+RetailKids+TeenWr+Carlovers+CountryColl)
parameters <- c(seq(0.1, 2, by =0.1) ,  seq(2, 5, 0.5) , seq(5, 25, 1))
ridge.fit<-train(y=y_train,x=X_train,method='glmnet',trControl=train_control,tuneGrid=expand.grid(alpha=0,lambda = parameters))
print(ridge.fit)
glmnet 

184 samples
 21 predictor

No pre-processing
Resampling: Cross-Validated (10 fold, repeated 3 times) 
Summary of sample sizes: 165, 167, 168, 164, 165, 165, ... 
Resampling results across tuning parameters:

  lambda  RMSE      Rsquared   MAE      
   0.1    1.282431  0.3389732  1.0136866
   0.2    1.262920  0.3477084  1.0012533
   0.3    1.255321  0.3519455  0.9979231
   0.4    1.252062  0.3543630  0.9972646
   0.5    1.251011  0.3558583  0.9976626
   0.6    1.251259  0.3568258  0.9990369
   0.7    1.252338  0.3574662  1.0010517
   0.8    1.253995  0.3578612  1.0033494
   0.9    1.256056  0.3580738  1.0058887
   1.0    1.258394  0.3581592  1.0086132
   1.1    1.260931  0.3581387  1.0113090
   1.2    1.263603  0.3580336  1.0139815
   1.3    1.266368  0.3578600  1.0166161
   1.4    1.269187  0.3576379  1.0192355
   1.5    1.272041  0.3573677  1.0217359
   1.6    1.274899  0.3570578  1.0241457
   1.7    1.277760  0.3567171  1.0265044
   1.8    1.280606  0.3563590  1.0287912
   1.9    1.283413  0.3559797  1.0309755
   2.0    1.286203  0.3555893  1.0330928
   2.5    1.299502  0.3534787  1.0432612
   3.0    1.311641  0.3513105  1.0526532
   3.5    1.322620  0.3492042  1.0618671
   4.0    1.332510  0.3471970  1.0703347
   4.5    1.341475  0.3453146  1.0779618
   5.0    1.349588  0.3435733  1.0848968
   6.0    1.363703  0.3404632  1.0974258
   7.0    1.375527  0.3378082  1.1077753
   8.0    1.385618  0.3355069  1.1165298
   9.0    1.394274  0.3335277  1.1238685
  10.0    1.401810  0.3317875  1.1302016
  11.0    1.408425  0.3302622  1.1356920
  12.0    1.414280  0.3289142  1.1405733
  13.0    1.419500  0.3277156  1.1448879
  14.0    1.424186  0.3266288  1.1487019
  15.0    1.428399  0.3256585  1.1521298
  16.0    1.432213  0.3247865  1.1551995
  17.0    1.435707  0.3239915  1.1579793
  18.0    1.438887  0.3232622  1.1604801
  19.0    1.441809  0.3226010  1.1627590
  20.0    1.444514  0.3219793  1.1648501
  21.0    1.446994  0.3214221  1.1667773
  22.0    1.449315  0.3208923  1.1685728
  23.0    1.451452  0.3204155  1.1702319
  24.0    1.453462  0.3199579  1.1717784
  25.0    1.455326  0.3195462  1.1732128

Tuning parameter 'alpha' was held constant at a value of 0
RMSE was used to select the optimal model using the smallest value.
The final values used for the model were alpha = 0 and lambda = 0.5.

c. Fit a lasso model on the training set, with \(\lambda\) chosen by cross-validation. Report the CV error obtained, along with the number of non-zero coefficient estimates.

y_train=log(cat.clean$SpendRat)
X_train=model_matrix(cat.clean,log(SpendRat)~Age+LenRes+Income+TotAsset+SecAssets+ShortLiq+LongLiq+WlthIdx+SpendVol+SpenVel+CollGifts+BricMortar+MarthaHome+SunAds+ThemeColl+CustDec+RetailKids+TeenWr+Carlovers+CountryColl)
parameters <- c(seq(0.1, 2, by =0.1) ,  seq(2, 5, 0.5) , seq(5, 25, 1))
lasso.fit<-train(y=y_train,x=X_train,method='glmnet',trControl=train_control,tuneGrid=expand.grid(alpha=1,lambda = parameters))
print(lasso.fit)
glmnet 

184 samples
 21 predictor

No pre-processing
Resampling: Cross-Validated (10 fold, repeated 3 times) 
Summary of sample sizes: 166, 167, 165, 165, 167, 168, ... 
Resampling results across tuning parameters:

  lambda  RMSE      Rsquared    MAE      
   0.1    1.250853  0.35615328  0.9923317
   0.2    1.293874  0.33931292  1.0341048
   0.3    1.341793  0.33336816  1.0739817
   0.4    1.407003  0.29713600  1.1281301
   0.5    1.467919  0.23196363  1.1778427
   0.6    1.508460  0.08560497  1.2102028
   0.7    1.510381         NaN  1.2115618
   0.8    1.510381         NaN  1.2115618
   0.9    1.510381         NaN  1.2115618
   1.0    1.510381         NaN  1.2115618
   1.1    1.510381         NaN  1.2115618
   1.2    1.510381         NaN  1.2115618
   1.3    1.510381         NaN  1.2115618
   1.4    1.510381         NaN  1.2115618
   1.5    1.510381         NaN  1.2115618
   1.6    1.510381         NaN  1.2115618
   1.7    1.510381         NaN  1.2115618
   1.8    1.510381         NaN  1.2115618
   1.9    1.510381         NaN  1.2115618
   2.0    1.510381         NaN  1.2115618
   2.5    1.510381         NaN  1.2115618
   3.0    1.510381         NaN  1.2115618
   3.5    1.510381         NaN  1.2115618
   4.0    1.510381         NaN  1.2115618
   4.5    1.510381         NaN  1.2115618
   5.0    1.510381         NaN  1.2115618
   6.0    1.510381         NaN  1.2115618
   7.0    1.510381         NaN  1.2115618
   8.0    1.510381         NaN  1.2115618
   9.0    1.510381         NaN  1.2115618
  10.0    1.510381         NaN  1.2115618
  11.0    1.510381         NaN  1.2115618
  12.0    1.510381         NaN  1.2115618
  13.0    1.510381         NaN  1.2115618
  14.0    1.510381         NaN  1.2115618
  15.0    1.510381         NaN  1.2115618
  16.0    1.510381         NaN  1.2115618
  17.0    1.510381         NaN  1.2115618
  18.0    1.510381         NaN  1.2115618
  19.0    1.510381         NaN  1.2115618
  20.0    1.510381         NaN  1.2115618
  21.0    1.510381         NaN  1.2115618
  22.0    1.510381         NaN  1.2115618
  23.0    1.510381         NaN  1.2115618
  24.0    1.510381         NaN  1.2115618
  25.0    1.510381         NaN  1.2115618

Tuning parameter 'alpha' was held constant at a value of 1
RMSE was used to select the optimal model using the smallest value.
The final values used for the model were alpha = 1 and lambda = 0.1.

d. Fit a PCR model on the training set, with M chosen by cross-validation. Report the CV error obtained, along with the value of M selected by cross-validation.

pcr.fit<-train(log(SpendRat)~., data=cat.clean, trControl=train_control,tuneLength=ncol(cat.clean),method='pcr')
plot(pcr.fit)

pcr.fit$bestTune
print(pcr.fit)
Principal Component Analysis 

184 samples
 20 predictor

No pre-processing
Resampling: Cross-Validated (10 fold, repeated 3 times) 
Summary of sample sizes: 167, 165, 166, 166, 165, 165, ... 
Resampling results across tuning parameters:

  ncomp  RMSE      Rsquared    MAE     
   1     1.504416  0.05292512  1.226453
   2     1.502397  0.05696327  1.227758
   3     1.506584  0.05669179  1.238072
   4     1.504600  0.05817332  1.228613
   5     1.504614  0.05487248  1.228104
   6     1.568391  0.04708296  1.268189
   7     1.530471  0.03903891  1.246003
   8     1.563494  0.04184430  1.267878
   9     1.566718  0.03774084  1.267141
  10     1.590034  0.04801677  1.269187
  11     1.493764  0.13038231  1.208531
  12     1.418096  0.23581979  1.105241
  13     1.394111  0.27989803  1.053194
  14     1.394441  0.27807673  1.051699
  15     1.307876  0.31287039  1.020025
  16     1.325327  0.30587889  1.028624
  17     1.337142  0.29880732  1.035104
  18     1.348773  0.30239710  1.044208
  19     1.367447  0.29728069  1.052854

RMSE was used to select the optimal model using the smallest value.
The final value used for the model was ncomp = 15.

e. Fit a PLS model on the training set, with M chosen by cross-validation. Report the CV error obtained, along with the value of M selected by cross-validation.

pls.fit<-train(log(SpendRat)~., data=cat.clean, trControl=train_control,tuneLength=ncol(cat.clean),method='pls')
plot(pls.fit)

pls.fit$bestTune
print(pls.fit)
Partial Least Squares 

184 samples
 20 predictor

No pre-processing
Resampling: Cross-Validated (10 fold, repeated 3 times) 
Summary of sample sizes: 166, 167, 165, 166, 165, 164, ... 
Resampling results across tuning parameters:

  ncomp  RMSE      Rsquared    MAE     
   1     1.515817  0.07985721  1.234183
   2     1.521152  0.07681501  1.235722
   3     1.524430  0.07891818  1.236456
   4     1.525921  0.06506635  1.227040
   5     1.601973  0.06390192  1.276570
   6     1.672190  0.06527717  1.308169
   7     1.621498  0.08136191  1.286456
   8     1.642158  0.09102616  1.282712
   9     1.730764  0.09214255  1.291040
  10     1.480394  0.22943277  1.135545
  11     1.353831  0.31676170  1.046596
  12     1.357684  0.33486266  1.031558
  13     1.361018  0.32809382  1.046569
  14     1.383036  0.32544019  1.055099
  15     1.385985  0.32711307  1.052993
  16     1.382261  0.32780757  1.050593
  17     1.381936  0.32786463  1.050362
  18     1.381863  0.32790378  1.050287
  19     1.381829  0.32791716  1.050270

RMSE was used to select the optimal model using the smallest value.
The final value used for the model was ncomp = 11.

f. Comment on the results obtained. How accurately can we predict the Spending Ratio? Is there much difference among the CV errors resulting from these five approaches?

Model RMSE
Lasso Regression 1.2508531
Ridge Regression 1.2510108
Principle Components Regression 1.3078756
Partial Least Squares Regression 1.3538306
Linear Regression 1.3942314

Best model was Lasso with \(\lambda\) = 0.1 with a RMSE of 1.2508531. The worst performing model was the linear regression model with a RMSE of 1.3942314. There’s not a substantial amount of difference of CV RMSE across the five models.

Part 3: Classification (40 Points)

In this problem, you will develop a model to predict whether income exceeds $50K/yr based on census data.

a. Use the code in Blackboard to create the adult data set.

adult<-read_csv("https://archive.ics.uci.edu/ml/machine-learning-databases/adult/adult.data", col_names=FALSE, na='?')
names(adult)<-c("age","workclass","fnlwgt","education","education_num","marital_status","occupation","relationship","race","sex","capital_gain","capital_loss","hours_per_week","native_country","income")
adult$fnlwgt<-NULL #remove unnecessary column
#coerce character variables to factors
adult$workclass<-as_factor(adult$workclass)
adult$education<-as_factor(adult$education)
adult$marital_status<-as_factor(adult$marital_status)
adult$occupation<-as_factor(adult$occupation)
adult$relationship<-as_factor(adult$relationship)
adult$race<-as_factor(adult$race)
adult$sex<-as_factor(adult$sex)
adult$native_country<-as_factor(adult$native_country)
adult$income<-as_factor(adult$income)
adult<-na.omit(adult) #remove missing observations
y=adult$income
X=model_matrix(adult,income~.) #create dummy variables
X$`(Intercept)`<-NULL #remove unnecessary column
adult2<-as_tibble(cbind(adult$income,X),.name_repair = "unique") #create new data set
names(adult2)[1]<-"income" #fix the name of the outcome variable
nsv<-nearZeroVar(adult2,saveMetrics = FALSE) #identify near zero variance predictors
adult3<-adult2[,-nsv] #remove them
adult3

b. Explore the data graphically in order to investigate the association between income and the other features. Which of the other features seem most likely to be useful in predicting income? Scatterplots and boxplots may be useful tools to answer this question. Describe your findings.

Using random forest method for feature selection.

##Generate a small sample of the data set to investigate which variables are closely associated with income
k=sample(nrow(adult3),nrow(adult2)*0.08)

##Use random forest model to calculate variable importance
rf=train(income~.,data=adult3[k,])
rfImp<-varImp(rf)
plot(rfImp,top=10)

c. Split the data into an 80% training set and a 20% test set. Set the seed at 1303.

##Create training indicator vector
inTrain <- createDataPartition(adult3$income, p=0.8, list=FALSE)
##Tabulate training and test data sets
train=adult3[inTrain,]
test=adult3[-inTrain,]
dim(adult2)
[1] 30162    97
dim(train)
[1] 24131    24
dim(test)
[1] 6031   24

d. Perform LDA on the training data in order to predict income using the variables that seemed most associated with income in (b). What is the test error of the model obtained?

##Train Model
lda.fit=train(income~`marital_statusMarried-civ-spouse` + education_num + relationshipHusband  + age + hours_per_week  + `occupationExec-managerial`  + `occupationProf-specialty` + sexFemale + `relationshipOwn-child`,data=train,method='lda',trControl = trainControl(method = "cv"))
lda.fit
Linear Discriminant Analysis 

24131 samples
    9 predictor
    2 classes: '<=50K', '>50K' 

No pre-processing
Resampling: Cross-Validated (10 fold) 
Summary of sample sizes: 21719, 21718, 21717, 21718, 21718, 21719, ... 
Resampling results:

  Accuracy   Kappa    
  0.8226754  0.4894095
##Calculate Predictions
pred.lda<-predict(lda.fit,test)
##Estimate Accuracy
confusionMatrix(pred.lda,test$income)
Confusion Matrix and Statistics

          Reference
Prediction <=50K >50K
     <=50K  4139  704
     >50K    391  797
                                          
               Accuracy : 0.8184          
                 95% CI : (0.8085, 0.8281)
    No Information Rate : 0.7511          
    P-Value [Acc > NIR] : < 2.2e-16       
                                          
                  Kappa : 0.478           
                                          
 Mcnemar's Test P-Value : < 2.2e-16       
                                          
            Sensitivity : 0.9137          
            Specificity : 0.5310          
         Pos Pred Value : 0.8546          
         Neg Pred Value : 0.6709          
             Prevalence : 0.7511          
         Detection Rate : 0.6863          
   Detection Prevalence : 0.8030          
      Balanced Accuracy : 0.7223          
                                          
       'Positive' Class : <=50K           
                                          

e. Perform QDA on the training data in order to predict income using the variables that seemed most associated with income in (b). What is the test error of the model obtained?

##Train Model
qda.fit=train(income~`marital_statusMarried-civ-spouse` + education_num + relationshipHusband  + age + hours_per_week  + `occupationExec-managerial`  + `occupationProf-specialty` + sexFemale + `relationshipOwn-child`,data=train,method='qda',trControl = trainControl(method = "cv"))
qda.fit
Quadratic Discriminant Analysis 

24131 samples
    9 predictor
    2 classes: '<=50K', '>50K' 

No pre-processing
Resampling: Cross-Validated (10 fold) 
Summary of sample sizes: 21719, 21718, 21718, 21719, 21718, 21718, ... 
Resampling results:

  Accuracy   Kappa    
  0.7522264  0.4660741
##Calculate Predictions
pred.qda<-predict(qda.fit,test)
##Estimate Accuracy
confusionMatrix(pred.qda,test$income)
Confusion Matrix and Statistics

          Reference
Prediction <=50K >50K
     <=50K  3271  213
     >50K   1259 1288
                                          
               Accuracy : 0.7559          
                 95% CI : (0.7449, 0.7667)
    No Information Rate : 0.7511          
    P-Value [Acc > NIR] : 0.1982          
                                          
                  Kappa : 0.4705          
                                          
 Mcnemar's Test P-Value : <2e-16          
                                          
            Sensitivity : 0.7221          
            Specificity : 0.8581          
         Pos Pred Value : 0.9389          
         Neg Pred Value : 0.5057          
             Prevalence : 0.7511          
         Detection Rate : 0.5424          
   Detection Prevalence : 0.5777          
      Balanced Accuracy : 0.7901          
                                          
       'Positive' Class : <=50K           
                                          

f. Perform logistic regression on the training data in order to predict income using the variables that seemed most associated with income in (b). What is the test error of the model obtained?

##Train Model
glm.fit=train(income~`marital_statusMarried-civ-spouse` + education_num + relationshipHusband  + age + hours_per_week  + `occupationExec-managerial`  + `occupationProf-specialty` + sexFemale + `relationshipOwn-child`,data=train,method='glm',trControl = trainControl(method = "cv"))
glm.fit
Generalized Linear Model 

24131 samples
    9 predictor
    2 classes: '<=50K', '>50K' 

No pre-processing
Resampling: Cross-Validated (10 fold) 
Summary of sample sizes: 21719, 21718, 21717, 21719, 21717, 21717, ... 
Resampling results:

  Accuracy   Kappa    
  0.8238368  0.4869807
##Calculate Predictions
pred.glm<-predict(glm.fit,test)
##Estimate Accuracy
confusionMatrix(pred.glm,test$income)
Confusion Matrix and Statistics

          Reference
Prediction <=50K >50K
     <=50K  4154  728
     >50K    376  773
                                         
               Accuracy : 0.8169         
                 95% CI : (0.807, 0.8266)
    No Information Rate : 0.7511         
    P-Value [Acc > NIR] : < 2.2e-16      
                                         
                  Kappa : 0.4687         
                                         
 Mcnemar's Test P-Value : < 2.2e-16      
                                         
            Sensitivity : 0.9170         
            Specificity : 0.5150         
         Pos Pred Value : 0.8509         
         Neg Pred Value : 0.6728         
             Prevalence : 0.7511         
         Detection Rate : 0.6888         
   Detection Prevalence : 0.8095         
      Balanced Accuracy : 0.7160         
                                         
       'Positive' Class : <=50K          
                                         

g. Perform KNN on the training data, with several values of K, in order to predict income. Use only the variables that seemed most associated with income in (b). What test errors do you obtain? Which value of K seems to perform the best on this data set?

##Train Model, Let CV choose value for K
knn.fit<-train(income~`marital_statusMarried-civ-spouse` + education_num + relationshipHusband  + age + hours_per_week  + `occupationExec-managerial`  + `occupationProf-specialty` + sexFemale + `relationshipOwn-child`,data=train,method='knn',trControl = trainControl(method = "cv"), tuneLength=20)
knn.fit
k-Nearest Neighbors 

24131 samples
    9 predictor
    2 classes: '<=50K', '>50K' 

No pre-processing
Resampling: Cross-Validated (10 fold) 
Summary of sample sizes: 21718, 21717, 21718, 21718, 21718, 21718, ... 
Resampling results across tuning parameters:

  k   Accuracy   Kappa    
   5  0.8047330  0.4363006
   7  0.8067635  0.4383265
   9  0.8078823  0.4407662
  11  0.8092911  0.4431910
  13  0.8097055  0.4439116
  15  0.8100371  0.4443474
  17  0.8093331  0.4421319
  19  0.8086285  0.4380045
  21  0.8098304  0.4399584
  23  0.8096647  0.4388197
  25  0.8100791  0.4385366
  27  0.8106590  0.4386679
  29  0.8095400  0.4356190
  31  0.8099544  0.4361528
  33  0.8094984  0.4343682
  35  0.8097058  0.4343902
  37  0.8108248  0.4370759
  39  0.8097059  0.4336888
  41  0.8098714  0.4334224
  43  0.8094986  0.4328404

Accuracy was used to select the optimal model using the largest value.
The final value used for the model was k = 37.
##Calculate Predictions
pred.knn<-predict(knn.fit,test)
##Estimate Accuracy
confusionMatrix(pred.knn,test$income)
Confusion Matrix and Statistics

          Reference
Prediction <=50K >50K
     <=50K  4184  794
     >50K    346  707
                                          
               Accuracy : 0.811           
                 95% CI : (0.8009, 0.8208)
    No Information Rate : 0.7511          
    P-Value [Acc > NIR] : < 2.2e-16       
                                          
                  Kappa : 0.4384          
                                          
 Mcnemar's Test P-Value : < 2.2e-16       
                                          
            Sensitivity : 0.9236          
            Specificity : 0.4710          
         Pos Pred Value : 0.8405          
         Neg Pred Value : 0.6714          
             Prevalence : 0.7511          
         Detection Rate : 0.6937          
   Detection Prevalence : 0.8254          
      Balanced Accuracy : 0.6973          
                                          
       'Positive' Class : <=50K           
                                          

h. Choose which model predicts income the best and justify your choice.

Model Accuracy
Quadratic Discriminant 0.7522264
K Nearest Neighbors (K=37) 0.8108248
Linear Discriminant 0.8226754
Logistic Regression 0.8238368
LS0tDQp0aXRsZTogIlNUQSA0MTQzIERhdGEgTWluaW5nIE1pZHRlcm0gaW4gQ0FSRVQiDQpvdXRwdXQ6IA0KICBodG1sX25vdGVib29rOg0KICAgIHRvYzogdHJ1ZQ0KICAgIHRvY19mbG9hdDogdHJ1ZQ0KLS0tDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRSkNCmBgYA0KDQpgYGB7cn0NCmxpYnJhcnkoJ3RpZHl2ZXJzZScpDQpsaWJyYXJ5KCdjYXJldCcpDQpsaWJyYXJ5KCdtb2RlbHInKQ0Kc2V0LnNlZWQoMzAzKQ0KYGBgDQojIyMgUGFydCAyOiBSZWdyZXNzaW9uICg0MCBQb2ludHMpDQpUaGUgdGFibGUgYmVsb3cgZGlzcGxheXMgY2F0YWxvZy1zcGVuZGluZyBkYXRhIGZvciB0aGUgZmlyc3QgZmV3IG9mIDIwMCByYW5kb21seSBzZWxlY3RlZCBpbmRpdmlkdWFscyBmcm9tIGEgdmVyeSBsYXJnZSAob3ZlciAyMCwwMDAgaG91c2Vob2xkcykgZGF0YSBiYXNlLjEgVGhlIHZhcmlhYmxlIG9mIHBhcnRpY3VsYXIgaW50ZXJlc3QgaXMgY2F0YWxvZyBzcGVuZGluZyBhcyBtZWFzdXJlZCBieSB0aGUgU3BlbmRpbmcgUmF0aW8gKFNwZW5kUmF0KS4gQWxsIG9mIHRoZSBjYXRhbG9nIHZhcmlhYmxlcyBhcmUgcmVwcmVzZW50ZWQgYnkgaW5kaWNhdG9yIHZhcmlhYmxlczsgZWl0aGVyIHRoZSBjb25zdW1lciBib3VnaHQgYW5kIHRoZSB2YXJpYWJsZSBpcyBjb2RlZCBhcyAxIG9yIHRoZSBjb25zdW1lciBkaWRu4oCZdCBidXkgYW5kIHRoZSB2YXJpYWJsZSBpcyBjb2RlZCBhcyAwLiBUaGUgb3RoZXIgdmFyaWFibGVzIGNhbiBiZSB2aWV3ZWQgYXMgaW5kZXhlcyBmb3IgbWVhc3VyaW5nIGFzc2V0cywgbGlxdWlkaXR5LCBhbmQgc3BlbmRpbmcuDQoNCmBgYHtyfQ0KY2F0YWxvZzwtcmVhZF9jc3YoJ0M6L1VzZXJzL2VtYWlsL0Rvd25sb2Fkcy9jYXRhbG9nLmNzdicpDQpjYXRhbG9nJENvbGxHaWZ0czwtYXNfZmFjdG9yKGNhdGFsb2ckQ29sbEdpZnRzKQ0KY2F0YWxvZyRCcmljTW9ydGFyPC1hc19mYWN0b3IoY2F0YWxvZyRCcmljTW9ydGFyKQ0KY2F0YWxvZyRNYXJ0aGFIb21lPC1hc19mYWN0b3IoY2F0YWxvZyRNYXJ0aGFIb21lKQ0KY2F0YWxvZyRTdW5BZHM8LWFzX2ZhY3RvcihjYXRhbG9nJFN1bkFkcykNCmNhdGFsb2ckVGhlbWVDb2xsPC1hc19mYWN0b3IoY2F0YWxvZyRUaGVtZUNvbGwpDQpjYXRhbG9nJEN1c3REZWM8LWFzX2ZhY3RvcihjYXRhbG9nJEN1c3REZWMpDQpjYXRhbG9nJFJldGFpbEtpZHM8LWFzX2ZhY3RvcihjYXRhbG9nJFJldGFpbEtpZHMpDQpjYXRhbG9nJFRlZW5XcjwtYXNfZmFjdG9yKGNhdGFsb2ckVGVlbldyKQ0KY2F0YWxvZyRDYXJsb3ZlcnM8LWFzX2ZhY3RvcihjYXRhbG9nJENhcmxvdmVycykNCmNhdGFsb2ckQ291bnRyeUNvbGw8LWFzX2ZhY3RvcihjYXRhbG9nJENvdW50cnlDb2xsKQ0Kc3RyKGNhdGFsb2cpDQpgYGANCg0KIyMjIyBEYXRhIENsZWFuaW5nDQpUaGUgZ29hbCBvZiB0aGlzIHNlY3Rpb24gaXMgdG8gZXhwbG9yZSB0aGUgZGF0YSBzZXQgYW5kIGdldCBpdCByZWFkeSBmb3IgYW5hbHlzaXMuIFRoZXJlIGFyZSBubyBtaXNzaW5nIHZhbHVlcyBpbiB0aGUgZGF0YSBzZXQsIGJ1dCB0aGVyZSBhcmUgc29tZSBpbmNvcnJlY3QgZW50cmllcyB0aGF0IG11c3QgYmUgaWRlbnRpZmllZCBhbmQgcmVtb3ZlZCBiZWZvcmUgY29tcGxldGluZyB0aGUgYW5hbHlzaXMuIEluY29tZSBpcyBjb2RlZCBhcyBhbiBvcmRpbmFsIHZhbHVlLCByYW5naW5nIGZyb20gMSB0byAxMi4gQWdlIGNhbiBiZSByZWdhcmRlZCBhcyBxdWFudGl0YXRpdmUsIGFuZCBhbnkgdmFsdWUgbGVzcyB0aGFuIDE4IGlzIGludmFsaWQuIExlbmd0aCBvZiByZXNpZGVuY2UgKExlblJlcykgaXMgYSB2YWx1ZSByYW5naW5nIGZyb20gemVybyB0byBzb21lb25l4oCZcyBhZ2UuIExlblJlcyBzaG91bGQgbm90IGJlIGhpZ2hlciB0aGFuIEFnZS4gWW91IHNob3VsZCBjcmVhdGUgYSBzaW1wbGUgMS0yIHBhcmFncmFwaCBzdW1tYXJ5IG9mIHRoaXMgc2VjdGlvbi4gQmUgc3VyZSB0byBmdWxseSBleHBsYWluIHRoZSByZWFzb25pbmcgYmVoaW5kIHRyYW5zZm9ybWluZyBhbnkgY29sdW1ucyBhbmQgcmVtb3ZpbmcgYW55IHJvd3MuIENhbXBiZWxsIHRvbGQgbWUgdG8gaXMgbm90IHN1ZmZpY2llbnQuIEp1c3RpZnkgd2h5IGl0IG1ha2VzIHNlbnNlIG5vdCB0byBpbmNsdWRlIGFueSByb3dzIHdob3NlIGFnZSBpcyBsZXNzIHRoYW4gMTggb3Igd2h5IHdlIHNob3VsZG7igJl0IHVzZSByb3dzIGluIHdoaWNoIGxlbmd0aCBvZiByZXNpZGVuY2UgaXMgbGFyZ2VyIHRoYW4gYWdlLg0KDQpgYGB7cn0NCmNhdC5jbGVhbjwtZmlsdGVyKGNhdGFsb2csQWdlPj0xOCxMZW5SZXM8PUFnZSkNCmBgYA0KDQojIyMjIEJhc2ljIFN1bW1hcnkNClByb3ZpZGUgYSBiYXNpYyBzdW1tYXJ5IG9mIHRoZSBjbGVhbmVkIGRhdGEgc2V0LiBJbmNsdWRlIGEgdGFibGUgb2YgdW5pdmFyaWF0ZSBzdGF0aXN0aWNzIHRvIHN1bW1hcml6ZSBlYWNoIHZhcmlhYmxlLiBDaG9vc2UgbWVhbmluZ2Z1bCBzdW1tYXJ5IHN0YXRpc3RpY3MgZm9yIGVhY2ggdHlwZSBvZiB2YXJpYWJsZS4gWW91IHNob3VsZCBhbHNvIGluY2x1ZGUgYSBiYXNpYyBzdW1tYXJ5IG9mIHRoZSBjYXRhbG9nIHNwZW5kaW5nIChTcGVuZFJhdCkgaW5jbHVkaW5nIGFuIGFwcHJvcHJpYXRlIGdyYXBoaWNhbCBkaXNwbGF5Lg0KDQpgYGB7cn0NCmRpbShjYXQuY2xlYW4pDQpzdW1tYXJ5KGNhdC5jbGVhbikNCmNhdC5jbGVhbiAlPiUNCiAgZ2dwbG90KGFlcyh4PWxvZyhTcGVuZFJhdCkpKSArIGdlb21faGlzdG9ncmFtKCkNCmBgYA0KDQojIyMjIE1vZGVsaW5nDQpXZSBhcmUgaW50ZXJlc3RlZCBpbiBkZXZlbG9waW5nIGEgbW9kZWwgdG8gcHJlZGljdCBzcGVuZGluZyByYXRpby4gRmluZCBhIG11bHRpcGxlIHJlZ3Jlc3Npb24gbW9kZWwgZm9yIHByZWRpY3RpbmcgdGhlIGFtb3VudCBvZiBtb25leSB0aGF0IGNvbnN1bWVycyB3aWxsIHNwZW5kIG9uIGNhdGFsb2cgc2hvcHBpbmcsIGFzIG1lYXN1cmVkIGJ5IHNwZW5kaW5nIHJhdGlvLiBZb3VyIGdvYWwgaXMgdG8gaWRlbnRpZnkgdGhlIGJlc3QgbW9kZWwgeW91IGNhbi4gSW4geW91ciB3cml0ZS11cCBiZSBzdXJlIHRvIGp1c3RpZnkgeW91ciBjaG9pY2Ugb2YgbW9kZWwsIGRpc2N1c3MgYW55IHRyYW5zZm9ybWF0aW9uIHlvdSBtYWtlIHRvIHRoZSB2YXJpYWJsZXMsIGRpc2N1c3MgeW91ciBtb2RlbCBmaXQsIGFuZCBkaXNjdXNzIHRoZSBlZmZlY3Qgb2YgdGhlIHNpZ25pZmljYW50IHByZWRpY3RvcnMgdXNpbmcgYm90aCBoeXBvdGhlc2lzIHRlc3RzIGFuZCBjb25maWRlbmNlIGludGVydmFscy4gUmVtZW1iZXIgdG8gY2hlY2sgdGhlIGNvbmRpdGlvbnMgZm9yIGluZmVyZW5jZSBhcyB5b3UgZXZhbHVhdGUgeW91ciBtb2RlbHMuIFRoZSBkYXRhIHNldCBpcyBtdWNoIHRvbyBzbWFsbCB0byBzcGxpdCBpbnRvIHRyYWluaW5nIGFuZCB0ZXN0IGRhdGEgc2V0cywgc28gdXNlIGNyb3NzIHZhbGlkYXRpb24gaW4gYWxsIHlvdXIgbW9kZWxzDQoNCmBgYHtyfQ0KIyMgU2V0IHVwIFJlcGVhdGVkIGstZm9sZCBDcm9zcyBWYWxpZGF0aW9uDQp0cmFpbl9jb250cm9sIDwtIHRyYWluQ29udHJvbChtZXRob2Q9InJlcGVhdGVkY3YiLCBudW1iZXI9MTAsIHJlcGVhdHM9MykNCmBgYA0KDQoqKmEuIEZpdCBhIGxpbmVhciBtb2RlbCB1c2luZyBsZWFzdCBzcXVhcmVzIG9uIHRoZSB0cmFpbmluZyBzZXQsIGFuZCByZXBvcnQgdGhlIENWIGVycm9yIG9idGFpbmVkLioqDQoNCmBgYHtyfQ0KbG0uZml0PC10cmFpbihsb2coU3BlbmRSYXQpfi4sIGRhdGE9Y2F0LmNsZWFuLCB0ckNvbnRyb2w9dHJhaW5fY29udHJvbCxtZXRob2Q9J2xtJykNCnByaW50KGxtLmZpdCkNCmBgYA0KDQoqKmIuIEZpdCBhIHJpZGdlIHJlZ3Jlc3Npb24gbW9kZWwgb24gdGhlIHRyYWluaW5nIHNldCwgd2l0aCAkXGxhbWJkYSQgY2hvc2VuIGJ5IGNyb3NzLXZhbGlkYXRpb24uIFJlcG9ydCB0aGUgQ1YgZXJyb3Igb2J0YWluZWQuKioNCmBgYHtyfQ0KeV90cmFpbj1sb2coY2F0LmNsZWFuJFNwZW5kUmF0KQ0KWF90cmFpbj1tb2RlbF9tYXRyaXgoY2F0LmNsZWFuLGxvZyhTcGVuZFJhdCl+QWdlK0xlblJlcytJbmNvbWUrVG90QXNzZXQrU2VjQXNzZXRzK1Nob3J0TGlxK0xvbmdMaXErV2x0aElkeCtTcGVuZFZvbCtTcGVuVmVsK0NvbGxHaWZ0cytCcmljTW9ydGFyK01hcnRoYUhvbWUrU3VuQWRzK1RoZW1lQ29sbCtDdXN0RGVjK1JldGFpbEtpZHMrVGVlbldyK0NhcmxvdmVycytDb3VudHJ5Q29sbCkNCnBhcmFtZXRlcnMgPC0gYyhzZXEoMC4xLCAyLCBieSA9MC4xKSAsICBzZXEoMiwgNSwgMC41KSAsIHNlcSg1LCAyNSwgMSkpDQpyaWRnZS5maXQ8LXRyYWluKHk9eV90cmFpbix4PVhfdHJhaW4sbWV0aG9kPSdnbG1uZXQnLHRyQ29udHJvbD10cmFpbl9jb250cm9sLHR1bmVHcmlkPWV4cGFuZC5ncmlkKGFscGhhPTAsbGFtYmRhID0gcGFyYW1ldGVycykpDQpwcmludChyaWRnZS5maXQpDQpgYGANCioqYy4gRml0IGEgbGFzc28gbW9kZWwgb24gdGhlIHRyYWluaW5nIHNldCwgd2l0aCAkXGxhbWJkYSQgY2hvc2VuIGJ5IGNyb3NzLXZhbGlkYXRpb24uIFJlcG9ydCB0aGUgQ1YgZXJyb3Igb2J0YWluZWQsIGFsb25nIHdpdGggdGhlIG51bWJlciBvZiBub24temVybyBjb2VmZmljaWVudCBlc3RpbWF0ZXMuKioNCg0KYGBge3J9DQp5X3RyYWluPWxvZyhjYXQuY2xlYW4kU3BlbmRSYXQpDQpYX3RyYWluPW1vZGVsX21hdHJpeChjYXQuY2xlYW4sbG9nKFNwZW5kUmF0KX5BZ2UrTGVuUmVzK0luY29tZStUb3RBc3NldCtTZWNBc3NldHMrU2hvcnRMaXErTG9uZ0xpcStXbHRoSWR4K1NwZW5kVm9sK1NwZW5WZWwrQ29sbEdpZnRzK0JyaWNNb3J0YXIrTWFydGhhSG9tZStTdW5BZHMrVGhlbWVDb2xsK0N1c3REZWMrUmV0YWlsS2lkcytUZWVuV3IrQ2FybG92ZXJzK0NvdW50cnlDb2xsKQ0KcGFyYW1ldGVycyA8LSBjKHNlcSgwLjEsIDIsIGJ5ID0wLjEpICwgIHNlcSgyLCA1LCAwLjUpICwgc2VxKDUsIDI1LCAxKSkNCmxhc3NvLmZpdDwtdHJhaW4oeT15X3RyYWluLHg9WF90cmFpbixtZXRob2Q9J2dsbW5ldCcsdHJDb250cm9sPXRyYWluX2NvbnRyb2wsdHVuZUdyaWQ9ZXhwYW5kLmdyaWQoYWxwaGE9MSxsYW1iZGEgPSBwYXJhbWV0ZXJzKSkNCnByaW50KGxhc3NvLmZpdCkNCmBgYA0KDQoqKmQuIEZpdCBhIFBDUiBtb2RlbCBvbiB0aGUgdHJhaW5pbmcgc2V0LCB3aXRoIE0gY2hvc2VuIGJ5IGNyb3NzLXZhbGlkYXRpb24uIFJlcG9ydCB0aGUgQ1YgZXJyb3Igb2J0YWluZWQsIGFsb25nIHdpdGggdGhlIHZhbHVlIG9mIE0gc2VsZWN0ZWQgYnkgY3Jvc3MtdmFsaWRhdGlvbi4qKg0KDQpgYGB7cn0NCnBjci5maXQ8LXRyYWluKGxvZyhTcGVuZFJhdCl+LiwgZGF0YT1jYXQuY2xlYW4sIHRyQ29udHJvbD10cmFpbl9jb250cm9sLHR1bmVMZW5ndGg9bmNvbChjYXQuY2xlYW4pLG1ldGhvZD0ncGNyJykNCnBsb3QocGNyLmZpdCkNCnBjci5maXQkYmVzdFR1bmUNCnByaW50KHBjci5maXQpDQpgYGANCg0KKiplLiBGaXQgYSBQTFMgbW9kZWwgb24gdGhlIHRyYWluaW5nIHNldCwgd2l0aCBNIGNob3NlbiBieSBjcm9zcy12YWxpZGF0aW9uLiBSZXBvcnQgdGhlIENWIGVycm9yIG9idGFpbmVkLCBhbG9uZyB3aXRoIHRoZSB2YWx1ZSBvZiBNIHNlbGVjdGVkIGJ5IGNyb3NzLXZhbGlkYXRpb24uKioNCg0KYGBge3J9DQpwbHMuZml0PC10cmFpbihsb2coU3BlbmRSYXQpfi4sIGRhdGE9Y2F0LmNsZWFuLCB0ckNvbnRyb2w9dHJhaW5fY29udHJvbCx0dW5lTGVuZ3RoPW5jb2woY2F0LmNsZWFuKSxtZXRob2Q9J3BscycpDQpwbG90KHBscy5maXQpDQpwbHMuZml0JGJlc3RUdW5lDQpwcmludChwbHMuZml0KQ0KYGBgDQoNCioqZi4gQ29tbWVudCBvbiB0aGUgcmVzdWx0cyBvYnRhaW5lZC4gSG93IGFjY3VyYXRlbHkgY2FuIHdlIHByZWRpY3QgdGhlIFNwZW5kaW5nIFJhdGlvPyBJcyB0aGVyZSBtdWNoIGRpZmZlcmVuY2UgYW1vbmcgdGhlIENWIGVycm9ycyByZXN1bHRpbmcgZnJvbSB0aGVzZSBmaXZlIGFwcHJvYWNoZXM/KioNCg0KfCBNb2RlbCAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IFJNU0UgICAgIHwNCnwtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tfC0tLS0tLS0tLS18DQp8IExhc3NvIFJlZ3Jlc3Npb24gICAgICAgICAgICAgICAgIHwgYHIgbWluKGxhc3NvLmZpdCRyZXN1bHRzJFJNU0UpYCB8DQp8IFJpZGdlIFJlZ3Jlc3Npb24gICAgICAgICAgICAgICAgIHwgYHIgbWluKHJpZGdlLmZpdCRyZXN1bHRzJFJNU0UpYCB8DQp8IFByaW5jaXBsZSBDb21wb25lbnRzIFJlZ3Jlc3Npb24gIHwgYHIgbWluKHBjci5maXQkcmVzdWx0cyRSTVNFKWAgfA0KfCBQYXJ0aWFsIExlYXN0IFNxdWFyZXMgUmVncmVzc2lvbiB8IGByIG1pbihwbHMuZml0JHJlc3VsdHMkUk1TRSlgIHwNCnwgTGluZWFyIFJlZ3Jlc3Npb24gICAgICAgICAgICAgICAgfCBgciBsbS5maXQkcmVzdWx0cyRSTVNFYCB8DQoNCg0KQmVzdCBtb2RlbCB3YXMgTGFzc28gd2l0aCAkXGxhbWJkYSQgPSAwLjEgd2l0aCBhIFJNU0Ugb2YgYHIgbWluKGxhc3NvLmZpdCRyZXN1bHRzJFJNU0UpYC4gVGhlIHdvcnN0IHBlcmZvcm1pbmcgbW9kZWwgd2FzIHRoZSBsaW5lYXIgcmVncmVzc2lvbiBtb2RlbCB3aXRoIGEgUk1TRSBvZiBgciBsbS5maXQkcmVzdWx0cyRSTVNFYC4gVGhlcmUncyBub3QgYSBzdWJzdGFudGlhbCBhbW91bnQgb2YgZGlmZmVyZW5jZSBvZiBDViBSTVNFIGFjcm9zcyB0aGUgZml2ZSBtb2RlbHMuIA0KDQojIyMgUGFydCAzOiBDbGFzc2lmaWNhdGlvbiAoNDAgUG9pbnRzKQ0KSW4gdGhpcyBwcm9ibGVtLCB5b3Ugd2lsbCBkZXZlbG9wIGEgbW9kZWwgdG8gcHJlZGljdCB3aGV0aGVyIGluY29tZSBleGNlZWRzICQ1MEsveXIgYmFzZWQgb24gY2Vuc3VzIGRhdGEuDQoNCioqYS4gVXNlIHRoZSBjb2RlIGluIEJsYWNrYm9hcmQgdG8gY3JlYXRlIHRoZSBhZHVsdCBkYXRhIHNldC4qKg0KDQpgYGB7cn0NCmFkdWx0PC1yZWFkX2NzdigiaHR0cHM6Ly9hcmNoaXZlLmljcy51Y2kuZWR1L21sL21hY2hpbmUtbGVhcm5pbmctZGF0YWJhc2VzL2FkdWx0L2FkdWx0LmRhdGEiLCBjb2xfbmFtZXM9RkFMU0UsIG5hPSc/JykNCm5hbWVzKGFkdWx0KTwtYygiYWdlIiwid29ya2NsYXNzIiwiZm5sd2d0IiwiZWR1Y2F0aW9uIiwiZWR1Y2F0aW9uX251bSIsIm1hcml0YWxfc3RhdHVzIiwib2NjdXBhdGlvbiIsInJlbGF0aW9uc2hpcCIsInJhY2UiLCJzZXgiLCJjYXBpdGFsX2dhaW4iLCJjYXBpdGFsX2xvc3MiLCJob3Vyc19wZXJfd2VlayIsIm5hdGl2ZV9jb3VudHJ5IiwiaW5jb21lIikNCmFkdWx0JGZubHdndDwtTlVMTCAjcmVtb3ZlIHVubmVjZXNzYXJ5IGNvbHVtbg0KI2NvZXJjZSBjaGFyYWN0ZXIgdmFyaWFibGVzIHRvIGZhY3RvcnMNCmFkdWx0JHdvcmtjbGFzczwtYXNfZmFjdG9yKGFkdWx0JHdvcmtjbGFzcykNCmFkdWx0JGVkdWNhdGlvbjwtYXNfZmFjdG9yKGFkdWx0JGVkdWNhdGlvbikNCmFkdWx0JG1hcml0YWxfc3RhdHVzPC1hc19mYWN0b3IoYWR1bHQkbWFyaXRhbF9zdGF0dXMpDQphZHVsdCRvY2N1cGF0aW9uPC1hc19mYWN0b3IoYWR1bHQkb2NjdXBhdGlvbikNCmFkdWx0JHJlbGF0aW9uc2hpcDwtYXNfZmFjdG9yKGFkdWx0JHJlbGF0aW9uc2hpcCkNCmFkdWx0JHJhY2U8LWFzX2ZhY3RvcihhZHVsdCRyYWNlKQ0KYWR1bHQkc2V4PC1hc19mYWN0b3IoYWR1bHQkc2V4KQ0KYWR1bHQkbmF0aXZlX2NvdW50cnk8LWFzX2ZhY3RvcihhZHVsdCRuYXRpdmVfY291bnRyeSkNCmFkdWx0JGluY29tZTwtYXNfZmFjdG9yKGFkdWx0JGluY29tZSkNCmFkdWx0PC1uYS5vbWl0KGFkdWx0KSAjcmVtb3ZlIG1pc3Npbmcgb2JzZXJ2YXRpb25zDQp5PWFkdWx0JGluY29tZQ0KWD1tb2RlbF9tYXRyaXgoYWR1bHQsaW5jb21lfi4pICNjcmVhdGUgZHVtbXkgdmFyaWFibGVzDQpYJGAoSW50ZXJjZXB0KWA8LU5VTEwgI3JlbW92ZSB1bm5lY2Vzc2FyeSBjb2x1bW4NCmFkdWx0MjwtYXNfdGliYmxlKGNiaW5kKGFkdWx0JGluY29tZSxYKSwubmFtZV9yZXBhaXIgPSAidW5pcXVlIikgI2NyZWF0ZSBuZXcgZGF0YSBzZXQNCm5hbWVzKGFkdWx0MilbMV08LSJpbmNvbWUiICNmaXggdGhlIG5hbWUgb2YgdGhlIG91dGNvbWUgdmFyaWFibGUNCm5zdjwtbmVhclplcm9WYXIoYWR1bHQyLHNhdmVNZXRyaWNzID0gRkFMU0UpICNpZGVudGlmeSBuZWFyIHplcm8gdmFyaWFuY2UgcHJlZGljdG9ycw0KYWR1bHQzPC1hZHVsdDJbLC1uc3ZdICNyZW1vdmUgdGhlbQ0KYWR1bHQzDQpgYGANCg0KKipiLiBFeHBsb3JlIHRoZSBkYXRhIGdyYXBoaWNhbGx5IGluIG9yZGVyIHRvIGludmVzdGlnYXRlIHRoZSBhc3NvY2lhdGlvbiBiZXR3ZWVuIGluY29tZSBhbmQgdGhlIG90aGVyIGZlYXR1cmVzLiBXaGljaCBvZiB0aGUgb3RoZXIgZmVhdHVyZXMgc2VlbSBtb3N0IGxpa2VseSB0byBiZSB1c2VmdWwgaW4gcHJlZGljdGluZyBpbmNvbWU/IFNjYXR0ZXJwbG90cyBhbmQgYm94cGxvdHMgbWF5IGJlIHVzZWZ1bCB0b29scyB0byBhbnN3ZXIgdGhpcyBxdWVzdGlvbi4gRGVzY3JpYmUgeW91ciBmaW5kaW5ncy4qKg0KDQpVc2luZyBbcmFuZG9tIGZvcmVzdCBtZXRob2RdKGh0dHA6Ly9yLXN0YXRpc3RpY3MuY28vVmFyaWFibGUtU2VsZWN0aW9uLWFuZC1JbXBvcnRhbmNlLVdpdGgtUi5odG1sKSBmb3IgZmVhdHVyZSBzZWxlY3Rpb24uDQoNCmBgYHtyLCBjYWNoZT1UUlVFfQ0KIyNHZW5lcmF0ZSBhIHNtYWxsIHNhbXBsZSBvZiB0aGUgZGF0YSBzZXQgdG8gaW52ZXN0aWdhdGUgd2hpY2ggdmFyaWFibGVzIGFyZSBjbG9zZWx5IGFzc29jaWF0ZWQgd2l0aCBpbmNvbWUNCms9c2FtcGxlKG5yb3coYWR1bHQzKSxucm93KGFkdWx0MikqMC4wOCkNCg0KIyNVc2UgcmFuZG9tIGZvcmVzdCBtb2RlbCB0byBjYWxjdWxhdGUgdmFyaWFibGUgaW1wb3J0YW5jZQ0KcmY9dHJhaW4oaW5jb21lfi4sZGF0YT1hZHVsdDNbayxdKQ0KcmZJbXA8LXZhckltcChyZikNCnBsb3QocmZJbXAsdG9wPTEwKQ0KYGBgDQoNCioqYy4gU3BsaXQgdGhlIGRhdGEgaW50byBhbiA4MCUgdHJhaW5pbmcgc2V0IGFuZCBhIDIwJSB0ZXN0IHNldC4gU2V0IHRoZSBzZWVkIGF0IDEzMDMuKioNCg0KYGBge3J9DQojI0NyZWF0ZSB0cmFpbmluZyBpbmRpY2F0b3IgdmVjdG9yDQppblRyYWluIDwtIGNyZWF0ZURhdGFQYXJ0aXRpb24oYWR1bHQzJGluY29tZSwgcD0wLjgsIGxpc3Q9RkFMU0UpDQojI1RhYnVsYXRlIHRyYWluaW5nIGFuZCB0ZXN0IGRhdGEgc2V0cw0KdHJhaW49YWR1bHQzW2luVHJhaW4sXQ0KdGVzdD1hZHVsdDNbLWluVHJhaW4sXQ0KZGltKGFkdWx0MikNCmRpbSh0cmFpbikNCmRpbSh0ZXN0KQ0KYGBgDQoNCioqZC4gUGVyZm9ybSBMREEgb24gdGhlIHRyYWluaW5nIGRhdGEgaW4gb3JkZXIgdG8gcHJlZGljdCBpbmNvbWUgdXNpbmcgdGhlIHZhcmlhYmxlcyB0aGF0IHNlZW1lZCBtb3N0IGFzc29jaWF0ZWQgd2l0aCBpbmNvbWUgaW4gKGIpLiBXaGF0IGlzIHRoZSB0ZXN0IGVycm9yIG9mIHRoZSBtb2RlbCBvYnRhaW5lZD8qKg0KDQpgYGB7cn0NCiMjVHJhaW4gTW9kZWwNCmxkYS5maXQ9dHJhaW4oaW5jb21lfmBtYXJpdGFsX3N0YXR1c01hcnJpZWQtY2l2LXNwb3VzZWAgKyBlZHVjYXRpb25fbnVtICsgcmVsYXRpb25zaGlwSHVzYmFuZCAgKyBhZ2UgKyBob3Vyc19wZXJfd2VlayAgKyBgb2NjdXBhdGlvbkV4ZWMtbWFuYWdlcmlhbGAgICsgYG9jY3VwYXRpb25Qcm9mLXNwZWNpYWx0eWAgKyBzZXhGZW1hbGUgKyBgcmVsYXRpb25zaGlwT3duLWNoaWxkYCxkYXRhPXRyYWluLG1ldGhvZD0nbGRhJyx0ckNvbnRyb2wgPSB0cmFpbkNvbnRyb2wobWV0aG9kID0gImN2IikpDQpsZGEuZml0DQojI0NhbGN1bGF0ZSBQcmVkaWN0aW9ucw0KcHJlZC5sZGE8LXByZWRpY3QobGRhLmZpdCx0ZXN0KQ0KIyNFc3RpbWF0ZSBBY2N1cmFjeQ0KY29uZnVzaW9uTWF0cml4KHByZWQubGRhLHRlc3QkaW5jb21lKQ0KYGBgDQoNCioqZS4gUGVyZm9ybSBRREEgb24gdGhlIHRyYWluaW5nIGRhdGEgaW4gb3JkZXIgdG8gcHJlZGljdCBpbmNvbWUgdXNpbmcgdGhlIHZhcmlhYmxlcyB0aGF0IHNlZW1lZCBtb3N0IGFzc29jaWF0ZWQgd2l0aCBpbmNvbWUgaW4gKGIpLiBXaGF0IGlzIHRoZSB0ZXN0IGVycm9yIG9mIHRoZSBtb2RlbCBvYnRhaW5lZD8qKg0KYGBge3J9DQojI1RyYWluIE1vZGVsDQpxZGEuZml0PXRyYWluKGluY29tZX5gbWFyaXRhbF9zdGF0dXNNYXJyaWVkLWNpdi1zcG91c2VgICsgZWR1Y2F0aW9uX251bSArIHJlbGF0aW9uc2hpcEh1c2JhbmQgICsgYWdlICsgaG91cnNfcGVyX3dlZWsgICsgYG9jY3VwYXRpb25FeGVjLW1hbmFnZXJpYWxgICArIGBvY2N1cGF0aW9uUHJvZi1zcGVjaWFsdHlgICsgc2V4RmVtYWxlICsgYHJlbGF0aW9uc2hpcE93bi1jaGlsZGAsZGF0YT10cmFpbixtZXRob2Q9J3FkYScsdHJDb250cm9sID0gdHJhaW5Db250cm9sKG1ldGhvZCA9ICJjdiIpKQ0KcWRhLmZpdA0KIyNDYWxjdWxhdGUgUHJlZGljdGlvbnMNCnByZWQucWRhPC1wcmVkaWN0KHFkYS5maXQsdGVzdCkNCiMjRXN0aW1hdGUgQWNjdXJhY3kNCmNvbmZ1c2lvbk1hdHJpeChwcmVkLnFkYSx0ZXN0JGluY29tZSkNCmBgYA0KKipmLiBQZXJmb3JtIGxvZ2lzdGljIHJlZ3Jlc3Npb24gb24gdGhlIHRyYWluaW5nIGRhdGEgaW4gb3JkZXIgdG8gcHJlZGljdCBpbmNvbWUgdXNpbmcgdGhlIHZhcmlhYmxlcyB0aGF0IHNlZW1lZCBtb3N0IGFzc29jaWF0ZWQgd2l0aCBpbmNvbWUgaW4gKGIpLiBXaGF0IGlzIHRoZSB0ZXN0IGVycm9yIG9mIHRoZSBtb2RlbCBvYnRhaW5lZD8qKg0KDQpgYGB7cn0NCiMjVHJhaW4gTW9kZWwNCmdsbS5maXQ9dHJhaW4oaW5jb21lfmBtYXJpdGFsX3N0YXR1c01hcnJpZWQtY2l2LXNwb3VzZWAgKyBlZHVjYXRpb25fbnVtICsgcmVsYXRpb25zaGlwSHVzYmFuZCAgKyBhZ2UgKyBob3Vyc19wZXJfd2VlayAgKyBgb2NjdXBhdGlvbkV4ZWMtbWFuYWdlcmlhbGAgICsgYG9jY3VwYXRpb25Qcm9mLXNwZWNpYWx0eWAgKyBzZXhGZW1hbGUgKyBgcmVsYXRpb25zaGlwT3duLWNoaWxkYCxkYXRhPXRyYWluLG1ldGhvZD0nZ2xtJyx0ckNvbnRyb2wgPSB0cmFpbkNvbnRyb2wobWV0aG9kID0gImN2IikpDQpnbG0uZml0DQojI0NhbGN1bGF0ZSBQcmVkaWN0aW9ucw0KcHJlZC5nbG08LXByZWRpY3QoZ2xtLmZpdCx0ZXN0KQ0KIyNFc3RpbWF0ZSBBY2N1cmFjeQ0KY29uZnVzaW9uTWF0cml4KHByZWQuZ2xtLHRlc3QkaW5jb21lKQ0KYGBgDQoNCioqZy4gUGVyZm9ybSBLTk4gb24gdGhlIHRyYWluaW5nIGRhdGEsIHdpdGggc2V2ZXJhbCB2YWx1ZXMgb2YgSywgaW4gb3JkZXIgdG8gcHJlZGljdCBpbmNvbWUuIFVzZSBvbmx5IHRoZSB2YXJpYWJsZXMgdGhhdCBzZWVtZWQgbW9zdCBhc3NvY2lhdGVkIHdpdGggaW5jb21lIGluIChiKS4gV2hhdCB0ZXN0IGVycm9ycyBkbyB5b3Ugb2J0YWluPyBXaGljaCB2YWx1ZSBvZiBLIHNlZW1zIHRvIHBlcmZvcm0gdGhlIGJlc3Qgb24gdGhpcyBkYXRhIHNldD8qKg0KDQpgYGB7cixjYWNoZT1UUlVFfQ0KIyNUcmFpbiBNb2RlbCwgTGV0IENWIGNob29zZSB2YWx1ZSBmb3IgSw0Ka25uLmZpdDwtdHJhaW4oaW5jb21lfmBtYXJpdGFsX3N0YXR1c01hcnJpZWQtY2l2LXNwb3VzZWAgKyBlZHVjYXRpb25fbnVtICsgcmVsYXRpb25zaGlwSHVzYmFuZCAgKyBhZ2UgKyBob3Vyc19wZXJfd2VlayAgKyBgb2NjdXBhdGlvbkV4ZWMtbWFuYWdlcmlhbGAgICsgYG9jY3VwYXRpb25Qcm9mLXNwZWNpYWx0eWAgKyBzZXhGZW1hbGUgKyBgcmVsYXRpb25zaGlwT3duLWNoaWxkYCxkYXRhPXRyYWluLG1ldGhvZD0na25uJyx0ckNvbnRyb2wgPSB0cmFpbkNvbnRyb2wobWV0aG9kID0gImN2IiksIHR1bmVMZW5ndGg9MjApDQprbm4uZml0DQojI0NhbGN1bGF0ZSBQcmVkaWN0aW9ucw0KcHJlZC5rbm48LXByZWRpY3Qoa25uLmZpdCx0ZXN0KQ0KIyNFc3RpbWF0ZSBBY2N1cmFjeQ0KY29uZnVzaW9uTWF0cml4KHByZWQua25uLHRlc3QkaW5jb21lKQ0KYGBgDQoqKmguIENob29zZSB3aGljaCBtb2RlbCBwcmVkaWN0cyBpbmNvbWUgdGhlIGJlc3QgYW5kIGp1c3RpZnkgeW91ciBjaG9pY2UuKioNCg0KfCBNb2RlbCAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IEFjY3VyYWN5IHwNCnwtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tfC0tLS0tLS0tLS18DQp8IFF1YWRyYXRpYyBEaXNjcmltaW5hbnQgICAgICAgICAgICAgICAgIHwgYHIgcWRhLmZpdCRyZXN1bHRzWzJdW1sxXV1gIHwNCnwgSyBOZWFyZXN0IE5laWdoYm9ycyAoSz0zNykgIHwgYHIgbWF4KGtubi5maXQkcmVzdWx0c1syXVtbMV1dKWB8DQp8IExpbmVhciBEaXNjcmltaW5hbnQgICAgICAgICAgICAgICAgIHwgYHIgbGRhLmZpdCRyZXN1bHRzWzJdW1sxXV1gIHwNCnwgXyoqTG9naXN0aWMgUmVncmVzc2lvbioqXyB8IF8qKmByIGdsbS5maXQkcmVzdWx0c1syXVtbMV1dYCoqXyB8DQoNCg==