{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.11","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":46105,"databundleVersionId":5087314,"isSourceIdPinned":false,"sourceType":"competition"},{"sourceId":2632847,"sourceType":"datasetVersion","datasetId":1589971}],"dockerImageVersionId":31040,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import os\nimport sys\nimport warnings\nimport logging\nfrom contextlib import redirect_stderr\n\n\nos.environ['TF_CPP_MIN_LOG_LEVEL'] = '3'\nos.environ['TF_ENABLE_ONEDNN_OPTS'] = '0'\nos.environ['CUDA_VISIBLE_DEVICES'] = '0'  # Use GPU if available\nos.environ['TF_FORCE_GPU_ALLOW_GROWTH'] = 'true'\n\n# Suppress all warnings\nwarnings.filterwarnings('ignore')\nlogging.getLogger().setLevel(logging.ERROR)\n\nprint(\"✅ Environment setup complete\")","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-06-18T08:04:48.569096Z","iopub.execute_input":"2025-06-18T08:04:48.569375Z","iopub.status.idle":"2025-06-18T08:04:48.581725Z","shell.execute_reply.started":"2025-06-18T08:04:48.569347Z","shell.execute_reply":"2025-06-18T08:04:48.580848Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\n!pip install mediapipe\n\nprint(\"✅ MediaPipe installation complete\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-18T08:06:14.438744Z","iopub.execute_input":"2025-06-18T08:06:14.439122Z","iopub.status.idle":"2025-06-18T08:06:42.505251Z","shell.execute_reply.started":"2025-06-18T08:06:14.439096Z","shell.execute_reply":"2025-06-18T08:06:42.504198Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import json\nimport numpy as np\nimport pandas as pd\nfrom sklearn.model_selection import train_test_split, StratifiedKFold\nfrom sklearn.preprocessing import LabelEncoder, StandardScaler\nfrom sklearn.metrics import classification_report, confusion_matrix, accuracy_score\nimport tensorflow as tf\nfrom tensorflow.keras.models import Sequential, Model\nfrom tensorflow.keras.layers import (LSTM, GRU, Dense, Dropout, BatchNormalization, \n                                   Input, Conv1D, MaxPooling1D, GlobalMaxPooling1D,\n                                   MultiHeadAttention, LayerNormalization,\n                                   Concatenate, Bidirectional, TimeDistributed)\nfrom tensorflow.keras.callbacks import EarlyStopping, ReduceLROnPlateau, ModelCheckpoint\nfrom tensorflow.keras.optimizers import Adam\nfrom tensorflow.keras.regularizers import l1_l2\nimport cv2\nimport mediapipe as mp\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nfrom collections import Counter\nimport pickle\nfrom tqdm import tqdm\n\n# Set up MediaPipe\nmp_drawing = mp.solutions.drawing_utils\nmp_drawing_styles = mp.solutions.drawing_styles\nmp_holistic = mp.solutions.holistic\n\nprint(\"✅ All libraries imported successfully\")\nprint(f\"TensorFlow version: {tf.__version__}\")\nprint(f\"GPU available: {tf.config.list_physical_devices('GPU')}\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-18T08:07:19.995634Z","iopub.execute_input":"2025-06-18T08:07:19.996815Z","iopub.status.idle":"2025-06-18T08:07:20.839945Z","shell.execute_reply.started":"2025-06-18T08:07:19.996768Z","shell.execute_reply":"2025-06-18T08:07:20.839125Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# BLOCK 4: Configuration and Constants\n# ====================================================================\n\n# Model configuration\nCONFIG = {\n    'confidence_threshold': 0.7,\n    'tracking_threshold': 0.5,\n    'sequence_length': 30,\n    'batch_size': 32,\n    'epochs': 100,\n    'learning_rate': 0.001,\n    'model_type': 'hybrid',  # 'hybrid', 'transformer', 'cnn_lstm'\n    'test_size': 0.2,\n    'val_size': 0.1\n}\n\n# Feature dimensions for different landmark types\nFEATURE_DIMS = {\n    'face': 468,\n    'pose': 33,\n    'left_hand': 21,\n    'right_hand': 21\n}\n\n# Paths (modify these according to your Kaggle setup)\nPATHS = {\n    'metadata': '/kaggle/input/wlasl-processed/WLASL_v0.3.json',\n    'videos': '/kaggle/input/wlasl-processed/videos',\n    'output': '/kaggle/working/processed_data',\n    'models': '/kaggle/working/models'\n}\n\n# Create directories\nos.makedirs(PATHS['output'], exist_ok=True)\nos.makedirs(PATHS['models'], exist_ok=True)\n\nprint(\"✅ Configuration set up complete\")\nprint(f\"Config: {CONFIG}\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-18T08:07:25.358549Z","iopub.execute_input":"2025-06-18T08:07:25.359618Z","iopub.status.idle":"2025-06-18T08:07:25.367354Z","shell.execute_reply.started":"2025-06-18T08:07:25.359587Z","shell.execute_reply":"2025-06-18T08:07:25.366093Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# BLOCK 5: Utility Functions\n# ====================================================================\n\ndef create_suppress_context():\n    \"\"\"Context manager to suppress TensorFlow warnings\"\"\"\n    class SuppressStderr:\n        def __enter__(self):\n            self._original_stderr = sys.stderr\n            sys.stderr = open(os.devnull, 'w')\n            return self\n        def __exit__(self, exc_type, exc_val, exc_tb):\n            sys.stderr.close()\n            sys.stderr = self._original_stderr\n    return SuppressStderr()\ndef check_data_availability():\n    \"\"\"Check if required data files exist\"\"\"\n    if not os.path.exists(PATHS['metadata']):\n        print(f\"❌ Metadata file not found: {PATHS['metadata']}\")\n        return False\n    \n    if not os.path.exists(PATHS['videos']):\n        print(f\"❌ Videos directory not found: {PATHS['videos']}\")\n        return False\n    \n    video_files = [f for f in os.listdir(PATHS['videos']) if f.endswith('.mp4')]\n    if len(video_files) == 0:\n        print(\"❌ No video files found\")\n        return False\n    \n    print(f\"✅ Found {len(video_files)} video files\")\n    return True\n\n\ndef load_metadata(metadata_path):\n    \"\"\"Load and process WLASL metadata\"\"\"\n    with open(metadata_path, 'r') as file:\n        metadata = json.load(file)\n    \n    label_map = {}\n    for item in metadata:\n        label = item['gloss']\n        for instance in item['instances']:\n            video_id = int(instance['video_id'])\n            frame_start = instance['frame_start']\n            frame_end = instance['frame_end']\n            fps = instance['fps']\n            label_map[video_id] = [label, frame_start, frame_end, fps]\n    \n    print(f\"✅ Loaded metadata for {len(label_map)} videos\")\n    print(f\"Number of unique labels: {len(set([v[0] for v in label_map.values()]))}\")\n    \n    return label_map\n\ndef get_video_files(video_directory):\n    \"\"\"Get list of video files\"\"\"\n    video_files = [f for f in os.listdir(video_directory) if f.endswith('.mp4')]\n    print(f\"✅ Found {len(video_files)} video files\")\n    return video_files\n\nprint(\"✅ Utility functions defined\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-18T08:07:29.040129Z","iopub.execute_input":"2025-06-18T08:07:29.040472Z","iopub.status.idle":"2025-06-18T08:07:29.051748Z","shell.execute_reply.started":"2025-06-18T08:07:29.040447Z","shell.execute_reply":"2025-06-18T08:07:29.050813Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def extract_frame_landmarks(results, frame_number):\n    \"\"\"Extract landmarks from a single frame with enhanced features\"\"\"\n    frame_data = []\n    \n    # Face landmarks\n    if results.face_landmarks:\n        for idx, landmark in enumerate(results.face_landmarks.landmark):\n            frame_data.append({\n                'frame': frame_number,\n                'type': 'face',\n                'landmark_index': idx,\n                'x': landmark.x,\n                'y': landmark.y,\n                'z': landmark.z,\n                'visibility': getattr(landmark, 'visibility', 1.0)\n            })\n    else:\n        for idx in range(FEATURE_DIMS['face']):\n            frame_data.append({\n                'frame': frame_number,\n                'type': 'face',\n                'landmark_index': idx,\n                'x': 0.0, 'y': 0.0, 'z': 0.0, 'visibility': 0.0\n            })\n    \n    # Pose landmarks\n    if results.pose_landmarks:\n        for idx, landmark in enumerate(results.pose_landmarks.landmark):\n            frame_data.append({\n                'frame': frame_number,\n                'type': 'pose',\n                'landmark_index': idx,\n                'x': landmark.x,\n                'y': landmark.y,\n                'z': landmark.z,\n                'visibility': getattr(landmark, 'visibility', 1.0)\n            })\n    else:\n        for idx in range(FEATURE_DIMS['pose']):\n            frame_data.append({\n                'frame': frame_number,\n                'type': 'pose',\n                'landmark_index': idx,\n                'x': 0.0, 'y': 0.0, 'z': 0.0, 'visibility': 0.0\n            })\n    \n    # Hand landmarks\n    for hand_type, landmarks in [('left_hand', results.left_hand_landmarks), \n                               ('right_hand', results.right_hand_landmarks)]:\n        if landmarks:\n            for idx, landmark in enumerate(landmarks.landmark):\n                frame_data.append({\n                    'frame': frame_number,\n                    'type': hand_type,\n                    'landmark_index': idx,\n                    'x': landmark.x,\n                    'y': landmark.y,\n                    'z': landmark.z,\n                    'visibility': getattr(landmark, 'visibility', 1.0)\n                })\n        else:\n            for idx in range(FEATURE_DIMS[hand_type]):\n                frame_data.append({\n                    'frame': frame_number,\n                    'type': hand_type,\n                    'landmark_index': idx,\n                    'x': 0.0, 'y': 0.0, 'z': 0.0, 'visibility': 0.0\n                })\n    \n    return frame_data\n\ndef extract_landmarks_from_video(video_path, start_frame=0, end_frame=-1, fps=30):\n    \"\"\"Extract landmarks from video with optimized processing\"\"\"\n    landmarks_data = []\n    frame_number = 0\n    \n    cap = cv2.VideoCapture(video_path)\n    if not cap.isOpened():\n        print(f\"❌ Error: Could not open video {video_path}\")\n        return pd.DataFrame()\n        \n    cap.set(cv2.CAP_PROP_FPS, fps)\n    \n    with mp_holistic.Holistic(\n        min_detection_confidence=CONFIG['confidence_threshold'],\n        min_tracking_confidence=CONFIG['tracking_threshold'],\n        model_complexity=2\n    ) as holistic:\n        \n        while cap.isOpened():\n            success, image = cap.read()\n            if not success:\n                break\n                \n            frame_number += 1\n            if frame_number < start_frame:\n                continue\n            if end_frame != -1 and frame_number > end_frame:\n                break\n                \n            # Process frame\n            image.flags.writeable = False\n            image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n            results = holistic.process(image)\n            \n            # Extract landmarks\n            frame_landmarks = extract_frame_landmarks(results, frame_number)\n            landmarks_data.extend(frame_landmarks)\n            \n    cap.release()\n    return pd.DataFrame(landmarks_data)\n\nprint(\"✅ Landmark extraction functions defined\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-18T08:07:35.196925Z","iopub.execute_input":"2025-06-18T08:07:35.197239Z","iopub.status.idle":"2025-06-18T08:07:35.211471Z","shell.execute_reply.started":"2025-06-18T08:07:35.197216Z","shell.execute_reply":"2025-06-18T08:07:35.21055Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# BLOCK 7: Data Processing Pipeline\n# ====================================================================\n\ndef process_single_video(video_file, video_directory, label_map, output_directory):\n    \"\"\"Process a single video file\"\"\"\n    video_id = int(os.path.splitext(video_file)[0])\n    \n    if video_id not in label_map:\n        return None\n        \n    label, start_frame, end_frame, fps = label_map[video_id]\n    video_path = os.path.join(video_directory, video_file)\n    \n    # Extract landmarks\n    landmarks_df = extract_landmarks_from_video(video_path, start_frame, end_frame, fps)\n    \n    if landmarks_df.empty:\n        return None\n    \n    # Save landmarks\n    output_path = os.path.join(output_directory, f'{video_id}.parquet')\n    landmarks_df.to_parquet(output_path)\n    \n    return {\n        'video_id': video_id,\n        'landmarks_path': output_path,\n        'label': label,\n        'frame_count': len(landmarks_df['frame'].unique())\n    }\n\ndef process_all_videos(video_directory, label_map, output_directory, max_videos=None):\n    \"\"\"Process all videos with progress tracking\"\"\"\n    video_files = get_video_files(video_directory)\n    \n    if max_videos:\n        video_files = video_files[:max_videos]\n        print(f\"🔄 Processing first {max_videos} videos for testing\")\n    \n    processed_data = []\n    failed_videos = []\n    \n    for i, video_file in enumerate(tqdm(video_files, desc=\"Processing videos\")):\n        try:\n            result = process_single_video(video_file, video_directory, label_map, output_directory)\n            if result:\n                processed_data.append(result)\n            else:\n                failed_videos.append(video_file)\n        except Exception as e:\n            print(f\"❌ Error processing {video_file}: {str(e)}\")\n            failed_videos.append(video_file)\n    \n    print(f\"✅ Successfully processed: {len(processed_data)} videos\")\n    print(f\"❌ Failed to process: {len(failed_videos)} videos\")\n    \n    # Save summary\n    if processed_data:\n        summary_df = pd.DataFrame(processed_data)\n        summary_path = os.path.join(output_directory, 'summary.csv')\n        summary_df.to_csv(summary_path, index=False)\n        print(f\"📊 Summary saved to: {summary_path}\")\n        \n        # Show label distribution\n        label_counts = summary_df['label'].value_counts()\n        print(f\"\\n📈 Label distribution (top 10):\")\n        print(label_counts.head(10))\n    \n    return processed_data\n\nprint(\"✅ Data processing pipeline defined\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-18T08:07:43.509977Z","iopub.execute_input":"2025-06-18T08:07:43.510303Z","iopub.status.idle":"2025-06-18T08:07:43.521172Z","shell.execute_reply.started":"2025-06-18T08:07:43.510278Z","shell.execute_reply":"2025-06-18T08:07:43.520435Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def landmarks_to_array(landmarks_df):\n    \"\"\"Convert landmarks DataFrame to structured numpy array\"\"\"\n    frames = sorted(landmarks_df['frame'].unique())\n    total_features = sum(FEATURE_DIMS.values()) * 4  # x, y, z, visibility\n    \n    landmark_array = np.zeros((len(frames), total_features))\n    \n    for i, frame in enumerate(frames):\n        frame_data = landmarks_df[landmarks_df['frame'] == frame]\n        feature_idx = 0\n        \n        for landmark_type in ['face', 'pose', 'left_hand', 'right_hand']:\n            type_data = frame_data[frame_data['type'] == landmark_type]\n            \n            for j in range(FEATURE_DIMS[landmark_type]):\n                landmark_row = type_data[type_data['landmark_index'] == j]\n                \n                if not landmark_row.empty:\n                    landmark_array[i, feature_idx:feature_idx+4] = [\n                        landmark_row['x'].iloc[0],\n                        landmark_row['y'].iloc[0],\n                        landmark_row['z'].iloc[0],\n                        landmark_row['visibility'].iloc[0]\n                    ]\n                feature_idx += 4\n    \n    return landmark_array\n\ndef add_temporal_features(sequence):\n    \"\"\"Add temporal features like velocity and acceleration\"\"\"\n    # Calculate velocity (first derivative)\n    velocity = np.diff(sequence, axis=0)\n    velocity = np.vstack([velocity[0:1], velocity])  # Pad to maintain shape\n    \n    # Calculate acceleration (second derivative)\n    acceleration = np.diff(velocity, axis=0)\n    acceleration = np.vstack([acceleration[0:1], acceleration])\n    \n    # Combine original features with temporal features\n    enhanced_sequence = np.concatenate([sequence, velocity, acceleration], axis=1)\n    \n    return enhanced_sequence\n\ndef create_sequences_from_processed_data(processed_data, sequence_length=30):\n    \"\"\"Create sequences for training from processed data\"\"\"\n    sequences = []\n    labels = []\n    \n    print(f\"🔄 Creating sequences with length {sequence_length}\")\n    \n    for item in tqdm(processed_data, desc=\"Creating sequences\"):\n        try:\n            # Load landmarks\n            landmarks_df = pd.read_parquet(item['landmarks_path'])\n            label = item['label']\n            \n            # Convert to array\n            landmark_array = landmarks_to_array(landmarks_df)\n            \n            # Create overlapping sequences\n            step_size = max(1, sequence_length // 3)  # 66% overlap\n            for i in range(0, len(landmark_array) - sequence_length + 1, step_size):\n                sequence = landmark_array[i:i + sequence_length]\n                if len(sequence) == sequence_length:\n                    # Add temporal features\n                    enhanced_sequence = add_temporal_features(sequence)\n                    sequences.append(enhanced_sequence)\n                    labels.append(label)\n        except Exception as e:\n            print(f\"❌ Error processing {item['video_id']}: {str(e)}\")\n            continue\n    \n    print(f\"✅ Created {len(sequences)} sequences from {len(processed_data)} videos\")\n    \n    return np.array(sequences), np.array(labels)\n\nprint(\"✅ Feature engineering functions defined\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-18T08:07:49.469469Z","iopub.execute_input":"2025-06-18T08:07:49.469774Z","iopub.status.idle":"2025-06-18T08:07:49.482382Z","shell.execute_reply.started":"2025-06-18T08:07:49.469752Z","shell.execute_reply":"2025-06-18T08:07:49.481159Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def create_hybrid_model(input_shape, num_classes):\n    \"\"\"Create a hybrid model combining CNN, LSTM, and Attention mechanisms\"\"\"\n    inputs = Input(shape=input_shape)\n    \n    # CNN branch for spatial features\n    cnn_branch = Conv1D(128, 3, activation='relu', padding='same')(inputs)\n    cnn_branch = BatchNormalization()(cnn_branch)\n    cnn_branch = Conv1D(256, 3, activation='relu', padding='same')(cnn_branch)\n    cnn_branch = BatchNormalization()(cnn_branch)\n    cnn_branch = MaxPooling1D(2)(cnn_branch)\n    cnn_branch = Dropout(0.3)(cnn_branch)\n    \n    # LSTM branch for temporal features\n    lstm_branch = Bidirectional(LSTM(128, return_sequences=True, dropout=0.3))(inputs)\n    lstm_branch = BatchNormalization()(lstm_branch)\n    lstm_branch = Bidirectional(LSTM(64, return_sequences=True, dropout=0.3))(lstm_branch)\n    \n    # Attention mechanism\n    attention = MultiHeadAttention(num_heads=8, key_dim=64)(lstm_branch, lstm_branch)\n    attention = LayerNormalization()(attention + lstm_branch)\n    \n    # Combine branches\n    combined = Concatenate()([cnn_branch, attention])\n    combined = GlobalMaxPooling1D()(combined)\n    \n    # Classification head\n    dense = Dense(512, activation='relu', kernel_regularizer=l1_l2(0.01, 0.01))(combined)\n    dense = BatchNormalization()(dense)\n    dense = Dropout(0.5)(dense)\n    \n    dense = Dense(256, activation='relu', kernel_regularizer=l1_l2(0.01, 0.01))(dense)\n    dense = BatchNormalization()(dense)\n    dense = Dropout(0.3)(dense)\n    \n    outputs = Dense(num_classes, activation='softmax')(dense)\n    \n    model = Model(inputs=inputs, outputs=outputs)\n    return model\n\ndef create_transformer_model(input_shape, num_classes):\n    \"\"\"Create a transformer-based model for sequence classification\"\"\"\n    inputs = Input(shape=input_shape)\n    \n    # Positional encoding\n    x = Dense(512)(inputs)\n    \n    # Multi-head attention layers\n    for i in range(4):\n        attention_output = MultiHeadAttention(\n            num_heads=8, key_dim=64, dropout=0.1\n        )(x, x)\n        x = LayerNormalization()(x + attention_output)\n        \n        # Feed forward network\n        ffn_output = Dense(2048, activation='relu')(x)\n        ffn_output = Dense(512)(ffn_output)\n        x = LayerNormalization()(x + ffn_output)\n    \n    # Global pooling and classification\n    x = GlobalMaxPooling1D()(x)\n    x = Dense(256, activation='relu')(x)\n    x = Dropout(0.3)(x)\n    outputs = Dense(num_classes, activation='softmax')(x)\n    \n    model = Model(inputs=inputs, outputs=outputs)\n    return model\n\ndef create_cnn_lstm_model(input_shape, num_classes):\n    \"\"\"Create a CNN-LSTM model\"\"\"\n    inputs = Input(shape=input_shape)\n    \n    # CNN layers\n    x = Conv1D(64, 3, activation='relu', padding='same')(inputs)\n    x = BatchNormalization()(x)\n    x = Conv1D(128, 3, activation='relu', padding='same')(x)\n    x = BatchNormalization()(x)\n    x = MaxPooling1D(2)(x)\n    x = Dropout(0.3)(x)\n    \n    # LSTM layers\n    x = LSTM(128, return_sequences=True, dropout=0.3)(x)\n    x = LSTM(64, dropout=0.3)(x)\n    \n    # Dense layers\n    x = Dense(256, activation='relu')(x)\n    x = BatchNormalization()(x)\n    x = Dropout(0.5)(x)\n    \n    outputs = Dense(num_classes, activation='softmax')(x)\n    \n    model = Model(inputs=inputs, outputs=outputs)\n    return model\n\ndef create_model(input_shape, num_classes, model_type='hybrid'):\n    \"\"\"Create model based on specified type\"\"\"\n    if model_type == 'transformer':\n        model = create_transformer_model(input_shape, num_classes)\n    elif model_type == 'cnn_lstm':\n        model = create_cnn_lstm_model(input_shape, num_classes)\n    else:  # hybrid\n        model = create_hybrid_model(input_shape, num_classes)\n    \n    # Compile model\n    optimizer = Adam(learning_rate=CONFIG['learning_rate'])\n    model.compile(\n        optimizer=optimizer,\n        loss='sparse_categorical_crossentropy',\n        metrics=['accuracy']\n    )\n    \n    return model\n\nprint(\"✅ Model architecture functions defined\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-18T08:07:54.80841Z","iopub.execute_input":"2025-06-18T08:07:54.808981Z","iopub.status.idle":"2025-06-18T08:07:54.825115Z","shell.execute_reply.started":"2025-06-18T08:07:54.808957Z","shell.execute_reply":"2025-06-18T08:07:54.824136Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def prepare_training_data(sequences, labels):\n    \"\"\"Prepare data for training with proper encoding and filtering\"\"\"\n    print(\"🔄 Preparing training data...\")\n    \n    # Create label counts\n    label_counts = Counter(labels)\n    print(f\"Total unique labels: {len(label_counts)}\")\n    \n    # Filter classes with insufficient samples\n    min_samples = CONFIG['min_samples_per_class']\n    valid_labels = [label for label, count in label_counts.items() if count >= min_samples]\n    \n    # Filter sequences and labels\n    filtered_sequences = []\n    filtered_labels = []\n    \n    for seq, label in zip(sequences, labels):\n        if label in valid_labels:\n            filtered_sequences.append(seq)\n            filtered_labels.append(label)\n    \n    sequences = np.array(filtered_sequences)\n    labels = np.array(filtered_labels)\n    \n    print(f\"After filtering: {len(sequences)} sequences, {len(set(labels))} classes\")\n    \n    # Encode labels\n    label_encoder = LabelEncoder()\n    encoded_labels = label_encoder.fit_transform(labels)\n    \n    # Split data\n    X_train, X_test, y_train, y_test = train_test_split(\n        sequences, encoded_labels, \n        test_size=CONFIG['test_size'], \n        random_state=42, \n        stratify=encoded_labels\n    )\n    \n    X_train, X_val, y_train, y_val = train_test_split(\n        X_train, y_train, \n        test_size=CONFIG['val_size']/(1-CONFIG['test_size']), \n        random_state=42, \n        stratify=y_train\n    )\n    \n    print(f\"Training set: {X_train.shape}\")\n    print(f\"Validation set: {X_val.shape}\")\n    print(f\"Test set: {X_test.shape}\")\n    \n    return (X_train, X_val, X_test, y_train, y_val, y_test, label_encoder)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-18T08:07:59.762901Z","iopub.execute_input":"2025-06-18T08:07:59.763675Z","iopub.status.idle":"2025-06-18T08:07:59.772105Z","shell.execute_reply.started":"2025-06-18T08:07:59.763647Z","shell.execute_reply":"2025-06-18T08:07:59.771079Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def train_model(X_train, X_val, y_train, y_val, num_classes, model_type='hybrid'):\n    \"\"\"Train the model with callbacks and monitoring\"\"\"\n    print(f\"🔄 Training {model_type} model...\")\n    \n    # Create model\n    input_shape = (X_train.shape[1], X_train.shape[2])\n    model = create_model(input_shape, num_classes, model_type)\n    \n    print(f\"Model input shape: {input_shape}\")\n    print(f\"Number of classes: {num_classes}\")\n    print(f\"Model parameters: {model.count_params():,}\")\n    \n    # Callbacks\n    callbacks = [\n        EarlyStopping(\n            monitor='val_accuracy',\n            patience=15,\n            restore_best_weights=True,\n            verbose=1\n        ),\n        ReduceLROnPlateau(\n            monitor='val_loss',\n            factor=0.5,\n            patience=8,\n            min_lr=1e-7,\n            verbose=1\n        ),\n        ModelCheckpoint(\n            os.path.join(PATHS['models'], f'best_{model_type}_model.h5'),\n            monitor='val_accuracy',\n            save_best_only=True,\n            verbose=1\n        )\n    ]\n    \n    # Train model\n    history = model.fit(\n        X_train, y_train,\n        batch_size=CONFIG['batch_size'],\n        epochs=CONFIG['epochs'],\n        validation_data=(X_val, y_val),\n        callbacks=callbacks,\n        verbose=1\n    )\n    \n    return model, history\n\ndef evaluate_model(model, X_test, y_test, label_encoder):\n    \"\"\"Evaluate model performance\"\"\"\n    print(\"🔄 Evaluating model...\")\n    \n    # Predictions\n    y_pred = model.predict(X_test)\n    y_pred_classes = np.argmax(y_pred, axis=1)\n    \n    # Accuracy\n    accuracy = accuracy_score(y_test, y_pred_classes)\n    print(f\"Test Accuracy: {accuracy:.4f}\")\n    \n    # Classification report\n    target_names = label_encoder.classes_\n    report = classification_report(y_test, y_pred_classes, target_names=target_names)\n    print(\"\\nClassification Report:\")\n    print(report)\n    \n    # Confusion matrix\n    cm = confusion_matrix(y_test, y_pred_classes)\n    plt.figure(figsize=(12, 10))\n    sns.heatmap(cm, annot=True, fmt='d', cmap='Blues', \n                xticklabels=target_names, yticklabels=target_names)\n    plt.title('Confusion Matrix')\n    plt.ylabel('True Label')\n    plt.xlabel('Predicted Label')\n    plt.xticks(rotation=45)\n    plt.yticks(rotation=0)\n    plt.tight_layout()\n    plt.savefig(os.path.join(PATHS['models'], 'confusion_matrix.png'), dpi=300, bbox_inches='tight')\n    plt.show()\n    \n    return accuracy, report","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-18T08:08:04.794691Z","iopub.execute_input":"2025-06-18T08:08:04.795044Z","iopub.status.idle":"2025-06-18T08:08:04.805442Z","shell.execute_reply.started":"2025-06-18T08:08:04.79502Z","shell.execute_reply":"2025-06-18T08:08:04.804278Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"CONFIG['min_samples_per_class'] = 5  # Add this to your CONFIG dict\nCONFIG['max_videos_for_demo'] = 50   # Add this for demo purposes\n\ndef main():\n    \"\"\"Main execution function using only defined functions\"\"\"\n    print(\"🚀 Starting ASL Recognition Pipeline\")\n    print(\"=\" * 60)\n    \n    # Step 1: Check data availability\n    if not check_data_availability():\n        print(\"❌ Cannot proceed without required data files\")\n        return\n    \n    # Step 2: Load metadata\n    print(\"\\n📂 Loading metadata...\")\n    label_map = load_metadata(PATHS['metadata'])\n    if not label_map:\n        print(\"❌ Failed to load metadata\")\n        return\n    \n    # Step 3: Process videos (using defined functions)\n    print(\"\\n🎬 Processing videos...\")\n    processed_data = process_all_videos(\n        PATHS['videos'], \n        label_map, \n        PATHS['output'],\n        CONFIG['max_videos_for_demo']  # Limit for demo\n    )\n    \n    if not processed_data:\n        print(\"❌ No videos were successfully processed\")\n        return\n    \n    # Step 4: Create sequences from processed data\n    print(\"\\n🔧 Creating sequences...\")\n    sequences, labels = create_sequences_from_processed_data(\n        processed_data, \n        CONFIG['sequence_length']\n    )\n    \n    if len(sequences) == 0:\n        print(\"❌ No sequences were created\")\n        return\n    \n    # Step 5: Prepare training data\n    print(\"\\n📊 Preparing training data...\")\n    X_train, X_val, X_test, y_train, y_val, y_test, label_encoder = prepare_training_data(\n        sequences, labels\n    )\n    \n    num_classes = len(label_encoder.classes_)\n    print(f\"Number of classes: {num_classes}\")\n    \n    # Step 6: Train model\n    print(\"\\n🏋️ Training model...\")\n    model, history = train_model(\n        X_train, X_val, y_train, y_val, \n        num_classes, \n        CONFIG['model_type']\n    )\n    \n    # Step 7: Evaluate model\n    print(\"\\n📈 Evaluating model...\")\n    accuracy, report = evaluate_model(model, X_test, y_test, label_encoder)\n    \n    # Step 8: Save model and results\n    print(\"\\n💾 Saving model and results...\")\n    model_path = os.path.join(PATHS['models'], 'final_asl_model.h5')\n    encoder_path = os.path.join(PATHS['models'], 'label_encoder.pkl')\n    \n    model.save(model_path)\n    with open(encoder_path, 'wb') as f:\n        pickle.dump(label_encoder, f)\n    \n    # Save training history\n    history_path = os.path.join(PATHS['models'], 'training_history.pkl')\n    with open(history_path, 'wb') as f:\n        pickle.dump(history.history, f)\n    \n    print(f\"\\n✅ Pipeline completed successfully!\")\n    print(f\"Final accuracy: {accuracy:.4f}\")\n    print(f\"Model saved to: {model_path}\")\n    print(f\"Label encoder saved to: {encoder_path}\")\n    print(f\"Training history saved to: {history_path}\")\n    \n    # Plot training history\n    plt.figure(figsize=(12, 4))\n    \n    plt.subplot(1, 2, 1)\n    plt.plot(history.history['accuracy'], label='Training Accuracy')\n    plt.plot(history.history['val_accuracy'], label='Validation Accuracy')\n    plt.title('Model Accuracy')\n    plt.xlabel('Epoch')\n    plt.ylabel('Accuracy')\n    plt.legend()\n    \n    plt.subplot(1, 2, 2)\n    plt.plot(history.history['loss'], label='Training Loss')\n    plt.plot(history.history['val_loss'], label='Validation Loss')\n    plt.title('Model Loss')\n    plt.xlabel('Epoch')\n    plt.ylabel('Loss')\n    plt.legend()\n    \n    plt.tight_layout()\n    plt.savefig(os.path.join(PATHS['models'], 'training_history.png'), dpi=300, bbox_inches='tight')\n    plt.show()\n\n# Run the main function\nmain()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-18T08:08:38.988877Z","iopub.execute_input":"2025-06-18T08:08:38.989195Z","iopub.status.idle":"2025-06-18T08:08:39.170798Z","shell.execute_reply.started":"2025-06-18T08:08:38.989176Z","shell.execute_reply":"2025-06-18T08:08:39.16962Z"}},"outputs":[],"execution_count":null}]}