Piyush23890/Sign_Language_Decoder
0
1"""2train_dynamic_model.py3======================4Train an LSTM sequence classifier on dynamic ISL gesture recordings.5 6Expects dynamic_dataset/<action>/*.npy with shape (30, 126).7Saves dynamic_sign_model.h58 9Usage10-----11 python train_dynamic_model.py12"""13 14import os15import numpy as np16from sklearn.model_selection import train_test_split17 18# ── Config ──────────────────────────────────────────────────────────────────────19DATASET_PATH = "dynamic_dataset"20ACTIONS = ["hello", "thank_you"] # must match collection labels21SEQUENCE_LENGTH = 3022FEATURES = 12623EPOCHS = 3024BATCH_SIZE = 1625MODEL_PATH = "dynamic_sign_model.h5"26 27# ── TF import (isolated so the mock in app.py doesn't interfere) ────────────────28import tensorflow as tf29from tensorflow.keras.models import Sequential30from tensorflow.keras.layers import LSTM, Dense, Dropout31from tensorflow.keras.utils import to_categorical32from tensorflow.keras.callbacks import EarlyStopping, ModelCheckpoint33 34print("=" * 50)35print("SignBridge — Dynamic Model Trainer")36print(f"TF version : {tf.__version__}")37print("=" * 50)38 39# ── 1. Load .npy sequences ──────────────────────────────────────────────────────40X, y = [], []41for label_idx, action in enumerate(ACTIONS):42 folder = os.path.join(DATASET_PATH, action)43 if not os.path.isdir(folder):44 print(f" [WARN] Missing folder: {folder}")45 continue46 files = [f for f in os.listdir(folder) if f.endswith(".npy")]47 print(f" [{action}] {len(files)} sequences")48 for fname in files:49 arr = np.load(os.path.join(folder, fname))50 if arr.shape == (SEQUENCE_LENGTH, FEATURES):51 X.append(arr)52 y.append(label_idx)53 else:54 print(f" [skip] bad shape {arr.shape}: {fname}")55 56X = np.array(X, dtype=np.float32)57y = to_categorical(y, num_classes=len(ACTIONS))58print(f"\nDataset: {X.shape[0]} sequences × {SEQUENCE_LENGTH} frames × {FEATURES} features")59 60# ── 2. Split ─────────────────────────────────────────────────────────────────────61X_train, X_test, y_train, y_test = train_test_split(62 X, y, test_size=0.20, random_state=4263)64print(f"Train: {len(X_train)} | Test: {len(X_test)}")65 66# ── 3. Model ──────────────────────────────────────────────────────────────────────67model = Sequential([68 LSTM(64, return_sequences=True,69 input_shape=(SEQUENCE_LENGTH, FEATURES)),70 Dropout(0.30),71 LSTM(64),72 Dense(32, activation="relu"),73 Dense(len(ACTIONS), activation="softmax"),74], name="dynamic_isl")75 76model.compile(77 optimizer="adam",78 loss="categorical_crossentropy",79 metrics=["accuracy"],80)81model.summary()82 83# ── 4. Train ─────────────────────────────────────────────────────────────────────84callbacks = [85 EarlyStopping(monitor="val_accuracy", patience=5,86 restore_best_weights=True, verbose=1),87 ModelCheckpoint(MODEL_PATH, monitor="val_accuracy",88 save_best_only=True, verbose=1),89]90 91print(f"\nTraining for up to {EPOCHS} epochs …")92history = model.fit(93 X_train, y_train,94 epochs=EPOCHS,95 batch_size=BATCH_SIZE,96 validation_data=(X_test, y_test),97 callbacks=callbacks,98 verbose=1,99)100 101# ── 5. Final evaluation ───────────────────────────────────────────────────────────102loss, acc = model.evaluate(X_test, y_test, verbose=0)103print(f"\nFinal Test Accuracy : {acc * 100:.2f}%")104print(f"Model saved : {MODEL_PATH}")105 