<jupyter_start><jupyter_text>Read data and Preprocess  Adaptive EQ Processing<jupyter_code># from os import walk
# from skimage import io

# f = []
# for (dirpath, dirnames, filenames) in walk(train_data_dir):
#     f.extend(filenames)
# f

# for each in f:
# #     print(train_data_direach)
#     img = io.imread(train_data_dir+'/'+each)
#     img_adapteq = exposure.equalize_adapthist(img, clip_limit=0.03)
#     io.imsave('../data/Processed/'+each, img_adapteq)<jupyter_output><empty_output><jupyter_text>Read Image Attributes<jupyter_code>#data
df = pd.read_csv('../data/SedMLdata.csv')
df.head()<jupyter_output><empty_output><jupyter_text>For functional api Multi-Output<jupyter_code># Define dirs and files
train_data_dir = '../data/Processed/'
# train_data_dir = '../data/CropPics/Pics/' #unprocessed original pictures
split = 0.2

#set batch Size
batch_size = 4

# c_ch = 1
# c_mode = 'grayscale'
c_ch = 3
c_mode = 'rgb'

#set Image size (RGB so imshape is 3)
pix_dim = 1024
imsize = (pix_dim, pix_dim) 
imshape = (pix_dim, pix_dim, c_ch)


df = pd.read_csv('../data/SedMLdata.csv')
columns=["D2mm", "D5mm", "D10mm", "D16mm",
"D25mm","D50mm", "D75mm", "D84mm", "D90mm",
"D95mm", "D98mm", "skew", "kurtosis"]



train_datagen = ImageDataGenerator(
                                   rescale = 1./255.,
                                   horizontal_flip = True,
                                   vertical_flip = True,
                                   fill_mode='nearest',
                                   validation_split = split,
                                  )

def multiple_outputs(generator, dataframe, image_dir, columns,class_mode, batch_size, color_mode, imsize, subset):
    gen = train_datagen.flow_from_dataframe(
        dataframe = dataframe,
        directory = image_dir,
        class_mode = 'raw',
        fill_mode='nearest',
        target_size=imsize,
        batch_size=batch_size,
        x_col = 'CropName',
        y_col = columns,
        color_mode = color_mode,
        use_multiprocessing=True,
        subset=subset)
    
    while True:
        gnext = gen.next()
        # return image batch and 3 sets of lables (Distribution, [Skew,Kurt])
        yield gnext[0], [gnext[1][:,:11], gnext[1][:,11].reshape(-1,1), gnext[1][:,12].reshape(-1,1)]

train_generator = multiple_outputs(generator=train_datagen,
                                   dataframe = df,
                                   image_dir = train_data_dir,
                                   batch_size = batch_size,
                                   class_mode = 'raw',
                                   imsize = imsize,
                                   columns=columns,
                                   color_mode = c_mode,
                                   subset = 'training')
validation_generator =  multiple_outputs(
                                   generator=train_datagen,
                                   dataframe=df,
                                   image_dir = train_data_dir,
                                   batch_size = batch_size,
                                   class_mode = 'raw',
                                   imsize = imsize,
                                   columns=columns,
                                   color_mode = c_mode,
                                   subset = 'validation')<jupyter_output><empty_output><jupyter_text>Check Shape<jupyter_code>for each in train_generator:
    print(each[1][0].shape)
    break
for each in validation_generator:
    print(each[1][0].shape)
    break
total_train = 240
total_val = 60<jupyter_output><empty_output><jupyter_text>Model Development  Set Weights and Biases Tracking<jupyter_code># define other metrics
mae_metric = tf.keras.metrics.MeanAbsoluteError(name='mae')
mape_metric = tf.keras.metrics.MeanAbsolutePercentageError(name='mape')

wandb.init(
  project="sandcam_2",
  # Set entity to specify your username or team name
  # ex: entity="wandb",
  config={
      "activation": "gelu",
      "dlayer_0": 512,
      "activation_0": "relu",
      "dlayer_1": 128,
      "activation_1": "relu",
      "dropout": 0.5,
      "dlayer_2": 64,
      "activation_2": "relu",
      "dlayer_dist": 11,
      "activation_dist": "relu",
      "dlayer_skew": 1,
      "activation_skew": "relu",
      "dlayer_kurt": 1,
      "activation_kurt": "relu",
      "optimizer": "Adam",
      "loss": 'mean_squared_error',
      "metric": "accuracy",
      "epoch": 50,
      "batch_size": 4,
      "loss_weights": [0.1, 0.1, 0.1, 0.2, 0.5, 1, 0.5, 0.2, 0.1, 0.1, 0.1 ]
      
  })
