File size: 6,514 Bytes
2ae87d4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
"""
create_new_model.py - Create a new working model from scratch
"""

import tensorflow as tf
from tensorflow.keras import layers, Model
import numpy as np
import os

print("=" * 60)
print("CREATING NEW WORKING MODEL")
print("=" * 60)

def create_vit_extractor():
    """Create a Vision Transformer feature extractor."""
    print("Building Vision Transformer extractor...")
    
    # Input layer
    inputs = layers.Input(shape=(224, 224, 3), name='input_image')
    
    # Preprocessing
    x = layers.Rescaling(1./255)(inputs)
    
    # Patch embeddings (simulated with Conv2D)
    x = layers.Conv2D(
        filters=768,
        kernel_size=16,
        strides=16,
        padding='valid',
        name='patch_embeddings'
    )(x)
    
    # Reshape to (batch, num_patches, embed_dim)
    batch_size = tf.shape(x)[0]
    x = tf.reshape(x, [batch_size, -1, 768])
    
    # Add class token
    cls_token = tf.Variable(
        tf.random.normal((1, 1, 768)),
        trainable=True,
        name='cls_token'
    )
    cls_token = tf.tile(cls_token, [batch_size, 1, 1])
    x = tf.concat([cls_token, x], axis=1)
    
    # Position embeddings
    pos_emb = layers.Dense(768, name='position_embeddings')(tf.zeros((1, 197, 768)))
    x = x + pos_emb
    
    # Transformer blocks
    for i in range(6):
        # Layer norm 1
        x_norm = layers.LayerNormalization(epsilon=1e-6, name=f'transformer_{i}_ln1')(x)
        
        # Multi-head attention
        attn = layers.MultiHeadAttention(
            num_heads=12,
            key_dim=64,
            name=f'transformer_{i}_attn'
        )
        attn_output = attn(x_norm, x_norm)
        
        # First residual
        x = x + attn_output
        
        # Layer norm 2
        x_norm = layers.LayerNormalization(epsilon=1e-6, name=f'transformer_{i}_ln2')(x)
        
        # MLP
        mlp = tf.keras.Sequential([
            layers.Dense(3072, activation='gelu', name=f'transformer_{i}_mlp1'),
            layers.Dropout(0.1),
            layers.Dense(768, name=f'transformer_{i}_mlp2'),
            layers.Dropout(0.1)
        ], name=f'transformer_{i}_mlp')
        
        mlp_output = mlp(x_norm)
        
        # Second residual
        x = x + mlp_output
    
    # Extract class token
    x = x[:, 0, :]  # Shape: (batch, 768)
    
    # Project to feature space
    x = layers.Dense(512, activation='relu', name='proj1')(x)
    x = layers.Dropout(0.3, name='dropout1')(x)
    x = layers.Dense(256, activation='relu', name='proj2')(x)
    outputs = layers.Dense(512, activation='relu', name='output_features')(x)
    
    # Create model
    model = Model(inputs=inputs, outputs=outputs, name='hybrid_feature_extractor')
    
    # Compile (not needed for inference but helps)
    model.compile(optimizer='adam', loss='mse')
    
    print(f"βœ“ Vision Transformer created")
    return model

def create_cnn_extractor():
    """Create a CNN-based feature extractor (faster)."""
    print("Building CNN extractor...")
    
    inputs = layers.Input(shape=(224, 224, 3), name='input_image')
    
    # Use EfficientNetV2B0 for good performance
    base_model = tf.keras.applications.EfficientNetV2B0(
        include_top=False,
        weights='imagenet',
        input_tensor=inputs,
        pooling='avg'
    )
    base_model.trainable = False
    
    # Get features
    features = base_model.output
    
    # Add custom layers
    x = layers.Dense(512, activation='relu', name='fc1')(features)
    x = layers.Dropout(0.3, name='dropout1')(x)
    x = layers.Dense(256, activation='relu', name='fc2')(x)
    x = layers.Dropout(0.2, name='dropout2')(x)
    outputs = layers.Dense(512, activation='relu', name='output_features')(x)
    
    model = Model(inputs=inputs, outputs=outputs, name='cnn_feature_extractor')
    
    print(f"βœ“ CNN extractor created")
    return model

def save_model_multiple_formats(model, base_name):
    """Save model in multiple formats for compatibility."""
    print(f"\nSaving model in multiple formats...")
    
    # 1. Save as .keras (recommended)
    keras_path = f"{base_name}.keras"
    model.save(keras_path)
    print(f"βœ“ Saved as {keras_path}")
    
    # 2. Save as SavedModel
    sm_path = f"{base_name}_savedmodel"
    model.save(sm_path, save_format='tf')
    print(f"βœ“ Saved as SavedModel: {sm_path}")
    
    # 3. Save as H5 (for backward compatibility)
    h5_path = f"{base_name}.h5"
    model.save(h5_path, save_format='h5')
    print(f"βœ“ Saved as H5: {h5_path}")
    
    return keras_path, sm_path, h5_path

def create_dummy_data(model):
    """Create dummy training data to initialize model."""
    print("\nCreating dummy training data...")
    
    # Generate random images
    dummy_images = np.random.randn(10, 224, 224, 3).astype('float32')
    dummy_features = np.random.randn(10, model.output_shape[1]).astype('float32')
    
    # Train for 1 epoch (just to initialize weights properly)
    model.fit(
        dummy_images,
        dummy_features,
        epochs=1,
        verbose=0
    )
    
    print("βœ“ Model initialized with dummy data")

if __name__ == "__main__":
    print("Select model type:")
    print("1. Vision Transformer (ViT) - More accurate")
    print("2. CNN (EfficientNet) - Faster inference")
    print("3. Hybrid (CNN + Transformer) - Best of both")
    
    choice = input("\nEnter choice (1, 2, or 3): ").strip()
    
    if choice == '1':
        model = create_vit_extractor()
        model_name = "vit_extractor"
    elif choice == '2':
        model = create_cnn_extractor()
        model_name = "cnn_extractor"
    else:
        # Create hybrid model
        print("Building hybrid model...")
        model = create_cnn_extractor()
        model_name = "hybrid_extractor"
    
    # Show model summary
    print(f"\nModel Summary:")
    model.summary()
    
    # Initialize with dummy data
    create_dummy_data(model)
    
    # Save in multiple formats
    keras_path, sm_path, h5_path = save_model_multiple_formats(model, model_name)
    
    print("\n" + "=" * 60)
    print("MODEL CREATION COMPLETE")
    print("=" * 60)
    print(f"βœ… Model: {model.name}")
    print(f"βœ… Input shape: {model.input_shape}")
    print(f"βœ… Output shape: {model.output_shape}")
    print(f"βœ… Formats available:")
    print(f"   - {keras_path} (recommended)")
    print(f"   - {sm_path}/ (SavedModel)")
    print(f"   - {h5_path} (H5 for compatibility)")
    print("\nNow update your app.py to use one of these files!")
    print("=" * 60)