library('neuralnet')
concrete <- read.csv("https://s3.us-east-2.amazonaws.com/artificium.us/datasets/concrete.csv")
head(concrete)
summary(concrete)
     cement           slag            ash             water        superplastic      coarseagg         fineagg           age        
 Min.   :102.0   Min.   :  0.0   Min.   :  0.00   Min.   :121.8   Min.   : 0.000   Min.   : 801.0   Min.   :594.0   Min.   :  1.00  
 1st Qu.:192.4   1st Qu.:  0.0   1st Qu.:  0.00   1st Qu.:164.9   1st Qu.: 0.000   1st Qu.: 932.0   1st Qu.:731.0   1st Qu.:  7.00  
 Median :272.9   Median : 22.0   Median :  0.00   Median :185.0   Median : 6.400   Median : 968.0   Median :779.5   Median : 28.00  
 Mean   :281.2   Mean   : 73.9   Mean   : 54.19   Mean   :181.6   Mean   : 6.205   Mean   : 972.9   Mean   :773.6   Mean   : 45.66  
 3rd Qu.:350.0   3rd Qu.:142.9   3rd Qu.:118.30   3rd Qu.:192.0   3rd Qu.:10.200   3rd Qu.:1029.4   3rd Qu.:824.0   3rd Qu.: 56.00  
 Max.   :540.0   Max.   :359.4   Max.   :200.10   Max.   :247.0   Max.   :32.200   Max.   :1145.0   Max.   :992.6   Max.   :365.00  
    strength    
 Min.   : 2.33  
 1st Qu.:23.71  
 Median :34.45  
 Mean   :35.82  
 3rd Qu.:46.13  
 Max.   :82.60  
str(concrete)
'data.frame':   1030 obs. of  9 variables:
 $ cement      : num  540 540 332 332 199 ...
 $ slag        : num  0 0 142 142 132 ...
 $ ash         : num  0 0 0 0 0 0 0 0 0 0 ...
 $ water       : num  162 162 228 228 192 228 228 228 228 228 ...
 $ superplastic: num  2.5 2.5 0 0 0 0 0 0 0 0 ...
 $ coarseagg   : num  1040 1055 932 932 978 ...
 $ fineagg     : num  676 676 594 594 826 ...
 $ age         : int  28 28 270 365 360 90 365 28 28 28 ...
 $ strength    : num  80 61.9 40.3 41 44.3 ...
table(is.na(concrete))

FALSE 
 9270 

normalize <- function(x) {
  a <- x - min(x)
  b <- max(x) - min(x)
  return(a / b)
}

The goal of the code chunk below is to rescale the data as some of the variables have very wide scales like a min of 0 and a maximum of 200. we are using teh function above to normalize the data, that means bring it to a range of 0 - 1

concrete_norm <- as.data.frame(lapply(concrete, normalize))

compare two variables

summary(concrete$age)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
   1.00    7.00   28.00   45.66   56.00  365.00 
summary(concrete_norm$age)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
0.00000 0.01648 0.07418 0.12270 0.15110 1.00000 

split into train and test

concrete_train <- concrete_norm[1:773,]
concrete_test <- concrete_norm[774:1030, ]

install neuralnet package build the model

m <- neuralnet(strength ~ cement + slag + ash + water + superplastic + coarseagg + fineagg + age,
               data = concrete_train)

evaluate the model performance

model_resuts <- compute(m, concrete_test[1:8])

The compute function returns 1.neurons and 2.result

summary(model_resuts)
           Length Class  Mode   
neurons      2    -none- list   
net.result 257    -none- numeric

Becasue this is a numerical predition problem and not a classification problem, we cannot use a ocnfusion matrix to examine model accuracy

cor(predicted_strength, concrete_test$strength)
          [,1]
[1,] 0.7204596

correlations close to 1 indicate strong liner relationships between variables

Improve the model performance

m2 <- neuralnet(strength ~ cement + slag + ash + water + superplastic + coarseagg + fineagg + age,
                hidden = 5,
               data = concrete_train)

Compare the two models: Model 1:Error 5.6671 hidden layer : 1 steps: 2349

Model2:Error 1.5542 hidden layer: 5 steps: 56406