config = wandb.config<jupyter_output>wandb: wandb version 0.12.7 is available!  To upgrade, please run:
wandb:  $ pip install wandb --upgrade<jupyter_text>Base ModelFixed kernel size<jupyter_code># inp = layers.Input(shape=imshape)

# cnn1 = layers.Conv2D(filters=32, kernel_size=3, padding='same', activation='relu')(inp)
# # bn1 = layers.BatchNormalization()(cnn1)
# mp1 = layers.MaxPool2D()(cnn1)
# dr1 = layers.Dropout(config.dropout)(mp1)

# cnn2 = layers.Conv2D(64, 3, padding='same', activation='relu')(dr1)
# cnn3 = layers.Conv2D(64, 3, padding='same', activation='relu')(cnn2)
# # bn2 = layers.BatchNormalization()(cnn3)
# mp2 = layers.MaxPool2D()(cnn3)
# dr2 = layers.Dropout(config.dropout)(mp2)

# cnn4 = layers.Conv2D(128, 3, padding='same', activation='relu')(dr2)
# cnn5 = layers.Conv2D(128, 3, padding='same', activation='relu')(cnn4)
# # bn3 = layers.BatchNormalization()(cnn5)
# mp3 = layers.MaxPool2D()(cnn5)
# dr3 = layers.Dropout(config.dropout)(mp3)

# cnn6 = layers.Conv2D(128, 3, padding='same', activation='relu')(dr3)
# cnn7 = layers.Conv2D(128, 3, padding='same', activation='relu')(cnn6)
# # bn4 = layers.BatchNormalization()(cnn7)
# mp4 = layers.MaxPool2D()(cnn7)
# dr4 = layers.Dropout(config.dropout)(mp4)

# gp1 = layers.GlobalMaxPooling2D()(dr4)
    
# d1 = layers.Dense(config.dlayer_0, activation=config.activation_0)(gp1)
# dr5 = layers.Dropout(config.dropout)(d1)

# d2 = layers.Dense(config.dlayer_1, activation=config.activation_1)(dr5)
# dr6 = layers.Dropout(config.dropout)(d2)

# d3 = layers.Dense(config.dlayer_2, activation=config.activation_2)(dr6)
# dr7 = layers.Dropout(config.dropout)(d3)
    
# dr_skew = layers.Dense(config.dlayer_skew, activation=config.activation_skew, name='Skew')(dr7)

# dr_kurt = layers.Dense(config.dlayer_kurt, activation=config.activation_kurt, name='Kurt')(dr7)

# combo = layers.concatenate([dr7, dr_skew, dr_kurt])

# dr_dist = layers.Dense(11, activation=config.activation_dist, name='Dist')(combo)

# # dr_dist = layers.Dense(11, activation=config.activation_dist, name='Dist')(dr7)



# model = Model(inp, [dr_dist, dr_skew, dr_kurt])

# # model = Model(inp, [dr_dist])

# model._name = "SandCam_CNN"

# initial_learning_rate = 0.0001
# lr_schedule = tf.keras.optimizers.schedules.ExponentialDecay(
#     initial_learning_rate,
#     decay_steps=100000,
#     decay_rate=0.96,
#     staircase=True)

# # opt = tf.keras.optimizers.SGD(lr=1e-2, momentum=0.9, decay=1e-2/200)
# opt = tf.keras.optimizers.Adam()

# model.compile(loss={
#                 'Dist':'mean_squared_error',
#                 'Skew':'mean_squared_error',
#                 'Kurt':'mean_squared_error',
#                 }, 
#                   optimizer=opt,
#                   metrics = mape_metric
#          )<jupyter_output><empty_output><jupyter_text>Larger ModelLarger number of filters<jupyter_code># baseFilter= 32

# inp = layers.Input(shape=imshape)

# cnn0 = layers.SeparableConv2D(filters = baseFilter, kernel_size=3, padding='same', activation='relu')(inp)
# cnn1 = layers.SeparableConv2D(baseFilter*2, 3, padding='same', activation='relu')(cnn0)
# mp1 = layers.MaxPool2D()(cnn1)
# dr1 = layers.Dropout(config.dropout)(mp1)

