| import tensorflow as tf
|
| from tensorflow.keras import layers, Model
|
|
|
| ACTIVITIES = [
|
| 'WALKING', 'WALKING_UPSTAIRS', 'WALKING_DOWNSTAIRS',
|
| 'SITTING', 'STANDING', 'LAYING'
|
| ]
|
| N_CLASSES = len(ACTIVITIES)
|
| INPUT_SHAPE = (128, 9)
|
|
|
|
|
| def build_imu_model(input_shape=INPUT_SHAPE, n_classes=N_CLASSES):
|
| """
|
| Compact 1D-CNN for IMU activity classification.
|
| Designed from scratch for pruning + INT8 quantization.
|
|
|
| Architecture rationale:
|
| - Conv1D blocks β extract local motion patterns per axis
|
| - BatchNorm β stable training, works well post-quantization
|
| - MaxPooling β downsample before deeper layers
|
| - GlobalAvgPool β replaces Flatten, much fewer params, less overfit
|
| - Dense head β final classifier
|
|
|
| Total params: ~85K (intentionally small for edge deployment)
|
| """
|
|
|
| inputs = tf.keras.Input(shape=input_shape, name='imu_input')
|
|
|
|
|
| x = layers.Conv1D(32, kernel_size=5, padding='same',
|
| activation='relu', name='conv1')(inputs)
|
| x = layers.BatchNormalization(name='bn1')(x)
|
| x = layers.MaxPooling1D(pool_size=2, name='pool1')(x)
|
| x = layers.Dropout(0.1, name='drop1')(x)
|
|
|
|
|
| x = layers.Conv1D(64, kernel_size=3, padding='same',
|
| activation='relu', name='conv2')(x)
|
| x = layers.BatchNormalization(name='bn2')(x)
|
| x = layers.MaxPooling1D(pool_size=2, name='pool2')(x)
|
| x = layers.Dropout(0.1, name='drop2')(x)
|
|
|
|
|
| x = layers.Conv1D(128, kernel_size=3, padding='same',
|
| activation='relu', name='conv3')(x)
|
| x = layers.BatchNormalization(name='bn3')(x)
|
| x = layers.MaxPooling1D(pool_size=2, name='pool3')(x)
|
| x = layers.Dropout(0.1, name='drop4')(x)
|
|
|
|
|
| x = layers.Conv1D(128, kernel_size=3, padding='same',
|
| activation='relu', name='conv4')(x)
|
| x = layers.BatchNormalization(name='bn4')(x)
|
|
|
|
|
| x = layers.GlobalAveragePooling1D(name='gap')(x)
|
|
|
| x = layers.Dense(64, activation='relu', name='dense1')(x)
|
| x = layers.Dropout(0.3, name='drop5')(x)
|
|
|
| outputs = layers.Dense(
|
| n_classes, activation='softmax', name='activity'
|
| )(x)
|
|
|
| model = Model(inputs, outputs, name='IMU_Classifier')
|
| return model
|
|
|
|
|
|
|
|
|
|
|
| if __name__ == '__main__':
|
| model = build_imu_model()
|
| model.summary()
|
|
|
| total = model.count_params()
|
| size_kb = total * 4 / 1024
|
|
|
| print(f"\nββ Model Info ββββββββββββββββββββββββββ")
|
| print(f"Total parameters : {total:,}")
|
| print(f"FP32 size estimate: {size_kb:.1f} KB")
|
| print(f"Input shape : {INPUT_SHAPE}")
|
| print(f"Output classes : {N_CLASSES} β {ACTIVITIES}")
|
| print(f"\nβ
Model built successfully.") |