Spaces:
Runtime error
Runtime error
| import tensorflow as tf | |
| from tensorflow.keras import layers | |
| def build_cnn_baseline(input_shape=(224, 224, 3), dropout_rate=0.3): | |
| inputs = tf.keras.Input(shape=input_shape, name='image_input') | |
| x = layers.Rescaling(1.0 / 255)(inputs) | |
| x = layers.Conv2D(32, 3, activation='relu', padding='same', name='conv_block_1')(x) | |
| x = layers.MaxPooling2D(name='pool_block_1')(x) | |
| x = layers.Conv2D(64, 3, activation='relu', padding='same', name='conv_block_2')(x) | |
| x = layers.MaxPooling2D(name='pool_block_2')(x) | |
| x = layers.Conv2D(128, 3, activation='relu', padding='same', name='conv_block_3')(x) | |
| x = layers.MaxPooling2D(name='pool_block_3')(x) | |
| x = layers.Dropout(dropout_rate)(x) | |
| x = layers.Flatten()(x) | |
| x = layers.Dense(128, activation='relu')(x) | |
| x = layers.Dropout(dropout_rate)(x) | |
| outputs = layers.Dense(1, activation='sigmoid', name='output')(x) | |
| return tf.keras.Model(inputs, outputs, name='cnn_baseline') | |
| def build_transfer_model( | |
| input_shape=(224, 224, 3), | |
| dropout_rate=0.3, | |
| base_model_name='resnet50', | |
| weights='imagenet', | |
| fine_tune=False, | |
| fine_tune_at=None, | |
| ): | |
| inputs = tf.keras.Input(shape=input_shape, name='image_input') | |
| if base_model_name.lower() == 'resnet50': | |
| x = tf.keras.applications.resnet50.preprocess_input(inputs) | |
| base_model = tf.keras.applications.ResNet50( | |
| include_top=False, | |
| weights=weights, | |
| input_shape=input_shape, | |
| pooling='avg', | |
| name='resnet_base', | |
| ) | |
| elif base_model_name.lower() == 'vgg16': | |
| x = tf.keras.applications.vgg16.preprocess_input(inputs) | |
| base_model = tf.keras.applications.VGG16( | |
| include_top=False, | |
| weights=weights, | |
| input_shape=input_shape, | |
| pooling='avg', | |
| name='vgg_base', | |
| ) | |
| else: | |
| raise ValueError('Unsupported base_model_name. Use resnet50 or vgg16.') | |
| base_model.trainable = fine_tune | |
| if fine_tune and fine_tune_at is not None: | |
| for layer in base_model.layers[:fine_tune_at]: | |
| layer.trainable = False | |
| for layer in base_model.layers: | |
| if isinstance(layer, layers.BatchNormalization): | |
| layer.trainable = False | |
| x = base_model(x, training=False) | |
| x = layers.Dropout(dropout_rate)(x) | |
| x = layers.Dense(256, activation='relu')(x) | |
| x = layers.Dropout(dropout_rate)(x) | |
| outputs = layers.Dense(1, activation='sigmoid', name='output')(x) | |
| return tf.keras.Model(inputs, outputs, name='transfer_model') | |
| class PatchEncoder(layers.Layer): | |
| def __init__(self, num_patches, projection_dim): | |
| super().__init__() | |
| self.num_patches = num_patches | |
| self.projection = layers.Dense(projection_dim) | |
| self.position_embedding = layers.Embedding(input_dim=num_patches, output_dim=projection_dim) | |
| def call(self, patch): | |
| positions = tf.range(start=0, limit=self.num_patches, delta=1) | |
| encoded = self.projection(patch) + self.position_embedding(positions) | |
| return encoded | |
| def transformer_block(x, num_heads, projection_dim, mlp_dim, dropout_rate, block_id=None): | |
| x1 = layers.LayerNormalization(epsilon=1e-6, name=f'vit_norm_{block_id}_1')(x) | |
| attention_layer = layers.MultiHeadAttention( | |
| num_heads=num_heads, | |
| key_dim=projection_dim, | |
| dropout=dropout_rate, | |
| name=f'vit_attention_{block_id}', | |
| ) | |
| attention_output = attention_layer(x1, x1) | |
| x2 = layers.Add()([attention_output, x]) | |
| x3 = layers.LayerNormalization(epsilon=1e-6, name=f'vit_norm_{block_id}_2')(x2) | |
| x3 = layers.Dense(mlp_dim, activation='gelu')(x3) | |
| x3 = layers.Dropout(dropout_rate)(x3) | |
| x3 = layers.Dense(projection_dim)(x3) | |
| x3 = layers.Dropout(dropout_rate)(x3) | |
| x4 = layers.Add()([x3, x2]) | |
| return x4 | |
| def build_vit_classifier( | |
| input_shape=(224, 224, 3), | |
| patch_size=16, | |
| num_layers=4, | |
| num_heads=4, | |
| projection_dim=128, | |
| mlp_dim=256, | |
| dropout_rate=0.1, | |
| weights='imagenet', | |
| ): | |
| inputs = tf.keras.Input(shape=input_shape, name='image_input') | |
| x = tf.keras.applications.resnet50.preprocess_input(inputs) | |
| backbone = tf.keras.applications.ResNet50( | |
| include_top=False, | |
| weights=weights, | |
| input_shape=input_shape, | |
| pooling=None, | |
| name='vit_hybrid_resnet_base', | |
| ) | |
| backbone.trainable = False | |
| x = backbone(x, training=False) | |
| x = layers.Conv2D(projection_dim, 1, padding='same', name='hybrid_patch_projection')(x) | |
| num_patches = (input_shape[0] // 32) * (input_shape[1] // 32) | |
| patches = layers.Reshape((num_patches, projection_dim), name='hybrid_patch_tokens')(x) | |
| x = PatchEncoder(num_patches, projection_dim)(patches) | |
| for i in range(num_layers): | |
| x = transformer_block(x, num_heads, projection_dim, mlp_dim, dropout_rate, block_id=i) | |
| x = layers.LayerNormalization(epsilon=1e-6)(x) | |
| x = layers.GlobalAveragePooling1D()(x) | |
| x = layers.Dropout(dropout_rate)(x) | |
| x = layers.Dense(128, activation='relu')(x) | |
| x = layers.Dropout(dropout_rate)(x) | |
| outputs = layers.Dense(1, activation='sigmoid', name='output')(x) | |
| return tf.keras.Model(inputs=inputs, outputs=outputs, name='vit_classifier') | |
| def get_model( | |
| model_name, | |
| input_shape=(224, 224, 3), | |
| transfer_weights='imagenet', | |
| fine_tune_transfer=False, | |
| transfer_fine_tune_at=None, | |
| ): | |
| model_name = model_name.lower() | |
| if model_name == 'cnn': | |
| return build_cnn_baseline(input_shape=input_shape) | |
| if model_name == 'transfer': | |
| return build_transfer_model( | |
| input_shape=input_shape, | |
| weights=transfer_weights, | |
| fine_tune=fine_tune_transfer, | |
| fine_tune_at=transfer_fine_tune_at, | |
| ) | |
| if model_name == 'vit': | |
| return build_vit_classifier(input_shape=input_shape, weights=transfer_weights) | |
| raise ValueError('Unknown model_name. Use cnn, transfer, or vit.') | |