# cnn2 = layers.SeparableConv2D(baseFilter*3, 3, padding='same', activation='relu')(dr1)
# mp2 = layers.MaxPool2D()(cnn2)
# dr2 = layers.Dropout(config.dropout)(mp2)

# cnn3 = layers.SeparableConv2D(baseFilter*3, 3, padding='same', activation='relu')(dr2)
# mp3 = layers.MaxPool2D()(cnn3)
# dr3 = layers.Dropout(config.dropout)(mp3)

# cnn4 = layers.SeparableConv2D(baseFilter*4, 3, padding='same', activation='relu')(dr3)
# mp4 = layers.MaxPool2D()(cnn4)
# dr4 = layers.Dropout(config.dropout)(mp4)

# cnn5 = layers.SeparableConv2D(baseFilter*5, 3, padding='same', activation='relu')(dr4)
# mp5 = layers.MaxPool2D()(cnn5)
# dr5 = layers.Dropout(config.dropout)(mp5)

# cnn6 = layers.SeparableConv2D(baseFilter*6, 3, padding='same', activation='relu')(dr5)
# mp6 = layers.MaxPool2D()(cnn6)
# dr6 = layers.Dropout(config.dropout)(mp6)

# cnn7 = layers.SeparableConv2D(baseFilter*7, 3, padding='same', activation='relu')(dr6)
# mp7 = layers.MaxPool2D()(cnn7)
# dr7 = layers.Dropout(config.dropout)(mp7)

# gp1 = layers.GlobalMaxPooling2D()(dr7)
    
# d1 = layers.Dense(config.dlayer_0, activation=config.activation_0)(gp1)
# dr8 = layers.Dropout(config.dropout)(d1)

# d2 = layers.Dense(config.dlayer_1, activation=config.activation_1)(dr8)
# dr9 = layers.Dropout(config.dropout)(d2)

# d3 = layers.Dense(config.dlayer_2, activation=config.activation_2)(dr9)
# dr10 = layers.Dropout(config.dropout)(d3)
    
# dr_skew = layers.Dense(config.dlayer_skew, activation=config.activation_skew, name='Skew')(dr10)

# dr_kurt = layers.Dense(config.dlayer_kurt, activation=config.activation_kurt, name='Kurt')(dr10)

# combo = layers.concatenate([dr10, dr_skew, dr_kurt])

# dr_dist = layers.Dense(11, activation=config.activation_dist, name='Dist')(combo)

# # dr_dist = layers.Dense(11, activation=config.activation_dist, name='Dist')(dr7)



# model = Model(inp, [dr_dist, dr_skew, dr_kurt])

# # model = Model(inp, [dr_dist])

# model._name = "SandCam_CNN"

# initial_learning_rate = 0.0001
# lr_schedule = tf.keras.optimizers.schedules.ExponentialDecay(
#     initial_learning_rate,
#     decay_steps=100000,
#     decay_rate=0.96,
#     staircase=True)

# # opt = tf.keras.optimizers.SGD(lr=1e-2, momentum=0.9, decay=1e-2/200)
# opt = tf.keras.optimizers.Adam()

# model.compile(loss={
#                 'Dist':'mean_squared_error',
#                 'Skew':'mean_squared_error',
#                 'Kurt':'mean_squared_error',
#                 }, 
#                   optimizer=opt,
#                   metrics = mape_metric
#          )<jupyter_output><empty_output><jupyter_text>Residual Model 1Skip connections with Relu and BatchNorm<jupyter_code># baseFilter= 32

# inp = layers.Input(shape=imshape)

# cnn0 = layers.SeparableConv2D(filters = baseFilter, kernel_size=3, padding='same', activation='relu')(inp)
# cnn1 = layers.SeparableConv2D(baseFilter*2, 3, padding='same', activation='relu')(cnn0)
# mp1 = layers.MaxPool2D()(cnn1)
# dr1 = layers.Dropout(config.dropout)(mp1)

# cnn2 = layers.SeparableConv2D(baseFilter*3, 3, padding='same', activation='relu')(dr1)
# mp2 = layers.MaxPool2D()(cnn2)
# dr2 = layers.Dropout(config.dropout)(mp2)

