|
from config import DatasetName, AffectnetConf, InputDataSize, LearningConfig |
|
|
|
|
|
import tensorflow as tf |
|
|
|
|
|
from keras.models import Model |
|
|
|
from keras.applications import mobilenet_v2, mobilenet, resnet50, densenet, resnet |
|
from keras.layers import Dense, MaxPooling2D, Conv2D, Flatten, \ |
|
BatchNormalization, Activation, GlobalAveragePooling2D, DepthwiseConv2D, \ |
|
Dropout, ReLU, Concatenate, Input, GlobalMaxPool2D, LeakyReLU, Softmax, ELU |
|
|
|
class CNNModel: |
|
def get_model(self, arch, num_of_classes, weights): |
|
if arch == 'resnet': |
|
model = self._create_resnetemb(num_of_classes, |
|
num_of_embeddings=LearningConfig.num_embeddings, |
|
input_shape=(InputDataSize.image_input_size, |
|
InputDataSize.image_input_size, 3), |
|
weights=weights |
|
) |
|
if arch == 'xcp': |
|
model = self._create_Xception_l2(num_of_classes, |
|
num_of_embeddings=LearningConfig.num_embeddings, |
|
input_shape=(InputDataSize.image_input_size, |
|
InputDataSize.image_input_size, 3), |
|
weights=weights |
|
) |
|
|
|
return model |
|
|
|
def _create_resnetemb(self, num_of_classes, input_shape, weights, num_of_embeddings): |
|
resnet_model = resnet.ResNet50( |
|
input_shape=input_shape, |
|
include_top=True, |
|
weights='imagenet', |
|
|
|
input_tensor=None, |
|
pooling=None) |
|
resnet_model.layers.pop() |
|
|
|
avg_pool = resnet_model.get_layer('avg_pool').output |
|
'''''' |
|
embeddings = [] |
|
for i in range(num_of_embeddings): |
|
emb = tf.keras.layers.Dense(LearningConfig.embedding_size, activation=None)(avg_pool) |
|
emb_l2 = tf.keras.layers.Lambda(lambda x: tf.math.l2_normalize(x, axis=1))(emb) |
|
embeddings.append(emb_l2) |
|
|
|
if num_of_embeddings > 1: |
|
fused = tf.keras.layers.Concatenate(axis=1)([embeddings[i] for i in range(num_of_embeddings)]) |
|
else: |
|
fused = embeddings[0] |
|
|
|
fused = Dropout(rate=0.5)(fused) |
|
|
|
'''out''' |
|
out_categorical = Dense(num_of_classes, |
|
activation='softmax', |
|
name='out')(fused) |
|
|
|
inp = [resnet_model.input] |
|
|
|
revised_model = Model(inp, [out_categorical] + [embeddings[i] for i in range(num_of_embeddings)]) |
|
revised_model.summary() |
|
'''save json''' |
|
model_json = revised_model.to_json() |
|
|
|
with open("./model_archs/resnetemb.json", "w") as json_file: |
|
json_file.write(model_json) |
|
|
|
return revised_model |
|
|
|
def _create_Xception_l2(self, num_of_classes, num_of_embeddings, input_shape, weights): |
|
xception_model = tf.keras.applications.Xception( |
|
include_top=False, |
|
|
|
input_tensor=None, |
|
weights='imagenet', |
|
input_shape=input_shape, |
|
pooling=None, |
|
classes=num_of_classes |
|
) |
|
|
|
act_14 = xception_model.get_layer('block14_sepconv2_act').output |
|
avg_pool = GlobalAveragePooling2D()(act_14) |
|
|
|
embeddings = [] |
|
for i in range(num_of_embeddings): |
|
emb = tf.keras.layers.Dense(LearningConfig.embedding_size, activation=None)(avg_pool) |
|
emb_l2 = tf.keras.layers.Lambda(lambda x: tf.math.l2_normalize(x, axis=1))(emb) |
|
|
|
embeddings.append(emb_l2) |
|
if num_of_embeddings > 1: |
|
fused = tf.keras.layers.Concatenate(axis=1)([embeddings[i] for i in range(num_of_embeddings)]) |
|
else: |
|
fused = embeddings[0] |
|
fused = Dropout(rate=0.5)(fused) |
|
|
|
'''out''' |
|
out_categorical = Dense(num_of_classes, |
|
activation='softmax', |
|
name='out')(fused) |
|
|
|
inp = [xception_model.input] |
|
|
|
revised_model = Model(inp, [out_categorical] + [embeddings[i] for i in range(num_of_embeddings)]) |
|
revised_model.summary() |
|
'''save json''' |
|
model_json = revised_model.to_json() |
|
|
|
with open("./model_archs/xcp_embedding.json", "w") as json_file: |
|
json_file.write(model_json) |
|
|
|
return revised_model |