{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":112070,"databundleVersionId":13354591,"sourceType":"competition"}],"dockerImageVersionId":31089,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import tensorflow as tf\nfrom tensorflow.keras import layers, models\nfrom tensorflow.keras.applications import MobileNetV2\nimport numpy as np\nimport glob\nimport random\n\n# Ruta a las imágenes\nDATA_PATH = '/kaggle/input/facial-recognition-7th-gen/Fotos Grupo/'\nstudent_folders = sorted(glob.glob(DATA_PATH + '*/'))\nclass_names = [p.split('/')[-2] for p in student_folders]\nlabel_map = {name: i for i, name in enumerate(class_names)}\nnum_classes = len(class_names)\n\nprint(f\"Se encontraron {num_classes} clases (alumnos): {class_names}\")\n\n# Preparar los datos\ntrain_paths, train_labels, test_paths, test_labels = [], [], [], []\n\nfor student_folder in student_folders:\n    student_name = student_folder.split('/')[-2]\n    image_paths = glob.glob(student_folder + '*.jpg')\n    random.shuffle(image_paths)\n    \n    current_train_paths = image_paths[:20]\n    current_test_paths = image_paths[20:]\n    \n    num_train_images = len(current_train_paths)\n    num_test_images = len(current_test_paths)\n    \n    train_paths.extend(current_train_paths)\n    test_paths.extend(current_test_paths)\n    \n    train_labels.extend([label_map[student_name]] * num_train_images)\n    test_labels.extend([label_map[student_name]] * num_test_images)\n\n# Parámetros\nIMG_SIZE = 160\nBATCH_SIZE = 32\n\n# Función de preprocesamiento\ndef load_and_preprocess_image(path, label):\n    image = tf.io.read_file(path)\n    image = tf.image.decode_jpeg(image, channels=3)\n    image = tf.image.resize(image, [IMG_SIZE, IMG_SIZE])\n    image = image / 255.0\n    return image, label\n\n# Crear datasets\ntrain_dataset = tf.data.Dataset.from_tensor_slices((train_paths, train_labels))\ntrain_dataset = train_dataset.shuffle(len(train_paths)).map(load_and_preprocess_image).batch(BATCH_SIZE).prefetch(tf.data.AUTOTUNE)\n\ntest_dataset = tf.data.Dataset.from_tensor_slices((test_paths, test_labels))\ntest_dataset = test_dataset.map(load_and_preprocess_image).batch(BATCH_SIZE).prefetch(tf.data.AUTOTUNE)\n\n# Modelo base (más rápido que EfficientNet)\nbase_model = MobileNetV2(include_top=False, weights='imagenet', input_shape=(IMG_SIZE, IMG_SIZE, 3))\nbase_model.trainable = False\n\n# Construcción del modelo\ninputs = layers.Input(shape=(IMG_SIZE, IMG_SIZE, 3))\nx = base_model(inputs, training=False)\nx = layers.GlobalAveragePooling2D()(x)\nx = layers.Dropout(0.2)(x)\noutputs = layers.Dense(num_classes, activation='softmax')(x)\nmodel = models.Model(inputs, outputs)\n\nmodel.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])\nmodel.summary()\n\n# Entrenar\nhistory = model.fit(\n    train_dataset,\n    epochs=10,\n    validation_data=test_dataset\n)\n\n# Guardar el modelo con el nombre 'arnold.h5'\nmodel.save('arnold.h5')\nprint(\"Modelo guardado como 'arnold.h5'\")\n","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-08-12T00:55:19.810972Z","iopub.execute_input":"2025-08-12T00:55:19.811235Z","iopub.status.idle":"2025-08-12T00:58:10.800101Z","shell.execute_reply.started":"2025-08-12T00:55:19.811213Z","shell.execute_reply":"2025-08-12T00:58:10.798976Z"}},"outputs":[],"execution_count":null}]}