# ## residual

# res1 = layers.Add([dr1, dr2])
# act1 = layers.ReLU()(res1)
# out1 = layers.BatchNormalization()(act1)

# cnn3 = layers.SeparableConv2D(baseFilter*3, 3, padding='same', activation='relu')(act1)
# mp3 = layers.MaxPool2D()(cnn3)
# dr3 = layers.Dropout(config.dropout)(mp3)


# ## residual

# res2 = layers.Add([out1, dr3])
# act2 = layers.ReLU()(res2)
# out2 = layers.BatchNormalization()(act2)

# cnn4 = layers.SeparableConv2D(baseFilter*4, 3, padding='same', activation='relu')(out2)
# mp4 = layers.MaxPool2D()(cnn4)
# dr4 = layers.Dropout(config.dropout)(mp4)

# ## residual

# res3 = layers.Add([out2, dr4])
# act3 = layers.ReLU()(res3)
# out3 = layers.BatchNormalization()(act3)


# cnn5 = layers.SeparableConv2D(baseFilter*5, 3, padding='same', activation='relu')(out3)
# mp5 = layers.MaxPool2D()(cnn5)
# dr5 = layers.Dropout(config.dropout)(mp5)

# ## residual

# res4 = layers.Add([out3, dr5])
# act4 = layers.ReLU()(res4)
# out4 = layers.BatchNormalization()(act4)


# cnn6 = layers.SeparableConv2D(baseFilter*6, 3, padding='same', activation='relu')(act4)
# mp6 = layers.MaxPool2D()(cnn6)
# dr6 = layers.Dropout(config.dropout)(mp6)

# ## residual

# res5 = layers.Add([out4, dr6])
# act5 = layers.ReLU()(res5)
# out5 = layers.BatchNormalization()(act5)


# cnn7 = layers.SeparableConv2D(baseFilter*7, 3, padding='same', activation='relu')(out5)
# mp7 = layers.MaxPool2D()(cnn7)
# dr7 = layers.Dropout(config.dropout)(mp7)

# ## residual

# res6 = layers.Add([out5, dr7])
# act6 = layers.ReLU()(res6)
# out6 = layers.BatchNormalization()(act6)


# gp1 = layers.GlobalMaxPooling2D()(out6)
    
# d1 = layers.Dense(config.dlayer_0, activation=config.activation_0)(gp1)
# dr5 = layers.Dropout(config.dropout)(d1)

# d2 = layers.Dense(config.dlayer_1, activation=config.activation_1)(dr5)
# dr6 = layers.Dropout(config.dropout)(d2)

# d3 = layers.Dense(config.dlayer_2, activation=config.activation_2)(dr6)
# dr7 = layers.Dropout(config.dropout)(d3)
    
# dr_skew = layers.Dense(config.dlayer_skew, activation=config.activation_skew, name='Skew')(dr7)

# dr_kurt = layers.Dense(config.dlayer_kurt, activation=config.activation_kurt, name='Kurt')(dr7)

# combo = layers.concatenate([dr7, dr_skew, dr_kurt])

# dr_dist = layers.Dense(11, activation=config.activation_dist, name='Dist')(combo)

# # dr_dist = layers.Dense(11, activation=config.activation_dist, name='Dist')(dr7)



# model = Model(inp, [dr_dist, dr_skew, dr_kurt])

# # model = Model(inp, [dr_dist])

# model._name = "SandCam_CNN"

# initial_learning_rate = 0.0001
# lr_schedule = tf.keras.optimizers.schedules.ExponentialDecay(
#     initial_learning_rate,
#     decay_steps=100000,
#     decay_rate=0.96,
#     staircase=True)

# # opt = tf.keras.optimizers.SGD(lr=1e-2, momentum=0.9, decay=1e-2/200)
# opt = tf.keras.optimizers.Adam()

# model.compile(loss={
#                 'Dist':'mean_squared_error',
#                 'Skew':'mean_squared_error',
#                 'Kurt':'mean_squared_error',
#                 }, 
#                   optimizer=opt,
#                   metrics = mape_metric
#          )<jupyter_output><empty_output><jupyter_text>Residual Model 2Skip connections with Gelu and BatchNorm<jupyter_code># def relu_bn(inputs: tf.Tensor) -> tf.Tensor:
#     relu = layers.ReLU()(inputs)
#     bn = layers.BatchNormalization()(relu)
#     return bn

