Spaces:
Runtime error
Runtime error
| import numpy as np | |
| import cv2 | |
| import pandas as pd | |
| from sklearn.model_selection import train_test_split | |
| from src import data, features, model, augmentation | |
| def process_dataset_with_augmentation(df, is_training=False): | |
| #Loops through the dataframe. | |
| #If is_training=True, it augments minority classes to balance the data. | |
| X = [] | |
| y = [] | |
| # 1. Calculate Statistics for Balancing (Only needed for training) | |
| if is_training: | |
| class_counts = df['target'].value_counts().to_dict() | |
| max_count = max(class_counts.values()) | |
| print(f" [Augmentation] Balancing classes to match majority count: {max_count}") | |
| total = len(df) | |
| for idx, row in df.iterrows(): | |
| if idx % 100 == 0: print(f" Processing image {idx}/{total}...") | |
| # Load Original Image | |
| img = cv2.imread(row['path']) | |
| if img is None: continue | |
| # A. Extract Features for Original Image | |
| feats = features.extract_all_features_pipeline(img) | |
| if feats is not None: | |
| X.append(feats) | |
| y.append(row['label_idx']) | |
| # B. Augmentation Logic (Training Only) | |
| if is_training: | |
| # Check how many extra copies we need | |
| class_name = row['target'] | |
| # Calculate factor. e.g., if factor is 5, we generate 4 NEW images | |
| # so total = 1 original + 4 augmented = 5 | |
| factor = augmentation.get_augmentation_factor(class_name, class_counts, max_count) | |
| num_new_images = factor - 1 | |
| if num_new_images > 0: | |
| # Generate variations | |
| aug_imgs = augmentation.generate_augmented_images(img, count=num_new_images) | |
| # Extract features for every augmented variation | |
| for aug_img in aug_imgs: | |
| aug_feats = features.extract_all_features_pipeline(aug_img) | |
| if aug_feats is not None: | |
| X.append(aug_feats) | |
| y.append(row['label_idx']) | |
| return np.array(X), np.array(y) | |
| def main(): | |
| #This is the starting point of the training. | |
| #It produces -between others- plots and a model saved in serialized format (classes.pkl) | |
| # 1. Load Data (Metadata only) | |
| df, classes = data.load_metadata(limit=None) # Adjust limit as needed | |
| print("-" * 50) | |
| print("STEP 1: Splitting Data (Train/Test) on File Paths") | |
| print("-" * 50) | |
| # Split DataFrame FIRST to avoid data leakage | |
| df_train, df_test = train_test_split( | |
| df, test_size=0.1, stratify=df['label_idx'] | |
| ) | |
| print(f"Training Samples (Files): {len(df_train)}") | |
| print(f"Test Samples (Files): {len(df_test)}") | |
| # 2. Process Test Data (No Augmentation, just feature extraction) | |
| print("\n" + "-" * 50) | |
| print("STEP 2: Extracting Test Features (Standard)") | |
| print("-" * 50) | |
| X_test, y_test = process_dataset_with_augmentation(df_test, is_training=False) | |
| # 3. Process Training Data (WITH Augmentation) | |
| print("\n" + "-" * 50) | |
| print("STEP 3: Extracting Training Features (With Keras Augmentation)") | |
| print("-" * 50) | |
| X_train, y_train = process_dataset_with_augmentation(df_train, is_training=True) | |
| print(f"\nFinal Feature Matrix Shapes:") | |
| print(f"X_train: {X_train.shape}, y_train: {y_train.shape}") | |
| print(f"X_test: {X_test.shape}, y_test: {y_test.shape}") | |
| # 4. Train & Evaluate | |
| # We pass the pre-split arrays directly to a modified train function | |
| if len(X_train) > 0 and len(X_test) > 0: | |
| model.train_and_evaluate_split(X_train, y_train, X_test, y_test, classes) | |
| else: | |
| print("Error: Feature extraction failed.") | |
| if __name__ == "__main__": | |
| main() |