Chapter 11 Functional Approximations by Trees and Neural Networks
Here we show how the function \[ x \mapsto exp(4 x) \] can be easily approximated by a tree-based methods (Trees, Random Forest) and a neural network (2 Layered Neural Network)
set.seed(1)
<- matrix(runif(1000),1000,1)
X_train <- exp(4*X_train) #Noiseless case Y=g(X)
Y_train dim(X_train)
## [1] 1000 1
library(rpart)
# shallow tree
<- rpart(Y_train~X_train, cp=.01) #cp is penalty level
TreeModel<- predict(TreeModel, newx=X_train)
pred.TMplot(X_train, Y_train, type="p", pch=19, xlab="z", ylab="g(z)")
points(X_train, pred.TM, col=3, pch=19)
# importing relevant packages
import numpy as np
from SyncRNG import SyncRNG
from sklearn.tree import DecisionTreeRegressor
from sklearn.ensemble import RandomForestRegressor
from sklearn.ensemble import GradientBoostingRegressor
import matplotlib.pyplot as plt
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
from keras.models import Sequential
from keras.layers import Dense
= SyncRNG(seed = 123456)
s
= np.zeros( 1000 ).reshape( 1000 , 1 )
X_train print( X_train.shape )
## (1000, 1)
for i in range( 0 , X_train.shape[0] ):
0 ] = s.rand()
X_train[ i ,
= np.exp( 4 * X_train )
Y_train
= DecisionTreeRegressor( random_state = 0, ccp_alpha = 2.02 )
TreeModel TreeModel.fit( X_train , Y_train )
## DecisionTreeRegressor(ccp_alpha=2.02, random_state=0)
= TreeModel.predict( X_train )
pred_TM
= plt.figure( figsize = ( 5 , 5 ) , dpi = 100 )
fig = fig.add_subplot( 111 )
ax1 ='black', marker="o" , s = 20 ) ax1.scatter( X_train , Y_train, c
## <matplotlib.collections.PathCollection object at 0x000000002D9B6CA0>
='green', marker="o" , s = 20) ax1.scatter( X_train , pred_TM , c
## <matplotlib.collections.PathCollection object at 0x000000002A2E61C0>
"z" ) plt.xlabel(
## Text(0.5, 0, 'z')
"g(z)" ) plt.ylabel(
## Text(0, 0.5, 'g(z)')
plt.show()
11.1 Functional Approximation by a Tree
set.seed(1)
<- matrix(runif(1000),1000,1)
X_train <- exp(4*X_train) #Noiseless case Y=g(X)
Y_train dim(X_train)
## [1] 1000 1
library(rpart)
<- rpart(Y_train~X_train, cp = .0005) #cp is penalty level
TreeModel<- predict(TreeModel, newx = X_train)
pred.TMplot(X_train, Y_train, type="p", pch=19, xlab="z", ylab="g(z)")
points(X_train, pred.TM, col=3, pch=19)
= SyncRNG(seed = 123456)
s
= np.zeros( 1000 ).reshape( 1000 , 1 )
X_train for i in range( 0 , X_train.shape[0] ):
0 ] = s.rand()
X_train[ i ,
= np.exp( 4 * X_train )
Y_train
= DecisionTreeRegressor( random_state = 0, ccp_alpha = 2.02*0.0005/0.01 )
TreeModel TreeModel.fit( X_train , Y_train )
## DecisionTreeRegressor(ccp_alpha=0.101, random_state=0)
= TreeModel.predict( X_train )
pred_TM
= plt.figure( figsize = ( 5 , 5 ) , dpi = 100 )
fig = fig.add_subplot( 111 )
ax1 ='black', marker="o" , s = 20 ) ax1.scatter( X_train , Y_train, c
## <matplotlib.collections.PathCollection object at 0x0000000037EF0F10>
='green', marker="o" , s = 20) ax1.scatter( X_train , pred_TM , c
## <matplotlib.collections.PathCollection object at 0x0000000037EFD2B0>
"z" ) plt.xlabel(
## Text(0.5, 0, 'z')
"g(z)" ) plt.ylabel(
## Text(0, 0.5, 'g(z)')
plt.show()
11.2 Functional Approximation by RF
Here we show how the function \[ x \mapsto exp(4 x) \] can be easily approximated by a tree-based method (Random Forest) and a neural network (2 Layered Neural Network)
library(randomForest)
## randomForest 4.6-14
## Type rfNews() to see new features/changes/bug fixes.
<- randomForest(Y_train~X_train)
RFmodel<- predict(RFmodel, newdata=X_train)
pred.RFplot(X_train, Y_train, type="p", pch=19, xlab="z", ylab="g(z)")
points(X_train, pred.RF, col=4, pch=19,)
= SyncRNG(seed = 123456)
s
= np.zeros( 1000 ).reshape( 1000 , 1 )
X_train for i in range( 0 , X_train.shape[0] ):
0 ] = s.rand()
X_train[ i ,
= np.exp( 4 * X_train )
Y_train
## REstrictions to make RF from SKlearn
## similar to random forest from r package
if Y_train is not None and ( Y_train.dtype != str ):
= max( [ np.round( ( X_train.shape[ 1 ]/3 ) ).astype(int) , 1 ] )
mtry else:
= np.round( np.sqrt( X_train.shape[ 1 ] ) ).astype(int)
mtry
if Y_train is not None and ( Y_train.dtype != str ):
= 5
nodesize1 else:
= 1
nodesize1
= RandomForestRegressor( random_state = 0 , n_estimators = 500 ,\
RFModel = mtry , \
max_features = 4 , \
n_jobs = nodesize1 ).\
min_samples_leaf fit( X_train , Y_train )
## <string>:1: DataConversionWarning: A column-vector y was passed when a 1d array was expected. Please change the shape of y to (n_samples,), for example using ravel().
RFModel.fit( X_train , Y_train )
## RandomForestRegressor(max_features=1, min_samples_leaf=5, n_estimators=500,
## n_jobs=4, random_state=0)
##
## <string>:1: DataConversionWarning: A column-vector y was passed when a 1d array was expected. Please change the shape of y to (n_samples,), for example using ravel().
= RFModel.predict( X_train )
pred_RF
= plt.figure( figsize = ( 5 , 5 ) , dpi = 100 )
fig = fig.add_subplot( 111 )
ax1 ='black', marker="o" , s = 20 ) ax1.scatter( X_train , Y_train, c
## <matplotlib.collections.PathCollection object at 0x0000000038025D00>
='blue', marker="o" , s = 5) ax1.scatter( X_train , pred_RF , c
## <matplotlib.collections.PathCollection object at 0x00000000380320A0>
"z" ) plt.xlabel(
## Text(0.5, 0, 'z')
"g(z)" ) plt.ylabel(
## Text(0, 0.5, 'g(z)')
plt.show()
11.3 Boosted Trees
library(gbm)
## Loaded gbm 2.1.8
= as.data.frame(cbind(X_train, Y_train))
data_train <- gbm(Y_train~X_train, distribution= "gaussian", n.trees=100, shrinkage=.01, interaction.depth
BoostTreemodel=4)
#shrinkage is "learning rate"
# n.trees is the number of boosting steps
<- predict(BoostTreemodel, newdata=data_train, n.trees=100)
pred.BTplot(X_train, Y_train, type="p", pch=19, xlab="z", ylab="g(z)")
points(X_train, pred.BT, col=4, pch=19,)
= GradientBoostingRegressor(random_state=0 , max_depth = 4 , learning_rate = 0.01 , n_estimators = 100 )
BoostTreemodel BoostTreemodel.fit( X_train, Y_train )
## GradientBoostingRegressor(learning_rate=0.01, max_depth=4, random_state=0)
##
## C:\Users\MSI-NB\ANACON~1\envs\TENSOR~2\lib\site-packages\sklearn\utils\validation.py:63: DataConversionWarning: A column-vector y was passed when a 1d array was expected. Please change the shape of y to (n_samples, ), for example using ravel().
## return f(*args, **kwargs)
= BoostTreemodel.predict( X_train )
pred_BT
= plt.figure( figsize = ( 5 , 5 ) , dpi = 100 )
fig = fig.add_subplot( 111 )
ax1 ='black', marker="o" , s = 20 ) ax1.scatter( X_train , Y_train, c
## <matplotlib.collections.PathCollection object at 0x0000000038046C40>
='blue', marker="o" , s = 20) ax1.scatter( X_train , pred_BT , c
## <matplotlib.collections.PathCollection object at 0x000000003803F970>
"z" ) plt.xlabel(
## Text(0.5, 0, 'z')
"g(z)" ) plt.ylabel(
## Text(0, 0.5, 'g(z)')
plt.show()
library(gbm)
= as.data.frame(cbind(X_train, Y_train))
data_train <- gbm(Y_train~X_train, distribution= "gaussian", n.trees=1000, shrinkage=.01, interaction.depth
BoostTreemodel=4)
# shrinkage is "learning rate"
# n.trees is the number of boosting steps
<- predict(BoostTreemodel, newdata=data_train, n.trees=1000)
pred.BTplot(X_train, Y_train, type="p", pch=19, xlab="z", ylab="g(z)")
points(X_train, pred.BT, col=4, pch=19,)
= GradientBoostingRegressor(random_state=0 , max_depth = 4 , learning_rate = 0.01 , n_estimators = 1000 )
BoostTreemodel BoostTreemodel.fit( X_train, Y_train )
## GradientBoostingRegressor(learning_rate=0.01, max_depth=4, n_estimators=1000,
## random_state=0)
##
## C:\Users\MSI-NB\ANACON~1\envs\TENSOR~2\lib\site-packages\sklearn\utils\validation.py:63: DataConversionWarning: A column-vector y was passed when a 1d array was expected. Please change the shape of y to (n_samples, ), for example using ravel().
## return f(*args, **kwargs)
= BoostTreemodel.predict( X_train )
pred_BT
= plt.figure( figsize = ( 10 , 10 ) , dpi = 80 )
fig = fig.add_subplot( 111 )
ax1 ='black', marker="o" , s = 30 ) ax1.scatter( X_train , Y_train, c
## <matplotlib.collections.PathCollection object at 0x00000000385222E0>
='blue', marker="o" , s = 30) ax1.scatter( X_train , pred_BT , c
## <matplotlib.collections.PathCollection object at 0x0000000038522730>
"z" ) plt.xlabel(
## Text(0.5, 0, 'z')
"g(z)" ) plt.ylabel(
## Text(0, 0.5, 'g(z)')
plt.show()
11.4 Same Example with a Neural Network
library(keras)
## Warning: package 'keras' was built under R version 4.0.5
<- function() {
build_model <- keras_model_sequential() %>%
model layer_dense(units = 200, activation = "relu",
input_shape = 1)%>%
layer_dense(units = 20, activation = "relu") %>%
layer_dense(units = 1)
%>% compile(
model optimizer = optimizer_adam(lr = 0.01),
loss = "mse",
metrics = c("mae"),
)
}
<- build_model()
model summary(model)
## Model: "sequential"
## ________________________________________________________________________________
## Layer (type) Output Shape Param #
## ================================================================================
## dense_2 (Dense) (None, 200) 400
## ________________________________________________________________________________
## dense_1 (Dense) (None, 20) 4020
## ________________________________________________________________________________
## dense (Dense) (None, 1) 21
## ================================================================================
## Total params: 4,441
## Trainable params: 4,441
## Non-trainable params: 0
## ________________________________________________________________________________
# define the keras model
= Sequential()
model 200, input_dim = X_train.shape[1], activation = 'relu'))
model.add(Dense(20, activation = 'relu'))
model.add(Dense(1))
model.add(Dense(
# compile the keras model
= keras.optimizers.Adam(learning_rate=0.01)
opt = tf.keras.losses.MeanSquaredError()
mse = tf.keras.metrics.MeanAbsoluteError(name="mean_absolute_error", dtype=None)
mae
compile(loss=mse, optimizer= opt , metrics=mae)
model.=None, positions=None, print_fn=None) model.summary(line_length
## Model: "sequential_1"
## _________________________________________________________________
## Layer (type) Output Shape Param #
## =================================================================
## dense_3 (Dense) (None, 200) 400
## _________________________________________________________________
## dense_4 (Dense) (None, 20) 4020
## _________________________________________________________________
## dense_5 (Dense) (None, 1) 21
## =================================================================
## Total params: 4,441
## Trainable params: 4,441
## Non-trainable params: 0
## _________________________________________________________________
<- 1
num_epochs %>% fit(X_train, Y_train,
model epochs = num_epochs, batch_size = 10, verbose = 0)
<- model %>% predict(X_train)
pred.NN plot(X_train, Y_train, type="p", pch=19, xlab="z", ylab="g(z)")
points(X_train, pred.NN, col=4, pch=19,)
= 1
num_epochs = num_epochs , batch_size=10, verbose = 0 ) model.fit( X_train, Y_train, epochs
## <tensorflow.python.keras.callbacks.History object at 0x0000000038FD2F10>
= model.predict( X_train )
pred_NN
= plt.figure( figsize = ( 10 , 10 ) , dpi = 80 )
fig = fig.add_subplot( 111 )
ax1 ='black', marker="o" , s = 30 ) ax1.scatter( X_train , Y_train, c
## <matplotlib.collections.PathCollection object at 0x0000000039177FD0>
='blue', marker="o" , s = 30) ax1.scatter( X_train , pred_NN , c
## <matplotlib.collections.PathCollection object at 0x0000000037B923A0>
"z" ) plt.xlabel(
## Text(0.5, 0, 'z')
"g(z)" ) plt.ylabel(
## Text(0, 0.5, 'g(z)')
plt.show()
<- 100
num_epochs %>% fit(X_train, Y_train,
model epochs = num_epochs, batch_size = 10, verbose = 0)
<- model %>% predict(X_train)
pred.NN plot(X_train, Y_train, type="p", pch=19, xlab="z", ylab="g(z)")
points(X_train, pred.NN, col=4, pch=19,)
= 100
num_epochs = num_epochs , batch_size=10, verbose = 0 ) model.fit( X_train, Y_train, epochs
## <tensorflow.python.keras.callbacks.History object at 0x00000000476FA370>
= model.predict( X_train )
pred_NN
= plt.figure( figsize = ( 10 , 10 ) , dpi = 80 )
fig = fig.add_subplot( 111 )
ax1 ='black', marker="o" , s = 30 ) ax1.scatter( X_train , Y_train, c
## <matplotlib.collections.PathCollection object at 0x000000004773EA00>
='blue', marker="o" , s = 30) ax1.scatter( X_train , pred_NN , c
## <matplotlib.collections.PathCollection object at 0x000000004773EE50>
"z" ) plt.xlabel(
## Text(0.5, 0, 'z')
"g(z)" ) plt.ylabel(
## Text(0, 0.5, 'g(z)')
plt.show()