# def residual_block(x: tf.Tensor, downsample: bool, filters: int, kernel_size: int = 3) -> tf.Tensor:
#     y = layers.Conv2D(kernel_size=kernel_size,
#                strides= (1 if not downsample else 2),
#                filters=filters,
#                padding="same")(x)
#     y = relu_bn(y)
#     y = layers.Conv2D(kernel_size=kernel_size,
#                strides=1,
#                filters=filters,
#                padding="same")(y)

#     if downsample:
#         x = layers.Conv2D(kernel_size=1,
#                    strides=2,
#                    filters=filters,
#                    padding="same")(x)
#     out = layers.Add()([x, y])
#     out = relu_bn(out)
#     return out

# num_filters = 32
# inp = layers.Input(shape=imshape)

# t = layers.BatchNormalization()(inp)
# t = layers.Conv2D(kernel_size=3,
#            strides=1,
#            filters=num_filters,
#            padding="same")(t)
# t = relu_bn(t)

# num_blocks_list = [2]
# for i in range(len(num_blocks_list)):
#     num_blocks = num_blocks_list[i]
#     for j in range(num_blocks):
#         t = residual_block(t, downsample=(j==0 and i!=0), filters=num_filters)
#     num_filters *= 2
    
# gp1 = layers.GlobalMaxPooling2D()(t)

# d1 = layers.Dense(config.dlayer_0, activation=config.activation)(gp1)
# dr8 = layers.Dropout(config.dropout)(d1)

# d2 = layers.Dense(config.dlayer_1, activation=config.activation)(dr8)
# dr9 = layers.Dropout(config.dropout)(d2)

# d3 = layers.Dense(config.dlayer_2, activation=config.activation)(dr9)
# dr10 = layers.Dropout(config.dropout)(d3)
    
# dr_skew = layers.Dense(config.dlayer_skew, activation="gelu", name='Skew')(dr10)

# dr_kurt = layers.Dense(config.dlayer_kurt, activation="gelu", name='Kurt')(dr10)

# combo = layers.concatenate([dr10, dr_skew, dr_kurt])

# dr_dist = layers.Dense(11, activation=config.activation, name='Dist')(combo)

# model = Model(inp, [dr_dist, dr_skew, dr_kurt])

# # model = Model(inp, [dr_dist])

# model._name = "SandCam_CNN"

# initial_learning_rate = 0.0001
# lr_schedule = tf.keras.optimizers.schedules.ExponentialDecay(
#     initial_learning_rate,
#     decay_steps=100000,
#     decay_rate=0.96,
#     staircase=True)

# # opt = tf.keras.optimizers.SGD(lr=1e-2, momentum=0.9, decay=1e-2/200)
# opt = tf.keras.optimizers.Adam()

# model.compile(loss={
#                 'Dist':'mean_squared_error',
#                 'Skew':'mean_squared_error',
#                 'Kurt':'mean_squared_error',
#                 }, 
#                   optimizer=opt,
#                   metrics = mape_metric
#          )<jupyter_output><empty_output><jupyter_text>Large ModelLarger kernel size with Gelu activations (Currently the best model)<jupyter_code>baseFilter= 32
kernelSize = 6

inp = layers.Input(shape=imshape)

cnn0 = layers.SeparableConv2D(filters = baseFilter, kernel_size=kernelSize, padding='same', activation='gelu')(inp)
mp1 = layers.MaxPool2D()(cnn0)
dr1 = layers.Dropout(config.dropout)(mp1)

cnn1 = layers.SeparableConv2D(baseFilter*2, kernel_size=kernelSize, padding='same', activation='gelu')(dr1)
cnn2 = layers.SeparableConv2D(baseFilter*2, kernel_size=kernelSize, padding='same', activation='gelu')(cnn1)
mp2 = layers.MaxPool2D()(cnn2)
dr2 = layers.Dropout(config.dropout)(mp2)

cnn3 = layers.SeparableConv2D(baseFilter*4, kernel_size=kernelSize, padding='same', activation='gelu')(dr2)
cnn4 = layers.SeparableConv2D(baseFilter*4, kernel_size=kernelSize, padding='same', activation='gelu')(cnn1)
mp3 = layers.MaxPool2D()(cnn4)
dr3 = layers.Dropout(config.dropout)(mp3)