Hyperparameters like ‘hidde’ are design choices, not facts. You try , evaluate and justify with evidence

model_resuts_2 <- compute(m2, concrete_test[1:8])
summary(model_resuts_2)
           Length Class  Mode   
neurons      2    -none- list   
net.result 257    -none- numeric
predicted_strength_2 <- model_resuts_2$net.result
cor(predicted_strength_2, concrete_test$strength)
          [,1]
[1,] 0.8237139

The choice of activation function is importnat in deep learining rectifier activation function ReLU-> rectified linear unit A node in a neural network that uses the rectifier activation function

As depicted in the following figure, the rectifier activation function is defined such that it returns x if x is at least zero, and zero otherwise. The significance of this function is due to the fact that it is nonlinear yet has simple mathematical properties that make it both computationally inexpensive and highly efficient for gradient descent. Unfortunately, its derivative is undefined at x = 0 and therefore cannot be used with the neuralnet() function.

Instead, we can use a smooth approximation of the ReLU known as softplus or SmoothReLU, an activation function defined as log(1 + ex). As shown in the following figure, the softplus function is nearly zero for x less than zero and approximately x when x is greater than zero:

#softplus <- function(x) {
  #log(1 + exp(x))
#}

Add the softplus activation function to neural bet through act.fct # lets add a second hidden layer of 5 nodes

softplus <- function(x) {
  log(1 + exp(x))
}

set.seed(12345)

m3 <- neuralnet(strength ~ cement + slag + ash + water + superplastic + coarseagg + fineagg + age,
                hidden = c(5,5),
                data = concrete_train,
                act.fct = softplus,
                stepmax = 1e6
)
plot(m3)

Compare the three models: Model 1:Error 5.6671 activation function: default hidden layer : 1 steps: 2349

Model2:Error 1.5542 hidden layer: 5 activation function: default steps: 56406

Model2:Error 1.2606 hidden layer: 5 + 5 activation function: softplus steps: 467665

model_resuts_3 <- compute(m3, concrete_test[1:8])
summary(model_resuts_3)
           Length Class  Mode   
neurons      3    -none- list   
net.result 257    -none- numeric
predicted_strength_3 <- model_resuts_3$net.result
cor(predicted_strength_3, concrete_test$strength)
         [,1]
[1,] 0.773088

M3 has a lower training error but a worse case correlation. This is a case of overfitting.

**** when trauining keeps improving but testing gets worse, ypou have crossed the overfitting line. ********

