""" Contains core classes and methods for initializing the deep learning 3D CNN model with different variants of the loss function, inputs are provided from the modelconfig_train.py file"""
[docs]class DLModel:
""" Deep Learning Model Class
:param model_type: Type of model to be used for training 3D CNN with MSE loss, 3D CNN with hetreoskedastic aleatoric loss, 3D CNN with a mixture density network (GMM) output
:type model_type: str (required)
:param output_dimension: Number of output nodes for the network equal to number of KCCs for the assembly in case MSE is used as loss function
:type output_dimension: int (required)
:param optimizer: The optimizer to be used while model training, refer: https://keras.io/optimizers/ for more information
:type optimizer: keras.optimizer (required)
:param loss_function: The loss function to be optimized by training the model, refer: https://keras.io/losses/ for more information
:type loss_function: keras.losses (required)
:param regularizer_coeff: The L2 norm regularization coefficient value used in the penultimate fully connected layer of the model, refer: https://keras.io/regularizers/ for more information
:type regularizer_coeff: float (required)
:param output_type: The output type of the model which can be regression or classification, this is used to define the output layer of the model, defaults to regression (classification: softmax, regression: linear)
:type output_type: str
"""
def __init__(self,model_type,output_dimension,optimizer,loss_function,regularizer_coeff,output_type='regression'):
self.output_dimension=output_dimension
self.model_type=model_type
self.optimizer=optimizer
self.loss_function=loss_function
self.regularizer_coeff=regularizer_coeff
self.output_type=output_type
[docs] def cnn_model_3d(self,voxel_dim,deviation_channels):
"""Build the 3D Model using the specified loss function, the inputs are parsed from the assemblyconfig_<case_study_name>.py file
:param voxel_dim: The voxel dimension of the input, required to build input to the 3D CNN model
:type voxel_dim: int (required)
:param voxel_channels: The number of voxel channels in the input structure, required to build input to the 3D CNN model
:type voxel_channels: int (required)
"""
from tensorflow.keras.layers import Conv3D, MaxPool3D, Flatten, Dense, Dropout
from tensorflow.keras.models import Sequential
from tensorflow.keras import regularizers
if(self.output_type=="regression"):
final_layer_avt='linear'
if(self.output_type=="classification"):
final_layer_avt='softmax'
model = Sequential()
model.add(Conv3D(32, kernel_size=(5,5,5),strides=(2,2,2),activation='relu',input_shape=(voxel_dim,voxel_dim,voxel_dim,deviation_channels)))
model.add(Conv3D(32, kernel_size=(4,4,4),strides=(2,2,2),activation='relu'))
model.add(Conv3D(32, kernel_size=(3,3,3),strides=(1,1,1),activation='relu'))
model.add(MaxPool3D(pool_size=(2,2,2)))
model.add(Flatten())
model.add(Dense(64,kernel_regularizer=regularizers.l2(self.regularizer_coeff),activation='relu'))
#model.add(Dropout(0.2))
model.add(Dense(64,kernel_regularizer=regularizers.l2(self.regularizer_coeff),activation='relu'))
model.add(Dense(self.output_dimension, activation=final_layer_avt))
model.compile(loss=self.loss_function, optimizer=self.optimizer, metrics=['mae'])
print("3D CNN model successfully compiled")
return model
def resnet_3d_cnn(self,voxel_dim,deviation_channels,w_val=0):
import numpy as np
import tensorflow.keras.backend as K
from tensorflow.keras.models import Model
from tensorflow.keras import regularizers
from tensorflow.keras.layers import Conv3D, MaxPooling3D, Add, BatchNormalization, Input, LeakyReLU,Activation, Lambda, Concatenate, Flatten, Dense,UpSampling3D,GlobalAveragePooling3D
if(w_val==0):
w_val=np.zeros(self.output_dimension)
w_val[:]=1/self.output_dimension
def weighted_mse(val):
def loss(yTrue,yPred):
#val = np.array([0.1,0.1,0.1,0.1,0.1])
w_var = K.variable(value=val, dtype='float32',
name='weight_vec')
#weight_vec = K.ones_like(yTrue[0,:]) #a simple vector with ones shaped as (60,)
#idx = K.cumsum(ones) #similar to a 'range(1,61)'
return K.mean((w_var)*K.square(yTrue-yPred))
return loss
input_size=(voxel_dim,voxel_dim,voxel_dim,deviation_channels)
inputs = Input(input_size)
x = inputs
y = Conv3D(32, kernel_size=(4,4,4),strides=(2,2,2), name="conv_block_1")(x)
res1=y
y = LeakyReLU()(y)
y = Conv3D(32, kernel_size=(3,3,3),strides=(1,1,1), padding='same',name="conv_block_2")(y)
y = LeakyReLU()(y)
y = Conv3D(32, kernel_size=(3,3,3),strides=(1,1,1), padding='same',name="conv_block_3")(y)
y = Add()([res1, y])
y = LeakyReLU()(y)
y = Conv3D(32, kernel_size=(3,3,3),strides=(2,2,2), name="conv_block_4")(y)
res2=y
y = LeakyReLU()(y)
y = Conv3D(32, kernel_size=(3,3,3),strides=(1,1,1), padding='same',name="conv_block_5")(y)
y = LeakyReLU()(y)
y = Conv3D(32, kernel_size=(3,3,3),strides=(1,1,1), padding='same',name="conv_block_6")(y)
y = Add()([res2, y])
y = LeakyReLU()(y)
y = Conv3D(32, kernel_size=(3,3,3),strides=(2,2,2), name="conv_block_7")(y)
res3=y
y = LeakyReLU()(y)
y = Conv3D(32, kernel_size=(3,3,3),strides=(1,1,1),padding='same', name="conv_block_8")(y)
y = LeakyReLU()(y)
y = Conv3D(32, kernel_size=(3,3,3),strides=(1,1,1),padding='same', name="conv_block_9")(y)
y = Add()([res3, y])
y = LeakyReLU()(y)
y=Flatten()(y)
y=Dense(128,kernel_regularizer=regularizers.l2(self.regularizer_coeff),activation='relu')(y)
y=Dense(64,kernel_regularizer=regularizers.l2(self.regularizer_coeff),activation='relu')(y)
output=Dense(self.output_dimension)(y)
model=Model(inputs, outputs=output, name='Res_3D_CNN')
model.compile(loss=self.loss_function, optimizer=self.optimizer, metrics=['mae'])
#print(model.summary())
return model
[docs] def cnn_model_3d_tl(self,voxel_dim,deviation_channels):
"""Build the 3D Model with GlobalMAxPooling3D instead of flatten, this enables input for different voxel dimensions, to be used when the model needs to be leveraged for transfer learning with different size input
:param voxel_dim: The voxel dimension of the input, required to build input to the 3D CNN model
:type voxel_dim: int (required)
:param voxel_channels: The number of voxel channels in the input structure, required to build input to the 3D CNN model
:type voxel_channels: int (required)
"""
from tensorflow.keras.layers import Conv3D, MaxPool3D, Flatten, Dense, Dropout, Input
from tensorflow.keras.models import Model
from tensorflow.keras import regularizers
inputs = Input(shape=(None,None,None,3,))
cnn3d_1=Conv3D(32, kernel_size=(5,5,5),strides=(2,2,2),activation='relu')(inputs)
cnn3d_2=Conv3D(32, kernel_size=(4,4,4),strides=(2,2,2),activation='relu')(cnn3d_1)
cnn3d_3=Conv3D(32, kernel_size=(3,3,3),strides=(1,1,1),activation='relu')(cnn3d_2)
max_pool3d=MaxPool3D(pool_size=(2,2,2))(cnn3d_3)
pooled_layer=GlobalMaxPooling3D()(max_pool3d)
dense_1=Dense(128,kernel_regularizer=regularizers.l2(self.regularizer_coeff),activation='relu')(pooled_layer)
predictions=Dense(self.output_dimension, activation=final_layer_avt)(dense_1)
model = Model(inputs=inputs, outputs=predictions)
model.compile(loss=self.loss_function, optimizer=self.optimizer, metrics=['mae'])
return model
[docs] def cnn_model_3d_aleatoric(self,voxel_dim,deviation_channels):
"""Build the 3D Model with a heteroeskedastic aleatoric loss, this enables different standard deviation of each predicted value, to be used when the expected sensor noise is heteroskedastic
:param voxel_dim: The voxel dimension of the input, required to build input to the 3D CNN model
:type voxel_dim: int (required)
:param voxel_channels: The number of voxel channels in the input structure, required to build input to the 3D CNN model
:type voxel_channels: int (required)
"""
if(self.model_type=="regression"):
final_layer_avt='linear'
if(self.model_type=="classification"):
final_layer_avt='softmax'
def myloss(y_true, y_pred):
prediction = y_pred[:,0:self.output_dimension]
log_variance = y_pred[:,self.output_dimension:self.output_dimension+1]
loss = tf.reduce_mean(0.5 * tf.exp(-1 * log_variance) * tf.square(tf.abs(y_true - prediction))+ 0.5 * log_variance)
return loss
from tensorflow.keras.layers import Conv3D, MaxPool3D, Flatten, Dense
from tensorflow.keras.models import Sequential
model = Sequential()
model.add(Conv3D(32, kernel_size=(5,5,5),strides=(2,2,2),activation='relu',input_shape=(voxel_dim,voxel_dim,voxel_dim,deviation_channels)))
model.add(Conv3D(32, kernel_size=(4,4,4),strides=(2,2,2),activation='relu'))
model.add(Conv3D(32, kernel_size=(3,3,3),strides=(1,1,1),activation='relu'))
model.add(MaxPool3D(pool_size=(2,2,2)))
model.add(Flatten())
model.add(Dense(128,kernel_regularizer=regularizers.l2(0.02),activation='relu'))
#model.add(Dropout(0.3))
model.add(Dense(self.output_dimension, activation=final_layer_avt))
model.compile(loss=myloss, optimizer='adam', metrics=['mae'])
print("3D CNN model Aleatoric successfully compiled")
return model
[docs] def cnn_model_3d_mdn(self,voxel_dim,deviation_channels,num_of_mixtures=5):
"""Build the 3D Model with a Mixture Density Network output the gives parameters of a Gaussian Mixture Model as output, to be used if the system is expected to be collinear (Multi-Stage Assembly Systems) i.e. a single input can have multiple outputs
Functions for predicting and sampling from a MDN.py need to used when deploying a MDN based model
refer https://publications.aston.ac.uk/id/eprint/373/1/NCRG_94_004.pdf for more details on the working of a MDN model
refer https://arxiv.org/pdf/1709.02249.pdf to understand how a MDN model can be leveraged to estimate the epistemic and aleatoric unceratninty present in manufacturing sytems based on the data collected
:param voxel_dim: The voxel dimension of the input, reuired to build input to the 3D CNN model
:type voxel_dim: int (required)
:param voxel_channels: The number of voxel channels in the input structure, required to build input to the 3D CNN model
:type voxel_channels: int (required)
:param number_of_mixtures: The number of mixtures in the Gaussian Mixture Model output, defaults to 5, can be increased if higher collinearity is expected
:type number_of_mixtures: int
"""
assert self.model_type=="regression","Mixture Density Network Should be a Regression Model"
from tensorflow.keras.layers import Conv3D, MaxPool3D, Flatten, Dense
from tensorflow.keras.models import Sequential
import mdn
model = Sequential()
model.add(Conv3D(32, kernel_size=(5,5,5),strides=(2,2,2),activation='relu',input_shape=(voxel_dim,voxel_dim,voxel_dim,deviation_channels)))
model.add(Conv3D(32, kernel_size=(4,4,4),strides=(2,2,2),activation='relu'))
model.add(Conv3D(32, kernel_size=(3,3,3),strides=(1,1,1),activation='relu'))
model.add(MaxPool3D(pool_size=(2,2,2)))
model.add(Flatten())
model.add(Dense(128,kernel_regularizer=regularizers.l2(0.02),activation='relu'))
#model.add(Dropout(0.3))
model.add(Dense(self.output_dimension, activation=final_layer_avt))
model.add(mdn.MDN(self.output_dimension, num_of_mixtures))
model.compile(loss=mdn.get_mixture_loss_func(self.output_dimension,num_of_mixtures), optimizer='adam')
print("3D CNN Mixture Density Network model successfully compiled")
return model
if (__name__=="__main__"):
print('Model Deep Learning Class')