cnn4 = layers.SeparableConv2D(baseFilter*4, kernel_size=kernelSize, padding='same', activation='gelu')(dr3)
cnn5 = layers.SeparableConv2D(baseFilter*4, kernel_size=kernelSize, padding='same', activation='gelu')(cnn4)
mp4 = layers.MaxPool2D()(cnn5)
dr4 = layers.Dropout(config.dropout)(mp4)

gp1 = layers.GlobalMaxPooling2D()(dr4)
    
d1 = layers.Dense(config.dlayer_0, activation=config.activation)(gp1)
dr8 = layers.Dropout(config.dropout)(d1)

d2 = layers.Dense(config.dlayer_1, activation=config.activation)(dr8)
dr9 = layers.Dropout(config.dropout)(d2)

d3 = layers.Dense(config.dlayer_2, activation=config.activation)(dr9)
dr10 = layers.Dropout(config.dropout)(d3)
    
dr_skew = layers.Dense(config.dlayer_skew, activation="gelu", name='Skew')(dr10)

dr_kurt = layers.Dense(config.dlayer_kurt, activation="gelu", name='Kurt')(dr10)

combo = layers.concatenate([dr10, dr_skew, dr_kurt])

dr_dist = layers.Dense(11, activation=config.activation, name='Dist')(combo)

model = Model(inp, [dr_dist, dr_skew, dr_kurt])

# model = Model(inp, [dr_dist])

model._name = "SandCam_CNN"

initial_learning_rate = 0.0001
lr_schedule = tf.keras.optimizers.schedules.ExponentialDecay(
    initial_learning_rate,
    decay_steps=100000,
    decay_rate=0.96,
    staircase=True)

# opt = tf.keras.optimizers.SGD(lr=1e-2, momentum=0.9, decay=1e-2/200)
opt = tf.keras.optimizers.Adam()

model.compile(loss={
                'Dist':'mean_squared_error',
                'Skew':'mean_squared_error',
                'Kurt':'mean_squared_error',
                }, 
                  optimizer=opt,
                  metrics = mape_metric
         )<jupyter_output><empty_output><jupyter_text>Very Large ModelLarger kernel size with Gelu activations (Was not able to run)<jupyter_code># baseFilter= 32
# kernelSize = 6

# inp = layers.Input(shape=imshape)

# cnn0 = layers.SeparableConv2D(filters = baseFilter, kernel_size=kernelSize, padding='same', activation='relu')(inp)
# cnn1 = layers.SeparableConv2D(baseFilter*2, kernel_size=kernelSize, padding='same', activation='gelu')(cnn0)
# mp1 = layers.MaxPool2D()(cnn1)
# dr1 = layers.Dropout(config.dropout)(mp1)

# cnn2 = layers.SeparableConv2D(baseFilter*3, kernel_size=kernelSize, padding='same', activation='gelu')(dr1)
# mp2 = layers.MaxPool2D()(cnn2)
# dr2 = layers.Dropout(config.dropout)(mp2)

# # cnn3 = layers.SeparableConv2D(baseFilter*3, kernel_size=kernelSize, padding='same', activation='gelu')(dr2)
# # mp3 = layers.MaxPool2D()(cnn3)
# # dr3 = layers.Dropout(config.dropout)(mp3)

# cnn4 = layers.SeparableConv2D(baseFilter*4, kernel_size=kernelSize, padding='same', activation='gelu')(dr2)
# mp4 = layers.MaxPool2D()(cnn4)
# dr4 = layers.Dropout(config.dropout)(mp4)

# # cnn5 = layers.SeparableConv2D(baseFilter*5, kernel_size=kernelSize, padding='same', activation='gelu')(dr4)
# # mp5 = layers.MaxPool2D()(cnn5)
# # dr5 = layers.Dropout(config.dropout)(mp5)

# # cnn6 = layers.SeparableConv2D(baseFilter*6, kernel_size=kernelSize, padding='same', activation='gelu')(dr5)
# # mp6 = layers.MaxPool2D()(cnn6)
# # dr6 = layers.Dropout(config.dropout)(mp6)

# # cnn7 = layers.SeparableConv2D(baseFilter*7, kernel_size=kernelSize, padding='same', activation='gelu')(dr6)
# # mp7 = layers.MaxPool2D()(cnn7)
# # dr7 = layers.Dropout(config.dropout)(mp7)