LS0tCnRpdGxlOiAiTW9kZWxpbmcgdGhlIHN0cmVuZ3RoIG9mIGNvbmNyZXRlIHdpdGggQU5OJ3MiCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KCmBgYHtyfQpsaWJyYXJ5KCduZXVyYWxuZXQnKQpgYGAKCgpgYGB7cn0KY29uY3JldGUgPC0gcmVhZC5jc3YoImh0dHBzOi8vczMudXMtZWFzdC0yLmFtYXpvbmF3cy5jb20vYXJ0aWZpY2l1bS51cy9kYXRhc2V0cy9jb25jcmV0ZS5jc3YiKQpoZWFkKGNvbmNyZXRlKQpgYGAKCmBgYHtyfQpzdW1tYXJ5KGNvbmNyZXRlKQpgYGAKCmBgYHtyfQpzdHIoY29uY3JldGUpCmBgYAoKYGBge3J9CnRhYmxlKGlzLm5hKGNvbmNyZXRlKSkKYGBgCmBgYHtyfQoKbm9ybWFsaXplIDwtIGZ1bmN0aW9uKHgpIHsKICBhIDwtIHggLSBtaW4oeCkKICBiIDwtIG1heCh4KSAtIG1pbih4KQogIHJldHVybihhIC8gYikKfQpgYGAKCgpUaGUgZ29hbCBvZiB0aGUgY29kZSBjaHVuayBiZWxvdyBpcyB0byByZXNjYWxlIHRoZSBkYXRhIGFzIHNvbWUgb2YgdGhlIHZhcmlhYmxlcyBoYXZlIHZlcnkgd2lkZSBzY2FsZXMgbGlrZSBhIG1pbiBvZiAwIGFuZCBhIG1heGltdW0gb2YgMjAwLiB3ZSBhcmUgdXNpbmcgdGVoIGZ1bmN0aW9uIGFib3ZlIHRvIG5vcm1hbGl6ZSB0aGUgZGF0YSwgdGhhdCBtZWFucyBicmluZyBpdCB0byBhIHJhbmdlIG9mIDAgLSAxCmBgYHtyfQpjb25jcmV0ZV9ub3JtIDwtIGFzLmRhdGEuZnJhbWUobGFwcGx5KGNvbmNyZXRlLCBub3JtYWxpemUpKQpgYGAKCmNvbXBhcmUgdHdvIHZhcmlhYmxlcwpgYGB7cn0Kc3VtbWFyeShjb25jcmV0ZSRhZ2UpCmBgYAoKYGBge3J9CnN1bW1hcnkoY29uY3JldGVfbm9ybSRhZ2UpCmBgYAoKIHNwbGl0IGludG8gdHJhaW4gYW5kIHRlc3QKYGBge3J9CmNvbmNyZXRlX3RyYWluIDwtIGNvbmNyZXRlX25vcm1bMTo3NzMsXQpjb25jcmV0ZV90ZXN0IDwtIGNvbmNyZXRlX25vcm1bNzc0OjEwMzAsIF0KYGBgCgppbnN0YWxsIG5ldXJhbG5ldCBwYWNrYWdlCmJ1aWxkIHRoZSBtb2RlbApgYGB7cn0KbSA8LSBuZXVyYWxuZXQoc3RyZW5ndGggfiBjZW1lbnQgKyBzbGFnICsgYXNoICsgd2F0ZXIgKyBzdXBlcnBsYXN0aWMgKyBjb2Fyc2VhZ2cgKyBmaW5lYWdnICsgYWdlLAogICAgICAgICAgICAgICBkYXRhID0gY29uY3JldGVfdHJhaW4pCgpgYGAKCmBgYHtyfQpwbG90KG0pCmBgYAoKCmV2YWx1YXRlIHRoZSBtb2RlbCBwZXJmb3JtYW5jZQoKYGBge3J9Cm1vZGVsX3Jlc3V0cyA8LSBjb21wdXRlKG0sIGNvbmNyZXRlX3Rlc3RbMTo4XSkKYGBgCgpUaGUgY29tcHV0ZSBmdW5jdGlvbiByZXR1cm5zIDEubmV1cm9ucyBhbmQgMi5yZXN1bHQKCgoKYGBge3J9CnN1bW1hcnkobW9kZWxfcmVzdXRzKQpgYGAKCmBgYHtyfQpwcmVkaWN0ZWRfc3RyZW5ndGggPC0gbW9kZWxfcmVzdXRzJG5ldC5yZXN1bHQKYGBgCgpCZWNhc3VlIHRoaXMgaXMgYSBudW1lcmljYWwgcHJlZGl0aW9uIHByb2JsZW0gYW5kIG5vdCBhIGNsYXNzaWZpY2F0aW9uIHByb2JsZW0sIHdlIGNhbm5vdCB1c2UgYSBvY25mdXNpb24gbWF0cml4IHRvIGV4YW1pbmUgbW9kZWwgYWNjdXJhY3kKYGBge3J9CmNvcihwcmVkaWN0ZWRfc3RyZW5ndGgsIGNvbmNyZXRlX3Rlc3Qkc3RyZW5ndGgpCmBgYApjb3JyZWxhdGlvbnMgY2xvc2UgdG8gMSBpbmRpY2F0ZSBzdHJvbmcgbGluZXIgcmVsYXRpb25zaGlwcyBiZXR3ZWVuIHZhcmlhYmxlcwoKCkltcHJvdmUgdGhlIG1vZGVsIHBlcmZvcm1hbmNlCmBgYHtyfQptMiA8LSBuZXVyYWxuZXQoc3RyZW5ndGggfiBjZW1lbnQgKyBzbGFnICsgYXNoICsgd2F0ZXIgKyBzdXBlcnBsYXN0aWMgKyBjb2Fyc2VhZ2cgKyBmaW5lYWdnICsgYWdlLAogICAgICAgICAgICAgICAgaGlkZGVuID0gNSwKICAgICAgICAgICAgICAgZGF0YSA9IGNvbmNyZXRlX3RyYWluKQpgYGAKCmBgYHtyfQpwbG90KG0yKQpgYGAKQ29tcGFyZSB0aGUgdHdvIG1vZGVsczoKTW9kZWwgMTpFcnJvciA1LjY2NzEKaGlkZGVuIGxheWVyIDogMQpzdGVwczogMjM0OQoKTW9kZWwyOkVycm9yIDEuNTU0MgpoaWRkZW4gbGF5ZXI6IDUKc3RlcHM6IDU2NDA2CgpIeXBlcnBhcmFtZXRlcnMgbGlrZSAnaGlkZGUnIGFyZSBkZXNpZ24gY2hvaWNlcywgbm90IGZhY3RzLiBZb3UgdHJ5ICwgZXZhbHVhdGUgYW5kIGp1c3RpZnkgd2l0aCBldmlkZW5jZQoKYGBge3J9Cm1vZGVsX3Jlc3V0c18yIDwtIGNvbXB1dGUobTIsIGNvbmNyZXRlX3Rlc3RbMTo4XSkKc3VtbWFyeShtb2RlbF9yZXN1dHNfMikKYGBgCgpgYGB7cn0KcHJlZGljdGVkX3N0cmVuZ3RoXzIgPC0gbW9kZWxfcmVzdXRzXzIkbmV0LnJlc3VsdApjb3IocHJlZGljdGVkX3N0cmVuZ3RoXzIsIGNvbmNyZXRlX3Rlc3Qkc3RyZW5ndGgpCmBgYAoKVGhlIGNob2ljZSBvZiBhY3RpdmF0aW9uIGZ1bmN0aW9uIGlzIGltcG9ydG5hdCBpbiBkZWVwIGxlYXJpbmluZwpyZWN0aWZpZXIgYWN0aXZhdGlvbiBmdW5jdGlvbgpSZUxVLT4gcmVjdGlmaWVkIGxpbmVhciB1bml0CkEgbm9kZSBpbiBhIG5ldXJhbCBuZXR3b3JrIHRoYXQgdXNlcyB0aGUgcmVjdGlmaWVyIGFjdGl2YXRpb24gZnVuY3Rpb24KCkFzIGRlcGljdGVkIGluIHRoZSBmb2xsb3dpbmcgZmlndXJlLCB0aGUgcmVjdGlmaWVyIGFjdGl2YXRpb24gZnVuY3Rpb24gaXMgZGVmaW5lZCBzdWNoIHRoYXQgaXQgcmV0dXJucyB4IGlmIHggaXMgYXQgbGVhc3QgemVybywgYW5kIHplcm8gb3RoZXJ3aXNlLiBUaGUgc2lnbmlmaWNhbmNlIG9mIHRoaXMgZnVuY3Rpb24gaXMgZHVlIHRvIHRoZSBmYWN0IHRoYXQgaXQgaXMgbm9ubGluZWFyIHlldCBoYXMgc2ltcGxlIG1hdGhlbWF0aWNhbCBwcm9wZXJ0aWVzIHRoYXQgbWFrZSBpdCBib3RoIGNvbXB1dGF0aW9uYWxseSBpbmV4cGVuc2l2ZSBhbmQgaGlnaGx5IGVmZmljaWVudCBmb3IgZ3JhZGllbnQgZGVzY2VudC4gVW5mb3J0dW5hdGVseSwgaXRzIGRlcml2YXRpdmUgaXMgdW5kZWZpbmVkIGF0IHggPSAwIGFuZCB0aGVyZWZvcmUgY2Fubm90IGJlIHVzZWQgd2l0aCB0aGUgbmV1cmFsbmV0KCkgZnVuY3Rpb24uCgoKSW5zdGVhZCwgd2UgY2FuIHVzZSBhIHNtb290aCBhcHByb3hpbWF0aW9uIG9mIHRoZSBSZUxVIGtub3duIGFzIHNvZnRwbHVzIG9yIFNtb290aFJlTFUsIGFuIGFjdGl2YXRpb24gZnVuY3Rpb24gZGVmaW5lZCBhcyBsb2coMSArIGV4KS4gQXMgc2hvd24gaW4gdGhlIGZvbGxvd2luZyBmaWd1cmUsIHRoZSBzb2Z0cGx1cyBmdW5jdGlvbiBpcyBuZWFybHkgemVybyBmb3IgeCBsZXNzIHRoYW4gemVybyBhbmQgYXBwcm94aW1hdGVseSB4IHdoZW4geCBpcyBncmVhdGVyIHRoYW4gemVybzoKCmBgYHtyfQojc29mdHBsdXMgPC0gZnVuY3Rpb24oeCkgewogICNsb2coMSArIGV4cCh4KSkKI30KYGBgCgpBZGQgdGhlIHNvZnRwbHVzIGFjdGl2YXRpb24gZnVuY3Rpb24gdG8gbmV1cmFsIGJldCB0aHJvdWdoIGFjdC5mY3QKIyBsZXRzIGFkZCBhIHNlY29uZCBoaWRkZW4gbGF5ZXIgb2YgNSBub2RlcwpgYGB7cn0Kc29mdHBsdXMgPC0gZnVuY3Rpb24oeCkgewogIGxvZygxICsgZXhwKHgpKQp9CgpzZXQuc2VlZCgxMjM0NSkKCm0zIDwtIG5ldXJhbG5ldChzdHJlbmd0aCB+IGNlbWVudCArIHNsYWcgKyBhc2ggKyB3YXRlciArIHN1cGVycGxhc3RpYyArIGNvYXJzZWFnZyArIGZpbmVhZ2cgKyBhZ2UsCiAgICAgICAgICAgICAgICBoaWRkZW4gPSBjKDUsNSksCiAgICAgICAgICAgICAgICBkYXRhID0gY29uY3JldGVfdHJhaW4sCiAgICAgICAgICAgICAgICBhY3QuZmN0ID0gc29mdHBsdXMsCiAgICAgICAgICAgICAgICBzdGVwbWF4ID0gMWU2CikKYGBgCgoKYGBge3J9CnBsb3QobTMpCmBgYAoKQ29tcGFyZSB0aGUgdGhyZWUgbW9kZWxzOgpNb2RlbCAxOkVycm9yIDUuNjY3MQphY3RpdmF0aW9uIGZ1bmN0aW9uOiBkZWZhdWx0CmhpZGRlbiBsYXllciA6IDEKc3RlcHM6IDIzNDkKCk1vZGVsMjpFcnJvciAxLjU1NDIKaGlkZGVuIGxheWVyOiA1CmFjdGl2YXRpb24gZnVuY3Rpb246IGRlZmF1bHQKc3RlcHM6IDU2NDA2CgoKTW9kZWwyOkVycm9yIDEuMjYwNgpoaWRkZW4gbGF5ZXI6IDUgKyA1CmFjdGl2YXRpb24gZnVuY3Rpb246IHNvZnRwbHVzCnN0ZXBzOiA0Njc2NjUKCgoKYGBge3J9Cm1vZGVsX3Jlc3V0c18zIDwtIGNvbXB1dGUobTMsIGNvbmNyZXRlX3Rlc3RbMTo4XSkKc3VtbWFyeShtb2RlbF9yZXN1dHNfMykKYGBgCgpgYGB7cn0KcHJlZGljdGVkX3N0cmVuZ3RoXzMgPC0gbW9kZWxfcmVzdXRzXzMkbmV0LnJlc3VsdApjb3IocHJlZGljdGVkX3N0cmVuZ3RoXzMsIGNvbmNyZXRlX3Rlc3Qkc3RyZW5ndGgpCmBgYAoKTTMgaGFzIGEgbG93ZXIgdHJhaW5pbmcgZXJyb3IgYnV0IGEgd29yc2UgY2FzZSBjb3JyZWxhdGlvbi4gVGhpcyBpcyBhIGNhc2Ugb2Ygb3ZlcmZpdHRpbmcuIAoKKioqKiB3aGVuIHRyYXVpbmluZyBrZWVwcyBpbXByb3ZpbmcgYnV0IHRlc3RpbmcgZ2V0cyB3b3JzZSwgeXBvdSBoYXZlIGNyb3NzZWQgdGhlIG92ZXJmaXR0aW5nIGxpbmUuICoqKioqKioqCg==