# gp1 = layers.GlobalMaxPooling2D()(dr4)
    
# d1 = layers.Dense(config.dlayer_0, activation=config.activation)(gp1)
# dr8 = layers.Dropout(config.dropout)(d1)

# d2 = layers.Dense(config.dlayer_1, activation=config.activation)(dr8)
# dr9 = layers.Dropout(config.dropout)(d2)

# d3 = layers.Dense(config.dlayer_2, activation=config.activation)(dr9)
# dr10 = layers.Dropout(config.dropout)(d3)
    
# dr_skew = layers.Dense(config.dlayer_skew, activation="gelu", name='Skew')(dr10)

# dr_kurt = layers.Dense(config.dlayer_kurt, activation="gelu", name='Kurt')(dr10)

# combo = layers.concatenate([dr10, dr_skew, dr_kurt])

# dr_dist = layers.Dense(11, activation=config.activation, name='Dist')(combo)

# # dr_dist = layers.Dense(11, activation=config.activation_dist, name='Dist')(dr7)



# model = Model(inp, [dr_dist, dr_skew, dr_kurt])

# # model = Model(inp, [dr_dist])

# model._name = "SandCam_CNN"

# initial_learning_rate = 0.0001
# lr_schedule = tf.keras.optimizers.schedules.ExponentialDecay(
#     initial_learning_rate,
#     decay_steps=100000,
#     decay_rate=0.96,
#     staircase=True)

# # opt = tf.keras.optimizers.SGD(lr=1e-2, momentum=0.9, decay=1e-2/200)
# opt = tf.keras.optimizers.Adam()

# model.compile(loss={
#                 'Dist':'mean_squared_error',
#                 'Skew':'mean_squared_error',
#                 'Kurt':'mean_squared_error',
#                 }, 
#                   optimizer=opt,
#                   metrics = mape_metric
#          )<jupyter_output><empty_output><jupyter_text>Model Architecture<jupyter_code>tf.keras.utils.plot_model(model, show_shapes=True)<jupyter_output><empty_output><jupyter_text>Callbacks<jupyter_code># define a callback

early_stop = tf.keras.callbacks.EarlyStopping(monitor = 'val_loss', 
                                             patience = 20, 
                                             restore_best_weights = True)

reduce_lr = tf.keras.callbacks.ReduceLROnPlateau(monitor='val_loss', 
                                                 factor = 0.02,
                                                 verbose = 1,
                                                 patience=10)


logging_callback = WandbCallback(log_evaluation=True)<jupyter_output><empty_output><jupyter_text>Train and Validate the model<jupyter_code>#train the model
history = model.fit(train_generator,
                    steps_per_epoch = total_train // batch_size,
                    validation_data = validation_generator,
                    validation_steps =  total_val // batch_size,
                    epochs= 200,
                    
#                     workers = 8,
                    callbacks =[early_stop, reduce_lr, logging_callback])
wandb.finish()<jupyter_output>wandb: WARNING WandbCallback is unable to log validation data. When using a generator for validation_data, you must pass validation_steps<jupyter_text>Model Performance<jupyter_code>from IPython.display import IFrame

IFrame("https://wandb.ai/chk_null/sandcam_2/workspace?workspace=user-chk_null", width="100%", height=720)<jupyter_output><empty_output><jupyter_text>Saved Models  Original Model<jupyter_code>#save the model
filepath = './log/saved_model/sandcam-multiout.h5'
model.save(filepath)

#model size

print(
    "Size of the model: %.2f Mb"
    % (os.path.getsize(filepath) / float(2 ** 20))
)<jupyter_output>Size of the model: 2.38 Mb
{'fraction_non_alphanumeric': 0.14850636630754163, 'fraction_numerical': 0.03472902383284362, 'mean_word_length': 3.6393411586520257, 'pattern_counts': {'":': 20, '<': 62, '<?xml version=': 0, '>': 64, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 43, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '16', 'dir': 'jupyter-structured-clean-dedup', 'id': '458195', 'license': 'MIT', 'n_tokens_mistral': 9453, 'n_tokens_neox': 8963, 'n_words': 1321, 'path': 'ML/src/SandNetModel-Functional_Multiout.ipynb', 'repo_name': 'UNCG-DAISY/SediNetCam', 'size': '24504'}