Spaces:
Build error
Build error
Varsha Dewangan
commited on
Commit
·
ee1d4aa
0
Parent(s):
Initial clean commit for project deployment
Browse files- .gitattributes +35 -0
- .gitignore +30 -0
- Dockerfile +65 -0
- README.md +147 -0
- file.py +235 -0
- paths_to_forget.txt +6 -0
- requirements.txt +19 -0
- src/__init__.py +0 -0
- src/app.py +146 -0
- src/config.py +108 -0
- src/data_preprocessing.py +247 -0
- src/evaluation.py +691 -0
- src/inference_api.py +124 -0
- src/model.py +502 -0
- src/train.py +471 -0
- src/utils.py +571 -0
- templates/auth.html +1283 -0
- templates/index - Copy.txt +1343 -0
- templates/index.html +1766 -0
- text_files/bleu_metrics.csv +30 -0
- text_files/file.py +64 -0
- text_files/scores.py +72 -0
- text_files/training (2).txt +335 -0
- text_files/training_log_17_27.txt +806 -0
- text_files/training_log_1_18.txt +668 -0
- text_files/training_log_21_30.txt +734 -0
- text_files/training_metrics.csv +1190 -0
- text_files/validation_metrics.csv +30 -0
- text_files/validation_script.py +77 -0
- web_app.py +650 -0
.gitattributes
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
*.7z filter=lfs diff=lfs merge=lfs -text
|
| 2 |
+
*.arrow filter=lfs diff=lfs merge=lfs -text
|
| 3 |
+
*.bin filter=lfs diff=lfs merge=lfs -text
|
| 4 |
+
*.bz2 filter=lfs diff=lfs merge=lfs -text
|
| 5 |
+
*.ckpt filter=lfs diff=lfs merge=lfs -text
|
| 6 |
+
*.ftz filter=lfs diff=lfs merge=lfs -text
|
| 7 |
+
*.gz filter=lfs diff=lfs merge=lfs -text
|
| 8 |
+
*.h5 filter=lfs diff=lfs merge=lfs -text
|
| 9 |
+
*.joblib filter=lfs diff=lfs merge=lfs -text
|
| 10 |
+
*.lfs.* filter=lfs diff=lfs merge=lfs -text
|
| 11 |
+
*.mlmodel filter=lfs diff=lfs merge=lfs -text
|
| 12 |
+
*.model filter=lfs diff=lfs merge=lfs -text
|
| 13 |
+
*.msgpack filter=lfs diff=lfs merge=lfs -text
|
| 14 |
+
*.npy filter=lfs diff=lfs merge=lfs -text
|
| 15 |
+
*.npz filter=lfs diff=lfs merge=lfs -text
|
| 16 |
+
*.onnx filter=lfs diff=lfs merge=lfs -text
|
| 17 |
+
*.ot filter=lfs diff=lfs merge=lfs -text
|
| 18 |
+
*.parquet filter=lfs diff=lfs merge=lfs -text
|
| 19 |
+
*.pb filter=lfs diff=lfs merge=lfs -text
|
| 20 |
+
*.pickle filter=lfs diff=lfs merge=lfs -text
|
| 21 |
+
*.pkl filter=lfs diff=lfs merge=lfs -text
|
| 22 |
+
*.pt filter=lfs diff=lfs merge=lfs -text
|
| 23 |
+
*.pth filter=lfs diff=lfs merge=lfs -text
|
| 24 |
+
*.rar filter=lfs diff=lfs merge=lfs -text
|
| 25 |
+
*.safetensors filter=lfs diff=lfs merge=lfs -text
|
| 26 |
+
saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
| 27 |
+
*.tar.* filter=lfs diff=lfs merge=lfs -text
|
| 28 |
+
*.tar filter=lfs diff=lfs merge=lfs -text
|
| 29 |
+
*.tflite filter=lfs diff=lfs merge=lfs -text
|
| 30 |
+
*.tgz filter=lfs diff=lfs merge=lfs -text
|
| 31 |
+
*.wasm filter=lfs diff=lfs merge=lfs -text
|
| 32 |
+
*.xz filter=lfs diff=lfs merge=lfs -text
|
| 33 |
+
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
+
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
+
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
.gitignore
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Database
|
| 2 |
+
instance/
|
| 3 |
+
*.db
|
| 4 |
+
|
| 5 |
+
# Uploaded files
|
| 6 |
+
static/uploads/
|
| 7 |
+
|
| 8 |
+
# Output/Log files
|
| 9 |
+
output/
|
| 10 |
+
# Specific large model file if you have it in your root and don't want it tracked
|
| 11 |
+
yolov8x-seg.pt
|
| 12 |
+
models/*.pth
|
| 13 |
+
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
data/images/ # Add this line
|
| 17 |
+
|
| 18 |
+
# Python cache and environment files
|
| 19 |
+
__pycache__/
|
| 20 |
+
*.pyc
|
| 21 |
+
.env
|
| 22 |
+
venv/
|
| 23 |
+
.ipynb_checkpoints/
|
| 24 |
+
|
| 25 |
+
# MacOS specific files
|
| 26 |
+
.DS_Store
|
| 27 |
+
|
| 28 |
+
# Jupyter Notebook files
|
| 29 |
+
.ipynb_checkpoints/
|
| 30 |
+
|
Dockerfile
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# ==============================================================================
|
| 2 |
+
# Dockerfile for Perceptra AI (Image Captioning & Segmentation App)
|
| 3 |
+
# Optimized for deployment on Hugging Face Spaces with GPU support.
|
| 4 |
+
# ==============================================================================
|
| 5 |
+
|
| 6 |
+
# -- Stage 1: Base Image and System Dependencies --
|
| 7 |
+
# Start with a stable Python version. 3.9 is a good choice for broad compatibility.
|
| 8 |
+
# Using the 'slim' variant to keep the image size smaller.
|
| 9 |
+
FROM python:3.9-slim
|
| 10 |
+
|
| 11 |
+
# Set the working directory inside the container. All subsequent commands
|
| 12 |
+
# will run from this path.
|
| 13 |
+
WORKDIR /app
|
| 14 |
+
|
| 15 |
+
# Set environment variables to prevent Python from writing .pyc files and to
|
| 16 |
+
# ensure output is sent straight to the console without buffering.
|
| 17 |
+
ENV PYTHONDONTWRITEBYTECODE 1
|
| 18 |
+
ENV PYTHONUNBUFFERED 1
|
| 19 |
+
|
| 20 |
+
# Install essential system dependencies. Many Python libraries, especially for
|
| 21 |
+
# computer vision, have underlying system requirements.
|
| 22 |
+
# - build-essential & cmake: Needed to compile libraries like dlib (for face-recognition).
|
| 23 |
+
# - libgl1-mesa-glx, libglib2.0-0, etc.: Required by OpenCV for image processing in a headless environment.
|
| 24 |
+
RUN apt-get update && apt-get install -y --no-install-recommends \
|
| 25 |
+
build-essential \
|
| 26 |
+
cmake \
|
| 27 |
+
libgl1-mesa-glx \
|
| 28 |
+
libglib2.0-0 \
|
| 29 |
+
libsm6 \
|
| 30 |
+
libxext6 \
|
| 31 |
+
libxrender-dev \
|
| 32 |
+
&& rm -rf /var/lib/apt/lists/*
|
| 33 |
+
|
| 34 |
+
# -- Stage 2: Python Dependencies --
|
| 35 |
+
# First, copy only the requirements.txt file. This allows Docker to cache the
|
| 36 |
+
# installed packages. The layer will only be re-built if requirements.txt changes.
|
| 37 |
+
COPY requirements.txt .
|
| 38 |
+
|
| 39 |
+
# Install the Python packages specified in requirements.txt.
|
| 40 |
+
# --no-cache-dir: Reduces the image size by not storing the pip cache.
|
| 41 |
+
RUN pip install --no-cache-dir -r requirements.txt
|
| 42 |
+
|
| 43 |
+
# -- Stage 3: Application Code & Models --
|
| 44 |
+
# Copy the rest of your application's source code into the container.
|
| 45 |
+
# This includes web_app.py, the 'src' directory, and the 'templates' directory.
|
| 46 |
+
COPY . .
|
| 47 |
+
|
| 48 |
+
# Optimization: Pre-download the large YOLO model during the build process.
|
| 49 |
+
# This makes the application start much faster on Hugging Face Spaces, as it
|
| 50 |
+
# won't need to download the model on every startup.
|
| 51 |
+
RUN python -c "from ultralytics import YOLO; YOLO('yolov8x-seg.pt')"
|
| 52 |
+
|
| 53 |
+
# -- Stage 4: Runtime Configuration --
|
| 54 |
+
# Expose the port the app will run on. Hugging Face Spaces will automatically
|
| 55 |
+
# map this to the public URL. Gunicorn will run on this port.
|
| 56 |
+
# The default Flask port is 5000, which we'll use here.
|
| 57 |
+
EXPOSE 7860
|
| 58 |
+
|
| 59 |
+
# The command to run your application using Gunicorn, a production-ready
|
| 60 |
+
# WSGI server. This is the standard way to run Flask apps in production.
|
| 61 |
+
# - --workers 2: Starts 2 worker processes to handle requests. Adjust as needed.
|
| 62 |
+
# - --bind 0.0.0.0:5000: Binds to all network interfaces on port 5000.
|
| 63 |
+
# - web_app:app: Tells Gunicorn to look for the Flask instance named 'app'
|
| 64 |
+
# inside the 'web_app.py' file.
|
| 65 |
+
CMD ["gunicorn", "--workers", "2", "--bind", "0.0.0.0:7860", "web_app:app"]
|
README.md
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Image Captioning with Attention
|
| 2 |
+
This project implements an image captioning model using a ResNet50-based CNN Encoder and an LSTM Decoder with Bahdanau-style Attention. The model is trained on the COCO 2017 dataset to generate descriptive captions for images.
|
| 3 |
+
|
| 4 |
+
Features
|
| 5 |
+
Modular Architecture: Separated concerns into distinct Python files for clarity and maintainability.
|
| 6 |
+
|
| 7 |
+
CNN Encoder: Utilizes a pre-trained ResNet50 for robust feature extraction.
|
| 8 |
+
|
| 9 |
+
Attention Mechanism: Allows the model to focus on salient regions of an image when generating specific words.
|
| 10 |
+
|
| 11 |
+
LSTM Decoder: Generates captions word by word, conditioned on image features and previously generated words.
|
| 12 |
+
|
| 13 |
+
Beam Search: Implemented for high-quality caption generation during inference.
|
| 14 |
+
|
| 15 |
+
Comprehensive Evaluation: Calculates standard metrics like BLEU (1-4), METEOR, ROUGE-L, and CIDEr.
|
| 16 |
+
|
| 17 |
+
Training Resumption: Ability to resume training from the latest checkpoint.
|
| 18 |
+
|
| 19 |
+
Logging: Detailed logging for training progress and evaluation results.
|
| 20 |
+
|
| 21 |
+
Project Structure
|
| 22 |
+
ImageCaptioning/
|
| 23 |
+
├── data/
|
| 24 |
+
│ ├── coco/
|
| 25 |
+
│ │ ├── train2017/ # COCO 2017 training images
|
| 26 |
+
│ │ ├── val2017/ # COCO 2017 validation images
|
| 27 |
+
│ │ └── annotations/
|
| 28 |
+
│ │ ├── captions_train2017.json # Training captions JSON
|
| 29 |
+
│ │ └── captions_val2017.json # Validation captions JSON
|
| 30 |
+
├── models/ # Directory for saving trained model checkpoints
|
| 31 |
+
│ └── (e.g., best_model_bleu0.1037.pth)
|
| 32 |
+
├── src/
|
| 33 |
+
│ ├── app.py # Main script for running inference
|
| 34 |
+
│ ├── config.py # Configuration parameters for training, eval, inference
|
| 35 |
+
│ ├── data_preprocessing.py # Classes for vocabulary and dataset loading
|
| 36 |
+
│ ├── model.py # Defines the Encoder, Attention, and Decoder modules
|
| 37 |
+
│ ├── train.py # Contains the training loop and validation functions
|
| 38 |
+
│ ├── evaluation.py # Functions for calculating various evaluation metrics
|
| 39 |
+
│ └── utils.py # General utility functions (e.g., logging setup, attention visualization)
|
| 40 |
+
├── output/ # Output directory for logs, saved vocabulary, and evaluation results
|
| 41 |
+
├── requirements.txt # List of Python dependencies
|
| 42 |
+
└── README.md # This file
|
| 43 |
+
|
| 44 |
+
Setup
|
| 45 |
+
Follow these steps to set up the project locally.
|
| 46 |
+
|
| 47 |
+
1. Clone the Repository
|
| 48 |
+
git clone https://github.com/YourUsername/ImageCaptioning.git # Replace with your repo URL
|
| 49 |
+
cd ImageCaptioning
|
| 50 |
+
|
| 51 |
+
2. Create a Python Virtual Environment (Recommended)
|
| 52 |
+
python -m venv venv
|
| 53 |
+
# On Windows
|
| 54 |
+
.\venv\Scripts\activate
|
| 55 |
+
# On macOS/Linux
|
| 56 |
+
source venv/bin/activate
|
| 57 |
+
|
| 58 |
+
3. Install Dependencies
|
| 59 |
+
Install the required Python packages. Note that pycocoevalcap needs to be installed directly from its GitHub repository as it's not on PyPI.
|
| 60 |
+
|
| 61 |
+
pip install -r requirements.txt
|
| 62 |
+
|
| 63 |
+
4. Download NLTK Data
|
| 64 |
+
The evaluation metrics (BLEU, METEOR) require NLTK's punkt and wordnet data.
|
| 65 |
+
|
| 66 |
+
import nltk
|
| 67 |
+
nltk.download('punkt')
|
| 68 |
+
nltk.download('wordnet')
|
| 69 |
+
|
| 70 |
+
5. Download COCO 2017 Dataset
|
| 71 |
+
You'll need the COCO 2017 dataset.
|
| 72 |
+
|
| 73 |
+
Images:
|
| 74 |
+
|
| 75 |
+
train2017.zip (around 18GB): http://images.cocodataset.org/zips/train2017.zip
|
| 76 |
+
|
| 77 |
+
val2017.zip (around 1GB): http://images.cocodataset.org/zips/val2017.zip
|
| 78 |
+
|
| 79 |
+
Annotations:
|
| 80 |
+
|
| 81 |
+
annotations_trainval2017.zip (around 250MB): http://images.cocodataset.org/annotations/annotations_trainval2017.zip
|
| 82 |
+
|
| 83 |
+
After downloading:
|
| 84 |
+
|
| 85 |
+
Create the data/coco directory if it doesn't exist.
|
| 86 |
+
|
| 87 |
+
Extract train2017.zip into data/coco/train2017/.
|
| 88 |
+
|
| 89 |
+
Extract val2017.zip into data/coco/val2017/.
|
| 90 |
+
|
| 91 |
+
Extract annotations_trainval2017.zip into data/coco/annotations/. This will create captions_train2017.json and captions_val2017.json (among others).
|
| 92 |
+
|
| 93 |
+
Your data/coco directory should then look like this:
|
| 94 |
+
|
| 95 |
+
data/coco/
|
| 96 |
+
├── train2017/
|
| 97 |
+
├── val2017/
|
| 98 |
+
└── annotations/
|
| 99 |
+
├── captions_train2017.json
|
| 100 |
+
└── captions_val2017.json
|
| 101 |
+
└── ... (other annotation files)
|
| 102 |
+
|
| 103 |
+
Usage
|
| 104 |
+
1. Configure Parameters
|
| 105 |
+
All configurable parameters are located in src/config.py. Open this file and adjust paths, hyperparameters, and other settings as needed.
|
| 106 |
+
|
| 107 |
+
data_folder: Ensure this points to the data/coco directory.
|
| 108 |
+
|
| 109 |
+
model_path: Update this to the path of your trained model (e.g., models/best_model_bleu0.1037.pth if you've already trained one or downloaded a pre-trained model).
|
| 110 |
+
|
| 111 |
+
2. Train the Model
|
| 112 |
+
To start or resume training, run the train.py script:
|
| 113 |
+
|
| 114 |
+
python src/train.py
|
| 115 |
+
|
| 116 |
+
Training logs, model checkpoints, and a saved vocabulary file will be stored in the output/ directory. The best model (based on BLEU-4 score) will be saved in the models/ directory.
|
| 117 |
+
|
| 118 |
+
3. Evaluate the Model
|
| 119 |
+
After training, you can evaluate the model's performance on the validation set:
|
| 120 |
+
|
| 121 |
+
python src/evaluation.py
|
| 122 |
+
|
| 123 |
+
This will generate captions for the test set and calculate various metrics. The detailed results will be saved in the output/evaluation_results/ directory.
|
| 124 |
+
|
| 125 |
+
4. Run Inference (Generate Caption for a Single Image)
|
| 126 |
+
To generate a caption for a specific image, run the app.py script. Make sure src/config.py has the correct model_path and example_image_path set.
|
| 127 |
+
|
| 128 |
+
python src/app.py
|
| 129 |
+
|
| 130 |
+
The generated caption will be printed to the console. You can modify inference_config in src/config.py to change the beam_size or max_caption_length.
|
| 131 |
+
|
| 132 |
+
Pre-trained Models
|
| 133 |
+
(Optional: If you plan to provide pre-trained models, you would include instructions here on how users can download and place them in the models/ directory.)
|
| 134 |
+
|
| 135 |
+
Future Improvements
|
| 136 |
+
Implement a web interface (e.g., using Flask or FastAPI) for interactive captioning.
|
| 137 |
+
|
| 138 |
+
Explore different CNN backbones (e.g., EfficientNet, Vision Transformers).
|
| 139 |
+
|
| 140 |
+
Integrate advanced attention mechanisms or transformer architectures.
|
| 141 |
+
|
| 142 |
+
Add support for more datasets.
|
| 143 |
+
|
| 144 |
+
Quantization or pruning for model optimization.
|
| 145 |
+
|
| 146 |
+
License
|
| 147 |
+
(Add your chosen license, e.g., MIT, Apache 2.0)
|
file.py
ADDED
|
@@ -0,0 +1,235 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import cv2
|
| 2 |
+
import numpy as np
|
| 3 |
+
import torch
|
| 4 |
+
from PIL import Image
|
| 5 |
+
from sklearn.metrics import (jaccard_score, f1_score,
|
| 6 |
+
accuracy_score, precision_score,
|
| 7 |
+
recall_score)
|
| 8 |
+
from scipy.spatial.distance import directed_hausdorff
|
| 9 |
+
|
| 10 |
+
# MUST BE FIRST STREAMLIT COMMAND
|
| 11 |
+
import streamlit as st
|
| 12 |
+
st.set_page_config(
|
| 13 |
+
page_title="Advanced Segmentation Metrics Analyzer",
|
| 14 |
+
page_icon="🧪",
|
| 15 |
+
layout="wide"
|
| 16 |
+
)
|
| 17 |
+
|
| 18 |
+
# Model loading with enhanced error handling
|
| 19 |
+
@st.cache_resource
|
| 20 |
+
def load_model():
|
| 21 |
+
try:
|
| 22 |
+
# First try official ultralytics package
|
| 23 |
+
from ultralytics import YOLO
|
| 24 |
+
return YOLO('yolov8x-seg.pt')
|
| 25 |
+
except ImportError:
|
| 26 |
+
try:
|
| 27 |
+
# Fallback to torch hub
|
| 28 |
+
model = torch.hub.load('ultralytics/yolov8', 'yolov8x-seg', pretrained=True)
|
| 29 |
+
return model.to('cuda' if torch.cuda.is_available() else 'cpu')
|
| 30 |
+
except Exception as e:
|
| 31 |
+
st.error(f"⚠️ Model loading failed: {str(e)}")
|
| 32 |
+
st.info("Please check your internet connection and try again")
|
| 33 |
+
return None
|
| 34 |
+
|
| 35 |
+
model = load_model()
|
| 36 |
+
|
| 37 |
+
def validate_image(img_array):
|
| 38 |
+
"""Ensure 3-channel RGB format"""
|
| 39 |
+
if len(img_array.shape) == 2: # Grayscale
|
| 40 |
+
img_array = cv2.cvtColor(img_array, cv2.COLOR_GRAY2RGB)
|
| 41 |
+
elif img_array.shape[2] == 4: # RGBA
|
| 42 |
+
img_array = cv2.cvtColor(img_array, cv2.COLOR_RGBA2RGB)
|
| 43 |
+
elif img_array.shape[2] > 3: # Extra channels
|
| 44 |
+
img_array = img_array[:, :, :3]
|
| 45 |
+
return img_array
|
| 46 |
+
|
| 47 |
+
def calculate_boundary_iou(mask1, mask2, boundary_width=2):
|
| 48 |
+
"""Calculate Boundary IoU with error handling"""
|
| 49 |
+
try:
|
| 50 |
+
kernel = np.ones((boundary_width, boundary_width), np.uint8)
|
| 51 |
+
boundary1 = cv2.morphologyEx(mask1, cv2.MORPH_GRADIENT, kernel)
|
| 52 |
+
boundary2 = cv2.morphologyEx(mask2, cv2.MORPH_GRADIENT, kernel)
|
| 53 |
+
return jaccard_score(boundary1.flatten(), boundary2.flatten())
|
| 54 |
+
except Exception:
|
| 55 |
+
return 0.0 # Graceful degradation
|
| 56 |
+
|
| 57 |
+
def calculate_metrics(results, img_shape):
|
| 58 |
+
"""Robust metric calculation"""
|
| 59 |
+
if not model:
|
| 60 |
+
return {"error": "Model not loaded"}
|
| 61 |
+
if not results or results[0].masks is None:
|
| 62 |
+
return {"error": "No objects detected"}
|
| 63 |
+
|
| 64 |
+
try:
|
| 65 |
+
# Process predictions
|
| 66 |
+
pred_masks = torch.stack([m.data[0] for m in results[0].masks]).cpu().numpy()
|
| 67 |
+
pred_masks = (pred_masks > 0.5).astype(np.uint8)
|
| 68 |
+
|
| 69 |
+
# Generate mock ground truth
|
| 70 |
+
gt_masks = np.zeros_like(pred_masks)
|
| 71 |
+
h, w = img_shape[:2]
|
| 72 |
+
gt_masks[:, h//4:3*h//4, w//4:3*w//4] = 1
|
| 73 |
+
|
| 74 |
+
# Initialize metrics
|
| 75 |
+
metrics = {
|
| 76 |
+
'IoU': {'mean': 0, 'per_instance': [], 'class_wise': {}},
|
| 77 |
+
'Dice': 0,
|
| 78 |
+
'Pixel_Accuracy': 0,
|
| 79 |
+
'Boundary_IoU': 0,
|
| 80 |
+
'Object_Counts': {},
|
| 81 |
+
'Class_Distribution': {}
|
| 82 |
+
}
|
| 83 |
+
|
| 84 |
+
# Calculate per-mask metrics
|
| 85 |
+
valid_masks = 0
|
| 86 |
+
for i, (pred_mask, gt_mask) in enumerate(zip(pred_masks, gt_masks)):
|
| 87 |
+
try:
|
| 88 |
+
pred_flat = pred_mask.flatten()
|
| 89 |
+
gt_flat = gt_mask.flatten()
|
| 90 |
+
|
| 91 |
+
if np.sum(gt_flat) == 0:
|
| 92 |
+
continue
|
| 93 |
+
|
| 94 |
+
# Core metrics
|
| 95 |
+
metrics['IoU']['per_instance'].append(jaccard_score(gt_flat, pred_flat))
|
| 96 |
+
metrics['Dice'] += f1_score(gt_flat, pred_flat)
|
| 97 |
+
metrics['Pixel_Accuracy'] += accuracy_score(gt_flat, pred_flat)
|
| 98 |
+
metrics['Boundary_IoU'] += calculate_boundary_iou(gt_mask, pred_mask)
|
| 99 |
+
|
| 100 |
+
# Class tracking
|
| 101 |
+
cls = int(results[0].boxes.cls[i])
|
| 102 |
+
cls_name = model.names[cls]
|
| 103 |
+
metrics['Object_Counts'][cls_name] = metrics['Object_Counts'].get(cls_name, 0) + 1
|
| 104 |
+
metrics['Class_Distribution'][cls_name] = metrics['Class_Distribution'].get(cls_name, 0) + 1
|
| 105 |
+
|
| 106 |
+
valid_masks += 1
|
| 107 |
+
except Exception:
|
| 108 |
+
continue
|
| 109 |
+
|
| 110 |
+
# Finalize metrics
|
| 111 |
+
if valid_masks > 0:
|
| 112 |
+
metrics['IoU']['mean'] = np.mean(metrics['IoU']['per_instance'])
|
| 113 |
+
metrics['Dice'] /= valid_masks
|
| 114 |
+
metrics['Pixel_Accuracy'] /= valid_masks
|
| 115 |
+
metrics['Boundary_IoU'] /= valid_masks
|
| 116 |
+
|
| 117 |
+
# Class-wise metrics
|
| 118 |
+
total = sum(metrics['Object_Counts'].values())
|
| 119 |
+
metrics['IoU']['class_wise'] = {k: v/total for k, v in metrics['Object_Counts'].items()}
|
| 120 |
+
|
| 121 |
+
return metrics
|
| 122 |
+
|
| 123 |
+
except Exception as e:
|
| 124 |
+
return {"error": f"Metric calculation failed: {str(e)}"}
|
| 125 |
+
|
| 126 |
+
def visualize_results(img, results):
|
| 127 |
+
"""Generate visualizations with error handling"""
|
| 128 |
+
try:
|
| 129 |
+
# Segmentation overlay
|
| 130 |
+
seg_img = img.copy()
|
| 131 |
+
if results[0].masks is not None:
|
| 132 |
+
for mask in results[0].masks:
|
| 133 |
+
mask_points = mask.xy[0].astype(int)
|
| 134 |
+
cv2.fillPoly(seg_img, [mask_points], (0, 0, 255, 100))
|
| 135 |
+
|
| 136 |
+
# Bounding boxes
|
| 137 |
+
det_img = img.copy()
|
| 138 |
+
for box, cls, conf in zip(results[0].boxes.xyxy, results[0].boxes.cls, results[0].boxes.conf):
|
| 139 |
+
x1, y1, x2, y2 = map(int, box)
|
| 140 |
+
cv2.rectangle(det_img, (x1, y1), (x2, y2), (255, 0, 0), 2)
|
| 141 |
+
cv2.putText(det_img, f"{model.names[int(cls)]} {conf:.2f}",
|
| 142 |
+
(x1, y1-10), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (255,255,255), 2)
|
| 143 |
+
|
| 144 |
+
return seg_img, det_img
|
| 145 |
+
except Exception:
|
| 146 |
+
return img, img # Fallback to original images
|
| 147 |
+
|
| 148 |
+
def process_image(input_img):
|
| 149 |
+
"""Main processing pipeline"""
|
| 150 |
+
try:
|
| 151 |
+
img = np.array(input_img)
|
| 152 |
+
img = validate_image(img)
|
| 153 |
+
results = model(img)
|
| 154 |
+
seg_img, det_img = visualize_results(img, results)
|
| 155 |
+
metrics = calculate_metrics(results, img.shape)
|
| 156 |
+
return Image.fromarray(seg_img), Image.fromarray(det_img), metrics
|
| 157 |
+
except Exception as e:
|
| 158 |
+
st.error(f"Processing failed: {str(e)}")
|
| 159 |
+
return None, None, {"error": str(e)}
|
| 160 |
+
|
| 161 |
+
# Main UI
|
| 162 |
+
def main():
|
| 163 |
+
st.title("🧪 Advanced Segmentation Metrics Analyzer")
|
| 164 |
+
st.markdown("""
|
| 165 |
+
Upload an image to analyze object segmentation performance using YOLOv8.
|
| 166 |
+
The system provides detailed metrics and visualizations.
|
| 167 |
+
""")
|
| 168 |
+
|
| 169 |
+
with st.sidebar:
|
| 170 |
+
st.header("Configuration")
|
| 171 |
+
conf_threshold = st.slider("Confidence Threshold", 0.1, 1.0, 0.5)
|
| 172 |
+
boundary_width = st.slider("Boundary Width (pixels)", 1, 10, 2)
|
| 173 |
+
st.markdown("---")
|
| 174 |
+
st.markdown(f"**Device:** {'GPU 🔥' if torch.cuda.is_available() else 'CPU 🐢'}")
|
| 175 |
+
|
| 176 |
+
uploaded_file = st.file_uploader(
|
| 177 |
+
"Choose an image",
|
| 178 |
+
type=["jpg", "jpeg", "png", "bmp"],
|
| 179 |
+
help="Supports JPG, PNG, BMP formats"
|
| 180 |
+
)
|
| 181 |
+
|
| 182 |
+
if uploaded_file:
|
| 183 |
+
try:
|
| 184 |
+
img = Image.open(uploaded_file)
|
| 185 |
+
col1, col2 = st.columns(2)
|
| 186 |
+
with col1:
|
| 187 |
+
st.image(img, caption="Original Image", use_column_width=True)
|
| 188 |
+
|
| 189 |
+
if st.button("Analyze", type="primary"):
|
| 190 |
+
with st.spinner("Processing..."):
|
| 191 |
+
seg_img, det_img, metrics = process_image(img)
|
| 192 |
+
|
| 193 |
+
if metrics and "error" not in metrics:
|
| 194 |
+
tabs = st.tabs(["Visual Results", "Metrics Dashboard", "Raw Data"])
|
| 195 |
+
|
| 196 |
+
with tabs[0]:
|
| 197 |
+
st.subheader("Segmentation Analysis")
|
| 198 |
+
cols = st.columns(2)
|
| 199 |
+
cols[0].image(seg_img, caption="Segmentation Mask", use_column_width=True)
|
| 200 |
+
cols[1].image(det_img, caption="Detected Objects", use_column_width=True)
|
| 201 |
+
|
| 202 |
+
with tabs[1]:
|
| 203 |
+
st.subheader("Performance Metrics")
|
| 204 |
+
st.metric("Mean IoU", f"{metrics['IoU']['mean']:.2%}",
|
| 205 |
+
help="Intersection over Union")
|
| 206 |
+
st.metric("Dice Coefficient", f"{metrics['Dice']:.2%}",
|
| 207 |
+
help="F1 Score for segmentation")
|
| 208 |
+
st.metric("Pixel Accuracy", f"{metrics['Pixel_Accuracy']:.2%}")
|
| 209 |
+
|
| 210 |
+
st.plotly_chart({
|
| 211 |
+
'data': [{
|
| 212 |
+
'x': list(metrics['Class_Distribution'].keys()),
|
| 213 |
+
'y': list(metrics['Class_Distribution'].values()),
|
| 214 |
+
'type': 'bar'
|
| 215 |
+
}],
|
| 216 |
+
'layout': {'title': 'Class Distribution'}
|
| 217 |
+
})
|
| 218 |
+
|
| 219 |
+
with tabs[2]:
|
| 220 |
+
st.download_button(
|
| 221 |
+
"Download Metrics",
|
| 222 |
+
str(metrics),
|
| 223 |
+
"metrics.json",
|
| 224 |
+
"application/json"
|
| 225 |
+
)
|
| 226 |
+
st.json(metrics)
|
| 227 |
+
|
| 228 |
+
elif metrics and "error" in metrics:
|
| 229 |
+
st.error(metrics["error"])
|
| 230 |
+
|
| 231 |
+
except Exception as e:
|
| 232 |
+
st.error(f"Error loading image: {str(e)}")
|
| 233 |
+
|
| 234 |
+
if __name__ == "__main__":
|
| 235 |
+
main()
|
paths_to_forget.txt
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
output/
|
| 2 |
+
static/uploads/
|
| 3 |
+
instance/users.db
|
| 4 |
+
models/best_model_bleu*.pth
|
| 5 |
+
yolov8x-seg.pt
|
| 6 |
+
data/images/ # Add this line
|
requirements.txt
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
torch
|
| 2 |
+
torchvision
|
| 3 |
+
Pillow
|
| 4 |
+
numpy
|
| 5 |
+
matplotlib
|
| 6 |
+
tqdm
|
| 7 |
+
nltk
|
| 8 |
+
rouge-score
|
| 9 |
+
pycocotools
|
| 10 |
+
pycocoevalcap @ git+https://github.com/salaniz/pycocoevalcap.git
|
| 11 |
+
flask
|
| 12 |
+
flask_sqlalchemy
|
| 13 |
+
gunicorn
|
| 14 |
+
ultralytics
|
| 15 |
+
face-recognition
|
| 16 |
+
Pillow
|
| 17 |
+
opencv-python-headless
|
| 18 |
+
numpy
|
| 19 |
+
werkzeug
|
src/__init__.py
ADDED
|
File without changes
|
src/app.py
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import torch
|
| 3 |
+
from PIL import Image
|
| 4 |
+
import sys # Import sys for flushing stdout
|
| 5 |
+
|
| 6 |
+
# Import modules from your project structure
|
| 7 |
+
# Ensure utils is imported early to set up logging
|
| 8 |
+
from .utils import get_logger, get_eval_transform, visualize_attention
|
| 9 |
+
from .model import ImageCaptioningModel
|
| 10 |
+
from .data_preprocessing import COCOVocabulary
|
| 11 |
+
from .config import INFERENCE_CONFIG, update_config_with_latest_model # config is imported here
|
| 12 |
+
from .evaluation import calculate_bleu_scores_detailed # evaluation is imported here
|
| 13 |
+
|
| 14 |
+
# Get the module-specific logger. This logger will inherit from the root logger
|
| 15 |
+
# which is configured when `utils` is imported.
|
| 16 |
+
logger = get_logger(__name__)
|
| 17 |
+
|
| 18 |
+
def run_inference_example(model_path, image_path, config=None):
|
| 19 |
+
"""
|
| 20 |
+
Function to run inference on a single image and generate a caption.
|
| 21 |
+
|
| 22 |
+
Args:
|
| 23 |
+
model_path (str): Path to the saved model checkpoint (.pth file).
|
| 24 |
+
image_path (str): Path to the image file for captioning.
|
| 25 |
+
config (dict, optional): Configuration dictionary for inference parameters
|
| 26 |
+
(e.g., beam_size, max_caption_length).
|
| 27 |
+
Returns:
|
| 28 |
+
str: The generated caption for the image.
|
| 29 |
+
Raises:
|
| 30 |
+
FileNotFoundError: If the model checkpoint or image file is not found.
|
| 31 |
+
Exception: For other unexpected errors during inference.
|
| 32 |
+
"""
|
| 33 |
+
logger.info("Loading model for inference...")
|
| 34 |
+
|
| 35 |
+
if not os.path.exists(model_path):
|
| 36 |
+
raise FileNotFoundError(f"Model checkpoint not found at {model_path}. "
|
| 37 |
+
"Please train the model first or provide a valid path.")
|
| 38 |
+
|
| 39 |
+
# Load the complete checkpoint (model state, optimizer state, vocabulary, config)
|
| 40 |
+
# map_location='cpu' ensures it loads to CPU even if trained on GPU
|
| 41 |
+
checkpoint = torch.load(model_path, map_location='cpu', weights_only=False)
|
| 42 |
+
|
| 43 |
+
# Extract configuration and vocabulary from the checkpoint
|
| 44 |
+
model_config_from_checkpoint = checkpoint.get('config', {})
|
| 45 |
+
vocabulary = checkpoint['vocabulary']
|
| 46 |
+
|
| 47 |
+
# Initialize the model structure with parameters saved in the checkpoint
|
| 48 |
+
# Ensure dropout is set to 0.0 for inference and fine_tune_encoder is False
|
| 49 |
+
model = ImageCaptioningModel(
|
| 50 |
+
vocab_size=vocabulary.vocab_size,
|
| 51 |
+
embed_dim=model_config_from_checkpoint.get('embed_dim', 256),
|
| 52 |
+
attention_dim=model_config_from_checkpoint.get('attention_dim', 256),
|
| 53 |
+
decoder_dim=model_config_from_checkpoint.get('decoder_dim', 256),
|
| 54 |
+
dropout=0.0, # Dropout should be off during inference
|
| 55 |
+
fine_tune_encoder=False, # Encoder should not be fine-tuned during inference
|
| 56 |
+
max_caption_length=config.get('max_caption_length', 20) if config else 20 # Use config's max length for inference
|
| 57 |
+
)
|
| 58 |
+
# Load the trained weights into the model
|
| 59 |
+
model.load_state_dict(checkpoint['model_state_dict'])
|
| 60 |
+
model.eval() # Set the model to evaluation mode (important for batch norm, dropout)
|
| 61 |
+
|
| 62 |
+
# Determine the device to run inference on
|
| 63 |
+
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
|
| 64 |
+
model = model.to(device) # Move model to GPU if available
|
| 65 |
+
logger.info(f"Model loaded successfully on device: {device}")
|
| 66 |
+
|
| 67 |
+
# Get the image transformation pipeline for evaluation/inference
|
| 68 |
+
transform = get_eval_transform()
|
| 69 |
+
|
| 70 |
+
if not os.path.exists(image_path):
|
| 71 |
+
raise FileNotFoundError(f"Image not found at {image_path}. Please check the image path.")
|
| 72 |
+
|
| 73 |
+
# Load and preprocess the image
|
| 74 |
+
try:
|
| 75 |
+
image = Image.open(image_path).convert('RGB')
|
| 76 |
+
image_tensor = transform(image).to(device)
|
| 77 |
+
except Exception as e:
|
| 78 |
+
raise Exception(f"Error loading or transforming image {image_path}: {e}")
|
| 79 |
+
|
| 80 |
+
logger.info(f"Generating caption for {image_path} using beam search (beam_size="
|
| 81 |
+
f"{config.get('beam_size', 5) if config else 5})...")
|
| 82 |
+
|
| 83 |
+
# Generate the caption using the model's integrated method
|
| 84 |
+
generated_caption = model.generate_caption(
|
| 85 |
+
image_tensor,
|
| 86 |
+
vocabulary,
|
| 87 |
+
device,
|
| 88 |
+
beam_size=config.get('beam_size', 5) if config else 5,
|
| 89 |
+
max_length=config.get('max_caption_length', 20) if config else 20
|
| 90 |
+
)
|
| 91 |
+
|
| 92 |
+
# Optional: Visualize attention weights
|
| 93 |
+
visualize_attention(model, image_path, vocabulary, device,
|
| 94 |
+
save_path=os.path.join('output', 'attention_visualization.png'))
|
| 95 |
+
|
| 96 |
+
# These logs are now placed AFTER the point where the logger is definitely active.
|
| 97 |
+
logger.info("\n" + "="*50)
|
| 98 |
+
logger.info(" GENERATED CAPTION")
|
| 99 |
+
logger.info("="*50)
|
| 100 |
+
logger.info(f"Image: {image_path}")
|
| 101 |
+
logger.info(f"Caption: {generated_caption}")
|
| 102 |
+
logger.info("="*50 + "\n")
|
| 103 |
+
sys.stdout.flush() # Explicitly flush the standard output buffer
|
| 104 |
+
|
| 105 |
+
return generated_caption
|
| 106 |
+
|
| 107 |
+
|
| 108 |
+
if __name__ == '__main__':
|
| 109 |
+
# When `app.py` is run directly, it will run the inference example.
|
| 110 |
+
# Update INFERENCE_CONFIG with the latest model path if available
|
| 111 |
+
update_config_with_latest_model(INFERENCE_CONFIG)
|
| 112 |
+
|
| 113 |
+
# --- User Input/Configuration for Inference ---
|
| 114 |
+
# These values are now primarily controlled via INFERENCE_CONFIG in config.py
|
| 115 |
+
# You can override them here if you need to test specific scenarios immediately.
|
| 116 |
+
my_image_path = INFERENCE_CONFIG['example_image_path']
|
| 117 |
+
my_model_path = INFERENCE_CONFIG['model_path']
|
| 118 |
+
# You can also set a reference caption here if you know it for comparison
|
| 119 |
+
my_reference_caption = "Two riders on horses are performing a reining maneuver on a green grassy field surrounded by trees" # Example reference, replace or leave empty
|
| 120 |
+
|
| 121 |
+
# Use a copy of INFERENCE_CONFIG to avoid modifying the global config directly
|
| 122 |
+
inference_params = INFERENCE_CONFIG.copy()
|
| 123 |
+
|
| 124 |
+
logger.info("--- Running Inference Example ---")
|
| 125 |
+
try:
|
| 126 |
+
generated_caption = run_inference_example(my_model_path, my_image_path, config=inference_params)
|
| 127 |
+
|
| 128 |
+
# You can add evaluation of this single generated caption against its reference here if desired
|
| 129 |
+
if my_reference_caption:
|
| 130 |
+
# calculate_bleu_scores_detailed is already imported from evaluation
|
| 131 |
+
bleu_scores = calculate_bleu_scores_detailed([my_reference_caption], [generated_caption])
|
| 132 |
+
logger.info("\n--- Single Image Evaluation ---")
|
| 133 |
+
logger.info(f"Reference: {my_reference_caption}")
|
| 134 |
+
logger.info(f"Generated: {generated_caption}")
|
| 135 |
+
logger.info(f"BLEU-4 Score: {bleu_scores['BLEU-4']:.4f}")
|
| 136 |
+
logger.info("-------------------------------\n")
|
| 137 |
+
sys.stdout.flush() # Explicitly flush after single image evaluation too
|
| 138 |
+
|
| 139 |
+
except FileNotFoundError as e:
|
| 140 |
+
logger.error(f"Error: {e}")
|
| 141 |
+
logger.error("Please ensure your model, vocabulary, and image paths are correct "
|
| 142 |
+
"and data is downloaded as per README.md.")
|
| 143 |
+
sys.stdout.flush() # Flush errors too
|
| 144 |
+
except Exception as e:
|
| 145 |
+
logger.critical(f"An unexpected error occurred during inference: {e}", exc_info=True)
|
| 146 |
+
sys.stdout.flush() # Flush critical errors too
|
src/config.py
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
|
| 3 |
+
# Base data folder, assuming COCO 2017 is extracted here
|
| 4 |
+
# Adjust this path if your data is located elsewhere
|
| 5 |
+
_BASE_DATA_FOLDER = 'data/images'
|
| 6 |
+
|
| 7 |
+
# Output directory for logs, saved vocabulary, and temporary files
|
| 8 |
+
# and where the best model checkpoint will be saved for easy access
|
| 9 |
+
_OUTPUT_DIR = 'output'
|
| 10 |
+
_MODELS_DIR = 'models' # Where the final best model will be saved
|
| 11 |
+
|
| 12 |
+
# Ensure output and models directories exist
|
| 13 |
+
os.makedirs(_OUTPUT_DIR, exist_ok=True)
|
| 14 |
+
os.makedirs(_MODELS_DIR, exist_ok=True)
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
# --- Configuration for Training ---
|
| 18 |
+
TRAINING_CONFIG = {
|
| 19 |
+
'data_folder': _BASE_DATA_FOLDER,
|
| 20 |
+
'train_image_folder': 'train2017',
|
| 21 |
+
'val_image_folder': 'val2017',
|
| 22 |
+
'train_caption_file': os.path.join(_BASE_DATA_FOLDER, 'annotations', 'captions_train2017.json'),
|
| 23 |
+
'val_caption_file': os.path.join(_BASE_DATA_FOLDER, 'annotations', 'captions_val2017.json'),
|
| 24 |
+
|
| 25 |
+
# Subset sizes for quicker testing during development. Set to None for full dataset.
|
| 26 |
+
'vocab_subset_size': None,
|
| 27 |
+
'train_subset_size': None, # e.g., 200000 for a large subset, None for full
|
| 28 |
+
'val_subset_size': None, # e.g., 10000 for a subset, None for full
|
| 29 |
+
|
| 30 |
+
# Model Hyperparameters
|
| 31 |
+
'embed_dim': 256,
|
| 32 |
+
'attention_dim': 256,
|
| 33 |
+
'decoder_dim': 256,
|
| 34 |
+
'dropout': 0.5,
|
| 35 |
+
'fine_tune_encoder': True, # Set to False to freeze ResNet weights during training
|
| 36 |
+
|
| 37 |
+
# Training Parameters
|
| 38 |
+
'batch_size': 64,
|
| 39 |
+
'num_workers': 4, # Adjust based on your CPU cores and RAM (e.g., 2, 4, 8)
|
| 40 |
+
'learning_rate': 4e-4,
|
| 41 |
+
'encoder_learning_rate': 1e-5, # Lower LR for encoder if fine_tune_encoder is True
|
| 42 |
+
'lr_reduce_factor': 0.5,
|
| 43 |
+
'lr_patience': 5,
|
| 44 |
+
'num_epochs': 20, # Total number of epochs to run
|
| 45 |
+
'log_step': 100, # Print loss every N steps
|
| 46 |
+
'grad_clip': 5.0, # Gradient clipping value
|
| 47 |
+
|
| 48 |
+
'max_caption_length': 30, # Max length of captions, including <START> and <END>
|
| 49 |
+
'val_beam_size': 3, # Beam size used for validation inference during training
|
| 50 |
+
'val_inference_batches': None, # None to generate captions for all validation batches, or an int for a subset
|
| 51 |
+
|
| 52 |
+
'output_dir': _OUTPUT_DIR, # Where training logs and vocabulary will be saved
|
| 53 |
+
'models_dir': _MODELS_DIR # Where the best model checkpoint will be saved
|
| 54 |
+
}
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
# --- Configuration for Evaluation ---
|
| 58 |
+
# This uses the validation set for evaluation, as is common practice.
|
| 59 |
+
EVALUATION_CONFIG = {
|
| 60 |
+
'data_folder': _BASE_DATA_FOLDER,
|
| 61 |
+
'test_image_folder': 'val2017', # Typically evaluate on the validation set for final metrics
|
| 62 |
+
'test_caption_file': os.path.join(_BASE_DATA_FOLDER, 'annotations', 'captions_val2017.json'),
|
| 63 |
+
'test_subset_size': None, # Evaluate on a subset for faster testing, or None for full validation set
|
| 64 |
+
'eval_batch_size': 1, # Must be 1 for accurate beam search evaluation
|
| 65 |
+
'beam_size': 5, # Beam size for caption generation during evaluation
|
| 66 |
+
'max_caption_length': 30,
|
| 67 |
+
'num_workers': 4,
|
| 68 |
+
'eval_output_dir': os.path.join(_OUTPUT_DIR, 'evaluation_results'), # Directory to save evaluation results JSONs
|
| 69 |
+
'output_dir': _OUTPUT_DIR,
|
| 70 |
+
|
| 71 |
+
# Placeholder for model path. This will be updated dynamically after training or
|
| 72 |
+
# can be set manually if you have a pre-trained model.
|
| 73 |
+
'model_path': os.path.join(_MODELS_DIR, 'best_model_bleu0.1058.pth') # Placeholder, update after training
|
| 74 |
+
}
|
| 75 |
+
|
| 76 |
+
|
| 77 |
+
# --- Configuration for Inference Example ---
|
| 78 |
+
INFERENCE_CONFIG = {
|
| 79 |
+
'beam_size': 5,
|
| 80 |
+
'max_caption_length': 30,
|
| 81 |
+
# Placeholder for model path. This will be updated dynamically after training or
|
| 82 |
+
# can be set manually if you have a pre-trained model.
|
| 83 |
+
'model_path': os.path.join(_MODELS_DIR, 'models/best_model_bleu0.1058.pth'), # Placeholder, update after training
|
| 84 |
+
|
| 85 |
+
# Path to an example image for quick inference demonstration
|
| 86 |
+
'example_image_path': os.path.join(_BASE_DATA_FOLDER, 'new_one.jpg') # Example image from COCO val2017
|
| 87 |
+
}
|
| 88 |
+
|
| 89 |
+
|
| 90 |
+
# --- Utility Functions for updating config with latest trained model ---
|
| 91 |
+
def update_config_with_latest_model(config_dict):
|
| 92 |
+
"""
|
| 93 |
+
Finds the latest best model checkpoint in the models directory and updates
|
| 94 |
+
the given configuration dictionary's 'model_path'.
|
| 95 |
+
"""
|
| 96 |
+
saved_models = [f for f in os.listdir(_MODELS_DIR) if f.startswith('best_model_bleu') and f.endswith('.pth')]
|
| 97 |
+
if saved_models:
|
| 98 |
+
# Get the one with the highest BLEU score in its name
|
| 99 |
+
latest_model_name = max(saved_models, key=lambda f: float(f.split('bleu')[1].replace('.pth', '')))
|
| 100 |
+
latest_model_path = os.path.join(_MODELS_DIR, latest_model_name)
|
| 101 |
+
config_dict['model_path'] = latest_model_path
|
| 102 |
+
print(f"Updated config with latest model: {latest_model_path}")
|
| 103 |
+
else:
|
| 104 |
+
print(f"Warning: No best model found in '{_MODELS_DIR}'. Inference/Evaluation might fail.")
|
| 105 |
+
|
| 106 |
+
# Update inference and evaluation configs to point to the latest model if available
|
| 107 |
+
update_config_with_latest_model(EVALUATION_CONFIG)
|
| 108 |
+
update_config_with_latest_model(INFERENCE_CONFIG)
|
src/data_preprocessing.py
ADDED
|
@@ -0,0 +1,247 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import json
|
| 3 |
+
import pickle
|
| 4 |
+
import random
|
| 5 |
+
from collections import Counter
|
| 6 |
+
from tqdm import tqdm
|
| 7 |
+
from PIL import Image
|
| 8 |
+
import torch
|
| 9 |
+
from torch.utils.data import Dataset
|
| 10 |
+
import torchvision.transforms as transforms
|
| 11 |
+
|
| 12 |
+
from .utils import get_logger, get_eval_transform # Import logger and transforms from utils
|
| 13 |
+
|
| 14 |
+
logger = get_logger(__name__)
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
class COCOVocabulary:
|
| 18 |
+
"""
|
| 19 |
+
Vocabulary builder for COCO captions.
|
| 20 |
+
Handles tokenization, building word-to-index and index-to-word mappings,
|
| 21 |
+
and converting captions to numerical indices.
|
| 22 |
+
"""
|
| 23 |
+
def __init__(self, min_word_freq=5):
|
| 24 |
+
"""
|
| 25 |
+
Initializes the COCOVocabulary.
|
| 26 |
+
Args:
|
| 27 |
+
min_word_freq (int): Minimum frequency for a word to be included in the vocabulary.
|
| 28 |
+
Words less frequent than this will be replaced by <UNK>.
|
| 29 |
+
"""
|
| 30 |
+
self.min_word_freq = min_word_freq
|
| 31 |
+
self.word2idx = {} # Maps words to their numerical indices
|
| 32 |
+
self.idx2word = {} # Maps numerical indices back to words
|
| 33 |
+
self.word_freq = Counter() # Counts frequency of each word
|
| 34 |
+
self.vocab_size = 0 # Total number of unique words in the vocabulary
|
| 35 |
+
|
| 36 |
+
def build_vocabulary(self, captions):
|
| 37 |
+
"""
|
| 38 |
+
Builds the vocabulary from a list of captions.
|
| 39 |
+
Args:
|
| 40 |
+
captions (list): A list of strings, where each string is a caption.
|
| 41 |
+
"""
|
| 42 |
+
logger.info("Building vocabulary...")
|
| 43 |
+
|
| 44 |
+
# 1. Count word frequencies
|
| 45 |
+
for caption in tqdm(captions, desc="Counting word frequencies"):
|
| 46 |
+
tokens = self.tokenize(caption)
|
| 47 |
+
self.word_freq.update(tokens)
|
| 48 |
+
|
| 49 |
+
# 2. Add special tokens
|
| 50 |
+
special_tokens = ['<PAD>', '<START>', '<END>', '<UNK>']
|
| 51 |
+
for token in special_tokens:
|
| 52 |
+
if token not in self.word2idx: # Avoid re-adding if already present
|
| 53 |
+
self.word2idx[token] = len(self.word2idx)
|
| 54 |
+
self.idx2word[len(self.idx2word)] = token
|
| 55 |
+
|
| 56 |
+
# 3. Add words that meet the minimum frequency threshold
|
| 57 |
+
for word, freq in self.word_freq.items():
|
| 58 |
+
if freq >= self.min_word_freq:
|
| 59 |
+
if word not in self.word2idx: # Avoid re-adding words if they are special tokens
|
| 60 |
+
self.word2idx[word] = len(self.word2idx)
|
| 61 |
+
self.idx2word[len(self.idx2word)] = word
|
| 62 |
+
|
| 63 |
+
self.vocab_size = len(self.word2idx)
|
| 64 |
+
logger.info(f"Vocabulary built successfully. Size: {self.vocab_size}")
|
| 65 |
+
|
| 66 |
+
def tokenize(self, caption):
|
| 67 |
+
"""
|
| 68 |
+
Simple tokenization: convert to lowercase, strip leading/trailing spaces,
|
| 69 |
+
and split by space. Normalizes multiple spaces.
|
| 70 |
+
Args:
|
| 71 |
+
caption (str): The input caption string.
|
| 72 |
+
Returns:
|
| 73 |
+
list: A list of tokenized words.
|
| 74 |
+
"""
|
| 75 |
+
caption = caption.lower().strip()
|
| 76 |
+
# Normalize multiple spaces into a single space
|
| 77 |
+
caption = ' '.join(caption.split())
|
| 78 |
+
tokens = caption.split()
|
| 79 |
+
return tokens
|
| 80 |
+
|
| 81 |
+
def caption_to_indices(self, caption, max_length=20):
|
| 82 |
+
"""
|
| 83 |
+
Converts a caption string into a list of numerical indices.
|
| 84 |
+
Adds <START> and <END> tokens and pads with <PAD> up to max_length.
|
| 85 |
+
Args:
|
| 86 |
+
caption (str): The input caption string.
|
| 87 |
+
max_length (int): The maximum desired length for the indexed caption.
|
| 88 |
+
Returns:
|
| 89 |
+
list: A list of integer indices representing the caption.
|
| 90 |
+
"""
|
| 91 |
+
tokens = self.tokenize(caption)
|
| 92 |
+
indices = [self.word2idx['<START>']] # Start with the <START> token
|
| 93 |
+
|
| 94 |
+
for token in tokens:
|
| 95 |
+
if len(indices) >= max_length - 1: # Reserve space for <END>
|
| 96 |
+
break
|
| 97 |
+
idx = self.word2idx.get(token, self.word2idx['<UNK>']) # Use <UNK> for unknown words
|
| 98 |
+
indices.append(idx)
|
| 99 |
+
|
| 100 |
+
indices.append(self.word2idx['<END>']) # End with the <END> token
|
| 101 |
+
|
| 102 |
+
# Pad with <PAD> tokens if the caption is shorter than max_length
|
| 103 |
+
while len(indices) < max_length:
|
| 104 |
+
indices.append(self.word2idx['<PAD>'])
|
| 105 |
+
|
| 106 |
+
return indices[:max_length] # Ensure the caption does not exceed max_length
|
| 107 |
+
|
| 108 |
+
def indices_to_caption(self, indices):
|
| 109 |
+
"""
|
| 110 |
+
Converts a list of numerical indices back into a human-readable caption string.
|
| 111 |
+
Stops at <END> token and ignores <PAD> and <START> tokens.
|
| 112 |
+
Args:
|
| 113 |
+
indices (list or numpy.ndarray): A list or array of integer indices.
|
| 114 |
+
Returns:
|
| 115 |
+
str: The reconstructed caption string.
|
| 116 |
+
"""
|
| 117 |
+
words = []
|
| 118 |
+
for idx in indices:
|
| 119 |
+
word = self.idx2word.get(idx, '<UNK>') # Get word, default to <UNK>
|
| 120 |
+
if word == '<END>':
|
| 121 |
+
break # Stop decoding when <END> token is encountered
|
| 122 |
+
if word not in ['<PAD>', '<START>']: # Ignore special tokens
|
| 123 |
+
words.append(word)
|
| 124 |
+
return ' '.join(words)
|
| 125 |
+
|
| 126 |
+
|
| 127 |
+
class COCODataset(Dataset):
|
| 128 |
+
"""
|
| 129 |
+
PyTorch Dataset for COCO Image Captioning.
|
| 130 |
+
Loads image paths and their corresponding captions,
|
| 131 |
+
and returns preprocessed image tensors and indexed caption tensors.
|
| 132 |
+
"""
|
| 133 |
+
def __init__(self, image_dir, caption_file, vocabulary=None,
|
| 134 |
+
max_caption_length=20, subset_size=None, transform=None):
|
| 135 |
+
"""
|
| 136 |
+
Initializes the COCODataset.
|
| 137 |
+
Args:
|
| 138 |
+
image_dir (str): Path to the directory containing COCO images (e.g., 'train2017', 'val2017').
|
| 139 |
+
caption_file (str): Path to the COCO captions JSON file (e.g., 'captions_train2017.json').
|
| 140 |
+
vocabulary (COCOVocabulary, optional): A pre-built COCOVocabulary object. If None,
|
| 141 |
+
a new vocabulary will be built from the captions.
|
| 142 |
+
max_caption_length (int): Maximum length for indexed captions.
|
| 143 |
+
subset_size (int, optional): If specified, uses a random subset of this size from the dataset.
|
| 144 |
+
transform (torchvision.transforms.Compose, optional): Image transformations to apply.
|
| 145 |
+
"""
|
| 146 |
+
self.image_dir = image_dir
|
| 147 |
+
self.max_caption_length = max_caption_length
|
| 148 |
+
self.transform = transform if transform is not None else get_eval_transform() # Default transform
|
| 149 |
+
|
| 150 |
+
try:
|
| 151 |
+
with open(caption_file, 'r') as f:
|
| 152 |
+
self.coco_data = json.load(f)
|
| 153 |
+
logger.info(f"Successfully loaded captions from {caption_file}")
|
| 154 |
+
except FileNotFoundError:
|
| 155 |
+
logger.error(f"Caption file not found at {caption_file}. Please check the path.")
|
| 156 |
+
raise
|
| 157 |
+
except json.JSONDecodeError:
|
| 158 |
+
logger.error(f"Error decoding JSON from {caption_file}. Ensure it's a valid JSON file.")
|
| 159 |
+
raise
|
| 160 |
+
|
| 161 |
+
# Create a mapping from image ID to its filename for quick lookup
|
| 162 |
+
self.id_to_filename = {img_info['id']: img_info['file_name'] for img_info in self.coco_data['images']}
|
| 163 |
+
|
| 164 |
+
self.data = [] # Stores (image_path, caption, image_id) tuples
|
| 165 |
+
missing_image_files = 0
|
| 166 |
+
|
| 167 |
+
# Process annotations to pair image paths with captions
|
| 168 |
+
for ann in tqdm(self.coco_data['annotations'], desc="Processing annotations"):
|
| 169 |
+
image_id = ann['image_id']
|
| 170 |
+
if image_id in self.id_to_filename:
|
| 171 |
+
caption = ann['caption']
|
| 172 |
+
filename = self.id_to_filename[image_id]
|
| 173 |
+
image_full_path = os.path.join(image_dir, filename)
|
| 174 |
+
|
| 175 |
+
if os.path.exists(image_full_path):
|
| 176 |
+
self.data.append({
|
| 177 |
+
'image_path': image_full_path,
|
| 178 |
+
'caption': caption,
|
| 179 |
+
'image_id': image_id # Store original image_id for evaluation
|
| 180 |
+
})
|
| 181 |
+
else:
|
| 182 |
+
missing_image_files += 1
|
| 183 |
+
# logger.warning(f"Image file not found: {image_full_path}. Skipping this annotation.")
|
| 184 |
+
else:
|
| 185 |
+
logger.warning(f"Image ID {image_id} not found in images list. Skipping annotation.")
|
| 186 |
+
|
| 187 |
+
if missing_image_files > 0:
|
| 188 |
+
logger.warning(f"Skipped {missing_image_files} annotations due to missing image files. "
|
| 189 |
+
"Please ensure all images are in the specified directory.")
|
| 190 |
+
|
| 191 |
+
# If subset_size is specified, take a random sample
|
| 192 |
+
if subset_size and subset_size < len(self.data):
|
| 193 |
+
self.data = random.sample(self.data, subset_size)
|
| 194 |
+
logger.info(f"Using subset of {subset_size} samples for the dataset.")
|
| 195 |
+
|
| 196 |
+
logger.info(f"Dataset size after filtering: {len(self.data)} samples.")
|
| 197 |
+
|
| 198 |
+
# Build vocabulary if not provided
|
| 199 |
+
if vocabulary is None:
|
| 200 |
+
self.vocabulary = COCOVocabulary()
|
| 201 |
+
captions_for_vocab = [item['caption'] for item in self.data]
|
| 202 |
+
self.vocabulary.build_vocabulary(captions_for_vocab)
|
| 203 |
+
else:
|
| 204 |
+
self.vocabulary = vocabulary
|
| 205 |
+
|
| 206 |
+
def __len__(self):
|
| 207 |
+
"""Returns the total number of samples in the dataset."""
|
| 208 |
+
return len(self.data)
|
| 209 |
+
|
| 210 |
+
def __getitem__(self, idx):
|
| 211 |
+
"""
|
| 212 |
+
Retrieves an item from the dataset at the given index.
|
| 213 |
+
Returns:
|
| 214 |
+
tuple: (image_tensor, caption_tensor, caption_length, image_id)
|
| 215 |
+
"""
|
| 216 |
+
item = self.data[idx]
|
| 217 |
+
|
| 218 |
+
# Load and transform image
|
| 219 |
+
try:
|
| 220 |
+
image = Image.open(item['image_path']).convert('RGB')
|
| 221 |
+
if self.transform:
|
| 222 |
+
image = self.transform(image)
|
| 223 |
+
except Exception as e:
|
| 224 |
+
logger.error(f"Error loading image {item['image_path']}: {e}. Returning a black image as fallback.")
|
| 225 |
+
# Return a black image tensor of expected size (3, 224, 224) if image loading fails
|
| 226 |
+
image = torch.zeros(3, 224, 224)
|
| 227 |
+
|
| 228 |
+
# Convert caption to indices
|
| 229 |
+
caption_indices = self.vocabulary.caption_to_indices(
|
| 230 |
+
item['caption'], self.max_caption_length
|
| 231 |
+
)
|
| 232 |
+
caption_tensor = torch.tensor(caption_indices, dtype=torch.long)
|
| 233 |
+
|
| 234 |
+
# Calculate actual length of the caption (excluding padding, including START/END)
|
| 235 |
+
try:
|
| 236 |
+
# Find the index of <END> token, length is (index + 1)
|
| 237 |
+
end_idx = caption_indices.index(self.vocabulary.word2idx['<END>'])
|
| 238 |
+
caption_length = end_idx + 1
|
| 239 |
+
except ValueError:
|
| 240 |
+
# If <END> not found (shouldn't happen with proper max_caption_length),
|
| 241 |
+
# count non-PAD tokens.
|
| 242 |
+
caption_length = len([idx for idx in caption_indices if idx != self.vocabulary.word2idx['<PAD>']])
|
| 243 |
+
|
| 244 |
+
caption_length = torch.tensor(caption_length, dtype=torch.long)
|
| 245 |
+
|
| 246 |
+
# Return image tensor, caption tensor, actual caption length, and original image ID
|
| 247 |
+
return image, caption_tensor, caption_length, item['image_id']
|
src/evaluation.py
ADDED
|
@@ -0,0 +1,691 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import time
|
| 3 |
+
import json
|
| 4 |
+
import numpy as np
|
| 5 |
+
from tqdm import tqdm
|
| 6 |
+
import torch
|
| 7 |
+
from torch.utils.data import DataLoader
|
| 8 |
+
import math # For perplexity
|
| 9 |
+
import random
|
| 10 |
+
from .config import EVALUATION_CONFIG, update_config_with_latest_model
|
| 11 |
+
from .data_preprocessing import COCOVocabulary
|
| 12 |
+
|
| 13 |
+
# Import necessary NLTK components for BLEU, METEOR
|
| 14 |
+
try:
|
| 15 |
+
import nltk
|
| 16 |
+
from nltk.translate.bleu_score import corpus_bleu, SmoothingFunction
|
| 17 |
+
from nltk.translate.meteor_score import meteor_score
|
| 18 |
+
from nltk.tokenize import word_tokenize
|
| 19 |
+
# Suppress NLTK download messages if already downloaded
|
| 20 |
+
nltk.download('punkt', quiet=True)
|
| 21 |
+
nltk.download('wordnet', quiet=True)
|
| 22 |
+
except ImportError:
|
| 23 |
+
print("NLTK not installed or data not downloaded. BLEU/METEOR scores will be skipped.")
|
| 24 |
+
print("Please install NLTK (`pip install nltk`) and download data (`python -c \"import nltk; nltk.download('punkt'); nltk.download('wordnet')\"`)")
|
| 25 |
+
corpus_bleu = None
|
| 26 |
+
meteor_score = None
|
| 27 |
+
word_tokenize = None
|
| 28 |
+
SmoothingFunction = None
|
| 29 |
+
|
| 30 |
+
# Import ROUGE
|
| 31 |
+
try:
|
| 32 |
+
from rouge_score import rouge_scorer
|
| 33 |
+
except ImportError:
|
| 34 |
+
print("rouge-score not installed. ROUGE-L score will be skipped.")
|
| 35 |
+
print("Please install it: `pip install rouge-score`")
|
| 36 |
+
rouge_scorer = None
|
| 37 |
+
|
| 38 |
+
# Import pycocotools and pycocoevalcap for CIDEr
|
| 39 |
+
try:
|
| 40 |
+
from pycocotools.coco import COCO
|
| 41 |
+
from pycocoevalcap.eval import COCOEvalCap
|
| 42 |
+
import tempfile
|
| 43 |
+
except ImportError:
|
| 44 |
+
print("pycocotools or pycocoevalcap not installed. CIDEr score will be skipped.")
|
| 45 |
+
print("Please install: `pip install pycocotools` and `pip install git+https://github.com/salaniz/pycocoevalcap.git`")
|
| 46 |
+
COCO = None
|
| 47 |
+
COCOEvalCap = None
|
| 48 |
+
tempfile = None
|
| 49 |
+
|
| 50 |
+
|
| 51 |
+
from .model import ImageCaptioningModel # Import the model
|
| 52 |
+
from .data_preprocessing import COCODataset # Import dataset
|
| 53 |
+
from .utils import get_logger, get_eval_transform # Import utilities
|
| 54 |
+
|
| 55 |
+
logger = get_logger(__name__)
|
| 56 |
+
|
| 57 |
+
|
| 58 |
+
def calculate_bleu_scores_detailed(references, hypotheses):
|
| 59 |
+
"""
|
| 60 |
+
Calculates detailed BLEU scores (BLEU-1 to BLEU-4) for a corpus.
|
| 61 |
+
Args:
|
| 62 |
+
references (list of str): List of reference captions. Each reference is a single string.
|
| 63 |
+
hypotheses (list of str): List of hypothesis (generated) captions. Each hypothesis is a single string.
|
| 64 |
+
Returns:
|
| 65 |
+
dict: A dictionary containing BLEU-1, BLEU-2, BLEU-3, BLEU-4 scores.
|
| 66 |
+
Returns zeros if NLTK is not available or an error occurs.
|
| 67 |
+
"""
|
| 68 |
+
if corpus_bleu is None or word_tokenize is None or SmoothingFunction is None:
|
| 69 |
+
logger.error("NLTK requirements for BLEU not met. Returning 0 for BLEU scores.")
|
| 70 |
+
return {'BLEU-1': 0, 'BLEU-2': 0, 'BLEU-3': 0, 'BLEU-4': 0}
|
| 71 |
+
|
| 72 |
+
try:
|
| 73 |
+
# Each reference is a list of ONE tokenized sentence (as `corpus_bleu` expects multiple references per hypothesis)
|
| 74 |
+
# We assume one reference per image for simplicity.
|
| 75 |
+
ref_tokens = [[word_tokenize(ref.lower())] for ref in references]
|
| 76 |
+
hyp_tokens = [word_tokenize(hyp.lower()) for hyp in hypotheses]
|
| 77 |
+
|
| 78 |
+
# Use smoothing function for better BLEU calculation, especially for short sentences or small test sets
|
| 79 |
+
smooth = SmoothingFunction().method1
|
| 80 |
+
|
| 81 |
+
# Calculate corpus-level BLEU scores for different n-grams
|
| 82 |
+
bleu_1 = corpus_bleu(ref_tokens, hyp_tokens, weights=(1, 0, 0, 0), smoothing_function=smooth)
|
| 83 |
+
bleu_2 = corpus_bleu(ref_tokens, hyp_tokens, weights=(0.5, 0.5, 0, 0), smoothing_function=smooth)
|
| 84 |
+
bleu_3 = corpus_bleu(ref_tokens, hyp_tokens, weights=(0.33, 0.33, 0.33, 0), smoothing_function=smooth)
|
| 85 |
+
bleu_4 = corpus_bleu(ref_tokens, hyp_tokens, weights=(0.25, 0.25, 0.25, 0.25), smoothing_function=smooth)
|
| 86 |
+
|
| 87 |
+
return {
|
| 88 |
+
'BLEU-1': bleu_1,
|
| 89 |
+
'BLEU-2': bleu_2,
|
| 90 |
+
'BLEU-3': bleu_3,
|
| 91 |
+
'BLEU-4': bleu_4
|
| 92 |
+
}
|
| 93 |
+
except Exception as e:
|
| 94 |
+
logger.error(f"Error calculating BLEU scores: {e}")
|
| 95 |
+
return {'BLEU-1': 0, 'BLEU-2': 0, 'BLEU-3': 0, 'BLEU-4': 0}
|
| 96 |
+
|
| 97 |
+
|
| 98 |
+
def calculate_meteor_score(references, hypotheses):
|
| 99 |
+
"""
|
| 100 |
+
Calculates the METEOR score for a corpus.
|
| 101 |
+
Args:
|
| 102 |
+
references (list of str): List of reference captions.
|
| 103 |
+
hypotheses (list of str): List of hypothesis (generated) captions.
|
| 104 |
+
Returns:
|
| 105 |
+
float: Average METEOR score, or None if NLTK/WordNet not available.
|
| 106 |
+
"""
|
| 107 |
+
if meteor_score is None or word_tokenize is None:
|
| 108 |
+
logger.error("NLTK requirements for METEOR (wordnet) not met. Returning None for METEOR score.")
|
| 109 |
+
return None
|
| 110 |
+
|
| 111 |
+
scores = []
|
| 112 |
+
try:
|
| 113 |
+
for ref, hyp in zip(references, hypotheses):
|
| 114 |
+
ref_tokens = word_tokenize(ref.lower())
|
| 115 |
+
hyp_tokens = word_tokenize(hyp.lower())
|
| 116 |
+
# meteor_score expects a list of reference sentences (even if only one)
|
| 117 |
+
score = meteor_score([ref_tokens], hyp_tokens)
|
| 118 |
+
scores.append(score)
|
| 119 |
+
|
| 120 |
+
return np.mean(scores) if scores else 0.0
|
| 121 |
+
except Exception as e:
|
| 122 |
+
logger.error(f"Error calculating METEOR score: {e}")
|
| 123 |
+
return None
|
| 124 |
+
|
| 125 |
+
|
| 126 |
+
def calculate_rouge_l_score(references, hypotheses):
|
| 127 |
+
"""
|
| 128 |
+
Calculates the ROUGE-L F-measure score for a corpus.
|
| 129 |
+
Args:
|
| 130 |
+
references (list of str): List of reference captions.
|
| 131 |
+
hypotheses (list of str): List of hypothesis (generated) captions.
|
| 132 |
+
Returns:
|
| 133 |
+
float: Average ROUGE-L score, or None if rouge-score library not available.
|
| 134 |
+
"""
|
| 135 |
+
if rouge_scorer is None:
|
| 136 |
+
logger.error("rouge-score library not available. Returning None for ROUGE-L score.")
|
| 137 |
+
return None
|
| 138 |
+
|
| 139 |
+
try:
|
| 140 |
+
# Use 'rougeL' for Longest Common Subsequence based ROUGE
|
| 141 |
+
scorer = rouge_scorer.RougeScorer(['rougeL'], use_stemmer=True)
|
| 142 |
+
scores = []
|
| 143 |
+
|
| 144 |
+
for ref, hyp in zip(references, hypotheses):
|
| 145 |
+
score = scorer.score(ref, hyp)
|
| 146 |
+
scores.append(score['rougeL'].fmeasure) # We are interested in the F-measure
|
| 147 |
+
|
| 148 |
+
return np.mean(scores) if scores else 0.0
|
| 149 |
+
except Exception as e:
|
| 150 |
+
logger.error(f"Error calculating ROUGE-L score: {e}")
|
| 151 |
+
return None
|
| 152 |
+
|
| 153 |
+
|
| 154 |
+
def calculate_cider_score(references, hypotheses):
|
| 155 |
+
"""
|
| 156 |
+
Calculates the CIDEr score using pycocoevalcap library.
|
| 157 |
+
Requires pycocotools and pycocoevalcap to be installed.
|
| 158 |
+
Args:
|
| 159 |
+
references (list of str): List of reference captions.
|
| 160 |
+
hypotheses (list of str): List of hypothesis (generated) captions.
|
| 161 |
+
Returns:
|
| 162 |
+
float: CIDEr score, or None if pycocotools/pycocoevalcap not available.
|
| 163 |
+
"""
|
| 164 |
+
if COCO is None or COCOEvalCap is None or tempfile is None:
|
| 165 |
+
logger.error("pycocotools or pycocoevalcap not available. Returning None for CIDEr score.")
|
| 166 |
+
return None
|
| 167 |
+
|
| 168 |
+
try:
|
| 169 |
+
# pycocoevalcap requires data in a specific COCO format
|
| 170 |
+
# Create dummy image IDs for the COCO objects
|
| 171 |
+
dummy_image_ids = list(range(len(references)))
|
| 172 |
+
|
| 173 |
+
# Format references for COCO
|
| 174 |
+
refs_coco_format = []
|
| 175 |
+
for i, ref_str in enumerate(references):
|
| 176 |
+
refs_coco_format.append({"image_id": dummy_image_ids[i], "id": i, "caption": ref_str})
|
| 177 |
+
|
| 178 |
+
# Format hypotheses for COCO
|
| 179 |
+
hyps_coco_format = []
|
| 180 |
+
for i, hyp_str in enumerate(hypotheses):
|
| 181 |
+
hyps_coco_format.append({"image_id": dummy_image_ids[i], "id": i, "caption": hyp_str})
|
| 182 |
+
|
| 183 |
+
# Save to temporary JSON files as required by COCO/COCOEvalCap
|
| 184 |
+
with tempfile.NamedTemporaryFile(mode='w', delete=False, suffix='.json') as f_ref:
|
| 185 |
+
# Need to create a minimal COCO-like structure for references
|
| 186 |
+
json.dump({"annotations": refs_coco_format, "images": [{"id": i} for i in dummy_image_ids]}, f_ref)
|
| 187 |
+
ref_path = f_ref.name
|
| 188 |
+
|
| 189 |
+
with tempfile.NamedTemporaryFile(mode='w', delete=False, suffix='.json') as f_hyp:
|
| 190 |
+
json.dump(hyps_coco_format, f_hyp)
|
| 191 |
+
hyp_path = f_hyp.name
|
| 192 |
+
|
| 193 |
+
# Initialize COCO and COCOEvalCap objects
|
| 194 |
+
coco = COCO(ref_path)
|
| 195 |
+
cocoRes = coco.loadRes(hyp_path)
|
| 196 |
+
|
| 197 |
+
cocoEval = COCOEvalCap(coco, cocoRes)
|
| 198 |
+
cocoEval.params['image_id'] = cocoRes.getImgIds() # Specify images to evaluate
|
| 199 |
+
cocoEval.evaluate() # Perform evaluation
|
| 200 |
+
|
| 201 |
+
# Clean up temporary files
|
| 202 |
+
os.remove(ref_path)
|
| 203 |
+
os.remove(hyp_path)
|
| 204 |
+
|
| 205 |
+
return cocoEval.eval['CIDEr'] # CIDEr score is directly available
|
| 206 |
+
except Exception as e:
|
| 207 |
+
logger.error(f"Error calculating CIDEr score: {e}")
|
| 208 |
+
return None
|
| 209 |
+
|
| 210 |
+
|
| 211 |
+
def calculate_length_statistics(generated_captions, reference_captions):
|
| 212 |
+
"""
|
| 213 |
+
Calculates statistics related to caption lengths.
|
| 214 |
+
Args:
|
| 215 |
+
generated_captions (list of str): List of generated captions.
|
| 216 |
+
reference_captions (list of str): List of reference captions.
|
| 217 |
+
Returns:
|
| 218 |
+
dict: Dictionary containing average, std dev, and difference in lengths.
|
| 219 |
+
"""
|
| 220 |
+
gen_lengths = [len(cap.split()) for cap in generated_captions]
|
| 221 |
+
ref_lengths = [len(cap.split()) for cap in reference_captions]
|
| 222 |
+
|
| 223 |
+
return {
|
| 224 |
+
'avg_generated_length': np.mean(gen_lengths) if gen_lengths else 0,
|
| 225 |
+
'avg_reference_length': np.mean(ref_lengths) if ref_lengths else 0,
|
| 226 |
+
'length_difference': (np.mean(gen_lengths) - np.mean(ref_lengths)) if gen_lengths and ref_lengths else 0,
|
| 227 |
+
'length_std_generated': np.std(gen_lengths) if gen_lengths else 0,
|
| 228 |
+
'length_std_reference': np.std(ref_lengths) if ref_lengths else 0
|
| 229 |
+
}
|
| 230 |
+
|
| 231 |
+
|
| 232 |
+
def calculate_vocabulary_statistics(generated_captions, vocabulary):
|
| 233 |
+
"""
|
| 234 |
+
Calculates vocabulary usage statistics for generated captions.
|
| 235 |
+
Args:
|
| 236 |
+
generated_captions (list of str): List of generated captions.
|
| 237 |
+
vocabulary (COCOVocabulary): The vocabulary object used by the model.
|
| 238 |
+
Returns:
|
| 239 |
+
dict: Dictionary with unique word count, vocabulary coverage, etc.
|
| 240 |
+
"""
|
| 241 |
+
all_words = []
|
| 242 |
+
from collections import Counter # Import here to avoid circular dependency issues
|
| 243 |
+
for caption in generated_captions:
|
| 244 |
+
words = caption.lower().split()
|
| 245 |
+
all_words.extend(words)
|
| 246 |
+
|
| 247 |
+
unique_words = set(all_words)
|
| 248 |
+
word_freq = Counter(all_words)
|
| 249 |
+
|
| 250 |
+
return {
|
| 251 |
+
'unique_words_used': len(unique_words),
|
| 252 |
+
'total_vocabulary_size': vocabulary.vocab_size,
|
| 253 |
+
'vocabulary_coverage': len(unique_words) / vocabulary.vocab_size if vocabulary.vocab_size > 0 else 0,
|
| 254 |
+
'avg_word_frequency': np.mean(list(word_freq.values())) if word_freq else 0,
|
| 255 |
+
'most_common_generated_words': word_freq.most_common(10)
|
| 256 |
+
}
|
| 257 |
+
|
| 258 |
+
|
| 259 |
+
def calculate_diversity_metrics(generated_captions):
|
| 260 |
+
"""
|
| 261 |
+
Calculates diversity metrics for generated captions, such as Type-Token Ratio (TTR),
|
| 262 |
+
Self-BLEU, and caption uniqueness.
|
| 263 |
+
Args:
|
| 264 |
+
generated_captions (list of str): List of generated captions.
|
| 265 |
+
Returns:
|
| 266 |
+
dict: Dictionary containing diversity metrics.
|
| 267 |
+
"""
|
| 268 |
+
# Type-Token Ratio (TTR)
|
| 269 |
+
all_words = []
|
| 270 |
+
from collections import Counter
|
| 271 |
+
for caption in generated_captions:
|
| 272 |
+
words = caption.lower().split()
|
| 273 |
+
all_words.extend(words)
|
| 274 |
+
|
| 275 |
+
unique_words = set(all_words)
|
| 276 |
+
ttr = len(unique_words) / len(all_words) if all_words else 0
|
| 277 |
+
|
| 278 |
+
# Self-BLEU (diversity measure) - calculate on a subset for efficiency
|
| 279 |
+
self_bleu = 0
|
| 280 |
+
try:
|
| 281 |
+
if corpus_bleu and word_tokenize and SmoothingFunction:
|
| 282 |
+
smooth = SmoothingFunction().method1
|
| 283 |
+
self_bleu_scores = []
|
| 284 |
+
|
| 285 |
+
# Sample a subset of generated captions for Self-BLEU to avoid long computation
|
| 286 |
+
sample_size = min(1000, len(generated_captions))
|
| 287 |
+
sampled_captions = random.sample(generated_captions, sample_size) if len(generated_captions) > sample_size else generated_captions
|
| 288 |
+
|
| 289 |
+
for i, caption in enumerate(sampled_captions):
|
| 290 |
+
# References are all other captions in the sample
|
| 291 |
+
references_for_self_bleu = [[word_tokenize(other_cap.lower())]
|
| 292 |
+
for j, other_cap in enumerate(sampled_captions) if i != j]
|
| 293 |
+
hypothesis = word_tokenize(caption.lower())
|
| 294 |
+
|
| 295 |
+
if references_for_self_bleu and hypothesis: # Ensure there are references and hypothesis tokens
|
| 296 |
+
# Calculate sentence BLEU with other captions as references
|
| 297 |
+
score = corpus_bleu(references_for_self_bleu, [hypothesis], smoothing_function=smooth)
|
| 298 |
+
self_bleu_scores.append(score)
|
| 299 |
+
|
| 300 |
+
self_bleu = np.mean(self_bleu_scores) if self_bleu_scores else 0
|
| 301 |
+
else:
|
| 302 |
+
logger.warning("NLTK not fully available for Self-BLEU calculation. Skipping.")
|
| 303 |
+
except Exception as e:
|
| 304 |
+
logger.error(f"Error calculating Self-BLEU: {e}")
|
| 305 |
+
self_bleu = 0
|
| 306 |
+
|
| 307 |
+
# Caption uniqueness
|
| 308 |
+
unique_captions = len(set(generated_captions))
|
| 309 |
+
uniqueness_ratio = unique_captions / len(generated_captions) if len(generated_captions) > 0 else 0
|
| 310 |
+
|
| 311 |
+
return {
|
| 312 |
+
'type_token_ratio': ttr,
|
| 313 |
+
'self_bleu': self_bleu,
|
| 314 |
+
'unique_captions_count': unique_captions,
|
| 315 |
+
'caption_uniqueness_ratio': uniqueness_ratio
|
| 316 |
+
}
|
| 317 |
+
|
| 318 |
+
|
| 319 |
+
def calculate_perplexity(model, data_loader, vocabulary, device):
|
| 320 |
+
"""
|
| 321 |
+
Calculates the perplexity of the model on a given dataset.
|
| 322 |
+
Perplexity measures how well a probability model predicts a sample. Lower is better.
|
| 323 |
+
Args:
|
| 324 |
+
model (nn.Module): The trained image captioning model.
|
| 325 |
+
data_loader (DataLoader): DataLoader for the dataset.
|
| 326 |
+
vocabulary (COCOVocabulary): The vocabulary object.
|
| 327 |
+
device (torch.device): Device to run calculation on.
|
| 328 |
+
Returns:
|
| 329 |
+
float: Perplexity score, or infinity if calculation fails.
|
| 330 |
+
"""
|
| 331 |
+
model.eval()
|
| 332 |
+
total_loss = 0
|
| 333 |
+
total_words = 0
|
| 334 |
+
|
| 335 |
+
# Use CrossEntropyLoss with sum reduction to get the sum of losses over all tokens
|
| 336 |
+
criterion = torch.nn.CrossEntropyLoss(ignore_index=vocabulary.word2idx['<PAD>'], reduction='sum')
|
| 337 |
+
|
| 338 |
+
with torch.no_grad():
|
| 339 |
+
for images, captions_from_loader, caption_lengths_from_loader, _ in tqdm(data_loader, desc="Calculating Perplexity"):
|
| 340 |
+
images = images.to(device)
|
| 341 |
+
captions_for_model = captions_from_loader.to(device)
|
| 342 |
+
caption_lengths_for_model = caption_lengths_from_loader.to(device)
|
| 343 |
+
|
| 344 |
+
# Forward pass to get scores
|
| 345 |
+
scores, caps_sorted, decode_lengths, _, _ = model(images, captions_for_model, caption_lengths_for_model)
|
| 346 |
+
|
| 347 |
+
# Prepare targets: remove <START> token and slice to match the sequence length of 'scores'.
|
| 348 |
+
# scores are (batch_size, max_decode_len_in_batch, vocab_size)
|
| 349 |
+
# targets should be (batch_size, max_decode_len_in_batch)
|
| 350 |
+
targets = caps_sorted[:, 1:scores.size(1) + 1].contiguous().view(-1) # Flatten targets
|
| 351 |
+
scores_flat = scores.view(-1, scores.size(-1)) # Flatten scores
|
| 352 |
+
|
| 353 |
+
loss = criterion(scores_flat, targets) # Calculate loss for all tokens
|
| 354 |
+
total_loss += loss.item()
|
| 355 |
+
|
| 356 |
+
# Count non-padded words in the targets that were actually used for loss.
|
| 357 |
+
num_valid_targets_in_batch = targets.ne(vocabulary.word2idx['<PAD>']).sum().item()
|
| 358 |
+
total_words += num_valid_targets_in_batch
|
| 359 |
+
|
| 360 |
+
if total_words == 0:
|
| 361 |
+
logger.warning("No valid words found to calculate perplexity (total_words is 0). Returning inf.")
|
| 362 |
+
return float('inf')
|
| 363 |
+
|
| 364 |
+
avg_loss_per_word = total_loss / total_words
|
| 365 |
+
|
| 366 |
+
# Perplexity is exp(average negative log-likelihood)
|
| 367 |
+
try:
|
| 368 |
+
perplexity = math.exp(avg_loss_per_word)
|
| 369 |
+
except OverflowError: # Handle cases where avg_loss_per_word is very large, leading to overflow
|
| 370 |
+
perplexity = float('inf')
|
| 371 |
+
|
| 372 |
+
return perplexity
|
| 373 |
+
|
| 374 |
+
|
| 375 |
+
def print_evaluation_results(metrics):
|
| 376 |
+
"""
|
| 377 |
+
Prints the evaluation results in a formatted way.
|
| 378 |
+
Args:
|
| 379 |
+
metrics (dict): Dictionary containing all evaluation metrics.
|
| 380 |
+
"""
|
| 381 |
+
logger.info("\n"+"="*60)
|
| 382 |
+
logger.info(" EVALUATION RESULTS")
|
| 383 |
+
logger.info("="*60)
|
| 384 |
+
|
| 385 |
+
# BLEU Scores
|
| 386 |
+
if 'BLEU-1' in metrics:
|
| 387 |
+
logger.info(f"\nBLEU Scores:")
|
| 388 |
+
logger.info(f" BLEU-1: {metrics['BLEU-1']:.4f}")
|
| 389 |
+
logger.info(f" BLEU-2: {metrics['BLEU-2']:.4f}")
|
| 390 |
+
logger.info(f" BLEU-3: {metrics['BLEU-3']:.4f}")
|
| 391 |
+
logger.info(f" BLEU-4: {metrics['BLEU-4']:.4f}")
|
| 392 |
+
|
| 393 |
+
# Other metrics
|
| 394 |
+
if 'METEOR' in metrics and metrics['METEOR'] is not None:
|
| 395 |
+
logger.info(f"\nMETEOR Score: {metrics['METEOR']:.4f}")
|
| 396 |
+
|
| 397 |
+
if 'ROUGE-L' in metrics and metrics['ROUGE-L'] is not None:
|
| 398 |
+
logger.info(f"ROUGE-L Score: {metrics['ROUGE-L']:.4f}")
|
| 399 |
+
|
| 400 |
+
if 'CIDEr' in metrics and metrics['CIDEr'] is not None:
|
| 401 |
+
logger.info(f"CIDEr Score: {metrics['CIDEr']:.4f}")
|
| 402 |
+
|
| 403 |
+
if 'Perplexity' in metrics and metrics['Perplexity'] is not None:
|
| 404 |
+
logger.info(f"Perplexity: {metrics['Perplexity']:.2f}")
|
| 405 |
+
|
| 406 |
+
# Length Statistics
|
| 407 |
+
logger.info(f"\nLength Statistics:")
|
| 408 |
+
logger.info(f" Avg Generated Length: {metrics.get('avg_generated_length', 0):.2f}")
|
| 409 |
+
logger.info(f" Avg Reference Length: {metrics.get('avg_reference_length', 0):.2f}")
|
| 410 |
+
logger.info(f" Length Difference (Gen - Ref): {metrics.get('length_difference', 0):.2f}")
|
| 411 |
+
logger.info(f" Std Dev Generated Length: {metrics.get('length_std_generated', 0):.2f}")
|
| 412 |
+
logger.info(f" Std Dev Reference Length: {metrics.get('length_std_reference', 0):.2f}")
|
| 413 |
+
|
| 414 |
+
# Diversity Metrics
|
| 415 |
+
logger.info(f"\nDiversity Metrics:")
|
| 416 |
+
logger.info(f" Type-Token Ratio: {metrics.get('type_token_ratio', 0):.4f}")
|
| 417 |
+
logger.info(f" Caption Uniqueness Ratio: {metrics.get('caption_uniqueness_ratio', 0):.4f}")
|
| 418 |
+
logger.info(f" Self-BLEU (Higher is lower diversity): {metrics.get('self_bleu', 0):.4f}")
|
| 419 |
+
logger.info(f" Unique Captions Count: {metrics.get('unique_captions_count', 0)}")
|
| 420 |
+
|
| 421 |
+
# Vocabulary Usage
|
| 422 |
+
logger.info(f"\nVocabulary Usage:")
|
| 423 |
+
logger.info(f" Unique Words Used in Generated Captions: {metrics.get('unique_words_used', 0)}")
|
| 424 |
+
logger.info(f" Vocabulary Coverage (Used / Total): {metrics.get('vocabulary_coverage', 0):.4f}")
|
| 425 |
+
if 'most_common_generated_words' in metrics:
|
| 426 |
+
logger.info(f" Most Common Generated Words: {metrics['most_common_generated_words']}")
|
| 427 |
+
|
| 428 |
+
logger.info(f"\nEvaluation Info:")
|
| 429 |
+
eval_info = metrics.get('evaluation_info', {})
|
| 430 |
+
logger.info(f" Total Samples Evaluated: {eval_info.get('total_samples', 0)}")
|
| 431 |
+
logger.info(f" Evaluation Time: {eval_info.get('evaluation_time_seconds', 0):.2f}s")
|
| 432 |
+
logger.info(f" Test Data Path: {eval_info.get('test_data_path', 'N/A')}")
|
| 433 |
+
logger.info(f" Image Directory Used: {eval_info.get('image_dir_used', 'N/A')}")
|
| 434 |
+
logger.info(f" Device: {eval_info.get('device', 'unknown')}")
|
| 435 |
+
logger.info(f" Model Architecture: {eval_info.get('model_architecture', 'N/A')}")
|
| 436 |
+
|
| 437 |
+
logger.info("="*60)
|
| 438 |
+
|
| 439 |
+
|
| 440 |
+
def save_evaluation_results(metrics, generated_captions, reference_captions, image_ids, output_dir='evaluation_results'):
|
| 441 |
+
"""
|
| 442 |
+
Saves detailed evaluation results to JSON files.
|
| 443 |
+
Args:
|
| 444 |
+
metrics (dict): Dictionary containing all evaluation metrics.
|
| 445 |
+
generated_captions (list of str): List of generated captions.
|
| 446 |
+
reference_captions (list of str): List of reference captions.
|
| 447 |
+
image_ids (list): List of original image IDs corresponding to captions.
|
| 448 |
+
output_dir (str): Directory to save the results.
|
| 449 |
+
"""
|
| 450 |
+
os.makedirs(output_dir, exist_ok=True) # Ensure output directory exists
|
| 451 |
+
|
| 452 |
+
# Save metrics
|
| 453 |
+
metrics_path = os.path.join(output_dir, 'metrics.json')
|
| 454 |
+
# Convert numpy types to Python types for JSON serialization
|
| 455 |
+
serializable_metrics = {}
|
| 456 |
+
for key, value in metrics.items():
|
| 457 |
+
if isinstance(value, (np.float32, np.float64)):
|
| 458 |
+
serializable_metrics[key] = float(value)
|
| 459 |
+
elif isinstance(value, (np.int32, np.int64)):
|
| 460 |
+
serializable_metrics[key] = int(value)
|
| 461 |
+
else:
|
| 462 |
+
serializable_metrics[key] = value
|
| 463 |
+
|
| 464 |
+
with open(metrics_path, 'w') as f:
|
| 465 |
+
json.dump(serializable_metrics, f, indent=2)
|
| 466 |
+
|
| 467 |
+
# Save generated captions and their references along with image_ids
|
| 468 |
+
captions_data = []
|
| 469 |
+
for img_id, gen_cap, ref_cap in zip(image_ids, generated_captions, reference_captions):
|
| 470 |
+
captions_data.append({
|
| 471 |
+
'image_id': img_id,
|
| 472 |
+
'generated_caption': gen_cap,
|
| 473 |
+
'reference_caption': ref_cap
|
| 474 |
+
})
|
| 475 |
+
|
| 476 |
+
captions_path = os.path.join(output_dir, 'captions.json')
|
| 477 |
+
with open(captions_path, 'w') as f:
|
| 478 |
+
json.dump(captions_data, f, indent=2)
|
| 479 |
+
|
| 480 |
+
logger.info(f"\nDetailed evaluation results saved to: {output_dir}/")
|
| 481 |
+
logger.info(f"Metrics saved to: {metrics_path}")
|
| 482 |
+
logger.info(f"Captions saved to: {captions_path}")
|
| 483 |
+
|
| 484 |
+
|
| 485 |
+
def perform_evaluation(model, vocabulary, test_config):
|
| 486 |
+
"""
|
| 487 |
+
Performs comprehensive evaluation of the image captioning model on a test set.
|
| 488 |
+
|
| 489 |
+
Args:
|
| 490 |
+
model (nn.Module): The trained image captioning model.
|
| 491 |
+
vocabulary (COCOVocabulary): The vocabulary object used by the model.
|
| 492 |
+
test_config (dict): Configuration dictionary for evaluation.
|
| 493 |
+
|
| 494 |
+
Returns:
|
| 495 |
+
dict: Dictionary containing all evaluation metrics.
|
| 496 |
+
"""
|
| 497 |
+
logger.info("Starting comprehensive model evaluation...")
|
| 498 |
+
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
|
| 499 |
+
model.to(device)
|
| 500 |
+
model.eval() # Set model to evaluation mode
|
| 501 |
+
logger.info(f"Model set to evaluation mode on device: {device}")
|
| 502 |
+
|
| 503 |
+
# Data paths for evaluation from config
|
| 504 |
+
data_folder = test_config['data_folder']
|
| 505 |
+
test_image_folder = test_config['test_image_folder']
|
| 506 |
+
test_caption_file = test_config['test_caption_file']
|
| 507 |
+
|
| 508 |
+
if not os.path.exists(test_caption_file):
|
| 509 |
+
raise FileNotFoundError(f"Test caption file not found: {test_caption_file}")
|
| 510 |
+
|
| 511 |
+
# Construct the correct image directory path for evaluation
|
| 512 |
+
image_dir_for_eval = os.path.join(data_folder, test_image_folder)
|
| 513 |
+
if not os.path.exists(image_dir_for_eval):
|
| 514 |
+
logger.error(f"Image directory for evaluation not found: {image_dir_for_eval}")
|
| 515 |
+
logger.error("Please ensure COCO images are extracted to the correct path.")
|
| 516 |
+
return {'error': f'Image directory not found: {image_dir_for_eval}'}
|
| 517 |
+
|
| 518 |
+
logger.info(f"Attempting to load evaluation images from directory: {image_dir_for_eval}")
|
| 519 |
+
|
| 520 |
+
# Create test dataset
|
| 521 |
+
test_dataset = COCODataset(
|
| 522 |
+
image_dir=image_dir_for_eval,
|
| 523 |
+
caption_file=test_caption_file,
|
| 524 |
+
vocabulary=vocabulary, # Use the vocabulary from training
|
| 525 |
+
max_caption_length=test_config.get('max_caption_length', 20),
|
| 526 |
+
subset_size=test_config.get('test_subset_size'),
|
| 527 |
+
transform=get_eval_transform() # Use standard eval transform
|
| 528 |
+
)
|
| 529 |
+
|
| 530 |
+
test_loader = DataLoader(
|
| 531 |
+
test_dataset,
|
| 532 |
+
batch_size=test_config.get('eval_batch_size', 1), # Batch size 1 is crucial for beam search
|
| 533 |
+
shuffle=False, # Do not shuffle test data
|
| 534 |
+
num_workers=test_config.get('num_workers', 2),
|
| 535 |
+
pin_memory=True
|
| 536 |
+
)
|
| 537 |
+
|
| 538 |
+
logger.info(f"Test dataset size: {len(test_dataset)}")
|
| 539 |
+
|
| 540 |
+
if len(test_dataset) == 0:
|
| 541 |
+
logger.warning("Test dataset is empty. Evaluation will not produce meaningful results.")
|
| 542 |
+
return {'error': 'Test dataset is empty', 'image_dir_checked': image_dir_for_eval}
|
| 543 |
+
|
| 544 |
+
# Generate captions for all test images
|
| 545 |
+
logger.info("Generating captions for evaluation set...")
|
| 546 |
+
generated_captions_list = []
|
| 547 |
+
reference_captions_list = []
|
| 548 |
+
image_ids_list = [] # To store original image IDs for mapping
|
| 549 |
+
|
| 550 |
+
eval_start_time = time.time()
|
| 551 |
+
|
| 552 |
+
with torch.no_grad(): # Disable gradient calculations
|
| 553 |
+
for i, (images, caption_indices_batch, _, original_image_ids_batch) in enumerate(tqdm(test_loader, desc="Generating captions")):
|
| 554 |
+
images = images.to(device)
|
| 555 |
+
|
| 556 |
+
for j in range(images.size(0)): # Iterate through batch (should be size 1 if eval_batch_size=1)
|
| 557 |
+
image_tensor_single = images[j] # Get single image tensor from batch
|
| 558 |
+
|
| 559 |
+
# Generate caption using the model's beam search method
|
| 560 |
+
generated_caption = model.generate_caption(
|
| 561 |
+
image_tensor_single, vocabulary, device,
|
| 562 |
+
beam_size=test_config.get('beam_size', 5),
|
| 563 |
+
max_length=test_config.get('max_caption_length', 20)
|
| 564 |
+
)
|
| 565 |
+
|
| 566 |
+
# Convert reference caption indices back to string
|
| 567 |
+
reference_caption_str = vocabulary.indices_to_caption(caption_indices_batch[j].cpu().numpy())
|
| 568 |
+
|
| 569 |
+
generated_captions_list.append(generated_caption)
|
| 570 |
+
reference_captions_list.append(reference_caption_str)
|
| 571 |
+
# Ensure image_id is a string or compatible type for JSON serialization
|
| 572 |
+
image_ids_list.append(str(original_image_ids_batch[j].item()))
|
| 573 |
+
|
| 574 |
+
eval_time = time.time() - eval_start_time
|
| 575 |
+
logger.info(f"Caption generation completed in {eval_time:.2f} seconds for {len(generated_captions_list)} images.")
|
| 576 |
+
|
| 577 |
+
if not generated_captions_list or not reference_captions_list:
|
| 578 |
+
logger.error("No captions were generated or no reference captions were loaded. Cannot calculate metrics.")
|
| 579 |
+
return {'error': 'No generated or reference captions available for metric calculation.'}
|
| 580 |
+
|
| 581 |
+
# Calculate evaluation metrics
|
| 582 |
+
logger.info("Calculating evaluation metrics...")
|
| 583 |
+
metrics = {}
|
| 584 |
+
|
| 585 |
+
# Calculate standard metrics
|
| 586 |
+
bleu_scores = calculate_bleu_scores_detailed(reference_captions_list, generated_captions_list)
|
| 587 |
+
metrics.update(bleu_scores)
|
| 588 |
+
|
| 589 |
+
meteor_score_val = calculate_meteor_score(reference_captions_list, generated_captions_list)
|
| 590 |
+
if meteor_score_val is not None:
|
| 591 |
+
metrics['METEOR'] = meteor_score_val
|
| 592 |
+
|
| 593 |
+
rouge_score_val = calculate_rouge_l_score(reference_captions_list, generated_captions_list)
|
| 594 |
+
if rouge_score_val is not None:
|
| 595 |
+
metrics['ROUGE-L'] = rouge_score_val
|
| 596 |
+
|
| 597 |
+
cider_score_val = calculate_cider_score(reference_captions_list, generated_captions_list)
|
| 598 |
+
if cider_score_val is not None:
|
| 599 |
+
metrics['CIDEr'] = cider_score_val
|
| 600 |
+
|
| 601 |
+
# Calculate length and diversity statistics
|
| 602 |
+
length_stats = calculate_length_statistics(generated_captions_list, reference_captions_list)
|
| 603 |
+
metrics.update(length_stats)
|
| 604 |
+
|
| 605 |
+
vocab_stats = calculate_vocabulary_statistics(generated_captions_list, vocabulary)
|
| 606 |
+
metrics.update(vocab_stats)
|
| 607 |
+
|
| 608 |
+
diversity_stats = calculate_diversity_metrics(generated_captions_list)
|
| 609 |
+
metrics.update(diversity_stats)
|
| 610 |
+
|
| 611 |
+
# Calculate perplexity
|
| 612 |
+
try:
|
| 613 |
+
perplexity = calculate_perplexity(model, test_loader, vocabulary, device)
|
| 614 |
+
metrics['Perplexity'] = perplexity
|
| 615 |
+
except Exception as e:
|
| 616 |
+
logger.error(f"Could not calculate perplexity: {e}")
|
| 617 |
+
|
| 618 |
+
# Add meta information about the evaluation run
|
| 619 |
+
metrics['evaluation_info'] = {
|
| 620 |
+
'total_samples': len(generated_captions_list),
|
| 621 |
+
'evaluation_time_seconds': eval_time,
|
| 622 |
+
'test_data_path': test_caption_file,
|
| 623 |
+
'image_dir_used': image_dir_for_eval,
|
| 624 |
+
'device': str(device),
|
| 625 |
+
'model_architecture': 'ResNet50 Encoder + LSTM Decoder with Attention',
|
| 626 |
+
'beam_size_for_inference': test_config.get('beam_size', 5),
|
| 627 |
+
'max_caption_length_for_inference': test_config.get('max_caption_length', 20)
|
| 628 |
+
}
|
| 629 |
+
|
| 630 |
+
# Print and save results
|
| 631 |
+
print_evaluation_results(metrics)
|
| 632 |
+
save_evaluation_results(metrics, generated_captions_list, reference_captions_list, image_ids_list, output_dir=test_config.get('eval_output_dir', 'output/evaluation_results'))
|
| 633 |
+
|
| 634 |
+
return metrics
|
| 635 |
+
|
| 636 |
+
|
| 637 |
+
if __name__ == '__main__':
|
| 638 |
+
# When `evaluation.py` is run directly, it will perform evaluation.
|
| 639 |
+
from .config import EVALUATION_CONFIG, update_config_with_latest_model
|
| 640 |
+
import pickle # For loading vocabulary
|
| 641 |
+
|
| 642 |
+
logger.info("Starting model evaluation process...")
|
| 643 |
+
|
| 644 |
+
# Load the vocabulary first
|
| 645 |
+
VOCABULARY_FILE_PATH = 'output/vocabulary.pkl' # Path to the vocabulary file
|
| 646 |
+
if not os.path.exists(VOCABULARY_FILE_PATH):
|
| 647 |
+
logger.error(f"Vocabulary not found at {VOCABULARY_FILE_PATH}. Please train the model first or provide a pre-trained vocabulary.")
|
| 648 |
+
exit() # Exit if vocabulary is not found
|
| 649 |
+
try:
|
| 650 |
+
with open(VOCABULARY_FILE_PATH, 'rb') as f:
|
| 651 |
+
vocabulary = pickle.load(f)
|
| 652 |
+
logger.info(f"Loaded vocabulary from {VOCABULARY_FILE_PATH}")
|
| 653 |
+
except Exception as e:
|
| 654 |
+
logger.error(f"Error loading vocabulary from {VOCABULARY_FILE_PATH}: {e}")
|
| 655 |
+
exit()
|
| 656 |
+
|
| 657 |
+
# Update evaluation config to point to the latest trained model
|
| 658 |
+
update_config_with_latest_model(EVALUATION_CONFIG)
|
| 659 |
+
model_path = EVALUATION_CONFIG.get('model_path')
|
| 660 |
+
|
| 661 |
+
if not model_path or not os.path.exists(model_path):
|
| 662 |
+
logger.error(f"Model checkpoint not found at {model_path}. Please train the model or specify a valid model_path in config.py.")
|
| 663 |
+
exit()
|
| 664 |
+
|
| 665 |
+
try:
|
| 666 |
+
# Load the model state dict and config from the checkpoint
|
| 667 |
+
checkpoint = torch.load(model_path, map_location='cpu')
|
| 668 |
+
model_config_from_checkpoint = checkpoint.get('config', {})
|
| 669 |
+
|
| 670 |
+
# Initialize model with parameters from checkpoint config (or defaults if missing)
|
| 671 |
+
eval_model = ImageCaptioningModel(
|
| 672 |
+
vocab_size=vocabulary.vocab_size, # Use the loaded vocabulary's size
|
| 673 |
+
embed_dim=model_config_from_checkpoint.get('embed_dim', 256),
|
| 674 |
+
attention_dim=model_config_from_checkpoint.get('attention_dim', 256),
|
| 675 |
+
decoder_dim=model_config_from_checkpoint.get('decoder_dim', 256),
|
| 676 |
+
dropout=0.0, # No dropout during evaluation
|
| 677 |
+
fine_tune_encoder=False, # No fine-tuning during evaluation
|
| 678 |
+
max_caption_length=model_config_from_checkpoint.get('max_caption_length', 20)
|
| 679 |
+
)
|
| 680 |
+
eval_model.load_state_dict(checkpoint['model_state_dict'])
|
| 681 |
+
logger.info(f"Model loaded successfully from {model_path} for evaluation.")
|
| 682 |
+
|
| 683 |
+
# Perform the comprehensive evaluation
|
| 684 |
+
eval_metrics = perform_evaluation(eval_model, vocabulary, EVALUATION_CONFIG)
|
| 685 |
+
logger.info("Model Evaluation Complete!")
|
| 686 |
+
|
| 687 |
+
except FileNotFoundError as e:
|
| 688 |
+
logger.error(f"Error during evaluation setup: {e}")
|
| 689 |
+
logger.error("Please ensure the model path and data paths are correct.")
|
| 690 |
+
except Exception as e:
|
| 691 |
+
logger.critical(f"An unexpected error occurred during evaluation: {e}", exc_info=True)
|
src/inference_api.py
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import torch
|
| 3 |
+
from PIL import Image
|
| 4 |
+
|
| 5 |
+
# Import core model components and utilities using ABSOLUTE IMPORTS
|
| 6 |
+
# Since 'src' is added to sys.path, we refer to modules directly under 'src'.
|
| 7 |
+
from src.model import ImageCaptioningModel
|
| 8 |
+
from src.data_preprocessing import COCOVocabulary
|
| 9 |
+
from src.utils import get_logger, get_eval_transform
|
| 10 |
+
from src.config import INFERENCE_CONFIG, update_config_with_latest_model # Import global config
|
| 11 |
+
|
| 12 |
+
logger = get_logger(__name__)
|
| 13 |
+
|
| 14 |
+
# --- Global variables to store the loaded model and vocabulary ---
|
| 15 |
+
# These will be loaded once when this module is first imported.
|
| 16 |
+
_model = None
|
| 17 |
+
_vocabulary = None
|
| 18 |
+
_device = None
|
| 19 |
+
_transform = None
|
| 20 |
+
|
| 21 |
+
def _load_model_and_vocabulary():
|
| 22 |
+
"""
|
| 23 |
+
Loads the image captioning model and vocabulary.
|
| 24 |
+
This function should be called only once during application startup.
|
| 25 |
+
"""
|
| 26 |
+
global _model, _vocabulary, _device, _transform
|
| 27 |
+
|
| 28 |
+
if _model is not None:
|
| 29 |
+
logger.info("Model and vocabulary already loaded.")
|
| 30 |
+
return
|
| 31 |
+
|
| 32 |
+
logger.info("Initializing model and vocabulary for web inference...")
|
| 33 |
+
|
| 34 |
+
# Update INFERENCE_CONFIG with the path to the latest best model
|
| 35 |
+
# This ensures the web app uses the correct trained model.
|
| 36 |
+
update_config_with_latest_model(INFERENCE_CONFIG)
|
| 37 |
+
model_path = INFERENCE_CONFIG['model_path']
|
| 38 |
+
example_image_path = INFERENCE_CONFIG['example_image_path'] # Not directly used for inference, but useful for context
|
| 39 |
+
|
| 40 |
+
if not os.path.exists(model_path):
|
| 41 |
+
logger.error(f"Model checkpoint not found at {model_path}. "
|
| 42 |
+
"Please ensure the model is trained and saved.")
|
| 43 |
+
raise FileNotFoundError(f"Model checkpoint not found: {model_path}")
|
| 44 |
+
|
| 45 |
+
try:
|
| 46 |
+
# Load the complete checkpoint (model state, vocabulary, config)
|
| 47 |
+
checkpoint = torch.load(model_path, map_location='cpu', weights_only=False)
|
| 48 |
+
|
| 49 |
+
# Extract configuration and vocabulary from the checkpoint
|
| 50 |
+
model_config_from_checkpoint = checkpoint.get('config', {})
|
| 51 |
+
_vocabulary = checkpoint['vocabulary']
|
| 52 |
+
|
| 53 |
+
# Initialize the model structure with parameters saved in the checkpoint
|
| 54 |
+
_model = ImageCaptioningModel(
|
| 55 |
+
vocab_size=_vocabulary.vocab_size,
|
| 56 |
+
embed_dim=model_config_from_checkpoint.get('embed_dim', 256),
|
| 57 |
+
attention_dim=model_config_from_checkpoint.get('attention_dim', 256),
|
| 58 |
+
decoder_dim=model_config_from_checkpoint.get('decoder_dim', 256),
|
| 59 |
+
dropout=0.0, # Dropout should be off during inference
|
| 60 |
+
fine_tune_encoder=False, # Encoder should not be fine-tuned during inference
|
| 61 |
+
max_caption_length=INFERENCE_CONFIG.get('max_caption_length', 20)
|
| 62 |
+
)
|
| 63 |
+
# Load the trained weights into the model
|
| 64 |
+
_model.load_state_dict(checkpoint['model_state_dict'])
|
| 65 |
+
_model.eval() # Set the model to evaluation mode (important for batch norm, dropout)
|
| 66 |
+
|
| 67 |
+
# Determine the device to run inference on
|
| 68 |
+
_device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
|
| 69 |
+
_model = _model.to(_device) # Move model to GPU if available
|
| 70 |
+
logger.info(f"Model loaded successfully on device: {_device}")
|
| 71 |
+
|
| 72 |
+
# Get the image transformation pipeline for evaluation/inference
|
| 73 |
+
_transform = get_eval_transform()
|
| 74 |
+
|
| 75 |
+
logger.info("Model and vocabulary are ready for inference.")
|
| 76 |
+
|
| 77 |
+
except Exception as e:
|
| 78 |
+
logger.critical(f"Failed to load model or vocabulary: {e}", exc_info=True)
|
| 79 |
+
# Reraise the exception to prevent the Flask app from starting without the model
|
| 80 |
+
raise
|
| 81 |
+
|
| 82 |
+
# Call the loading function immediately when this module is imported
|
| 83 |
+
# This ensures the model is loaded only once when the Flask app starts
|
| 84 |
+
_load_model_and_vocabulary()
|
| 85 |
+
|
| 86 |
+
|
| 87 |
+
def generate_caption_for_image(image_path: str) -> str:
|
| 88 |
+
"""
|
| 89 |
+
Generates a caption for a given image path using the pre-loaded model.
|
| 90 |
+
|
| 91 |
+
Args:
|
| 92 |
+
image_path (str): The full path to the image file.
|
| 93 |
+
|
| 94 |
+
Returns:
|
| 95 |
+
str: The generated caption.
|
| 96 |
+
Raises:
|
| 97 |
+
FileNotFoundError: If the image file does not exist.
|
| 98 |
+
Exception: For errors during image loading or caption generation.
|
| 99 |
+
"""
|
| 100 |
+
if _model is None or _vocabulary is None or _transform is None or _device is None:
|
| 101 |
+
logger.error("Model or vocabulary not loaded. Cannot generate caption.")
|
| 102 |
+
raise RuntimeError("Image captioning model is not initialized.")
|
| 103 |
+
|
| 104 |
+
if not os.path.exists(image_path):
|
| 105 |
+
raise FileNotFoundError(f"Image not found at {image_path}.")
|
| 106 |
+
|
| 107 |
+
logger.info(f"Processing image: {image_path}")
|
| 108 |
+
|
| 109 |
+
try:
|
| 110 |
+
image = Image.open(image_path).convert('RGB')
|
| 111 |
+
image_tensor = _transform(image).to(_device)
|
| 112 |
+
except Exception as e:
|
| 113 |
+
raise Exception(f"Error loading or transforming image {image_path}: {e}")
|
| 114 |
+
|
| 115 |
+
# Generate the caption using the model's integrated method
|
| 116 |
+
generated_caption = _model.generate_caption(
|
| 117 |
+
image_tensor,
|
| 118 |
+
_vocabulary,
|
| 119 |
+
_device,
|
| 120 |
+
beam_size=INFERENCE_CONFIG.get('beam_size', 5),
|
| 121 |
+
max_length=INFERENCE_CONFIG.get('max_caption_length', 20)
|
| 122 |
+
)
|
| 123 |
+
logger.info(f"Generated caption: {generated_caption}")
|
| 124 |
+
return generated_caption
|
src/model.py
ADDED
|
@@ -0,0 +1,502 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import torch
|
| 2 |
+
import torch.nn as nn
|
| 3 |
+
import torch.nn.functional as F
|
| 4 |
+
import torchvision.models as models # Used for ResNet50
|
| 5 |
+
|
| 6 |
+
from .utils import get_logger # Import logger
|
| 7 |
+
|
| 8 |
+
logger = get_logger(__name__)
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
class EncoderCNN(nn.Module):
|
| 12 |
+
"""
|
| 13 |
+
Encoder using a pre-trained ResNet50 model.
|
| 14 |
+
The output feature maps are adaptively pooled to a fixed size
|
| 15 |
+
and then reshaped for the attention mechanism in the decoder.
|
| 16 |
+
"""
|
| 17 |
+
def __init__(self, encoded_image_size=14, fine_tune=True):
|
| 18 |
+
"""
|
| 19 |
+
Initializes the EncoderCNN.
|
| 20 |
+
Args:
|
| 21 |
+
encoded_image_size (int): The spatial dimension (e.g., 14x14) to which
|
| 22 |
+
the feature maps will be adaptively pooled.
|
| 23 |
+
fine_tune (bool): If True, allows the parameters of the pre-trained
|
| 24 |
+
ResNet to be updated during training. If False, they are frozen.
|
| 25 |
+
"""
|
| 26 |
+
super(EncoderCNN, self).__init__()
|
| 27 |
+
self.encoded_image_size = encoded_image_size
|
| 28 |
+
|
| 29 |
+
# Load pre-trained ResNet50 and remove the final classification layer
|
| 30 |
+
# We use the default recommended weights for ResNet50.
|
| 31 |
+
resnet = models.resnet50(weights=models.ResNet50_Weights.DEFAULT)
|
| 32 |
+
|
| 33 |
+
# Remove the average pooling layer and the fully connected layer at the end.
|
| 34 |
+
# We want the feature maps before these layers for spatial attention.
|
| 35 |
+
# The `modules` list will contain layers up to `layer4` (the last convolutional block).
|
| 36 |
+
modules = list(resnet.children())[:-2]
|
| 37 |
+
self.resnet = nn.Sequential(*modules)
|
| 38 |
+
|
| 39 |
+
# Freeze parameters of the pre-trained ResNet if fine_tune is False.
|
| 40 |
+
# This prevents updating their weights during training.
|
| 41 |
+
if not fine_tune:
|
| 42 |
+
for param in self.resnet.parameters():
|
| 43 |
+
param.requires_grad = False
|
| 44 |
+
logger.info("ResNet encoder base layers are frozen.")
|
| 45 |
+
else:
|
| 46 |
+
logger.info("ResNet encoder base layers are fine-tuning enabled.")
|
| 47 |
+
|
| 48 |
+
# Adaptive pool to a fixed size (e.g., 14x14).
|
| 49 |
+
# This ensures a consistent spatial dimension for the feature maps,
|
| 50 |
+
# regardless of the input image size, useful for attention.
|
| 51 |
+
self.adaptive_pool = nn.AdaptiveAvgPool2d((encoded_image_size, encoded_image_size))
|
| 52 |
+
|
| 53 |
+
# The output feature dimension from ResNet50 before the last avg pool/fc is 2048.
|
| 54 |
+
self.encoder_dim = 2048
|
| 55 |
+
|
| 56 |
+
def forward(self, images):
|
| 57 |
+
"""
|
| 58 |
+
Forward pass through the ResNet encoder.
|
| 59 |
+
Args:
|
| 60 |
+
images (torch.Tensor): Input images, shape (batch_size, 3, H, W).
|
| 61 |
+
Returns:
|
| 62 |
+
torch.Tensor: Encoded image features,
|
| 63 |
+
shape (batch_size, encoder_dim, encoded_image_size, encoded_image_size).
|
| 64 |
+
"""
|
| 65 |
+
# Pass images through the ResNet feature extractor
|
| 66 |
+
out = self.resnet(images)
|
| 67 |
+
# Apply adaptive pooling to get a fixed spatial size (e.g., 14x14)
|
| 68 |
+
out = self.adaptive_pool(out)
|
| 69 |
+
|
| 70 |
+
# The output shape is (batch_size, encoder_dim, encoded_image_size, encoded_image_size)
|
| 71 |
+
return out
|
| 72 |
+
|
| 73 |
+
|
| 74 |
+
class Attention(nn.Module):
|
| 75 |
+
"""
|
| 76 |
+
Additive Attention Mechanism (Bahdanau style).
|
| 77 |
+
Calculates attention weights based on encoded image features and decoder's hidden state.
|
| 78 |
+
"""
|
| 79 |
+
def __init__(self, encoder_dim, decoder_dim, attention_dim):
|
| 80 |
+
"""
|
| 81 |
+
Initializes the Attention module.
|
| 82 |
+
Args:
|
| 83 |
+
encoder_dim (int): Feature size of encoded images (e.g., 2048 for ResNet50).
|
| 84 |
+
decoder_dim (int): Hidden state size of the decoder LSTM.
|
| 85 |
+
attention_dim (int): Size of the linear layers within the attention mechanism.
|
| 86 |
+
"""
|
| 87 |
+
super(Attention, self).__init__()
|
| 88 |
+
# Linear layer to transform encoder output for attention calculation
|
| 89 |
+
self.encoder_att = nn.Linear(encoder_dim, attention_dim)
|
| 90 |
+
# Linear layer to transform decoder hidden state for attention calculation
|
| 91 |
+
self.decoder_att = nn.Linear(decoder_dim, attention_dim)
|
| 92 |
+
# Linear layer to calculate attention "score" (or energy)
|
| 93 |
+
# This layer projects the combined features to a single scalar per pixel.
|
| 94 |
+
self.full_att = nn.Linear(attention_dim, 1)
|
| 95 |
+
self.relu = nn.ReLU()
|
| 96 |
+
# Softmax over the "num_pixels" dimension to get attention weights that sum to 1
|
| 97 |
+
self.softmax = nn.Softmax(dim=1)
|
| 98 |
+
|
| 99 |
+
def forward(self, encoder_out, decoder_hidden):
|
| 100 |
+
"""
|
| 101 |
+
Forward pass through the attention mechanism.
|
| 102 |
+
Args:
|
| 103 |
+
encoder_out (torch.Tensor): Encoded images, shape (batch_size, num_pixels, encoder_dim).
|
| 104 |
+
decoder_hidden (torch.Tensor): Previous decoder hidden state, shape (batch_size, decoder_dim).
|
| 105 |
+
Returns:
|
| 106 |
+
tuple:
|
| 107 |
+
- attention_weighted_encoding (torch.Tensor): Context vector,
|
| 108 |
+
shape (batch_size, encoder_dim).
|
| 109 |
+
- alpha (torch.Tensor): Attention weights (probability distribution over pixels),
|
| 110 |
+
shape (batch_size, num_pixels).
|
| 111 |
+
"""
|
| 112 |
+
# Transform encoder output: (batch_size, num_pixels, attention_dim)
|
| 113 |
+
att1 = self.encoder_att(encoder_out)
|
| 114 |
+
# Transform decoder hidden state, then unsqueeze to (batch_size, 1, attention_dim)
|
| 115 |
+
# for broadcasting during addition with att1
|
| 116 |
+
att2 = self.decoder_att(decoder_hidden).unsqueeze(1)
|
| 117 |
+
|
| 118 |
+
# Calculate attention scores: (batch_size, num_pixels)
|
| 119 |
+
# Sum of transformed encoder output and transformed decoder hidden state,
|
| 120 |
+
# passed through ReLU and then a linear layer to get a single score per pixel.
|
| 121 |
+
att = self.full_att(self.relu(att1 + att2)).squeeze(2)
|
| 122 |
+
|
| 123 |
+
# Apply softmax to get attention weights (alpha): (batch_size, num_pixels)
|
| 124 |
+
alpha = self.softmax(att)
|
| 125 |
+
|
| 126 |
+
# Calculate attention-weighted encoding: (batch_size, encoder_dim)
|
| 127 |
+
# This is the context vector, a weighted sum of the encoder features.
|
| 128 |
+
attention_weighted_encoding = (encoder_out * alpha.unsqueeze(2)).sum(dim=1)
|
| 129 |
+
|
| 130 |
+
return attention_weighted_encoding, alpha
|
| 131 |
+
|
| 132 |
+
|
| 133 |
+
class DecoderWithAttention(nn.Module):
|
| 134 |
+
"""
|
| 135 |
+
LSTM Decoder with Attention mechanism.
|
| 136 |
+
Generates captions word by word, using the attention-weighted image features
|
| 137 |
+
and previously generated words.
|
| 138 |
+
"""
|
| 139 |
+
def __init__(self, attention_dim, embed_dim, decoder_dim, vocab_size,
|
| 140 |
+
encoder_dim=2048, dropout=0.5):
|
| 141 |
+
"""
|
| 142 |
+
Initializes the DecoderWithAttention.
|
| 143 |
+
Args:
|
| 144 |
+
attention_dim (int): Size of the attention linear layer.
|
| 145 |
+
embed_dim (int): Dimension of word embeddings.
|
| 146 |
+
decoder_dim (int): Hidden state size of the decoder LSTM.
|
| 147 |
+
vocab_size (int): Total size of the vocabulary.
|
| 148 |
+
encoder_dim (int): Feature size of encoded images (default 2048 for ResNet50).
|
| 149 |
+
dropout (float): Dropout rate for regularization.
|
| 150 |
+
"""
|
| 151 |
+
super(DecoderWithAttention, self).__init__()
|
| 152 |
+
|
| 153 |
+
self.encoder_dim = encoder_dim
|
| 154 |
+
self.attention_dim = attention_dim
|
| 155 |
+
self.embed_dim = embed_dim
|
| 156 |
+
self.decoder_dim = decoder_dim
|
| 157 |
+
self.vocab_size = vocab_size
|
| 158 |
+
self.dropout_rate = dropout
|
| 159 |
+
|
| 160 |
+
# Attention network
|
| 161 |
+
self.attention = Attention(encoder_dim, decoder_dim, attention_dim)
|
| 162 |
+
|
| 163 |
+
# Word embedding layer
|
| 164 |
+
self.embedding = nn.Embedding(vocab_size, embed_dim)
|
| 165 |
+
self.embedding_dropout = nn.Dropout(self.dropout_rate)
|
| 166 |
+
|
| 167 |
+
# LSTMCell for decoding
|
| 168 |
+
# Input to LSTMCell is the concatenation of word embedding and attention-weighted encoding
|
| 169 |
+
self.decode_step = nn.LSTMCell(embed_dim + encoder_dim, decoder_dim, bias=True)
|
| 170 |
+
|
| 171 |
+
# Linear layers to initialize the LSTM's hidden and cell states from the encoder output
|
| 172 |
+
self.init_h = nn.Linear(encoder_dim, decoder_dim)
|
| 173 |
+
self.init_c = nn.Linear(encoder_dim, decoder_dim)
|
| 174 |
+
|
| 175 |
+
# Linear layer to create a "gate" for the attention-weighted encoding (Visual Sentinel)
|
| 176 |
+
# This f_beta gate allows the model to decide how much of the attention-weighted
|
| 177 |
+
# context to use for generating the next word, enabling it to ignore irrelevant visual information.
|
| 178 |
+
self.f_beta = nn.Linear(decoder_dim, encoder_dim)
|
| 179 |
+
self.sigmoid = nn.Sigmoid() # Activation for the gate
|
| 180 |
+
|
| 181 |
+
# Linear layer to project decoder output to vocabulary size (scores for each word)
|
| 182 |
+
self.fc = nn.Linear(decoder_dim, vocab_size)
|
| 183 |
+
self.dropout_layer = nn.Dropout(self.dropout_rate)
|
| 184 |
+
|
| 185 |
+
# Initialize some weights
|
| 186 |
+
self.init_weights()
|
| 187 |
+
|
| 188 |
+
# A placeholder for max caption length during inference/generation
|
| 189 |
+
# This will typically be set by the calling model or config
|
| 190 |
+
self.max_caption_length_for_inference = 20
|
| 191 |
+
|
| 192 |
+
def init_weights(self):
|
| 193 |
+
"""Initializes some parameters with values from the uniform distribution."""
|
| 194 |
+
self.embedding.weight.data.uniform_(-0.1, 0.1)
|
| 195 |
+
self.fc.bias.data.fill_(0)
|
| 196 |
+
self.fc.weight.data.uniform_(-0.1, 0.1)
|
| 197 |
+
|
| 198 |
+
def load_pretrained_embeddings(self, embeddings):
|
| 199 |
+
"""
|
| 200 |
+
Loads pre-trained embeddings into the embedding layer.
|
| 201 |
+
Args:
|
| 202 |
+
embeddings (torch.Tensor): A tensor of pre-trained word embeddings.
|
| 203 |
+
"""
|
| 204 |
+
self.embedding.weight = nn.Parameter(embeddings)
|
| 205 |
+
# Optionally, freeze embeddings if they are pre-trained and you don't want to fine-tune them
|
| 206 |
+
# self.embedding.weight.requires_grad = False
|
| 207 |
+
|
| 208 |
+
def fine_tune_embeddings(self, fine_tune=True):
|
| 209 |
+
"""
|
| 210 |
+
Allows or disallows fine-tuning of the embedding layer.
|
| 211 |
+
Args:
|
| 212 |
+
fine_tune (bool): If True, embedding weights are trainable. If False, they are frozen.
|
| 213 |
+
"""
|
| 214 |
+
for p in self.embedding.parameters():
|
| 215 |
+
p.requires_grad = fine_tune
|
| 216 |
+
|
| 217 |
+
def init_hidden_state(self, encoder_out):
|
| 218 |
+
"""
|
| 219 |
+
Creates initial hidden and cell states for the LSTM from the encoded image.
|
| 220 |
+
Uses the mean of the encoder output features to initialize the LSTM states.
|
| 221 |
+
Args:
|
| 222 |
+
encoder_out (torch.Tensor): Encoded images, shape (batch_size, num_pixels, encoder_dim).
|
| 223 |
+
Returns:
|
| 224 |
+
tuple: (hidden state (h), cell state (c)), each of shape (batch_size, decoder_dim).
|
| 225 |
+
"""
|
| 226 |
+
# Calculate mean of encoder output across pixels
|
| 227 |
+
mean_encoder_out = encoder_out.mean(dim=1)
|
| 228 |
+
h = self.init_h(mean_encoder_out) # (batch_size, decoder_dim)
|
| 229 |
+
c = self.init_c(mean_encoder_out) # (batch_size, decoder_dim)
|
| 230 |
+
return h, c
|
| 231 |
+
|
| 232 |
+
def forward(self, encoder_out, encoded_captions, caption_lengths):
|
| 233 |
+
"""
|
| 234 |
+
Forward pass through the decoder during training.
|
| 235 |
+
Args:
|
| 236 |
+
encoder_out (torch.Tensor): Encoded images from CNN,
|
| 237 |
+
shape (batch_size, encoder_dim, enc_image_size_H, enc_image_size_W).
|
| 238 |
+
encoded_captions (torch.Tensor): Captions, shape (batch_size, max_caption_length).
|
| 239 |
+
caption_lengths (torch.Tensor): Actual lengths of captions (before padding), shape (batch_size,).
|
| 240 |
+
Returns:
|
| 241 |
+
tuple:
|
| 242 |
+
- predictions (torch.Tensor): Predicted word scores,
|
| 243 |
+
shape (batch_size, max_decode_length_in_batch, vocab_size).
|
| 244 |
+
- encoded_captions (torch.Tensor): Captions sorted by length.
|
| 245 |
+
- decode_lengths (list): Actual decoding lengths for each caption in the batch.
|
| 246 |
+
- alphas (torch.Tensor): Attention weights,
|
| 247 |
+
shape (batch_size, max_decode_length_in_batch, num_pixels).
|
| 248 |
+
- sort_ind (torch.Tensor): Indices used to sort the batch.
|
| 249 |
+
"""
|
| 250 |
+
batch_size = encoder_out.size(0)
|
| 251 |
+
enc_image_h = encoder_out.size(2)
|
| 252 |
+
enc_image_w = encoder_out.size(3)
|
| 253 |
+
num_pixels = enc_image_h * enc_image_w
|
| 254 |
+
|
| 255 |
+
# Reshape encoder_out for attention: (batch_size, num_pixels, encoder_dim)
|
| 256 |
+
# Permute from (N, C, H, W) to (N, H, W, C) then flatten H*W
|
| 257 |
+
encoder_out = encoder_out.permute(0, 2, 3, 1).contiguous()
|
| 258 |
+
encoder_out = encoder_out.view(batch_size, num_pixels, self.encoder_dim)
|
| 259 |
+
|
| 260 |
+
# Sort input data by decreasing lengths for packed sequences.
|
| 261 |
+
# This is crucial for efficient processing with `pack_padded_sequence`.
|
| 262 |
+
caption_lengths, sort_ind = caption_lengths.sort(dim=0, descending=True)
|
| 263 |
+
encoder_out = encoder_out[sort_ind] # Apply sorting to encoder output
|
| 264 |
+
encoded_captions = encoded_captions[sort_ind] # Apply sorting to captions
|
| 265 |
+
|
| 266 |
+
# Embedding: (batch_size, max_caption_length, embed_dim)
|
| 267 |
+
embeddings = self.embedding(encoded_captions)
|
| 268 |
+
embeddings = self.embedding_dropout(embeddings)
|
| 269 |
+
|
| 270 |
+
# Initialize LSTM state (h, c) from the mean of encoder output
|
| 271 |
+
h, c = self.init_hidden_state(encoder_out)
|
| 272 |
+
|
| 273 |
+
# Create tensors to hold word predictions and attention weights.
|
| 274 |
+
# We predict up to (max_caption_length - 1) words (excluding the <START> token).
|
| 275 |
+
decode_lengths = (caption_lengths - 1).tolist() # Lengths of sequences to decode
|
| 276 |
+
max_decode_length = max(decode_lengths) # Max length in the current batch
|
| 277 |
+
|
| 278 |
+
predictions = torch.zeros(batch_size, max_decode_length, self.vocab_size).to(encoder_out.device)
|
| 279 |
+
alphas = torch.zeros(batch_size, max_decode_length, num_pixels).to(encoder_out.device)
|
| 280 |
+
|
| 281 |
+
# For each time step in the decoding process
|
| 282 |
+
for t in range(max_decode_length):
|
| 283 |
+
# Get batch size for current time step.
|
| 284 |
+
# Sequences are padded, so some might finish early.
|
| 285 |
+
batch_size_t = sum([l > t for l in decode_lengths])
|
| 286 |
+
|
| 287 |
+
# Apply attention mechanism to the active sequences in the batch
|
| 288 |
+
attention_weighted_encoding, alpha = self.attention(encoder_out[:batch_size_t], h[:batch_size_t])
|
| 289 |
+
|
| 290 |
+
# Apply sigmoid gate to attention-weighted encoding (Visual Sentinel)
|
| 291 |
+
gate = self.sigmoid(self.f_beta(h[:batch_size_t]))
|
| 292 |
+
attention_weighted_encoding = gate * attention_weighted_encoding
|
| 293 |
+
|
| 294 |
+
# Perform one step of LSTM decoding
|
| 295 |
+
# Input to LSTM: (current_word_embedding + attention_weighted_encoding)
|
| 296 |
+
h, c = self.decode_step(
|
| 297 |
+
torch.cat([embeddings[:batch_size_t, t, :], attention_weighted_encoding], dim=1),
|
| 298 |
+
(h[:batch_size_t], c[:batch_size_t])
|
| 299 |
+
)
|
| 300 |
+
|
| 301 |
+
# Predict next word using the fully connected layer
|
| 302 |
+
preds = self.fc(self.dropout_layer(h))
|
| 303 |
+
|
| 304 |
+
# Store predictions and attention weights for the current time step
|
| 305 |
+
predictions[:batch_size_t, t, :] = preds
|
| 306 |
+
alphas[:batch_size_t, t, :] = alpha
|
| 307 |
+
|
| 308 |
+
return predictions, encoded_captions, decode_lengths, alphas, sort_ind
|
| 309 |
+
|
| 310 |
+
|
| 311 |
+
class ImageCaptioningModel(nn.Module):
|
| 312 |
+
"""
|
| 313 |
+
Complete Image Captioning Model integrating EncoderCNN and DecoderWithAttention.
|
| 314 |
+
Provides methods for both training (forward pass) and inference (caption generation).
|
| 315 |
+
"""
|
| 316 |
+
def __init__(self, vocab_size, embed_dim=256, attention_dim=256, encoder_dim=2048,
|
| 317 |
+
decoder_dim=256, dropout=0.5, fine_tune_encoder=True, max_caption_length=20):
|
| 318 |
+
"""
|
| 319 |
+
Initializes the ImageCaptioningModel.
|
| 320 |
+
Args:
|
| 321 |
+
vocab_size (int): Total size of the vocabulary.
|
| 322 |
+
embed_dim (int): Dimension of word embeddings.
|
| 323 |
+
attention_dim (int): Size of the attention linear layer.
|
| 324 |
+
encoder_dim (int): Feature size of encoded images (default 2048 for ResNet50).
|
| 325 |
+
decoder_dim (int): Hidden state size of the decoder LSTM.
|
| 326 |
+
dropout (float): Dropout rate for regularization.
|
| 327 |
+
fine_tune_encoder (bool): If True, allows the encoder parameters to be updated.
|
| 328 |
+
max_caption_length (int): Maximum length of generated captions during inference.
|
| 329 |
+
"""
|
| 330 |
+
super(ImageCaptioningModel, self).__init__()
|
| 331 |
+
|
| 332 |
+
# Initialize the Encoder (ResNet50-based)
|
| 333 |
+
self.encoder = EncoderCNN(encoded_image_size=14, fine_tune=fine_tune_encoder)
|
| 334 |
+
# Ensure encoder_dim matches ResNet50 output dimension
|
| 335 |
+
self.encoder_dim = self.encoder.encoder_dim # This will be 2048
|
| 336 |
+
|
| 337 |
+
# Initialize the Decoder with Attention
|
| 338 |
+
self.decoder = DecoderWithAttention(
|
| 339 |
+
attention_dim=attention_dim,
|
| 340 |
+
embed_dim=embed_dim,
|
| 341 |
+
decoder_dim=decoder_dim,
|
| 342 |
+
vocab_size=vocab_size,
|
| 343 |
+
encoder_dim=self.encoder_dim, # Pass the correct encoder_dim
|
| 344 |
+
dropout=dropout
|
| 345 |
+
)
|
| 346 |
+
self.decoder.max_caption_length_for_inference = max_caption_length # Set max length for inference
|
| 347 |
+
|
| 348 |
+
def forward(self, images, captions, caption_lengths):
|
| 349 |
+
"""
|
| 350 |
+
Forward pass through the complete model for training.
|
| 351 |
+
Args:
|
| 352 |
+
images (torch.Tensor): Input images.
|
| 353 |
+
captions (torch.Tensor): Target captions.
|
| 354 |
+
caption_lengths (torch.Tensor): Actual lengths of captions.
|
| 355 |
+
Returns:
|
| 356 |
+
tuple: (predictions, encoded_captions, decode_lengths, alphas, sort_ind)
|
| 357 |
+
as returned by the decoder's forward pass.
|
| 358 |
+
"""
|
| 359 |
+
encoder_out = self.encoder(images) # Encode images
|
| 360 |
+
predictions, encoded_captions, decode_lengths, alphas, sort_ind = self.decoder(
|
| 361 |
+
encoder_out, captions, caption_lengths # Decode captions
|
| 362 |
+
)
|
| 363 |
+
return predictions, encoded_captions, decode_lengths, alphas, sort_ind
|
| 364 |
+
|
| 365 |
+
def generate_caption(self, image_tensor, vocabulary, device, beam_size=5, max_length=None):
|
| 366 |
+
"""
|
| 367 |
+
Performs beam search to generate a caption for a single image.
|
| 368 |
+
This method is now part of the ImageCaptioningModel class.
|
| 369 |
+
Args:
|
| 370 |
+
image_tensor (torch.Tensor): Preprocessed image tensor (3, H, W). NOT batched.
|
| 371 |
+
vocabulary (COCOVocabulary): Vocabulary object.
|
| 372 |
+
device (torch.device): Device to run the model on (cpu/cuda).
|
| 373 |
+
beam_size (int): Size of beam for beam search.
|
| 374 |
+
max_length (int, optional): Maximum length of the generated caption.
|
| 375 |
+
If None, uses self.decoder.max_caption_length_for_inference.
|
| 376 |
+
Returns:
|
| 377 |
+
str: Generated caption string.
|
| 378 |
+
"""
|
| 379 |
+
self.eval() # Set model to evaluation mode
|
| 380 |
+
# Use the max_length from config if provided, otherwise fallback to model's default
|
| 381 |
+
current_max_length = max_length if max_length is not None else self.decoder.max_caption_length_for_inference
|
| 382 |
+
|
| 383 |
+
with torch.no_grad():
|
| 384 |
+
# Add batch dimension and move to device for the encoder
|
| 385 |
+
# image_tensor goes from (C, H, W) to (1, C, H, W)
|
| 386 |
+
image_tensor_batched = image_tensor.unsqueeze(0).to(device)
|
| 387 |
+
|
| 388 |
+
# Get encoder output: (1, encoder_dim, encoded_image_size, encoded_image_size)
|
| 389 |
+
encoder_output_from_cnn = self.encoder(image_tensor_batched)
|
| 390 |
+
|
| 391 |
+
# Reshape encoder_output_from_cnn to (1, num_pixels, encoder_dim) for attention
|
| 392 |
+
# Permute from (N, C, H, W) to (N, H, W, C) then flatten H*W
|
| 393 |
+
encoder_out = encoder_output_from_cnn.permute(0, 2, 3, 1).contiguous()
|
| 394 |
+
encoder_out = encoder_out.view(1, -1, self.encoder_dim) # (1, num_pixels, encoder_dim)
|
| 395 |
+
|
| 396 |
+
# Expand for beam search: (beam_size, num_pixels, encoder_dim)
|
| 397 |
+
encoder_out = encoder_out.expand(beam_size, encoder_out.size(1), encoder_out.size(2))
|
| 398 |
+
|
| 399 |
+
# Tensor to store top k previous words at each step; initialized with <START> token for all beams
|
| 400 |
+
k_prev_words = torch.LongTensor([[vocabulary.word2idx['<START>']]] * beam_size).to(device)
|
| 401 |
+
|
| 402 |
+
# Tensor to store top k sequences; initially just the <START> token
|
| 403 |
+
seqs = k_prev_words
|
| 404 |
+
|
| 405 |
+
# Tensor to store top k sequences' scores (log probabilities); initially all zeros
|
| 406 |
+
top_k_scores = torch.zeros(beam_size, 1).to(device)
|
| 407 |
+
|
| 408 |
+
# Lists to store completed captions and their scores
|
| 409 |
+
complete_seqs = list()
|
| 410 |
+
complete_seqs_scores = list()
|
| 411 |
+
|
| 412 |
+
# Initialize hidden state and cell state for LSTM
|
| 413 |
+
# encoder_out is already expanded for beam_size, so init_hidden_state will work
|
| 414 |
+
h, c = self.decoder.init_hidden_state(encoder_out)
|
| 415 |
+
|
| 416 |
+
# Start decoding loop
|
| 417 |
+
step = 1
|
| 418 |
+
while True:
|
| 419 |
+
# Get embeddings for the previously predicted words
|
| 420 |
+
embeddings = self.decoder.embedding(k_prev_words).squeeze(1) # (beam_size, embed_dim)
|
| 421 |
+
|
| 422 |
+
# Calculate attention-weighted encoding and attention weights
|
| 423 |
+
attention_weighted_encoding, alpha = self.decoder.attention(encoder_out, h)
|
| 424 |
+
# Apply visual sentinel gate
|
| 425 |
+
gate = self.decoder.sigmoid(self.decoder.f_beta(h))
|
| 426 |
+
attention_weighted_encoding = gate * attention_weighted_encoding
|
| 427 |
+
|
| 428 |
+
# Perform one step of LSTM decoding
|
| 429 |
+
h, c = self.decoder.decode_step(
|
| 430 |
+
torch.cat([embeddings, attention_weighted_encoding], dim=1),
|
| 431 |
+
(h, c)
|
| 432 |
+
) # (beam_size, decoder_dim)
|
| 433 |
+
|
| 434 |
+
# Get scores for the next word
|
| 435 |
+
scores = self.decoder.fc(h) # (beam_size, vocab_size)
|
| 436 |
+
scores = F.log_softmax(scores, dim=1) # Convert to log-probabilities
|
| 437 |
+
|
| 438 |
+
# Add current scores to previous scores for beam search
|
| 439 |
+
scores = top_k_scores.expand_as(scores) + scores # (beam_size, vocab_size)
|
| 440 |
+
|
| 441 |
+
# For the first step, all k generated words are from the same parent (<START>).
|
| 442 |
+
# For subsequent steps, they are from different parents.
|
| 443 |
+
if step == 1:
|
| 444 |
+
# For the first step, select top 'beam_size' words from the first beam's scores
|
| 445 |
+
top_k_scores, top_k_words = scores[0].topk(beam_size, 0, True, True) # (beam_size)
|
| 446 |
+
else:
|
| 447 |
+
# Flatten scores to find the top 'beam_size' overall (from all current beams)
|
| 448 |
+
top_k_scores, top_k_words = scores.view(-1).topk(beam_size, 0, True, True) # (beam_size)
|
| 449 |
+
|
| 450 |
+
# Convert flattened indices to actual row (previous word's beam index)
|
| 451 |
+
# and column (next word's vocabulary index) indices
|
| 452 |
+
prev_word_inds = top_k_words // vocabulary.vocab_size # (beam_size)
|
| 453 |
+
next_word_inds = top_k_words % vocabulary.vocab_size # (beam_size)
|
| 454 |
+
|
| 455 |
+
# Add new words to sequences
|
| 456 |
+
seqs = torch.cat([seqs[prev_word_inds], next_word_inds.unsqueeze(1)], dim=1) # (beam_size, step + 1)
|
| 457 |
+
|
| 458 |
+
# Identify completed sequences (where <END> is generated)
|
| 459 |
+
incomplete_inds = [ind for ind, next_word in enumerate(next_word_inds)
|
| 460 |
+
if next_word != vocabulary.word2idx['<END>']]
|
| 461 |
+
complete_inds = list(set(range(len(next_word_inds))) - set(incomplete_inds))
|
| 462 |
+
|
| 463 |
+
# Add complete sequences to their lists
|
| 464 |
+
if len(complete_inds) > 0:
|
| 465 |
+
complete_seqs.extend(seqs[complete_inds].tolist())
|
| 466 |
+
complete_seqs_scores.extend(top_k_scores[complete_inds])
|
| 467 |
+
|
| 468 |
+
# Update beam_size: number of active beams for the next step
|
| 469 |
+
beam_size -= len(complete_inds)
|
| 470 |
+
if beam_size == 0: # If all beams complete, break
|
| 471 |
+
break
|
| 472 |
+
|
| 473 |
+
# Filter seqs, hidden states, cell states, scores, and previous words for incomplete sequences
|
| 474 |
+
seqs = seqs[incomplete_inds]
|
| 475 |
+
h = h[prev_word_inds[incomplete_inds]]
|
| 476 |
+
c = c[prev_word_inds[incomplete_inds]]
|
| 477 |
+
top_k_scores = top_k_scores[incomplete_inds].unsqueeze(1) # Reshape for next step
|
| 478 |
+
k_prev_words = next_word_inds[incomplete_inds].unsqueeze(1)
|
| 479 |
+
encoder_out = encoder_out[prev_word_inds[incomplete_inds]] # Propagate encoder_out for active beams
|
| 480 |
+
|
| 481 |
+
# Break if maximum caption length is exceeded
|
| 482 |
+
if step > current_max_length:
|
| 483 |
+
break
|
| 484 |
+
step += 1
|
| 485 |
+
|
| 486 |
+
# If no complete captions were found (e.g., all beams exceeded max_length before <END>),
|
| 487 |
+
# pick the best incomplete sequence found so far.
|
| 488 |
+
if not complete_seqs:
|
| 489 |
+
# Take the best sequence among the currently active (incomplete) beams
|
| 490 |
+
final_seqs = seqs.tolist()
|
| 491 |
+
final_scores = top_k_scores.squeeze(1).tolist()
|
| 492 |
+
if not final_seqs: # Fallback if even no incomplete sequences are available (shouldn't happen)
|
| 493 |
+
return ""
|
| 494 |
+
i = final_scores.index(max(final_scores))
|
| 495 |
+
best_seq = final_seqs[i]
|
| 496 |
+
else:
|
| 497 |
+
# Find the best caption among all completed sequences based on score
|
| 498 |
+
i = complete_seqs_scores.index(max(complete_seqs_scores))
|
| 499 |
+
best_seq = complete_seqs[i]
|
| 500 |
+
|
| 501 |
+
# Convert the best sequence of indices back to a human-readable caption
|
| 502 |
+
return vocabulary.indices_to_caption(best_seq)
|
src/train.py
ADDED
|
@@ -0,0 +1,471 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import time
|
| 3 |
+
import math
|
| 4 |
+
import pickle
|
| 5 |
+
import gc # For memory optimization
|
| 6 |
+
|
| 7 |
+
import torch
|
| 8 |
+
import torch.nn as nn
|
| 9 |
+
import torch.optim as optim
|
| 10 |
+
from torch.utils.data import DataLoader
|
| 11 |
+
from torch.nn.utils.rnn import pack_padded_sequence
|
| 12 |
+
|
| 13 |
+
from .model import ImageCaptioningModel # Import the model
|
| 14 |
+
from .data_preprocessing import COCODataset, COCOVocabulary # Import data handling classes
|
| 15 |
+
from .evaluation import calculate_bleu_scores_detailed # Import evaluation metric
|
| 16 |
+
from .utils import get_logger, get_train_transform, get_eval_transform # Import utilities
|
| 17 |
+
|
| 18 |
+
logger = get_logger(__name__)
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
def train_epoch(model, train_loader, criterion, optimizer, device, epoch, config):
|
| 22 |
+
"""
|
| 23 |
+
Performs a single training epoch.
|
| 24 |
+
|
| 25 |
+
Args:
|
| 26 |
+
model (nn.Module): The image captioning model.
|
| 27 |
+
train_loader (DataLoader): DataLoader for training data.
|
| 28 |
+
criterion (nn.Module): Loss function.
|
| 29 |
+
optimizer (torch.optim.Optimizer): Optimizer.
|
| 30 |
+
device (torch.device): Device to run training on (cpu/cuda).
|
| 31 |
+
epoch (int): Current epoch number (0-indexed).
|
| 32 |
+
config (dict): Configuration dictionary.
|
| 33 |
+
|
| 34 |
+
Returns:
|
| 35 |
+
float: Average training loss for the epoch.
|
| 36 |
+
"""
|
| 37 |
+
model.train() # Set model to training mode
|
| 38 |
+
running_loss = 0.0
|
| 39 |
+
start_time = time.time()
|
| 40 |
+
total_batches = len(train_loader)
|
| 41 |
+
|
| 42 |
+
# Use tqdm for a progress bar
|
| 43 |
+
for i, (images, captions, lengths, _) in enumerate(train_loader):
|
| 44 |
+
images = images.to(device)
|
| 45 |
+
captions = captions.to(device)
|
| 46 |
+
lengths = lengths.to(device)
|
| 47 |
+
|
| 48 |
+
# Forward pass
|
| 49 |
+
# scores: (batch_size, max_decode_length_in_batch, vocab_size)
|
| 50 |
+
# caps_sorted: (batch_size, max_padded_length_from_dataset)
|
| 51 |
+
# decode_lengths: list of actual lengths for current batch (after sorting)
|
| 52 |
+
scores, caps_sorted, decode_lengths, _, _ = model(images, captions, lengths)
|
| 53 |
+
|
| 54 |
+
# Prepare targets for loss calculation
|
| 55 |
+
# Pack scores to remove padding and ensure correct length for loss calculation.
|
| 56 |
+
# This matches the dynamic lengths of the sequences.
|
| 57 |
+
scores_packed = pack_padded_sequence(scores, decode_lengths, batch_first=True).data
|
| 58 |
+
|
| 59 |
+
# Slice targets to match the length of scores_packed, removing the <START> token.
|
| 60 |
+
# The target sequence is `caption[1:]` because the model predicts the word
|
| 61 |
+
# at `t+1` given `caption[t]`.
|
| 62 |
+
targets = caps_sorted[:, 1:] # Remove <START> token from targets
|
| 63 |
+
targets_packed = pack_padded_sequence(targets, decode_lengths, batch_first=True).data
|
| 64 |
+
|
| 65 |
+
loss = criterion(scores_packed, targets_packed)
|
| 66 |
+
|
| 67 |
+
# Backward pass and optimize
|
| 68 |
+
optimizer.zero_grad() # Clear gradients from previous step
|
| 69 |
+
loss.backward() # Compute gradients
|
| 70 |
+
|
| 71 |
+
# Gradient clipping to prevent exploding gradients, especially common in RNNs
|
| 72 |
+
torch.nn.utils.clip_grad_norm_(model.parameters(), config.get('grad_clip', 5.0))
|
| 73 |
+
|
| 74 |
+
optimizer.step() # Update model parameters
|
| 75 |
+
|
| 76 |
+
running_loss += loss.item()
|
| 77 |
+
|
| 78 |
+
# Log training progress periodically
|
| 79 |
+
if (i + 1) % config.get('log_step', 100) == 0:
|
| 80 |
+
current_loss = loss.item()
|
| 81 |
+
perplexity = math.exp(current_loss) if current_loss < float('inf') else float('inf')
|
| 82 |
+
logger.info(f"Epoch [{epoch+1}/{config['num_epochs']}], Step [{i+1}/{total_batches}], "
|
| 83 |
+
f"Loss: {current_loss:.4f}, Perplexity: {perplexity:.4f}")
|
| 84 |
+
|
| 85 |
+
epoch_loss = running_loss / total_batches
|
| 86 |
+
epoch_time = time.time() - start_time
|
| 87 |
+
logger.info(f"Epoch {epoch+1} Training finished. Avg Loss: {epoch_loss:.4f}, Time: {epoch_time:.2f}s")
|
| 88 |
+
return epoch_loss
|
| 89 |
+
|
| 90 |
+
|
| 91 |
+
def validate_epoch(model, val_loader, criterion, vocabulary, device, config):
|
| 92 |
+
"""
|
| 93 |
+
Performs a single validation epoch.
|
| 94 |
+
Generates captions for a subset of the validation set to calculate BLEU scores.
|
| 95 |
+
|
| 96 |
+
Args:
|
| 97 |
+
model (nn.Module): The image captioning model.
|
| 98 |
+
val_loader (DataLoader): DataLoader for validation data.
|
| 99 |
+
criterion (nn.Module): Loss function (used for validation loss).
|
| 100 |
+
vocabulary (COCOVocabulary): Vocabulary object, used for converting indices to words.
|
| 101 |
+
device (torch.device): Device to run validation on (cpu/cuda).
|
| 102 |
+
config (dict): Configuration dictionary.
|
| 103 |
+
|
| 104 |
+
Returns:
|
| 105 |
+
tuple: (Average validation loss, list of generated captions, list of reference captions)
|
| 106 |
+
"""
|
| 107 |
+
model.eval() # Set model to evaluation mode
|
| 108 |
+
val_running_loss = 0.0
|
| 109 |
+
val_generated_captions = []
|
| 110 |
+
val_reference_captions = []
|
| 111 |
+
|
| 112 |
+
with torch.no_grad(): # Disable gradient calculations for validation
|
| 113 |
+
total_batches = len(val_loader)
|
| 114 |
+
# Iterate through the validation loader for loss calculation and caption generation
|
| 115 |
+
for i, (images, captions, lengths, _) in enumerate(val_loader):
|
| 116 |
+
images = images.to(device)
|
| 117 |
+
val_captions_for_loss = captions.to(device)
|
| 118 |
+
val_lengths_for_loss = lengths.to(device)
|
| 119 |
+
|
| 120 |
+
# Forward pass for loss calculation (similar to training)
|
| 121 |
+
val_scores, val_caps_sorted, val_decode_lengths, _, _ = model(images, val_captions_for_loss, val_lengths_for_loss)
|
| 122 |
+
|
| 123 |
+
val_scores_packed = pack_padded_sequence(val_scores, val_decode_lengths, batch_first=True).data
|
| 124 |
+
val_targets = val_caps_sorted[:, 1:] # Remove <START>
|
| 125 |
+
val_targets_packed = pack_padded_sequence(val_targets, val_decode_lengths, batch_first=True).data
|
| 126 |
+
|
| 127 |
+
val_loss = criterion(val_scores_packed, val_targets_packed)
|
| 128 |
+
val_running_loss += val_loss.item()
|
| 129 |
+
|
| 130 |
+
# Generate captions using beam search for a subset of batches or all
|
| 131 |
+
# The `val_inference_batches` config parameter controls how many batches to run inference on.
|
| 132 |
+
val_inference_batches_limit = config.get('val_inference_batches')
|
| 133 |
+
if val_inference_batches_limit is None or i < val_inference_batches_limit:
|
| 134 |
+
# Iterate through each image in the current batch to generate captions
|
| 135 |
+
for j in range(images.size(0)):
|
| 136 |
+
image_tensor_single = images[j] # Get a single image tensor (C, H, W)
|
| 137 |
+
generated_caption = model.generate_caption(
|
| 138 |
+
image_tensor_single, vocabulary, device,
|
| 139 |
+
beam_size=config.get('val_beam_size', 3), # Use beam search for validation
|
| 140 |
+
max_length=config.get('max_caption_length', 20)
|
| 141 |
+
)
|
| 142 |
+
# Convert reference caption indices back to string for metric calculation
|
| 143 |
+
reference_caption_str = vocabulary.indices_to_caption(captions[j].cpu().numpy())
|
| 144 |
+
val_generated_captions.append(generated_caption)
|
| 145 |
+
val_reference_captions.append(reference_caption_str)
|
| 146 |
+
|
| 147 |
+
val_avg_loss = val_running_loss / total_batches
|
| 148 |
+
perplexity = math.exp(val_avg_loss) if val_avg_loss < float('inf') else float('inf')
|
| 149 |
+
logger.info(f"Validation Avg Loss: {val_avg_loss:.4f}, Perplexity: {perplexity:.4f}")
|
| 150 |
+
|
| 151 |
+
return val_avg_loss, val_generated_captions, val_reference_captions
|
| 152 |
+
|
| 153 |
+
|
| 154 |
+
def train_model(config):
|
| 155 |
+
"""
|
| 156 |
+
Main training function. Orchestrates training and validation epochs.
|
| 157 |
+
|
| 158 |
+
Args:
|
| 159 |
+
config (dict): Configuration dictionary containing all training parameters.
|
| 160 |
+
|
| 161 |
+
Returns:
|
| 162 |
+
tuple: (Trained model, optimizer, scheduler, vocabulary)
|
| 163 |
+
"""
|
| 164 |
+
logger.info("Starting training process...")
|
| 165 |
+
|
| 166 |
+
# Set device (CUDA if available, else CPU)
|
| 167 |
+
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
| 168 |
+
logger.info(f"Using device: {device}")
|
| 169 |
+
|
| 170 |
+
# Load data paths from configuration
|
| 171 |
+
data_folder = config['data_folder']
|
| 172 |
+
train_image_folder = config['train_image_folder']
|
| 173 |
+
val_image_folder = config['val_image_folder']
|
| 174 |
+
train_caption_file = config['train_caption_file']
|
| 175 |
+
val_caption_file = config['val_caption_file']
|
| 176 |
+
|
| 177 |
+
# Check if caption files exist
|
| 178 |
+
if not os.path.exists(train_caption_file):
|
| 179 |
+
raise FileNotFoundError(f"Training caption file not found: {train_caption_file}")
|
| 180 |
+
if not os.path.exists(val_caption_file):
|
| 181 |
+
raise FileNotFoundError(f"Validation caption file not found: {val_caption_file}")
|
| 182 |
+
|
| 183 |
+
# Image transformations for training and validation
|
| 184 |
+
train_transform = get_train_transform()
|
| 185 |
+
val_transform = get_eval_transform() # Use eval transform for validation images
|
| 186 |
+
|
| 187 |
+
# ======================== VOCABULARY HANDLING ========================
|
| 188 |
+
# Define paths for loading/saving vocabulary
|
| 189 |
+
# First, try to load from a pre-saved vocabulary file in the output directory
|
| 190 |
+
VOCABULARY_FILE_PATH = os.path.join(config['output_dir'], 'vocabulary.pkl')
|
| 191 |
+
|
| 192 |
+
vocabulary = None # Initialize vocabulary to None
|
| 193 |
+
|
| 194 |
+
# Try to LOAD vocabulary
|
| 195 |
+
if os.path.exists(VOCABULARY_FILE_PATH):
|
| 196 |
+
try:
|
| 197 |
+
with open(VOCABULARY_FILE_PATH, 'rb') as f:
|
| 198 |
+
vocabulary = pickle.load(f)
|
| 199 |
+
logger.info(f"Loaded vocabulary from {VOCABULARY_FILE_PATH}")
|
| 200 |
+
except Exception as e:
|
| 201 |
+
logger.warning(f"Could not load vocabulary from {VOCABULARY_FILE_PATH}: {e}. Will attempt to build new vocabulary.")
|
| 202 |
+
vocabulary = None # Ensure it's None if loading fails
|
| 203 |
+
else:
|
| 204 |
+
logger.info(f"Vocabulary file not found at {VOCABULARY_FILE_PATH}. Will build new vocabulary.")
|
| 205 |
+
|
| 206 |
+
# If vocabulary is still None (meaning it couldn't be loaded), then BUILD a new one
|
| 207 |
+
if vocabulary is None:
|
| 208 |
+
logger.info("Building new vocabulary from training dataset...")
|
| 209 |
+
# Create a temporary dataset to build the vocabulary.
|
| 210 |
+
# No image transforms are needed for vocabulary building.
|
| 211 |
+
temp_train_dataset_for_vocab = COCODataset(
|
| 212 |
+
image_dir=os.path.join(data_folder, train_image_folder), # Image dir is still needed for dataset init
|
| 213 |
+
caption_file=train_caption_file,
|
| 214 |
+
subset_size=config.get('vocab_subset_size'), # Use subset if specified for vocab building
|
| 215 |
+
transform=None,
|
| 216 |
+
vocabulary=None # Explicitly tell it to build a new vocabulary
|
| 217 |
+
)
|
| 218 |
+
vocabulary = temp_train_dataset_for_vocab.vocabulary
|
| 219 |
+
del temp_train_dataset_for_vocab # Free up memory
|
| 220 |
+
gc.collect() # Force garbage collection
|
| 221 |
+
logger.info("New vocabulary built.")
|
| 222 |
+
|
| 223 |
+
# Save the newly built vocabulary
|
| 224 |
+
try:
|
| 225 |
+
os.makedirs(os.path.dirname(VOCABULARY_FILE_PATH), exist_ok=True)
|
| 226 |
+
with open(VOCABULARY_FILE_PATH, 'wb') as f:
|
| 227 |
+
pickle.dump(vocabulary, f)
|
| 228 |
+
logger.info(f"Saved newly built vocabulary to {VOCABULARY_FILE_PATH}")
|
| 229 |
+
except Exception as e:
|
| 230 |
+
logger.error(f"Error saving newly built vocabulary to {VOCABULARY_FILE_PATH}: {e}")
|
| 231 |
+
# ===========================================================================
|
| 232 |
+
|
| 233 |
+
|
| 234 |
+
# Create datasets for training and validation using the determined vocabulary
|
| 235 |
+
train_dataset = COCODataset(
|
| 236 |
+
image_dir=os.path.join(data_folder, train_image_folder),
|
| 237 |
+
caption_file=train_caption_file,
|
| 238 |
+
vocabulary=vocabulary, # Pass the vocabulary
|
| 239 |
+
max_caption_length=config.get('max_caption_length', 20),
|
| 240 |
+
subset_size=config.get('train_subset_size'),
|
| 241 |
+
transform=train_transform
|
| 242 |
+
)
|
| 243 |
+
|
| 244 |
+
val_dataset = COCODataset(
|
| 245 |
+
image_dir=os.path.join(data_folder, val_image_folder),
|
| 246 |
+
caption_file=val_caption_file,
|
| 247 |
+
vocabulary=vocabulary, # Pass the same vocabulary
|
| 248 |
+
max_caption_length=config.get('max_caption_length', 20),
|
| 249 |
+
subset_size=config.get('val_subset_size'),
|
| 250 |
+
transform=val_transform
|
| 251 |
+
)
|
| 252 |
+
|
| 253 |
+
# Create data loaders
|
| 254 |
+
train_loader = DataLoader(
|
| 255 |
+
train_dataset,
|
| 256 |
+
batch_size=config.get('batch_size', 64),
|
| 257 |
+
shuffle=True, # Shuffle training data
|
| 258 |
+
num_workers=config.get('num_workers', 2),
|
| 259 |
+
pin_memory=True # Pin memory for faster data transfer to GPU
|
| 260 |
+
)
|
| 261 |
+
|
| 262 |
+
val_loader = DataLoader(
|
| 263 |
+
val_dataset,
|
| 264 |
+
batch_size=config.get('batch_size', 64),
|
| 265 |
+
shuffle=False, # Do not shuffle validation data
|
| 266 |
+
num_workers=config.get('num_workers', 2),
|
| 267 |
+
pin_memory=True
|
| 268 |
+
)
|
| 269 |
+
|
| 270 |
+
logger.info(f"Training dataset size: {len(train_dataset)}")
|
| 271 |
+
logger.info(f"Validation dataset size: {len(val_dataset)}")
|
| 272 |
+
|
| 273 |
+
# Initialize model
|
| 274 |
+
model = ImageCaptioningModel(
|
| 275 |
+
vocab_size=vocabulary.vocab_size,
|
| 276 |
+
embed_dim=config.get('embed_dim', 256),
|
| 277 |
+
attention_dim=config.get('attention_dim', 256),
|
| 278 |
+
decoder_dim=config.get('decoder_dim', 256),
|
| 279 |
+
dropout=config.get('dropout', 0.5),
|
| 280 |
+
fine_tune_encoder=config.get('fine_tune_encoder', True),
|
| 281 |
+
max_caption_length=config.get('max_caption_length', 20) # Pass for model's generate_caption
|
| 282 |
+
).to(device) # Move model to specified device
|
| 283 |
+
|
| 284 |
+
# Loss function and optimizer
|
| 285 |
+
# CrossEntropyLoss ignores the <PAD> token in target labels
|
| 286 |
+
criterion = nn.CrossEntropyLoss(ignore_index=vocabulary.word2idx['<PAD>']).to(device)
|
| 287 |
+
|
| 288 |
+
# Separate optimizer for encoder and decoder if fine_tune_encoder is True.
|
| 289 |
+
# This allows setting different learning rates.
|
| 290 |
+
encoder_params = list(model.encoder.parameters())
|
| 291 |
+
decoder_params = list(model.decoder.parameters())
|
| 292 |
+
|
| 293 |
+
optimizer = optim.Adam([
|
| 294 |
+
{'params': encoder_params, 'lr': config.get('encoder_learning_rate', 1e-5) if config.get('fine_tune_encoder', True) else 0.0},
|
| 295 |
+
{'params': decoder_params, 'lr': config.get('learning_rate', 4e-4)}
|
| 296 |
+
])
|
| 297 |
+
|
| 298 |
+
# Learning rate scheduler: Reduces learning rate when a metric (BLEU-4) stops improving
|
| 299 |
+
scheduler = optim.lr_scheduler.ReduceLROnPlateau(
|
| 300 |
+
optimizer,
|
| 301 |
+
mode='max', # Monitor validation metric (e.g., BLEU-4, which we want to maximize)
|
| 302 |
+
factor=config.get('lr_reduce_factor', 0.5), # Factor by which the learning rate will be reduced
|
| 303 |
+
patience=config.get('lr_patience', 5), # Number of epochs with no improvement after which learning rate will be reduced
|
| 304 |
+
verbose=True, # Print messages when LR is updated
|
| 305 |
+
min_lr=1e-7 # Minimum learning rate
|
| 306 |
+
)
|
| 307 |
+
|
| 308 |
+
# ======================== RESUMPTION LOGIC ========================
|
| 309 |
+
start_epoch = 0
|
| 310 |
+
# Initialize best_val_score to a very low value for 'max' mode, so any improvement is noted
|
| 311 |
+
best_val_score = 0.0
|
| 312 |
+
output_dir = config['output_dir']
|
| 313 |
+
models_dir = config['models_dir']
|
| 314 |
+
|
| 315 |
+
# Try to find and load the latest checkpoint to resume training
|
| 316 |
+
latest_checkpoint_path = None
|
| 317 |
+
# Look for best_model_bleu*.pth first, then model_epoch_*.pth
|
| 318 |
+
saved_models = [f for f in os.listdir(models_dir) if f.startswith('best_model_bleu') and f.endswith('.pth')]
|
| 319 |
+
if not saved_models:
|
| 320 |
+
saved_models = [f for f in os.listdir(output_dir) if f.startswith('model_epoch_') and f.endswith('.pth')]
|
| 321 |
+
|
| 322 |
+
if saved_models:
|
| 323 |
+
if 'best_model_bleu' in saved_models[0]:
|
| 324 |
+
# Sort by BLEU score extracted from filename for best_model_bleu naming
|
| 325 |
+
latest_checkpoint_name = max(saved_models, key=lambda f: float(f.split('bleu')[1].replace('.pth', '')))
|
| 326 |
+
else: # For 'model_epoch_X.pth' or similar, sort by epoch number
|
| 327 |
+
latest_checkpoint_name = sorted(saved_models, key=lambda x: int(x.split('_')[-1].split('.')[0]))[-1]
|
| 328 |
+
|
| 329 |
+
# Determine the full path of the latest checkpoint
|
| 330 |
+
if latest_checkpoint_name.startswith('best_model_bleu'):
|
| 331 |
+
latest_checkpoint_path = os.path.join(models_dir, latest_checkpoint_name)
|
| 332 |
+
else:
|
| 333 |
+
latest_checkpoint_path = os.path.join(output_dir, latest_checkpoint_name)
|
| 334 |
+
|
| 335 |
+
logger.info(f"Attempting to resume training from checkpoint: {latest_checkpoint_path}")
|
| 336 |
+
try:
|
| 337 |
+
# Load checkpoint without strict=False unless there are known key mismatches
|
| 338 |
+
checkpoint = torch.load(latest_checkpoint_path, map_location=device)
|
| 339 |
+
model.load_state_dict(checkpoint['model_state_dict'])
|
| 340 |
+
optimizer.load_state_dict(checkpoint['optimizer_state_dict'])
|
| 341 |
+
|
| 342 |
+
# Load scheduler state if it exists in the checkpoint (important for correct LR adjustment)
|
| 343 |
+
if 'scheduler_state_dict' in checkpoint:
|
| 344 |
+
scheduler.load_state_dict(checkpoint['scheduler_state_dict'])
|
| 345 |
+
else:
|
| 346 |
+
logger.warning("Scheduler state not found in checkpoint. Scheduler will restart its state.")
|
| 347 |
+
|
| 348 |
+
start_epoch = checkpoint['epoch']
|
| 349 |
+
# Safely get best_val_score, default to 0.0 if not found
|
| 350 |
+
best_val_score = checkpoint.get('best_val_score', 0.0)
|
| 351 |
+
logger.info(f"Resumed training from epoch {start_epoch}. Best validation score so far: {best_val_score:.4f}")
|
| 352 |
+
except Exception as e:
|
| 353 |
+
logger.error(f"Could not load checkpoint from {latest_checkpoint_path}: {e}. Starting training from scratch.")
|
| 354 |
+
# Reset start_epoch and best_val_score if loading fails
|
| 355 |
+
start_epoch = 0
|
| 356 |
+
best_val_score = 0.0
|
| 357 |
+
else:
|
| 358 |
+
logger.info("No checkpoint found. Starting training from scratch.")
|
| 359 |
+
# ===========================================================================
|
| 360 |
+
|
| 361 |
+
|
| 362 |
+
# Training loop
|
| 363 |
+
num_epochs = config.get('num_epochs', 10)
|
| 364 |
+
|
| 365 |
+
for epoch in range(start_epoch, num_epochs): # Start from 'start_epoch' for resuming
|
| 366 |
+
# Train for one epoch
|
| 367 |
+
epoch_train_loss = train_epoch(model, train_loader, criterion, optimizer, device, epoch, config)
|
| 368 |
+
|
| 369 |
+
# Validate after each training epoch
|
| 370 |
+
val_avg_loss, val_generated_captions, val_reference_captions = validate_epoch(
|
| 371 |
+
model, val_loader, criterion, vocabulary, device, config
|
| 372 |
+
)
|
| 373 |
+
|
| 374 |
+
# Calculate BLEU scores on validation set for tracking and scheduler stepping
|
| 375 |
+
if val_generated_captions and val_reference_captions:
|
| 376 |
+
val_bleu_scores = calculate_bleu_scores_detailed(val_reference_captions, val_generated_captions)
|
| 377 |
+
current_val_score_for_scheduler = val_bleu_scores['BLEU-4'] # Use BLEU-4 for scheduler
|
| 378 |
+
logger.info(f"Epoch {epoch+1} Validation BLEU-4: {current_val_score_for_scheduler:.4f}")
|
| 379 |
+
|
| 380 |
+
# Step the scheduler based on validation BLEU-4.
|
| 381 |
+
# This will reduce the learning rate if BLEU-4 does not improve for 'patience' epochs.
|
| 382 |
+
scheduler.step(current_val_score_for_scheduler)
|
| 383 |
+
|
| 384 |
+
# Save the best model based on BLEU-4 score on the validation set
|
| 385 |
+
if current_val_score_for_scheduler > best_val_score:
|
| 386 |
+
best_val_score = current_val_score_for_scheduler
|
| 387 |
+
# Save best model to the 'models' directory
|
| 388 |
+
model_path = os.path.join(models_dir, f"best_model_bleu{best_val_score:.4f}.pth")
|
| 389 |
+
torch.save({
|
| 390 |
+
'epoch': epoch + 1,
|
| 391 |
+
'model_state_dict': model.state_dict(),
|
| 392 |
+
'optimizer_state_dict': optimizer.state_dict(),
|
| 393 |
+
'scheduler_state_dict': scheduler.state_dict(), # IMPORTANT: Save scheduler state!
|
| 394 |
+
'loss': epoch_train_loss,
|
| 395 |
+
'vocabulary': vocabulary,
|
| 396 |
+
'config': config, # Save config for easy loading later
|
| 397 |
+
'best_val_score': best_val_score # Save the best score achieved
|
| 398 |
+
}, model_path)
|
| 399 |
+
logger.info(f"Saved best model checkpoint to {model_path}")
|
| 400 |
+
else:
|
| 401 |
+
logger.warning("No captions generated during validation for metric calculation. Scheduler stepped with 0.0.")
|
| 402 |
+
scheduler.step(0.0) # Step with a low value if no metrics
|
| 403 |
+
|
| 404 |
+
# Save checkpoint periodically (optional)
|
| 405 |
+
# This is good practice for resuming training even if it's not the "best" model yet.
|
| 406 |
+
if (epoch + 1) % config.get('save_interval', 5) == 0:
|
| 407 |
+
model_path_periodic = os.path.join(output_dir, f"model_epoch_{epoch+1}.pth")
|
| 408 |
+
torch.save({
|
| 409 |
+
'epoch': epoch + 1,
|
| 410 |
+
'model_state_dict': model.state_dict(),
|
| 411 |
+
'optimizer_state_dict': optimizer.state_dict(),
|
| 412 |
+
'scheduler_state_dict': scheduler.state_dict(), # IMPORTANT: Save scheduler state!
|
| 413 |
+
'loss': epoch_train_loss,
|
| 414 |
+
'vocabulary': vocabulary,
|
| 415 |
+
'config': config,
|
| 416 |
+
'best_val_score': best_val_score # Also save current best score here
|
| 417 |
+
}, model_path_periodic)
|
| 418 |
+
logger.info(f"Saved periodic model checkpoint to {model_path_periodic}")
|
| 419 |
+
|
| 420 |
+
|
| 421 |
+
# ======================== MEMORY OPTIMIZATION AFTER EACH EPOCH ========================
|
| 422 |
+
logger.info("Performing memory optimization after epoch...")
|
| 423 |
+
# Clear PyTorch's CUDA cache (if using GPU)
|
| 424 |
+
if torch.cuda.is_available():
|
| 425 |
+
torch.cuda.empty_cache()
|
| 426 |
+
logger.info("CUDA cache emptied.")
|
| 427 |
+
|
| 428 |
+
# Force Python's garbage collector to run to free up unreferenced objects
|
| 429 |
+
gc.collect()
|
| 430 |
+
logger.info("Python garbage collector run.")
|
| 431 |
+
# ======================================================================================
|
| 432 |
+
|
| 433 |
+
logger.info("Training complete.")
|
| 434 |
+
return model, optimizer, scheduler, vocabulary # Return trained components for potential further use
|
| 435 |
+
|
| 436 |
+
|
| 437 |
+
if __name__ == '__main__':
|
| 438 |
+
# When `train.py` is run directly, it will initiate the training process.
|
| 439 |
+
from config import TRAINING_CONFIG, update_config_with_latest_model, _MODELS_DIR, _OUTPUT_DIR
|
| 440 |
+
|
| 441 |
+
# Update config to ensure it looks for latest model in 'models' dir
|
| 442 |
+
# This specifically helps if you copy pre-trained models into 'models' folder for initial load.
|
| 443 |
+
# If starting from scratch, it will still default to 0.0000.
|
| 444 |
+
update_config_with_latest_model(TRAINING_CONFIG)
|
| 445 |
+
|
| 446 |
+
logger.info("Starting model training process...")
|
| 447 |
+
try:
|
| 448 |
+
trained_model, optimizer, scheduler, vocabulary = train_model(TRAINING_CONFIG)
|
| 449 |
+
logger.info("Model Training Complete!")
|
| 450 |
+
|
| 451 |
+
# Optional: You might want to save the final model explicitly if it's not the best one.
|
| 452 |
+
# This ensures you have the model from the last epoch.
|
| 453 |
+
final_model_path = os.path.join(_MODELS_DIR, f"final_model_epoch_{TRAINING_CONFIG['num_epochs']}.pth")
|
| 454 |
+
torch.save({
|
| 455 |
+
'epoch': TRAINING_CONFIG['num_epochs'],
|
| 456 |
+
'model_state_dict': trained_model.state_dict(),
|
| 457 |
+
'optimizer_state_dict': optimizer.state_dict(),
|
| 458 |
+
'scheduler_state_dict': scheduler.state_dict(),
|
| 459 |
+
'vocabulary': vocabulary,
|
| 460 |
+
'config': TRAINING_CONFIG,
|
| 461 |
+
'best_val_score': 0 # Placeholder, retrieve from scheduler if needed
|
| 462 |
+
}, final_model_path)
|
| 463 |
+
logger.info(f"Saved final model checkpoint to {final_model_path}")
|
| 464 |
+
|
| 465 |
+
|
| 466 |
+
except FileNotFoundError as e:
|
| 467 |
+
logger.error(f"Critical data file missing: {e}")
|
| 468 |
+
logger.error("Please ensure the COCO dataset and annotation files are correctly placed as described in README.md.")
|
| 469 |
+
except Exception as e:
|
| 470 |
+
logger.critical(f"An unhandled error occurred during training: {e}", exc_info=True)
|
| 471 |
+
# exc_info=True prints the full traceback
|
src/utils.py
ADDED
|
@@ -0,0 +1,571 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# import logging
|
| 2 |
+
# import sys
|
| 3 |
+
# import os
|
| 4 |
+
# import shutil
|
| 5 |
+
# import matplotlib.pyplot as plt
|
| 6 |
+
# import numpy as np
|
| 7 |
+
# from PIL import Image
|
| 8 |
+
# import torch
|
| 9 |
+
# import torchvision.transforms as transforms
|
| 10 |
+
|
| 11 |
+
# # --- Logging Configuration ---
|
| 12 |
+
# # Configure logging to output to console and a file.
|
| 13 |
+
# # This logger will be used across all modules.
|
| 14 |
+
# logger = logging.getLogger(__name__) # Get a logger specific to this module
|
| 15 |
+
# logger.setLevel(logging.INFO) # Set the minimum level of messages to be logged
|
| 16 |
+
|
| 17 |
+
# # Ensure handlers are not duplicated if script is run multiple times in same session
|
| 18 |
+
# if not logger.handlers:
|
| 19 |
+
# # Console handler
|
| 20 |
+
# c_handler = logging.StreamHandler(sys.stdout)
|
| 21 |
+
# c_handler.setLevel(logging.INFO)
|
| 22 |
+
|
| 23 |
+
# # File handler - logs to 'training.log' in the 'output' directory
|
| 24 |
+
# # Ensure 'output' directory exists before creating the log file
|
| 25 |
+
# log_dir = 'output'
|
| 26 |
+
# os.makedirs(log_dir, exist_ok=True)
|
| 27 |
+
# f_handler = logging.FileHandler(os.path.join(log_dir, 'training.log'))
|
| 28 |
+
# f_handler.setLevel(logging.INFO)
|
| 29 |
+
|
| 30 |
+
# # Formatters
|
| 31 |
+
# c_format = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
|
| 32 |
+
# f_format = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
|
| 33 |
+
# c_handler.setFormatter(c_format)
|
| 34 |
+
# f_handler.setFormatter(f_format)
|
| 35 |
+
|
| 36 |
+
# # Add handlers to the logger
|
| 37 |
+
# logger.addHandler(c_handler)
|
| 38 |
+
# logger.addHandler(f_handler)
|
| 39 |
+
|
| 40 |
+
# # Get a top-level logger to ensure all modules use the same setup
|
| 41 |
+
# def get_logger(name=__name__):
|
| 42 |
+
# """Returns a logger instance with predefined settings."""
|
| 43 |
+
# return logging.getLogger(name)
|
| 44 |
+
|
| 45 |
+
|
| 46 |
+
# # --- Image Transformation Utilities ---
|
| 47 |
+
# def get_train_transform():
|
| 48 |
+
# """Get image transform for training (resize, horizontal flip, normalize)"""
|
| 49 |
+
# return transforms.Compose([
|
| 50 |
+
# transforms.Resize((224, 224)), # Resize images to 224x224 pixels
|
| 51 |
+
# transforms.RandomHorizontalFlip(), # Randomly flip images horizontally for data augmentation
|
| 52 |
+
# transforms.ToTensor(), # Convert PIL Image or numpy.ndarray to tensor
|
| 53 |
+
# transforms.Normalize(mean=[0.485, 0.456, 0.406], # Normalize pixel values
|
| 54 |
+
# std=[0.229, 0.224, 0.225])
|
| 55 |
+
# ])
|
| 56 |
+
|
| 57 |
+
# def get_eval_transform():
|
| 58 |
+
# """Get image transform for evaluation/inference (resize, normalize)"""
|
| 59 |
+
# return transforms.Compose([
|
| 60 |
+
# transforms.Resize((224, 224)), # Resize images to 224x224 pixels
|
| 61 |
+
# transforms.ToTensor(), # Convert PIL Image or numpy.ndarray to tensor
|
| 62 |
+
# transforms.Normalize(mean=[0.485, 0.456, 0.406], # Normalize pixel values
|
| 63 |
+
# std=[0.229, 0.224, 0.225])
|
| 64 |
+
# ])
|
| 65 |
+
|
| 66 |
+
|
| 67 |
+
# # --- Dataset Analysis Utility (moved from original script for modularity) ---
|
| 68 |
+
# class DatasetAnalyzer:
|
| 69 |
+
# """Utility class to analyze COCO dataset statistics."""
|
| 70 |
+
|
| 71 |
+
# @staticmethod
|
| 72 |
+
# def analyze_captions(caption_file, max_samples=None):
|
| 73 |
+
# """
|
| 74 |
+
# Analyzes caption statistics from a COCO-format JSON file.
|
| 75 |
+
# Args:
|
| 76 |
+
# caption_file (str): Path to the COCO captions JSON file.
|
| 77 |
+
# max_samples (int, optional): Maximum number of captions to analyze.
|
| 78 |
+
# Useful for large datasets. Defaults to None (all).
|
| 79 |
+
# Returns:
|
| 80 |
+
# dict: A dictionary containing various caption statistics.
|
| 81 |
+
# """
|
| 82 |
+
# try:
|
| 83 |
+
# with open(caption_file, 'r') as f:
|
| 84 |
+
# data = json.load(f)
|
| 85 |
+
# except FileNotFoundError:
|
| 86 |
+
# logger.error(f"Caption file not found for analysis: {caption_file}")
|
| 87 |
+
# return {}
|
| 88 |
+
# except json.JSONDecodeError:
|
| 89 |
+
# logger.error(f"Error decoding JSON from {caption_file}. Ensure it's valid.")
|
| 90 |
+
# return {}
|
| 91 |
+
|
| 92 |
+
# captions = [ann['caption'] for ann in data['annotations']]
|
| 93 |
+
# if max_samples:
|
| 94 |
+
# captions = captions[:max_samples]
|
| 95 |
+
|
| 96 |
+
# # Basic statistics
|
| 97 |
+
# lengths = [len(caption.split()) for caption in captions]
|
| 98 |
+
|
| 99 |
+
# stats = {
|
| 100 |
+
# 'total_captions': len(captions),
|
| 101 |
+
# 'avg_length': np.mean(lengths) if lengths else 0,
|
| 102 |
+
# 'std_length': np.std(lengths) if lengths else 0,
|
| 103 |
+
# 'min_length': min(lengths) if lengths else 0,
|
| 104 |
+
# 'max_length': max(lengths) if lengths else 0,
|
| 105 |
+
# 'median_length': np.median(lengths) if lengths else 0
|
| 106 |
+
# }
|
| 107 |
+
|
| 108 |
+
# # Word frequency
|
| 109 |
+
# all_words = []
|
| 110 |
+
# from collections import Counter # Import here to avoid circular dependency issues if Counter is used elsewhere
|
| 111 |
+
# for caption in captions:
|
| 112 |
+
# words = caption.lower().split()
|
| 113 |
+
# all_words.extend(words)
|
| 114 |
+
|
| 115 |
+
# word_freq = Counter(all_words)
|
| 116 |
+
# stats['unique_words'] = len(word_freq)
|
| 117 |
+
# stats['most_common_words'] = word_freq.most_common(20)
|
| 118 |
+
|
| 119 |
+
# return stats
|
| 120 |
+
|
| 121 |
+
# @staticmethod
|
| 122 |
+
# def plot_length_distribution(caption_file, max_samples=None, save_path=None):
|
| 123 |
+
# """
|
| 124 |
+
# Plots the distribution of caption lengths.
|
| 125 |
+
# Args:
|
| 126 |
+
# caption_file (str): Path to the COCO captions JSON file.
|
| 127 |
+
# max_samples (int, optional): Maximum number of captions to plot. Defaults to None (all).
|
| 128 |
+
# save_path (str, optional): Path to save the plot. If None, displays the plot.
|
| 129 |
+
# """
|
| 130 |
+
# try:
|
| 131 |
+
# with open(caption_file, 'r') as f:
|
| 132 |
+
# data = json.load(f)
|
| 133 |
+
# except FileNotFoundError:
|
| 134 |
+
# logger.error(f"Caption file not found for plotting: {caption_file}")
|
| 135 |
+
# return
|
| 136 |
+
# except json.JSONDecodeError:
|
| 137 |
+
# logger.error(f"Error decoding JSON from {caption_file}. Ensure it's valid.")
|
| 138 |
+
# return
|
| 139 |
+
|
| 140 |
+
# captions = [ann['caption'] for ann in data['annotations']]
|
| 141 |
+
# if max_samples:
|
| 142 |
+
# captions = captions[:max_samples]
|
| 143 |
+
|
| 144 |
+
# lengths = [len(caption.split()) for caption in captions]
|
| 145 |
+
|
| 146 |
+
# plt.figure(figsize=(10, 6))
|
| 147 |
+
# plt.hist(lengths, bins=50, alpha=0.7, edgecolor='black')
|
| 148 |
+
# plt.xlabel('Caption Length (words)')
|
| 149 |
+
# plt.ylabel('Frequency')
|
| 150 |
+
# plt.title('Distribution of Caption Lengths')
|
| 151 |
+
# plt.grid(True, alpha=0.3)
|
| 152 |
+
|
| 153 |
+
# if save_path:
|
| 154 |
+
# plt.savefig(save_path, bbox_inches='tight', dpi=150)
|
| 155 |
+
# logger.info(f"Caption length distribution plot saved to {save_path}")
|
| 156 |
+
# else:
|
| 157 |
+
# plt.show()
|
| 158 |
+
|
| 159 |
+
# # Import json here as it's used by DatasetAnalyzer
|
| 160 |
+
# import json
|
| 161 |
+
|
| 162 |
+
# # --- Attention Visualization Utility ---
|
| 163 |
+
# def visualize_attention(model, image_path, vocabulary, device, save_path=None, max_words_to_show=10):
|
| 164 |
+
# """
|
| 165 |
+
# Visualizes attention weights on an image for a generated caption.
|
| 166 |
+
# This function requires the model to have a `generate_caption` method
|
| 167 |
+
# and access to the encoder and decoder components to extract attention.
|
| 168 |
+
|
| 169 |
+
# Args:
|
| 170 |
+
# model (ImageCaptioningModel): The trained image captioning model.
|
| 171 |
+
# image_path (str): Path to the image file for visualization.
|
| 172 |
+
# vocabulary (COCOVocabulary): The vocabulary object.
|
| 173 |
+
# device (torch.device): Device to run the model on (cpu/cuda).
|
| 174 |
+
# save_path (str, optional): Path to save the visualization plot. If None, displays the plot.
|
| 175 |
+
# max_words_to_show (int): Maximum number of words to visualize attention for.
|
| 176 |
+
# """
|
| 177 |
+
# logger = get_logger(__name__) # Get logger for this function
|
| 178 |
+
|
| 179 |
+
# model.eval() # Set model to evaluation mode
|
| 180 |
+
|
| 181 |
+
# # Load and preprocess image
|
| 182 |
+
# transform = get_eval_transform()
|
| 183 |
+
|
| 184 |
+
# try:
|
| 185 |
+
# image = Image.open(image_path).convert('RGB')
|
| 186 |
+
# except FileNotFoundError:
|
| 187 |
+
# logger.error(f"Image not found at {image_path} for attention visualization.")
|
| 188 |
+
# return
|
| 189 |
+
# except Exception as e:
|
| 190 |
+
# logger.error(f"Error loading image {image_path} for attention visualization: {e}")
|
| 191 |
+
# return
|
| 192 |
+
|
| 193 |
+
# image_tensor = transform(image).unsqueeze(0).to(device) # Add batch dimension
|
| 194 |
+
|
| 195 |
+
# with torch.no_grad():
|
| 196 |
+
# # Get encoder output
|
| 197 |
+
# # (1, encoder_dim, encoded_image_size, encoded_image_size)
|
| 198 |
+
# encoder_out = model.encoder(image_tensor)
|
| 199 |
+
|
| 200 |
+
# # Reshape for attention: (1, num_pixels, encoder_dim)
|
| 201 |
+
# encoder_out_reshaped = encoder_out.permute(0, 2, 3, 1).contiguous()
|
| 202 |
+
# encoder_out_reshaped = encoder_out_reshaped.view(1, -1, model.encoder_dim)
|
| 203 |
+
|
| 204 |
+
# # Initialize decoder states
|
| 205 |
+
# h, c = model.decoder.init_hidden_state(encoder_out_reshaped)
|
| 206 |
+
|
| 207 |
+
# # Start of sentence token
|
| 208 |
+
# word_idx = vocabulary.word2idx['<START>']
|
| 209 |
+
# caption_words = []
|
| 210 |
+
# attention_weights = []
|
| 211 |
+
|
| 212 |
+
# # Generate caption word by word and collect attention weights
|
| 213 |
+
# # Iterate up to max_words_to_show or until <END> token is generated
|
| 214 |
+
# for _ in range(model.decoder.max_caption_length_for_inference): # Use model's max_length
|
| 215 |
+
# if word_idx == vocabulary.word2idx['<END>'] or len(caption_words) >= max_words_to_show:
|
| 216 |
+
# break
|
| 217 |
+
|
| 218 |
+
# # Get embeddings for current word
|
| 219 |
+
# # (1, embed_dim)
|
| 220 |
+
# embeddings = model.decoder.embedding(torch.LongTensor([word_idx]).to(device))
|
| 221 |
+
|
| 222 |
+
# # Get attention-weighted encoding and alpha
|
| 223 |
+
# # alpha: (1, num_pixels)
|
| 224 |
+
# awe, alpha = model.decoder.attention(encoder_out_reshaped, h)
|
| 225 |
+
# attention_weights.append(alpha.cpu().numpy())
|
| 226 |
+
|
| 227 |
+
# # Apply gate to attention-weighted encoding
|
| 228 |
+
# gate = model.decoder.sigmoid(model.decoder.f_beta(h))
|
| 229 |
+
# awe = gate * awe
|
| 230 |
+
|
| 231 |
+
# # Perform one step of LSTM decoding
|
| 232 |
+
# h, c = model.decoder.decode_step(
|
| 233 |
+
# torch.cat([embeddings, awe], dim=1),
|
| 234 |
+
# (h, c)
|
| 235 |
+
# )
|
| 236 |
+
|
| 237 |
+
# # Predict next word
|
| 238 |
+
# scores = model.decoder.fc(h) # (1, vocab_size)
|
| 239 |
+
# word_idx = scores.argmax(dim=1).item() # Get the index of the predicted word
|
| 240 |
+
|
| 241 |
+
# word = vocabulary.idx2word[word_idx]
|
| 242 |
+
# caption_words.append(word)
|
| 243 |
+
|
| 244 |
+
# # Visualize the attention maps
|
| 245 |
+
# num_plots = len(caption_words)
|
| 246 |
+
# if num_plots == 0:
|
| 247 |
+
# logger.warning("No words generated for attention visualization. Cannot create plot.")
|
| 248 |
+
# return
|
| 249 |
+
|
| 250 |
+
# # Adjust figure size dynamically based on number of plots
|
| 251 |
+
# fig, axes = plt.subplots(1, num_plots, figsize=(4 * num_plots, 5))
|
| 252 |
+
# if num_plots == 1: # Ensure axes is iterable even for single plot
|
| 253 |
+
# axes = [axes]
|
| 254 |
+
|
| 255 |
+
# for i, (word, alpha) in enumerate(zip(caption_words, attention_weights)):
|
| 256 |
+
# # Reshape attention to encoder's spatial size (e.g., 14x14 for ResNet50)
|
| 257 |
+
# # Assuming encoded_image_size is available in model.encoder
|
| 258 |
+
# enc_img_size = model.encoder.encoded_image_size
|
| 259 |
+
# alpha_img = alpha.reshape(enc_img_size, enc_img_size)
|
| 260 |
+
|
| 261 |
+
# # Resize attention map to original image size for overlay
|
| 262 |
+
# alpha_img_resized = Image.fromarray(alpha_img * 255).resize(image.size, Image.LANCZOS)
|
| 263 |
+
# alpha_img_np = np.array(alpha_img_resized) / 255.0 # Normalize back to 0-1
|
| 264 |
+
|
| 265 |
+
# axes[i].imshow(image)
|
| 266 |
+
# axes[i].imshow(alpha_img_np, alpha=0.6, cmap='jet') # Overlay attention map
|
| 267 |
+
# axes[i].set_title(f'Word: {word}')
|
| 268 |
+
# axes[i].axis('off')
|
| 269 |
+
|
| 270 |
+
# plt.suptitle(f"Generated Caption (Attention Visualization): {' '.join(caption_words)}")
|
| 271 |
+
# plt.tight_layout(rect=[0, 0.03, 1, 0.95]) # Adjust layout to prevent title overlap
|
| 272 |
+
|
| 273 |
+
# if save_path:
|
| 274 |
+
# os.makedirs(os.path.dirname(save_path), exist_ok=True)
|
| 275 |
+
# plt.savefig(save_path, bbox_inches='tight', dpi=150)
|
| 276 |
+
# logger.info(f"Attention visualization saved to {save_path}")
|
| 277 |
+
# else:
|
| 278 |
+
# plt.show()
|
| 279 |
+
|
| 280 |
+
# return ' '.join(caption_words)
|
| 281 |
+
|
| 282 |
+
|
| 283 |
+
|
| 284 |
+
|
| 285 |
+
|
| 286 |
+
import logging
|
| 287 |
+
import sys
|
| 288 |
+
import os
|
| 289 |
+
import shutil
|
| 290 |
+
import matplotlib.pyplot as plt
|
| 291 |
+
import numpy as np
|
| 292 |
+
from PIL import Image
|
| 293 |
+
import torch
|
| 294 |
+
import torchvision.transforms as transforms
|
| 295 |
+
|
| 296 |
+
# --- Logging Configuration ---
|
| 297 |
+
# Get the root logger
|
| 298 |
+
root_logger = logging.getLogger()
|
| 299 |
+
# Set the minimum level for the root logger. This ensures all messages at or above
|
| 300 |
+
# this level from any logger (including child loggers like those in app.py) are processed.
|
| 301 |
+
root_logger.setLevel(logging.INFO)
|
| 302 |
+
|
| 303 |
+
# Ensure handlers are not duplicated if script is run multiple times in same session
|
| 304 |
+
# This check is crucial and applies to the root logger's handlers.
|
| 305 |
+
if not root_logger.handlers:
|
| 306 |
+
# Console handler: directs log messages to standard output (console)
|
| 307 |
+
c_handler = logging.StreamHandler(sys.stdout)
|
| 308 |
+
c_handler.setLevel(logging.INFO) # Set level for console output
|
| 309 |
+
|
| 310 |
+
# File handler: directs log messages to a file
|
| 311 |
+
# Ensure the 'output' directory exists before creating the log file
|
| 312 |
+
log_dir = 'output'
|
| 313 |
+
os.makedirs(log_dir, exist_ok=True)
|
| 314 |
+
f_handler = logging.FileHandler(os.path.join(log_dir, 'training.log'))
|
| 315 |
+
f_handler.setLevel(logging.INFO) # Set level for file output
|
| 316 |
+
|
| 317 |
+
# Formatters define the layout of log records
|
| 318 |
+
c_format = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
|
| 319 |
+
f_format = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
|
| 320 |
+
c_handler.setFormatter(c_format)
|
| 321 |
+
f_handler.setFormatter(f_format)
|
| 322 |
+
|
| 323 |
+
# Add handlers to the ROOT logger. This is the critical change.
|
| 324 |
+
# Any logger instance obtained later will inherit these handlers by default.
|
| 325 |
+
root_logger.addHandler(c_handler)
|
| 326 |
+
root_logger.addHandler(f_handler)
|
| 327 |
+
|
| 328 |
+
def get_logger(name=__name__):
|
| 329 |
+
"""
|
| 330 |
+
Returns a logger instance with predefined settings.
|
| 331 |
+
When called with a specific name (e.g., __name__), it retrieves
|
| 332 |
+
a child logger that inherits settings (like handlers) from the root logger.
|
| 333 |
+
"""
|
| 334 |
+
return logging.getLogger(name)
|
| 335 |
+
|
| 336 |
+
|
| 337 |
+
# --- Image Transformation Utilities ---
|
| 338 |
+
def get_train_transform():
|
| 339 |
+
"""Get image transform for training (resize, horizontal flip, normalize)"""
|
| 340 |
+
return transforms.Compose([
|
| 341 |
+
transforms.Resize((224, 224)), # Resize images to 224x224 pixels
|
| 342 |
+
transforms.RandomHorizontalFlip(), # Randomly flip images horizontally for data augmentation
|
| 343 |
+
transforms.ToTensor(), # Convert PIL Image or numpy.ndarray to tensor
|
| 344 |
+
transforms.Normalize(mean=[0.485, 0.456, 0.406], # Normalize pixel values
|
| 345 |
+
std=[0.229, 0.224, 0.225])
|
| 346 |
+
])
|
| 347 |
+
|
| 348 |
+
def get_eval_transform():
|
| 349 |
+
"""Get image transform for evaluation/inference (resize, normalize)"""
|
| 350 |
+
return transforms.Compose([
|
| 351 |
+
transforms.Resize((224, 224)), # Resize images to 224x224 pixels
|
| 352 |
+
transforms.ToTensor(), # Convert PIL Image or numpy.ndarray to tensor
|
| 353 |
+
transforms.Normalize(mean=[0.485, 0.456, 0.406], # Normalize pixel values
|
| 354 |
+
std=[0.229, 0.224, 0.225])
|
| 355 |
+
])
|
| 356 |
+
|
| 357 |
+
|
| 358 |
+
# --- Dataset Analysis Utility (moved from original script for modularity) ---
|
| 359 |
+
class DatasetAnalyzer:
|
| 360 |
+
"""Utility class to analyze COCO dataset statistics."""
|
| 361 |
+
|
| 362 |
+
@staticmethod
|
| 363 |
+
def analyze_captions(caption_file, max_samples=None):
|
| 364 |
+
"""
|
| 365 |
+
Analyzes caption statistics from a COCO-format JSON file.
|
| 366 |
+
Args:
|
| 367 |
+
caption_file (str): Path to the COCO captions JSON file.
|
| 368 |
+
max_samples (int, optional): Maximum number of captions to analyze.
|
| 369 |
+
Useful for large datasets. Defaults to None (all).
|
| 370 |
+
Returns:
|
| 371 |
+
dict: A dictionary containing various caption statistics.
|
| 372 |
+
"""
|
| 373 |
+
try:
|
| 374 |
+
with open(caption_file, 'r') as f:
|
| 375 |
+
data = json.load(f)
|
| 376 |
+
except FileNotFoundError:
|
| 377 |
+
root_logger.error(f"Caption file not found for analysis: {caption_file}")
|
| 378 |
+
return {}
|
| 379 |
+
except json.JSONDecodeError:
|
| 380 |
+
root_logger.error(f"Error decoding JSON from {caption_file}. Ensure it's valid.")
|
| 381 |
+
return {}
|
| 382 |
+
|
| 383 |
+
captions = [ann['caption'] for ann in data['annotations']]
|
| 384 |
+
if max_samples:
|
| 385 |
+
captions = captions[:max_samples]
|
| 386 |
+
|
| 387 |
+
# Basic statistics
|
| 388 |
+
lengths = [len(caption.split()) for caption in captions]
|
| 389 |
+
|
| 390 |
+
stats = {
|
| 391 |
+
'total_captions': len(captions),
|
| 392 |
+
'avg_length': np.mean(lengths) if lengths else 0,
|
| 393 |
+
'std_length': np.std(lengths) if lengths else 0,
|
| 394 |
+
'min_length': min(lengths) if lengths else 0,
|
| 395 |
+
'max_length': max(lengths) if lengths else 0,
|
| 396 |
+
'median_length': np.median(lengths) if lengths else 0
|
| 397 |
+
}
|
| 398 |
+
|
| 399 |
+
# Word frequency
|
| 400 |
+
all_words = []
|
| 401 |
+
from collections import Counter # Import here to avoid circular dependency issues if Counter is used elsewhere
|
| 402 |
+
for caption in captions:
|
| 403 |
+
words = caption.lower().split()
|
| 404 |
+
all_words.extend(words)
|
| 405 |
+
|
| 406 |
+
word_freq = Counter(all_words)
|
| 407 |
+
stats['unique_words'] = len(word_freq)
|
| 408 |
+
stats['most_common_words'] = word_freq.most_common(20)
|
| 409 |
+
|
| 410 |
+
return stats
|
| 411 |
+
|
| 412 |
+
@staticmethod
|
| 413 |
+
def plot_length_distribution(caption_file, max_samples=None, save_path=None):
|
| 414 |
+
"""
|
| 415 |
+
Plots the distribution of caption lengths.
|
| 416 |
+
Args:
|
| 417 |
+
caption_file (str): Path to the COCO captions JSON file.
|
| 418 |
+
max_samples (int, optional): Maximum number of captions to plot. Defaults to None (all).
|
| 419 |
+
save_path (str, optional): Path to save the plot. If None, displays the plot.
|
| 420 |
+
"""
|
| 421 |
+
try:
|
| 422 |
+
with open(caption_file, 'r') as f:
|
| 423 |
+
data = json.load(f)
|
| 424 |
+
except FileNotFoundError:
|
| 425 |
+
root_logger.error(f"Caption file not found for plotting: {caption_file}")
|
| 426 |
+
return
|
| 427 |
+
except json.JSONDecodeError:
|
| 428 |
+
root_logger.error(f"Error decoding JSON from {caption_file}. Ensure it's valid.")
|
| 429 |
+
return
|
| 430 |
+
|
| 431 |
+
captions = [ann['caption'] for ann in data['annotations']]
|
| 432 |
+
if max_samples:
|
| 433 |
+
captions = captions[:max_samples]
|
| 434 |
+
|
| 435 |
+
lengths = [len(caption.split()) for caption in captions]
|
| 436 |
+
|
| 437 |
+
plt.figure(figsize=(10, 6))
|
| 438 |
+
plt.hist(lengths, bins=50, alpha=0.7, edgecolor='black')
|
| 439 |
+
plt.xlabel('Caption Length (words)')
|
| 440 |
+
plt.ylabel('Frequency')
|
| 441 |
+
plt.title('Distribution of Caption Lengths')
|
| 442 |
+
plt.grid(True, alpha=0.3)
|
| 443 |
+
|
| 444 |
+
if save_path:
|
| 445 |
+
plt.savefig(save_path, bbox_inches='tight', dpi=150)
|
| 446 |
+
root_logger.info(f"Caption length distribution plot saved to {save_path}")
|
| 447 |
+
else:
|
| 448 |
+
plt.show()
|
| 449 |
+
|
| 450 |
+
# Import json here as it's used by DatasetAnalyzer
|
| 451 |
+
import json
|
| 452 |
+
|
| 453 |
+
# --- Attention Visualization Utility ---
|
| 454 |
+
def visualize_attention(model, image_path, vocabulary, device, save_path=None, max_words_to_show=10):
|
| 455 |
+
"""
|
| 456 |
+
Visualizes attention weights on an image for a generated caption.
|
| 457 |
+
This function requires the model to have a `generate_caption` method
|
| 458 |
+
and access to the encoder and decoder components to extract attention.
|
| 459 |
+
|
| 460 |
+
Args:
|
| 461 |
+
model (ImageCaptioningModel): The trained image captioning model.
|
| 462 |
+
image_path (str): Path to the image file for visualization.
|
| 463 |
+
vocabulary (COCOVocabulary): The vocabulary object.
|
| 464 |
+
device (torch.device): Device to run the model on (cpu/cuda).
|
| 465 |
+
save_path (str, optional): Path to save the visualization plot. If None, displays the plot.
|
| 466 |
+
max_words_to_show (int): Maximum number of words to visualize attention for.
|
| 467 |
+
"""
|
| 468 |
+
logger = get_logger(__name__) # Get logger for this function
|
| 469 |
+
|
| 470 |
+
model.eval() # Set model to evaluation mode
|
| 471 |
+
|
| 472 |
+
# Load and preprocess image
|
| 473 |
+
transform = get_eval_transform()
|
| 474 |
+
|
| 475 |
+
try:
|
| 476 |
+
image = Image.open(image_path).convert('RGB')
|
| 477 |
+
except FileNotFoundError:
|
| 478 |
+
logger.error(f"Image not found at {image_path} for attention visualization.")
|
| 479 |
+
return
|
| 480 |
+
except Exception as e:
|
| 481 |
+
logger.error(f"Error loading image {image_path} for attention visualization: {e}")
|
| 482 |
+
return
|
| 483 |
+
|
| 484 |
+
image_tensor = transform(image).unsqueeze(0).to(device) # Add batch dimension
|
| 485 |
+
|
| 486 |
+
with torch.no_grad():
|
| 487 |
+
# Get encoder output
|
| 488 |
+
# (1, encoder_dim, encoded_image_size, encoded_image_size)
|
| 489 |
+
encoder_out = model.encoder(image_tensor)
|
| 490 |
+
|
| 491 |
+
# Reshape for attention: (1, num_pixels, encoder_dim)
|
| 492 |
+
encoder_out_reshaped = encoder_out.permute(0, 2, 3, 1).contiguous()
|
| 493 |
+
encoder_out_reshaped = encoder_out_reshaped.view(1, -1, model.encoder_dim)
|
| 494 |
+
|
| 495 |
+
# Initialize decoder states
|
| 496 |
+
h, c = model.decoder.init_hidden_state(encoder_out_reshaped)
|
| 497 |
+
|
| 498 |
+
# Start of sentence token
|
| 499 |
+
word_idx = vocabulary.word2idx['<START>']
|
| 500 |
+
caption_words = []
|
| 501 |
+
attention_weights = []
|
| 502 |
+
|
| 503 |
+
# Generate caption word by word and collect attention weights
|
| 504 |
+
# Iterate up to max_words_to_show or until <END> token is generated
|
| 505 |
+
for _ in range(model.decoder.max_caption_length_for_inference): # Use model's max_length
|
| 506 |
+
if word_idx == vocabulary.word2idx['<END>'] or len(caption_words) >= max_words_to_show:
|
| 507 |
+
break
|
| 508 |
+
|
| 509 |
+
# Get embeddings for current word
|
| 510 |
+
# (1, embed_dim)
|
| 511 |
+
embeddings = model.decoder.embedding(torch.LongTensor([word_idx]).to(device))
|
| 512 |
+
|
| 513 |
+
# Get attention-weighted encoding and alpha
|
| 514 |
+
# alpha: (1, num_pixels)
|
| 515 |
+
awe, alpha = model.decoder.attention(encoder_out_reshaped, h)
|
| 516 |
+
attention_weights.append(alpha.cpu().numpy())
|
| 517 |
+
|
| 518 |
+
# Apply gate to attention-weighted encoding
|
| 519 |
+
gate = model.decoder.sigmoid(model.decoder.f_beta(h))
|
| 520 |
+
awe = gate * awe
|
| 521 |
+
|
| 522 |
+
# Perform one step of LSTM decoding
|
| 523 |
+
h, c = model.decoder.decode_step(
|
| 524 |
+
torch.cat([embeddings, awe], dim=1),
|
| 525 |
+
(h, c)
|
| 526 |
+
)
|
| 527 |
+
|
| 528 |
+
# Predict next word
|
| 529 |
+
scores = model.decoder.fc(h) # (1, vocab_size)
|
| 530 |
+
word_idx = scores.argmax(dim=1).item() # Get the index of the predicted word
|
| 531 |
+
|
| 532 |
+
word = vocabulary.idx2word[word_idx]
|
| 533 |
+
caption_words.append(word)
|
| 534 |
+
|
| 535 |
+
# Visualize the attention maps
|
| 536 |
+
num_plots = len(caption_words)
|
| 537 |
+
if num_plots == 0:
|
| 538 |
+
logger.warning("No words generated for attention visualization. Cannot create plot.")
|
| 539 |
+
return
|
| 540 |
+
|
| 541 |
+
# Adjust figure size dynamically based on number of plots
|
| 542 |
+
fig, axes = plt.subplots(1, num_plots, figsize=(4 * num_plots, 5))
|
| 543 |
+
if num_plots == 1: # Ensure axes is iterable even for single plot
|
| 544 |
+
axes = [axes]
|
| 545 |
+
|
| 546 |
+
for i, (word, alpha) in enumerate(zip(caption_words, attention_weights)):
|
| 547 |
+
# Reshape attention to encoder's spatial size (e.g., 14x14 for ResNet50)
|
| 548 |
+
# Assuming encoded_image_size is available in model.encoder
|
| 549 |
+
enc_img_size = model.encoder.encoded_image_size
|
| 550 |
+
alpha_img = alpha.reshape(enc_img_size, enc_img_size)
|
| 551 |
+
|
| 552 |
+
# Resize attention map to original image size for overlay
|
| 553 |
+
alpha_img_resized = Image.fromarray(alpha_img * 255).resize(image.size, Image.LANCZOS)
|
| 554 |
+
alpha_img_np = np.array(alpha_img_resized) / 255.0 # Normalize back to 0-1
|
| 555 |
+
|
| 556 |
+
axes[i].imshow(image)
|
| 557 |
+
axes[i].imshow(alpha_img_np, alpha=0.6, cmap='jet') # Overlay attention map
|
| 558 |
+
axes[i].set_title(f'Word: {word}')
|
| 559 |
+
axes[i].axis('off')
|
| 560 |
+
|
| 561 |
+
plt.suptitle(f"Generated Caption (Attention Visualization): {' '.join(caption_words)}")
|
| 562 |
+
plt.tight_layout(rect=[0, 0.03, 1, 0.95]) # Adjust layout to prevent title overlap
|
| 563 |
+
|
| 564 |
+
if save_path:
|
| 565 |
+
os.makedirs(os.path.dirname(save_path), exist_ok=True)
|
| 566 |
+
plt.savefig(save_path, bbox_inches='tight', dpi=150)
|
| 567 |
+
logger.info(f"Attention visualization saved to {save_path}")
|
| 568 |
+
else:
|
| 569 |
+
plt.show()
|
| 570 |
+
|
| 571 |
+
return ' '.join(caption_words)
|
templates/auth.html
ADDED
|
@@ -0,0 +1,1283 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html lang="en">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="UTF-8">
|
| 5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
+
<title>Dynamic Facial Recognition Authentication</title>
|
| 7 |
+
<style>
|
| 8 |
+
* {
|
| 9 |
+
margin: 0;
|
| 10 |
+
padding: 0;
|
| 11 |
+
box-sizing: border-box;
|
| 12 |
+
}
|
| 13 |
+
|
| 14 |
+
body {
|
| 15 |
+
font-family: 'Inter', 'Segoe UI', system-ui, -apple-system, sans-serif;
|
| 16 |
+
background: #0B1121;
|
| 17 |
+
min-height: 100vh;
|
| 18 |
+
overflow-x: hidden;
|
| 19 |
+
position: relative;
|
| 20 |
+
color: #E5E7EB;
|
| 21 |
+
font-weight: 400;
|
| 22 |
+
letter-spacing: -0.01em;
|
| 23 |
+
}
|
| 24 |
+
|
| 25 |
+
/* Animated Background - Subtle particles matching main theme */
|
| 26 |
+
.bg-particles {
|
| 27 |
+
position: fixed;
|
| 28 |
+
top: 0;
|
| 29 |
+
left: 0;
|
| 30 |
+
width: 100%;
|
| 31 |
+
height: 100%;
|
| 32 |
+
pointer-events: none;
|
| 33 |
+
z-index: 1;
|
| 34 |
+
}
|
| 35 |
+
|
| 36 |
+
.particle {
|
| 37 |
+
position: absolute;
|
| 38 |
+
background: rgba(59, 130, 246, 0.1);
|
| 39 |
+
border-radius: 50%;
|
| 40 |
+
animation: float 8s ease-in-out infinite;
|
| 41 |
+
}
|
| 42 |
+
|
| 43 |
+
.particle:nth-child(1) { width: 60px; height: 60px; left: 10%; animation-delay: 0s; }
|
| 44 |
+
.particle:nth-child(2) { width: 80px; height: 80px; left: 20%; animation-delay: 3s; }
|
| 45 |
+
.particle:nth-child(3) { width: 40px; height: 40px; left: 60%; animation-delay: 1s; }
|
| 46 |
+
.particle:nth-child(4) { width: 70px; height: 70px; left: 80%; animation-delay: 4s; }
|
| 47 |
+
.particle:nth-child(5) { width: 30px; height: 30px; left: 70%; animation-delay: 2s; }
|
| 48 |
+
|
| 49 |
+
@keyframes float {
|
| 50 |
+
0%, 100% { transform: translateY(0px) rotate(0deg); opacity: 0.3; }
|
| 51 |
+
50% { transform: translateY(-30px) rotate(180deg); opacity: 0.6; }
|
| 52 |
+
}
|
| 53 |
+
|
| 54 |
+
/* Main Container */
|
| 55 |
+
.auth-wrapper {
|
| 56 |
+
min-height: 100vh;
|
| 57 |
+
display: flex;
|
| 58 |
+
align-items: center;
|
| 59 |
+
justify-content: center;
|
| 60 |
+
padding: 20px;
|
| 61 |
+
position: relative;
|
| 62 |
+
z-index: 2;
|
| 63 |
+
background: radial-gradient(circle at 20% 80%, rgba(59, 130, 246, 0.1) 0%, transparent 50%),
|
| 64 |
+
radial-gradient(circle at 80% 20%, rgba(99, 102, 241, 0.1) 0%, transparent 50%);
|
| 65 |
+
}
|
| 66 |
+
|
| 67 |
+
.auth-container {
|
| 68 |
+
background: #1E293B;
|
| 69 |
+
border: 1px solid #334155;
|
| 70 |
+
border-radius: 16px;
|
| 71 |
+
padding: 0;
|
| 72 |
+
box-shadow: 0 10px 25px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
|
| 73 |
+
width: 100%;
|
| 74 |
+
max-width: 450px;
|
| 75 |
+
position: relative;
|
| 76 |
+
overflow: hidden;
|
| 77 |
+
transform: translateY(20px);
|
| 78 |
+
animation: slideUp 0.8s ease-out forwards;
|
| 79 |
+
}
|
| 80 |
+
|
| 81 |
+
@keyframes slideUp {
|
| 82 |
+
to {
|
| 83 |
+
transform: translateY(0);
|
| 84 |
+
opacity: 1;
|
| 85 |
+
}
|
| 86 |
+
}
|
| 87 |
+
|
| 88 |
+
/* Header Section */
|
| 89 |
+
.auth-header {
|
| 90 |
+
background: linear-gradient(135deg, #1E293B 0%, #334155 100%);
|
| 91 |
+
padding: 30px;
|
| 92 |
+
text-align: center;
|
| 93 |
+
position: relative;
|
| 94 |
+
border-bottom: 1px solid #374151;
|
| 95 |
+
}
|
| 96 |
+
|
| 97 |
+
.auth-header::before {
|
| 98 |
+
content: '';
|
| 99 |
+
position: absolute;
|
| 100 |
+
top: 0;
|
| 101 |
+
left: 0;
|
| 102 |
+
right: 0;
|
| 103 |
+
height: 3px;
|
| 104 |
+
background: linear-gradient(90deg, #3B82F6, #6366F1);
|
| 105 |
+
animation: glow 2s ease-in-out infinite alternate;
|
| 106 |
+
}
|
| 107 |
+
|
| 108 |
+
@keyframes glow {
|
| 109 |
+
from { box-shadow: 0 0 5px rgba(59, 130, 246, 0.5); }
|
| 110 |
+
to { box-shadow: 0 0 20px rgba(59, 130, 246, 0.8); }
|
| 111 |
+
}
|
| 112 |
+
|
| 113 |
+
.auth-title {
|
| 114 |
+
color: #FFFFFF;
|
| 115 |
+
font-size: 28px;
|
| 116 |
+
font-weight: 700;
|
| 117 |
+
margin-bottom: 10px;
|
| 118 |
+
letter-spacing: -0.02em;
|
| 119 |
+
transition: all 0.3s ease;
|
| 120 |
+
}
|
| 121 |
+
|
| 122 |
+
.auth-subtitle {
|
| 123 |
+
color: #94A3B8;
|
| 124 |
+
font-size: 14px;
|
| 125 |
+
font-weight: 400;
|
| 126 |
+
}
|
| 127 |
+
|
| 128 |
+
/* Tab Navigation */
|
| 129 |
+
.tab-navigation {
|
| 130 |
+
display: flex;
|
| 131 |
+
background: #111827;
|
| 132 |
+
margin: 0;
|
| 133 |
+
border-bottom: 1px solid #374151;
|
| 134 |
+
}
|
| 135 |
+
|
| 136 |
+
.tab-btn {
|
| 137 |
+
flex: 1;
|
| 138 |
+
padding: 20px;
|
| 139 |
+
background: none;
|
| 140 |
+
border: none;
|
| 141 |
+
color: #94A3B8;
|
| 142 |
+
font-size: 16px;
|
| 143 |
+
font-weight: 600;
|
| 144 |
+
cursor: pointer;
|
| 145 |
+
transition: all 0.3s ease;
|
| 146 |
+
position: relative;
|
| 147 |
+
overflow: hidden;
|
| 148 |
+
font-family: inherit;
|
| 149 |
+
}
|
| 150 |
+
|
| 151 |
+
.tab-btn::before {
|
| 152 |
+
content: '';
|
| 153 |
+
position: absolute;
|
| 154 |
+
bottom: 0;
|
| 155 |
+
left: 50%;
|
| 156 |
+
width: 0;
|
| 157 |
+
height: 3px;
|
| 158 |
+
background: linear-gradient(90deg, #3B82F6, #6366F1);
|
| 159 |
+
transition: all 0.3s ease;
|
| 160 |
+
transform: translateX(-50%);
|
| 161 |
+
}
|
| 162 |
+
|
| 163 |
+
.tab-btn.active {
|
| 164 |
+
color: #FFFFFF;
|
| 165 |
+
background: #1E293B;
|
| 166 |
+
}
|
| 167 |
+
|
| 168 |
+
.tab-btn.active::before {
|
| 169 |
+
width: 100%;
|
| 170 |
+
}
|
| 171 |
+
|
| 172 |
+
.tab-btn:hover {
|
| 173 |
+
background: #1E293B;
|
| 174 |
+
color: #FFFFFF;
|
| 175 |
+
}
|
| 176 |
+
|
| 177 |
+
/* Form Content */
|
| 178 |
+
.form-content {
|
| 179 |
+
padding: 40px;
|
| 180 |
+
background: #1E293B;
|
| 181 |
+
}
|
| 182 |
+
|
| 183 |
+
.form-container {
|
| 184 |
+
position: relative;
|
| 185 |
+
min-height: 300px;
|
| 186 |
+
}
|
| 187 |
+
|
| 188 |
+
.form-panel {
|
| 189 |
+
position: absolute;
|
| 190 |
+
top: 0;
|
| 191 |
+
left: 0;
|
| 192 |
+
right: 0;
|
| 193 |
+
opacity: 0;
|
| 194 |
+
transform: translateX(30px);
|
| 195 |
+
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
|
| 196 |
+
pointer-events: none;
|
| 197 |
+
}
|
| 198 |
+
|
| 199 |
+
.form-panel.active {
|
| 200 |
+
opacity: 1;
|
| 201 |
+
transform: translateX(0);
|
| 202 |
+
pointer-events: all;
|
| 203 |
+
}
|
| 204 |
+
|
| 205 |
+
.form-group {
|
| 206 |
+
margin-bottom: 25px;
|
| 207 |
+
position: relative;
|
| 208 |
+
}
|
| 209 |
+
|
| 210 |
+
.input-wrapper {
|
| 211 |
+
position: relative;
|
| 212 |
+
overflow: hidden;
|
| 213 |
+
border-radius: 8px;
|
| 214 |
+
}
|
| 215 |
+
|
| 216 |
+
.form-input {
|
| 217 |
+
width: 100%;
|
| 218 |
+
padding: 16px 20px;
|
| 219 |
+
border: 1px solid #374151;
|
| 220 |
+
border-radius: 8px;
|
| 221 |
+
font-size: 16px;
|
| 222 |
+
background: #111827;
|
| 223 |
+
color: #E5E7EB;
|
| 224 |
+
transition: all 0.3s ease;
|
| 225 |
+
font-family: inherit;
|
| 226 |
+
}
|
| 227 |
+
|
| 228 |
+
.form-input::placeholder {
|
| 229 |
+
color: #6B7280;
|
| 230 |
+
}
|
| 231 |
+
|
| 232 |
+
.form-input:focus {
|
| 233 |
+
outline: none;
|
| 234 |
+
border-color: #3B82F6;
|
| 235 |
+
background: #111827;
|
| 236 |
+
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
|
| 237 |
+
transform: translateY(-1px);
|
| 238 |
+
}
|
| 239 |
+
|
| 240 |
+
.input-icon {
|
| 241 |
+
position: absolute;
|
| 242 |
+
right: 15px;
|
| 243 |
+
top: 50%;
|
| 244 |
+
transform: translateY(-50%);
|
| 245 |
+
color: #6B7280;
|
| 246 |
+
font-size: 18px;
|
| 247 |
+
transition: all 0.3s ease;
|
| 248 |
+
}
|
| 249 |
+
|
| 250 |
+
.form-input:focus + .input-icon {
|
| 251 |
+
color: #3B82F6;
|
| 252 |
+
transform: translateY(-50%) scale(1.1);
|
| 253 |
+
}
|
| 254 |
+
|
| 255 |
+
/* Buttons */
|
| 256 |
+
.btn {
|
| 257 |
+
width: 100%;
|
| 258 |
+
padding: 16px;
|
| 259 |
+
border: none;
|
| 260 |
+
border-radius: 8px;
|
| 261 |
+
font-size: 16px;
|
| 262 |
+
font-weight: 600;
|
| 263 |
+
cursor: pointer;
|
| 264 |
+
transition: all 0.2s ease;
|
| 265 |
+
margin-bottom: 15px;
|
| 266 |
+
position: relative;
|
| 267 |
+
overflow: hidden;
|
| 268 |
+
font-family: inherit;
|
| 269 |
+
letter-spacing: -0.01em;
|
| 270 |
+
}
|
| 271 |
+
|
| 272 |
+
.btn::before {
|
| 273 |
+
content: '';
|
| 274 |
+
position: absolute;
|
| 275 |
+
top: 0;
|
| 276 |
+
left: -100%;
|
| 277 |
+
width: 100%;
|
| 278 |
+
height: 100%;
|
| 279 |
+
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.1), transparent);
|
| 280 |
+
transition: left 0.5s;
|
| 281 |
+
}
|
| 282 |
+
|
| 283 |
+
.btn:hover::before {
|
| 284 |
+
left: 100%;
|
| 285 |
+
}
|
| 286 |
+
|
| 287 |
+
.btn-primary {
|
| 288 |
+
background: #3B82F6;
|
| 289 |
+
color: #FFFFFF;
|
| 290 |
+
box-shadow: 0 4px 14px 0 rgba(59, 130, 246, 0.25);
|
| 291 |
+
}
|
| 292 |
+
|
| 293 |
+
.btn-primary:hover {
|
| 294 |
+
background: #2563EB;
|
| 295 |
+
transform: translateY(-1px);
|
| 296 |
+
box-shadow: 0 6px 20px 0 rgba(59, 130, 246, 0.35);
|
| 297 |
+
}
|
| 298 |
+
|
| 299 |
+
.btn-secondary {
|
| 300 |
+
background: #6366F1;
|
| 301 |
+
color: #FFFFFF;
|
| 302 |
+
box-shadow: 0 4px 14px 0 rgba(99, 102, 241, 0.25);
|
| 303 |
+
}
|
| 304 |
+
|
| 305 |
+
.btn-secondary:hover {
|
| 306 |
+
background: #5B21B6;
|
| 307 |
+
transform: translateY(-1px);
|
| 308 |
+
box-shadow: 0 6px 20px 0 rgba(99, 102, 241, 0.35);
|
| 309 |
+
}
|
| 310 |
+
|
| 311 |
+
.btn-danger {
|
| 312 |
+
background: #EF4444;
|
| 313 |
+
color: #FFFFFF;
|
| 314 |
+
box-shadow: 0 4px 14px 0 rgba(239, 68, 68, 0.25);
|
| 315 |
+
}
|
| 316 |
+
|
| 317 |
+
.btn-danger:hover {
|
| 318 |
+
background: #DC2626;
|
| 319 |
+
transform: translateY(-1px);
|
| 320 |
+
box-shadow: 0 6px 20px 0 rgba(239, 68, 68, 0.35);
|
| 321 |
+
}
|
| 322 |
+
|
| 323 |
+
.btn:disabled {
|
| 324 |
+
opacity: 0.6;
|
| 325 |
+
cursor: not-allowed;
|
| 326 |
+
transform: none;
|
| 327 |
+
}
|
| 328 |
+
|
| 329 |
+
.btn:disabled:hover {
|
| 330 |
+
transform: none;
|
| 331 |
+
}
|
| 332 |
+
|
| 333 |
+
/* Divider */
|
| 334 |
+
.divider {
|
| 335 |
+
display: flex;
|
| 336 |
+
align-items: center;
|
| 337 |
+
margin: 30px 0;
|
| 338 |
+
color: #6B7280;
|
| 339 |
+
}
|
| 340 |
+
|
| 341 |
+
.divider::before,
|
| 342 |
+
.divider::after {
|
| 343 |
+
content: '';
|
| 344 |
+
flex: 1;
|
| 345 |
+
height: 1px;
|
| 346 |
+
background: linear-gradient(90deg, transparent, #374151, transparent);
|
| 347 |
+
}
|
| 348 |
+
|
| 349 |
+
.divider span {
|
| 350 |
+
padding: 0 20px;
|
| 351 |
+
font-size: 14px;
|
| 352 |
+
font-weight: 500;
|
| 353 |
+
background: #1E293B;
|
| 354 |
+
border-radius: 20px;
|
| 355 |
+
border: 1px solid #374151;
|
| 356 |
+
}
|
| 357 |
+
|
| 358 |
+
/* Face Auth Buttons */
|
| 359 |
+
.face-auth-section {
|
| 360 |
+
margin: 20px 0;
|
| 361 |
+
}
|
| 362 |
+
|
| 363 |
+
.face-auth-section button {
|
| 364 |
+
|
| 365 |
+
background:#4079f4;
|
| 366 |
+
}
|
| 367 |
+
|
| 368 |
+
.face-auth-section button:hover {
|
| 369 |
+
background: #2563EB;
|
| 370 |
+
}
|
| 371 |
+
|
| 372 |
+
.face-btn-group {
|
| 373 |
+
display: flex;
|
| 374 |
+
gap: 12px;
|
| 375 |
+
}
|
| 376 |
+
|
| 377 |
+
.face-btn-group .btn {
|
| 378 |
+
flex: 1;
|
| 379 |
+
margin-bottom: 0;
|
| 380 |
+
display: flex;
|
| 381 |
+
align-items: center;
|
| 382 |
+
justify-content: center;
|
| 383 |
+
gap: 8px;
|
| 384 |
+
}
|
| 385 |
+
|
| 386 |
+
.face-icon {
|
| 387 |
+
font-size: 20px;
|
| 388 |
+
animation: pulse 2s infinite;
|
| 389 |
+
}
|
| 390 |
+
|
| 391 |
+
@keyframes pulse {
|
| 392 |
+
0%, 100% { transform: scale(1); }
|
| 393 |
+
50% { transform: scale(1.05); }
|
| 394 |
+
}
|
| 395 |
+
|
| 396 |
+
/* Status Messages */
|
| 397 |
+
.status-message {
|
| 398 |
+
padding: 15px 20px;
|
| 399 |
+
border-radius: 8px;
|
| 400 |
+
margin-bottom: 25px;
|
| 401 |
+
text-align: center;
|
| 402 |
+
font-weight: 500;
|
| 403 |
+
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
|
| 404 |
+
display: none;
|
| 405 |
+
animation: slideIn 0.4s ease-out;
|
| 406 |
+
}
|
| 407 |
+
|
| 408 |
+
@keyframes slideIn {
|
| 409 |
+
from {
|
| 410 |
+
opacity: 0;
|
| 411 |
+
transform: translateY(-10px);
|
| 412 |
+
}
|
| 413 |
+
to {
|
| 414 |
+
opacity: 1;
|
| 415 |
+
transform: translateY(0);
|
| 416 |
+
}
|
| 417 |
+
}
|
| 418 |
+
|
| 419 |
+
.status-message.success {
|
| 420 |
+
background: rgba(34, 197, 94, 0.1);
|
| 421 |
+
color: #22C55E;
|
| 422 |
+
border: 1px solid rgba(34, 197, 94, 0.2);
|
| 423 |
+
}
|
| 424 |
+
|
| 425 |
+
.status-message.error {
|
| 426 |
+
background: rgba(239, 68, 68, 0.1);
|
| 427 |
+
color: #EF4444;
|
| 428 |
+
border: 1px solid rgba(239, 68, 68, 0.2);
|
| 429 |
+
}
|
| 430 |
+
|
| 431 |
+
.status-message.info {
|
| 432 |
+
background: rgba(59, 130, 246, 0.1);
|
| 433 |
+
color: #3B82F6;
|
| 434 |
+
border: 1px solid rgba(59, 130, 246, 0.2);
|
| 435 |
+
}
|
| 436 |
+
|
| 437 |
+
/* Webcam Section */
|
| 438 |
+
.webcam-section {
|
| 439 |
+
position: fixed;
|
| 440 |
+
top: 0;
|
| 441 |
+
left: 0;
|
| 442 |
+
width: 100%;
|
| 443 |
+
height: 100%;
|
| 444 |
+
background: rgba(11, 17, 33, 0.95);
|
| 445 |
+
display: none;
|
| 446 |
+
align-items: center;
|
| 447 |
+
justify-content: center;
|
| 448 |
+
z-index: 1000;
|
| 449 |
+
backdrop-filter: blur(20px);
|
| 450 |
+
animation: fadeIn 0.3s ease-out;
|
| 451 |
+
}
|
| 452 |
+
|
| 453 |
+
@keyframes fadeIn {
|
| 454 |
+
from { opacity: 0; }
|
| 455 |
+
to { opacity: 1; }
|
| 456 |
+
}
|
| 457 |
+
|
| 458 |
+
.webcam-section.active {
|
| 459 |
+
display: flex;
|
| 460 |
+
}
|
| 461 |
+
|
| 462 |
+
.webcam-container {
|
| 463 |
+
background: #1E293B;
|
| 464 |
+
border: 1px solid #334155;
|
| 465 |
+
border-radius: 16px;
|
| 466 |
+
padding: 30px;
|
| 467 |
+
text-align: center;
|
| 468 |
+
max-width: 500px;
|
| 469 |
+
width: 90%;
|
| 470 |
+
animation: zoomIn 0.4s cubic-bezier(0.4, 0, 0.2, 1);
|
| 471 |
+
box-shadow: 0 10px 25px -3px rgba(0, 0, 0, 0.3);
|
| 472 |
+
}
|
| 473 |
+
|
| 474 |
+
@keyframes zoomIn {
|
| 475 |
+
from {
|
| 476 |
+
opacity: 0;
|
| 477 |
+
transform: scale(0.8);
|
| 478 |
+
}
|
| 479 |
+
to {
|
| 480 |
+
opacity: 1;
|
| 481 |
+
transform: scale(1);
|
| 482 |
+
}
|
| 483 |
+
}
|
| 484 |
+
|
| 485 |
+
.video-container {
|
| 486 |
+
position: relative;
|
| 487 |
+
margin: 20px 0;
|
| 488 |
+
border-radius: 12px;
|
| 489 |
+
overflow: hidden;
|
| 490 |
+
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
|
| 491 |
+
}
|
| 492 |
+
|
| 493 |
+
#webcamVideo {
|
| 494 |
+
width: 100%;
|
| 495 |
+
height: auto;
|
| 496 |
+
max-width: 400px;
|
| 497 |
+
display: block;
|
| 498 |
+
margin: 0 auto;
|
| 499 |
+
border-radius: 12px;
|
| 500 |
+
transition: all 0.3s ease;
|
| 501 |
+
}
|
| 502 |
+
|
| 503 |
+
#webcamCanvas {
|
| 504 |
+
display: none;
|
| 505 |
+
}
|
| 506 |
+
|
| 507 |
+
.webcam-controls {
|
| 508 |
+
display: flex;
|
| 509 |
+
gap: 15px;
|
| 510 |
+
justify-content: center;
|
| 511 |
+
margin-top: 25px;
|
| 512 |
+
flex-wrap: wrap;
|
| 513 |
+
}
|
| 514 |
+
|
| 515 |
+
.webcam-controls .btn {
|
| 516 |
+
flex: 1;
|
| 517 |
+
min-width: 140px;
|
| 518 |
+
margin-bottom: 0;
|
| 519 |
+
}
|
| 520 |
+
|
| 521 |
+
/* Loading Spinner */
|
| 522 |
+
.loading-overlay {
|
| 523 |
+
position: fixed;
|
| 524 |
+
top: 0;
|
| 525 |
+
left: 0;
|
| 526 |
+
width: 100%;
|
| 527 |
+
height: 100%;
|
| 528 |
+
background: rgba(11, 17, 33, 0.95);
|
| 529 |
+
display: none;
|
| 530 |
+
align-items: center;
|
| 531 |
+
justify-content: center;
|
| 532 |
+
z-index: 9999;
|
| 533 |
+
backdrop-filter: blur(10px);
|
| 534 |
+
}
|
| 535 |
+
|
| 536 |
+
.loading-overlay.active {
|
| 537 |
+
display: flex;
|
| 538 |
+
}
|
| 539 |
+
|
| 540 |
+
.loading-spinner {
|
| 541 |
+
text-align: center;
|
| 542 |
+
color: #E5E7EB;
|
| 543 |
+
}
|
| 544 |
+
|
| 545 |
+
.spinner {
|
| 546 |
+
width: 60px;
|
| 547 |
+
height: 60px;
|
| 548 |
+
border: 4px solid #374151;
|
| 549 |
+
border-top: 4px solid #3B82F6;
|
| 550 |
+
border-radius: 50%;
|
| 551 |
+
animation: spin 1s linear infinite;
|
| 552 |
+
margin: 0 auto 20px;
|
| 553 |
+
}
|
| 554 |
+
|
| 555 |
+
@keyframes spin {
|
| 556 |
+
0% { transform: rotate(0deg); }
|
| 557 |
+
100% { transform: rotate(360deg); }
|
| 558 |
+
}
|
| 559 |
+
|
| 560 |
+
/* Security Note */
|
| 561 |
+
.security-note {
|
| 562 |
+
/* background: #111827; */
|
| 563 |
+
border: 1px solid #374151;
|
| 564 |
+
border-radius: 8px;
|
| 565 |
+
padding: 20px;
|
| 566 |
+
margin-top: 30px;
|
| 567 |
+
font-size: 14px;
|
| 568 |
+
/* color: #94A3B8; */
|
| 569 |
+
text-align: center;
|
| 570 |
+
/* animation: fadeInUp 0.6s ease-out 0.5s both; */
|
| 571 |
+
}
|
| 572 |
+
|
| 573 |
+
@keyframes fadeInUp {
|
| 574 |
+
from {
|
| 575 |
+
opacity: 0;
|
| 576 |
+
transform: translateY(20px);
|
| 577 |
+
}
|
| 578 |
+
to {
|
| 579 |
+
opacity: 1;
|
| 580 |
+
transform: translateY(0);
|
| 581 |
+
}
|
| 582 |
+
}
|
| 583 |
+
|
| 584 |
+
.security-icon {
|
| 585 |
+
color: #3B82F6;
|
| 586 |
+
margin-right: 8px;
|
| 587 |
+
font-size: 16px;
|
| 588 |
+
animation: rotate 6s linear infinite;
|
| 589 |
+
}
|
| 590 |
+
|
| 591 |
+
@keyframes rotate {
|
| 592 |
+
from { transform: rotate(0deg); }
|
| 593 |
+
to { transform: rotate(360deg); }
|
| 594 |
+
}
|
| 595 |
+
|
| 596 |
+
/* Responsive Design */
|
| 597 |
+
@media (max-width: 768px) {
|
| 598 |
+
.auth-container {
|
| 599 |
+
margin: 10px;
|
| 600 |
+
border-radius: 12px;
|
| 601 |
+
}
|
| 602 |
+
|
| 603 |
+
.auth-header {
|
| 604 |
+
padding: 25px 20px;
|
| 605 |
+
}
|
| 606 |
+
|
| 607 |
+
.form-content {
|
| 608 |
+
padding: 30px 25px;
|
| 609 |
+
}
|
| 610 |
+
|
| 611 |
+
.auth-title {
|
| 612 |
+
font-size: 24px;
|
| 613 |
+
}
|
| 614 |
+
|
| 615 |
+
.face-btn-group {
|
| 616 |
+
flex-direction: column;
|
| 617 |
+
}
|
| 618 |
+
|
| 619 |
+
.webcam-controls {
|
| 620 |
+
flex-direction: column;
|
| 621 |
+
}
|
| 622 |
+
|
| 623 |
+
.webcam-controls .btn {
|
| 624 |
+
min-width: auto;
|
| 625 |
+
}
|
| 626 |
+
|
| 627 |
+
.particle {
|
| 628 |
+
opacity: 0.2;
|
| 629 |
+
}
|
| 630 |
+
}
|
| 631 |
+
|
| 632 |
+
@media (max-width: 480px) {
|
| 633 |
+
.auth-container {
|
| 634 |
+
margin: 5px;
|
| 635 |
+
}
|
| 636 |
+
|
| 637 |
+
.tab-btn {
|
| 638 |
+
padding: 15px 10px;
|
| 639 |
+
font-size: 14px;
|
| 640 |
+
}
|
| 641 |
+
|
| 642 |
+
.form-content {
|
| 643 |
+
padding: 25px 20px;
|
| 644 |
+
}
|
| 645 |
+
}
|
| 646 |
+
|
| 647 |
+
/* Custom scrollbar */
|
| 648 |
+
::-webkit-scrollbar {
|
| 649 |
+
width: 8px;
|
| 650 |
+
}
|
| 651 |
+
|
| 652 |
+
::-webkit-scrollbar-track {
|
| 653 |
+
background: #1E293B;
|
| 654 |
+
border-radius: 10px;
|
| 655 |
+
}
|
| 656 |
+
|
| 657 |
+
::-webkit-scrollbar-thumb {
|
| 658 |
+
background: linear-gradient(135deg, #3B82F6 0%, #6366F1 100%);
|
| 659 |
+
border-radius: 10px;
|
| 660 |
+
}
|
| 661 |
+
|
| 662 |
+
::-webkit-scrollbar-thumb:hover {
|
| 663 |
+
background: linear-gradient(135deg, #2563EB 0%, #5B21B6 100%);
|
| 664 |
+
}
|
| 665 |
+
</style>
|
| 666 |
+
</head>
|
| 667 |
+
<body>
|
| 668 |
+
<!-- Animated Background -->
|
| 669 |
+
<div class="bg-particles">
|
| 670 |
+
<div class="particle"></div>
|
| 671 |
+
<div class="particle"></div>
|
| 672 |
+
<div class="particle"></div>
|
| 673 |
+
<div class="particle"></div>
|
| 674 |
+
<div class="particle"></div>
|
| 675 |
+
</div>
|
| 676 |
+
|
| 677 |
+
<!-- Loading Overlay -->
|
| 678 |
+
<div id="loadingOverlay" class="loading-overlay">
|
| 679 |
+
<div class="loading-spinner">
|
| 680 |
+
<div class="spinner"></div>
|
| 681 |
+
<p>Processing...</p>
|
| 682 |
+
</div>
|
| 683 |
+
</div>
|
| 684 |
+
|
| 685 |
+
<!-- Main Wrapper -->
|
| 686 |
+
<div class="auth-wrapper">
|
| 687 |
+
<div class="auth-container">
|
| 688 |
+
<!-- Header -->
|
| 689 |
+
<div class="auth-header">
|
| 690 |
+
<h1 id="authModeTitle" class="auth-title">Welcome Back</h1>
|
| 691 |
+
<p id="authSubtitle" class="auth-subtitle">Secure authentication with facial recognition</p>
|
| 692 |
+
</div>
|
| 693 |
+
|
| 694 |
+
<!-- Tab Navigation -->
|
| 695 |
+
<div class="tab-navigation">
|
| 696 |
+
<button id="loginTab" class="tab-btn active">
|
| 697 |
+
🔑 Login
|
| 698 |
+
</button>
|
| 699 |
+
<button id="registerTab" class="tab-btn">
|
| 700 |
+
👤 Register
|
| 701 |
+
</button>
|
| 702 |
+
</div>
|
| 703 |
+
|
| 704 |
+
<!-- Form Content -->
|
| 705 |
+
<div class="form-content">
|
| 706 |
+
<!-- Flash messages from Flask are handled here -->
|
| 707 |
+
{% with messages = get_flashed_messages(with_categories=true) %}
|
| 708 |
+
{% if messages %}
|
| 709 |
+
<div id="flaskStatusMessage" class="status-message">
|
| 710 |
+
{% for category, message in messages %}
|
| 711 |
+
<div class="flash-message flash-{{ category }}">{{ message }}</div>
|
| 712 |
+
{% endfor %}
|
| 713 |
+
</div>
|
| 714 |
+
{% else %}
|
| 715 |
+
<div id="authStatusMessage" class="status-message"></div>
|
| 716 |
+
{% endif %}
|
| 717 |
+
{% endwith %}
|
| 718 |
+
|
| 719 |
+
<div class="form-container">
|
| 720 |
+
<!-- Login Panel -->
|
| 721 |
+
<div id="loginPanel" class="form-panel active">
|
| 722 |
+
<form id="loginForm">
|
| 723 |
+
<div class="form-group">
|
| 724 |
+
<div class="input-wrapper">
|
| 725 |
+
<input type="email" id="loginEmail" name="email" class="form-input"
|
| 726 |
+
placeholder="Enter your email address" required>
|
| 727 |
+
<div class="input-icon">📧</div>
|
| 728 |
+
</div>
|
| 729 |
+
</div>
|
| 730 |
+
<div class="form-group">
|
| 731 |
+
<div class="input-wrapper">
|
| 732 |
+
<input type="password" id="loginPassword" name="password" class="form-input"
|
| 733 |
+
placeholder="Enter your password" required>
|
| 734 |
+
<div class="input-icon">🔒</div>
|
| 735 |
+
</div>
|
| 736 |
+
</div>
|
| 737 |
+
<button type="submit" class="btn btn-primary">
|
| 738 |
+
🚀 Sign In
|
| 739 |
+
</button>
|
| 740 |
+
</form>
|
| 741 |
+
|
| 742 |
+
<div class="divider">
|
| 743 |
+
<span>or continue with</span>
|
| 744 |
+
</div>
|
| 745 |
+
|
| 746 |
+
<div class="face-auth-section">
|
| 747 |
+
<button type="button" id="faceLoginBtn" class="btn btn-secondary">
|
| 748 |
+
<span class="face-icon">👁️</span>
|
| 749 |
+
Face Recognition
|
| 750 |
+
</button>
|
| 751 |
+
</div>
|
| 752 |
+
</div>
|
| 753 |
+
|
| 754 |
+
<!-- Register Panel -->
|
| 755 |
+
<div id="registerPanel" class="form-panel">
|
| 756 |
+
<form id="registerForm">
|
| 757 |
+
<div class="form-group">
|
| 758 |
+
<div class="input-wrapper">
|
| 759 |
+
<input type="email" id="registerEmail" name="email" class="form-input"
|
| 760 |
+
placeholder="Enter your email address" required>
|
| 761 |
+
<div class="input-icon">📧</div>
|
| 762 |
+
</div>
|
| 763 |
+
</div>
|
| 764 |
+
<div class="form-group">
|
| 765 |
+
<div class="input-wrapper">
|
| 766 |
+
<input type="password" id="registerPassword" name="password" class="form-input"
|
| 767 |
+
placeholder="Create a strong password" required minlength="6">
|
| 768 |
+
<div class="input-icon">🔐</div>
|
| 769 |
+
</div>
|
| 770 |
+
</div>
|
| 771 |
+
<button type="submit" class="btn btn-primary">
|
| 772 |
+
✨ Create Account
|
| 773 |
+
</button>
|
| 774 |
+
</form>
|
| 775 |
+
|
| 776 |
+
<div class="divider">
|
| 777 |
+
<span>enhance security with</span>
|
| 778 |
+
</div>
|
| 779 |
+
|
| 780 |
+
<div class="face-auth-section">
|
| 781 |
+
<button type="button" id="faceRegisterBtn" class="btn btn-secondary">
|
| 782 |
+
<span class="face-icon">📸</span>
|
| 783 |
+
Setup Face ID
|
| 784 |
+
</button>
|
| 785 |
+
</div>
|
| 786 |
+
</div>
|
| 787 |
+
</div>
|
| 788 |
+
|
| 789 |
+
<!-- Security Note -->
|
| 790 |
+
<div class="security-note">
|
| 791 |
+
<span class="security-icon"></span>
|
| 792 |
+
<!-- Your facial data is encrypted and stored locally with bank-level security -->
|
| 793 |
+
</div>
|
| 794 |
+
</div>
|
| 795 |
+
</div>
|
| 796 |
+
</div>
|
| 797 |
+
|
| 798 |
+
<!-- Webcam Section -->
|
| 799 |
+
<div id="webcamSection" class="webcam-section">
|
| 800 |
+
<div class="webcam-container">
|
| 801 |
+
<h2 style="color: white; margin-bottom: 20px;">📷 Face Recognition</h2>
|
| 802 |
+
<div class="video-container">
|
| 803 |
+
<video id="webcamVideo" autoplay muted playsinline></video>
|
| 804 |
+
<canvas id="webcamCanvas"></canvas>
|
| 805 |
+
</div>
|
| 806 |
+
|
| 807 |
+
<div class="webcam-controls">
|
| 808 |
+
<button id="captureFaceBtn" class="btn btn-primary" style="display: none;">
|
| 809 |
+
📸 Capture Face (0/3)
|
| 810 |
+
</button>
|
| 811 |
+
<button id="cancelWebcamBtn" class="btn btn-danger">
|
| 812 |
+
❌ Cancel
|
| 813 |
+
</button>
|
| 814 |
+
</div>
|
| 815 |
+
</div>
|
| 816 |
+
</div>
|
| 817 |
+
|
| 818 |
+
<script>
|
| 819 |
+
document.addEventListener('DOMContentLoaded', () => {
|
| 820 |
+
// DOM Elements
|
| 821 |
+
const authModeTitle = document.getElementById('authModeTitle');
|
| 822 |
+
const authSubtitle = document.getElementById('authSubtitle');
|
| 823 |
+
const loginTab = document.getElementById('loginTab');
|
| 824 |
+
const registerTab = document.getElementById('registerTab');
|
| 825 |
+
const loginPanel = document.getElementById('loginPanel');
|
| 826 |
+
const registerPanel = document.getElementById('registerPanel');
|
| 827 |
+
const loginForm = document.getElementById('loginForm');
|
| 828 |
+
const registerForm = document.getElementById('registerForm');
|
| 829 |
+
const authStatusMessage = document.getElementById('authStatusMessage'); // JS-driven message
|
| 830 |
+
const flaskStatusMessage = document.getElementById('flaskStatusMessage'); // Flask flash message container
|
| 831 |
+
|
| 832 |
+
|
| 833 |
+
const webcamSection = document.getElementById('webcamSection');
|
| 834 |
+
const webcamVideo = document.getElementById('webcamVideo');
|
| 835 |
+
const webcamCanvas = document.getElementById('webcamCanvas');
|
| 836 |
+
const captureFaceBtn = document.getElementById('captureFaceBtn');
|
| 837 |
+
const cancelWebcamBtn = document.getElementById('cancelWebcamBtn');
|
| 838 |
+
const loadingOverlay = document.getElementById('loadingOverlay');
|
| 839 |
+
|
| 840 |
+
const faceRegisterBtn = document.getElementById('faceRegisterBtn');
|
| 841 |
+
const faceLoginBtn = document.getElementById('faceLoginBtn');
|
| 842 |
+
|
| 843 |
+
let currentStream;
|
| 844 |
+
let captureCount = 0;
|
| 845 |
+
const MAX_CAPTURES = 3;
|
| 846 |
+
let capturedImages = [];
|
| 847 |
+
let currentAuthMode = 'login'; // Track current mode for webcam behavior
|
| 848 |
+
|
| 849 |
+
// --- Utility Functions ---
|
| 850 |
+
const showMessage = (message, type = 'info') => {
|
| 851 |
+
// Clear any existing Flask messages when showing JS messages
|
| 852 |
+
if (flaskStatusMessage) {
|
| 853 |
+
flaskStatusMessage.innerHTML = '';
|
| 854 |
+
flaskStatusMessage.style.display = 'none';
|
| 855 |
+
}
|
| 856 |
+
|
| 857 |
+
if (message) {
|
| 858 |
+
authStatusMessage.textContent = message;
|
| 859 |
+
authStatusMessage.className = `status-message ${type}`;
|
| 860 |
+
authStatusMessage.style.display = 'block';
|
| 861 |
+
} else {
|
| 862 |
+
authStatusMessage.style.display = 'none';
|
| 863 |
+
}
|
| 864 |
+
console.log(`UI Message (${type}): ${message}`);
|
| 865 |
+
};
|
| 866 |
+
|
| 867 |
+
const showLoading = (show) => {
|
| 868 |
+
if (show) {
|
| 869 |
+
loadingOverlay.classList.add('active');
|
| 870 |
+
} else {
|
| 871 |
+
loadingOverlay.classList.remove('active');
|
| 872 |
+
}
|
| 873 |
+
};
|
| 874 |
+
|
| 875 |
+
const resetCapture = () => {
|
| 876 |
+
captureCount = 0;
|
| 877 |
+
capturedImages = [];
|
| 878 |
+
captureFaceBtn.textContent = `📸 Capture Face (0/${MAX_CAPTURES})`;
|
| 879 |
+
};
|
| 880 |
+
|
| 881 |
+
// --- Tab Functions ---
|
| 882 |
+
const showLoginMode = () => {
|
| 883 |
+
currentAuthMode = 'login';
|
| 884 |
+
authModeTitle.textContent = 'Welcome Back';
|
| 885 |
+
authSubtitle.textContent = 'Secure authentication with facial recognition';
|
| 886 |
+
|
| 887 |
+
loginTab.classList.add('active');
|
| 888 |
+
registerTab.classList.remove('active');
|
| 889 |
+
|
| 890 |
+
loginPanel.classList.add('active');
|
| 891 |
+
registerPanel.classList.remove('active');
|
| 892 |
+
|
| 893 |
+
showMessage(''); // Clear JS messages when changing tabs
|
| 894 |
+
hideWebcam();
|
| 895 |
+
};
|
| 896 |
+
|
| 897 |
+
const showRegisterMode = () => {
|
| 898 |
+
currentAuthMode = 'register';
|
| 899 |
+
authModeTitle.textContent = 'Join Us Today';
|
| 900 |
+
authSubtitle.textContent = 'Create your secure account with advanced biometrics';
|
| 901 |
+
|
| 902 |
+
registerTab.classList.add('active');
|
| 903 |
+
loginTab.classList.remove('active');
|
| 904 |
+
|
| 905 |
+
registerPanel.classList.add('active');
|
| 906 |
+
loginPanel.classList.remove('active');
|
| 907 |
+
|
| 908 |
+
showMessage(''); // Clear JS messages when changing tabs
|
| 909 |
+
hideWebcam();
|
| 910 |
+
};
|
| 911 |
+
|
| 912 |
+
// --- Webcam Functions ---
|
| 913 |
+
const startWebcam = async () => {
|
| 914 |
+
try {
|
| 915 |
+
console.log('Starting webcam...');
|
| 916 |
+
resetCapture(); // Reset captures every time webcam starts
|
| 917 |
+
|
| 918 |
+
const stream = await navigator.mediaDevices.getUserMedia({
|
| 919 |
+
video: {
|
| 920 |
+
width: { ideal: 640 },
|
| 921 |
+
height: { ideal: 480 },
|
| 922 |
+
facingMode: 'user'
|
| 923 |
+
}
|
| 924 |
+
});
|
| 925 |
+
|
| 926 |
+
webcamVideo.srcObject = stream;
|
| 927 |
+
currentStream = stream;
|
| 928 |
+
webcamSection.classList.add('active');
|
| 929 |
+
|
| 930 |
+
// Wait for video to be ready
|
| 931 |
+
webcamVideo.onloadedmetadata = () => {
|
| 932 |
+
console.log('Webcam ready');
|
| 933 |
+
if (currentAuthMode === 'register') {
|
| 934 |
+
captureFaceBtn.style.display = 'block';
|
| 935 |
+
showMessage(`Position your face clearly in the camera. You need to capture ${MAX_CAPTURES} images.`, 'info');
|
| 936 |
+
captureFaceBtn.textContent = `📸 Capture Face (0/${MAX_CAPTURES})`; // Reset text
|
| 937 |
+
} else { // Login mode
|
| 938 |
+
showMessage('Position your face clearly in the camera for recognition.', 'info');
|
| 939 |
+
captureFaceBtn.style.display = 'none'; // No manual capture button for login
|
| 940 |
+
// For login, capture automatically after a short delay
|
| 941 |
+
setTimeout(() => {
|
| 942 |
+
captureForLogin();
|
| 943 |
+
}, 2000); // Give user 2 seconds to position face
|
| 944 |
+
}
|
| 945 |
+
};
|
| 946 |
+
|
| 947 |
+
} catch (error) {
|
| 948 |
+
console.error('Error accessing webcam:', error);
|
| 949 |
+
let errorMessage = 'Error accessing camera. Please ensure camera permissions are granted.';
|
| 950 |
+
if (error.name === 'NotAllowedError') {
|
| 951 |
+
errorMessage = 'Camera access denied. Please allow camera access in your browser settings.';
|
| 952 |
+
} else if (error.name === 'NotFoundError') {
|
| 953 |
+
errorMessage = 'No camera found. Please ensure a camera is connected and working.';
|
| 954 |
+
}
|
| 955 |
+
showMessage(errorMessage, 'error');
|
| 956 |
+
}
|
| 957 |
+
};
|
| 958 |
+
|
| 959 |
+
const hideWebcam = () => {
|
| 960 |
+
webcamSection.classList.remove('active');
|
| 961 |
+
captureFaceBtn.style.display = 'none';
|
| 962 |
+
if (currentStream) {
|
| 963 |
+
currentStream.getTracks().forEach(track => track.stop());
|
| 964 |
+
currentStream = null;
|
| 965 |
+
}
|
| 966 |
+
resetCapture(); // Also reset captures when hiding webcam
|
| 967 |
+
};
|
| 968 |
+
|
| 969 |
+
const captureImage = () => {
|
| 970 |
+
const canvas = webcamCanvas;
|
| 971 |
+
const context = canvas.getContext('2d');
|
| 972 |
+
const video = webcamVideo;
|
| 973 |
+
|
| 974 |
+
// Set canvas dimensions to match video
|
| 975 |
+
canvas.width = video.videoWidth;
|
| 976 |
+
canvas.height = video.videoHeight;
|
| 977 |
+
|
| 978 |
+
// Draw current video frame to canvas
|
| 979 |
+
context.drawImage(video, 0, 0, canvas.width, canvas.height);
|
| 980 |
+
|
| 981 |
+
// Get base64 image data
|
| 982 |
+
const imageData = canvas.toDataURL('image/jpeg', 0.8); // 0.8 quality for smaller size
|
| 983 |
+
console.log('Image captured, data length:', imageData.length);
|
| 984 |
+
|
| 985 |
+
return imageData;
|
| 986 |
+
};
|
| 987 |
+
|
| 988 |
+
const captureForRegister = () => {
|
| 989 |
+
if (captureCount >= MAX_CAPTURES) {
|
| 990 |
+
console.log('Max captures already reached for registration.');
|
| 991 |
+
return;
|
| 992 |
+
}
|
| 993 |
+
|
| 994 |
+
const imageData = captureImage();
|
| 995 |
+
if (imageData) {
|
| 996 |
+
capturedImages.push(imageData);
|
| 997 |
+
captureCount++;
|
| 998 |
+
captureFaceBtn.textContent = `📸 Capture Face (${captureCount}/${MAX_CAPTURES})`;
|
| 999 |
+
|
| 1000 |
+
console.log(`Captured image ${captureCount}/${MAX_CAPTURES}`);
|
| 1001 |
+
|
| 1002 |
+
if (captureCount === MAX_CAPTURES) {
|
| 1003 |
+
showMessage('All images captured! Processing registration...', 'info');
|
| 1004 |
+
captureFaceBtn.disabled = true; // Disable button after all captures
|
| 1005 |
+
setTimeout(() => submitFaceRegistration(), 500); // Small delay before submitting
|
| 1006 |
+
} else {
|
| 1007 |
+
showMessage(`Captured image ${captureCount}/${MAX_CAPTURES}. Capture ${MAX_CAPTURES - captureCount} more.`, 'success');
|
| 1008 |
+
}
|
| 1009 |
+
} else {
|
| 1010 |
+
showMessage('Failed to capture image. Please try again.', 'error');
|
| 1011 |
+
}
|
| 1012 |
+
};
|
| 1013 |
+
|
| 1014 |
+
const captureForLogin = () => {
|
| 1015 |
+
const imageData = captureImage();
|
| 1016 |
+
if (imageData) {
|
| 1017 |
+
console.log('Image captured for login');
|
| 1018 |
+
showMessage('Image captured. Processing login...', 'info');
|
| 1019 |
+
submitFaceLogin(imageData);
|
| 1020 |
+
} else {
|
| 1021 |
+
showMessage('Failed to capture image for login. Please try again.', 'error');
|
| 1022 |
+
hideWebcam(); // Close webcam on failure for login
|
| 1023 |
+
}
|
| 1024 |
+
};
|
| 1025 |
+
|
| 1026 |
+
// --- API Functions ---
|
| 1027 |
+
const submitFaceRegistration = async () => {
|
| 1028 |
+
showLoading(true);
|
| 1029 |
+
|
| 1030 |
+
const email = document.getElementById('registerEmail').value;
|
| 1031 |
+
const password = document.getElementById('registerPassword').value;
|
| 1032 |
+
|
| 1033 |
+
if (!email || !password) {
|
| 1034 |
+
showMessage('Please enter email and password before capturing face images.', 'error');
|
| 1035 |
+
showLoading(false);
|
| 1036 |
+
captureFaceBtn.disabled = false; // Re-enable button
|
| 1037 |
+
return;
|
| 1038 |
+
}
|
| 1039 |
+
|
| 1040 |
+
if (password.length < 6) {
|
| 1041 |
+
showMessage('Password must be at least 6 characters long.', 'error');
|
| 1042 |
+
showLoading(false);
|
| 1043 |
+
captureFaceBtn.disabled = false; // Re-enable button
|
| 1044 |
+
return;
|
| 1045 |
+
}
|
| 1046 |
+
|
| 1047 |
+
try {
|
| 1048 |
+
console.log('Submitting face registration with', capturedImages.length, 'images');
|
| 1049 |
+
|
| 1050 |
+
const response = await fetch('/face_register', {
|
| 1051 |
+
method: 'POST',
|
| 1052 |
+
headers: {
|
| 1053 |
+
'Content-Type': 'application/json',
|
| 1054 |
+
},
|
| 1055 |
+
body: JSON.stringify({
|
| 1056 |
+
email: email,
|
| 1057 |
+
password: password,
|
| 1058 |
+
images: capturedImages
|
| 1059 |
+
})
|
| 1060 |
+
});
|
| 1061 |
+
|
| 1062 |
+
const result = await response.json();
|
| 1063 |
+
console.log('Face registration response:', result);
|
| 1064 |
+
|
| 1065 |
+
if (result.success) {
|
| 1066 |
+
showMessage(result.message, 'success');
|
| 1067 |
+
hideWebcam();
|
| 1068 |
+
setTimeout(() => {
|
| 1069 |
+
showLoginMode(); // Redirect to login after successful registration
|
| 1070 |
+
}, 2000);
|
| 1071 |
+
} else {
|
| 1072 |
+
showMessage(result.message, 'error');
|
| 1073 |
+
resetCapture();
|
| 1074 |
+
captureFaceBtn.disabled = false; // Re-enable button
|
| 1075 |
+
captureFaceBtn.style.display = 'block'; // Show button again
|
| 1076 |
+
}
|
| 1077 |
+
} catch (error) {
|
| 1078 |
+
console.error('Face registration error:', error);
|
| 1079 |
+
showMessage('Network error during face registration. Please try again.', 'error');
|
| 1080 |
+
resetCapture();
|
| 1081 |
+
captureFaceBtn.disabled = false; // Re-enable button
|
| 1082 |
+
captureFaceBtn.style.display = 'block'; // Show button again
|
| 1083 |
+
} finally {
|
| 1084 |
+
showLoading(false);
|
| 1085 |
+
}
|
| 1086 |
+
};
|
| 1087 |
+
|
| 1088 |
+
const submitFaceLogin = async (imageData) => {
|
| 1089 |
+
showLoading(true);
|
| 1090 |
+
|
| 1091 |
+
try {
|
| 1092 |
+
console.log('Submitting face login');
|
| 1093 |
+
|
| 1094 |
+
const response = await fetch('/face_login', {
|
| 1095 |
+
method: 'POST',
|
| 1096 |
+
headers: {
|
| 1097 |
+
'Content-Type': 'application/json',
|
| 1098 |
+
},
|
| 1099 |
+
body: JSON.stringify({
|
| 1100 |
+
image: imageData
|
| 1101 |
+
})
|
| 1102 |
+
});
|
| 1103 |
+
|
| 1104 |
+
const result = await response.json();
|
| 1105 |
+
console.log('Face login response:', result);
|
| 1106 |
+
|
| 1107 |
+
if (result.success) {
|
| 1108 |
+
showMessage(result.message, 'success');
|
| 1109 |
+
hideWebcam();
|
| 1110 |
+
setTimeout(() => {
|
| 1111 |
+
window.location.href = '/main_app'; // Redirect to main app page after login
|
| 1112 |
+
}, 1500);
|
| 1113 |
+
} else {
|
| 1114 |
+
showMessage(result.message, 'error');
|
| 1115 |
+
hideWebcam();
|
| 1116 |
+
// No need to restart webcam, user can click Face Recognition again
|
| 1117 |
+
}
|
| 1118 |
+
} catch (error) {
|
| 1119 |
+
console.error('Face login error:', error);
|
| 1120 |
+
showMessage('Network error during face login. Please try again.', 'error');
|
| 1121 |
+
hideWebcam();
|
| 1122 |
+
} finally {
|
| 1123 |
+
showLoading(false);
|
| 1124 |
+
}
|
| 1125 |
+
};
|
| 1126 |
+
|
| 1127 |
+
const submitLogin = async (formData) => {
|
| 1128 |
+
showLoading(true);
|
| 1129 |
+
|
| 1130 |
+
try {
|
| 1131 |
+
const response = await fetch('/login', {
|
| 1132 |
+
method: 'POST',
|
| 1133 |
+
body: formData
|
| 1134 |
+
});
|
| 1135 |
+
|
| 1136 |
+
const result = await response.json();
|
| 1137 |
+
|
| 1138 |
+
if (result.success) {
|
| 1139 |
+
showMessage(result.message, 'success');
|
| 1140 |
+
setTimeout(() => {
|
| 1141 |
+
window.location.href = '/main_app'; // Redirect to main app page after login
|
| 1142 |
+
}, 1500);
|
| 1143 |
+
} else {
|
| 1144 |
+
showMessage(result.message, 'error');
|
| 1145 |
+
}
|
| 1146 |
+
} catch (error) {
|
| 1147 |
+
console.error('Login error:', error);
|
| 1148 |
+
showMessage('Network error during login. Please try again.', 'error');
|
| 1149 |
+
} finally {
|
| 1150 |
+
showLoading(false);
|
| 1151 |
+
}
|
| 1152 |
+
};
|
| 1153 |
+
|
| 1154 |
+
const submitRegister = async (formData) => {
|
| 1155 |
+
showLoading(true);
|
| 1156 |
+
|
| 1157 |
+
try {
|
| 1158 |
+
const response = await fetch('/register', {
|
| 1159 |
+
method: 'POST',
|
| 1160 |
+
body: formData
|
| 1161 |
+
});
|
| 1162 |
+
|
| 1163 |
+
const result = await response.json();
|
| 1164 |
+
|
| 1165 |
+
if (result.success) {
|
| 1166 |
+
showMessage(result.message, 'success');
|
| 1167 |
+
setTimeout(() => {
|
| 1168 |
+
showLoginMode(); // Redirect to login after successful registration
|
| 1169 |
+
}, 2000);
|
| 1170 |
+
} else {
|
| 1171 |
+
showMessage(result.message, 'error');
|
| 1172 |
+
}
|
| 1173 |
+
} catch (error) {
|
| 1174 |
+
console.error('Registration error:', error);
|
| 1175 |
+
showMessage('Network error during registration. Please try again.', 'error');
|
| 1176 |
+
} finally {
|
| 1177 |
+
showLoading(false);
|
| 1178 |
+
}
|
| 1179 |
+
};
|
| 1180 |
+
|
| 1181 |
+
// --- Event Listeners ---
|
| 1182 |
+
loginTab.addEventListener('click', showLoginMode);
|
| 1183 |
+
registerTab.addEventListener('click', showRegisterMode);
|
| 1184 |
+
|
| 1185 |
+
loginForm.addEventListener('submit', (e) => {
|
| 1186 |
+
e.preventDefault();
|
| 1187 |
+
const formData = new FormData(e.target);
|
| 1188 |
+
submitLogin(formData);
|
| 1189 |
+
});
|
| 1190 |
+
|
| 1191 |
+
registerForm.addEventListener('submit', (e) => {
|
| 1192 |
+
e.preventDefault();
|
| 1193 |
+
const formData = new FormData(e.target);
|
| 1194 |
+
submitRegister(formData);
|
| 1195 |
+
});
|
| 1196 |
+
|
| 1197 |
+
faceRegisterBtn.addEventListener('click', () => {
|
| 1198 |
+
const email = document.getElementById('registerEmail').value;
|
| 1199 |
+
const password = document.getElementById('registerPassword').value;
|
| 1200 |
+
|
| 1201 |
+
if (!email || !password) {
|
| 1202 |
+
showMessage('Please enter email and password before setting up face registration.', 'error');
|
| 1203 |
+
return;
|
| 1204 |
+
}
|
| 1205 |
+
|
| 1206 |
+
if (password.length < 6) {
|
| 1207 |
+
showMessage('Password must be at least 6 characters long.', 'error');
|
| 1208 |
+
return;
|
| 1209 |
+
}
|
| 1210 |
+
|
| 1211 |
+
startWebcam(); // Start webcam for capturing multiple images
|
| 1212 |
+
});
|
| 1213 |
+
|
| 1214 |
+
faceLoginBtn.addEventListener('click', () => {
|
| 1215 |
+
startWebcam(); // Start webcam for a single login attempt
|
| 1216 |
+
});
|
| 1217 |
+
|
| 1218 |
+
captureFaceBtn.addEventListener('click', () => {
|
| 1219 |
+
if (currentAuthMode === 'register') {
|
| 1220 |
+
captureForRegister();
|
| 1221 |
+
}
|
| 1222 |
+
// No action needed for login on this button, as login capture is automatic
|
| 1223 |
+
});
|
| 1224 |
+
|
| 1225 |
+
cancelWebcamBtn.addEventListener('click', () => {
|
| 1226 |
+
hideWebcam();
|
| 1227 |
+
showMessage('Camera cancelled.', 'info');
|
| 1228 |
+
});
|
| 1229 |
+
|
| 1230 |
+
// Add input focus animations
|
| 1231 |
+
const formInputs = document.querySelectorAll('.form-input');
|
| 1232 |
+
formInputs.forEach(input => {
|
| 1233 |
+
input.addEventListener('focus', () => {
|
| 1234 |
+
input.parentElement.style.transform = 'translateY(-2px)';
|
| 1235 |
+
});
|
| 1236 |
+
|
| 1237 |
+
input.addEventListener('blur', () => {
|
| 1238 |
+
input.parentElement.style.transform = 'translateY(0)';
|
| 1239 |
+
});
|
| 1240 |
+
});
|
| 1241 |
+
|
| 1242 |
+
// Add button click animations
|
| 1243 |
+
const allButtons = document.querySelectorAll('.btn');
|
| 1244 |
+
allButtons.forEach(button => {
|
| 1245 |
+
button.addEventListener('click', () => {
|
| 1246 |
+
button.style.transform = 'scale(0.98)';
|
| 1247 |
+
setTimeout(() => {
|
| 1248 |
+
button.style.transform = '';
|
| 1249 |
+
}, 150);
|
| 1250 |
+
});
|
| 1251 |
+
});
|
| 1252 |
+
|
| 1253 |
+
// Initialize the page
|
| 1254 |
+
console.log('Dynamic Facial Recognition Authentication System Loaded');
|
| 1255 |
+
|
| 1256 |
+
// Check for Flask flash messages on page load and display them
|
| 1257 |
+
if (flaskStatusMessage && flaskStatusMessage.children.length > 0) {
|
| 1258 |
+
flaskStatusMessage.style.display = 'block';
|
| 1259 |
+
// Hide JS-driven message if Flask messages are present
|
| 1260 |
+
authStatusMessage.style.display = 'none';
|
| 1261 |
+
// Set a timeout to fade out Flask messages if desired, similar to JS messages
|
| 1262 |
+
setTimeout(() => {
|
| 1263 |
+
flaskStatusMessage.style.opacity = '0';
|
| 1264 |
+
setTimeout(() => flaskStatusMessage.style.display = 'none', 300); // Allow fade out
|
| 1265 |
+
}, 5000); // Hide after 5 seconds
|
| 1266 |
+
} else {
|
| 1267 |
+
showMessage(''); // Clear initial message if no Flask messages
|
| 1268 |
+
}
|
| 1269 |
+
|
| 1270 |
+
// Add some dynamic particle movement
|
| 1271 |
+
const particles = document.querySelectorAll('.particle');
|
| 1272 |
+
particles.forEach((particle, index) => {
|
| 1273 |
+
setInterval(() => {
|
| 1274 |
+
const randomX = Math.random() * 100;
|
| 1275 |
+
const randomY = Math.random() * 100;
|
| 1276 |
+
particle.style.left = randomX + '%';
|
| 1277 |
+
particle.style.top = randomY + '%';
|
| 1278 |
+
}, 8000 + index * 1000);
|
| 1279 |
+
});
|
| 1280 |
+
});
|
| 1281 |
+
</script>
|
| 1282 |
+
</body>
|
| 1283 |
+
</html>
|
templates/index - Copy.txt
ADDED
|
@@ -0,0 +1,1343 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html lang="en">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="UTF-8">
|
| 5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
+
<title>VisionCraft AI - Custom Image Captioning & Segmentation</title>
|
| 7 |
+
<style>
|
| 8 |
+
/* All original CSS from website_for_image_captioning.txt */
|
| 9 |
+
* {
|
| 10 |
+
margin: 0;
|
| 11 |
+
padding: 0;
|
| 12 |
+
box-sizing: border-box;
|
| 13 |
+
}
|
| 14 |
+
|
| 15 |
+
body {
|
| 16 |
+
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
| 17 |
+
line-height: 1.6;
|
| 18 |
+
color: #333;
|
| 19 |
+
overflow-x: hidden;
|
| 20 |
+
background-color: #f0f2f5; /* Added a light background for overall page */
|
| 21 |
+
}
|
| 22 |
+
|
| 23 |
+
/* Hero Section */
|
| 24 |
+
.hero {
|
| 25 |
+
height: 100vh;
|
| 26 |
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
| 27 |
+
display: flex;
|
| 28 |
+
align-items: center;
|
| 29 |
+
justify-content: center;
|
| 30 |
+
position: relative;
|
| 31 |
+
overflow: hidden;
|
| 32 |
+
}
|
| 33 |
+
|
| 34 |
+
.hero::before {
|
| 35 |
+
content: '';
|
| 36 |
+
position: absolute;
|
| 37 |
+
width: 200%;
|
| 38 |
+
height: 200%;
|
| 39 |
+
background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><circle cx="25" cy="25" r="1" fill="rgba(255,255,255,0.1)"/><circle cx="75" cy="75" r="1" fill="rgba(255,255,255,0.1)"/><circle cx="50" cy="50" r="0.5" fill="rgba(255,255,255,0.2)"/></svg>') repeat;
|
| 40 |
+
animation: float 20s infinite linear;
|
| 41 |
+
}
|
| 42 |
+
|
| 43 |
+
@keyframes float {
|
| 44 |
+
0% { transform: translate(-50%, -50%); }
|
| 45 |
+
100% { transform: translate(-30%, -30%); }
|
| 46 |
+
}
|
| 47 |
+
|
| 48 |
+
.hero-content {
|
| 49 |
+
text-align: center;
|
| 50 |
+
z-index: 2;
|
| 51 |
+
position: relative;
|
| 52 |
+
}
|
| 53 |
+
|
| 54 |
+
.hero h1 {
|
| 55 |
+
font-size: 4rem;
|
| 56 |
+
font-weight: 700;
|
| 57 |
+
margin-bottom: 1rem;
|
| 58 |
+
background: linear-gradient(45deg, #fff, #f0f8ff);
|
| 59 |
+
-webkit-background-clip: text;
|
| 60 |
+
-webkit-text-fill-color: transparent;
|
| 61 |
+
background-clip: text;
|
| 62 |
+
animation: glow 2s ease-in-out infinite alternate;
|
| 63 |
+
}
|
| 64 |
+
|
| 65 |
+
@keyframes glow {
|
| 66 |
+
from { text-shadow: 0 0 20px rgba(255,255,255,0.5); }
|
| 67 |
+
to { text-shadow: 0 0 30px rgba(255,255,255,0.8); }
|
| 68 |
+
}
|
| 69 |
+
|
| 70 |
+
.hero p {
|
| 71 |
+
font-size: 1.5rem;
|
| 72 |
+
color: rgba(255,255,255,0.9);
|
| 73 |
+
margin-bottom: 2rem;
|
| 74 |
+
max-width: 800px;
|
| 75 |
+
}
|
| 76 |
+
|
| 77 |
+
.cta-buttons {
|
| 78 |
+
display: flex;
|
| 79 |
+
gap: 2rem;
|
| 80 |
+
justify-content: center;
|
| 81 |
+
flex-wrap: wrap;
|
| 82 |
+
}
|
| 83 |
+
|
| 84 |
+
.btn {
|
| 85 |
+
padding: 1rem 2rem;
|
| 86 |
+
border: none;
|
| 87 |
+
border-radius: 50px;
|
| 88 |
+
font-size: 1.1rem;
|
| 89 |
+
font-weight: 600;
|
| 90 |
+
cursor: pointer;
|
| 91 |
+
transition: all 0.3s ease;
|
| 92 |
+
text-decoration: none;
|
| 93 |
+
display: inline-flex;
|
| 94 |
+
align-items: center;
|
| 95 |
+
gap: 0.5rem;
|
| 96 |
+
}
|
| 97 |
+
|
| 98 |
+
.btn-primary {
|
| 99 |
+
background: linear-gradient(45deg, #ff6b6b, #feca57);
|
| 100 |
+
color: white;
|
| 101 |
+
box-shadow: 0 10px 30px rgba(255,107,107,0.3);
|
| 102 |
+
}
|
| 103 |
+
|
| 104 |
+
.btn-primary:hover {
|
| 105 |
+
transform: translateY(-3px);
|
| 106 |
+
box-shadow: 0 15px 40px rgba(255,107,107,0.4);
|
| 107 |
+
}
|
| 108 |
+
|
| 109 |
+
.btn-secondary {
|
| 110 |
+
background: rgba(255,255,255,0.1);
|
| 111 |
+
color: white;
|
| 112 |
+
border: 2px solid rgba(255,255,255,0.3);
|
| 113 |
+
backdrop-filter: blur(10px);
|
| 114 |
+
}
|
| 115 |
+
|
| 116 |
+
.btn-secondary:hover {
|
| 117 |
+
background: rgba(255,255,255,0.2);
|
| 118 |
+
transform: translateY(-3px);
|
| 119 |
+
}
|
| 120 |
+
|
| 121 |
+
/* Navigation */
|
| 122 |
+
.navbar {
|
| 123 |
+
position: fixed;
|
| 124 |
+
top: 0;
|
| 125 |
+
width: 100%;
|
| 126 |
+
background: rgba(255,255,255,0.1);
|
| 127 |
+
backdrop-filter: blur(20px);
|
| 128 |
+
z-index: 1000;
|
| 129 |
+
padding: 1rem 0;
|
| 130 |
+
transition: all 0.3s ease;
|
| 131 |
+
}
|
| 132 |
+
|
| 133 |
+
.nav-container {
|
| 134 |
+
max-width: 1200px;
|
| 135 |
+
margin: 0 auto;
|
| 136 |
+
display: flex;
|
| 137 |
+
justify-content: space-between;
|
| 138 |
+
align-items: center;
|
| 139 |
+
padding: 0 2rem;
|
| 140 |
+
}
|
| 141 |
+
|
| 142 |
+
.logo {
|
| 143 |
+
font-size: 1.5rem;
|
| 144 |
+
font-weight: 700;
|
| 145 |
+
color: white;
|
| 146 |
+
}
|
| 147 |
+
|
| 148 |
+
.nav-links {
|
| 149 |
+
display: flex;
|
| 150 |
+
list-style: none;
|
| 151 |
+
gap: 2rem;
|
| 152 |
+
}
|
| 153 |
+
|
| 154 |
+
.nav-links a {
|
| 155 |
+
color: white;
|
| 156 |
+
text-decoration: none;
|
| 157 |
+
font-weight: 500;
|
| 158 |
+
transition: color 0.3s ease;
|
| 159 |
+
}
|
| 160 |
+
|
| 161 |
+
.nav-links a:hover {
|
| 162 |
+
color: #feca57;
|
| 163 |
+
}
|
| 164 |
+
|
| 165 |
+
/* Demo Section */
|
| 166 |
+
.demo-section {
|
| 167 |
+
padding: 5rem 0;
|
| 168 |
+
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
|
| 169 |
+
}
|
| 170 |
+
|
| 171 |
+
.container {
|
| 172 |
+
max-width: 1200px;
|
| 173 |
+
margin: 0 auto;
|
| 174 |
+
padding: 0 2rem;
|
| 175 |
+
}
|
| 176 |
+
|
| 177 |
+
.section-title {
|
| 178 |
+
text-align: center;
|
| 179 |
+
font-size: 3rem;
|
| 180 |
+
font-weight: 700;
|
| 181 |
+
margin-bottom: 3rem;
|
| 182 |
+
background: linear-gradient(45deg, #667eea, #764ba2);
|
| 183 |
+
-webkit-background-clip: text;
|
| 184 |
+
-webkit-text-fill-color: transparent;
|
| 185 |
+
background-clip: text;
|
| 186 |
+
}
|
| 187 |
+
|
| 188 |
+
.demo-container {
|
| 189 |
+
display: grid;
|
| 190 |
+
grid-template-columns: 1fr 1fr;
|
| 191 |
+
gap: 3rem;
|
| 192 |
+
align-items: start;
|
| 193 |
+
}
|
| 194 |
+
|
| 195 |
+
.upload-area {
|
| 196 |
+
background: white;
|
| 197 |
+
border-radius: 20px;
|
| 198 |
+
padding: 3rem;
|
| 199 |
+
box-shadow: 0 20px 60px rgba(0,0,0,0.1);
|
| 200 |
+
text-align: center;
|
| 201 |
+
border: 3px dashed #ddd;
|
| 202 |
+
transition: all 0.3s ease;
|
| 203 |
+
position: relative;
|
| 204 |
+
overflow: hidden;
|
| 205 |
+
}
|
| 206 |
+
|
| 207 |
+
.upload-area:hover {
|
| 208 |
+
border-color: #667eea;
|
| 209 |
+
transform: translateY(-5px);
|
| 210 |
+
box-shadow: 0 25px 80px rgba(0,0,0,0.15);
|
| 211 |
+
}
|
| 212 |
+
|
| 213 |
+
.upload-area::before {
|
| 214 |
+
content: '';
|
| 215 |
+
position: absolute;
|
| 216 |
+
top: 0;
|
| 217 |
+
left: -100%;
|
| 218 |
+
width: 100%;
|
| 219 |
+
height: 100%;
|
| 220 |
+
background: linear-gradient(90deg, transparent, rgba(102,126,234,0.1), transparent);
|
| 221 |
+
transition: left 0.5s;
|
| 222 |
+
}
|
| 223 |
+
|
| 224 |
+
.upload-area:hover::before {
|
| 225 |
+
left: 100%;
|
| 226 |
+
}
|
| 227 |
+
|
| 228 |
+
.upload-icon {
|
| 229 |
+
font-size: 4rem;
|
| 230 |
+
color: #667eea;
|
| 231 |
+
margin-bottom: 1rem;
|
| 232 |
+
}
|
| 233 |
+
|
| 234 |
+
.results-panel {
|
| 235 |
+
background: white;
|
| 236 |
+
border-radius: 20px;
|
| 237 |
+
padding: 2rem;
|
| 238 |
+
box-shadow: 0 20px 60px rgba(0,0,0,0.1);
|
| 239 |
+
min-height: 400px;
|
| 240 |
+
}
|
| 241 |
+
|
| 242 |
+
.tabs {
|
| 243 |
+
display: flex;
|
| 244 |
+
border-bottom: 2px solid #f0f0f0;
|
| 245 |
+
margin-bottom: 2rem;
|
| 246 |
+
}
|
| 247 |
+
|
| 248 |
+
.tab {
|
| 249 |
+
padding: 1rem 2rem;
|
| 250 |
+
cursor: pointer;
|
| 251 |
+
font-weight: 600;
|
| 252 |
+
color: #666;
|
| 253 |
+
border-bottom: 3px solid transparent;
|
| 254 |
+
transition: all 0.3s ease;
|
| 255 |
+
}
|
| 256 |
+
|
| 257 |
+
.tab.active {
|
| 258 |
+
color: #667eea;
|
| 259 |
+
border-color: #667eea;
|
| 260 |
+
}
|
| 261 |
+
|
| 262 |
+
.tab-content {
|
| 263 |
+
display: none;
|
| 264 |
+
}
|
| 265 |
+
|
| 266 |
+
.tab-content.active {
|
| 267 |
+
display: block;
|
| 268 |
+
animation: fadeIn 0.5s ease;
|
| 269 |
+
}
|
| 270 |
+
|
| 271 |
+
@keyframes fadeIn {
|
| 272 |
+
from { opacity: 0; transform: translateY(20px); }
|
| 273 |
+
to { opacity: 1; transform: translateY(0); }
|
| 274 |
+
}
|
| 275 |
+
|
| 276 |
+
/* Features Section */
|
| 277 |
+
.features-section {
|
| 278 |
+
padding: 5rem 0;
|
| 279 |
+
background: #fff;
|
| 280 |
+
}
|
| 281 |
+
|
| 282 |
+
.features-grid {
|
| 283 |
+
display: grid;
|
| 284 |
+
grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
|
| 285 |
+
gap: 2rem;
|
| 286 |
+
margin-top: 3rem;
|
| 287 |
+
}
|
| 288 |
+
|
| 289 |
+
.feature-card {
|
| 290 |
+
background: linear-gradient(135deg, #667eea, #764ba2);
|
| 291 |
+
border-radius: 20px;
|
| 292 |
+
padding: 2.5rem;
|
| 293 |
+
color: white;
|
| 294 |
+
position: relative;
|
| 295 |
+
overflow: hidden;
|
| 296 |
+
transition: transform 0.3s ease;
|
| 297 |
+
}
|
| 298 |
+
|
| 299 |
+
.feature-card:hover {
|
| 300 |
+
transform: translateY(-10px) scale(1.02);
|
| 301 |
+
}
|
| 302 |
+
|
| 303 |
+
.feature-card::before {
|
| 304 |
+
content: '';
|
| 305 |
+
position: absolute;
|
| 306 |
+
top: 0;
|
| 307 |
+
right: -50%;
|
| 308 |
+
width: 100%;
|
| 309 |
+
height: 100%;
|
| 310 |
+
background: rgba(255,255,255,0.1);
|
| 311 |
+
transform: skewX(-15deg);
|
| 312 |
+
transition: right 0.5s ease;
|
| 313 |
+
}
|
| 314 |
+
|
| 315 |
+
.feature-card:hover::before {
|
| 316 |
+
right: 100%;
|
| 317 |
+
}
|
| 318 |
+
|
| 319 |
+
.feature-icon {
|
| 320 |
+
font-size: 3rem;
|
| 321 |
+
margin-bottom: 1rem;
|
| 322 |
+
display: block;
|
| 323 |
+
}
|
| 324 |
+
|
| 325 |
+
.feature-card h3 {
|
| 326 |
+
font-size: 1.5rem;
|
| 327 |
+
margin-bottom: 1rem;
|
| 328 |
+
}
|
| 329 |
+
|
| 330 |
+
/* Architecture Section */
|
| 331 |
+
.architecture-section {
|
| 332 |
+
padding: 5rem 0;
|
| 333 |
+
background: linear-gradient(135deg, #1e3c72 0%, #2a5298 100%);
|
| 334 |
+
color: white;
|
| 335 |
+
}
|
| 336 |
+
|
| 337 |
+
.architecture-viz {
|
| 338 |
+
background: rgba(255,255,255,0.1);
|
| 339 |
+
border-radius: 20px;
|
| 340 |
+
padding: 3rem;
|
| 341 |
+
margin-top: 3rem;
|
| 342 |
+
backdrop-filter: blur(10px);
|
| 343 |
+
border: 1px solid rgba(255,255,255,0.2);
|
| 344 |
+
}
|
| 345 |
+
|
| 346 |
+
.network-diagram {
|
| 347 |
+
display: flex;
|
| 348 |
+
justify-content: space-between;
|
| 349 |
+
align-items: center;
|
| 350 |
+
margin: 2rem 0;
|
| 351 |
+
flex-wrap: wrap;
|
| 352 |
+
gap: 2rem;
|
| 353 |
+
}
|
| 354 |
+
|
| 355 |
+
.network-node {
|
| 356 |
+
background: rgba(255,255,255,0.2);
|
| 357 |
+
border-radius: 15px;
|
| 358 |
+
padding: 1.5rem;
|
| 359 |
+
text-align: center;
|
| 360 |
+
backdrop-filter: blur(5px);
|
| 361 |
+
border: 1px solid rgba(255,255,255,0.3);
|
| 362 |
+
transition: all 0.3s ease;
|
| 363 |
+
cursor: pointer;
|
| 364 |
+
min-width: 150px;
|
| 365 |
+
}
|
| 366 |
+
|
| 367 |
+
.network-node:hover {
|
| 368 |
+
background: rgba(255,255,255,0.3);
|
| 369 |
+
transform: scale(1.05);
|
| 370 |
+
}
|
| 371 |
+
|
| 372 |
+
.arrow {
|
| 373 |
+
font-size: 2rem;
|
| 374 |
+
color: #feca57;
|
| 375 |
+
}
|
| 376 |
+
|
| 377 |
+
/* Metrics Section */
|
| 378 |
+
.metrics-section {
|
| 379 |
+
padding: 5rem 0;
|
| 380 |
+
background: #f8f9fa;
|
| 381 |
+
}
|
| 382 |
+
|
| 383 |
+
.metrics-grid {
|
| 384 |
+
display: grid;
|
| 385 |
+
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
| 386 |
+
gap: 2rem;
|
| 387 |
+
margin-top: 3rem;
|
| 388 |
+
}
|
| 389 |
+
|
| 390 |
+
.metric-card {
|
| 391 |
+
background: white;
|
| 392 |
+
border-radius: 15px;
|
| 393 |
+
padding: 2rem;
|
| 394 |
+
text-align: center;
|
| 395 |
+
box-shadow: 0 10px 30px rgba(0,0,0,0.1);
|
| 396 |
+
transition: transform 0.3s ease;
|
| 397 |
+
}
|
| 398 |
+
|
| 399 |
+
.metric-card:hover {
|
| 400 |
+
transform: translateY(-5px);
|
| 401 |
+
}
|
| 402 |
+
|
| 403 |
+
.metric-value {
|
| 404 |
+
font-size: 3rem;
|
| 405 |
+
font-weight: 700;
|
| 406 |
+
color: #667eea;
|
| 407 |
+
margin-bottom: 0.5rem;
|
| 408 |
+
}
|
| 409 |
+
|
| 410 |
+
.metric-label {
|
| 411 |
+
color: #666;
|
| 412 |
+
font-weight: 600;
|
| 413 |
+
}
|
| 414 |
+
|
| 415 |
+
/* Research Section */
|
| 416 |
+
.research-section {
|
| 417 |
+
padding: 5rem 0;
|
| 418 |
+
background: linear-gradient(135deg, #2c3e50 0%, #34495e 100%);
|
| 419 |
+
color: white;
|
| 420 |
+
}
|
| 421 |
+
|
| 422 |
+
.research-grid {
|
| 423 |
+
display: grid;
|
| 424 |
+
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
| 425 |
+
gap: 2rem;
|
| 426 |
+
margin-top: 3rem;
|
| 427 |
+
}
|
| 428 |
+
|
| 429 |
+
.research-card {
|
| 430 |
+
background: rgba(255,255,255,0.1);
|
| 431 |
+
border-radius: 15px;
|
| 432 |
+
padding: 2rem;
|
| 433 |
+
backdrop-filter: blur(10px);
|
| 434 |
+
border: 1px solid rgba(255,255,255,0.2);
|
| 435 |
+
transition: all 0.3s ease;
|
| 436 |
+
}
|
| 437 |
+
|
| 438 |
+
.research-card:hover {
|
| 439 |
+
background: rgba(255,255,255,0.2);
|
| 440 |
+
transform: translateY(-5px);
|
| 441 |
+
}
|
| 442 |
+
|
| 443 |
+
/* Footer */
|
| 444 |
+
.footer {
|
| 445 |
+
background: #1a1a1a;
|
| 446 |
+
color: white;
|
| 447 |
+
padding: 3rem 0;
|
| 448 |
+
text-align: center;
|
| 449 |
+
}
|
| 450 |
+
|
| 451 |
+
.footer-content {
|
| 452 |
+
display: grid;
|
| 453 |
+
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
| 454 |
+
gap: 2rem;
|
| 455 |
+
margin-bottom: 2rem;
|
| 456 |
+
}
|
| 457 |
+
|
| 458 |
+
.footer-section h3 {
|
| 459 |
+
margin-bottom: 1rem;
|
| 460 |
+
color: #feca57;
|
| 461 |
+
}
|
| 462 |
+
|
| 463 |
+
.social-links {
|
| 464 |
+
display: flex;
|
| 465 |
+
justify-content: center;
|
| 466 |
+
gap: 1rem;
|
| 467 |
+
margin-top: 2rem;
|
| 468 |
+
}
|
| 469 |
+
|
| 470 |
+
.social-link {
|
| 471 |
+
display: inline-flex;
|
| 472 |
+
align-items: center;
|
| 473 |
+
justify-content: center;
|
| 474 |
+
width: 50px;
|
| 475 |
+
height: 50px;
|
| 476 |
+
background: linear-gradient(45deg, #667eea, #764ba2);
|
| 477 |
+
border-radius: 50%;
|
| 478 |
+
color: white;
|
| 479 |
+
text-decoration: none;
|
| 480 |
+
font-size: 1.5rem;
|
| 481 |
+
transition: transform 0.3s ease;
|
| 482 |
+
}
|
| 483 |
+
|
| 484 |
+
.social-link:hover {
|
| 485 |
+
transform: scale(1.1) rotate(360deg);
|
| 486 |
+
}
|
| 487 |
+
|
| 488 |
+
/* Responsive Design */
|
| 489 |
+
@media (max-width: 768px) {
|
| 490 |
+
.hero h1 {
|
| 491 |
+
font-size: 2.5rem;
|
| 492 |
+
}
|
| 493 |
+
|
| 494 |
+
.demo-container {
|
| 495 |
+
grid-template-columns: 1fr;
|
| 496 |
+
}
|
| 497 |
+
|
| 498 |
+
.nav-links {
|
| 499 |
+
display: none;
|
| 500 |
+
}
|
| 501 |
+
|
| 502 |
+
.features-grid {
|
| 503 |
+
grid-template-columns: 1fr;
|
| 504 |
+
}
|
| 505 |
+
|
| 506 |
+
.network-diagram {
|
| 507 |
+
flex-direction: column;
|
| 508 |
+
}
|
| 509 |
+
|
| 510 |
+
.arrow {
|
| 511 |
+
transform: rotate(90deg);
|
| 512 |
+
}
|
| 513 |
+
}
|
| 514 |
+
|
| 515 |
+
/* Animations */
|
| 516 |
+
@keyframes pulse {
|
| 517 |
+
0%, 100% { transform: scale(1); }
|
| 518 |
+
50% { transform: scale(1.05); }
|
| 519 |
+
}
|
| 520 |
+
|
| 521 |
+
.pulse {
|
| 522 |
+
animation: pulse 2s infinite;
|
| 523 |
+
}
|
| 524 |
+
|
| 525 |
+
/* Processing Animation */
|
| 526 |
+
.processing {
|
| 527 |
+
display: inline-block;
|
| 528 |
+
width: 40px;
|
| 529 |
+
height: 40px;
|
| 530 |
+
border: 4px solid #f3f3f3;
|
| 531 |
+
border-top: 4px solid #667eea;
|
| 532 |
+
border-radius: 50%;
|
| 533 |
+
animation: spin 1s linear infinite;
|
| 534 |
+
}
|
| 535 |
+
|
| 536 |
+
@keyframes spin {
|
| 537 |
+
0% { transform: rotate(0deg); }
|
| 538 |
+
100% { transform: rotate(360deg); }
|
| 539 |
+
}
|
| 540 |
+
|
| 541 |
+
/* Progress Bar */
|
| 542 |
+
.progress-bar {
|
| 543 |
+
width: 100%;
|
| 544 |
+
height: 8px;
|
| 545 |
+
background: #f0f0f0;
|
| 546 |
+
border-radius: 4px;
|
| 547 |
+
overflow: hidden;
|
| 548 |
+
margin: 1rem 0;
|
| 549 |
+
}
|
| 550 |
+
|
| 551 |
+
.progress-fill {
|
| 552 |
+
height: 100%;
|
| 553 |
+
background: linear-gradient(45deg, #667eea, #764ba2);
|
| 554 |
+
width: 0%;
|
| 555 |
+
transition: width 0.3s ease;
|
| 556 |
+
border-radius: 4px;
|
| 557 |
+
}
|
| 558 |
+
|
| 559 |
+
/* --- NEW: Custom Styles for Flask Integration to blend with existing design --- */
|
| 560 |
+
/* These styles override/add to existing ones to make the Flask form look like part of the UI */
|
| 561 |
+
.flask-form-container {
|
| 562 |
+
background: white; /* Match demo-container's background */
|
| 563 |
+
border-radius: 20px; /* Match demo-container's border-radius */
|
| 564 |
+
padding: 3rem; /* Match demo-container's padding */
|
| 565 |
+
box-shadow: 0 20px 60px rgba(0,0,0,0.1); /* Match demo-container's shadow */
|
| 566 |
+
text-align: center;
|
| 567 |
+
border: 3px dashed #ddd; /* Match upload-area's dashed border */
|
| 568 |
+
transition: all 0.3s ease;
|
| 569 |
+
position: relative;
|
| 570 |
+
overflow: hidden;
|
| 571 |
+
}
|
| 572 |
+
/* Match hover effects of original upload-area */
|
| 573 |
+
.flask-form-container:hover {
|
| 574 |
+
border-color: #667eea;
|
| 575 |
+
transform: translateY(-5px);
|
| 576 |
+
box-shadow: 0 25px 80px rgba(0,0,0,0.15);
|
| 577 |
+
}
|
| 578 |
+
.flask-form-container::before {
|
| 579 |
+
content: '';
|
| 580 |
+
position: absolute;
|
| 581 |
+
top: 0;
|
| 582 |
+
left: -100%;
|
| 583 |
+
width: 100%;
|
| 584 |
+
height: 100%;
|
| 585 |
+
background: linear-gradient(90deg, transparent, rgba(102,126,234,0.1), transparent);
|
| 586 |
+
transition: left 0.5s;
|
| 587 |
+
}
|
| 588 |
+
.flask-form-container:hover::before {
|
| 589 |
+
left: 100%;
|
| 590 |
+
}
|
| 591 |
+
|
| 592 |
+
.flask-form-container h3 {
|
| 593 |
+
font-size: 1.8rem; /* Consistent heading size */
|
| 594 |
+
color: #333; /* Darker text for contrast */
|
| 595 |
+
margin-bottom: 1.5rem;
|
| 596 |
+
}
|
| 597 |
+
|
| 598 |
+
.flask-file-input {
|
| 599 |
+
display: block; /* Ensure it takes full width */
|
| 600 |
+
width: 100%;
|
| 601 |
+
padding: 0.8rem;
|
| 602 |
+
border: 1px solid #ddd;
|
| 603 |
+
border-radius: 5px;
|
| 604 |
+
margin-bottom: 1.5rem;
|
| 605 |
+
font-size: 1rem;
|
| 606 |
+
cursor: pointer;
|
| 607 |
+
background-color: #fff; /* White background */
|
| 608 |
+
}
|
| 609 |
+
/* Style the file input button (browser-specific styling) */
|
| 610 |
+
.flask-file-input::file-selector-button {
|
| 611 |
+
background-color: #667eea;
|
| 612 |
+
color: white;
|
| 613 |
+
border: none;
|
| 614 |
+
padding: 0.5rem 1rem;
|
| 615 |
+
border-radius: 5px;
|
| 616 |
+
cursor: pointer;
|
| 617 |
+
margin-right: 1rem;
|
| 618 |
+
transition: background-color 0.3s ease;
|
| 619 |
+
}
|
| 620 |
+
.flask-file-input::file-selector-button:hover {
|
| 621 |
+
background-color: #5567d4;
|
| 622 |
+
}
|
| 623 |
+
|
| 624 |
+
.flask-submit-btn {
|
| 625 |
+
/* Using btn-primary styles for consistency */
|
| 626 |
+
padding: 1rem 2rem;
|
| 627 |
+
border: none;
|
| 628 |
+
border-radius: 50px;
|
| 629 |
+
font-size: 1.1rem;
|
| 630 |
+
font-weight: 600;
|
| 631 |
+
cursor: pointer;
|
| 632 |
+
transition: all 0.3s ease;
|
| 633 |
+
text-decoration: none;
|
| 634 |
+
display: inline-flex;
|
| 635 |
+
align-items: center;
|
| 636 |
+
gap: 0.5rem;
|
| 637 |
+
background: linear-gradient(45deg, #ff6b6b, #feca57);
|
| 638 |
+
color: white;
|
| 639 |
+
box-shadow: 0 10px 30px rgba(255,107,107,0.3);
|
| 640 |
+
}
|
| 641 |
+
.flask-submit-btn:hover {
|
| 642 |
+
transform: translateY(-3px);
|
| 643 |
+
box-shadow: 0 15px 40px rgba(255,107,107,0.4);
|
| 644 |
+
}
|
| 645 |
+
|
| 646 |
+
.flask-result-box {
|
| 647 |
+
background: #f8f9fa; /* Light background for results */
|
| 648 |
+
padding: 1.5rem;
|
| 649 |
+
border-radius: 10px;
|
| 650 |
+
border-left: 4px solid #667eea; /* Accent border */
|
| 651 |
+
margin-top: 2rem;
|
| 652 |
+
text-align: left; /* Align text to left for readability */
|
| 653 |
+
box-shadow: 0 5px 15px rgba(0,0,0,0.05);
|
| 654 |
+
}
|
| 655 |
+
|
| 656 |
+
.flask-result-box h3 {
|
| 657 |
+
font-size: 1.6rem;
|
| 658 |
+
color: #667eea;
|
| 659 |
+
margin-bottom: 1rem;
|
| 660 |
+
text-align: center; /* Center heading for results */
|
| 661 |
+
}
|
| 662 |
+
|
| 663 |
+
.flask-result-box p {
|
| 664 |
+
font-size: 1.1rem;
|
| 665 |
+
color: #333;
|
| 666 |
+
line-height: 1.5;
|
| 667 |
+
word-wrap: break-word; /* Ensure long captions wrap */
|
| 668 |
+
}
|
| 669 |
+
|
| 670 |
+
.flask-uploaded-image {
|
| 671 |
+
max-width: 100%;
|
| 672 |
+
height: auto;
|
| 673 |
+
border-radius: 10px;
|
| 674 |
+
margin-top: 1.5rem;
|
| 675 |
+
margin-bottom: 1.5rem;
|
| 676 |
+
box-shadow: 0 4px 8px rgba(0,0,0,0.1);
|
| 677 |
+
}
|
| 678 |
+
|
| 679 |
+
/* Flash Messages */
|
| 680 |
+
.flash-message {
|
| 681 |
+
padding: 0.75rem 1.25rem;
|
| 682 |
+
margin-bottom: 1rem;
|
| 683 |
+
border: 1px solid transparent;
|
| 684 |
+
border-radius: 0.375rem;
|
| 685 |
+
font-weight: 500;
|
| 686 |
+
text-align: center;
|
| 687 |
+
}
|
| 688 |
+
.flash-success {
|
| 689 |
+
background-color: #d1e7dd; /* Light green */
|
| 690 |
+
color: #0f5132; /* Dark green */
|
| 691 |
+
border-color: #badbcc;
|
| 692 |
+
}
|
| 693 |
+
.flash-error {
|
| 694 |
+
background-color: #f8d7da; /* Light red */
|
| 695 |
+
color: #721c24; /* Dark red */
|
| 696 |
+
border-color: #f5c2c7;
|
| 697 |
+
}
|
| 698 |
+
|
| 699 |
+
/* Video Captioning Section (New) */
|
| 700 |
+
.video-captioning-section {
|
| 701 |
+
padding: 5rem 0;
|
| 702 |
+
background: linear-gradient(135deg, #e0f2f7 0%, #a7d9eb 100%); /* Light blue gradient */
|
| 703 |
+
text-align: center;
|
| 704 |
+
margin-top: 3rem; /* Space from previous section */
|
| 705 |
+
border-radius: 20px;
|
| 706 |
+
box-shadow: 0 20px 60px rgba(0,0,0,0.1);
|
| 707 |
+
}
|
| 708 |
+
.video-captioning-section h2 {
|
| 709 |
+
font-size: 3rem;
|
| 710 |
+
font-weight: 700;
|
| 711 |
+
margin-bottom: 1rem;
|
| 712 |
+
color: #1e3c72; /* Dark blue from your architecture section */
|
| 713 |
+
}
|
| 714 |
+
.video-captioning-section p {
|
| 715 |
+
font-size: 1.2rem;
|
| 716 |
+
color: #333;
|
| 717 |
+
margin-bottom: 2rem;
|
| 718 |
+
max-width: 800px;
|
| 719 |
+
margin-left: auto;
|
| 720 |
+
margin-right: auto;
|
| 721 |
+
}
|
| 722 |
+
.video-cta-btn {
|
| 723 |
+
/* Using btn-primary styles for consistency */
|
| 724 |
+
padding: 1rem 2.5rem;
|
| 725 |
+
border: none;
|
| 726 |
+
border-radius: 50px;
|
| 727 |
+
font-size: 1.1rem;
|
| 728 |
+
font-weight: 600;
|
| 729 |
+
cursor: pointer;
|
| 730 |
+
transition: all 0.3s ease;
|
| 731 |
+
text-decoration: none;
|
| 732 |
+
display: inline-flex;
|
| 733 |
+
align-items: center;
|
| 734 |
+
gap: 0.5rem;
|
| 735 |
+
background: linear-gradient(45deg, #2196F3, #667eea); /* Blue gradient */
|
| 736 |
+
color: white;
|
| 737 |
+
box-shadow: 0 10px 30px rgba(33,150,243,0.3);
|
| 738 |
+
}
|
| 739 |
+
.video-cta-btn:hover {
|
| 740 |
+
transform: translateY(-3px);
|
| 741 |
+
box-shadow: 0 15px 40px rgba(33,150,243,0.4);
|
| 742 |
+
}
|
| 743 |
+
|
| 744 |
+
</style>
|
| 745 |
+
<!-- FontAwesome for icons -->
|
| 746 |
+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">
|
| 747 |
+
</head>
|
| 748 |
+
<body>
|
| 749 |
+
<!-- Navigation -->
|
| 750 |
+
<nav class="navbar">
|
| 751 |
+
<div class="nav-container">
|
| 752 |
+
<div class="logo">VisionCraft AI</div>
|
| 753 |
+
<ul class="nav-links">
|
| 754 |
+
<li><a href="#demo">Live Demo</a></li>
|
| 755 |
+
<li><a href="#features">Features</a></li>
|
| 756 |
+
<li><a href="#architecture">Architecture</a></li>
|
| 757 |
+
<li><a href="#metrics">Performance</a></li>
|
| 758 |
+
<li><a href="#research">Research</a></li>
|
| 759 |
+
</ul>
|
| 760 |
+
</div>
|
| 761 |
+
</nav>
|
| 762 |
+
|
| 763 |
+
<!-- Hero Section -->
|
| 764 |
+
<section class="hero">
|
| 765 |
+
<div class="hero-content">
|
| 766 |
+
<h1>VisionCraft AI</h1>
|
| 767 |
+
<p>Revolutionary Image Captioning & Segmentation built from scratch using custom neural architectures. No pretrained models, pure innovation.</p>
|
| 768 |
+
<div class="cta-buttons">
|
| 769 |
+
<a href="#demo" class="btn btn-primary">
|
| 770 |
+
🚀 Try Live Demo
|
| 771 |
+
</a>
|
| 772 |
+
<a href="#architecture" class="btn btn-secondary">
|
| 773 |
+
🧠 Explore Architecture
|
| 774 |
+
</a>
|
| 775 |
+
</div>
|
| 776 |
+
</div>
|
| 777 |
+
</section>
|
| 778 |
+
|
| 779 |
+
<!-- Demo Section (Image Captioning & Segmentation) -->
|
| 780 |
+
<section id="demo" class="demo-section">
|
| 781 |
+
<div class="container">
|
| 782 |
+
<h2 class="section-title">Interactive AI Demo</h2>
|
| 783 |
+
<div class="demo-container">
|
| 784 |
+
<!-- Flask Image Captioning Form -->
|
| 785 |
+
<div class="upload-area flask-form-container">
|
| 786 |
+
<h3>Upload Your Image for Captioning</h3>
|
| 787 |
+
<p>Drag & drop an image or click to browse</p>
|
| 788 |
+
|
| 789 |
+
<!-- Flash Messages -->
|
| 790 |
+
{% with messages = get_flashed_messages(with_categories=true) %}
|
| 791 |
+
{% if messages %}
|
| 792 |
+
<div class="mb-4">
|
| 793 |
+
{% for category, message in messages %}
|
| 794 |
+
<div class="flash-message flash-{{ category }}">
|
| 795 |
+
{{ message }}
|
| 796 |
+
</div>
|
| 797 |
+
{% endfor %}
|
| 798 |
+
</div>
|
| 799 |
+
{% endif %}
|
| 800 |
+
{% endwith %}
|
| 801 |
+
|
| 802 |
+
<form action="/predict" method="post" enctype="multipart/form-data">
|
| 803 |
+
<input id="imageInput" name="file" type="file" accept="image/*" required class="flask-file-input">
|
| 804 |
+
<p style="font-size: 0.9em; color: #777; margin-top: 0.5rem; margin-bottom: 1rem;">PNG, JPG, JPEG, GIF formats allowed.</p>
|
| 805 |
+
<button type="submit" class="flask-submit-btn">
|
| 806 |
+
Generate Caption
|
| 807 |
+
</button>
|
| 808 |
+
</form>
|
| 809 |
+
</div>
|
| 810 |
+
|
| 811 |
+
<!-- Results Panel -->
|
| 812 |
+
<div class="results-panel">
|
| 813 |
+
<div class="tabs">
|
| 814 |
+
<div class="tab active" data-tab="caption">📝 Caption</div>
|
| 815 |
+
<div class="tab" data-tab="segment">🎯 Segmentation</div>
|
| 816 |
+
<div class="tab" data-tab="analysis">📊 Analysis</div>
|
| 817 |
+
</div>
|
| 818 |
+
|
| 819 |
+
<div class="tab-content active" id="caption">
|
| 820 |
+
<h3>Generated Caption</h3>
|
| 821 |
+
<div id="captionResult">
|
| 822 |
+
{% if caption %}
|
| 823 |
+
<div class="flask-result-box">
|
| 824 |
+
<h3>Your Uploaded Image:</h3>
|
| 825 |
+
{% if uploaded_image_url %}
|
| 826 |
+
<img src="{{ uploaded_image_url }}" alt="Uploaded Image" class="flask-uploaded-image">
|
| 827 |
+
{% endif %}
|
| 828 |
+
<h3>Generated Caption:</h3>
|
| 829 |
+
<p>"{{ caption }}"</p>
|
| 830 |
+
<!-- Placeholder for confidence score if you integrate it later from Flask -->
|
| 831 |
+
<!-- <div style="margin-top: 1rem; text-align: center;">Confidence: XX.X%</div> -->
|
| 832 |
+
</div>
|
| 833 |
+
{% else %}
|
| 834 |
+
<p style="color: #666; font-style: italic;">Upload an image to see the AI-generated caption...</p>
|
| 835 |
+
{% endif %}
|
| 836 |
+
</div>
|
| 837 |
+
<div id="confidenceScore" style="margin-top: 1rem;"></div>
|
| 838 |
+
</div>
|
| 839 |
+
|
| 840 |
+
<div class="tab-content" id="segment">
|
| 841 |
+
<h3>Segmentation Results (Partner's Work)</h3>
|
| 842 |
+
<div id="segmentResult">
|
| 843 |
+
<p style="color: #666; font-style: italic;">Segmentation masks will appear here once integrated.</p>
|
| 844 |
+
<div style="text-align: center; margin-top: 1rem;">
|
| 845 |
+
<img src="https://placehold.co/400x250/cccccc/333333?text=Segmentation+Preview" alt="Segmentation Placeholder" class="flask-uploaded-image">
|
| 846 |
+
<p style="margin-top: 0.5rem; font-size: 0.9em; color: #777;">Placeholder image until live segmentation is ready.</p>
|
| 847 |
+
</div>
|
| 848 |
+
</div>
|
| 849 |
+
</div>
|
| 850 |
+
|
| 851 |
+
<div class="tab-content" id="analysis">
|
| 852 |
+
<h3>Technical Analysis</h3>
|
| 853 |
+
<div id="analysisResult">
|
| 854 |
+
<p style="color: #666; font-style: italic;">Detailed analysis coming soon from backend...</p>
|
| 855 |
+
</div>
|
| 856 |
+
</div>
|
| 857 |
+
</div>
|
| 858 |
+
</div>
|
| 859 |
+
</div>
|
| 860 |
+
</section>
|
| 861 |
+
|
| 862 |
+
<!-- NEW: Video Captioning Section -->
|
| 863 |
+
<section id="video-captioning" class="video-captioning-section">
|
| 864 |
+
<div class="container">
|
| 865 |
+
<h2 class="section-title">Real-time Video Captioning</h2>
|
| 866 |
+
<p>Experience live descriptions of video streams, providing instant understanding of dynamic scenes. Click the button below to explore our dedicated video captioning demo.</p>
|
| 867 |
+
<a href="#" class="video-cta-btn" onclick="alert('Video captioning feature will be integrated soon!')">
|
| 868 |
+
Go to Video Captioning 🎥
|
| 869 |
+
</a>
|
| 870 |
+
</div>
|
| 871 |
+
</section>
|
| 872 |
+
<!-- END NEW: Video Captioning Section -->
|
| 873 |
+
|
| 874 |
+
<!-- Features Section (Existing) -->
|
| 875 |
+
<section id="features" class="features-section">
|
| 876 |
+
<div class="container">
|
| 877 |
+
<h2 class="section-title">Exceptional Features</h2>
|
| 878 |
+
<div class="features-grid">
|
| 879 |
+
<div class="feature-card">
|
| 880 |
+
<span class="feature-icon">🧠</span>
|
| 881 |
+
<h3>Custom Neural Architecture</h3>
|
| 882 |
+
<p>Built entirely from scratch without any pretrained models. Custom CNN+LSTM for captioning and U-Net variant for segmentation.</p>
|
| 883 |
+
</div>
|
| 884 |
+
|
| 885 |
+
<div class="feature-card">
|
| 886 |
+
<span class="feature-icon">⚡</span>
|
| 887 |
+
<h3>Real-time Processing</h3>
|
| 888 |
+
<p>Optimized inference pipeline capable of processing images in under 2 seconds with efficient memory management.</p>
|
| 889 |
+
</div>
|
| 890 |
+
|
| 891 |
+
<div class="feature-card">
|
| 892 |
+
<span class="feature-icon">🎯</span>
|
| 893 |
+
<h3>Dual Task Mastery</h3>
|
| 894 |
+
<p>Seamlessly integrated captioning and segmentation with shared feature extraction for enhanced performance.</p>
|
| 895 |
+
</div>
|
| 896 |
+
|
| 897 |
+
<div class="feature-card">
|
| 898 |
+
<span class="feature-icon">📊</span>
|
| 899 |
+
<h3>Advanced Analytics</h3>
|
| 900 |
+
<p>Comprehensive performance metrics, attention visualization, and detailed error analysis capabilities.</p>
|
| 901 |
+
</div>
|
| 902 |
+
|
| 903 |
+
<div class="feature-card">
|
| 904 |
+
<span class="feature-icon">🔧</span>
|
| 905 |
+
<h3>Interactive Tools</h3>
|
| 906 |
+
<p>Web-based interface with real-time processing, batch operations, and detailed result visualization.</p>
|
| 907 |
+
</div>
|
| 908 |
+
|
| 909 |
+
<div class="feature-card">
|
| 910 |
+
<span class="feature-icon">🚀</span>
|
| 911 |
+
<h3>Production Ready</h3>
|
| 912 |
+
<p>Dockerized deployment, REST API, comprehensive testing, and scalable cloud infrastructure.</p>
|
| 913 |
+
</div>
|
| 914 |
+
</div>
|
| 915 |
+
</div>
|
| 916 |
+
</section>
|
| 917 |
+
|
| 918 |
+
<!-- Architecture Section -->
|
| 919 |
+
<section id="architecture" class="architecture-section">
|
| 920 |
+
<div class="container">
|
| 921 |
+
<h2 class="section-title">Custom Architecture</h2>
|
| 922 |
+
<div class="architecture-viz">
|
| 923 |
+
<h3>Neural Network Flow</h3>
|
| 924 |
+
<div class="network-diagram">
|
| 925 |
+
<div class="network-node" data-info="Custom CNN feature extractor with attention mechanism">
|
| 926 |
+
<h4>Feature Extraction</h4>
|
| 927 |
+
<p>Custom CNN</p>
|
| 928 |
+
</div>
|
| 929 |
+
<div class="arrow">→</div>
|
| 930 |
+
<div class="network-node" data-info="Shared feature maps for both tasks">
|
| 931 |
+
<h4>Shared Features</h4>
|
| 932 |
+
<p>Multi-scale</p>
|
| 933 |
+
</div>
|
| 934 |
+
<div class="arrow">→</div>
|
| 935 |
+
<div class="network-node" data-info="LSTM with attention for caption generation">
|
| 936 |
+
<h4>Caption Branch</h4>
|
| 937 |
+
<p>LSTM + Attention</p>
|
| 938 |
+
</div>
|
| 939 |
+
</div>
|
| 940 |
+
|
| 941 |
+
<div class="network-diagram">
|
| 942 |
+
<div class="network-node" data-info="U-Net inspired architecture for segmentation">
|
| 943 |
+
<h4>Segmentation Branch</h4>
|
| 944 |
+
<p>Custom U-Net</p>
|
| 945 |
+
</div>
|
| 946 |
+
<div class="arrow">→</div>
|
| 947 |
+
<div class="network-node" data-info="Multi-task loss function optimization">
|
| 948 |
+
<h4>Loss Integration</h4>
|
| 949 |
+
<p>Multi-task Loss</p>
|
| 950 |
+
</div>
|
| 951 |
+
<div class="arrow">→</div>
|
| 952 |
+
<div class="network-node" data-info="Final output processing and confidence scoring">
|
| 953 |
+
<h4>Output Processing</h4>
|
| 954 |
+
<p>Post-processing</p>
|
| 955 |
+
</div>
|
| 956 |
+
</div>
|
| 957 |
+
|
| 958 |
+
<div style="text-align: center; margin-top: 2rem;">
|
| 959 |
+
<button class="btn btn-primary" onclick="showArchitectureDetails()">
|
| 960 |
+
🔍 Explore 3D Architecture
|
| 961 |
+
</button>
|
| 962 |
+
</div>
|
| 963 |
+
</div>
|
| 964 |
+
</div>
|
| 965 |
+
</section>
|
| 966 |
+
|
| 967 |
+
<!-- Metrics Section -->
|
| 968 |
+
<section id="metrics" class="metrics-section">
|
| 969 |
+
<div class="container">
|
| 970 |
+
<h2 class="section-title">Performance Metrics</h2>
|
| 971 |
+
<div class="metrics-grid">
|
| 972 |
+
<div class="metric-card">
|
| 973 |
+
<div class="metric-value" id="bleuScore">78.4</div>
|
| 974 |
+
<div class="metric-label">BLEU-4 Score</div>
|
| 975 |
+
</div>
|
| 976 |
+
|
| 977 |
+
<div class="metric-card">
|
| 978 |
+
<div class="metric-value" id="miouScore">82.1</div>
|
| 979 |
+
<div class="metric-label">mIoU Score (%)</div>
|
| 980 |
+
</div>
|
| 981 |
+
|
| 982 |
+
<div class="metric-card">
|
| 983 |
+
<div class="metric-value" id="inferenceTime">1.8</div>
|
| 984 |
+
<div class="metric-label">Inference Time (s)</div>
|
| 985 |
+
</div>
|
| 986 |
+
|
| 987 |
+
<div class="metric-card">
|
| 988 |
+
<div class="metric-value" id="modelSize">45.2</div>
|
| 989 |
+
<div class="metric-label">Model Size (MB)</div>
|
| 990 |
+
</div>
|
| 991 |
+
|
| 992 |
+
<div class="metric-card">
|
| 993 |
+
<div class="metric-value" id="accuracy">85.7</div>
|
| 994 |
+
<div class="metric-label">Overall Accuracy (%)</div>
|
| 995 |
+
</div>
|
| 996 |
+
|
| 997 |
+
<div class="metric-card">
|
| 998 |
+
<div class="metric-value" id="fps">12</div>
|
| 999 |
+
<div class="metric-label">Processing FPS</div>
|
| 1000 |
+
</div>
|
| 1001 |
+
</div>
|
| 1002 |
+
</div>
|
| 1003 |
+
</section>
|
| 1004 |
+
|
| 1005 |
+
<!-- Research Section -->
|
| 1006 |
+
<section id="research" class="research-section">
|
| 1007 |
+
<div class="container">
|
| 1008 |
+
<h2 class="section-title">Research & Innovation</h2>
|
| 1009 |
+
<div class="research-grid">
|
| 1010 |
+
<div class="research-card">
|
| 1011 |
+
<h3>📚 Technical Documentation</h3>
|
| 1012 |
+
<p>Complete research paper with mathematical formulations, architecture details, and experimental results.</p>
|
| 1013 |
+
<button class="btn btn-primary" style="margin-top: 1rem;">Read Paper</button>
|
| 1014 |
+
</div>
|
| 1015 |
+
|
| 1016 |
+
<div class="research-card">
|
| 1017 |
+
<h3>🔬 Ablation Studies</h3>
|
| 1018 |
+
<p>Comprehensive analysis of different architectural choices and their impact on model performance.</p>
|
| 1019 |
+
<button class="btn btn-primary" style="margin-top: 1rem;">View Studies</button>
|
| 1020 |
+
</div>
|
| 1021 |
+
|
| 1022 |
+
<div class="research-card">
|
| 1023 |
+
<h3>💻 Code Repository</h3>
|
| 1024 |
+
<p>Open-source implementation with detailed comments, training scripts, and deployment guides.</p>
|
| 1025 |
+
<button class="btn btn-primary" style="margin-top: 1rem;">GitHub Repo</button>
|
| 1026 |
+
</div>
|
| 1027 |
+
|
| 1028 |
+
<div class="research-card">
|
| 1029 |
+
<h3>📊 Training Insights</h3>
|
| 1030 |
+
<p>Interactive dashboard showing training progress, loss curves, and hyperparameter optimization results.</p>
|
| 1031 |
+
<button class="btn btn-primary" style="margin-top: 1rem;">Training Dashboard</button>
|
| 1032 |
+
</div>
|
| 1033 |
+
</div>
|
| 1034 |
+
</div>
|
| 1035 |
+
</section>
|
| 1036 |
+
|
| 1037 |
+
<!-- Footer -->
|
| 1038 |
+
<footer class="footer">
|
| 1039 |
+
<div class="container">
|
| 1040 |
+
<div class="footer-content">
|
| 1041 |
+
<div class="footer-section">
|
| 1042 |
+
<h3>VisionCraft AI</h3>
|
| 1043 |
+
<p>Revolutionary computer vision solutions built from scratch.</p>
|
| 1044 |
+
</div>
|
| 1045 |
+
|
| 1046 |
+
<div class="footer-section">
|
| 1047 |
+
<h3>Quick Links</h3>
|
| 1048 |
+
<p><a href="#demo" style="color: #ccc; text-decoration: none;">Live Demo</a></p>
|
| 1049 |
+
<p><a href="#architecture" style="color: #ccc; text-decoration: none;">Architecture</a></p>
|
| 1050 |
+
<p><a href="#research" style="color: #ccc; text-decoration: none;">Research</a></p>
|
| 1051 |
+
</div>
|
| 1052 |
+
|
| 1053 |
+
<div class="footer-section">
|
| 1054 |
+
<h3>Developer</h3>
|
| 1055 |
+
<p>Built with passion during internship at Zidio Development</p>
|
| 1056 |
+
<p>Contact: your.email@example.com</p>
|
| 1057 |
+
</div>
|
| 1058 |
+
</div>
|
| 1059 |
+
|
| 1060 |
+
<div class="social-links">
|
| 1061 |
+
<a href="#" class="social-link">📧</a>
|
| 1062 |
+
<a href="#" class="social-link">💼</a>
|
| 1063 |
+
<a href="#" class="social-link">🐙</a>
|
| 1064 |
+
<a href="#" class="social-link">🐦</a>
|
| 1065 |
+
</div>
|
| 1066 |
+
|
| 1067 |
+
<p style="margin-top: 2rem; padding-top: 2rem; border-top: 1px solid #333; color: #ccc;">
|
| 1068 |
+
© 2024 VisionCraft AI. Built with ❤️ for innovation.
|
| 1069 |
+
</p>
|
| 1070 |
+
</div>
|
| 1071 |
+
</footer>
|
| 1072 |
+
|
| 1073 |
+
<script>
|
| 1074 |
+
// Tab functionality (Existing, Modified to clear for Flask output)
|
| 1075 |
+
document.querySelectorAll('.tab').forEach(tab => {
|
| 1076 |
+
tab.addEventListener('click', function() {
|
| 1077 |
+
// Remove active class from all tabs and contents
|
| 1078 |
+
document.querySelectorAll('.tab').forEach(t => t.classList.remove('active'));
|
| 1079 |
+
document.querySelectorAll('.tab-content').forEach(c => c.classList.remove('active'));
|
| 1080 |
+
|
| 1081 |
+
// Add active class to clicked tab
|
| 1082 |
+
this.classList.add('active');
|
| 1083 |
+
|
| 1084 |
+
// Show corresponding content
|
| 1085 |
+
const tabId = this.getAttribute('data-tab');
|
| 1086 |
+
document.getElementById(tabId).classList.add('active');
|
| 1087 |
+
|
| 1088 |
+
// Clear previous results when switching tabs, except for the Flask-driven caption tab
|
| 1089 |
+
if (tabId !== 'caption') {
|
| 1090 |
+
// Reset segmentation and analysis tabs if they were showing old data
|
| 1091 |
+
document.getElementById('segmentResult').innerHTML = '<p style="color: #666; font-style: italic;">Segmentation masks will appear here once integrated.</p><div style="text-align: center; margin-top: 1rem;"><img src="https://placehold.co/400x250/cccccc/333333?text=Segmentation+Preview" alt="Segmentation Placeholder" class="flask-uploaded-image"><p style="margin-top: 0.5rem; font-size: 0.9em; color: #777;">Placeholder image until live segmentation is ready.</p></div>';
|
| 1092 |
+
document.getElementById('analysisResult').innerHTML = '<p style="color: #666; font-style: italic;">Detailed analysis coming soon from backend...</p>';
|
| 1093 |
+
}
|
| 1094 |
+
});
|
| 1095 |
+
});
|
| 1096 |
+
|
| 1097 |
+
// The original JavaScript for file upload simulation (processImage, showResults, drag/drop)
|
| 1098 |
+
// is REMOVED as Flask handles the actual file upload and rendering.
|
| 1099 |
+
// The HTML form now directly submits to Flask.
|
| 1100 |
+
|
| 1101 |
+
// Smooth scrolling for navigation links (Existing)
|
| 1102 |
+
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
|
| 1103 |
+
anchor.addEventListener('click', function (e) {
|
| 1104 |
+
e.preventDefault();
|
| 1105 |
+
const target = document.querySelector(this.getAttribute('href'));
|
| 1106 |
+
if (target) {
|
| 1107 |
+
target.scrollIntoView({
|
| 1108 |
+
behavior: 'smooth',
|
| 1109 |
+
block: 'start'
|
| 1110 |
+
});
|
| 1111 |
+
}
|
| 1112 |
+
});
|
| 1113 |
+
});
|
| 1114 |
+
|
| 1115 |
+
// Navbar scroll effect (Existing)
|
| 1116 |
+
window.addEventListener('scroll', function() {
|
| 1117 |
+
const navbar = document.querySelector('.navbar');
|
| 1118 |
+
if (window.scrollY > 100) {
|
| 1119 |
+
navbar.style.background = 'rgba(0,0,0,0.9)';
|
| 1120 |
+
} else {
|
| 1121 |
+
navbar.style.background = 'rgba(255,255,255,0.1)';
|
| 1122 |
+
}
|
| 1123 |
+
});
|
| 1124 |
+
|
| 1125 |
+
// Animate metrics when in view (Existing)
|
| 1126 |
+
function animateMetrics() {
|
| 1127 |
+
const metrics = document.querySelectorAll('.metric-value');
|
| 1128 |
+
const observer = new IntersectionObserver((entries) => {
|
| 1129 |
+
entries.forEach(entry => {
|
| 1130 |
+
if (entry.isIntersecting) {
|
| 1131 |
+
const target = entry.target;
|
| 1132 |
+
const finalValue = parseFloat(target.textContent);
|
| 1133 |
+
let currentValue = 0;
|
| 1134 |
+
const increment = finalValue / 50;
|
| 1135 |
+
|
| 1136 |
+
const timer = setInterval(() => {
|
| 1137 |
+
currentValue += increment;
|
| 1138 |
+
if (currentValue >= finalValue) {
|
| 1139 |
+
currentValue = finalValue;
|
| 1140 |
+
clearInterval(timer);
|
| 1141 |
+
}
|
| 1142 |
+
target.textContent = currentValue.toFixed(1);
|
| 1143 |
+
}, 30);
|
| 1144 |
+
|
| 1145 |
+
observer.unobserve(target);
|
| 1146 |
+
}
|
| 1147 |
+
});
|
| 1148 |
+
});
|
| 1149 |
+
|
| 1150 |
+
metrics.forEach(metric => observer.observe(metric));
|
| 1151 |
+
}
|
| 1152 |
+
|
| 1153 |
+
// Architecture details modal (Existing)
|
| 1154 |
+
function showArchitectureDetails() {
|
| 1155 |
+
const modal = document.createElement('div');
|
| 1156 |
+
modal.style.cssText = `
|
| 1157 |
+
position: fixed;
|
| 1158 |
+
top: 0;
|
| 1159 |
+
left: 0;
|
| 1160 |
+
width: 100%;
|
| 1161 |
+
height: 100%;
|
| 1162 |
+
background: rgba(0,0,0,0.8);
|
| 1163 |
+
display: flex;
|
| 1164 |
+
align-items: center;
|
| 1165 |
+
justify-content: center;
|
| 1166 |
+
z-index: 9999;
|
| 1167 |
+
backdrop-filter: blur(10px);
|
| 1168 |
+
`;
|
| 1169 |
+
|
| 1170 |
+
modal.innerHTML = `
|
| 1171 |
+
<div style="background: white; border-radius: 20px; padding: 3rem; max-width: 800px; max-height: 80vh; overflow-y: auto; position: relative;">
|
| 1172 |
+
<button onclick="this.closest('.modal').remove()" style="position: absolute; top: 1rem; right: 1rem; border: none; background: none; font-size: 2rem; cursor: pointer; color: #666;">×</button>
|
| 1173 |
+
|
| 1174 |
+
<h2 style="color: #667eea; margin-bottom: 2rem; text-align: center;">3D Architecture Visualization</h2>
|
| 1175 |
+
|
| 1176 |
+
<div style="text-align: center; margin-bottom: 2rem;">
|
| 1177 |
+
<div style="width: 300px; height: 200px; background: linear-gradient(45deg, #667eea, #764ba2); border-radius: 15px; margin: 0 auto; display: flex; align-items: center; justify-content: center; color: white; font-size: 1.2rem; transform-style: preserve-3d; animation: rotate3d 4s infinite linear;">
|
| 1178 |
+
🧠 Neural Network<br>3D Visualization
|
| 1179 |
+
</div>
|
| 1180 |
+
</div>
|
| 1181 |
+
|
| 1182 |
+
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 2rem; margin-top: 2rem;">
|
| 1183 |
+
<div>
|
| 1184 |
+
<h3 style="color: #667eea;">Caption Branch</h3>
|
| 1185 |
+
<ul style="padding-left: 1.5rem; color: #666;">
|
| 1186 |
+
<li>CNN Feature Extractor (5 layers)</li>
|
| 1187 |
+
<li>Attention Mechanism</li>
|
| 1188 |
+
<li>LSTM Decoder (2 layers)</li>
|
| 1189 |
+
<li>Vocabulary: 10,000 words</li>
|
| 1190 |
+
</ul>
|
| 1191 |
+
</div>
|
| 1192 |
+
<div>
|
| 1193 |
+
<h3 style="color: #667eea;">Segmentation Branch</h3>
|
| 1194 |
+
<ul style="padding-left: 1.5rem; color: #666;">
|
| 1195 |
+
<li>U-Net Architecture</li>
|
| 1196 |
+
<li>Skip Connections</li>
|
| 1197 |
+
<li>Multi-scale Features</li>
|
| 1198 |
+
<li>21 Object Classes</li>
|
| 1199 |
+
</ul>
|
| 1200 |
+
</div>
|
| 1201 |
+
</div>
|
| 1202 |
+
|
| 1203 |
+
<div style="background: #f8f9fa; padding: 2rem; border-radius: 10px; margin-top: 2rem;">
|
| 1204 |
+
<h3 style="color: #667eea; margin-bottom: 1rem;">Key Innovations</h3>
|
| 1205 |
+
<p style="color: #666; line-height: 1.8;">
|
| 1206 |
+
Our custom architecture implements shared feature extraction with dual-head processing,
|
| 1207 |
+
attention-based caption generation, and efficient multi-task learning with weighted loss optimization.
|
| 1208 |
+
</p>
|
| 1209 |
+
</div>
|
| 1210 |
+
</div>
|
| 1211 |
+
`;
|
| 1212 |
+
|
| 1213 |
+
modal.className = 'modal';
|
| 1214 |
+
document.body.appendChild(modal);
|
| 1215 |
+
|
| 1216 |
+
// Add rotation animation
|
| 1217 |
+
const style = document.createElement('style');
|
| 1218 |
+
style.textContent = `
|
| 1219 |
+
@keyframes rotate3d {
|
| 1220 |
+
0% { transform: rotateY(0deg) rotateX(10deg); }
|
| 1221 |
+
100% { transform: rotateY(360deg) rotateX(10deg); }
|
| 1222 |
+
}
|
| 1223 |
+
`;
|
| 1224 |
+
document.head.appendChild(style);
|
| 1225 |
+
}
|
| 1226 |
+
|
| 1227 |
+
// Network node hover effects (Existing)
|
| 1228 |
+
document.querySelectorAll('.network-node').forEach(node => {
|
| 1229 |
+
node.addEventListener('mouseenter', function() {
|
| 1230 |
+
const info = this.getAttribute('data-info');
|
| 1231 |
+
if (info) {
|
| 1232 |
+
const tooltip = document.createElement('div');
|
| 1233 |
+
tooltip.style.cssText = `
|
| 1234 |
+
position: absolute;
|
| 1235 |
+
background: rgba(0,0,0,0.9);
|
| 1236 |
+
color: white;
|
| 1237 |
+
padding: 1rem;
|
| 1238 |
+
border-radius: 8px;
|
| 1239 |
+
font-size: 0.9rem;
|
| 1240 |
+
max-width: 200px;
|
| 1241 |
+
z-index: 1000;
|
| 1242 |
+
top: -60px;
|
| 1243 |
+
left: 50%;
|
| 1244 |
+
transform: translateX(-50%);
|
| 1245 |
+
pointer-events: none;
|
| 1246 |
+
`;
|
| 1247 |
+
tooltip.textContent = info;
|
| 1248 |
+
tooltip.className = 'tooltip';
|
| 1249 |
+
this.style.position = 'relative';
|
| 1250 |
+
this.appendChild(tooltip);
|
| 1251 |
+
}
|
| 1252 |
+
});
|
| 1253 |
+
|
| 1254 |
+
node.addEventListener('mouseleave', function() {
|
| 1255 |
+
const tooltip = this.querySelector('.tooltip');
|
| 1256 |
+
if (tooltip) {
|
| 1257 |
+
tooltip.remove();
|
| 1258 |
+
}
|
| 1259 |
+
});
|
| 1260 |
+
});
|
| 1261 |
+
|
| 1262 |
+
// Initialize animations (Existing)
|
| 1263 |
+
document.addEventListener('DOMContentLoaded', function() {
|
| 1264 |
+
animateMetrics();
|
| 1265 |
+
|
| 1266 |
+
// Add pulse animation to CTA buttons
|
| 1267 |
+
document.querySelectorAll('.btn-primary').forEach(btn => {
|
| 1268 |
+
setInterval(() => {
|
| 1269 |
+
btn.classList.add('pulse');
|
| 1270 |
+
setTimeout(() => btn.classList.remove('pulse'), 1000);
|
| 1271 |
+
}, 5000);
|
| 1272 |
+
});
|
| 1273 |
+
});
|
| 1274 |
+
|
| 1275 |
+
// Add particle animation to hero section (Existing)
|
| 1276 |
+
function createParticles() {
|
| 1277 |
+
const hero = document.querySelector('.hero');
|
| 1278 |
+
for (let i = 0; i < 50; i++) {
|
| 1279 |
+
const particle = document.createElement('div');
|
| 1280 |
+
particle.style.cssText = `
|
| 1281 |
+
position: absolute;
|
| 1282 |
+
width: 2px;
|
| 1283 |
+
height: 2px;
|
| 1284 |
+
background: rgba(255,255,255,0.5);
|
| 1285 |
+
border-radius: 50%;
|
| 1286 |
+
left: ${Math.random() * 100}%;
|
| 1287 |
+
top: ${Math.random() * 100}%;
|
| 1288 |
+
animation: float ${5 + Math.random() * 10}s infinite linear;
|
| 1289 |
+
pointer-events: none;
|
| 1290 |
+
`;
|
| 1291 |
+
hero.appendChild(particle);
|
| 1292 |
+
}
|
| 1293 |
+
}
|
| 1294 |
+
|
| 1295 |
+
// Initialize particle animation (Existing)
|
| 1296 |
+
createParticles();
|
| 1297 |
+
|
| 1298 |
+
// Add typing effect to hero text (Existing)
|
| 1299 |
+
function typeWriter(element, text, speed = 50) {
|
| 1300 |
+
let i = 0;
|
| 1301 |
+
element.innerHTML = '';
|
| 1302 |
+
function typing() {
|
| 1303 |
+
if (i < text.length) {
|
| 1304 |
+
element.innerHTML += text.charAt(i);
|
| 1305 |
+
i++;
|
| 1306 |
+
setTimeout(typing, speed);
|
| 1307 |
+
}
|
| 1308 |
+
}
|
| 1309 |
+
typing();
|
| 1310 |
+
}
|
| 1311 |
+
|
| 1312 |
+
// Mobile menu toggle (if needed) (Existing)
|
| 1313 |
+
function toggleMobileMenu() {
|
| 1314 |
+
const navLinks = document.querySelector('.nav-links');
|
| 1315 |
+
navLinks.classList.toggle('active');
|
| 1316 |
+
}
|
| 1317 |
+
|
| 1318 |
+
// Add mobile styles (already in your original HTML, moved to style tag) (Existing)
|
| 1319 |
+
const mobileStyles = document.createElement('style');
|
| 1320 |
+
mobileStyles.textContent = `
|
| 1321 |
+
@media (max-width: 768px) {
|
| 1322 |
+
.nav-links.active {
|
| 1323 |
+
display: flex;
|
| 1324 |
+
flex-direction: column;
|
| 1325 |
+
position: absolute;
|
| 1326 |
+
top: 100%;
|
| 1327 |
+
left: 0;
|
| 1328 |
+
width: 100%;
|
| 1329 |
+
background: rgba(0,0,0,0.9);
|
| 1330 |
+
padding: 2rem;
|
| 1331 |
+
backdrop-filter: blur(20px);
|
| 1332 |
+
}
|
| 1333 |
+
|
| 1334 |
+
.nav-links.active a {
|
| 1335 |
+
padding: 1rem 0;
|
| 1336 |
+
border-bottom: 1px solid rgba(255,255,255,0.1);
|
| 1337 |
+
}
|
| 1338 |
+
}
|
| 1339 |
+
`;
|
| 1340 |
+
document.head.appendChild(mobileStyles);
|
| 1341 |
+
</script>
|
| 1342 |
+
</body>
|
| 1343 |
+
</html>
|
templates/index.html
ADDED
|
@@ -0,0 +1,1766 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html lang="en">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="UTF-8">
|
| 5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
+
<title>Perceptra AI: Intelligent Vision. Secure Insights. Real-time Understanding.</title>
|
| 7 |
+
<style>
|
| 8 |
+
/* Global Reset and Base Styles */
|
| 9 |
+
* {
|
| 10 |
+
margin: 0;
|
| 11 |
+
padding: 0;
|
| 12 |
+
box-sizing: border-box;
|
| 13 |
+
}
|
| 14 |
+
|
| 15 |
+
body {
|
| 16 |
+
font-family: 'Inter', 'Segoe UI', system-ui, -apple-system, sans-serif;
|
| 17 |
+
line-height: 1.6;
|
| 18 |
+
color: #E5E7EB;
|
| 19 |
+
overflow-x: hidden;
|
| 20 |
+
background: #0B1121;
|
| 21 |
+
font-weight: 400;
|
| 22 |
+
letter-spacing: -0.01em;
|
| 23 |
+
}
|
| 24 |
+
|
| 25 |
+
/* Hero Section */
|
| 26 |
+
.hero {
|
| 27 |
+
height: 100vh;
|
| 28 |
+
background: linear-gradient(135deg, #0B1121 0%, #1E293B 50%, #334155 100%);
|
| 29 |
+
display: flex;
|
| 30 |
+
align-items: center;
|
| 31 |
+
justify-content: center;
|
| 32 |
+
position: relative;
|
| 33 |
+
overflow: hidden;
|
| 34 |
+
}
|
| 35 |
+
|
| 36 |
+
.hero::before {
|
| 37 |
+
content: '';
|
| 38 |
+
position: absolute;
|
| 39 |
+
top: 0;
|
| 40 |
+
left: 0;
|
| 41 |
+
right: 0;
|
| 42 |
+
bottom: 0;
|
| 43 |
+
background: radial-gradient(circle at 20% 80%, rgba(59, 130, 246, 0.1) 0%, transparent 50%),
|
| 44 |
+
radial-gradient(circle at 80% 20%, rgba(99, 102, 241, 0.1) 0%, transparent 50%);
|
| 45 |
+
pointer-events: none;
|
| 46 |
+
}
|
| 47 |
+
|
| 48 |
+
.hero-content {
|
| 49 |
+
text-align: center;
|
| 50 |
+
z-index: 2;
|
| 51 |
+
position: relative;
|
| 52 |
+
max-width: 1000px;
|
| 53 |
+
padding: 0 2rem;
|
| 54 |
+
}
|
| 55 |
+
|
| 56 |
+
.hero h1 {
|
| 57 |
+
font-size: clamp(2.5rem, 5vw, 4.5rem);
|
| 58 |
+
font-weight: 700;
|
| 59 |
+
margin-bottom: 1.5rem;
|
| 60 |
+
color: #FFFFFF;
|
| 61 |
+
line-height: 1.1;
|
| 62 |
+
letter-spacing: -0.02em;
|
| 63 |
+
}
|
| 64 |
+
|
| 65 |
+
.hero p {
|
| 66 |
+
font-size: clamp(1.1rem, 2vw, 1.3rem);
|
| 67 |
+
color: #94A3B8;
|
| 68 |
+
margin-bottom: 3rem;
|
| 69 |
+
max-width: 700px;
|
| 70 |
+
margin-left: auto;
|
| 71 |
+
margin-right: auto;
|
| 72 |
+
font-weight: 400;
|
| 73 |
+
line-height: 1.7;
|
| 74 |
+
}
|
| 75 |
+
|
| 76 |
+
.cta-buttons {
|
| 77 |
+
display: flex;
|
| 78 |
+
gap: 1.5rem;
|
| 79 |
+
justify-content: center;
|
| 80 |
+
flex-wrap: wrap;
|
| 81 |
+
}
|
| 82 |
+
|
| 83 |
+
.btn {
|
| 84 |
+
padding: 1rem 2rem;
|
| 85 |
+
border: none;
|
| 86 |
+
border-radius: 8px;
|
| 87 |
+
font-size: 1rem;
|
| 88 |
+
font-weight: 600;
|
| 89 |
+
cursor: pointer;
|
| 90 |
+
transition: all 0.2s ease;
|
| 91 |
+
text-decoration: none;
|
| 92 |
+
display: inline-flex;
|
| 93 |
+
align-items: center;
|
| 94 |
+
gap: 0.5rem;
|
| 95 |
+
font-family: inherit;
|
| 96 |
+
letter-spacing: -0.01em;
|
| 97 |
+
}
|
| 98 |
+
|
| 99 |
+
.btn-primary {
|
| 100 |
+
background: #3B82F6;
|
| 101 |
+
color: #FFFFFF;
|
| 102 |
+
box-shadow: 0 4px 14px 0 rgba(59, 130, 246, 0.25);
|
| 103 |
+
}
|
| 104 |
+
|
| 105 |
+
.btn-primary:hover {
|
| 106 |
+
background: #2563EB;
|
| 107 |
+
transform: translateY(-1px);
|
| 108 |
+
box-shadow: 0 6px 20px 0 rgba(59, 130, 246, 0.35);
|
| 109 |
+
}
|
| 110 |
+
|
| 111 |
+
.btn-secondary {
|
| 112 |
+
background: transparent;
|
| 113 |
+
color: #E5E7EB;
|
| 114 |
+
border: 1px solid #374151;
|
| 115 |
+
}
|
| 116 |
+
|
| 117 |
+
.btn-secondary:hover {
|
| 118 |
+
background: #374151;
|
| 119 |
+
border-color: #4B5563;
|
| 120 |
+
transform: translateY(-1px);
|
| 121 |
+
}
|
| 122 |
+
|
| 123 |
+
/* Navigation */
|
| 124 |
+
.navbar {
|
| 125 |
+
position: fixed;
|
| 126 |
+
top: 0;
|
| 127 |
+
width: 100%;
|
| 128 |
+
background: rgba(11, 17, 33, 0.8);
|
| 129 |
+
backdrop-filter: blur(20px);
|
| 130 |
+
z-index: 1000;
|
| 131 |
+
padding: 1rem 0;
|
| 132 |
+
border-bottom: 1px solid rgba(255, 255, 255, 0.08);
|
| 133 |
+
}
|
| 134 |
+
|
| 135 |
+
.nav-container {
|
| 136 |
+
max-width: 1200px;
|
| 137 |
+
margin: 0 auto;
|
| 138 |
+
display: flex;
|
| 139 |
+
justify-content: space-between;
|
| 140 |
+
align-items: center;
|
| 141 |
+
padding: 0 2rem;
|
| 142 |
+
}
|
| 143 |
+
|
| 144 |
+
.logo {
|
| 145 |
+
font-size: 1.5rem;
|
| 146 |
+
font-weight: 700;
|
| 147 |
+
color: #FFFFFF;
|
| 148 |
+
letter-spacing: -0.02em;
|
| 149 |
+
}
|
| 150 |
+
|
| 151 |
+
.nav-links {
|
| 152 |
+
display: flex;
|
| 153 |
+
list-style: none;
|
| 154 |
+
gap: 2rem;
|
| 155 |
+
}
|
| 156 |
+
|
| 157 |
+
.nav-links a {
|
| 158 |
+
color: #94A3B8;
|
| 159 |
+
text-decoration: none;
|
| 160 |
+
font-weight: 500;
|
| 161 |
+
transition: color 0.2s ease;
|
| 162 |
+
font-size: 0.95rem;
|
| 163 |
+
}
|
| 164 |
+
|
| 165 |
+
.nav-links a:hover {
|
| 166 |
+
color: #FFFFFF;
|
| 167 |
+
}
|
| 168 |
+
|
| 169 |
+
/* Demo Section */
|
| 170 |
+
.demo-section, .features-section, .metrics-section, .research-section {
|
| 171 |
+
padding: 6rem 0;
|
| 172 |
+
background: #0B1121;
|
| 173 |
+
}
|
| 174 |
+
|
| 175 |
+
.container {
|
| 176 |
+
max-width: 1200px;
|
| 177 |
+
margin: 0 auto;
|
| 178 |
+
padding: 0 2rem;
|
| 179 |
+
}
|
| 180 |
+
|
| 181 |
+
.section-title {
|
| 182 |
+
text-align: center;
|
| 183 |
+
font-size: clamp(2rem, 4vw, 3rem);
|
| 184 |
+
font-weight: 700;
|
| 185 |
+
margin-bottom: 1rem;
|
| 186 |
+
color: #FFFFFF;
|
| 187 |
+
letter-spacing: -0.02em;
|
| 188 |
+
}
|
| 189 |
+
|
| 190 |
+
.section-subtitle {
|
| 191 |
+
text-align: center;
|
| 192 |
+
font-size: 1.1rem;
|
| 193 |
+
color: #94A3B8;
|
| 194 |
+
margin-bottom: 4rem;
|
| 195 |
+
max-width: 600px;
|
| 196 |
+
margin-left: auto;
|
| 197 |
+
margin-right: auto;
|
| 198 |
+
}
|
| 199 |
+
|
| 200 |
+
.demo-container {
|
| 201 |
+
display: grid;
|
| 202 |
+
grid-template-columns: 1fr 1fr;
|
| 203 |
+
gap: 3rem;
|
| 204 |
+
align-items: start;
|
| 205 |
+
}
|
| 206 |
+
|
| 207 |
+
/* Cards */
|
| 208 |
+
.upload-area.flask-form-container h3 {
|
| 209 |
+
color:#feca57;
|
| 210 |
+
}
|
| 211 |
+
|
| 212 |
+
.upload-area.flask-form-container, .results-panel, .feature-card, .metric-card, .research-card {
|
| 213 |
+
background: #1E293B;
|
| 214 |
+
border: 1px solid #334155;
|
| 215 |
+
border-radius: 12px;
|
| 216 |
+
padding: 2.5rem;
|
| 217 |
+
transition: all 0.2s ease;
|
| 218 |
+
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
| 219 |
+
}
|
| 220 |
+
|
| 221 |
+
/* .upload-area.flask-form-container:hover, .results-panel:hover, .feature-card:hover, .research-card:hover {
|
| 222 |
+
border-color: #475569;
|
| 223 |
+
transform: translateY(-2px);
|
| 224 |
+
box-shadow: 0 10px 25px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
|
| 225 |
+
} */
|
| 226 |
+
.upload-area.flask-form-container:hover, .results-panel:hover, .feature-card:hover, .research-card:hover {
|
| 227 |
+
transform: translateY(-7px); /* Consistent lift */
|
| 228 |
+
border-color: #3B82F6; /* Accent blue border */
|
| 229 |
+
box-shadow:
|
| 230 |
+
0 12px 30px -5px rgba(0, 0, 0, 0.2), /* Main lift shadow */
|
| 231 |
+
0 0 20px rgba(59, 130, 246, 0.4); /* Subtle blue glow */ /* NEW */
|
| 232 |
+
}
|
| 233 |
+
.flask-form-container h3, .results-panel h3 {
|
| 234 |
+
font-size: 1.5rem;
|
| 235 |
+
color: #FFFFFF;
|
| 236 |
+
margin-bottom: 1rem;
|
| 237 |
+
font-weight: 600;
|
| 238 |
+
text-align: center;
|
| 239 |
+
}
|
| 240 |
+
|
| 241 |
+
.flask-form-container p, .results-panel p {
|
| 242 |
+
color: #94A3B8;
|
| 243 |
+
text-align: center;
|
| 244 |
+
margin-bottom: 2rem;
|
| 245 |
+
}
|
| 246 |
+
|
| 247 |
+
.flask-file-input {
|
| 248 |
+
display: block;
|
| 249 |
+
width: 100%;
|
| 250 |
+
padding: 0.75rem;
|
| 251 |
+
border: 1px solid #374151;
|
| 252 |
+
border-radius: 8px;
|
| 253 |
+
margin-bottom: 1.5rem;
|
| 254 |
+
font-size: 1rem;
|
| 255 |
+
cursor: pointer;
|
| 256 |
+
background-color: #111827;
|
| 257 |
+
color: #E5E7EB;
|
| 258 |
+
transition: border-color 0.2s ease;
|
| 259 |
+
}
|
| 260 |
+
|
| 261 |
+
.flask-file-input:hover {
|
| 262 |
+
border-color: #4B5563;
|
| 263 |
+
}
|
| 264 |
+
|
| 265 |
+
.flask-file-input::file-selector-button {
|
| 266 |
+
background-color: #3B82F6;
|
| 267 |
+
color: #FFFFFF;
|
| 268 |
+
border: none;
|
| 269 |
+
padding: 0.5rem 1rem;
|
| 270 |
+
border-radius: 6px;
|
| 271 |
+
cursor: pointer;
|
| 272 |
+
margin-right: 1rem;
|
| 273 |
+
font-weight: 500;
|
| 274 |
+
transition: background-color 0.2s ease;
|
| 275 |
+
}
|
| 276 |
+
|
| 277 |
+
.flask-file-input::file-selector-button:hover {
|
| 278 |
+
background-color: #2563EB;
|
| 279 |
+
}
|
| 280 |
+
|
| 281 |
+
.flask-submit-btn {
|
| 282 |
+
width: 100%;
|
| 283 |
+
padding: 0.875rem 1.5rem;
|
| 284 |
+
border: none;
|
| 285 |
+
border-radius: 8px;
|
| 286 |
+
font-size: 1rem;
|
| 287 |
+
font-weight: 600;
|
| 288 |
+
cursor: pointer;
|
| 289 |
+
transition: all 0.2s ease;
|
| 290 |
+
background: #3B82F6;
|
| 291 |
+
color: #FFFFFF;
|
| 292 |
+
box-shadow: 0 4px 14px 0 rgba(59, 130, 246, 0.25);
|
| 293 |
+
}
|
| 294 |
+
|
| 295 |
+
.flask-submit-btn:hover {
|
| 296 |
+
background: #2563EB;
|
| 297 |
+
transform: translateY(-1px);
|
| 298 |
+
box-shadow: 0 6px 20px 0 rgba(59, 130, 246, 0.35);
|
| 299 |
+
}
|
| 300 |
+
|
| 301 |
+
.flask-result-box {
|
| 302 |
+
background: #111827;
|
| 303 |
+
padding: 1.5rem;
|
| 304 |
+
border-radius: 8px;
|
| 305 |
+
border-left: 4px solid #3B82F6;
|
| 306 |
+
margin-top: 2rem;
|
| 307 |
+
text-align: left;
|
| 308 |
+
}
|
| 309 |
+
|
| 310 |
+
.flask-result-box h3 {
|
| 311 |
+
font-size: 1.25rem;
|
| 312 |
+
color: #FFFFFF;
|
| 313 |
+
margin-bottom: 1rem;
|
| 314 |
+
text-align: center;
|
| 315 |
+
font-weight: 600;
|
| 316 |
+
}
|
| 317 |
+
|
| 318 |
+
.flask-result-box p {
|
| 319 |
+
font-size: 1rem;
|
| 320 |
+
color: #D1D5DB;
|
| 321 |
+
line-height: 1.6;
|
| 322 |
+
word-wrap: break-word;
|
| 323 |
+
}
|
| 324 |
+
|
| 325 |
+
.flask-uploaded-image {
|
| 326 |
+
max-width: 100%;
|
| 327 |
+
height: auto;
|
| 328 |
+
border-radius: 8px;
|
| 329 |
+
margin: 1.5rem 0;
|
| 330 |
+
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
|
| 331 |
+
}
|
| 332 |
+
|
| 333 |
+
/* Flash Messages */
|
| 334 |
+
.flash-message {
|
| 335 |
+
padding: 1rem 1.5rem;
|
| 336 |
+
margin-bottom: 1rem;
|
| 337 |
+
border-radius: 8px;
|
| 338 |
+
font-weight: 500;
|
| 339 |
+
text-align: center;
|
| 340 |
+
}
|
| 341 |
+
|
| 342 |
+
.flash-success {
|
| 343 |
+
background-color: rgba(34, 197, 94, 0.1);
|
| 344 |
+
color: #22C55E;
|
| 345 |
+
border: 1px solid rgba(34, 197, 94, 0.2);
|
| 346 |
+
}
|
| 347 |
+
|
| 348 |
+
.flash-error {
|
| 349 |
+
background-color: rgba(239, 68, 68, 0.1);
|
| 350 |
+
color: #EF4444;
|
| 351 |
+
border: 1px solid rgba(239, 68, 68, 0.2);
|
| 352 |
+
}
|
| 353 |
+
|
| 354 |
+
/* Tabs */
|
| 355 |
+
.tabs {
|
| 356 |
+
display: flex;
|
| 357 |
+
border-bottom: 1px solid #334155;
|
| 358 |
+
margin-bottom: 2rem;
|
| 359 |
+
}
|
| 360 |
+
|
| 361 |
+
.tab {
|
| 362 |
+
padding: 1rem 1.5rem;
|
| 363 |
+
cursor: pointer;
|
| 364 |
+
font-weight: 500;
|
| 365 |
+
color: #94A3B8;
|
| 366 |
+
border-bottom: 2px solid transparent;
|
| 367 |
+
transition: all 0.2s ease;
|
| 368 |
+
font-size: 0.95rem;
|
| 369 |
+
}
|
| 370 |
+
|
| 371 |
+
.tab.active {
|
| 372 |
+
color: #3B82F6;
|
| 373 |
+
border-color: #3B82F6;
|
| 374 |
+
}
|
| 375 |
+
|
| 376 |
+
.tab:hover:not(.active) {
|
| 377 |
+
color: #FFFFFF;
|
| 378 |
+
}
|
| 379 |
+
|
| 380 |
+
.tab-content {
|
| 381 |
+
display: none;
|
| 382 |
+
}
|
| 383 |
+
|
| 384 |
+
.tab-content.active {
|
| 385 |
+
display: block;
|
| 386 |
+
animation: fadeIn 0.3s ease;
|
| 387 |
+
}
|
| 388 |
+
|
| 389 |
+
@keyframes fadeIn {
|
| 390 |
+
from { opacity: 0; transform: translateY(10px); }
|
| 391 |
+
to { opacity: 1; transform: translateY(0); }
|
| 392 |
+
}
|
| 393 |
+
|
| 394 |
+
/* Video Captioning Section */
|
| 395 |
+
.video-captioning-section {
|
| 396 |
+
padding: 6rem 0;
|
| 397 |
+
background: linear-gradient(135deg, #1E293B 0%, #334155 100%);
|
| 398 |
+
text-align: center;
|
| 399 |
+
margin: 4rem 0;
|
| 400 |
+
border-radius: 16px;
|
| 401 |
+
}
|
| 402 |
+
|
| 403 |
+
.video-captioning-section h2 {
|
| 404 |
+
font-size: clamp(2rem, 4vw, 3rem);
|
| 405 |
+
font-weight: 700;
|
| 406 |
+
margin-bottom: 1rem;
|
| 407 |
+
color: #FFFFFF;
|
| 408 |
+
letter-spacing: -0.02em;
|
| 409 |
+
}
|
| 410 |
+
|
| 411 |
+
.video-captioning-section p {
|
| 412 |
+
font-size: 1.1rem;
|
| 413 |
+
color: #94A3B8;
|
| 414 |
+
margin-bottom: 2rem;
|
| 415 |
+
max-width: 600px;
|
| 416 |
+
margin-left: auto;
|
| 417 |
+
margin-right: auto;
|
| 418 |
+
line-height: 1.7;
|
| 419 |
+
}
|
| 420 |
+
|
| 421 |
+
.video-cta-btn {
|
| 422 |
+
padding: 1rem 2rem;
|
| 423 |
+
border: none;
|
| 424 |
+
border-radius: 8px;
|
| 425 |
+
font-size: 1rem;
|
| 426 |
+
font-weight: 600;
|
| 427 |
+
cursor: pointer;
|
| 428 |
+
transition: all 0.2s ease;
|
| 429 |
+
text-decoration: none;
|
| 430 |
+
display: inline-flex;
|
| 431 |
+
align-items: center;
|
| 432 |
+
gap: 0.5rem;
|
| 433 |
+
background: #3B82F6;
|
| 434 |
+
color: #FFFFFF;
|
| 435 |
+
box-shadow: 0 4px 14px 0 rgba(59, 130, 246, 0.25);
|
| 436 |
+
}
|
| 437 |
+
|
| 438 |
+
.video-cta-btn:hover {
|
| 439 |
+
background: #2563EB;
|
| 440 |
+
transform: translateY(-1px);
|
| 441 |
+
box-shadow: 0 6px 20px 0 rgba(59, 130, 246, 0.35);
|
| 442 |
+
}
|
| 443 |
+
|
| 444 |
+
/* Features Grid */
|
| 445 |
+
.features-grid {
|
| 446 |
+
display: grid;
|
| 447 |
+
grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
|
| 448 |
+
gap: 2rem;
|
| 449 |
+
margin-top: 3rem;
|
| 450 |
+
}
|
| 451 |
+
|
| 452 |
+
.feature-icon {
|
| 453 |
+
font-size: 2.5rem;
|
| 454 |
+
margin-bottom: 1.5rem;
|
| 455 |
+
display: block;
|
| 456 |
+
color: #3B82F6;
|
| 457 |
+
text-align: center;
|
| 458 |
+
}
|
| 459 |
+
|
| 460 |
+
.feature-card h3 {
|
| 461 |
+
font-size: 1.25rem;
|
| 462 |
+
color: #feca57;
|
| 463 |
+
margin-bottom: 1rem;
|
| 464 |
+
font-weight: 600;
|
| 465 |
+
text-align: center;
|
| 466 |
+
}
|
| 467 |
+
|
| 468 |
+
.feature-card p {
|
| 469 |
+
color: whitesmoke;
|
| 470 |
+
text-align: center;
|
| 471 |
+
line-height: 1.6;
|
| 472 |
+
}
|
| 473 |
+
|
| 474 |
+
/* Architecture Section */
|
| 475 |
+
.architecture-section {
|
| 476 |
+
padding: 6rem 0;
|
| 477 |
+
background: #111827;
|
| 478 |
+
}
|
| 479 |
+
|
| 480 |
+
.architecture-viz {
|
| 481 |
+
background: #1E293B;
|
| 482 |
+
border: 1px solid #334155;
|
| 483 |
+
border-radius: 12px;
|
| 484 |
+
padding: 3rem;
|
| 485 |
+
margin-top: 3rem;
|
| 486 |
+
}
|
| 487 |
+
|
| 488 |
+
.network-diagram-group {
|
| 489 |
+
margin-bottom: 3rem;
|
| 490 |
+
padding: 2rem;
|
| 491 |
+
border: 1px solid #374151;
|
| 492 |
+
border-radius: 12px;
|
| 493 |
+
background: #111827;
|
| 494 |
+
}
|
| 495 |
+
|
| 496 |
+
.network-diagram-group h4 {
|
| 497 |
+
color: #3B82F6;
|
| 498 |
+
margin-bottom: 2rem;
|
| 499 |
+
font-size: 1.5rem;
|
| 500 |
+
text-align: center;
|
| 501 |
+
font-weight: 600;
|
| 502 |
+
}
|
| 503 |
+
|
| 504 |
+
.network-diagram {
|
| 505 |
+
display: flex;
|
| 506 |
+
justify-content: space-between;
|
| 507 |
+
align-items: center;
|
| 508 |
+
margin: 1.5rem 0;
|
| 509 |
+
flex-wrap: wrap;
|
| 510 |
+
gap: 1.5rem;
|
| 511 |
+
}
|
| 512 |
+
|
| 513 |
+
.network-node {
|
| 514 |
+
background: #1E293B;
|
| 515 |
+
border: 1px solid #334155;
|
| 516 |
+
border-radius: 8px;
|
| 517 |
+
padding: 1.5rem;
|
| 518 |
+
text-align: center;
|
| 519 |
+
transition: all 0.2s ease;
|
| 520 |
+
cursor: pointer;
|
| 521 |
+
min-width: 150px;
|
| 522 |
+
flex-grow: 1;
|
| 523 |
+
}
|
| 524 |
+
|
| 525 |
+
.network-node:hover {
|
| 526 |
+
background: #334155;
|
| 527 |
+
border-color: #475569;
|
| 528 |
+
transform: translateY(-2px);
|
| 529 |
+
}
|
| 530 |
+
|
| 531 |
+
.network-node h4 {
|
| 532 |
+
font-size: 1rem;
|
| 533 |
+
margin-bottom: 0.5rem;
|
| 534 |
+
color: #feca57;
|
| 535 |
+
font-weight: 600;
|
| 536 |
+
}
|
| 537 |
+
|
| 538 |
+
.network-node p {
|
| 539 |
+
font-size: 0.875rem;
|
| 540 |
+
color: whitesmoke;
|
| 541 |
+
}
|
| 542 |
+
|
| 543 |
+
.arrow {
|
| 544 |
+
font-size: 1.5rem;
|
| 545 |
+
color: #3B82F6;
|
| 546 |
+
flex-shrink: 0;
|
| 547 |
+
margin: 0 0.5rem;
|
| 548 |
+
}
|
| 549 |
+
|
| 550 |
+
/* Metrics Grid */
|
| 551 |
+
.metrics-grid {
|
| 552 |
+
display: grid;
|
| 553 |
+
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
| 554 |
+
gap: 2rem;
|
| 555 |
+
margin-top: 3rem;
|
| 556 |
+
}
|
| 557 |
+
|
| 558 |
+
.metric-card {
|
| 559 |
+
text-align: center;
|
| 560 |
+
padding: 2.5rem 2rem;
|
| 561 |
+
}
|
| 562 |
+
|
| 563 |
+
.metric-value {
|
| 564 |
+
font-size: 2.5rem;
|
| 565 |
+
font-weight: 700;
|
| 566 |
+
color: #3B82F6;
|
| 567 |
+
margin-bottom: 0.5rem;
|
| 568 |
+
line-height: 1;
|
| 569 |
+
}
|
| 570 |
+
|
| 571 |
+
.metric-label {
|
| 572 |
+
color: #feca57;
|
| 573 |
+
font-weight: 500;
|
| 574 |
+
font-size: 0.95rem;
|
| 575 |
+
}
|
| 576 |
+
|
| 577 |
+
/* Research Grid */
|
| 578 |
+
.research-grid {
|
| 579 |
+
display: grid;
|
| 580 |
+
grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
|
| 581 |
+
gap: 2rem;
|
| 582 |
+
margin-top: 3rem;
|
| 583 |
+
}
|
| 584 |
+
|
| 585 |
+
.research-card h3 {
|
| 586 |
+
color: #feca57;
|
| 587 |
+
font-size: 1.25rem;
|
| 588 |
+
margin-bottom: 1rem;
|
| 589 |
+
font-weight: 700;
|
| 590 |
+
|
| 591 |
+
}
|
| 592 |
+
|
| 593 |
+
.research-card p {
|
| 594 |
+
color: whitesmoke;
|
| 595 |
+
margin-bottom: 1.5rem;
|
| 596 |
+
line-height: 1.6;
|
| 597 |
+
}
|
| 598 |
+
|
| 599 |
+
.research-card .btn {
|
| 600 |
+
background: #3B82F6;
|
| 601 |
+
color: #FFFFFF;
|
| 602 |
+
box-shadow: 0 4px 14px 0 rgba(59, 130, 246, 0.25);
|
| 603 |
+
}
|
| 604 |
+
|
| 605 |
+
.research-card .btn:hover {
|
| 606 |
+
background: #2563EB;
|
| 607 |
+
box-shadow: 0 6px 20px 0 rgba(59, 130, 246, 0.35);
|
| 608 |
+
}
|
| 609 |
+
|
| 610 |
+
/* Footer */
|
| 611 |
+
.footer {
|
| 612 |
+
background: #111827;
|
| 613 |
+
color: white;
|
| 614 |
+
padding: 3rem 0;
|
| 615 |
+
text-align: center;
|
| 616 |
+
}
|
| 617 |
+
|
| 618 |
+
.footer-content {
|
| 619 |
+
display: grid;
|
| 620 |
+
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
| 621 |
+
gap: 2rem;
|
| 622 |
+
margin-bottom: 2rem;
|
| 623 |
+
}
|
| 624 |
+
|
| 625 |
+
.footer-section h3 {
|
| 626 |
+
margin-bottom: 1rem;
|
| 627 |
+
color: #feca57;
|
| 628 |
+
font-weight: 700;
|
| 629 |
+
font-size: 1.3rem;
|
| 630 |
+
|
| 631 |
+
}
|
| 632 |
+
|
| 633 |
+
/* Footer links */
|
| 634 |
+
.footer-section p a {
|
| 635 |
+
color: white; /* Muted grey for text, consistent with other footer text */
|
| 636 |
+
text-decoration: none;
|
| 637 |
+
transition: color 0.3s ease; /* Smooth transition for hover effect */
|
| 638 |
+
}
|
| 639 |
+
|
| 640 |
+
.footer-section p a:hover {
|
| 641 |
+
color: #E74C3C; /* Professional red on hover */
|
| 642 |
+
}
|
| 643 |
+
|
| 644 |
+
.social-links {
|
| 645 |
+
display: flex;
|
| 646 |
+
flex-direction: column; /* Stacks the h3 and the new div vertically */
|
| 647 |
+
align-items: center;
|
| 648 |
+
gap: 1rem;
|
| 649 |
+
margin-top: 2rem;
|
| 650 |
+
|
| 651 |
+
}
|
| 652 |
+
.social-links h3 {
|
| 653 |
+
color: #feca57;
|
| 654 |
+
font-weight: 700;
|
| 655 |
+
font-size: 1.3rem;
|
| 656 |
+
}
|
| 657 |
+
|
| 658 |
+
.social-link {
|
| 659 |
+
display: inline-flex;
|
| 660 |
+
align-items: center;
|
| 661 |
+
justify-content: center;
|
| 662 |
+
width: 50px;
|
| 663 |
+
height: 50px;
|
| 664 |
+
background: #3B82F6;
|
| 665 |
+
border-radius: 50%;
|
| 666 |
+
color: white;
|
| 667 |
+
text-decoration: none;
|
| 668 |
+
font-size: 1.5rem;
|
| 669 |
+
transition: transform 0.3s ease;
|
| 670 |
+
}
|
| 671 |
+
|
| 672 |
+
.social-icons-row {
|
| 673 |
+
display: flex; /* Makes the icons themselves display in a row */
|
| 674 |
+
justify-content: center; /* Centers the icons within their new div */
|
| 675 |
+
gap: 1rem; /* Space between the icons */
|
| 676 |
+
}
|
| 677 |
+
.social-link:hover {
|
| 678 |
+
transform: scale(1.1) rotate(360deg);
|
| 679 |
+
}
|
| 680 |
+
|
| 681 |
+
/* Responsive Design */
|
| 682 |
+
@media (max-width: 768px) {
|
| 683 |
+
.hero h1 {
|
| 684 |
+
font-size: 2.5rem;
|
| 685 |
+
}
|
| 686 |
+
|
| 687 |
+
.demo-container {
|
| 688 |
+
grid-template-columns: 1fr;
|
| 689 |
+
}
|
| 690 |
+
|
| 691 |
+
.nav-links {
|
| 692 |
+
display: none;
|
| 693 |
+
}
|
| 694 |
+
|
| 695 |
+
.features-grid {
|
| 696 |
+
grid-template-columns: 1fr;
|
| 697 |
+
}
|
| 698 |
+
|
| 699 |
+
.network-diagram {
|
| 700 |
+
flex-direction: column;
|
| 701 |
+
}
|
| 702 |
+
|
| 703 |
+
.arrow {
|
| 704 |
+
transform: rotate(90deg);
|
| 705 |
+
}
|
| 706 |
+
}
|
| 707 |
+
|
| 708 |
+
/* Animations */
|
| 709 |
+
@keyframes pulse {
|
| 710 |
+
0%, 100% { transform: scale(1); }
|
| 711 |
+
50% { transform: scale(1.05); }
|
| 712 |
+
}
|
| 713 |
+
|
| 714 |
+
.pulse {
|
| 715 |
+
animation: pulse 2s infinite;
|
| 716 |
+
}
|
| 717 |
+
|
| 718 |
+
/* Processing Animation */
|
| 719 |
+
.processing {
|
| 720 |
+
display: inline-block;
|
| 721 |
+
width: 40px;
|
| 722 |
+
height: 40px;
|
| 723 |
+
border: 3px solid #374151;
|
| 724 |
+
border-top: 3px solid #3B82F6;
|
| 725 |
+
border-radius: 50%;
|
| 726 |
+
animation: spin 1s linear infinite;
|
| 727 |
+
}
|
| 728 |
+
|
| 729 |
+
@keyframes spin {
|
| 730 |
+
0% { transform: rotate(0deg); }
|
| 731 |
+
100% { transform: rotate(360deg); }
|
| 732 |
+
}
|
| 733 |
+
|
| 734 |
+
/* Progress Bar */
|
| 735 |
+
.progress-bar {
|
| 736 |
+
width: 100%;
|
| 737 |
+
height: 8px;
|
| 738 |
+
background: #f0f0f0;
|
| 739 |
+
border-radius: 4px;
|
| 740 |
+
overflow: hidden;
|
| 741 |
+
margin: 1rem 0;
|
| 742 |
+
}
|
| 743 |
+
|
| 744 |
+
.progress-fill {
|
| 745 |
+
height: 100%;
|
| 746 |
+
background: linear-gradient(45deg, #667eea, #764ba2);
|
| 747 |
+
width: 0%;
|
| 748 |
+
transition: width 0.3s ease;
|
| 749 |
+
border-radius: 4px;
|
| 750 |
+
}
|
| 751 |
+
|
| 752 |
+
/* Modal and 3D content */
|
| 753 |
+
.modal-content-3d {
|
| 754 |
+
width: 100%;
|
| 755 |
+
height: 500px;
|
| 756 |
+
background-color: #111827;
|
| 757 |
+
border-radius: 8px;
|
| 758 |
+
overflow: hidden;
|
| 759 |
+
}
|
| 760 |
+
|
| 761 |
+
.modal-content-3d canvas {
|
| 762 |
+
display: block;
|
| 763 |
+
width: 100%;
|
| 764 |
+
height: 100%;
|
| 765 |
+
}
|
| 766 |
+
|
| 767 |
+
/* Segmentation results */
|
| 768 |
+
.segmentation-results-display {
|
| 769 |
+
background: #111827;
|
| 770 |
+
padding: 1.5rem;
|
| 771 |
+
border-radius: 8px;
|
| 772 |
+
border-left: 4px solid #3B82F6;
|
| 773 |
+
margin-top: 2rem;
|
| 774 |
+
text-align: left;
|
| 775 |
+
}
|
| 776 |
+
|
| 777 |
+
.segmentation-results-display h4 {
|
| 778 |
+
font-size: 1.25rem;
|
| 779 |
+
color: #FFFFFF;
|
| 780 |
+
margin-bottom: 1rem;
|
| 781 |
+
text-align: center;
|
| 782 |
+
font-weight: 600;
|
| 783 |
+
}
|
| 784 |
+
|
| 785 |
+
.segmentation-results-display ul {
|
| 786 |
+
list-style-type: none;
|
| 787 |
+
padding: 0;
|
| 788 |
+
margin-top: 1rem;
|
| 789 |
+
}
|
| 790 |
+
|
| 791 |
+
.segmentation-results-display li {
|
| 792 |
+
background-color: rgba(59, 130, 246, 0.1);
|
| 793 |
+
margin-bottom: 0.5rem;
|
| 794 |
+
padding: 0.75rem 1rem;
|
| 795 |
+
border-radius: 6px;
|
| 796 |
+
font-size: 0.95rem;
|
| 797 |
+
color: #E5E7EB;
|
| 798 |
+
display: flex;
|
| 799 |
+
justify-content: space-between;
|
| 800 |
+
align-items: center;
|
| 801 |
+
border: 1px solid rgba(59, 130, 246, 0.2);
|
| 802 |
+
}
|
| 803 |
+
|
| 804 |
+
.segmentation-results-display li span {
|
| 805 |
+
font-weight: 600;
|
| 806 |
+
color: #FFFFFF;
|
| 807 |
+
}
|
| 808 |
+
|
| 809 |
+
/* Utility classes */
|
| 810 |
+
.text-center { text-align: center; }
|
| 811 |
+
.text-left { text-align: left; }
|
| 812 |
+
.text-right { text-align: right; }
|
| 813 |
+
.mb-1 { margin-bottom: 0.25rem; }
|
| 814 |
+
.mb-2 { margin-bottom: 0.5rem; }
|
| 815 |
+
.mb-3 { margin-bottom: 0.75rem; }
|
| 816 |
+
.mb-4 { margin-bottom: 1rem; }
|
| 817 |
+
.mt-1 { margin-top: 0.25rem; }
|
| 818 |
+
.mt-2 { margin-top: 0.5rem; }
|
| 819 |
+
.mt-3 { margin-top: 0.75rem; }
|
| 820 |
+
.mt-4 { margin-top: 1rem; }
|
| 821 |
+
</style>
|
| 822 |
+
|
| 823 |
+
|
| 824 |
+
<!-- FontAwesome for icons -->
|
| 825 |
+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">
|
| 826 |
+
|
| 827 |
+
<!-- Three.js Library -->
|
| 828 |
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
|
| 829 |
+
<!-- OrbitControls for camera interaction -->
|
| 830 |
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/controls/OrbitControls.min.js"></script>
|
| 831 |
+
</head>
|
| 832 |
+
<body>
|
| 833 |
+
<!-- Navigation -->
|
| 834 |
+
<nav class="navbar">
|
| 835 |
+
<div class="nav-container">
|
| 836 |
+
<div class="logo">Perceptra AI</div>
|
| 837 |
+
<ul class="nav-links">
|
| 838 |
+
<li><a href="#demo">Live Demo</a></li>
|
| 839 |
+
<li><a href="#features">Features</a></li>
|
| 840 |
+
<li><a href="#architecture">Architecture</a></li>
|
| 841 |
+
<li><a href="#metrics">Performance</a></li>
|
| 842 |
+
<li><a href="#research">Research</a></li>
|
| 843 |
+
<li><a href="/logout">Logout</a></li> {# Added Logout link #}
|
| 844 |
+
</ul>
|
| 845 |
+
</div>
|
| 846 |
+
</nav>
|
| 847 |
+
|
| 848 |
+
<!-- Hero Section -->
|
| 849 |
+
<section class="hero">
|
| 850 |
+
<div class="hero-content">
|
| 851 |
+
<h1>Perceptra AI: Unlocking Visual Intelligence</h1>
|
| 852 |
+
<p >Transforming static images and live video streams into actionable insights.
|
| 853 |
+
Experience custom-built AI for intelligent captioning, precise segmentation, and real-time visual understanding,
|
| 854 |
+
all powered by advanced, secure technology.</p>
|
| 855 |
+
<div class="cta-buttons">
|
| 856 |
+
<a href="#demo" class="btn btn-primary">
|
| 857 |
+
🚀 Try Live Demo
|
| 858 |
+
</a>
|
| 859 |
+
<a href="#architecture" class="btn btn-secondary">
|
| 860 |
+
🧠 Explore Architecture
|
| 861 |
+
</a>
|
| 862 |
+
</div>
|
| 863 |
+
</div>
|
| 864 |
+
</section>
|
| 865 |
+
|
| 866 |
+
<!-- Demo Section (Image Captioning & Segmentation) -->
|
| 867 |
+
<section id="demo" class="demo-section">
|
| 868 |
+
<div class="container">
|
| 869 |
+
<h2 class="section-title">Visual Intelligence Studio</h2>
|
| 870 |
+
<div class="demo-container">
|
| 871 |
+
<!-- Flask Image Captioning Form -->
|
| 872 |
+
<div class="upload-area flask-form-container">
|
| 873 |
+
<h3>Upload Your Image for Analysis</h3>
|
| 874 |
+
<p>Drag & drop an image or click to browse</p>
|
| 875 |
+
|
| 876 |
+
<!-- Flash Messages -->
|
| 877 |
+
{% with messages = get_flashed_messages(with_categories=true) %}
|
| 878 |
+
{% if messages %}
|
| 879 |
+
<div class="mb-4">
|
| 880 |
+
{% for category, message in messages %}
|
| 881 |
+
<div class="flash-message flash-{{ category }}">
|
| 882 |
+
{{ message }}
|
| 883 |
+
</div>
|
| 884 |
+
{% endfor %}
|
| 885 |
+
</div>
|
| 886 |
+
{% endif %}
|
| 887 |
+
{% endwith %}
|
| 888 |
+
|
| 889 |
+
<form action="/predict" method="post" enctype="multipart/form-data">
|
| 890 |
+
<input id="imageInput" name="file" type="file" accept="image/*" required class="flask-file-input">
|
| 891 |
+
<p style="font-size: 0.9em; color: #777; margin-top: 0.5rem; margin-bottom: 1rem;">PNG, JPG, JPEG, GIF formats allowed.</p>
|
| 892 |
+
<button type="submit" class="flask-submit-btn">
|
| 893 |
+
Analyze Image
|
| 894 |
+
</button>
|
| 895 |
+
</form>
|
| 896 |
+
</div>
|
| 897 |
+
|
| 898 |
+
<!-- Results Panel -->
|
| 899 |
+
<div class="results-panel">
|
| 900 |
+
<div class="tabs">
|
| 901 |
+
<div class="tab {% if not segmentation_image_url %}active{% endif %}" data-tab="caption">📝 Caption</div>
|
| 902 |
+
<div class="tab {% if segmentation_image_url %}active{% endif %}" data-tab="segment">🎯 Segmentation</div>
|
| 903 |
+
|
| 904 |
+
</div>
|
| 905 |
+
|
| 906 |
+
<div class="tab-content {% if not segmentation_image_url %}active{% endif %}" id="caption">
|
| 907 |
+
<h3>Generated Caption</h3>
|
| 908 |
+
<div id="captionResult">
|
| 909 |
+
{% if caption %}
|
| 910 |
+
<div class="flask-result-box">
|
| 911 |
+
<h3>Your Uploaded Image:</h3>
|
| 912 |
+
{% if uploaded_image_url %}
|
| 913 |
+
<img src="{{ uploaded_image_url }}" alt="Uploaded Image" class="flask-uploaded-image">
|
| 914 |
+
{% endif %}
|
| 915 |
+
<h3>Generated Caption:</h3>
|
| 916 |
+
<p>"{{ caption }}"</p>
|
| 917 |
+
</div>
|
| 918 |
+
{% else %}
|
| 919 |
+
<p style="color: #666; font-style: italic;">Upload an image to see the AI-generated caption...</p>
|
| 920 |
+
{% endif %}
|
| 921 |
+
</div>
|
| 922 |
+
</div>
|
| 923 |
+
|
| 924 |
+
<div class="tab-content {% if segmentation_image_url %}active{% endif %}" id="segment">
|
| 925 |
+
<h3>Segmentation Results</h3>
|
| 926 |
+
<div id="segmentResult">
|
| 927 |
+
{% if segmentation_image_url %}
|
| 928 |
+
<div class="segmentation-results-display">
|
| 929 |
+
<h4>Segmented Image:</h4>
|
| 930 |
+
<img src="{{ segmentation_image_url }}" alt="Segmented Image" class="flask-uploaded-image">
|
| 931 |
+
{% if segmentation_metrics.num_objects is defined %}
|
| 932 |
+
<h4>Detected Objects ({{ segmentation_metrics.num_objects }}):</h4>
|
| 933 |
+
<ul>
|
| 934 |
+
{% for obj in segmentation_metrics.detected_objects %}
|
| 935 |
+
<li><span>{{ obj }}</span></li>
|
| 936 |
+
{% endfor %}
|
| 937 |
+
{% if segmentation_metrics.error %}
|
| 938 |
+
<li style="color: red;">Error: {{ segmentation_metrics.error }}</li>
|
| 939 |
+
{% endif %}
|
| 940 |
+
</ul>
|
| 941 |
+
{% elif segmentation_metrics.status %}
|
| 942 |
+
<p style="color: #666;">{{ segmentation_metrics.status }}</p>
|
| 943 |
+
{% else %}
|
| 944 |
+
<p style="color: #666; font-style: italic;">No segmentation results available. Upload an image to analyze.</p>
|
| 945 |
+
{% endif %}
|
| 946 |
+
</div>
|
| 947 |
+
{% else %}
|
| 948 |
+
<p style="color: #666; font-style: italic;">Segmentation masks will appear here after image analysis.</p>
|
| 949 |
+
<div style="text-align: center; margin-top: 1rem;">
|
| 950 |
+
<img src="https://placehold.co/400x250/cccccc/333333?text=Segmentation+Preview" alt="Segmentation Placeholder" class="flask-uploaded-image">
|
| 951 |
+
<p style="margin-top: 0.5rem; font-size: 0.9em; color: #777;">Placeholder image until live segmentation is ready.</p>
|
| 952 |
+
</div>
|
| 953 |
+
{% endif %}
|
| 954 |
+
</div>
|
| 955 |
+
</div>
|
| 956 |
+
</div>
|
| 957 |
+
</div>
|
| 958 |
+
</div>
|
| 959 |
+
</section>
|
| 960 |
+
|
| 961 |
+
<!-- Dedicated LiveSense AI: Real-time Video Captioning Section -->
|
| 962 |
+
<section id="video-captioning" class="video-captioning-section">
|
| 963 |
+
<div class="container">
|
| 964 |
+
<h2 class="section-title">LiveSense AI: Real-time Video Understanding</h2>
|
| 965 |
+
<p>Step into the future of dynamic vision. Our dedicated LiveSense AI platform offers instant, intelligent descriptions of live video feeds, transforming real-world events into actionable insights.</p>
|
| 966 |
+
<a href="[Your LiveSense AI App URL Here]" target="_blank" class="video-cta-btn">
|
| 967 |
+
Launch LiveSense AI Application 🚀
|
| 968 |
+
</a>
|
| 969 |
+
</div>
|
| 970 |
+
</section>
|
| 971 |
+
<!-- END Dedicated LiveSense AI: Real-time Video Captioning Section -->
|
| 972 |
+
|
| 973 |
+
|
| 974 |
+
<!-- Features Section -->
|
| 975 |
+
<section id="features" class="features-section">
|
| 976 |
+
<div class="container">
|
| 977 |
+
<h2 class="section-title">Core Capabilities & Innovation</h2>
|
| 978 |
+
<div class="features-grid">
|
| 979 |
+
<div class="feature-card">
|
| 980 |
+
<span class="feature-icon">👁️</span>
|
| 981 |
+
<h3>Intelligent Image Captioning</h3>
|
| 982 |
+
<p>Our custom-built deep learning model accurately describes the content of static images, transforming visual data into rich, human-like narratives.</p>
|
| 983 |
+
</div>
|
| 984 |
+
|
| 985 |
+
<div class="feature-card">
|
| 986 |
+
<span class="feature-icon">🎯</span>
|
| 987 |
+
<h3>Precision Image Segmentation</h3>
|
| 988 |
+
<p>Leveraging advanced techniques, we precisely identify and segment objects within images, providing detailed insights into scene composition and object boundaries.</p>
|
| 989 |
+
</div>
|
| 990 |
+
|
| 991 |
+
<div class="feature-card">
|
| 992 |
+
<span class="feature-icon">⚡</span>
|
| 993 |
+
<h3>Real-time Dynamic Vision</h3>
|
| 994 |
+
<p>Experience instantaneous understanding of live video streams. Our optimized AI processes webcam feeds in real-time, providing continuous, intelligent descriptions and tracking of evolving scenes as they happen.</p>
|
| 995 |
+
</div>
|
| 996 |
+
|
| 997 |
+
<div class="feature-card">
|
| 998 |
+
<span class="feature-icon">🔐</span>
|
| 999 |
+
<h3>Robust Biometric Security</h3>
|
| 1000 |
+
<p>Safeguard access to sensitive AI capabilities with our multi-layered authentication. Featuring secure facial recognition and traditional email/password login, we ensure unparalleled user protection and data integrity.</p>
|
| 1001 |
+
</div>
|
| 1002 |
+
|
| 1003 |
+
<div class="feature-card">
|
| 1004 |
+
<span class="feature-icon">🧠</span>
|
| 1005 |
+
<h3>Proprietary Deep Learning Engine</h3>
|
| 1006 |
+
<p>Driven by custom-engineered neural architectures, including bespoke CNN-LSTM for captioning and advanced segmentation networks. Developed entirely from scratch for optimized performance and unique insights.</p>
|
| 1007 |
+
</div>
|
| 1008 |
+
|
| 1009 |
+
<div class="feature-card">
|
| 1010 |
+
<span class="feature-icon">📊</span>
|
| 1011 |
+
<h3>Performance & Operational Intelligence</h3>
|
| 1012 |
+
<p>Designed for high-throughput and low-latency operations, our system features adaptive processing, intelligent caching, and comprehensive performance analytics, ensuring scalable and reliable AI service delivery.</p>
|
| 1013 |
+
</div>
|
| 1014 |
+
</div>
|
| 1015 |
+
</div>
|
| 1016 |
+
</section>
|
| 1017 |
+
|
| 1018 |
+
<!-- Architecture Section -->
|
| 1019 |
+
<section id="architecture" class="architecture-section">
|
| 1020 |
+
<div class="container">
|
| 1021 |
+
<h2 class="section-title">Perceptra AI: Integrated Vision & Security Architecture</h2>
|
| 1022 |
+
<div class="architecture-viz">
|
| 1023 |
+
<h3>Core AI & System Components Overview</h3>
|
| 1024 |
+
|
| 1025 |
+
<div class="network-diagram-group">
|
| 1026 |
+
<h4>1. Static Image Analysis Pipeline</h4>
|
| 1027 |
+
<div class="network-diagram">
|
| 1028 |
+
<div class="network-node" data-info="The entry point for static images uploaded by users.">
|
| 1029 |
+
<h4>Image Input</h4>
|
| 1030 |
+
<p>Files/URLs</p>
|
| 1031 |
+
</div>
|
| 1032 |
+
<div class="arrow">→</div>
|
| 1033 |
+
<div class="network-node" data-info="Our custom-built model: ResNet50 Encoder extracts features, fed into an LSTM Decoder with Attention for generating descriptive captions.">
|
| 1034 |
+
<h4>Image Captioning Module</h4>
|
| 1035 |
+
<p>ResNet50-LSTM-Attention</p>
|
| 1036 |
+
</div>
|
| 1037 |
+
<div class="arrow">→</div>
|
| 1038 |
+
<div class="network-node" data-info="Integration of the powerful YOLOv8x-seg model for accurate object detection and precise instance segmentation.">
|
| 1039 |
+
<h4>Image Segmentation Module</h4>
|
| 1040 |
+
<p>YOLOv8x-seg</p>
|
| 1041 |
+
</div>
|
| 1042 |
+
<div class="arrow">→</div>
|
| 1043 |
+
<div class="network-node" data-info="Structured JSON outputs containing generated captions, identified objects, and segmentation masks.">
|
| 1044 |
+
<h4>Analyzed Output</h4>
|
| 1045 |
+
<p>Captions & Masks</p>
|
| 1046 |
+
</div>
|
| 1047 |
+
</div>
|
| 1048 |
+
</div>
|
| 1049 |
+
|
| 1050 |
+
<div class="network-diagram-group" style="margin-top: 3rem;">
|
| 1051 |
+
<h4>2. Real-time Video Intelligence (LiveSense AI)</h4>
|
| 1052 |
+
<div class="network-diagram">
|
| 1053 |
+
<div class="network-node" data-info="Captures live video streams directly from the user's webcam for instant processing.">
|
| 1054 |
+
<h4>Webcam Input</h4>
|
| 1055 |
+
<p>Live Stream</p>
|
| 1056 |
+
</div>
|
| 1057 |
+
<div class="arrow">→</div>
|
| 1058 |
+
<div class="network-node" data-info="Utilizes the BLIP model for real-time video understanding, enhanced by adaptive frame sampling, batch processing, and intelligent caching.">
|
| 1059 |
+
<h4>Dynamic Vision Core</h4>
|
| 1060 |
+
<p>BLIP & Optimizations</p>
|
| 1061 |
+
</div>
|
| 1062 |
+
<div class="arrow">→</div>
|
| 1063 |
+
<div class="network-node" data-info="Provides continuous, contextually rich descriptions of evolving scenes, displayed instantly in the UI.">
|
| 1064 |
+
<h4>Live Caption Stream</h4>
|
| 1065 |
+
<p>Real-time Output</p>
|
| 1066 |
+
</div>
|
| 1067 |
+
</div>
|
| 1068 |
+
</div>
|
| 1069 |
+
|
| 1070 |
+
<div class="network-diagram-group" style="margin-top: 3rem;">
|
| 1071 |
+
<h4>3. Secure Identity & Application Layer</h4>
|
| 1072 |
+
<div class="network-diagram">
|
| 1073 |
+
<div class="network-node" data-info="Supports user authentication via email/password and advanced facial recognition, capturing biometric data securely.">
|
| 1074 |
+
<h4>User Inputs</h4>
|
| 1075 |
+
<p>Biometrics & Passwords</p>
|
| 1076 |
+
</div>
|
| 1077 |
+
<div class="arrow">→</div>
|
| 1078 |
+
<div class="network-node" data-info="The core Flask backend orchestrates all AI services, handles API requests, and manages data flow.">
|
| 1079 |
+
<h4>Backend Orchestration</h4>
|
| 1080 |
+
<p>Flask API & Logic</p>
|
| 1081 |
+
</div>
|
| 1082 |
+
<div class="arrow">→</div>
|
| 1083 |
+
<div class="network-node" data-info="Securely stores user credentials, face encodings, and manages authentication states using SQLAlchemy.">
|
| 1084 |
+
<h4>User Database</h4>
|
| 1085 |
+
<p>SQLite/SQLAlchemy</p>
|
| 1086 |
+
</div>
|
| 1087 |
+
<div class="arrow">→</div>
|
| 1088 |
+
<div class="network-node" data-info="The user-facing web interface built with HTML, CSS, and JavaScript, providing interactive demos and real-time displays.">
|
| 1089 |
+
<h4>Frontend Interface</h4>
|
| 1090 |
+
<p>UI/UX</p>
|
| 1091 |
+
</div>
|
| 1092 |
+
</div>
|
| 1093 |
+
</div>
|
| 1094 |
+
|
| 1095 |
+
<div style="text-align: center; margin-top: 4rem;">
|
| 1096 |
+
<!-- <button class="btn btn-primary" onclick="showArchitectureDetails()">
|
| 1097 |
+
🔍 Explore Conceptual 3D Model
|
| 1098 |
+
</button> -->
|
| 1099 |
+
<p style="color: rgba(255,255,255,0.7); font-size: 0.9em; margin-top: 1rem;">
|
| 1100 |
+
Hover over nodes for details. The 3D model provides a conceptual visualization of a core AI pipeline within our system.
|
| 1101 |
+
</p>
|
| 1102 |
+
</div>
|
| 1103 |
+
</div>
|
| 1104 |
+
</div>
|
| 1105 |
+
</section>
|
| 1106 |
+
|
| 1107 |
+
|
| 1108 |
+
<!-- Metrics Section -->
|
| 1109 |
+
<!-- Metrics Section -->
|
| 1110 |
+
<section id="metrics" class="metrics-section">
|
| 1111 |
+
<div class="container">
|
| 1112 |
+
<h2 class="section-title">Performance Metrics</h2>
|
| 1113 |
+
<div class="metrics-grid">
|
| 1114 |
+
<div class="metric-card">
|
| 1115 |
+
<div class="metric-value" id="bleuScore">10.49%</div>
|
| 1116 |
+
<div class="metric-label">BLEU-4 Score</div>
|
| 1117 |
+
<p class="metric-subtext">For custom, scratch-built model</p>
|
| 1118 |
+
</div>
|
| 1119 |
+
|
| 1120 |
+
<div class="metric-card">
|
| 1121 |
+
<div class="metric-value" id="ciderScore">1.03</div>
|
| 1122 |
+
<div class="metric-label">CIDEr Score</div>
|
| 1123 |
+
<p class="metric-subtext">Measures agreement with human captions</p>
|
| 1124 |
+
</div>
|
| 1125 |
+
|
| 1126 |
+
<div class="metric-card">
|
| 1127 |
+
<div class="metric-value" id="meteorScore">31.58%</div>
|
| 1128 |
+
<div class="metric-label">METEOR Score</div>
|
| 1129 |
+
<p class="metric-subtext">Balances precision and recall of unigrams</p>
|
| 1130 |
+
</div>
|
| 1131 |
+
|
| 1132 |
+
<div class="metric-card">
|
| 1133 |
+
<div class="metric-value" id="inferenceLatency">27.7 ms</div>
|
| 1134 |
+
<div class="metric-label">Avg. Inference Latency</div>
|
| 1135 |
+
<p class="metric-subtext">Time to process one image</p>
|
| 1136 |
+
</div>
|
| 1137 |
+
|
| 1138 |
+
<div class="metric-card">
|
| 1139 |
+
<div class="metric-value" id="processingFps">36.1 FPS</div>
|
| 1140 |
+
<div class="metric-label">Processing Throughput</div>
|
| 1141 |
+
<p class="metric-subtext">Frames processed per second for live image</p>
|
| 1142 |
+
</div>
|
| 1143 |
+
|
| 1144 |
+
<div class="metric-card">
|
| 1145 |
+
<div class="metric-value" id="perplexity" style="font-size: 2rem;">12.43</div>
|
| 1146 |
+
<div class="metric-label">Perplexity</div>
|
| 1147 |
+
<p class="metric-subtext">Lower indicates better language model prediction</p>
|
| 1148 |
+
</div>
|
| 1149 |
+
</div>
|
| 1150 |
+
|
| 1151 |
+
</div>
|
| 1152 |
+
</section>
|
| 1153 |
+
|
| 1154 |
+
<!-- Research Section -->
|
| 1155 |
+
<section id="research" class="research-section">
|
| 1156 |
+
<div class="container">
|
| 1157 |
+
<h2 class="section-title">Research & Innovation</h2>
|
| 1158 |
+
<div class="research-grid">
|
| 1159 |
+
<div class="research-card">
|
| 1160 |
+
<h3>📚 Technical Documentation</h3>
|
| 1161 |
+
<p>Complete research paper with mathematical formulations, architecture details, and experimental results.</p>
|
| 1162 |
+
<button class="btn btn-primary" style="margin-top: 1rem;">Read Paper</button>
|
| 1163 |
+
</div>
|
| 1164 |
+
|
| 1165 |
+
<!-- <div class="research-card">
|
| 1166 |
+
<h3>🔬 Ablation Studies</h3>
|
| 1167 |
+
<p>Comprehensive analysis of different architectural choices and their impact on model performance.</p>
|
| 1168 |
+
<button class="btn btn-primary" style="margin-top: 1rem;">View Studies</button>
|
| 1169 |
+
</div> -->
|
| 1170 |
+
|
| 1171 |
+
<div class="research-card">
|
| 1172 |
+
<h3>💻 Code Repository</h3>
|
| 1173 |
+
<p>Open-source implementation with detailed comments, training scripts, and deployment guides.</p>
|
| 1174 |
+
<button class="btn btn-primary" style="margin-top: 1rem;">GitHub Repo</button>
|
| 1175 |
+
</div>
|
| 1176 |
+
|
| 1177 |
+
<div class="research-card">
|
| 1178 |
+
<h3>📊 Training Insights</h3>
|
| 1179 |
+
<p>Interactive dashboard showing training progress, loss curves, and hyperparameter optimization results.</p>
|
| 1180 |
+
<button class="btn btn-primary" style="margin-top: 1rem;">Training Dashboard</button>
|
| 1181 |
+
</div>
|
| 1182 |
+
</div>
|
| 1183 |
+
</div>
|
| 1184 |
+
</section>
|
| 1185 |
+
|
| 1186 |
+
<!-- Footer -->
|
| 1187 |
+
<footer class="footer">
|
| 1188 |
+
<div class="container">
|
| 1189 |
+
<div class="footer-content">
|
| 1190 |
+
<div class="footer-section">
|
| 1191 |
+
<h3>Perceptra AI</h3> {# Updated Brand Name #}
|
| 1192 |
+
<p style="color: #ccc; margin-top: 0.5rem; font-weight: 500;"><b>Intelligent Vision. Secure Insights. Real-time Understanding.</b></p> {# Added Tagline with styling #}
|
| 1193 |
+
</div>
|
| 1194 |
+
|
| 1195 |
+
<div class="footer-section">
|
| 1196 |
+
<h3>Quick Links</h3>
|
| 1197 |
+
<p><a href="#demo"><b>Live Demo</b></a></p>
|
| 1198 |
+
<p><a href="#architecture"><b>Architecture</b></a></p>
|
| 1199 |
+
<p><a href="#research"><b>Research</b></a></p>
|
| 1200 |
+
<p><a href="/main_app"><b>App Home</b></a></p> {# Added link to main app #}
|
| 1201 |
+
</div>
|
| 1202 |
+
|
| 1203 |
+
<div class="footer-section">
|
| 1204 |
+
<h3>Developer</h3>
|
| 1205 |
+
<p><b>Varsh Dewangan</b></p> {# Your Name #}
|
| 1206 |
+
<p><b>Data Scientist</b></p> {# Specific role and context #}
|
| 1207 |
+
</div>
|
| 1208 |
+
|
| 1209 |
+
</div>
|
| 1210 |
+
|
| 1211 |
+
<div class="social-links">
|
| 1212 |
+
<h3>Connect with me!</h3>
|
| 1213 |
+
<div class="social-icons-row"> {# This new div will hold your icons in a row #}
|
| 1214 |
+
<a href="mailto:varshadewangan1605@gmail.com" class="social-link">📧</a> {# Link to your email #}
|
| 1215 |
+
<a href="https://www.linkedin.com/in/varsha-dewangan-197983256/" target="_blank" class="social-link">💼</a> {# Link to your LinkedIn #}
|
| 1216 |
+
<a href="https://github.com/Varsha-1605" target="_blank" class="social-link">🐙</a> {# Link to your GitHub #}
|
| 1217 |
+
<a href="https://www.instagram.com/varshadewangan454/" target="_blank" class="social-link">📸</a> {# Replaced Twitter with Instagram #}
|
| 1218 |
+
</div>
|
| 1219 |
+
</div>
|
| 1220 |
+
|
| 1221 |
+
<p style="margin-top: 2rem; padding-top: 2rem; border-top: 1px solid #333; color: #ccc;">
|
| 1222 |
+
<b>© 2024 Perceptra AI. All rights reserved.</b>
|
| 1223 |
+
</p>
|
| 1224 |
+
</div>
|
| 1225 |
+
</footer>
|
| 1226 |
+
|
| 1227 |
+
<script>
|
| 1228 |
+
// Tab functionality (Existing, Modified to clear for Flask output)
|
| 1229 |
+
document.querySelectorAll('.tab').forEach(tab => {
|
| 1230 |
+
tab.addEventListener('click', function() {
|
| 1231 |
+
// Remove active class from all tabs and contents
|
| 1232 |
+
document.querySelectorAll('.tab').forEach(t => t.classList.remove('active'));
|
| 1233 |
+
document.querySelectorAll('.tab-content').forEach(c => c.classList.remove('active'));
|
| 1234 |
+
|
| 1235 |
+
// Add active class to clicked tab
|
| 1236 |
+
this.classList.add('active');
|
| 1237 |
+
|
| 1238 |
+
// Show corresponding content
|
| 1239 |
+
const tabId = this.getAttribute('data-tab');
|
| 1240 |
+
document.getElementById(tabId).classList.add('active');
|
| 1241 |
+
|
| 1242 |
+
// Clear previous results when switching tabs, except for the Flask-driven caption or segment tab
|
| 1243 |
+
// The Flask-driven content for caption and segment should persist until a new upload
|
| 1244 |
+
if (tabId !== 'caption' && tabId !== 'segment') {
|
| 1245 |
+
// Only clear the analysis tab
|
| 1246 |
+
document.getElementById('analysisResult').innerHTML = '<p style="color: #666; font-style: italic;">Detailed analysis coming soon from backend...</p>';
|
| 1247 |
+
}
|
| 1248 |
+
});
|
| 1249 |
+
});
|
| 1250 |
+
|
| 1251 |
+
// Auto-select the segmentation tab if segmentation_image_url is present after a Flask render
|
| 1252 |
+
document.addEventListener('DOMContentLoaded', function() {
|
| 1253 |
+
// Use a slightly different check for Flask template variables which might be 'None' string
|
| 1254 |
+
const segmentationImageUrl = "{{ segmentation_image_url }}";
|
| 1255 |
+
const captionContentExists = document.getElementById('captionResult').innerText.trim() !== 'Upload an image to see the AI-generated caption...' && document.getElementById('captionResult').innerText.trim() !== '';
|
| 1256 |
+
|
| 1257 |
+
if (segmentationImageUrl && segmentationImageUrl !== 'None') {
|
| 1258 |
+
// Deactivate current active tab
|
| 1259 |
+
document.querySelector('.tab.active')?.classList.remove('active');
|
| 1260 |
+
document.querySelector('.tab-content.active')?.classList.remove('active');
|
| 1261 |
+
|
| 1262 |
+
// Activate segmentation tab and content
|
| 1263 |
+
document.querySelector('.tab[data-tab="segment"]').classList.add('active');
|
| 1264 |
+
document.getElementById('segment').classList.add('active');
|
| 1265 |
+
} else if (captionContentExists) {
|
| 1266 |
+
// If no segmentation but caption exists, activate caption tab
|
| 1267 |
+
document.querySelector('.tab.active')?.classList.remove('active');
|
| 1268 |
+
document.querySelector('.tab-content.active')?.classList.remove('active');
|
| 1269 |
+
|
| 1270 |
+
document.querySelector('.tab[data-tab="caption"]').classList.add('active');
|
| 1271 |
+
document.getElementById('caption').classList.add('active');
|
| 1272 |
+
}
|
| 1273 |
+
// If neither has content, the default set in HTML (caption tab active) will apply
|
| 1274 |
+
});
|
| 1275 |
+
|
| 1276 |
+
|
| 1277 |
+
// The original JavaScript for file upload simulation (processImage, showResults, drag/drop)
|
| 1278 |
+
// is REMOVED as Flask handles the actual file upload and rendering.
|
| 1279 |
+
// The HTML form now directly submits to Flask.
|
| 1280 |
+
|
| 1281 |
+
// Smooth scrolling for navigation links (Existing)
|
| 1282 |
+
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
|
| 1283 |
+
anchor.addEventListener('click', function (e) {
|
| 1284 |
+
e.preventDefault();
|
| 1285 |
+
const target = document.querySelector(this.getAttribute('href'));
|
| 1286 |
+
if (target) {
|
| 1287 |
+
target.scrollIntoView({
|
| 1288 |
+
behavior: 'smooth',
|
| 1289 |
+
block: 'start'
|
| 1290 |
+
});
|
| 1291 |
+
}
|
| 1292 |
+
});
|
| 1293 |
+
});
|
| 1294 |
+
|
| 1295 |
+
// Navbar scroll effect (Existing)
|
| 1296 |
+
window.addEventListener('scroll', function() {
|
| 1297 |
+
const navbar = document.querySelector('.navbar');
|
| 1298 |
+
if (window.scrollY > 100) {
|
| 1299 |
+
navbar.style.background = 'rgba(0,0,0,0.9)';
|
| 1300 |
+
} else {
|
| 1301 |
+
navbar.style.background = 'rgba(255,255,255,0.1)';
|
| 1302 |
+
}
|
| 1303 |
+
});
|
| 1304 |
+
|
| 1305 |
+
// Animate metrics when in view (Existing)
|
| 1306 |
+
function animateMetrics() {
|
| 1307 |
+
const metrics = document.querySelectorAll('.metric-value');
|
| 1308 |
+
const observer = new IntersectionObserver((entries) => {
|
| 1309 |
+
entries.forEach(entry => {
|
| 1310 |
+
if (entry.isIntersecting) {
|
| 1311 |
+
const target = entry.target;
|
| 1312 |
+
const finalValue = parseFloat(target.textContent);
|
| 1313 |
+
let currentValue = 0;
|
| 1314 |
+
const increment = finalValue / 50;
|
| 1315 |
+
|
| 1316 |
+
const timer = setInterval(() => {
|
| 1317 |
+
currentValue += increment;
|
| 1318 |
+
if (currentValue >= finalValue) {
|
| 1319 |
+
currentValue = finalValue;
|
| 1320 |
+
clearInterval(timer);
|
| 1321 |
+
}
|
| 1322 |
+
target.textContent = currentValue.toFixed(1);
|
| 1323 |
+
}, 30);
|
| 1324 |
+
|
| 1325 |
+
observer.unobserve(target);
|
| 1326 |
+
}
|
| 1327 |
+
});
|
| 1328 |
+
});
|
| 1329 |
+
|
| 1330 |
+
metrics.forEach(metric => observer.observe(metric));
|
| 1331 |
+
}
|
| 1332 |
+
|
| 1333 |
+
// Architecture details modal (UPDATED for 3D)
|
| 1334 |
+
let scene, camera, renderer, controls, animationFrameId;
|
| 1335 |
+
|
| 1336 |
+
function showArchitectureDetails() {
|
| 1337 |
+
// Prevent multiple modals if clicked rapidly
|
| 1338 |
+
if (document.querySelector('.modal')) {
|
| 1339 |
+
return;
|
| 1340 |
+
}
|
| 1341 |
+
|
| 1342 |
+
const modal = document.createElement('div');
|
| 1343 |
+
modal.className = 'modal'; // Add a class for styling
|
| 1344 |
+
modal.style.cssText = `
|
| 1345 |
+
position: fixed;
|
| 1346 |
+
top: 0;
|
| 1347 |
+
left: 0;
|
| 1348 |
+
width: 100%;
|
| 1349 |
+
height: 100%;
|
| 1350 |
+
background: rgba(0,0,0,0.8);
|
| 1351 |
+
display: flex;
|
| 1352 |
+
align-items: center;
|
| 1353 |
+
justify-content: center;
|
| 1354 |
+
z-index: 9999;
|
| 1355 |
+
backdrop-filter: blur(10px);
|
| 1356 |
+
transition: opacity 0.3s ease;
|
| 1357 |
+
opacity: 0; /* Start hidden for fade-in */
|
| 1358 |
+
`;
|
| 1359 |
+
|
| 1360 |
+
modal.innerHTML = `
|
| 1361 |
+
<div style="background: white; border-radius: 20px; padding: 2rem; max-width: 90%; max-height: 90vh; overflow: hidden; position: relative; display: flex; flex-direction: column;">
|
| 1362 |
+
<button id="closeModalBtn" style="position: absolute; top: 1rem; right: 1rem; border: none; background: none; font-size: 2rem; cursor: pointer; color: #666;">×</button>
|
| 1363 |
+
|
| 1364 |
+
<h2 style="color: #667eea; margin-bottom: 1.5rem; text-align: center; font-size: 2rem;">3D Architecture Visualization</h2>
|
| 1365 |
+
|
| 1366 |
+
<div id="architectureCanvasContainer" class="modal-content-3d" style="flex-grow: 1; min-height: 300px; display: flex; justify-content: center; align-items: center;">
|
| 1367 |
+
<canvas id="architectureCanvas" style="display: block;"></canvas>
|
| 1368 |
+
<p id="loadingText" style="color: #ccc; text-align: center; position: absolute;">Loading 3D model...</p>
|
| 1369 |
+
</div>
|
| 1370 |
+
|
| 1371 |
+
<div style="display: flex; flex-wrap: wrap; justify-content: space-around; gap: 1rem; margin-top: 1.5rem; color: #666;">
|
| 1372 |
+
<div style="flex: 1; min-width: 250px;">
|
| 1373 |
+
<h3 style="color: #667eea; margin-bottom: 0.5rem;">Caption Branch</h3>
|
| 1374 |
+
<ul style="padding-left: 1.5rem; list-style-type: disc;">
|
| 1375 |
+
<li>CNN Feature Extractor</li>
|
| 1376 |
+
<li>Attention Mechanism</li>
|
| 1377 |
+
<li>LSTM Decoder</li>
|
| 1378 |
+
</ul>
|
| 1379 |
+
</div>
|
| 1380 |
+
<div style="flex: 1; min-width: 250px;">
|
| 1381 |
+
<h3 style="color: #667eea; margin-bottom: 0.5rem;">Segmentation Branch</h3>
|
| 1382 |
+
<ul style="padding-left: 1.5rem; list-style-type: disc;">
|
| 1383 |
+
<li>U-Net Architecture</li>
|
| 1384 |
+
<li>Skip Connections</li>
|
| 1385 |
+
<li>Multi-scale Features</li>
|
| 1386 |
+
</ul>
|
| 1387 |
+
</div>
|
| 1388 |
+
</div>
|
| 1389 |
+
<p style="text-align: center; margin-top: 1rem; font-size: 0.9em; color: #555;">
|
| 1390 |
+
Click and drag to rotate the 3D model. Scroll to zoom.
|
| 1391 |
+
</p>
|
| 1392 |
+
</div>
|
| 1393 |
+
`;
|
| 1394 |
+
|
| 1395 |
+
document.body.appendChild(modal);
|
| 1396 |
+
|
| 1397 |
+
// Fade in modal
|
| 1398 |
+
setTimeout(() => modal.style.opacity = '1', 10);
|
| 1399 |
+
|
| 1400 |
+
// Setup 3D scene after modal is in DOM
|
| 1401 |
+
const canvasContainer = document.getElementById('architectureCanvasContainer');
|
| 1402 |
+
const canvas = document.getElementById('architectureCanvas');
|
| 1403 |
+
const loadingText = document.getElementById('loadingText');
|
| 1404 |
+
|
| 1405 |
+
|
| 1406 |
+
// 1. Scene
|
| 1407 |
+
scene = new THREE.Scene();
|
| 1408 |
+
scene.background = new THREE.Color(0x1a1a1a); // Dark background for the 3D space
|
| 1409 |
+
|
| 1410 |
+
// 2. Camera
|
| 1411 |
+
camera = new THREE.PerspectiveCamera(75, 1, 0.1, 1000); // Set initial aspect to 1, will be updated
|
| 1412 |
+
camera.position.set(0, 0, 10); // Adjust camera position for better view
|
| 1413 |
+
|
| 1414 |
+
// 3. Renderer
|
| 1415 |
+
renderer = new THREE.WebGLRenderer({ canvas: canvas, antialias: true });
|
| 1416 |
+
renderer.setPixelRatio(window.devicePixelRatio);
|
| 1417 |
+
// setCanvasSize(); // Initial size setup - call it after objects are added for more reliable dimensions
|
| 1418 |
+
|
| 1419 |
+
// 4. Lights
|
| 1420 |
+
const ambientLight = new THREE.AmbientLight(0x404040); // soft white light
|
| 1421 |
+
scene.add(ambientLight);
|
| 1422 |
+
const directionalLight1 = new THREE.DirectionalLight(0xffffff, 0.7);
|
| 1423 |
+
directionalLight1.position.set(5, 5, 5).normalize();
|
| 1424 |
+
scene.add(directionalLight1);
|
| 1425 |
+
const directionalLight2 = new THREE.DirectionalLight(0xffffff, 0.5);
|
| 1426 |
+
directionalLight2.position.set(-5, -5, -5).normalize();
|
| 1427 |
+
scene.add(directionalLight2);
|
| 1428 |
+
|
| 1429 |
+
// 5. Controls
|
| 1430 |
+
controls = new OrbitControls(camera, renderer.domElement);
|
| 1431 |
+
controls.enableDamping = true; // an animation loop is required when damping is enabled
|
| 1432 |
+
controls.dampingFactor = 0.05;
|
| 1433 |
+
controls.screenSpacePanning = false;
|
| 1434 |
+
controls.minDistance = 5;
|
| 1435 |
+
controls.maxDistance = 20;
|
| 1436 |
+
|
| 1437 |
+
// --- Create Model Architecture Elements ---
|
| 1438 |
+
|
| 1439 |
+
// Colors
|
| 1440 |
+
const encoderColor = 0x667eea; // Blue
|
| 1441 |
+
const attentionColor = 0xfeca57; // Yellow
|
| 1442 |
+
const decoderColor = 0x764ba2; // Purple
|
| 1443 |
+
const segmentationColor = 0x4ecdc4; // Teal
|
| 1444 |
+
const arrowColor = 0xcccccc; // Light grey
|
| 1445 |
+
|
| 1446 |
+
const boxGeometry = new THREE.BoxGeometry(2, 2, 2);
|
| 1447 |
+
const cylinderGeometry = new THREE.CylinderGeometry(0.5, 0.5, 2, 32);
|
| 1448 |
+
const coneGeometry = new THREE.ConeGeometry(0.7, 1.5, 32);
|
| 1449 |
+
|
| 1450 |
+
// Encoder (CNN)
|
| 1451 |
+
const encoderMaterial = new THREE.MeshPhongMaterial({ color: encoderColor });
|
| 1452 |
+
const encoder = new THREE.Mesh(boxGeometry, encoderMaterial);
|
| 1453 |
+
encoder.position.set(-4, 0, 0);
|
| 1454 |
+
scene.add(encoder);
|
| 1455 |
+
|
| 1456 |
+
// Attention Mechanism
|
| 1457 |
+
const attentionMaterial = new THREE.MeshPhongMaterial({ color: attentionColor, emissive: attentionColor, emissiveIntensity: 0.3 });
|
| 1458 |
+
const attention = new THREE.Mesh(coneGeometry, attentionMaterial);
|
| 1459 |
+
attention.rotation.z = -Math.PI / 2; // Point towards decoder
|
| 1460 |
+
attention.position.set(-1.5, 0, 0); // Between encoder and decoder
|
| 1461 |
+
scene.add(attention);
|
| 1462 |
+
|
| 1463 |
+
// Decoder (LSTM)
|
| 1464 |
+
const decoderMaterial = new THREE.MeshPhongMaterial({ color: decoderColor });
|
| 1465 |
+
const decoder = new THREE.Mesh(boxGeometry, decoderMaterial);
|
| 1466 |
+
decoder.position.set(1.5, 1, 0); // Position slightly up for caption branch
|
| 1467 |
+
scene.add(decoder);
|
| 1468 |
+
|
| 1469 |
+
// Segmentation Branch (U-Net inspired - another block)
|
| 1470 |
+
const segmentation = new THREE.Mesh(boxGeometry, new THREE.MeshPhongMaterial({ color: segmentationColor }));
|
| 1471 |
+
segmentation.position.set(1.5, -1, 0); // Position slightly down for segmentation branch
|
| 1472 |
+
scene.add(segmentation);
|
| 1473 |
+
|
| 1474 |
+
// Arrows (data flow)
|
| 1475 |
+
const arrowMaterial = new THREE.MeshBasicMaterial({ color: arrowColor });
|
| 1476 |
+
const arrow1 = new THREE.Mesh(new THREE.BoxGeometry(2.5, 0.2, 0.2), arrowMaterial); // Encoder to Attention
|
| 1477 |
+
arrow1.position.set(-2.75, 0, 0);
|
| 1478 |
+
scene.add(arrow1);
|
| 1479 |
+
|
| 1480 |
+
const arrow2 = new THREE.Mesh(new THREE.BoxGeometry(2.5, 0.2, 0.2), arrowMaterial); // Attention to Decoder
|
| 1481 |
+
arrow2.position.set(0, 1, 0);
|
| 1482 |
+
arrow2.rotation.z = Math.PI / 4; // Angle it towards decoder
|
| 1483 |
+
scene.add(arrow2);
|
| 1484 |
+
|
| 1485 |
+
const arrow3 = new THREE.Mesh(new THREE.BoxGeometry(2.5, 0.2, 0.2), arrowMaterial); // Shared Feature to Segmentation
|
| 1486 |
+
arrow3.position.set(0, -1, 0);
|
| 1487 |
+
arrow3.rotation.z = -Math.PI / 4; // Angle it towards segmentation
|
| 1488 |
+
scene.add(arrow3);
|
| 1489 |
+
|
| 1490 |
+
// Output Caption Arrow/Block
|
| 1491 |
+
const outputCaption = new THREE.Mesh(new THREE.BoxGeometry(1, 0.8, 0.8), decoderMaterial);
|
| 1492 |
+
outputCaption.position.set(4, 1, 0);
|
| 1493 |
+
scene.add(outputCaption);
|
| 1494 |
+
const arrow4 = new THREE.Mesh(new THREE.BoxGeometry(2.5, 0.2, 0.2), arrowMaterial);
|
| 1495 |
+
arrow4.position.set(2.75, 1, 0);
|
| 1496 |
+
scene.add(arrow4);
|
| 1497 |
+
|
| 1498 |
+
// Output Segmentation Arrow/Block
|
| 1499 |
+
const outputSegmentation = new THREE.Mesh(new THREE.BoxGeometry(1, 0.8, 0.8), new THREE.MeshPhongMaterial({ color: segmentationColor }));
|
| 1500 |
+
outputSegmentation.position.set(4, -1, 0);
|
| 1501 |
+
scene.add(outputSegmentation);
|
| 1502 |
+
const arrow5 = new THREE.Mesh(new THREE.BoxGeometry(2.5, 0.2, 0.2), arrowMaterial);
|
| 1503 |
+
arrow5.position.set(2.75, -1, 0);
|
| 1504 |
+
scene.add(arrow5);
|
| 1505 |
+
|
| 1506 |
+
// --- Simple Text Labels (using CanvasTexture for better readability) ---
|
| 1507 |
+
function createTextSprite(message, color, fontSize = 60) {
|
| 1508 |
+
const canvas = document.createElement('canvas');
|
| 1509 |
+
const context = canvas.getContext('2d');
|
| 1510 |
+
context.font = `${fontSize}px Arial`;
|
| 1511 |
+
context.fillStyle = color;
|
| 1512 |
+
context.textAlign = 'center';
|
| 1513 |
+
context.textBaseline = 'middle';
|
| 1514 |
+
const metrics = context.measureText(message);
|
| 1515 |
+
canvas.width = metrics.width + 20;
|
| 1516 |
+
canvas.height = fontSize + 20;
|
| 1517 |
+
context.font = `${fontSize}px Arial`;
|
| 1518 |
+
context.fillStyle = color;
|
| 1519 |
+
context.textAlign = 'center';
|
| 1520 |
+
context.textBaseline = 'middle';
|
| 1521 |
+
context.fillText(message, canvas.width / 2, canvas.height / 2);
|
| 1522 |
+
|
| 1523 |
+
const texture = new THREE.CanvasTexture(canvas);
|
| 1524 |
+
const spriteMaterial = new THREE.SpriteMaterial({ map: texture });
|
| 1525 |
+
const sprite = new THREE.Sprite(spriteMaterial);
|
| 1526 |
+
// Adjust scale based on text length and desired size in 3D
|
| 1527 |
+
sprite.scale.set(canvas.width * 0.01, canvas.height * 0.01, 1);
|
| 1528 |
+
return sprite;
|
| 1529 |
+
}
|
| 1530 |
+
|
| 1531 |
+
const encoderLabel = createTextSprite("Encoder", "#ffffff");
|
| 1532 |
+
encoderLabel.position.set(encoder.position.x, encoder.position.y + 1.5, encoder.position.z);
|
| 1533 |
+
scene.add(encoderLabel);
|
| 1534 |
+
|
| 1535 |
+
const attentionLabel = createTextSprite("Attention", "#ffffff");
|
| 1536 |
+
attentionLabel.position.set(attention.position.x, attention.position.y + 1.2, attention.position.z);
|
| 1537 |
+
scene.add(attentionLabel);
|
| 1538 |
+
|
| 1539 |
+
const decoderLabel = createTextSprite("Decoder", "#ffffff");
|
| 1540 |
+
decoderLabel.position.set(decoder.position.x, decoder.position.y + 1.5, decoder.position.z);
|
| 1541 |
+
scene.add(decoderLabel);
|
| 1542 |
+
|
| 1543 |
+
const segmentationLabel = createTextSprite("Segmentation", "#ffffff");
|
| 1544 |
+
segmentationLabel.position.set(segmentation.position.x, segmentation.position.y - 1.5, segmentation.position.z);
|
| 1545 |
+
scene.add(segmentationLabel);
|
| 1546 |
+
|
| 1547 |
+
const outputCaptionLabel = createTextSprite("Caption", "#ffffff");
|
| 1548 |
+
outputCaptionLabel.position.set(outputCaption.position.x, outputCaption.position.y + 0.8, outputCaption.position.z);
|
| 1549 |
+
scene.add(outputCaptionLabel);
|
| 1550 |
+
|
| 1551 |
+
const outputSegmentationLabel = createTextSprite("Masks", "#ffffff");
|
| 1552 |
+
outputSegmentationLabel.position.set(outputSegmentation.position.x, outputSegmentation.position.y - 0.8, outputSegmentation.position.z);
|
| 1553 |
+
scene.add(outputSegmentationLabel);
|
| 1554 |
+
|
| 1555 |
+
// Inside the showArchitectureDetails function
|
| 1556 |
+
|
| 1557 |
+
// Set canvas size and hide loading text after all elements are potentially rendered
|
| 1558 |
+
setTimeout(() => {
|
| 1559 |
+
// Ensure the container is ready and has dimensions
|
| 1560 |
+
const canvasContainer = document.getElementById('architectureCanvasContainer');
|
| 1561 |
+
const loadingText = document.getElementById('loadingText');
|
| 1562 |
+
|
| 1563 |
+
if (canvasContainer && canvasContainer.clientWidth > 0) {
|
| 1564 |
+
const width = canvasContainer.clientWidth;
|
| 1565 |
+
const height = canvasContainer.clientHeight;
|
| 1566 |
+
|
| 1567 |
+
renderer.setSize(width, height);
|
| 1568 |
+
camera.aspect = width / height;
|
| 1569 |
+
camera.updateProjectionMatrix();
|
| 1570 |
+
|
| 1571 |
+
// Hide the loading text now that the canvas is sized
|
| 1572 |
+
if (loadingText) {
|
| 1573 |
+
loadingText.style.display = 'none';
|
| 1574 |
+
}
|
| 1575 |
+
|
| 1576 |
+
// Start the animation loop
|
| 1577 |
+
animate();
|
| 1578 |
+
} else {
|
| 1579 |
+
// Fallback or error for if the container isn't ready
|
| 1580 |
+
console.error("3D canvas container not ready or has no size.");
|
| 1581 |
+
if (loadingText) {
|
| 1582 |
+
loadingText.innerText = "Error loading 3D model.";
|
| 1583 |
+
}
|
| 1584 |
+
}
|
| 1585 |
+
}, 100); // 100ms delay to allow the DOM to render the modal
|
| 1586 |
+
|
| 1587 |
+
|
| 1588 |
+
// 6. Animation Loop
|
| 1589 |
+
function animate() {
|
| 1590 |
+
animationFrameId = requestAnimationFrame(animate);
|
| 1591 |
+
controls.update(); // only required if controls.enableDamping or controls.autoRotate are set to true
|
| 1592 |
+
renderer.render(scene, camera);
|
| 1593 |
+
}
|
| 1594 |
+
|
| 1595 |
+
// Cleanup function for modal close
|
| 1596 |
+
const closeModal = () => {
|
| 1597 |
+
cancelAnimationFrame(animationFrameId); // Stop the animation loop
|
| 1598 |
+
if (controls) controls.dispose(); // Dispose controls to free up event listeners
|
| 1599 |
+
if (renderer) renderer.dispose(); // Dispose renderer resources
|
| 1600 |
+
modal.remove(); // Remove modal from DOM
|
| 1601 |
+
window.removeEventListener('resize', setCanvasSize); // Remove resize listener
|
| 1602 |
+
// Clear scene to free up memory (optional but good practice)
|
| 1603 |
+
scene.traverse(object => {
|
| 1604 |
+
if (!object.isMesh) return;
|
| 1605 |
+
object.geometry.dispose();
|
| 1606 |
+
if (object.material.isMaterial) {
|
| 1607 |
+
cleanMaterial(object.material);
|
| 1608 |
+
} else {
|
| 1609 |
+
// an array of materials
|
| 1610 |
+
for (const material of object.material) cleanMaterial(material);
|
| 1611 |
+
}
|
| 1612 |
+
});
|
| 1613 |
+
scene = null;
|
| 1614 |
+
camera = null;
|
| 1615 |
+
renderer = null;
|
| 1616 |
+
controls = null;
|
| 1617 |
+
animationFrameId = null;
|
| 1618 |
+
};
|
| 1619 |
+
|
| 1620 |
+
document.getElementById('closeModalBtn').addEventListener('click', closeModal);
|
| 1621 |
+
modal.addEventListener('click', (e) => {
|
| 1622 |
+
if (e.target === modal) { // Close when clicking outside the inner content
|
| 1623 |
+
closeModal();
|
| 1624 |
+
}
|
| 1625 |
+
});
|
| 1626 |
+
|
| 1627 |
+
const setCanvasSize = () => {
|
| 1628 |
+
if (canvasContainer && camera && renderer) {
|
| 1629 |
+
const width = canvasContainer.clientWidth;
|
| 1630 |
+
const height = canvasContainer.clientHeight;
|
| 1631 |
+
renderer.setSize(width, height);
|
| 1632 |
+
camera.aspect = width / height;
|
| 1633 |
+
camera.updateProjectionMatrix();
|
| 1634 |
+
}
|
| 1635 |
+
};
|
| 1636 |
+
window.addEventListener('resize', setCanvasSize);
|
| 1637 |
+
}
|
| 1638 |
+
|
| 1639 |
+
// Helper to dispose materials (for cleanup)
|
| 1640 |
+
function cleanMaterial(material) {
|
| 1641 |
+
for (const key of Object.keys(material)) {
|
| 1642 |
+
const value = material[key];
|
| 1643 |
+
if (value && typeof value === 'object' && 'dispose' in value) {
|
| 1644 |
+
value.dispose();
|
| 1645 |
+
}
|
| 1646 |
+
}
|
| 1647 |
+
}
|
| 1648 |
+
|
| 1649 |
+
|
| 1650 |
+
// Network node hover effects (Existing)
|
| 1651 |
+
document.querySelectorAll('.network-node').forEach(node => {
|
| 1652 |
+
node.addEventListener('mouseenter', function() {
|
| 1653 |
+
const info = this.getAttribute('data-info');
|
| 1654 |
+
if (info) {
|
| 1655 |
+
const tooltip = document.createElement('div');
|
| 1656 |
+
tooltip.style.cssText = `
|
| 1657 |
+
position: absolute;
|
| 1658 |
+
background: rgba(0,0,0,0.9);
|
| 1659 |
+
color: white;
|
| 1660 |
+
padding: 1rem;
|
| 1661 |
+
border-radius: 8px;
|
| 1662 |
+
font-size: 0.9rem;
|
| 1663 |
+
max-width: 200px;
|
| 1664 |
+
z-index: 1000;
|
| 1665 |
+
top: -60px;
|
| 1666 |
+
left: 50%;
|
| 1667 |
+
transform: translateX(-50%);
|
| 1668 |
+
pointer-events: none;
|
| 1669 |
+
`;
|
| 1670 |
+
tooltip.textContent = info;
|
| 1671 |
+
tooltip.className = 'tooltip';
|
| 1672 |
+
this.style.position = 'relative';
|
| 1673 |
+
this.appendChild(tooltip);
|
| 1674 |
+
}
|
| 1675 |
+
});
|
| 1676 |
+
|
| 1677 |
+
node.addEventListener('mouseleave', function() {
|
| 1678 |
+
const tooltip = this.querySelector('.tooltip');
|
| 1679 |
+
if (tooltip) {
|
| 1680 |
+
tooltip.remove();
|
| 1681 |
+
}
|
| 1682 |
+
});
|
| 1683 |
+
});
|
| 1684 |
+
|
| 1685 |
+
// Initialize animations (Existing)
|
| 1686 |
+
document.addEventListener('DOMContentLoaded', function() {
|
| 1687 |
+
animateMetrics();
|
| 1688 |
+
|
| 1689 |
+
// Add pulse animation to CTA buttons
|
| 1690 |
+
document.querySelectorAll('.btn-primary').forEach(btn => {
|
| 1691 |
+
setInterval(() => {
|
| 1692 |
+
btn.classList.add('pulse');
|
| 1693 |
+
setTimeout(() => btn.classList.remove('pulse'), 1000);
|
| 1694 |
+
}, 5000);
|
| 1695 |
+
});
|
| 1696 |
+
});
|
| 1697 |
+
|
| 1698 |
+
// Add particle animation to hero section (Existing)
|
| 1699 |
+
function createParticles() {
|
| 1700 |
+
const hero = document.querySelector('.hero');
|
| 1701 |
+
for (let i = 0; i < 50; i++) {
|
| 1702 |
+
const particle = document.createElement('div');
|
| 1703 |
+
particle.style.cssText = `
|
| 1704 |
+
position: absolute;
|
| 1705 |
+
width: 2px;
|
| 1706 |
+
height: 2px;
|
| 1707 |
+
background: rgba(255,255,255,0.5);
|
| 1708 |
+
border-radius: 50%;
|
| 1709 |
+
left: ${Math.random() * 100}%;
|
| 1710 |
+
top: ${Math.random() * 100}%;
|
| 1711 |
+
animation: float ${5 + Math.random() * 10}s infinite linear;
|
| 1712 |
+
pointer-events: none;
|
| 1713 |
+
`;
|
| 1714 |
+
hero.appendChild(particle);
|
| 1715 |
+
}
|
| 1716 |
+
}
|
| 1717 |
+
|
| 1718 |
+
// Initialize particle animation (Existing)
|
| 1719 |
+
createParticles();
|
| 1720 |
+
|
| 1721 |
+
// Add typing effect to hero text (Existing)
|
| 1722 |
+
function typeWriter(element, text, speed = 50) {
|
| 1723 |
+
let i = 0;
|
| 1724 |
+
element.innerHTML = '';
|
| 1725 |
+
function typing() {
|
| 1726 |
+
if (i < text.length) {
|
| 1727 |
+
element.innerHTML += text.charAt(i);
|
| 1728 |
+
i++;
|
| 1729 |
+
setTimeout(typing, speed);
|
| 1730 |
+
}
|
| 1731 |
+
}
|
| 1732 |
+
typing();
|
| 1733 |
+
}
|
| 1734 |
+
|
| 1735 |
+
// Mobile menu toggle (if needed) (Existing)
|
| 1736 |
+
function toggleMobileMenu() {
|
| 1737 |
+
const navLinks = document.querySelector('.nav-links');
|
| 1738 |
+
navLinks.classList.toggle('active');
|
| 1739 |
+
}
|
| 1740 |
+
|
| 1741 |
+
// Add mobile styles (already in your original HTML, moved to style tag) (Existing)
|
| 1742 |
+
const mobileStyles = document.createElement('style');
|
| 1743 |
+
mobileStyles.textContent = `
|
| 1744 |
+
@media (max-width: 768px) {
|
| 1745 |
+
.nav-links.active {
|
| 1746 |
+
display: flex;
|
| 1747 |
+
flex-direction: column;
|
| 1748 |
+
position: absolute;
|
| 1749 |
+
top: 100%;
|
| 1750 |
+
left: 0;
|
| 1751 |
+
width: 100%;
|
| 1752 |
+
background: rgba(0,0,0,0.9);
|
| 1753 |
+
padding: 2rem;
|
| 1754 |
+
backdrop-filter: blur(20px);
|
| 1755 |
+
}
|
| 1756 |
+
|
| 1757 |
+
.nav-links.active a {
|
| 1758 |
+
padding: 1rem 0;
|
| 1759 |
+
border-bottom: 1px solid rgba(255,255,255,0.1);
|
| 1760 |
+
}
|
| 1761 |
+
}
|
| 1762 |
+
`;
|
| 1763 |
+
document.head.appendChild(mobileStyles);
|
| 1764 |
+
</script>
|
| 1765 |
+
</body>
|
| 1766 |
+
</html>
|
text_files/bleu_metrics.csv
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Epoch,BLEU-4
|
| 2 |
+
1,0.0836
|
| 3 |
+
2,0.0923
|
| 4 |
+
3,0.0986
|
| 5 |
+
4,0.0996
|
| 6 |
+
5,0.1011
|
| 7 |
+
6,0.1009
|
| 8 |
+
7,0.1028
|
| 9 |
+
8,0.1029
|
| 10 |
+
10,0.1032
|
| 11 |
+
11,0.1024
|
| 12 |
+
12,0.1011
|
| 13 |
+
13,0.1028
|
| 14 |
+
14,0.1034
|
| 15 |
+
15,0.1042
|
| 16 |
+
16,0.1047
|
| 17 |
+
17,0.1035
|
| 18 |
+
18,0.1054
|
| 19 |
+
19,0.1053
|
| 20 |
+
20,0.1058
|
| 21 |
+
21,0.105
|
| 22 |
+
22,0.1049
|
| 23 |
+
23,0.1051
|
| 24 |
+
24,0.1056
|
| 25 |
+
25,0.1028
|
| 26 |
+
26,0.1031
|
| 27 |
+
27,0.1046
|
| 28 |
+
28,0.1039
|
| 29 |
+
29,0.1032
|
| 30 |
+
30,0.1039
|
text_files/file.py
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import re
|
| 2 |
+
import pandas as pd
|
| 3 |
+
import os
|
| 4 |
+
|
| 5 |
+
# Define a list of your log file names
|
| 6 |
+
log_files = [
|
| 7 |
+
'training (2).txt',
|
| 8 |
+
'training_log_1_18.txt',
|
| 9 |
+
'training_log_17_27.txt',
|
| 10 |
+
'training_log_21_30.txt'
|
| 11 |
+
|
| 12 |
+
]
|
| 13 |
+
|
| 14 |
+
# Create an empty list to store parsed data
|
| 15 |
+
parsed_data = []
|
| 16 |
+
|
| 17 |
+
# Regex to capture Epoch, Step, Loss, and Perplexity
|
| 18 |
+
# This regex looks for lines containing 'Epoch [X/Y], Step [A/B], Loss: V, Perplexity: W'
|
| 19 |
+
log_pattern = re.compile(
|
| 20 |
+
r"Epoch\s\[(\d+)/\d+\],\sStep\s\[(\d+)/\d+\],\sLoss:\s([\d.]+),\sPerplexity:\s([\d.]+)"
|
| 21 |
+
)
|
| 22 |
+
|
| 23 |
+
print("Starting log parsing...")
|
| 24 |
+
|
| 25 |
+
# Loop through each log file
|
| 26 |
+
for file_name in log_files:
|
| 27 |
+
if not os.path.exists(file_name):
|
| 28 |
+
print(f"Warning: File not found - {file_name}. Skipping.")
|
| 29 |
+
continue
|
| 30 |
+
|
| 31 |
+
print(f"Processing {file_name}...")
|
| 32 |
+
# with open(file_name, 'r') as f:
|
| 33 |
+
with open(file_name, 'r', encoding='utf-8') as f:
|
| 34 |
+
for line in f:
|
| 35 |
+
match = log_pattern.search(line)
|
| 36 |
+
if match:
|
| 37 |
+
# Extracting values. Group 1: Epoch, Group 2: Step, Group 3: Loss, Group 4: Perplexity
|
| 38 |
+
epoch = int(match.group(1))
|
| 39 |
+
step = int(match.group(2))
|
| 40 |
+
loss = float(match.group(3))
|
| 41 |
+
perplexity = float(match.group(4)) # Correctly assigned to 'perplexity'
|
| 42 |
+
|
| 43 |
+
# Append to our list of dictionaries
|
| 44 |
+
parsed_data.append({
|
| 45 |
+
'Epoch': epoch,
|
| 46 |
+
'Step': step,
|
| 47 |
+
'Loss': loss,
|
| 48 |
+
'Perplexity': perplexity # Ensure this key matches the variable name
|
| 49 |
+
})
|
| 50 |
+
|
| 51 |
+
# Create a Pandas DataFrame from the parsed data
|
| 52 |
+
df = pd.DataFrame(parsed_data)
|
| 53 |
+
|
| 54 |
+
# Sort the data by Epoch and Step to ensure correct chronological order
|
| 55 |
+
df_sorted = df.sort_values(by=['Epoch', 'Step']).reset_index(drop=True)
|
| 56 |
+
|
| 57 |
+
# Save the DataFrame to a CSV file
|
| 58 |
+
output_csv_file = 'training_metrics.csv'
|
| 59 |
+
df_sorted.to_csv(output_csv_file, index=False)
|
| 60 |
+
|
| 61 |
+
print(f"\nSuccessfully parsed logs and saved data to {output_csv_file}")
|
| 62 |
+
print("You can now import this CSV file into Power BI to create your visualizations.")
|
| 63 |
+
print("\nFirst few rows of the generated CSV:")
|
| 64 |
+
print(df_sorted.head())
|
text_files/scores.py
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import re
|
| 2 |
+
import pandas as pd
|
| 3 |
+
import os
|
| 4 |
+
|
| 5 |
+
# Define a list of your log file names
|
| 6 |
+
log_files = [
|
| 7 |
+
'training (2).txt',
|
| 8 |
+
'training_log_1_18.txt',
|
| 9 |
+
'training_log_17_27.txt',
|
| 10 |
+
'training_log_21_30.txt'
|
| 11 |
+
|
| 12 |
+
]
|
| 13 |
+
|
| 14 |
+
# Create an empty list to store parsed BLEU data
|
| 15 |
+
bleu_data = []
|
| 16 |
+
|
| 17 |
+
# Regex to capture the Epoch number from training progress lines
|
| 18 |
+
epoch_pattern = re.compile(r"Epoch\s\[(\d+)/\d+],")
|
| 19 |
+
|
| 20 |
+
# Regex to capture the BLEU-4 score
|
| 21 |
+
bleu_pattern = re.compile(r"Validation BLEU-4:\s([\d.]+)")
|
| 22 |
+
|
| 23 |
+
current_epoch = None # Variable to keep track of the current epoch
|
| 24 |
+
|
| 25 |
+
print("Starting BLEU score parsing...")
|
| 26 |
+
|
| 27 |
+
# Loop through each log file
|
| 28 |
+
for file_name in log_files:
|
| 29 |
+
if not os.path.exists(file_name):
|
| 30 |
+
print(f"Warning: File not found - {file_name}. Skipping.")
|
| 31 |
+
continue
|
| 32 |
+
|
| 33 |
+
print(f"Processing {file_name} for BLEU scores...")
|
| 34 |
+
with open(file_name, 'r', encoding='utf-8') as f: # Use UTF-8 encoding
|
| 35 |
+
for line in f:
|
| 36 |
+
# Check for epoch line first to update current_epoch
|
| 37 |
+
epoch_match = epoch_pattern.search(line)
|
| 38 |
+
if epoch_match:
|
| 39 |
+
current_epoch = int(epoch_match.group(1))
|
| 40 |
+
|
| 41 |
+
# Check for BLEU score line
|
| 42 |
+
bleu_match = bleu_pattern.search(line)
|
| 43 |
+
if bleu_match:
|
| 44 |
+
bleu_score = float(bleu_match.group(1))
|
| 45 |
+
|
| 46 |
+
# Only add if we have an associated epoch
|
| 47 |
+
if current_epoch is not None:
|
| 48 |
+
bleu_data.append({
|
| 49 |
+
'Epoch': current_epoch,
|
| 50 |
+
'BLEU-4': bleu_score
|
| 51 |
+
})
|
| 52 |
+
else:
|
| 53 |
+
print(f"Warning: Found BLEU score ({bleu_score}) without a preceding epoch in {file_name}. Skipping this entry.")
|
| 54 |
+
|
| 55 |
+
# Create a Pandas DataFrame from the parsed BLEU data
|
| 56 |
+
df_bleu = pd.DataFrame(bleu_data)
|
| 57 |
+
|
| 58 |
+
# Remove duplicate entries for the same epoch if multiple BLEU scores are logged per epoch
|
| 59 |
+
# (e.g., if validation runs multiple times, take the last one or average, here we take the last one)
|
| 60 |
+
df_bleu_unique = df_bleu.drop_duplicates(subset=['Epoch'], keep='last')
|
| 61 |
+
|
| 62 |
+
# Sort the data by Epoch
|
| 63 |
+
df_bleu_sorted = df_bleu_unique.sort_values(by=['Epoch']).reset_index(drop=True)
|
| 64 |
+
|
| 65 |
+
# Save the DataFrame to a CSV file
|
| 66 |
+
output_csv_file = 'bleu_metrics.csv'
|
| 67 |
+
df_bleu_sorted.to_csv(output_csv_file, index=False)
|
| 68 |
+
|
| 69 |
+
print(f"\nSuccessfully parsed BLEU scores and saved data to {output_csv_file}")
|
| 70 |
+
print("You can now import this CSV file into Power BI to create your BLEU score visualizations.")
|
| 71 |
+
print("\nFirst few rows of the generated BLEU CSV:")
|
| 72 |
+
print(df_bleu_sorted.head())
|
text_files/training (2).txt
ADDED
|
@@ -0,0 +1,335 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
2025-06-05 09:14:36,398 - __main__ - INFO -
|
| 2 |
+
--- Starting Model Training ---
|
| 3 |
+
2025-06-05 09:14:36,399 - __main__ - INFO - Starting training process...
|
| 4 |
+
2025-06-05 09:14:36,400 - __main__ - INFO - Using device: cuda
|
| 5 |
+
2025-06-05 09:14:36,405 - __main__ - INFO - Initializing training dataset for vocabulary building...
|
| 6 |
+
2025-06-05 09:14:37,522 - __main__ - INFO - Successfully loaded captions from /kaggle/input/coco-2017-dataset/coco2017/annotations/captions_train2017.json
|
| 7 |
+
2025-06-05 09:17:31,012 - __main__ - INFO -
|
| 8 |
+
--- Starting Model Training ---
|
| 9 |
+
2025-06-05 09:17:31,013 - __main__ - INFO - Starting training process...
|
| 10 |
+
2025-06-05 09:17:31,014 - __main__ - INFO - Using device: cuda
|
| 11 |
+
2025-06-05 09:17:31,088 - __main__ - INFO - Loaded vocabulary from /kaggle/input/vocabulary_s/pytorch/default/1/vocabulary.pkl
|
| 12 |
+
2025-06-05 09:17:32,171 - __main__ - INFO - Successfully loaded captions from /kaggle/input/coco-2017-dataset/coco2017/annotations/captions_train2017.json
|
| 13 |
+
2025-06-05 09:23:17,287 - __main__ - INFO - Using subset of 200000 samples for the dataset.
|
| 14 |
+
2025-06-05 09:23:17,288 - __main__ - INFO - Dataset size after filtering: 200000 samples.
|
| 15 |
+
2025-06-05 09:23:17,386 - __main__ - INFO - Successfully loaded captions from /kaggle/input/coco-2017-dataset/coco2017/annotations/captions_val2017.json
|
| 16 |
+
2025-06-05 09:23:33,589 - __main__ - INFO - Dataset size after filtering: 25014 samples.
|
| 17 |
+
2025-06-05 09:23:33,590 - __main__ - INFO - Training dataset size: 200000
|
| 18 |
+
2025-06-05 09:23:33,591 - __main__ - INFO - Validation dataset size: 25014
|
| 19 |
+
2025-06-05 09:23:34,957 - __main__ - INFO - ResNet encoder base layers are fine-tuning enabled.
|
| 20 |
+
2025-06-05 09:23:35,415 - __main__ - INFO - No checkpoint found. Starting training from scratch.
|
| 21 |
+
2025-06-05 09:25:12,222 - __main__ - INFO - Epoch [1/9], Step [100/3125], Loss: 5.4706, Perplexity: 237.6090
|
| 22 |
+
2025-06-05 09:26:45,054 - __main__ - INFO - Epoch [1/9], Step [200/3125], Loss: 5.1889, Perplexity: 179.2651
|
| 23 |
+
2025-06-05 09:28:17,121 - __main__ - INFO - Epoch [1/9], Step [300/3125], Loss: 4.7951, Perplexity: 120.9148
|
| 24 |
+
2025-06-05 09:29:49,844 - __main__ - INFO - Epoch [1/9], Step [400/3125], Loss: 4.1438, Perplexity: 63.0419
|
| 25 |
+
2025-06-05 09:31:22,479 - __main__ - INFO - Epoch [1/9], Step [500/3125], Loss: 4.0644, Perplexity: 58.2316
|
| 26 |
+
2025-06-05 09:32:55,263 - __main__ - INFO - Epoch [1/9], Step [600/3125], Loss: 4.1386, Perplexity: 62.7179
|
| 27 |
+
2025-06-05 09:34:28,639 - __main__ - INFO - Epoch [1/9], Step [700/3125], Loss: 4.4148, Perplexity: 82.6655
|
| 28 |
+
2025-06-05 09:36:01,562 - __main__ - INFO - Epoch [1/9], Step [800/3125], Loss: 4.0775, Perplexity: 58.9954
|
| 29 |
+
2025-06-05 09:37:34,470 - __main__ - INFO - Epoch [1/9], Step [900/3125], Loss: 3.8928, Perplexity: 49.0485
|
| 30 |
+
2025-06-05 09:39:07,144 - __main__ - INFO - Epoch [1/9], Step [1000/3125], Loss: 3.7069, Perplexity: 40.7267
|
| 31 |
+
2025-06-05 09:40:39,832 - __main__ - INFO - Epoch [1/9], Step [1100/3125], Loss: 3.7165, Perplexity: 41.1201
|
| 32 |
+
2025-06-05 09:42:12,245 - __main__ - INFO - Epoch [1/9], Step [1200/3125], Loss: 3.6987, Perplexity: 40.3960
|
| 33 |
+
2025-06-05 09:43:44,664 - __main__ - INFO - Epoch [1/9], Step [1300/3125], Loss: 3.8443, Perplexity: 46.7262
|
| 34 |
+
2025-06-05 09:45:16,983 - __main__ - INFO - Epoch [1/9], Step [1400/3125], Loss: 3.7788, Perplexity: 43.7654
|
| 35 |
+
2025-06-05 09:46:49,549 - __main__ - INFO - Epoch [1/9], Step [1500/3125], Loss: 3.9427, Perplexity: 51.5586
|
| 36 |
+
2025-06-05 09:48:22,306 - __main__ - INFO - Epoch [1/9], Step [1600/3125], Loss: 3.9204, Perplexity: 50.4209
|
| 37 |
+
2025-06-05 09:49:55,016 - __main__ - INFO - Epoch [1/9], Step [1700/3125], Loss: 3.6418, Perplexity: 38.1600
|
| 38 |
+
2025-06-05 09:51:27,127 - __main__ - INFO - Epoch [1/9], Step [1800/3125], Loss: 3.5172, Perplexity: 33.6913
|
| 39 |
+
2025-06-05 09:52:59,489 - __main__ - INFO - Epoch [1/9], Step [1900/3125], Loss: 3.6409, Perplexity: 38.1244
|
| 40 |
+
2025-06-05 09:54:31,921 - __main__ - INFO - Epoch [1/9], Step [2000/3125], Loss: 3.2969, Perplexity: 27.0292
|
| 41 |
+
2025-06-05 09:56:04,383 - __main__ - INFO - Epoch [1/9], Step [2100/3125], Loss: 3.4517, Perplexity: 31.5544
|
| 42 |
+
2025-06-05 09:57:36,919 - __main__ - INFO - Epoch [1/9], Step [2200/3125], Loss: 3.4920, Perplexity: 32.8529
|
| 43 |
+
2025-06-05 09:59:10,022 - __main__ - INFO - Epoch [1/9], Step [2300/3125], Loss: 3.7028, Perplexity: 40.5603
|
| 44 |
+
2025-06-05 10:00:42,264 - __main__ - INFO - Epoch [1/9], Step [2400/3125], Loss: 3.6794, Perplexity: 39.6238
|
| 45 |
+
2025-06-05 10:02:14,437 - __main__ - INFO - Epoch [1/9], Step [2500/3125], Loss: 3.4977, Perplexity: 33.0382
|
| 46 |
+
2025-06-05 10:03:47,338 - __main__ - INFO - Epoch [1/9], Step [2600/3125], Loss: 3.4883, Perplexity: 32.7311
|
| 47 |
+
2025-06-05 10:05:20,077 - __main__ - INFO - Epoch [1/9], Step [2700/3125], Loss: 3.4596, Perplexity: 31.8036
|
| 48 |
+
2025-06-05 10:06:52,363 - __main__ - INFO - Epoch [1/9], Step [2800/3125], Loss: 3.4043, Perplexity: 30.0920
|
| 49 |
+
2025-06-05 10:08:24,721 - __main__ - INFO - Epoch [1/9], Step [2900/3125], Loss: 3.1842, Perplexity: 24.1488
|
| 50 |
+
2025-06-05 10:09:56,919 - __main__ - INFO - Epoch [1/9], Step [3000/3125], Loss: 3.2843, Perplexity: 26.6914
|
| 51 |
+
2025-06-05 10:11:29,066 - __main__ - INFO - Epoch [1/9], Step [3100/3125], Loss: 3.1950, Perplexity: 24.4100
|
| 52 |
+
2025-06-05 10:11:52,259 - __main__ - INFO - Epoch 1 Training finished. Avg Loss: 3.8943, Time: 2896.84s
|
| 53 |
+
2025-06-05 10:24:31,901 - __main__ - INFO - Validation Avg Loss: 3.1313, Perplexity: 22.9038
|
| 54 |
+
2025-06-05 10:24:44,857 - __main__ - INFO - Validation BLEU-4: 0.0836
|
| 55 |
+
2025-06-05 10:24:45,632 - __main__ - INFO - Saved best model checkpoint to ./output/best_model_bleu0.0836.pth
|
| 56 |
+
2025-06-05 10:24:45,633 - __main__ - INFO - Performing memory optimization after epoch...
|
| 57 |
+
2025-06-05 10:24:45,924 - __main__ - INFO - CUDA cache emptied.
|
| 58 |
+
2025-06-05 10:24:46,199 - __main__ - INFO - Python garbage collector run.
|
| 59 |
+
2025-06-05 10:26:22,213 - __main__ - INFO - Epoch [2/9], Step [100/3125], Loss: 3.1401, Perplexity: 23.1065
|
| 60 |
+
2025-06-05 10:27:55,157 - __main__ - INFO - Epoch [2/9], Step [200/3125], Loss: 3.0563, Perplexity: 21.2493
|
| 61 |
+
2025-06-05 10:29:27,968 - __main__ - INFO - Epoch [2/9], Step [300/3125], Loss: 3.2782, Perplexity: 26.5282
|
| 62 |
+
2025-06-05 10:31:00,270 - __main__ - INFO - Epoch [2/9], Step [400/3125], Loss: 3.1834, Perplexity: 24.1295
|
| 63 |
+
2025-06-05 10:32:33,440 - __main__ - INFO - Epoch [2/9], Step [500/3125], Loss: 3.3472, Perplexity: 28.4244
|
| 64 |
+
2025-06-05 10:34:06,422 - __main__ - INFO - Epoch [2/9], Step [600/3125], Loss: 3.1609, Perplexity: 23.5928
|
| 65 |
+
2025-06-05 10:35:39,261 - __main__ - INFO - Epoch [2/9], Step [700/3125], Loss: 2.9984, Perplexity: 20.0538
|
| 66 |
+
2025-06-05 10:37:11,706 - __main__ - INFO - Epoch [2/9], Step [800/3125], Loss: 3.2494, Perplexity: 25.7758
|
| 67 |
+
2025-06-05 10:38:44,368 - __main__ - INFO - Epoch [2/9], Step [900/3125], Loss: 3.1955, Perplexity: 24.4232
|
| 68 |
+
2025-06-05 10:40:17,199 - __main__ - INFO - Epoch [2/9], Step [1000/3125], Loss: 3.4101, Perplexity: 30.2673
|
| 69 |
+
2025-06-05 10:41:49,573 - __main__ - INFO - Epoch [2/9], Step [1100/3125], Loss: 3.3706, Perplexity: 29.0971
|
| 70 |
+
2025-06-05 10:43:21,777 - __main__ - INFO - Epoch [2/9], Step [1200/3125], Loss: 3.1680, Perplexity: 23.7608
|
| 71 |
+
2025-06-05 10:44:54,540 - __main__ - INFO - Epoch [2/9], Step [1300/3125], Loss: 3.0362, Perplexity: 20.8251
|
| 72 |
+
2025-06-05 10:46:27,295 - __main__ - INFO - Epoch [2/9], Step [1400/3125], Loss: 3.0925, Perplexity: 22.0321
|
| 73 |
+
2025-06-05 10:47:59,572 - __main__ - INFO - Epoch [2/9], Step [1500/3125], Loss: 3.1057, Perplexity: 22.3241
|
| 74 |
+
2025-06-05 10:49:32,053 - __main__ - INFO - Epoch [2/9], Step [1600/3125], Loss: 3.3277, Perplexity: 27.8730
|
| 75 |
+
2025-06-05 10:51:04,671 - __main__ - INFO - Epoch [2/9], Step [1700/3125], Loss: 3.1610, Perplexity: 23.5945
|
| 76 |
+
2025-06-05 10:52:37,560 - __main__ - INFO - Epoch [2/9], Step [1800/3125], Loss: 3.2718, Perplexity: 26.3582
|
| 77 |
+
2025-06-05 10:54:10,358 - __main__ - INFO - Epoch [2/9], Step [1900/3125], Loss: 3.1425, Perplexity: 23.1612
|
| 78 |
+
2025-06-05 10:55:43,281 - __main__ - INFO - Epoch [2/9], Step [2000/3125], Loss: 3.0522, Perplexity: 21.1619
|
| 79 |
+
2025-06-05 10:57:15,767 - __main__ - INFO - Epoch [2/9], Step [2100/3125], Loss: 2.9711, Perplexity: 19.5126
|
| 80 |
+
2025-06-05 10:58:48,072 - __main__ - INFO - Epoch [2/9], Step [2200/3125], Loss: 3.0638, Perplexity: 21.4079
|
| 81 |
+
2025-06-05 11:00:20,322 - __main__ - INFO - Epoch [2/9], Step [2300/3125], Loss: 3.1867, Perplexity: 24.2093
|
| 82 |
+
2025-06-05 11:01:53,270 - __main__ - INFO - Epoch [2/9], Step [2400/3125], Loss: 3.0060, Perplexity: 20.2070
|
| 83 |
+
2025-06-05 11:03:25,315 - __main__ - INFO - Epoch [2/9], Step [2500/3125], Loss: 3.1718, Perplexity: 23.8494
|
| 84 |
+
2025-06-05 11:04:57,298 - __main__ - INFO - Epoch [2/9], Step [2600/3125], Loss: 3.0628, Perplexity: 21.3874
|
| 85 |
+
2025-06-05 11:06:29,658 - __main__ - INFO - Epoch [2/9], Step [2700/3125], Loss: 3.3898, Perplexity: 29.6609
|
| 86 |
+
2025-06-05 11:08:01,931 - __main__ - INFO - Epoch [2/9], Step [2800/3125], Loss: 2.7914, Perplexity: 16.3038
|
| 87 |
+
2025-06-05 11:09:34,397 - __main__ - INFO - Epoch [2/9], Step [2900/3125], Loss: 2.8758, Perplexity: 17.7403
|
| 88 |
+
2025-06-05 11:11:06,755 - __main__ - INFO - Epoch [2/9], Step [3000/3125], Loss: 3.0766, Perplexity: 21.6847
|
| 89 |
+
2025-06-05 11:12:39,179 - __main__ - INFO - Epoch [2/9], Step [3100/3125], Loss: 3.0787, Perplexity: 21.7303
|
| 90 |
+
2025-06-05 11:13:02,556 - __main__ - INFO - Epoch 2 Training finished. Avg Loss: 3.1318, Time: 2896.36s
|
| 91 |
+
2025-06-05 11:25:51,359 - __main__ - INFO - Validation Avg Loss: 2.8683, Perplexity: 17.6076
|
| 92 |
+
2025-06-05 11:26:01,678 - __main__ - INFO - Validation BLEU-4: 0.0923
|
| 93 |
+
2025-06-05 11:26:02,402 - __main__ - INFO - Saved best model checkpoint to ./output/best_model_bleu0.0923.pth
|
| 94 |
+
2025-06-05 11:26:02,404 - __main__ - INFO - Performing memory optimization after epoch...
|
| 95 |
+
2025-06-05 11:26:02,690 - __main__ - INFO - CUDA cache emptied.
|
| 96 |
+
2025-06-05 11:26:03,026 - __main__ - INFO - Python garbage collector run.
|
| 97 |
+
2025-06-05 11:27:38,287 - __main__ - INFO - Epoch [3/9], Step [100/3125], Loss: 3.1375, Perplexity: 23.0468
|
| 98 |
+
2025-06-05 11:29:10,992 - __main__ - INFO - Epoch [3/9], Step [200/3125], Loss: 2.9503, Perplexity: 19.1119
|
| 99 |
+
2025-06-05 11:30:43,374 - __main__ - INFO - Epoch [3/9], Step [300/3125], Loss: 2.9096, Perplexity: 18.3486
|
| 100 |
+
2025-06-05 11:32:15,961 - __main__ - INFO - Epoch [3/9], Step [400/3125], Loss: 2.9213, Perplexity: 18.5648
|
| 101 |
+
2025-06-05 11:33:48,692 - __main__ - INFO - Epoch [3/9], Step [500/3125], Loss: 2.7807, Perplexity: 16.1304
|
| 102 |
+
2025-06-05 11:35:21,035 - __main__ - INFO - Epoch [3/9], Step [600/3125], Loss: 2.9757, Perplexity: 19.6029
|
| 103 |
+
2025-06-05 11:36:53,722 - __main__ - INFO - Epoch [3/9], Step [700/3125], Loss: 2.7691, Perplexity: 15.9448
|
| 104 |
+
2025-06-05 11:38:26,136 - __main__ - INFO - Epoch [3/9], Step [800/3125], Loss: 2.6290, Perplexity: 13.8597
|
| 105 |
+
2025-06-05 11:39:58,718 - __main__ - INFO - Epoch [3/9], Step [900/3125], Loss: 2.7852, Perplexity: 16.2028
|
| 106 |
+
2025-06-05 11:41:31,263 - __main__ - INFO - Epoch [3/9], Step [1000/3125], Loss: 2.9282, Perplexity: 18.6934
|
| 107 |
+
2025-06-05 11:43:04,789 - __main__ - INFO - Epoch [3/9], Step [1100/3125], Loss: 3.0185, Perplexity: 20.4607
|
| 108 |
+
2025-06-05 11:44:37,274 - __main__ - INFO - Epoch [3/9], Step [1200/3125], Loss: 3.1393, Perplexity: 23.0879
|
| 109 |
+
2025-06-05 11:46:10,068 - __main__ - INFO - Epoch [3/9], Step [1300/3125], Loss: 2.9986, Perplexity: 20.0580
|
| 110 |
+
2025-06-05 11:47:42,373 - __main__ - INFO - Epoch [3/9], Step [1400/3125], Loss: 2.8490, Perplexity: 17.2704
|
| 111 |
+
2025-06-05 11:49:14,841 - __main__ - INFO - Epoch [3/9], Step [1500/3125], Loss: 3.1596, Perplexity: 23.5610
|
| 112 |
+
2025-06-05 11:50:47,296 - __main__ - INFO - Epoch [3/9], Step [1600/3125], Loss: 2.9312, Perplexity: 18.7505
|
| 113 |
+
2025-06-05 11:52:19,632 - __main__ - INFO - Epoch [3/9], Step [1700/3125], Loss: 2.8247, Perplexity: 16.8555
|
| 114 |
+
2025-06-05 11:53:52,241 - __main__ - INFO - Epoch [3/9], Step [1800/3125], Loss: 2.9927, Perplexity: 19.9386
|
| 115 |
+
2025-06-05 11:55:24,747 - __main__ - INFO - Epoch [3/9], Step [1900/3125], Loss: 2.7951, Perplexity: 16.3638
|
| 116 |
+
2025-06-05 11:56:57,095 - __main__ - INFO - Epoch [3/9], Step [2000/3125], Loss: 2.8393, Perplexity: 17.1032
|
| 117 |
+
2025-06-05 11:58:29,803 - __main__ - INFO - Epoch [3/9], Step [2100/3125], Loss: 3.0383, Perplexity: 20.8706
|
| 118 |
+
2025-06-05 12:00:01,877 - __main__ - INFO - Epoch [3/9], Step [2200/3125], Loss: 3.1580, Perplexity: 23.5244
|
| 119 |
+
2025-06-05 12:01:34,524 - __main__ - INFO - Epoch [3/9], Step [2300/3125], Loss: 2.9753, Perplexity: 19.5955
|
| 120 |
+
2025-06-05 12:03:06,876 - __main__ - INFO - Epoch [3/9], Step [2400/3125], Loss: 2.7754, Perplexity: 16.0452
|
| 121 |
+
2025-06-05 12:04:39,456 - __main__ - INFO - Epoch [3/9], Step [2500/3125], Loss: 2.5844, Perplexity: 13.2559
|
| 122 |
+
2025-06-05 12:06:12,314 - __main__ - INFO - Epoch [3/9], Step [2600/3125], Loss: 2.9575, Perplexity: 19.2490
|
| 123 |
+
2025-06-05 12:07:44,508 - __main__ - INFO - Epoch [3/9], Step [2700/3125], Loss: 2.7714, Perplexity: 15.9803
|
| 124 |
+
2025-06-05 12:09:16,908 - __main__ - INFO - Epoch [3/9], Step [2800/3125], Loss: 2.6014, Perplexity: 13.4829
|
| 125 |
+
2025-06-05 12:10:49,531 - __main__ - INFO - Epoch [3/9], Step [2900/3125], Loss: 2.9240, Perplexity: 18.6159
|
| 126 |
+
2025-06-05 12:12:22,014 - __main__ - INFO - Epoch [3/9], Step [3000/3125], Loss: 2.8361, Perplexity: 17.0495
|
| 127 |
+
2025-06-05 12:13:54,500 - __main__ - INFO - Epoch [3/9], Step [3100/3125], Loss: 2.9557, Perplexity: 19.2145
|
| 128 |
+
2025-06-05 12:14:17,729 - __main__ - INFO - Epoch 3 Training finished. Avg Loss: 2.9138, Time: 2894.70s
|
| 129 |
+
2025-06-05 12:27:10,365 - __main__ - INFO - Validation Avg Loss: 2.7487, Perplexity: 15.6226
|
| 130 |
+
2025-06-05 12:27:20,942 - __main__ - INFO - Validation BLEU-4: 0.0986
|
| 131 |
+
2025-06-05 12:27:21,682 - __main__ - INFO - Saved best model checkpoint to ./output/best_model_bleu0.0986.pth
|
| 132 |
+
2025-06-05 12:27:21,683 - __main__ - INFO - Performing memory optimization after epoch...
|
| 133 |
+
2025-06-05 12:27:21,948 - __main__ - INFO - CUDA cache emptied.
|
| 134 |
+
2025-06-05 12:27:22,293 - __main__ - INFO - Python garbage collector run.
|
| 135 |
+
2025-06-05 12:28:57,255 - __main__ - INFO - Epoch [4/9], Step [100/3125], Loss: 2.8362, Perplexity: 17.0513
|
| 136 |
+
2025-06-05 12:30:30,013 - __main__ - INFO - Epoch [4/9], Step [200/3125], Loss: 2.5668, Perplexity: 13.0241
|
| 137 |
+
2025-06-05 12:32:02,681 - __main__ - INFO - Epoch [4/9], Step [300/3125], Loss: 2.7211, Perplexity: 15.1978
|
| 138 |
+
2025-06-05 12:33:35,422 - __main__ - INFO - Epoch [4/9], Step [400/3125], Loss: 2.9763, Perplexity: 19.6153
|
| 139 |
+
2025-06-05 12:35:07,932 - __main__ - INFO - Epoch [4/9], Step [500/3125], Loss: 2.7447, Perplexity: 15.5594
|
| 140 |
+
2025-06-05 12:36:40,894 - __main__ - INFO - Epoch [4/9], Step [600/3125], Loss: 2.6688, Perplexity: 14.4227
|
| 141 |
+
2025-06-05 12:38:13,657 - __main__ - INFO - Epoch [4/9], Step [700/3125], Loss: 2.7560, Perplexity: 15.7370
|
| 142 |
+
2025-06-05 12:39:46,304 - __main__ - INFO - Epoch [4/9], Step [800/3125], Loss: 2.7199, Perplexity: 15.1782
|
| 143 |
+
2025-06-05 12:41:18,843 - __main__ - INFO - Epoch [4/9], Step [900/3125], Loss: 2.9431, Perplexity: 18.9745
|
| 144 |
+
2025-06-05 12:42:51,310 - __main__ - INFO - Epoch [4/9], Step [1000/3125], Loss: 2.7849, Perplexity: 16.1979
|
| 145 |
+
2025-06-05 12:44:24,070 - __main__ - INFO - Epoch [4/9], Step [1100/3125], Loss: 2.6553, Perplexity: 14.2291
|
| 146 |
+
2025-06-05 12:45:56,314 - __main__ - INFO - Epoch [4/9], Step [1200/3125], Loss: 2.7191, Perplexity: 15.1662
|
| 147 |
+
2025-06-05 12:47:28,651 - __main__ - INFO - Epoch [4/9], Step [1300/3125], Loss: 2.7089, Perplexity: 15.0125
|
| 148 |
+
2025-06-05 12:49:01,294 - __main__ - INFO - Epoch [4/9], Step [1400/3125], Loss: 2.9824, Perplexity: 19.7352
|
| 149 |
+
2025-06-05 12:50:34,013 - __main__ - INFO - Epoch [4/9], Step [1500/3125], Loss: 2.7723, Perplexity: 15.9946
|
| 150 |
+
2025-06-05 12:52:06,802 - __main__ - INFO - Epoch [4/9], Step [1600/3125], Loss: 2.8024, Perplexity: 16.4847
|
| 151 |
+
2025-06-05 12:53:39,654 - __main__ - INFO - Epoch [4/9], Step [1700/3125], Loss: 2.7457, Perplexity: 15.5758
|
| 152 |
+
2025-06-05 12:55:12,141 - __main__ - INFO - Epoch [4/9], Step [1800/3125], Loss: 2.9873, Perplexity: 19.8314
|
| 153 |
+
2025-06-05 12:56:44,381 - __main__ - INFO - Epoch [4/9], Step [1900/3125], Loss: 2.6393, Perplexity: 14.0032
|
| 154 |
+
2025-06-05 12:58:16,535 - __main__ - INFO - Epoch [4/9], Step [2000/3125], Loss: 2.6532, Perplexity: 14.1999
|
| 155 |
+
2025-06-05 12:59:49,166 - __main__ - INFO - Epoch [4/9], Step [2100/3125], Loss: 2.7995, Perplexity: 16.4372
|
| 156 |
+
2025-06-05 13:01:21,714 - __main__ - INFO - Epoch [4/9], Step [2200/3125], Loss: 2.7488, Perplexity: 15.6245
|
| 157 |
+
2025-06-05 13:02:53,947 - __main__ - INFO - Epoch [4/9], Step [2300/3125], Loss: 2.8463, Perplexity: 17.2242
|
| 158 |
+
2025-06-05 13:04:26,007 - __main__ - INFO - Epoch [4/9], Step [2400/3125], Loss: 2.6901, Perplexity: 14.7335
|
| 159 |
+
2025-06-05 13:05:58,607 - __main__ - INFO - Epoch [4/9], Step [2500/3125], Loss: 2.8890, Perplexity: 17.9762
|
| 160 |
+
2025-06-05 13:07:31,240 - __main__ - INFO - Epoch [4/9], Step [2600/3125], Loss: 2.6551, Perplexity: 14.2270
|
| 161 |
+
2025-06-05 13:09:03,803 - __main__ - INFO - Epoch [4/9], Step [2700/3125], Loss: 2.8474, Perplexity: 17.2437
|
| 162 |
+
2025-06-05 13:10:36,148 - __main__ - INFO - Epoch [4/9], Step [2800/3125], Loss: 2.7218, Perplexity: 15.2075
|
| 163 |
+
2025-06-05 13:12:08,443 - __main__ - INFO - Epoch [4/9], Step [2900/3125], Loss: 2.6753, Perplexity: 14.5169
|
| 164 |
+
2025-06-05 13:13:41,235 - __main__ - INFO - Epoch [4/9], Step [3000/3125], Loss: 2.8698, Perplexity: 17.6342
|
| 165 |
+
2025-06-05 13:15:13,729 - __main__ - INFO - Epoch [4/9], Step [3100/3125], Loss: 2.5715, Perplexity: 13.0854
|
| 166 |
+
2025-06-05 13:15:37,016 - __main__ - INFO - Epoch 4 Training finished. Avg Loss: 2.7810, Time: 2894.72s
|
| 167 |
+
2025-06-05 13:28:14,233 - __main__ - INFO - Validation Avg Loss: 2.6835, Perplexity: 14.6358
|
| 168 |
+
2025-06-05 13:28:24,559 - __main__ - INFO - Validation BLEU-4: 0.0996
|
| 169 |
+
2025-06-05 13:28:25,299 - __main__ - INFO - Saved best model checkpoint to ./output/best_model_bleu0.0996.pth
|
| 170 |
+
2025-06-05 13:28:25,300 - __main__ - INFO - Performing memory optimization after epoch...
|
| 171 |
+
2025-06-05 13:28:25,596 - __main__ - INFO - CUDA cache emptied.
|
| 172 |
+
2025-06-05 13:28:25,927 - __main__ - INFO - Python garbage collector run.
|
| 173 |
+
2025-06-05 13:30:01,372 - __main__ - INFO - Epoch [5/9], Step [100/3125], Loss: 2.7858, Perplexity: 16.2124
|
| 174 |
+
2025-06-05 13:31:34,188 - __main__ - INFO - Epoch [5/9], Step [200/3125], Loss: 2.5799, Perplexity: 13.1955
|
| 175 |
+
2025-06-05 13:33:06,552 - __main__ - INFO - Epoch [5/9], Step [300/3125], Loss: 2.7141, Perplexity: 15.0910
|
| 176 |
+
2025-06-05 13:34:39,208 - __main__ - INFO - Epoch [5/9], Step [400/3125], Loss: 2.6322, Perplexity: 13.9042
|
| 177 |
+
2025-06-05 13:36:11,891 - __main__ - INFO - Epoch [5/9], Step [500/3125], Loss: 2.9920, Perplexity: 19.9248
|
| 178 |
+
2025-06-05 13:37:44,341 - __main__ - INFO - Epoch [5/9], Step [600/3125], Loss: 2.5876, Perplexity: 13.2972
|
| 179 |
+
2025-06-05 13:39:16,416 - __main__ - INFO - Epoch [5/9], Step [700/3125], Loss: 2.6221, Perplexity: 13.7644
|
| 180 |
+
2025-06-05 13:40:48,960 - __main__ - INFO - Epoch [5/9], Step [800/3125], Loss: 2.5546, Perplexity: 12.8666
|
| 181 |
+
2025-06-05 13:42:21,593 - __main__ - INFO - Epoch [5/9], Step [900/3125], Loss: 2.7899, Perplexity: 16.2789
|
| 182 |
+
2025-06-05 13:43:54,018 - __main__ - INFO - Epoch [5/9], Step [1000/3125], Loss: 2.7180, Perplexity: 15.1505
|
| 183 |
+
2025-06-05 13:45:26,629 - __main__ - INFO - Epoch [5/9], Step [1100/3125], Loss: 2.6338, Perplexity: 13.9268
|
| 184 |
+
2025-06-05 13:46:59,396 - __main__ - INFO - Epoch [5/9], Step [1200/3125], Loss: 2.9994, Perplexity: 20.0732
|
| 185 |
+
2025-06-05 13:48:31,472 - __main__ - INFO - Epoch [5/9], Step [1300/3125], Loss: 2.5138, Perplexity: 12.3518
|
| 186 |
+
2025-06-05 13:50:03,810 - __main__ - INFO - Epoch [5/9], Step [1400/3125], Loss: 2.7708, Perplexity: 15.9718
|
| 187 |
+
2025-06-05 13:51:36,234 - __main__ - INFO - Epoch [5/9], Step [1500/3125], Loss: 2.6756, Perplexity: 14.5208
|
| 188 |
+
2025-06-05 13:53:08,614 - __main__ - INFO - Epoch [5/9], Step [1600/3125], Loss: 2.6377, Perplexity: 13.9804
|
| 189 |
+
2025-06-05 13:54:41,451 - __main__ - INFO - Epoch [5/9], Step [1700/3125], Loss: 2.6101, Perplexity: 13.6009
|
| 190 |
+
2025-06-05 13:56:14,028 - __main__ - INFO - Epoch [5/9], Step [1800/3125], Loss: 2.6736, Perplexity: 14.4918
|
| 191 |
+
2025-06-05 13:57:46,796 - __main__ - INFO - Epoch [5/9], Step [1900/3125], Loss: 2.6328, Perplexity: 13.9123
|
| 192 |
+
2025-06-05 13:59:19,826 - __main__ - INFO - Epoch [5/9], Step [2000/3125], Loss: 2.5901, Perplexity: 13.3318
|
| 193 |
+
2025-06-05 14:00:52,403 - __main__ - INFO - Epoch [5/9], Step [2100/3125], Loss: 2.9779, Perplexity: 19.6469
|
| 194 |
+
2025-06-05 14:02:25,242 - __main__ - INFO - Epoch [5/9], Step [2200/3125], Loss: 2.5809, Perplexity: 13.2096
|
| 195 |
+
2025-06-05 14:03:58,214 - __main__ - INFO - Epoch [5/9], Step [2300/3125], Loss: 2.7360, Perplexity: 15.4247
|
| 196 |
+
2025-06-05 14:05:30,984 - __main__ - INFO - Epoch [5/9], Step [2400/3125], Loss: 2.5268, Perplexity: 12.5135
|
| 197 |
+
2025-06-05 14:07:04,027 - __main__ - INFO - Epoch [5/9], Step [2500/3125], Loss: 2.8699, Perplexity: 17.6357
|
| 198 |
+
2025-06-05 14:08:36,966 - __main__ - INFO - Epoch [5/9], Step [2600/3125], Loss: 2.7812, Perplexity: 16.1382
|
| 199 |
+
2025-06-05 14:10:09,378 - __main__ - INFO - Epoch [5/9], Step [2700/3125], Loss: 2.6540, Perplexity: 14.2111
|
| 200 |
+
2025-06-05 14:11:41,671 - __main__ - INFO - Epoch [5/9], Step [2800/3125], Loss: 2.6715, Perplexity: 14.4612
|
| 201 |
+
2025-06-05 14:13:14,497 - __main__ - INFO - Epoch [5/9], Step [2900/3125], Loss: 2.8780, Perplexity: 17.7783
|
| 202 |
+
2025-06-05 14:14:47,210 - __main__ - INFO - Epoch [5/9], Step [3000/3125], Loss: 2.6441, Perplexity: 14.0706
|
| 203 |
+
2025-06-05 14:16:19,723 - __main__ - INFO - Epoch [5/9], Step [3100/3125], Loss: 2.6745, Perplexity: 14.5049
|
| 204 |
+
2025-06-05 14:16:43,018 - __main__ - INFO - Epoch 5 Training finished. Avg Loss: 2.6866, Time: 2897.09s
|
| 205 |
+
2025-06-05 14:29:20,136 - __main__ - INFO - Validation Avg Loss: 2.6448, Perplexity: 14.0800
|
| 206 |
+
2025-06-05 14:29:30,680 - __main__ - INFO - Validation BLEU-4: 0.1011
|
| 207 |
+
2025-06-05 14:29:31,398 - __main__ - INFO - Saved best model checkpoint to ./output/best_model_bleu0.1011.pth
|
| 208 |
+
2025-06-05 14:29:32,142 - __main__ - INFO - Saved periodic model checkpoint to ./output/model_epoch_5.pth
|
| 209 |
+
2025-06-05 14:29:32,143 - __main__ - INFO - Performing memory optimization after epoch...
|
| 210 |
+
2025-06-05 14:29:32,408 - __main__ - INFO - CUDA cache emptied.
|
| 211 |
+
2025-06-05 14:29:32,753 - __main__ - INFO - Python garbage collector run.
|
| 212 |
+
2025-06-05 14:31:08,760 - __main__ - INFO - Epoch [6/9], Step [100/3125], Loss: 2.9338, Perplexity: 18.7981
|
| 213 |
+
2025-06-05 14:32:41,036 - __main__ - INFO - Epoch [6/9], Step [200/3125], Loss: 2.7460, Perplexity: 15.5799
|
| 214 |
+
2025-06-05 14:34:13,610 - __main__ - INFO - Epoch [6/9], Step [300/3125], Loss: 2.3894, Perplexity: 10.9066
|
| 215 |
+
2025-06-05 14:35:46,857 - __main__ - INFO - Epoch [6/9], Step [400/3125], Loss: 2.6891, Perplexity: 14.7191
|
| 216 |
+
2025-06-05 14:37:19,167 - __main__ - INFO - Epoch [6/9], Step [500/3125], Loss: 2.7032, Perplexity: 14.9273
|
| 217 |
+
2025-06-05 14:38:52,048 - __main__ - INFO - Epoch [6/9], Step [600/3125], Loss: 2.6848, Perplexity: 14.6553
|
| 218 |
+
2025-06-05 14:40:24,881 - __main__ - INFO - Epoch [6/9], Step [700/3125], Loss: 2.4991, Perplexity: 12.1715
|
| 219 |
+
2025-06-05 14:41:57,087 - __main__ - INFO - Epoch [6/9], Step [800/3125], Loss: 2.5794, Perplexity: 13.1892
|
| 220 |
+
2025-06-05 14:43:29,854 - __main__ - INFO - Epoch [6/9], Step [900/3125], Loss: 2.5044, Perplexity: 12.2366
|
| 221 |
+
2025-06-05 14:45:02,445 - __main__ - INFO - Epoch [6/9], Step [1000/3125], Loss: 2.6207, Perplexity: 13.7448
|
| 222 |
+
2025-06-05 14:46:35,344 - __main__ - INFO - Epoch [6/9], Step [1100/3125], Loss: 2.5424, Perplexity: 12.7103
|
| 223 |
+
2025-06-05 14:48:08,048 - __main__ - INFO - Epoch [6/9], Step [1200/3125], Loss: 2.5540, Perplexity: 12.8587
|
| 224 |
+
2025-06-05 14:49:40,487 - __main__ - INFO - Epoch [6/9], Step [1300/3125], Loss: 2.5427, Perplexity: 12.7145
|
| 225 |
+
2025-06-05 14:51:13,035 - __main__ - INFO - Epoch [6/9], Step [1400/3125], Loss: 2.6368, Perplexity: 13.9681
|
| 226 |
+
2025-06-05 14:52:45,059 - __main__ - INFO - Epoch [6/9], Step [1500/3125], Loss: 2.5717, Perplexity: 13.0879
|
| 227 |
+
2025-06-05 14:54:17,291 - __main__ - INFO - Epoch [6/9], Step [1600/3125], Loss: 2.4953, Perplexity: 12.1255
|
| 228 |
+
2025-06-05 14:55:50,488 - __main__ - INFO - Epoch [6/9], Step [1700/3125], Loss: 2.7300, Perplexity: 15.3336
|
| 229 |
+
2025-06-05 14:57:23,442 - __main__ - INFO - Epoch [6/9], Step [1800/3125], Loss: 2.6784, Perplexity: 14.5613
|
| 230 |
+
2025-06-05 14:58:55,865 - __main__ - INFO - Epoch [6/9], Step [1900/3125], Loss: 2.6738, Perplexity: 14.4946
|
| 231 |
+
2025-06-05 15:00:28,266 - __main__ - INFO - Epoch [6/9], Step [2000/3125], Loss: 2.6148, Perplexity: 13.6649
|
| 232 |
+
2025-06-05 15:02:00,818 - __main__ - INFO - Epoch [6/9], Step [2100/3125], Loss: 2.8018, Perplexity: 16.4748
|
| 233 |
+
2025-06-05 15:03:33,616 - __main__ - INFO - Epoch [6/9], Step [2200/3125], Loss: 2.6942, Perplexity: 14.7940
|
| 234 |
+
2025-06-05 15:05:05,991 - __main__ - INFO - Epoch [6/9], Step [2300/3125], Loss: 2.4844, Perplexity: 11.9935
|
| 235 |
+
2025-06-05 15:06:38,662 - __main__ - INFO - Epoch [6/9], Step [2400/3125], Loss: 2.4125, Perplexity: 11.1615
|
| 236 |
+
2025-06-05 15:08:11,014 - __main__ - INFO - Epoch [6/9], Step [2500/3125], Loss: 2.5616, Perplexity: 12.9564
|
| 237 |
+
2025-06-05 15:09:43,766 - __main__ - INFO - Epoch [6/9], Step [2600/3125], Loss: 2.5049, Perplexity: 12.2425
|
| 238 |
+
2025-06-05 15:11:16,830 - __main__ - INFO - Epoch [6/9], Step [2700/3125], Loss: 2.4866, Perplexity: 12.0206
|
| 239 |
+
2025-06-05 15:12:49,025 - __main__ - INFO - Epoch [6/9], Step [2800/3125], Loss: 2.3411, Perplexity: 10.3931
|
| 240 |
+
2025-06-05 15:14:21,512 - __main__ - INFO - Epoch [6/9], Step [2900/3125], Loss: 2.6441, Perplexity: 14.0713
|
| 241 |
+
2025-06-05 15:15:54,097 - __main__ - INFO - Epoch [6/9], Step [3000/3125], Loss: 2.5855, Perplexity: 13.2695
|
| 242 |
+
2025-06-05 15:17:26,931 - __main__ - INFO - Epoch [6/9], Step [3100/3125], Loss: 2.7371, Perplexity: 15.4419
|
| 243 |
+
2025-06-05 15:17:50,166 - __main__ - INFO - Epoch 6 Training finished. Avg Loss: 2.6127, Time: 2897.41s
|
| 244 |
+
2025-06-05 15:30:17,460 - __main__ - INFO - Validation Avg Loss: 2.6184, Perplexity: 13.7138
|
| 245 |
+
2025-06-05 15:30:28,171 - __main__ - INFO - Validation BLEU-4: 0.1009
|
| 246 |
+
2025-06-05 15:30:28,172 - __main__ - INFO - Performing memory optimization after epoch...
|
| 247 |
+
2025-06-05 15:30:28,470 - __main__ - INFO - CUDA cache emptied.
|
| 248 |
+
2025-06-05 15:30:28,816 - __main__ - INFO - Python garbage collector run.
|
| 249 |
+
2025-06-05 15:32:05,141 - __main__ - INFO - Epoch [7/9], Step [100/3125], Loss: 2.6545, Perplexity: 14.2180
|
| 250 |
+
2025-06-05 15:33:37,788 - __main__ - INFO - Epoch [7/9], Step [200/3125], Loss: 2.3907, Perplexity: 10.9206
|
| 251 |
+
2025-06-05 15:35:09,924 - __main__ - INFO - Epoch [7/9], Step [300/3125], Loss: 2.3964, Perplexity: 10.9837
|
| 252 |
+
2025-06-05 15:36:42,633 - __main__ - INFO - Epoch [7/9], Step [400/3125], Loss: 2.2917, Perplexity: 9.8918
|
| 253 |
+
2025-06-05 15:38:15,138 - __main__ - INFO - Epoch [7/9], Step [500/3125], Loss: 2.5460, Perplexity: 12.7565
|
| 254 |
+
2025-06-05 15:39:47,288 - __main__ - INFO - Epoch [7/9], Step [600/3125], Loss: 2.7165, Perplexity: 15.1276
|
| 255 |
+
2025-06-05 15:41:19,984 - __main__ - INFO - Epoch [7/9], Step [700/3125], Loss: 2.3160, Perplexity: 10.1350
|
| 256 |
+
2025-06-05 15:42:52,625 - __main__ - INFO - Epoch [7/9], Step [800/3125], Loss: 2.4257, Perplexity: 11.3097
|
| 257 |
+
2025-06-05 15:44:25,300 - __main__ - INFO - Epoch [7/9], Step [900/3125], Loss: 2.8313, Perplexity: 16.9669
|
| 258 |
+
2025-06-05 15:45:57,862 - __main__ - INFO - Epoch [7/9], Step [1000/3125], Loss: 2.4841, Perplexity: 11.9898
|
| 259 |
+
2025-06-05 15:47:30,346 - __main__ - INFO - Epoch [7/9], Step [1100/3125], Loss: 2.4737, Perplexity: 11.8667
|
| 260 |
+
2025-06-05 15:49:02,664 - __main__ - INFO - Epoch [7/9], Step [1200/3125], Loss: 2.3904, Perplexity: 10.9178
|
| 261 |
+
2025-06-05 15:50:34,955 - __main__ - INFO - Epoch [7/9], Step [1300/3125], Loss: 2.4815, Perplexity: 11.9595
|
| 262 |
+
2025-06-05 15:52:07,231 - __main__ - INFO - Epoch [7/9], Step [1400/3125], Loss: 2.7324, Perplexity: 15.3697
|
| 263 |
+
2025-06-05 15:53:39,430 - __main__ - INFO - Epoch [7/9], Step [1500/3125], Loss: 2.7363, Perplexity: 15.4298
|
| 264 |
+
2025-06-05 15:55:11,826 - __main__ - INFO - Epoch [7/9], Step [1600/3125], Loss: 2.7751, Perplexity: 16.0397
|
| 265 |
+
2025-06-05 15:56:44,380 - __main__ - INFO - Epoch [7/9], Step [1700/3125], Loss: 2.5598, Perplexity: 12.9329
|
| 266 |
+
2025-06-05 15:58:16,561 - __main__ - INFO - Epoch [7/9], Step [1800/3125], Loss: 2.7369, Perplexity: 15.4388
|
| 267 |
+
2025-06-05 15:59:49,080 - __main__ - INFO - Epoch [7/9], Step [1900/3125], Loss: 2.8117, Perplexity: 16.6374
|
| 268 |
+
2025-06-05 16:01:21,995 - __main__ - INFO - Epoch [7/9], Step [2000/3125], Loss: 2.6360, Perplexity: 13.9572
|
| 269 |
+
2025-06-05 16:02:54,730 - __main__ - INFO - Epoch [7/9], Step [2100/3125], Loss: 2.4383, Perplexity: 11.4533
|
| 270 |
+
2025-06-05 16:04:28,093 - __main__ - INFO - Epoch [7/9], Step [2200/3125], Loss: 2.7142, Perplexity: 15.0932
|
| 271 |
+
2025-06-05 16:06:01,476 - __main__ - INFO - Epoch [7/9], Step [2300/3125], Loss: 2.4590, Perplexity: 11.6927
|
| 272 |
+
2025-06-05 16:07:34,763 - __main__ - INFO - Epoch [7/9], Step [2400/3125], Loss: 2.6457, Perplexity: 14.0935
|
| 273 |
+
2025-06-05 16:09:07,778 - __main__ - INFO - Epoch [7/9], Step [2500/3125], Loss: 2.6708, Perplexity: 14.4518
|
| 274 |
+
2025-06-05 16:10:40,473 - __main__ - INFO - Epoch [7/9], Step [2600/3125], Loss: 2.5663, Perplexity: 13.0179
|
| 275 |
+
2025-06-05 16:12:12,943 - __main__ - INFO - Epoch [7/9], Step [2700/3125], Loss: 2.8020, Perplexity: 16.4769
|
| 276 |
+
2025-06-05 16:13:45,226 - __main__ - INFO - Epoch [7/9], Step [2800/3125], Loss: 2.6069, Perplexity: 13.5576
|
| 277 |
+
2025-06-05 16:15:17,969 - __main__ - INFO - Epoch [7/9], Step [2900/3125], Loss: 2.5213, Perplexity: 12.4453
|
| 278 |
+
2025-06-05 16:16:51,084 - __main__ - INFO - Epoch [7/9], Step [3000/3125], Loss: 2.5426, Perplexity: 12.7128
|
| 279 |
+
2025-06-05 16:18:23,560 - __main__ - INFO - Epoch [7/9], Step [3100/3125], Loss: 2.6069, Perplexity: 13.5576
|
| 280 |
+
2025-06-05 16:18:46,982 - __main__ - INFO - Epoch 7 Training finished. Avg Loss: 2.5503, Time: 2898.16s
|
| 281 |
+
2025-06-05 16:31:32,517 - __main__ - INFO - Validation Avg Loss: 2.6021, Perplexity: 13.4918
|
| 282 |
+
2025-06-05 16:31:42,995 - __main__ - INFO - Validation BLEU-4: 0.1028
|
| 283 |
+
2025-06-05 16:31:43,704 - __main__ - INFO - Saved best model checkpoint to ./output/best_model_bleu0.1028.pth
|
| 284 |
+
2025-06-05 16:31:43,705 - __main__ - INFO - Performing memory optimization after epoch...
|
| 285 |
+
2025-06-05 16:31:43,969 - __main__ - INFO - CUDA cache emptied.
|
| 286 |
+
2025-06-05 16:31:44,301 - __main__ - INFO - Python garbage collector run.
|
| 287 |
+
2025-06-05 16:33:19,208 - __main__ - INFO - Epoch [8/9], Step [100/3125], Loss: 2.5949, Perplexity: 13.3954
|
| 288 |
+
2025-06-05 16:34:52,087 - __main__ - INFO - Epoch [8/9], Step [200/3125], Loss: 2.3867, Perplexity: 10.8772
|
| 289 |
+
2025-06-05 16:36:24,295 - __main__ - INFO - Epoch [8/9], Step [300/3125], Loss: 2.4636, Perplexity: 11.7471
|
| 290 |
+
2025-06-05 16:37:56,189 - __main__ - INFO - Epoch [8/9], Step [400/3125], Loss: 2.5906, Perplexity: 13.3381
|
| 291 |
+
2025-06-05 16:39:29,764 - __main__ - INFO - Epoch [8/9], Step [500/3125], Loss: 2.5785, Perplexity: 13.1772
|
| 292 |
+
2025-06-05 16:41:02,645 - __main__ - INFO - Epoch [8/9], Step [600/3125], Loss: 2.5902, Perplexity: 13.3330
|
| 293 |
+
2025-06-05 16:42:35,744 - __main__ - INFO - Epoch [8/9], Step [700/3125], Loss: 2.6504, Perplexity: 14.1599
|
| 294 |
+
2025-06-05 16:44:08,175 - __main__ - INFO - Epoch [8/9], Step [800/3125], Loss: 2.5812, Perplexity: 13.2125
|
| 295 |
+
2025-06-05 16:45:41,068 - __main__ - INFO - Epoch [8/9], Step [900/3125], Loss: 2.3477, Perplexity: 10.4617
|
| 296 |
+
2025-06-05 16:47:13,040 - __main__ - INFO - Epoch [8/9], Step [1000/3125], Loss: 2.5416, Perplexity: 12.7004
|
| 297 |
+
2025-06-05 16:48:45,442 - __main__ - INFO - Epoch [8/9], Step [1100/3125], Loss: 2.5581, Perplexity: 12.9117
|
| 298 |
+
2025-06-05 16:50:18,029 - __main__ - INFO - Epoch [8/9], Step [1200/3125], Loss: 2.6781, Perplexity: 14.5574
|
| 299 |
+
2025-06-05 16:51:51,068 - __main__ - INFO - Epoch [8/9], Step [1300/3125], Loss: 2.4678, Perplexity: 11.7967
|
| 300 |
+
2025-06-05 16:53:23,767 - __main__ - INFO - Epoch [8/9], Step [1400/3125], Loss: 2.7964, Perplexity: 16.3863
|
| 301 |
+
2025-06-05 16:54:56,092 - __main__ - INFO - Epoch [8/9], Step [1500/3125], Loss: 2.5617, Perplexity: 12.9583
|
| 302 |
+
2025-06-05 16:56:28,564 - __main__ - INFO - Epoch [8/9], Step [1600/3125], Loss: 2.4647, Perplexity: 11.7597
|
| 303 |
+
2025-06-05 16:58:01,422 - __main__ - INFO - Epoch [8/9], Step [1700/3125], Loss: 2.5186, Perplexity: 12.4108
|
| 304 |
+
2025-06-05 16:59:34,614 - __main__ - INFO - Epoch [8/9], Step [1800/3125], Loss: 2.7458, Perplexity: 15.5764
|
| 305 |
+
2025-06-05 17:01:06,892 - __main__ - INFO - Epoch [8/9], Step [1900/3125], Loss: 2.4218, Perplexity: 11.2661
|
| 306 |
+
2025-06-05 17:02:39,718 - __main__ - INFO - Epoch [8/9], Step [2000/3125], Loss: 2.4996, Perplexity: 12.1774
|
| 307 |
+
2025-06-05 17:04:12,656 - __main__ - INFO - Epoch [8/9], Step [2100/3125], Loss: 2.4715, Perplexity: 11.8400
|
| 308 |
+
2025-06-05 17:05:45,350 - __main__ - INFO - Epoch [8/9], Step [2200/3125], Loss: 2.7304, Perplexity: 15.3395
|
| 309 |
+
2025-06-05 17:07:18,313 - __main__ - INFO - Epoch [8/9], Step [2300/3125], Loss: 2.6088, Perplexity: 13.5826
|
| 310 |
+
2025-06-05 17:08:50,891 - __main__ - INFO - Epoch [8/9], Step [2400/3125], Loss: 2.2952, Perplexity: 9.9266
|
| 311 |
+
2025-06-05 17:10:23,321 - __main__ - INFO - Epoch [8/9], Step [2500/3125], Loss: 2.6801, Perplexity: 14.5865
|
| 312 |
+
2025-06-05 17:11:56,233 - __main__ - INFO - Epoch [8/9], Step [2600/3125], Loss: 2.6453, Perplexity: 14.0877
|
| 313 |
+
2025-06-05 17:13:28,949 - __main__ - INFO - Epoch [8/9], Step [2700/3125], Loss: 2.4980, Perplexity: 12.1576
|
| 314 |
+
2025-06-05 17:15:01,500 - __main__ - INFO - Epoch [8/9], Step [2800/3125], Loss: 2.4855, Perplexity: 12.0065
|
| 315 |
+
2025-06-05 17:16:33,983 - __main__ - INFO - Epoch [8/9], Step [2900/3125], Loss: 2.7647, Perplexity: 15.8748
|
| 316 |
+
2025-06-05 17:18:06,726 - __main__ - INFO - Epoch [8/9], Step [3000/3125], Loss: 2.3954, Perplexity: 10.9722
|
| 317 |
+
2025-06-05 17:19:40,090 - __main__ - INFO - Epoch [8/9], Step [3100/3125], Loss: 2.5672, Perplexity: 13.0291
|
| 318 |
+
2025-06-05 17:20:03,575 - __main__ - INFO - Epoch 8 Training finished. Avg Loss: 2.4984, Time: 2899.27s
|
| 319 |
+
2025-06-05 17:32:41,641 - __main__ - INFO - Validation Avg Loss: 2.5887, Perplexity: 13.3131
|
| 320 |
+
2025-06-05 17:32:52,092 - __main__ - INFO - Validation BLEU-4: 0.1029
|
| 321 |
+
2025-06-05 17:32:52,835 - __main__ - INFO - Saved best model checkpoint to ./output/best_model_bleu0.1029.pth
|
| 322 |
+
2025-06-05 17:32:52,836 - __main__ - INFO - Performing memory optimization after epoch...
|
| 323 |
+
2025-06-05 17:32:53,135 - __main__ - INFO - CUDA cache emptied.
|
| 324 |
+
2025-06-05 17:32:53,477 - __main__ - INFO - Python garbage collector run.
|
| 325 |
+
2025-06-05 17:34:28,617 - __main__ - INFO - Epoch [9/9], Step [100/3125], Loss: 2.4885, Perplexity: 12.0428
|
| 326 |
+
2025-06-05 17:36:01,256 - __main__ - INFO - Epoch [9/9], Step [200/3125], Loss: 2.4464, Perplexity: 11.5461
|
| 327 |
+
2025-06-05 17:37:33,875 - __main__ - INFO - Epoch [9/9], Step [300/3125], Loss: 2.5567, Perplexity: 12.8926
|
| 328 |
+
2025-06-05 17:39:06,254 - __main__ - INFO - Epoch [9/9], Step [400/3125], Loss: 2.5434, Perplexity: 12.7234
|
| 329 |
+
2025-06-05 17:40:38,946 - __main__ - INFO - Epoch [9/9], Step [500/3125], Loss: 2.4282, Perplexity: 11.3380
|
| 330 |
+
2025-06-05 17:42:11,097 - __main__ - INFO - Epoch [9/9], Step [600/3125], Loss: 2.4907, Perplexity: 12.0691
|
| 331 |
+
2025-06-05 17:43:43,481 - __main__ - INFO - Epoch [9/9], Step [700/3125], Loss: 2.5079, Perplexity: 12.2789
|
| 332 |
+
2025-06-05 17:45:15,684 - __main__ - INFO - Epoch [9/9], Step [800/3125], Loss: 2.4735, Perplexity: 11.8636
|
| 333 |
+
2025-06-05 17:46:48,773 - __main__ - INFO - Epoch [9/9], Step [900/3125], Loss: 2.5014, Perplexity: 12.2001
|
| 334 |
+
2025-06-05 17:48:21,463 - __main__ - INFO - Epoch [9/9], Step [1000/3125], Loss: 2.7705, Perplexity: 15.9662
|
| 335 |
+
2025-06-05 17:49:53,960 - __main__ - INFO - Epoch [9/9], Step [1100/3125], Loss: 2.6952, Perplexity: 14.8082
|
text_files/training_log_17_27.txt
ADDED
|
@@ -0,0 +1,806 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
2025-06-10 07:24:28,182 - __main__ - INFO - Previous notebook output found at: /kaggle/input/part-2-10-19/output. Copying to ./output...
|
| 2 |
+
2025-06-10 07:25:23,506 - __main__ - INFO - Previous output copied successfully to current working directory for resumption.
|
| 3 |
+
2025-06-10 07:25:23,507 - __main__ - INFO -
|
| 4 |
+
--- Starting Model Training ---
|
| 5 |
+
2025-06-10 07:25:23,508 - __main__ - INFO - Starting training process...
|
| 6 |
+
2025-06-10 07:25:23,508 - __main__ - INFO - Using device: cuda
|
| 7 |
+
2025-06-10 07:25:23,511 - __main__ - WARNING - Vocabulary source not found at /kaggle/input/vocabulary_s/pytorch/default/1/vocabulary.pkl. Will build new vocabulary.
|
| 8 |
+
2025-06-10 07:25:23,512 - __main__ - INFO - Building new vocabulary from training dataset...
|
| 9 |
+
2025-06-10 07:25:24,512 - __main__ - INFO - Successfully loaded captions from /kaggle/input/coco-2017-dataset/coco2017/annotations/captions_train2017.json
|
| 10 |
+
Processing annotations: 100%|██████████| 591753/591753 [04:09<00:00, 2370.69it/s]
|
| 11 |
+
2025-06-10 07:29:34,159 - __main__ - INFO - Dataset size after filtering: 591753 samples.
|
| 12 |
+
2025-06-10 07:29:34,204 - __main__ - INFO - Building vocabulary...
|
| 13 |
+
Counting word frequencies: 100%|██████████| 591753/591753 [00:01<00:00, 340892.04it/s]
|
| 14 |
+
2025-06-10 07:29:35,947 - __main__ - INFO - Vocabulary size: 14030
|
| 15 |
+
2025-06-10 07:29:36,090 - __main__ - INFO - New vocabulary built.
|
| 16 |
+
2025-06-10 07:29:36,102 - __main__ - INFO - Saved newly built vocabulary to ./output/vocabulary.pkl
|
| 17 |
+
2025-06-10 07:29:37,007 - __main__ - INFO - Successfully loaded captions from /kaggle/input/coco-2017-dataset/coco2017/annotations/captions_train2017.json
|
| 18 |
+
Processing annotations: 100%|██████████| 591753/591753 [00:58<00:00, 10197.00it/s]
|
| 19 |
+
2025-06-10 07:30:35,215 - __main__ - INFO - Using subset of 200000 samples for the dataset.
|
| 20 |
+
2025-06-10 07:30:35,216 - __main__ - INFO - Dataset size after filtering: 200000 samples.
|
| 21 |
+
2025-06-10 07:30:35,288 - __main__ - INFO - Successfully loaded captions from /kaggle/input/coco-2017-dataset/coco2017/annotations/captions_val2017.json
|
| 22 |
+
Processing annotations: 100%|██████████| 25014/25014 [00:12<00:00, 2021.11it/s]
|
| 23 |
+
2025-06-10 07:30:47,667 - __main__ - INFO - Dataset size after filtering: 25014 samples.
|
| 24 |
+
2025-06-10 07:30:47,668 - __main__ - INFO - Training dataset size: 200000
|
| 25 |
+
2025-06-10 07:30:47,669 - __main__ - INFO - Validation dataset size: 25014
|
| 26 |
+
Downloading: "https://download.pytorch.org/models/resnet50-11ad3fa6.pth" to /root/.cache/torch/hub/checkpoints/resnet50-11ad3fa6.pth
|
| 27 |
+
100%|██████████| 97.8M/97.8M [00:00<00:00, 212MB/s]
|
| 28 |
+
2025-06-10 07:30:48,719 - __main__ - INFO - ResNet encoder base layers are fine-tuning enabled.
|
| 29 |
+
2025-06-10 07:30:49,052 - __main__ - INFO - Attempting to resume training from: ./output/best_model_bleu0.1047.pth
|
| 30 |
+
2025-06-10 07:30:49,453 - __main__ - INFO - Resumed training from epoch 16. Best validation score so far: 0.1047
|
| 31 |
+
Epoch 17 Training: 3%|▎ | 99/3125 [01:32<48:35, 1.04it/s]
|
| 32 |
+
2025-06-10 07:32:22,936 - __main__ - INFO - Epoch [17/27], Step [100/3125], Loss: 2.3526, Perplexity: 10.5128
|
| 33 |
+
Epoch 17 Training: 6%|▋ | 199/3125 [03:11<48:08, 1.01it/s]
|
| 34 |
+
2025-06-10 07:34:01,500 - __main__ - INFO - Epoch [17/27], Step [200/3125], Loss: 2.4604, Perplexity: 11.7090
|
| 35 |
+
Epoch 17 Training: 10%|▉ | 299/3125 [04:49<46:11, 1.02it/s]
|
| 36 |
+
2025-06-10 07:35:40,055 - __main__ - INFO - Epoch [17/27], Step [300/3125], Loss: 2.5760, Perplexity: 13.1449
|
| 37 |
+
Epoch 17 Training: 13%|█▎ | 399/3125 [06:27<44:41, 1.02it/s]
|
| 38 |
+
2025-06-10 07:37:18,437 - __main__ - INFO - Epoch [17/27], Step [400/3125], Loss: 2.5386, Perplexity: 12.6615
|
| 39 |
+
Epoch 17 Training: 16%|█▌ | 499/3125 [08:06<43:17, 1.01it/s]
|
| 40 |
+
2025-06-10 07:38:57,172 - __main__ - INFO - Epoch [17/27], Step [500/3125], Loss: 2.4724, Perplexity: 11.8508
|
| 41 |
+
Epoch 17 Training: 19%|█▉ | 599/3125 [09:45<41:23, 1.02it/s]
|
| 42 |
+
2025-06-10 07:40:35,800 - __main__ - INFO - Epoch [17/27], Step [600/3125], Loss: 3.0153, Perplexity: 20.3955
|
| 43 |
+
Epoch 17 Training: 22%|██▏ | 699/3125 [11:24<39:21, 1.03it/s]
|
| 44 |
+
2025-06-10 07:42:14,841 - __main__ - INFO - Epoch [17/27], Step [700/3125], Loss: 2.6407, Perplexity: 14.0232
|
| 45 |
+
Epoch 17 Training: 26%|██▌ | 799/3125 [13:03<39:44, 1.03s/it]
|
| 46 |
+
2025-06-10 07:43:53,867 - __main__ - INFO - Epoch [17/27], Step [800/3125], Loss: 2.5756, Perplexity: 13.1391
|
| 47 |
+
Epoch 17 Training: 29%|██▉ | 899/3125 [14:42<36:54, 1.01it/s]
|
| 48 |
+
2025-06-10 07:45:32,847 - __main__ - INFO - Epoch [17/27], Step [900/3125], Loss: 2.2050, Perplexity: 9.0706
|
| 49 |
+
Epoch 17 Training: 32%|███▏ | 999/3125 [16:21<35:00, 1.01it/s]
|
| 50 |
+
2025-06-10 07:47:11,912 - __main__ - INFO - Epoch [17/27], Step [1000/3125], Loss: 2.3957, Perplexity: 10.9755
|
| 51 |
+
Epoch 17 Training: 35%|███▌ | 1099/3125 [18:00<33:09, 1.02it/s]
|
| 52 |
+
2025-06-10 07:48:50,896 - __main__ - INFO - Epoch [17/27], Step [1100/3125], Loss: 2.2961, Perplexity: 9.9352
|
| 53 |
+
Epoch 17 Training: 38%|███▊ | 1199/3125 [19:39<31:44, 1.01it/s]
|
| 54 |
+
2025-06-10 07:50:30,069 - __main__ - INFO - Epoch [17/27], Step [1200/3125], Loss: 2.2552, Perplexity: 9.5371
|
| 55 |
+
Epoch 17 Training: 42%|████▏ | 1299/3125 [21:18<29:46, 1.02it/s]
|
| 56 |
+
2025-06-10 07:52:09,332 - __main__ - INFO - Epoch [17/27], Step [1300/3125], Loss: 2.5000, Perplexity: 12.1825
|
| 57 |
+
Epoch 17 Training: 45%|████▍ | 1399/3125 [22:57<28:03, 1.02it/s]
|
| 58 |
+
2025-06-10 07:53:47,838 - __main__ - INFO - Epoch [17/27], Step [1400/3125], Loss: 2.7185, Perplexity: 15.1579
|
| 59 |
+
Epoch 17 Training: 48%|████▊ | 1499/3125 [24:36<26:48, 1.01it/s]
|
| 60 |
+
2025-06-10 07:55:26,722 - __main__ - INFO - Epoch [17/27], Step [1500/3125], Loss: 2.5459, Perplexity: 12.7545
|
| 61 |
+
Epoch 17 Training: 51%|█████ | 1599/3125 [26:15<24:49, 1.02it/s]
|
| 62 |
+
2025-06-10 07:57:05,699 - __main__ - INFO - Epoch [17/27], Step [1600/3125], Loss: 2.3916, Perplexity: 10.9307
|
| 63 |
+
Epoch 17 Training: 54%|█████▍ | 1699/3125 [27:54<23:47, 1.00s/it]
|
| 64 |
+
2025-06-10 07:58:44,675 - __main__ - INFO - Epoch [17/27], Step [1700/3125], Loss: 2.5494, Perplexity: 12.7994
|
| 65 |
+
Epoch 17 Training: 58%|█████▊ | 1799/3125 [29:33<22:05, 1.00it/s]
|
| 66 |
+
2025-06-10 08:00:23,441 - __main__ - INFO - Epoch [17/27], Step [1800/3125], Loss: 2.4654, Perplexity: 11.7682
|
| 67 |
+
Epoch 17 Training: 61%|██████ | 1899/3125 [31:11<20:10, 1.01it/s]
|
| 68 |
+
2025-06-10 08:02:02,062 - __main__ - INFO - Epoch [17/27], Step [1900/3125], Loss: 2.6649, Perplexity: 14.3659
|
| 69 |
+
Epoch 17 Training: 64%|██████▍ | 1999/3125 [32:50<18:28, 1.02it/s]
|
| 70 |
+
2025-06-10 08:03:40,967 - __main__ - INFO - Epoch [17/27], Step [2000/3125], Loss: 2.2949, Perplexity: 9.9233
|
| 71 |
+
Epoch 17 Training: 67%|██████▋ | 2099/3125 [34:29<16:53, 1.01it/s]
|
| 72 |
+
2025-06-10 08:05:20,196 - __main__ - INFO - Epoch [17/27], Step [2100/3125], Loss: 2.6354, Perplexity: 13.9489
|
| 73 |
+
Epoch 17 Training: 70%|███████ | 2199/3125 [36:09<15:11, 1.02it/s]
|
| 74 |
+
2025-06-10 08:06:59,515 - __main__ - INFO - Epoch [17/27], Step [2200/3125], Loss: 2.5667, Perplexity: 13.0228
|
| 75 |
+
Epoch 17 Training: 74%|███████▎ | 2299/3125 [37:47<13:35, 1.01it/s]
|
| 76 |
+
2025-06-10 08:08:38,388 - __main__ - INFO - Epoch [17/27], Step [2300/3125], Loss: 2.4153, Perplexity: 11.1936
|
| 77 |
+
Epoch 17 Training: 77%|███████▋ | 2399/3125 [39:27<12:04, 1.00it/s]
|
| 78 |
+
2025-06-10 08:10:17,655 - __main__ - INFO - Epoch [17/27], Step [2400/3125], Loss: 2.5093, Perplexity: 12.2963
|
| 79 |
+
Epoch 17 Training: 80%|███████▉ | 2499/3125 [41:06<10:11, 1.02it/s]
|
| 80 |
+
2025-06-10 08:11:57,014 - __main__ - INFO - Epoch [17/27], Step [2500/3125], Loss: 2.3697, Perplexity: 10.6938
|
| 81 |
+
Epoch 17 Training: 83%|████████▎ | 2599/3125 [42:45<08:38, 1.01it/s]
|
| 82 |
+
2025-06-10 08:13:36,192 - __main__ - INFO - Epoch [17/27], Step [2600/3125], Loss: 2.5674, Perplexity: 13.0320
|
| 83 |
+
Epoch 17 Training: 86%|████████▋ | 2699/3125 [44:24<07:02, 1.01it/s]
|
| 84 |
+
2025-06-10 08:15:14,991 - __main__ - INFO - Epoch [17/27], Step [2700/3125], Loss: 2.4103, Perplexity: 11.1374
|
| 85 |
+
Epoch 17 Training: 90%|████████▉ | 2799/3125 [46:03<05:24, 1.00it/s]
|
| 86 |
+
2025-06-10 08:16:54,025 - __main__ - INFO - Epoch [17/27], Step [2800/3125], Loss: 2.4239, Perplexity: 11.2903
|
| 87 |
+
Epoch 17 Training: 93%|█████████▎| 2899/3125 [47:43<03:42, 1.02it/s]
|
| 88 |
+
2025-06-10 08:18:33,461 - __main__ - INFO - Epoch [17/27], Step [2900/3125], Loss: 2.6061, Perplexity: 13.5467
|
| 89 |
+
Epoch 17 Training: 96%|█████████▌| 2999/3125 [49:21<02:05, 1.00it/s]
|
| 90 |
+
2025-06-10 08:20:11,942 - __main__ - INFO - Epoch [17/27], Step [3000/3125], Loss: 2.3188, Perplexity: 10.1634
|
| 91 |
+
Epoch 17 Training: 99%|█████████▉| 3099/3125 [51:00<00:25, 1.01it/s]
|
| 92 |
+
2025-06-10 08:21:51,151 - __main__ - INFO - Epoch [17/27], Step [3100/3125], Loss: 2.3833, Perplexity: 10.8402
|
| 93 |
+
Epoch 17 Training: 100%|██████████| 3125/3125 [51:26<00:00, 1.01it/s]
|
| 94 |
+
2025-06-10 08:22:15,805 - __main__ - INFO - Epoch 17 Training finished. Avg Loss: 2.5127, Time: 3086.35s
|
| 95 |
+
Validation: 100%|██████████| 391/391 [11:34<00:00, 1.78s/it]
|
| 96 |
+
2025-06-10 08:33:50,046 - __main__ - INFO - Validation Avg Loss: 2.4818, Perplexity: 11.9623
|
| 97 |
+
2025-06-10 08:34:01,432 - __main__ - INFO - Validation BLEU-4: 0.1035
|
| 98 |
+
2025-06-10 08:34:01,433 - __main__ - INFO - Performing memory optimization after epoch...
|
| 99 |
+
2025-06-10 08:34:01,713 - __main__ - INFO - CUDA cache emptied.
|
| 100 |
+
2025-06-10 08:34:01,945 - __main__ - INFO - Python garbage collector run.
|
| 101 |
+
Epoch 18 Training: 3%|▎ | 99/3125 [01:40<48:46, 1.03it/s]
|
| 102 |
+
2025-06-10 08:35:43,887 - __main__ - INFO - Epoch [18/27], Step [100/3125], Loss: 2.5242, Perplexity: 12.4803
|
| 103 |
+
Epoch 18 Training: 6%|▋ | 199/3125 [03:20<47:57, 1.02it/s]
|
| 104 |
+
2025-06-10 08:37:22,956 - __main__ - INFO - Epoch [18/27], Step [200/3125], Loss: 2.5674, Perplexity: 13.0321
|
| 105 |
+
Epoch 18 Training: 10%|▉ | 299/3125 [04:59<46:50, 1.01it/s]
|
| 106 |
+
2025-06-10 08:39:02,407 - __main__ - INFO - Epoch [18/27], Step [300/3125], Loss: 2.4194, Perplexity: 11.2394
|
| 107 |
+
Epoch 18 Training: 13%|█▎ | 399/3125 [06:38<44:52, 1.01it/s]
|
| 108 |
+
2025-06-10 08:40:41,610 - __main__ - INFO - Epoch [18/27], Step [400/3125], Loss: 2.8139, Perplexity: 16.6747
|
| 109 |
+
Epoch 18 Training: 16%|█▌ | 499/3125 [08:17<42:37, 1.03it/s]
|
| 110 |
+
2025-06-10 08:42:20,012 - __main__ - INFO - Epoch [18/27], Step [500/3125], Loss: 2.3331, Perplexity: 10.3095
|
| 111 |
+
Epoch 18 Training: 19%|█▉ | 599/3125 [09:55<41:13, 1.02it/s]
|
| 112 |
+
2025-06-10 08:43:58,740 - __main__ - INFO - Epoch [18/27], Step [600/3125], Loss: 2.3093, Perplexity: 10.0678
|
| 113 |
+
Epoch 18 Training: 22%|██▏ | 699/3125 [11:35<39:36, 1.02it/s]
|
| 114 |
+
2025-06-10 08:45:38,180 - __main__ - INFO - Epoch [18/27], Step [700/3125], Loss: 2.3935, Perplexity: 10.9519
|
| 115 |
+
Epoch 18 Training: 26%|██▌ | 799/3125 [13:13<37:36, 1.03it/s]
|
| 116 |
+
2025-06-10 08:47:16,432 - __main__ - INFO - Epoch [18/27], Step [800/3125], Loss: 2.4676, Perplexity: 11.7936
|
| 117 |
+
Epoch 18 Training: 29%|██▉ | 899/3125 [14:52<36:09, 1.03it/s]
|
| 118 |
+
2025-06-10 08:48:55,636 - __main__ - INFO - Epoch [18/27], Step [900/3125], Loss: 2.4923, Perplexity: 12.0890
|
| 119 |
+
Epoch 18 Training: 32%|███▏ | 999/3125 [16:31<34:34, 1.02it/s]
|
| 120 |
+
2025-06-10 08:50:34,668 - __main__ - INFO - Epoch [18/27], Step [1000/3125], Loss: 2.3460, Perplexity: 10.4438
|
| 121 |
+
Epoch 18 Training: 35%|███▌ | 1099/3125 [18:10<33:19, 1.01it/s]
|
| 122 |
+
2025-06-10 08:52:13,854 - __main__ - INFO - Epoch [18/27], Step [1100/3125], Loss: 2.3353, Perplexity: 10.3324
|
| 123 |
+
Epoch 18 Training: 38%|███▊ | 1199/3125 [19:50<31:49, 1.01it/s]
|
| 124 |
+
2025-06-10 08:53:53,254 - __main__ - INFO - Epoch [18/27], Step [1200/3125], Loss: 2.6501, Perplexity: 14.1561
|
| 125 |
+
Epoch 18 Training: 42%|████▏ | 1299/3125 [21:30<30:17, 1.00it/s]
|
| 126 |
+
2025-06-10 08:55:33,187 - __main__ - INFO - Epoch [18/27], Step [1300/3125], Loss: 2.5033, Perplexity: 12.2222
|
| 127 |
+
Epoch 18 Training: 45%|████▍ | 1399/3125 [23:09<28:19, 1.02it/s]
|
| 128 |
+
2025-06-10 08:57:12,293 - __main__ - INFO - Epoch [18/27], Step [1400/3125], Loss: 2.5552, Perplexity: 12.8738
|
| 129 |
+
Epoch 18 Training: 48%|████▊ | 1499/3125 [24:48<26:55, 1.01it/s]
|
| 130 |
+
2025-06-10 08:58:51,613 - __main__ - INFO - Epoch [18/27], Step [1500/3125], Loss: 2.1927, Perplexity: 8.9596
|
| 131 |
+
Epoch 18 Training: 51%|█████ | 1599/3125 [26:27<25:18, 1.00it/s]
|
| 132 |
+
2025-06-10 09:00:30,661 - __main__ - INFO - Epoch [18/27], Step [1600/3125], Loss: 2.4970, Perplexity: 12.1465
|
| 133 |
+
Epoch 18 Training: 54%|█████▍ | 1699/3125 [28:06<23:17, 1.02it/s]
|
| 134 |
+
2025-06-10 09:02:09,514 - __main__ - INFO - Epoch [18/27], Step [1700/3125], Loss: 2.4935, Perplexity: 12.1037
|
| 135 |
+
Epoch 18 Training: 58%|█████▊ | 1799/3125 [29:45<21:57, 1.01it/s]
|
| 136 |
+
2025-06-10 09:03:48,633 - __main__ - INFO - Epoch [18/27], Step [1800/3125], Loss: 2.4783, Perplexity: 11.9213
|
| 137 |
+
Epoch 18 Training: 61%|██████ | 1899/3125 [31:24<20:28, 1.00s/it]
|
| 138 |
+
2025-06-10 09:05:27,649 - __main__ - INFO - Epoch [18/27], Step [1900/3125], Loss: 2.3436, Perplexity: 10.4189
|
| 139 |
+
Epoch 18 Training: 64%|██████▍ | 1999/3125 [33:03<18:17, 1.03it/s]
|
| 140 |
+
2025-06-10 09:07:06,719 - __main__ - INFO - Epoch [18/27], Step [2000/3125], Loss: 2.5853, Perplexity: 13.2677
|
| 141 |
+
Epoch 18 Training: 67%|██████▋ | 2099/3125 [34:42<16:47, 1.02it/s]
|
| 142 |
+
2025-06-10 09:08:45,283 - __main__ - INFO - Epoch [18/27], Step [2100/3125], Loss: 2.5161, Perplexity: 12.3804
|
| 143 |
+
Epoch 18 Training: 70%|███████ | 2199/3125 [36:21<15:34, 1.01s/it]
|
| 144 |
+
2025-06-10 09:10:24,189 - __main__ - INFO - Epoch [18/27], Step [2200/3125], Loss: 2.6254, Perplexity: 13.8102
|
| 145 |
+
Epoch 18 Training: 74%|███████▎ | 2299/3125 [38:00<13:23, 1.03it/s]
|
| 146 |
+
2025-06-10 09:12:03,789 - __main__ - INFO - Epoch [18/27], Step [2300/3125], Loss: 2.4902, Perplexity: 12.0631
|
| 147 |
+
Epoch 18 Training: 77%|███████▋ | 2399/3125 [39:39<11:57, 1.01it/s]
|
| 148 |
+
2025-06-10 09:13:42,698 - __main__ - INFO - Epoch [18/27], Step [2400/3125], Loss: 2.4329, Perplexity: 11.3913
|
| 149 |
+
Epoch 18 Training: 80%|███████▉ | 2499/3125 [41:18<10:27, 1.00s/it]
|
| 150 |
+
2025-06-10 09:15:21,802 - __main__ - INFO - Epoch [18/27], Step [2500/3125], Loss: 2.4294, Perplexity: 11.3520
|
| 151 |
+
Epoch 18 Training: 83%|████████▎ | 2599/3125 [42:58<08:45, 1.00it/s]
|
| 152 |
+
2025-06-10 09:17:01,212 - __main__ - INFO - Epoch [18/27], Step [2600/3125], Loss: 2.5354, Perplexity: 12.6210
|
| 153 |
+
Epoch 18 Training: 86%|████████▋ | 2699/3125 [44:37<06:51, 1.04it/s]
|
| 154 |
+
2025-06-10 09:18:40,318 - __main__ - INFO - Epoch [18/27], Step [2700/3125], Loss: 2.4877, Perplexity: 12.0333
|
| 155 |
+
Epoch 18 Training: 90%|████████▉ | 2799/3125 [46:16<05:21, 1.01it/s]
|
| 156 |
+
2025-06-10 09:20:19,433 - __main__ - INFO - Epoch [18/27], Step [2800/3125], Loss: 2.4673, Perplexity: 11.7911
|
| 157 |
+
Epoch 18 Training: 93%|█████████▎| 2899/3125 [47:56<03:50, 1.02s/it]
|
| 158 |
+
2025-06-10 09:21:59,119 - __main__ - INFO - Epoch [18/27], Step [2900/3125], Loss: 2.3145, Perplexity: 10.1199
|
| 159 |
+
Epoch 18 Training: 96%|█████████▌| 2999/3125 [49:35<02:05, 1.01it/s]
|
| 160 |
+
2025-06-10 09:23:38,775 - __main__ - INFO - Epoch [18/27], Step [3000/3125], Loss: 2.5194, Perplexity: 12.4214
|
| 161 |
+
Epoch 18 Training: 99%|█████████▉| 3099/3125 [51:14<00:25, 1.02it/s]
|
| 162 |
+
2025-06-10 09:25:17,977 - __main__ - INFO - Epoch [18/27], Step [3100/3125], Loss: 2.6512, Perplexity: 14.1717
|
| 163 |
+
Epoch 18 Training: 100%|██████████| 3125/3125 [51:40<00:00, 1.01it/s]
|
| 164 |
+
2025-06-10 09:25:42,823 - __main__ - INFO - Epoch 18 Training finished. Avg Loss: 2.4430, Time: 3100.88s
|
| 165 |
+
Validation: 100%|██████████| 391/391 [11:45<00:00, 1.80s/it]
|
| 166 |
+
2025-06-10 09:37:27,944 - __main__ - INFO - Validation Avg Loss: 2.4807, Perplexity: 11.9500
|
| 167 |
+
2025-06-10 09:37:37,250 - __main__ - INFO - Validation BLEU-4: 0.1054
|
| 168 |
+
2025-06-10 09:37:37,896 - __main__ - INFO - Saved best model checkpoint to ./output/best_model_bleu0.1054.pth
|
| 169 |
+
2025-06-10 09:37:37,897 - __main__ - INFO - Performing memory optimization after epoch...
|
| 170 |
+
2025-06-10 09:37:38,181 - __main__ - INFO - CUDA cache emptied.
|
| 171 |
+
2025-06-10 09:37:38,517 - __main__ - INFO - Python garbage collector run.
|
| 172 |
+
Epoch 19 Training: 3%|▎ | 99/3125 [01:40<49:53, 1.01it/s]
|
| 173 |
+
2025-06-10 09:39:20,412 - __main__ - INFO - Epoch [19/27], Step [100/3125], Loss: 2.3789, Perplexity: 10.7934
|
| 174 |
+
Epoch 19 Training: 6%|▋ | 199/3125 [03:20<47:55, 1.02it/s]
|
| 175 |
+
2025-06-10 09:40:59,969 - __main__ - INFO - Epoch [19/27], Step [200/3125], Loss: 2.4119, Perplexity: 11.1547
|
| 176 |
+
Epoch 19 Training: 10%|▉ | 299/3125 [04:59<46:40, 1.01it/s]
|
| 177 |
+
2025-06-10 09:42:39,188 - __main__ - INFO - Epoch [19/27], Step [300/3125], Loss: 2.4709, Perplexity: 11.8328
|
| 178 |
+
Epoch 19 Training: 13%|█▎ | 399/3125 [06:38<45:26, 1.00s/it]
|
| 179 |
+
2025-06-10 09:44:18,027 - __main__ - INFO - Epoch [19/27], Step [400/3125], Loss: 2.3014, Perplexity: 9.9881
|
| 180 |
+
Epoch 19 Training: 16%|█▌ | 499/3125 [08:17<43:21, 1.01it/s]
|
| 181 |
+
2025-06-10 09:45:56,904 - __main__ - INFO - Epoch [19/27], Step [500/3125], Loss: 2.5112, Perplexity: 12.3191
|
| 182 |
+
Epoch 19 Training: 19%|█▉ | 599/3125 [09:56<42:18, 1.00s/it]
|
| 183 |
+
2025-06-10 09:47:35,893 - __main__ - INFO - Epoch [19/27], Step [600/3125], Loss: 2.4034, Perplexity: 11.0610
|
| 184 |
+
Epoch 19 Training: 22%|██▏ | 699/3125 [11:35<39:49, 1.02it/s]
|
| 185 |
+
2025-06-10 09:49:15,424 - __main__ - INFO - Epoch [19/27], Step [700/3125], Loss: 2.4421, Perplexity: 11.4974
|
| 186 |
+
Epoch 19 Training: 26%|██▌ | 799/3125 [13:15<37:59, 1.02it/s]
|
| 187 |
+
2025-06-10 09:50:54,632 - __main__ - INFO - Epoch [19/27], Step [800/3125], Loss: 2.4358, Perplexity: 11.4253
|
| 188 |
+
Epoch 19 Training: 29%|██▉ | 899/3125 [14:53<36:45, 1.01it/s]
|
| 189 |
+
2025-06-10 09:52:33,475 - __main__ - INFO - Epoch [19/27], Step [900/3125], Loss: 2.4511, Perplexity: 11.6007
|
| 190 |
+
Epoch 19 Training: 32%|███▏ | 999/3125 [16:33<35:05, 1.01it/s]
|
| 191 |
+
2025-06-10 09:54:13,109 - __main__ - INFO - Epoch [19/27], Step [1000/3125], Loss: 2.3752, Perplexity: 10.7536
|
| 192 |
+
Epoch 19 Training: 35%|███▌ | 1099/3125 [18:12<33:12, 1.02it/s]
|
| 193 |
+
2025-06-10 09:55:52,508 - __main__ - INFO - Epoch [19/27], Step [1100/3125], Loss: 2.2818, Perplexity: 9.7943
|
| 194 |
+
Epoch 19 Training: 38%|███▊ | 1199/3125 [19:52<32:15, 1.01s/it]
|
| 195 |
+
2025-06-10 09:57:31,557 - __main__ - INFO - Epoch [19/27], Step [1200/3125], Loss: 2.5260, Perplexity: 12.5039
|
| 196 |
+
Epoch 19 Training: 42%|████▏ | 1299/3125 [21:31<29:53, 1.02it/s]
|
| 197 |
+
2025-06-10 09:59:10,940 - __main__ - INFO - Epoch [19/27], Step [1300/3125], Loss: 2.2350, Perplexity: 9.3461
|
| 198 |
+
Epoch 19 Training: 45%|████▍ | 1399/3125 [23:10<28:52, 1.00s/it]
|
| 199 |
+
2025-06-10 10:00:49,938 - __main__ - INFO - Epoch [19/27], Step [1400/3125], Loss: 2.5668, Perplexity: 13.0242
|
| 200 |
+
Epoch 19 Training: 48%|████▊ | 1499/3125 [24:49<27:07, 1.00s/it]
|
| 201 |
+
2025-06-10 10:02:29,195 - __main__ - INFO - Epoch [19/27], Step [1500/3125], Loss: 2.4380, Perplexity: 11.4499
|
| 202 |
+
Epoch 19 Training: 51%|█████ | 1599/3125 [26:28<24:53, 1.02it/s]
|
| 203 |
+
2025-06-10 10:04:08,447 - __main__ - INFO - Epoch [19/27], Step [1600/3125], Loss: 2.1895, Perplexity: 8.9306
|
| 204 |
+
Epoch 19 Training: 54%|█████▍ | 1699/3125 [28:08<23:49, 1.00s/it]
|
| 205 |
+
2025-06-10 10:05:47,701 - __main__ - INFO - Epoch [19/27], Step [1700/3125], Loss: 2.3286, Perplexity: 10.2640
|
| 206 |
+
Epoch 19 Training: 58%|█████▊ | 1799/3125 [29:47<21:43, 1.02it/s]
|
| 207 |
+
2025-06-10 10:07:26,770 - __main__ - INFO - Epoch [19/27], Step [1800/3125], Loss: 2.3863, Perplexity: 10.8737
|
| 208 |
+
Epoch 19 Training: 61%|██████ | 1899/3125 [31:26<20:06, 1.02it/s]
|
| 209 |
+
2025-06-10 10:09:06,544 - __main__ - INFO - Epoch [19/27], Step [1900/3125], Loss: 2.4867, Perplexity: 12.0217
|
| 210 |
+
Epoch 19 Training: 64%|██████▍ | 1999/3125 [33:06<18:29, 1.02it/s]
|
| 211 |
+
2025-06-10 10:10:45,538 - __main__ - INFO - Epoch [19/27], Step [2000/3125], Loss: 2.3649, Perplexity: 10.6430
|
| 212 |
+
Epoch 19 Training: 67%|██████▋ | 2099/3125 [34:44<16:54, 1.01it/s]
|
| 213 |
+
2025-06-10 10:12:24,330 - __main__ - INFO - Epoch [19/27], Step [2100/3125], Loss: 2.3546, Perplexity: 10.5342
|
| 214 |
+
Epoch 19 Training: 70%|███████ | 2199/3125 [36:24<15:24, 1.00it/s]
|
| 215 |
+
2025-06-10 10:14:03,624 - __main__ - INFO - Epoch [19/27], Step [2200/3125], Loss: 2.3941, Perplexity: 10.9579
|
| 216 |
+
Epoch 19 Training: 74%|███████▎ | 2299/3125 [38:02<13:28, 1.02it/s]
|
| 217 |
+
2025-06-10 10:15:42,466 - __main__ - INFO - Epoch [19/27], Step [2300/3125], Loss: 2.1938, Perplexity: 8.9695
|
| 218 |
+
Epoch 19 Training: 77%|███████▋ | 2399/3125 [39:41<12:09, 1.00s/it]
|
| 219 |
+
2025-06-10 10:17:21,479 - __main__ - INFO - Epoch [19/27], Step [2400/3125], Loss: 2.4041, Perplexity: 11.0679
|
| 220 |
+
Epoch 19 Training: 80%|███████▉ | 2499/3125 [41:20<10:23, 1.00it/s]
|
| 221 |
+
2025-06-10 10:19:00,375 - __main__ - INFO - Epoch [19/27], Step [2500/3125], Loss: 2.5131, Perplexity: 12.3433
|
| 222 |
+
Epoch 19 Training: 83%|████████▎ | 2599/3125 [43:00<08:52, 1.01s/it]
|
| 223 |
+
2025-06-10 10:20:39,698 - __main__ - INFO - Epoch [19/27], Step [2600/3125], Loss: 2.2205, Perplexity: 9.2123
|
| 224 |
+
Epoch 19 Training: 86%|████████▋ | 2699/3125 [44:39<07:02, 1.01it/s]
|
| 225 |
+
2025-06-10 10:22:19,043 - __main__ - INFO - Epoch [19/27], Step [2700/3125], Loss: 2.2930, Perplexity: 9.9044
|
| 226 |
+
Epoch 19 Training: 90%|████████▉ | 2799/3125 [46:18<05:21, 1.01it/s]
|
| 227 |
+
2025-06-10 10:23:58,189 - __main__ - INFO - Epoch [19/27], Step [2800/3125], Loss: 2.5673, Perplexity: 13.0307
|
| 228 |
+
Epoch 19 Training: 93%|█████████▎| 2899/3125 [47:58<03:44, 1.01it/s]
|
| 229 |
+
2025-06-10 10:25:37,764 - __main__ - INFO - Epoch [19/27], Step [2900/3125], Loss: 2.4287, Perplexity: 11.3445
|
| 230 |
+
Epoch 19 Training: 96%|█████████▌| 2999/3125 [49:37<02:05, 1.00it/s]
|
| 231 |
+
2025-06-10 10:27:17,138 - __main__ - INFO - Epoch [19/27], Step [3000/3125], Loss: 2.3494, Perplexity: 10.4788
|
| 232 |
+
Epoch 19 Training: 99%|█████████▉| 3099/3125 [51:17<00:25, 1.02it/s]
|
| 233 |
+
2025-06-10 10:28:56,764 - __main__ - INFO - Epoch [19/27], Step [3100/3125], Loss: 2.6807, Perplexity: 14.5951
|
| 234 |
+
Epoch 19 Training: 100%|██████████| 3125/3125 [51:43<00:00, 1.01it/s]
|
| 235 |
+
2025-06-10 10:29:21,832 - __main__ - INFO - Epoch 19 Training finished. Avg Loss: 2.3931, Time: 3103.31s
|
| 236 |
+
Validation: 100%|██████████| 391/391 [11:40<00:00, 1.79s/it]
|
| 237 |
+
2025-06-10 10:41:02,308 - __main__ - INFO - Validation Avg Loss: 2.4842, Perplexity: 11.9914
|
| 238 |
+
2025-06-10 10:41:11,596 - __main__ - INFO - Validation BLEU-4: 0.1053
|
| 239 |
+
2025-06-10 10:41:11,597 - __main__ - INFO - Performing memory optimization after epoch...
|
| 240 |
+
2025-06-10 10:41:11,861 - __main__ - INFO - CUDA cache emptied.
|
| 241 |
+
2025-06-10 10:41:12,194 - __main__ - INFO - Python garbage collector run.
|
| 242 |
+
Epoch 20 Training: 3%|▎ | 99/3125 [01:41<49:26, 1.02it/s]
|
| 243 |
+
2025-06-10 10:42:54,894 - __main__ - INFO - Epoch [20/27], Step [100/3125], Loss: 2.2876, Perplexity: 9.8510
|
| 244 |
+
Epoch 20 Training: 6%|▋ | 199/3125 [03:21<48:40, 1.00it/s]
|
| 245 |
+
2025-06-10 10:44:34,311 - __main__ - INFO - Epoch [20/27], Step [200/3125], Loss: 2.3219, Perplexity: 10.1953
|
| 246 |
+
Epoch 20 Training: 10%|▉ | 299/3125 [05:00<45:40, 1.03it/s]
|
| 247 |
+
2025-06-10 10:46:13,375 - __main__ - INFO - Epoch [20/27], Step [300/3125], Loss: 2.3180, Perplexity: 10.1558
|
| 248 |
+
Epoch 20 Training: 13%|█▎ | 399/3125 [06:38<44:53, 1.01it/s]
|
| 249 |
+
2025-06-10 10:47:52,154 - __main__ - INFO - Epoch [20/27], Step [400/3125], Loss: 2.2775, Perplexity: 9.7521
|
| 250 |
+
Epoch 20 Training: 16%|█▌ | 499/3125 [08:18<43:42, 1.00it/s]
|
| 251 |
+
2025-06-10 10:49:31,634 - __main__ - INFO - Epoch [20/27], Step [500/3125], Loss: 2.3627, Perplexity: 10.6199
|
| 252 |
+
Epoch 20 Training: 19%|█▉ | 599/3125 [09:57<41:42, 1.01it/s]
|
| 253 |
+
2025-06-10 10:51:10,386 - __main__ - INFO - Epoch [20/27], Step [600/3125], Loss: 2.5840, Perplexity: 13.2502
|
| 254 |
+
Epoch 20 Training: 22%|██▏ | 699/3125 [11:36<39:30, 1.02it/s]
|
| 255 |
+
2025-06-10 10:52:49,194 - __main__ - INFO - Epoch [20/27], Step [700/3125], Loss: 2.3991, Perplexity: 11.0130
|
| 256 |
+
Epoch 20 Training: 26%|██▌ | 799/3125 [13:15<38:23, 1.01it/s]
|
| 257 |
+
2025-06-10 10:54:28,248 - __main__ - INFO - Epoch [20/27], Step [800/3125], Loss: 2.3200, Perplexity: 10.1755
|
| 258 |
+
Epoch 20 Training: 29%|██▉ | 899/3125 [14:54<36:31, 1.02it/s]
|
| 259 |
+
2025-06-10 10:56:07,780 - __main__ - INFO - Epoch [20/27], Step [900/3125], Loss: 2.1218, Perplexity: 8.3458
|
| 260 |
+
Epoch 20 Training: 32%|███▏ | 999/3125 [16:33<34:45, 1.02it/s]
|
| 261 |
+
2025-06-10 10:57:46,489 - __main__ - INFO - Epoch [20/27], Step [1000/3125], Loss: 2.3538, Perplexity: 10.5252
|
| 262 |
+
Epoch 20 Training: 35%|███▌ | 1099/3125 [18:12<33:27, 1.01it/s]
|
| 263 |
+
2025-06-10 10:59:25,361 - __main__ - INFO - Epoch [20/27], Step [1100/3125], Loss: 2.2220, Perplexity: 9.2257
|
| 264 |
+
Epoch 20 Training: 38%|███▊ | 1199/3125 [19:51<31:32, 1.02it/s]
|
| 265 |
+
2025-06-10 11:01:04,348 - __main__ - INFO - Epoch [20/27], Step [1200/3125], Loss: 2.2933, Perplexity: 9.9077
|
| 266 |
+
Epoch 20 Training: 42%|████▏ | 1299/3125 [21:30<29:52, 1.02it/s]
|
| 267 |
+
2025-06-10 11:02:43,634 - __main__ - INFO - Epoch [20/27], Step [1300/3125], Loss: 2.4057, Perplexity: 11.0867
|
| 268 |
+
Epoch 20 Training: 45%|████▍ | 1399/3125 [23:09<28:58, 1.01s/it]
|
| 269 |
+
2025-06-10 11:04:22,597 - __main__ - INFO - Epoch [20/27], Step [1400/3125], Loss: 2.4458, Perplexity: 11.5401
|
| 270 |
+
Epoch 20 Training: 48%|████▊ | 1499/3125 [24:48<26:41, 1.02it/s]
|
| 271 |
+
2025-06-10 11:06:02,052 - __main__ - INFO - Epoch [20/27], Step [1500/3125], Loss: 2.2830, Perplexity: 9.8058
|
| 272 |
+
Epoch 20 Training: 51%|█████ | 1599/3125 [26:28<25:03, 1.02it/s]
|
| 273 |
+
2025-06-10 11:07:41,484 - __main__ - INFO - Epoch [20/27], Step [1600/3125], Loss: 2.3211, Perplexity: 10.1873
|
| 274 |
+
Epoch 20 Training: 54%|█████▍ | 1699/3125 [28:07<23:31, 1.01it/s]
|
| 275 |
+
2025-06-10 11:09:20,482 - __main__ - INFO - Epoch [20/27], Step [1700/3125], Loss: 2.4251, Perplexity: 11.3038
|
| 276 |
+
Epoch 20 Training: 58%|█████▊ | 1799/3125 [29:46<22:06, 1.00s/it]
|
| 277 |
+
2025-06-10 11:10:59,993 - __main__ - INFO - Epoch [20/27], Step [1800/3125], Loss: 2.3395, Perplexity: 10.3759
|
| 278 |
+
Epoch 20 Training: 61%|██████ | 1899/3125 [31:25<20:16, 1.01it/s]
|
| 279 |
+
2025-06-10 11:12:39,167 - __main__ - INFO - Epoch [20/27], Step [1900/3125], Loss: 2.5910, Perplexity: 13.3425
|
| 280 |
+
Epoch 20 Training: 64%|██████▍ | 1999/3125 [33:05<18:59, 1.01s/it]
|
| 281 |
+
2025-06-10 11:14:18,557 - __main__ - INFO - Epoch [20/27], Step [2000/3125], Loss: 2.2993, Perplexity: 9.9669
|
| 282 |
+
Epoch 20 Training: 67%|██████▋ | 2099/3125 [34:44<17:14, 1.01s/it]
|
| 283 |
+
2025-06-10 11:15:57,832 - __main__ - INFO - Epoch [20/27], Step [2100/3125], Loss: 2.1527, Perplexity: 8.6081
|
| 284 |
+
Epoch 20 Training: 70%|███████ | 2199/3125 [36:24<15:03, 1.02it/s]
|
| 285 |
+
2025-06-10 11:17:37,282 - __main__ - INFO - Epoch [20/27], Step [2200/3125], Loss: 2.3867, Perplexity: 10.8779
|
| 286 |
+
Epoch 20 Training: 74%|███████▎ | 2299/3125 [38:03<13:54, 1.01s/it]
|
| 287 |
+
2025-06-10 11:19:16,726 - __main__ - INFO - Epoch [20/27], Step [2300/3125], Loss: 2.3479, Perplexity: 10.4636
|
| 288 |
+
Epoch 20 Training: 77%|███████▋ | 2399/3125 [39:42<11:56, 1.01it/s]
|
| 289 |
+
2025-06-10 11:20:56,083 - __main__ - INFO - Epoch [20/27], Step [2400/3125], Loss: 2.2340, Perplexity: 9.3375
|
| 290 |
+
Epoch 20 Training: 80%|███████▉ | 2499/3125 [41:22<10:21, 1.01it/s]
|
| 291 |
+
2025-06-10 11:22:35,563 - __main__ - INFO - Epoch [20/27], Step [2500/3125], Loss: 2.3098, Perplexity: 10.0721
|
| 292 |
+
Epoch 20 Training: 83%|████████▎ | 2599/3125 [43:01<08:31, 1.03it/s]
|
| 293 |
+
2025-06-10 11:24:14,728 - __main__ - INFO - Epoch [20/27], Step [2600/3125], Loss: 2.3198, Perplexity: 10.1732
|
| 294 |
+
Epoch 20 Training: 86%|████████▋ | 2699/3125 [44:41<07:05, 1.00it/s]
|
| 295 |
+
2025-06-10 11:25:54,571 - __main__ - INFO - Epoch [20/27], Step [2700/3125], Loss: 2.3959, Perplexity: 10.9776
|
| 296 |
+
Epoch 20 Training: 90%|████████▉ | 2799/3125 [46:19<05:23, 1.01it/s]
|
| 297 |
+
2025-06-10 11:27:32,978 - __main__ - INFO - Epoch [20/27], Step [2800/3125], Loss: 2.7605, Perplexity: 15.8080
|
| 298 |
+
Epoch 20 Training: 93%|█████████▎| 2899/3125 [47:58<03:45, 1.00it/s]
|
| 299 |
+
2025-06-10 11:29:12,086 - __main__ - INFO - Epoch [20/27], Step [2900/3125], Loss: 2.4974, Perplexity: 12.1514
|
| 300 |
+
Epoch 20 Training: 96%|█████████▌| 2999/3125 [49:37<02:03, 1.02it/s]
|
| 301 |
+
2025-06-10 11:30:50,993 - __main__ - INFO - Epoch [20/27], Step [3000/3125], Loss: 2.4413, Perplexity: 11.4875
|
| 302 |
+
Epoch 20 Training: 99%|█████████▉| 3099/3125 [51:17<00:26, 1.00s/it]
|
| 303 |
+
2025-06-10 11:32:30,473 - __main__ - INFO - Epoch [20/27], Step [3100/3125], Loss: 2.3338, Perplexity: 10.3173
|
| 304 |
+
Epoch 20 Training: 100%|██████████| 3125/3125 [51:43<00:00, 1.01it/s]
|
| 305 |
+
2025-06-10 11:32:55,543 - __main__ - INFO - Epoch 20 Training finished. Avg Loss: 2.3498, Time: 3103.35s
|
| 306 |
+
Validation: 100%|██████████| 391/391 [11:41<00:00, 1.79s/it]
|
| 307 |
+
2025-06-10 11:44:37,028 - __main__ - INFO - Validation Avg Loss: 2.4874, Perplexity: 12.0298
|
| 308 |
+
2025-06-10 11:44:46,221 - __main__ - INFO - Validation BLEU-4: 0.1058
|
| 309 |
+
2025-06-10 11:44:46,914 - __main__ - INFO - Saved best model checkpoint to ./output/best_model_bleu0.1058.pth
|
| 310 |
+
2025-06-10 11:44:47,586 - __main__ - INFO - Saved periodic model checkpoint to ./output/model_epoch_20.pth
|
| 311 |
+
2025-06-10 11:44:47,587 - __main__ - INFO - Performing memory optimization after epoch...
|
| 312 |
+
2025-06-10 11:44:47,853 - __main__ - INFO - CUDA cache emptied.
|
| 313 |
+
2025-06-10 11:44:48,186 - __main__ - INFO - Python garbage collector run.
|
| 314 |
+
Epoch 21 Training: 3%|▎ | 99/3125 [01:40<48:40, 1.04it/s]
|
| 315 |
+
2025-06-10 11:46:29,972 - __main__ - INFO - Epoch [21/27], Step [100/3125], Loss: 2.1393, Perplexity: 8.4933
|
| 316 |
+
Epoch 21 Training: 6%|▋ | 199/3125 [03:20<47:37, 1.02it/s]
|
| 317 |
+
2025-06-10 11:48:09,315 - __main__ - INFO - Epoch [21/27], Step [200/3125], Loss: 2.3351, Perplexity: 10.3309
|
| 318 |
+
Epoch 21 Training: 10%|▉ | 299/3125 [04:59<47:30, 1.01s/it]
|
| 319 |
+
2025-06-10 11:49:48,545 - __main__ - INFO - Epoch [21/27], Step [300/3125], Loss: 2.0899, Perplexity: 8.0842
|
| 320 |
+
Epoch 21 Training: 13%|█▎ | 399/3125 [06:38<44:37, 1.02it/s]
|
| 321 |
+
2025-06-10 11:51:27,798 - __main__ - INFO - Epoch [21/27], Step [400/3125], Loss: 2.1491, Perplexity: 8.5775
|
| 322 |
+
Epoch 21 Training: 16%|█▌ | 499/3125 [08:17<43:33, 1.00it/s]
|
| 323 |
+
2025-06-10 11:53:06,975 - __main__ - INFO - Epoch [21/27], Step [500/3125], Loss: 2.2872, Perplexity: 9.8477
|
| 324 |
+
Epoch 21 Training: 19%|█▉ | 599/3125 [09:56<41:09, 1.02it/s]
|
| 325 |
+
2025-06-10 11:54:45,864 - __main__ - INFO - Epoch [21/27], Step [600/3125], Loss: 2.4272, Perplexity: 11.3273
|
| 326 |
+
Epoch 21 Training: 22%|██▏ | 699/3125 [11:35<39:33, 1.02it/s]
|
| 327 |
+
2025-06-10 11:56:24,485 - __main__ - INFO - Epoch [21/27], Step [700/3125], Loss: 2.1416, Perplexity: 8.5130
|
| 328 |
+
Epoch 21 Training: 26%|██▌ | 799/3125 [13:14<37:58, 1.02it/s]
|
| 329 |
+
2025-06-10 11:58:03,794 - __main__ - INFO - Epoch [21/27], Step [800/3125], Loss: 2.3899, Perplexity: 10.9122
|
| 330 |
+
Epoch 21 Training: 29%|██▉ | 899/3125 [14:54<36:35, 1.01it/s]
|
| 331 |
+
2025-06-10 11:59:43,688 - __main__ - INFO - Epoch [21/27], Step [900/3125], Loss: 2.3071, Perplexity: 10.0450
|
| 332 |
+
Epoch 21 Training: 32%|███▏ | 999/3125 [16:33<34:56, 1.01it/s]
|
| 333 |
+
2025-06-10 12:01:22,531 - __main__ - INFO - Epoch [21/27], Step [1000/3125], Loss: 2.1995, Perplexity: 9.0203
|
| 334 |
+
Epoch 21 Training: 35%|███▌ | 1099/3125 [18:12<33:03, 1.02it/s]
|
| 335 |
+
2025-06-10 12:03:01,611 - __main__ - INFO - Epoch [21/27], Step [1100/3125], Loss: 2.3339, Perplexity: 10.3183
|
| 336 |
+
Epoch 21 Training: 38%|███▊ | 1199/3125 [19:51<31:55, 1.01it/s]
|
| 337 |
+
2025-06-10 12:04:40,369 - __main__ - INFO - Epoch [21/27], Step [1200/3125], Loss: 2.4029, Perplexity: 11.0547
|
| 338 |
+
Epoch 21 Training: 42%|████▏ | 1299/3125 [21:30<29:42, 1.02it/s]
|
| 339 |
+
2025-06-10 12:06:19,291 - __main__ - INFO - Epoch [21/27], Step [1300/3125], Loss: 2.2694, Perplexity: 9.6740
|
| 340 |
+
Epoch 21 Training: 45%|████▍ | 1399/3125 [23:09<29:09, 1.01s/it]
|
| 341 |
+
2025-06-10 12:07:58,672 - __main__ - INFO - Epoch [21/27], Step [1400/3125], Loss: 2.1527, Perplexity: 8.6082
|
| 342 |
+
Epoch 21 Training: 48%|████▊ | 1499/3125 [24:48<27:00, 1.00it/s]
|
| 343 |
+
2025-06-10 12:09:37,343 - __main__ - INFO - Epoch [21/27], Step [1500/3125], Loss: 2.2131, Perplexity: 9.1442
|
| 344 |
+
Epoch 21 Training: 51%|█████ | 1599/3125 [26:26<25:42, 1.01s/it]
|
| 345 |
+
2025-06-10 12:11:16,155 - __main__ - INFO - Epoch [21/27], Step [1600/3125], Loss: 2.1473, Perplexity: 8.5615
|
| 346 |
+
Epoch 21 Training: 54%|█████▍ | 1699/3125 [28:05<23:07, 1.03it/s]
|
| 347 |
+
2025-06-10 12:12:55,135 - __main__ - INFO - Epoch [21/27], Step [1700/3125], Loss: 2.2490, Perplexity: 9.4778
|
| 348 |
+
Epoch 21 Training: 58%|█████▊ | 1799/3125 [29:45<21:42, 1.02it/s]
|
| 349 |
+
2025-06-10 12:14:34,267 - __main__ - INFO - Epoch [21/27], Step [1800/3125], Loss: 2.3484, Perplexity: 10.4684
|
| 350 |
+
Epoch 21 Training: 61%|██████ | 1899/3125 [31:24<20:08, 1.01it/s]
|
| 351 |
+
2025-06-10 12:16:13,587 - __main__ - INFO - Epoch [21/27], Step [1900/3125], Loss: 2.3690, Perplexity: 10.6865
|
| 352 |
+
Epoch 21 Training: 64%|██████▍ | 1999/3125 [33:03<18:07, 1.04it/s]
|
| 353 |
+
2025-06-10 12:17:52,694 - __main__ - INFO - Epoch [21/27], Step [2000/3125], Loss: 2.1483, Perplexity: 8.5702
|
| 354 |
+
Epoch 21 Training: 67%|██████▋ | 2099/3125 [34:42<17:02, 1.00it/s]
|
| 355 |
+
2025-06-10 12:19:31,958 - __main__ - INFO - Epoch [21/27], Step [2100/3125], Loss: 2.4676, Perplexity: 11.7938
|
| 356 |
+
Epoch 21 Training: 70%|███████ | 2199/3125 [36:21<15:05, 1.02it/s]
|
| 357 |
+
2025-06-10 12:21:10,625 - __main__ - INFO - Epoch [21/27], Step [2200/3125], Loss: 2.5696, Perplexity: 13.0607
|
| 358 |
+
Epoch 21 Training: 74%|███████▎ | 2299/3125 [38:00<13:55, 1.01s/it]
|
| 359 |
+
2025-06-10 12:22:49,585 - __main__ - INFO - Epoch [21/27], Step [2300/3125], Loss: 2.3604, Perplexity: 10.5955
|
| 360 |
+
Epoch 21 Training: 77%|███████▋ | 2399/3125 [39:39<11:56, 1.01it/s]
|
| 361 |
+
2025-06-10 12:24:28,578 - __main__ - INFO - Epoch [21/27], Step [2400/3125], Loss: 2.4663, Perplexity: 11.7783
|
| 362 |
+
Epoch 21 Training: 80%|███████▉ | 2499/3125 [41:18<10:26, 1.00s/it]
|
| 363 |
+
2025-06-10 12:26:07,929 - __main__ - INFO - Epoch [21/27], Step [2500/3125], Loss: 2.4053, Perplexity: 11.0819
|
| 364 |
+
Epoch 21 Training: 83%|████████▎ | 2599/3125 [42:57<08:41, 1.01it/s]
|
| 365 |
+
2025-06-10 12:27:46,767 - __main__ - INFO - Epoch [21/27], Step [2600/3125], Loss: 2.3557, Perplexity: 10.5451
|
| 366 |
+
Epoch 21 Training: 86%|████████▋ | 2699/3125 [44:36<06:58, 1.02it/s]
|
| 367 |
+
2025-06-10 12:29:25,781 - __main__ - INFO - Epoch [21/27], Step [2700/3125], Loss: 2.2723, Perplexity: 9.7018
|
| 368 |
+
Epoch 21 Training: 90%|████████▉ | 2799/3125 [46:15<05:16, 1.03it/s]
|
| 369 |
+
2025-06-10 12:31:04,767 - __main__ - INFO - Epoch [21/27], Step [2800/3125], Loss: 2.2502, Perplexity: 9.4895
|
| 370 |
+
Epoch 21 Training: 93%|█████████▎| 2899/3125 [47:54<03:45, 1.00it/s]
|
| 371 |
+
2025-06-10 12:32:43,808 - __main__ - INFO - Epoch [21/27], Step [2900/3125], Loss: 2.4847, Perplexity: 11.9973
|
| 372 |
+
Epoch 21 Training: 96%|█████████▌| 2999/3125 [49:33<02:02, 1.03it/s]
|
| 373 |
+
2025-06-10 12:34:22,740 - __main__ - INFO - Epoch [21/27], Step [3000/3125], Loss: 2.2226, Perplexity: 9.2317
|
| 374 |
+
Epoch 21 Training: 99%|█████████▉| 3099/3125 [51:13<00:25, 1.03it/s]
|
| 375 |
+
2025-06-10 12:36:02,355 - __main__ - INFO - Epoch [21/27], Step [3100/3125], Loss: 2.1203, Perplexity: 8.3340
|
| 376 |
+
Epoch 21 Training: 100%|██████████| 3125/3125 [51:39<00:00, 1.01it/s]
|
| 377 |
+
2025-06-10 12:36:27,232 - __main__ - INFO - Epoch 21 Training finished. Avg Loss: 2.3104, Time: 3099.04s
|
| 378 |
+
Validation: 100%|██████████| 391/391 [11:42<00:00, 1.80s/it]
|
| 379 |
+
2025-06-10 12:48:09,648 - __main__ - INFO - Validation Avg Loss: 2.4976, Perplexity: 12.1533
|
| 380 |
+
2025-06-10 12:48:18,948 - __main__ - INFO - Validation BLEU-4: 0.1039
|
| 381 |
+
2025-06-10 12:48:18,949 - __main__ - INFO - Performing memory optimization after epoch...
|
| 382 |
+
2025-06-10 12:48:19,238 - __main__ - INFO - CUDA cache emptied.
|
| 383 |
+
2025-06-10 12:48:19,573 - __main__ - INFO - Python garbage collector run.
|
| 384 |
+
Epoch 22 Training: 3%|▎ | 99/3125 [01:41<49:49, 1.01it/s]
|
| 385 |
+
2025-06-10 12:50:01,678 - __main__ - INFO - Epoch [22/27], Step [100/3125], Loss: 2.0841, Perplexity: 8.0371
|
| 386 |
+
Epoch 22 Training: 6%|▋ | 199/3125 [03:20<48:17, 1.01it/s]
|
| 387 |
+
2025-06-10 12:51:40,759 - __main__ - INFO - Epoch [22/27], Step [200/3125], Loss: 2.2103, Perplexity: 9.1183
|
| 388 |
+
Epoch 22 Training: 10%|▉ | 299/3125 [04:59<47:06, 1.00s/it]
|
| 389 |
+
2025-06-10 12:53:19,913 - __main__ - INFO - Epoch [22/27], Step [300/3125], Loss: 2.2659, Perplexity: 9.6397
|
| 390 |
+
Epoch 22 Training: 13%|█▎ | 399/3125 [06:38<44:47, 1.01it/s]
|
| 391 |
+
2025-06-10 12:54:58,861 - __main__ - INFO - Epoch [22/27], Step [400/3125], Loss: 2.4005, Perplexity: 11.0286
|
| 392 |
+
Epoch 22 Training: 16%|█▌ | 499/3125 [08:17<42:50, 1.02it/s]
|
| 393 |
+
2025-06-10 12:56:37,699 - __main__ - INFO - Epoch [22/27], Step [500/3125], Loss: 2.1922, Perplexity: 8.9553
|
| 394 |
+
Epoch 22 Training: 19%|█▉ | 599/3125 [09:56<41:26, 1.02it/s]
|
| 395 |
+
2025-06-10 12:58:16,583 - __main__ - INFO - Epoch [22/27], Step [600/3125], Loss: 2.3171, Perplexity: 10.1463
|
| 396 |
+
Epoch 22 Training: 22%|██▏ | 699/3125 [11:35<40:48, 1.01s/it]
|
| 397 |
+
2025-06-10 12:59:56,327 - __main__ - INFO - Epoch [22/27], Step [700/3125], Loss: 2.1564, Perplexity: 8.6396
|
| 398 |
+
Epoch 22 Training: 26%|██▌ | 799/3125 [13:14<38:34, 1.01it/s]
|
| 399 |
+
2025-06-10 13:01:35,149 - __main__ - INFO - Epoch [22/27], Step [800/3125], Loss: 2.3937, Perplexity: 10.9535
|
| 400 |
+
Epoch 22 Training: 29%|██▉ | 899/3125 [14:53<37:06, 1.00s/it]
|
| 401 |
+
2025-06-10 13:03:14,015 - __main__ - INFO - Epoch [22/27], Step [900/3125], Loss: 2.3248, Perplexity: 10.2245
|
| 402 |
+
Epoch 22 Training: 32%|███▏ | 999/3125 [16:32<34:50, 1.02it/s]
|
| 403 |
+
2025-06-10 13:04:52,893 - __main__ - INFO - Epoch [22/27], Step [1000/3125], Loss: 2.0701, Perplexity: 7.9253
|
| 404 |
+
Epoch 22 Training: 35%|███▌ | 1099/3125 [18:11<34:07, 1.01s/it]
|
| 405 |
+
2025-06-10 13:06:32,051 - __main__ - INFO - Epoch [22/27], Step [1100/3125], Loss: 2.1329, Perplexity: 8.4391
|
| 406 |
+
Epoch 22 Training: 38%|███▊ | 1199/3125 [19:50<32:07, 1.00s/it]
|
| 407 |
+
2025-06-10 13:08:11,551 - __main__ - INFO - Epoch [22/27], Step [1200/3125], Loss: 2.1940, Perplexity: 8.9706
|
| 408 |
+
Epoch 22 Training: 42%|████▏ | 1299/3125 [21:29<30:18, 1.00it/s]
|
| 409 |
+
2025-06-10 13:09:50,488 - __main__ - INFO - Epoch [22/27], Step [1300/3125], Loss: 2.4257, Perplexity: 11.3102
|
| 410 |
+
Epoch 22 Training: 45%|████▍ | 1399/3125 [23:08<28:25, 1.01it/s]
|
| 411 |
+
2025-06-10 13:11:29,499 - __main__ - INFO - Epoch [22/27], Step [1400/3125], Loss: 2.2594, Perplexity: 9.5774
|
| 412 |
+
Epoch 22 Training: 48%|████▊ | 1499/3125 [24:48<26:36, 1.02it/s]
|
| 413 |
+
2025-06-10 13:13:09,191 - __main__ - INFO - Epoch [22/27], Step [1500/3125], Loss: 2.2953, Perplexity: 9.9279
|
| 414 |
+
Epoch 22 Training: 51%|█████ | 1599/3125 [26:27<25:30, 1.00s/it]
|
| 415 |
+
2025-06-10 13:14:48,399 - __main__ - INFO - Epoch [22/27], Step [1600/3125], Loss: 2.3245, Perplexity: 10.2215
|
| 416 |
+
Epoch 22 Training: 54%|█████▍ | 1699/3125 [28:07<23:44, 1.00it/s]
|
| 417 |
+
2025-06-10 13:16:27,617 - __main__ - INFO - Epoch [22/27], Step [1700/3125], Loss: 2.3146, Perplexity: 10.1208
|
| 418 |
+
Epoch 22 Training: 58%|█████▊ | 1799/3125 [29:46<22:01, 1.00it/s]
|
| 419 |
+
2025-06-10 13:18:07,329 - __main__ - INFO - Epoch [22/27], Step [1800/3125], Loss: 2.3918, Perplexity: 10.9335
|
| 420 |
+
Epoch 22 Training: 61%|██████ | 1899/3125 [31:25<20:35, 1.01s/it]
|
| 421 |
+
2025-06-10 13:19:46,339 - __main__ - INFO - Epoch [22/27], Step [1900/3125], Loss: 2.4785, Perplexity: 11.9235
|
| 422 |
+
Epoch 22 Training: 64%|██████▍ | 1999/3125 [33:05<18:42, 1.00it/s]
|
| 423 |
+
2025-06-10 13:21:25,781 - __main__ - INFO - Epoch [22/27], Step [2000/3125], Loss: 2.2433, Perplexity: 9.4248
|
| 424 |
+
Epoch 22 Training: 67%|██████▋ | 2099/3125 [34:44<17:05, 1.00it/s]
|
| 425 |
+
2025-06-10 13:23:05,202 - __main__ - INFO - Epoch [22/27], Step [2100/3125], Loss: 2.3151, Perplexity: 10.1256
|
| 426 |
+
Epoch 22 Training: 70%|███████ | 2199/3125 [36:23<15:14, 1.01it/s]
|
| 427 |
+
2025-06-10 13:24:44,554 - __main__ - INFO - Epoch [22/27], Step [2200/3125], Loss: 2.1862, Perplexity: 8.9009
|
| 428 |
+
Epoch 22 Training: 74%|███████▎ | 2299/3125 [38:03<13:35, 1.01it/s]
|
| 429 |
+
2025-06-10 13:26:23,951 - __main__ - INFO - Epoch [22/27], Step [2300/3125], Loss: 2.4228, Perplexity: 11.2773
|
| 430 |
+
Epoch 22 Training: 77%|███████▋ | 2399/3125 [39:42<12:02, 1.00it/s]
|
| 431 |
+
2025-06-10 13:28:03,210 - __main__ - INFO - Epoch [22/27], Step [2400/3125], Loss: 2.2062, Perplexity: 9.0816
|
| 432 |
+
Epoch 22 Training: 80%|███████▉ | 2499/3125 [41:21<10:24, 1.00it/s]
|
| 433 |
+
2025-06-10 13:29:42,178 - __main__ - INFO - Epoch [22/27], Step [2500/3125], Loss: 2.1243, Perplexity: 8.3674
|
| 434 |
+
Epoch 22 Training: 83%|████████▎ | 2599/3125 [43:00<08:43, 1.00it/s]
|
| 435 |
+
2025-06-10 13:31:21,309 - __main__ - INFO - Epoch [22/27], Step [2600/3125], Loss: 2.3792, Perplexity: 10.7965
|
| 436 |
+
Epoch 22 Training: 86%|████████▋ | 2699/3125 [44:39<06:57, 1.02it/s]
|
| 437 |
+
2025-06-10 13:32:59,845 - __main__ - INFO - Epoch [22/27], Step [2700/3125], Loss: 2.3259, Perplexity: 10.2359
|
| 438 |
+
Epoch 22 Training: 90%|████████▉ | 2799/3125 [46:18<05:31, 1.02s/it]
|
| 439 |
+
2025-06-10 13:34:39,330 - __main__ - INFO - Epoch [22/27], Step [2800/3125], Loss: 2.4015, Perplexity: 11.0399
|
| 440 |
+
Epoch 22 Training: 93%|█████████▎| 2899/3125 [47:58<03:46, 1.00s/it]
|
| 441 |
+
2025-06-10 13:36:18,749 - __main__ - INFO - Epoch [22/27], Step [2900/3125], Loss: 2.5032, Perplexity: 12.2218
|
| 442 |
+
Epoch 22 Training: 96%|█████████▌| 2999/3125 [49:37<02:06, 1.00s/it]
|
| 443 |
+
2025-06-10 13:37:57,726 - __main__ - INFO - Epoch [22/27], Step [3000/3125], Loss: 2.1186, Perplexity: 8.3195
|
| 444 |
+
Epoch 22 Training: 99%|█████████▉| 3099/3125 [51:16<00:25, 1.02it/s]
|
| 445 |
+
2025-06-10 13:39:36,968 - __main__ - INFO - Epoch [22/27], Step [3100/3125], Loss: 2.3263, Perplexity: 10.2401
|
| 446 |
+
Epoch 22 Training: 100%|██████████| 3125/3125 [51:42<00:00, 1.01it/s]
|
| 447 |
+
2025-06-10 13:40:02,249 - __main__ - INFO - Epoch 22 Training finished. Avg Loss: 2.2757, Time: 3102.67s
|
| 448 |
+
Validation: 100%|██████████| 391/391 [11:48<00:00, 1.81s/it]
|
| 449 |
+
2025-06-10 13:51:50,314 - __main__ - INFO - Validation Avg Loss: 2.5026, Perplexity: 12.2138
|
| 450 |
+
2025-06-10 13:51:59,691 - __main__ - INFO - Validation BLEU-4: 0.1045
|
| 451 |
+
2025-06-10 13:51:59,691 - __main__ - INFO - Performing memory optimization after epoch...
|
| 452 |
+
2025-06-10 13:51:59,966 - __main__ - INFO - CUDA cache emptied.
|
| 453 |
+
2025-06-10 13:52:00,297 - __main__ - INFO - Python garbage collector run.
|
| 454 |
+
Epoch 23 Training: 3%|▎ | 99/3125 [01:41<49:12, 1.02it/s]
|
| 455 |
+
2025-06-10 13:53:42,343 - __main__ - INFO - Epoch [23/27], Step [100/3125], Loss: 2.2735, Perplexity: 9.7134
|
| 456 |
+
Epoch 23 Training: 6%|▋ | 199/3125 [03:20<47:52, 1.02it/s]
|
| 457 |
+
2025-06-10 13:55:21,824 - __main__ - INFO - Epoch [23/27], Step [200/3125], Loss: 2.1850, Perplexity: 8.8906
|
| 458 |
+
Epoch 23 Training: 10%|▉ | 299/3125 [04:59<46:41, 1.01it/s]
|
| 459 |
+
2025-06-10 13:57:00,821 - __main__ - INFO - Epoch [23/27], Step [300/3125], Loss: 2.2903, Perplexity: 9.8783
|
| 460 |
+
Epoch 23 Training: 13%|█▎ | 399/3125 [06:38<44:17, 1.03it/s]
|
| 461 |
+
2025-06-10 13:58:39,930 - __main__ - INFO - Epoch [23/27], Step [400/3125], Loss: 2.4636, Perplexity: 11.7469
|
| 462 |
+
Epoch 23 Training: 16%|█▌ | 499/3125 [08:17<43:03, 1.02it/s]
|
| 463 |
+
2025-06-10 14:00:19,257 - __main__ - INFO - Epoch [23/27], Step [500/3125], Loss: 2.2620, Perplexity: 9.6028
|
| 464 |
+
Epoch 23 Training: 19%|█▉ | 599/3125 [09:57<41:46, 1.01it/s]
|
| 465 |
+
2025-06-10 14:01:58,718 - __main__ - INFO - Epoch [23/27], Step [600/3125], Loss: 2.2474, Perplexity: 9.4631
|
| 466 |
+
Epoch 23 Training: 22%|██▏ | 699/3125 [11:36<39:22, 1.03it/s]
|
| 467 |
+
2025-06-10 14:03:37,859 - __main__ - INFO - Epoch [23/27], Step [700/3125], Loss: 2.1001, Perplexity: 8.1667
|
| 468 |
+
Epoch 23 Training: 26%|██▌ | 799/3125 [13:15<39:03, 1.01s/it]
|
| 469 |
+
2025-06-10 14:05:16,383 - __main__ - INFO - Epoch [23/27], Step [800/3125], Loss: 2.1119, Perplexity: 8.2638
|
| 470 |
+
Epoch 23 Training: 29%|██▉ | 899/3125 [14:54<37:51, 1.02s/it]
|
| 471 |
+
2025-06-10 14:06:55,867 - __main__ - INFO - Epoch [23/27], Step [900/3125], Loss: 2.2211, Perplexity: 9.2171
|
| 472 |
+
Epoch 23 Training: 32%|███▏ | 999/3125 [16:34<35:23, 1.00it/s]
|
| 473 |
+
2025-06-10 14:08:35,387 - __main__ - INFO - Epoch [23/27], Step [1000/3125], Loss: 2.2420, Perplexity: 9.4120
|
| 474 |
+
Epoch 23 Training: 35%|███▌ | 1099/3125 [18:13<34:31, 1.02s/it]
|
| 475 |
+
2025-06-10 14:10:14,380 - __main__ - INFO - Epoch [23/27], Step [1100/3125], Loss: 2.1189, Perplexity: 8.3216
|
| 476 |
+
Epoch 23 Training: 38%|███▊ | 1199/3125 [19:52<31:17, 1.03it/s]
|
| 477 |
+
2025-06-10 14:11:53,614 - __main__ - INFO - Epoch [23/27], Step [1200/3125], Loss: 2.1247, Perplexity: 8.3700
|
| 478 |
+
Epoch 23 Training: 42%|████▏ | 1299/3125 [21:31<29:57, 1.02it/s]
|
| 479 |
+
2025-06-10 14:13:32,955 - __main__ - INFO - Epoch [23/27], Step [1300/3125], Loss: 2.1127, Perplexity: 8.2704
|
| 480 |
+
Epoch 23 Training: 45%|████▍ | 1399/3125 [23:10<28:32, 1.01it/s]
|
| 481 |
+
2025-06-10 14:15:12,031 - __main__ - INFO - Epoch [23/27], Step [1400/3125], Loss: 2.1020, Perplexity: 8.1822
|
| 482 |
+
Epoch 23 Training: 48%|████▊ | 1499/3125 [24:49<27:27, 1.01s/it]
|
| 483 |
+
2025-06-10 14:16:51,107 - __main__ - INFO - Epoch [23/27], Step [1500/3125], Loss: 2.2269, Perplexity: 9.2714
|
| 484 |
+
Epoch 23 Training: 51%|█████ | 1599/3125 [26:29<25:11, 1.01it/s]
|
| 485 |
+
2025-06-10 14:18:30,314 - __main__ - INFO - Epoch [23/27], Step [1600/3125], Loss: 2.1121, Perplexity: 8.2657
|
| 486 |
+
Epoch 23 Training: 54%|█████▍ | 1699/3125 [28:08<23:24, 1.02it/s]
|
| 487 |
+
2025-06-10 14:20:09,761 - __main__ - INFO - Epoch [23/27], Step [1700/3125], Loss: 1.9466, Perplexity: 7.0051
|
| 488 |
+
Epoch 23 Training: 58%|█████▊ | 1799/3125 [29:47<21:55, 1.01it/s]
|
| 489 |
+
2025-06-10 14:21:48,846 - __main__ - INFO - Epoch [23/27], Step [1800/3125], Loss: 2.2108, Perplexity: 9.1232
|
| 490 |
+
Epoch 23 Training: 61%|██████ | 1899/3125 [31:26<20:11, 1.01it/s]
|
| 491 |
+
2025-06-10 14:23:28,059 - __main__ - INFO - Epoch [23/27], Step [1900/3125], Loss: 2.2285, Perplexity: 9.2856
|
| 492 |
+
Epoch 23 Training: 64%|██████▍ | 1999/3125 [33:05<18:24, 1.02it/s]
|
| 493 |
+
2025-06-10 14:25:06,867 - __main__ - INFO - Epoch [23/27], Step [2000/3125], Loss: 2.2417, Perplexity: 9.4092
|
| 494 |
+
Epoch 23 Training: 67%|██████▋ | 2099/3125 [34:44<16:53, 1.01it/s]
|
| 495 |
+
2025-06-10 14:26:45,881 - __main__ - INFO - Epoch [23/27], Step [2100/3125], Loss: 2.2783, Perplexity: 9.7597
|
| 496 |
+
Epoch 23 Training: 70%|███████ | 2199/3125 [36:24<15:29, 1.00s/it]
|
| 497 |
+
2025-06-10 14:28:25,408 - __main__ - INFO - Epoch [23/27], Step [2200/3125], Loss: 2.1256, Perplexity: 8.3781
|
| 498 |
+
Epoch 23 Training: 74%|███████▎ | 2299/3125 [38:03<13:27, 1.02it/s]
|
| 499 |
+
2025-06-10 14:30:04,667 - __main__ - INFO - Epoch [23/27], Step [2300/3125], Loss: 2.4059, Perplexity: 11.0888
|
| 500 |
+
Epoch 23 Training: 77%|███████▋ | 2399/3125 [39:42<11:53, 1.02it/s]
|
| 501 |
+
2025-06-10 14:31:44,014 - __main__ - INFO - Epoch [23/27], Step [2400/3125], Loss: 2.2476, Perplexity: 9.4653
|
| 502 |
+
Epoch 23 Training: 80%|███████▉ | 2499/3125 [41:22<10:48, 1.04s/it]
|
| 503 |
+
2025-06-10 14:33:23,465 - __main__ - INFO - Epoch [23/27], Step [2500/3125], Loss: 1.9663, Perplexity: 7.1443
|
| 504 |
+
Epoch 23 Training: 83%|████████▎ | 2599/3125 [43:01<08:45, 1.00it/s]
|
| 505 |
+
2025-06-10 14:35:02,976 - __main__ - INFO - Epoch [23/27], Step [2600/3125], Loss: 2.2005, Perplexity: 9.0293
|
| 506 |
+
Epoch 23 Training: 86%|████████▋ | 2699/3125 [44:40<07:02, 1.01it/s]
|
| 507 |
+
2025-06-10 14:36:42,183 - __main__ - INFO - Epoch [23/27], Step [2700/3125], Loss: 2.2762, Perplexity: 9.7399
|
| 508 |
+
Epoch 23 Training: 90%|████████▉ | 2799/3125 [46:19<05:18, 1.02it/s]
|
| 509 |
+
2025-06-10 14:38:21,135 - __main__ - INFO - Epoch [23/27], Step [2800/3125], Loss: 2.3507, Perplexity: 10.4930
|
| 510 |
+
Epoch 23 Training: 93%|█████████▎| 2899/3125 [47:59<03:43, 1.01it/s]
|
| 511 |
+
2025-06-10 14:40:00,701 - __main__ - INFO - Epoch [23/27], Step [2900/3125], Loss: 2.1719, Perplexity: 8.7753
|
| 512 |
+
Epoch 23 Training: 96%|█████████▌| 2999/3125 [49:38<02:03, 1.02it/s]
|
| 513 |
+
2025-06-10 14:41:39,941 - __main__ - INFO - Epoch [23/27], Step [3000/3125], Loss: 2.1339, Perplexity: 8.4474
|
| 514 |
+
Epoch 23 Training: 99%|█████████▉| 3099/3125 [51:18<00:25, 1.02it/s]
|
| 515 |
+
2025-06-10 14:43:19,557 - __main__ - INFO - Epoch [23/27], Step [3100/3125], Loss: 2.3432, Perplexity: 10.4140
|
| 516 |
+
Epoch 23 Training: 100%|██████████| 3125/3125 [51:44<00:00, 1.01it/s]
|
| 517 |
+
2025-06-10 14:43:44,527 - __main__ - INFO - Epoch 23 Training finished. Avg Loss: 2.2447, Time: 3104.23s
|
| 518 |
+
Validation: 100%|██████████| 391/391 [11:44<00:00, 1.80s/it]
|
| 519 |
+
2025-06-10 14:55:28,836 - __main__ - INFO - Validation Avg Loss: 2.5057, Perplexity: 12.2519
|
| 520 |
+
2025-06-10 14:55:38,160 - __main__ - INFO - Validation BLEU-4: 0.1043
|
| 521 |
+
2025-06-10 14:55:38,161 - __main__ - INFO - Performing memory optimization after epoch...
|
| 522 |
+
2025-06-10 14:55:38,437 - __main__ - INFO - CUDA cache emptied.
|
| 523 |
+
2025-06-10 14:55:38,774 - __main__ - INFO - Python garbage collector run.
|
| 524 |
+
Epoch 24 Training: 3%|▎ | 99/3125 [01:40<48:49, 1.03it/s]
|
| 525 |
+
2025-06-10 14:57:20,220 - __main__ - INFO - Epoch [24/27], Step [100/3125], Loss: 2.3766, Perplexity: 10.7685
|
| 526 |
+
Epoch 24 Training: 6%|▋ | 199/3125 [03:19<48:06, 1.01it/s]
|
| 527 |
+
2025-06-10 14:58:59,374 - __main__ - INFO - Epoch [24/27], Step [200/3125], Loss: 2.2492, Perplexity: 9.4799
|
| 528 |
+
Epoch 24 Training: 10%|▉ | 299/3125 [04:58<46:43, 1.01it/s]
|
| 529 |
+
2025-06-10 15:00:38,692 - __main__ - INFO - Epoch [24/27], Step [300/3125], Loss: 2.0896, Perplexity: 8.0816
|
| 530 |
+
Epoch 24 Training: 13%|█▎ | 399/3125 [06:38<44:56, 1.01it/s]
|
| 531 |
+
2025-06-10 15:02:17,779 - __main__ - INFO - Epoch [24/27], Step [400/3125], Loss: 2.1230, Perplexity: 8.3560
|
| 532 |
+
Epoch 24 Training: 16%|█▌ | 499/3125 [08:17<43:40, 1.00it/s]
|
| 533 |
+
2025-06-10 15:03:56,858 - __main__ - INFO - Epoch [24/27], Step [500/3125], Loss: 2.2929, Perplexity: 9.9039
|
| 534 |
+
Epoch 24 Training: 19%|█▉ | 599/3125 [09:56<42:13, 1.00s/it]
|
| 535 |
+
2025-06-10 15:05:35,920 - __main__ - INFO - Epoch [24/27], Step [600/3125], Loss: 2.2186, Perplexity: 9.1948
|
| 536 |
+
Epoch 24 Training: 22%|██▏ | 699/3125 [11:35<39:55, 1.01it/s]
|
| 537 |
+
2025-06-10 15:07:15,231 - __main__ - INFO - Epoch [24/27], Step [700/3125], Loss: 2.3652, Perplexity: 10.6457
|
| 538 |
+
Epoch 24 Training: 26%|██▌ | 799/3125 [13:15<39:08, 1.01s/it]
|
| 539 |
+
2025-06-10 15:08:54,829 - __main__ - INFO - Epoch [24/27], Step [800/3125], Loss: 2.4291, Perplexity: 11.3490
|
| 540 |
+
Epoch 24 Training: 29%|██▉ | 899/3125 [14:54<37:18, 1.01s/it]
|
| 541 |
+
2025-06-10 15:10:34,047 - __main__ - INFO - Epoch [24/27], Step [900/3125], Loss: 2.0992, Perplexity: 8.1598
|
| 542 |
+
Epoch 24 Training: 32%|███▏ | 999/3125 [16:33<35:14, 1.01it/s]
|
| 543 |
+
2025-06-10 15:12:13,251 - __main__ - INFO - Epoch [24/27], Step [1000/3125], Loss: 2.2295, Perplexity: 9.2953
|
| 544 |
+
Epoch 24 Training: 35%|███▌ | 1099/3125 [18:12<33:32, 1.01it/s]
|
| 545 |
+
2025-06-10 15:13:52,348 - __main__ - INFO - Epoch [24/27], Step [1100/3125], Loss: 2.2423, Perplexity: 9.4153
|
| 546 |
+
Epoch 24 Training: 38%|███▊ | 1199/3125 [19:51<31:34, 1.02it/s]
|
| 547 |
+
2025-06-10 15:15:31,270 - __main__ - INFO - Epoch [24/27], Step [1200/3125], Loss: 2.1982, Perplexity: 9.0089
|
| 548 |
+
Epoch 24 Training: 42%|████▏ | 1299/3125 [21:30<30:16, 1.00it/s]
|
| 549 |
+
2025-06-10 15:17:10,504 - __main__ - INFO - Epoch [24/27], Step [1300/3125], Loss: 2.3898, Perplexity: 10.9117
|
| 550 |
+
Epoch 24 Training: 45%|████▍ | 1399/3125 [23:10<29:03, 1.01s/it]
|
| 551 |
+
2025-06-10 15:18:49,778 - __main__ - INFO - Epoch [24/27], Step [1400/3125], Loss: 2.4188, Perplexity: 11.2319
|
| 552 |
+
Epoch 24 Training: 48%|████▊ | 1499/3125 [24:48<26:26, 1.02it/s]
|
| 553 |
+
2025-06-10 15:20:28,636 - __main__ - INFO - Epoch [24/27], Step [1500/3125], Loss: 2.2394, Perplexity: 9.3875
|
| 554 |
+
Epoch 24 Training: 51%|█████ | 1599/3125 [26:27<24:59, 1.02it/s]
|
| 555 |
+
2025-06-10 15:22:07,698 - __main__ - INFO - Epoch [24/27], Step [1600/3125], Loss: 2.3871, Perplexity: 10.8814
|
| 556 |
+
Epoch 24 Training: 54%|█████▍ | 1699/3125 [28:07<23:57, 1.01s/it]
|
| 557 |
+
2025-06-10 15:23:46,949 - __main__ - INFO - Epoch [24/27], Step [1700/3125], Loss: 2.4062, Perplexity: 11.0917
|
| 558 |
+
Epoch 24 Training: 58%|█████▊ | 1799/3125 [29:45<21:37, 1.02it/s]
|
| 559 |
+
2025-06-10 15:25:25,232 - __main__ - INFO - Epoch [24/27], Step [1800/3125], Loss: 2.2069, Perplexity: 9.0873
|
| 560 |
+
Epoch 24 Training: 61%|██████ | 1899/3125 [31:24<19:42, 1.04it/s]
|
| 561 |
+
2025-06-10 15:27:04,432 - __main__ - INFO - Epoch [24/27], Step [1900/3125], Loss: 2.1929, Perplexity: 8.9615
|
| 562 |
+
Epoch 24 Training: 64%|██████▍ | 1999/3125 [33:04<19:03, 1.02s/it]
|
| 563 |
+
2025-06-10 15:28:43,830 - __main__ - INFO - Epoch [24/27], Step [2000/3125], Loss: 2.2991, Perplexity: 9.9652
|
| 564 |
+
Epoch 24 Training: 67%|██████▋ | 2099/3125 [34:43<16:56, 1.01it/s]
|
| 565 |
+
2025-06-10 15:30:22,979 - __main__ - INFO - Epoch [24/27], Step [2100/3125], Loss: 2.2047, Perplexity: 9.0674
|
| 566 |
+
Epoch 24 Training: 70%|███████ | 2199/3125 [36:22<15:04, 1.02it/s]
|
| 567 |
+
2025-06-10 15:32:01,941 - __main__ - INFO - Epoch [24/27], Step [2200/3125], Loss: 2.1788, Perplexity: 8.8360
|
| 568 |
+
Epoch 24 Training: 74%|███████▎ | 2299/3125 [38:01<13:39, 1.01it/s]
|
| 569 |
+
2025-06-10 15:33:41,424 - __main__ - INFO - Epoch [24/27], Step [2300/3125], Loss: 2.3368, Perplexity: 10.3484
|
| 570 |
+
Epoch 24 Training: 77%|███████▋ | 2399/3125 [39:41<12:17, 1.02s/it]
|
| 571 |
+
2025-06-10 15:35:20,892 - __main__ - INFO - Epoch [24/27], Step [2400/3125], Loss: 2.3685, Perplexity: 10.6811
|
| 572 |
+
Epoch 24 Training: 80%|███████▉ | 2499/3125 [41:20<10:39, 1.02s/it]
|
| 573 |
+
2025-06-10 15:37:00,224 - __main__ - INFO - Epoch [24/27], Step [2500/3125], Loss: 2.1582, Perplexity: 8.6555
|
| 574 |
+
Epoch 24 Training: 83%|████████▎ | 2599/3125 [42:59<08:50, 1.01s/it]
|
| 575 |
+
2025-06-10 15:38:39,540 - __main__ - INFO - Epoch [24/27], Step [2600/3125], Loss: 2.2999, Perplexity: 9.9734
|
| 576 |
+
Epoch 24 Training: 86%|████████▋ | 2699/3125 [44:39<07:09, 1.01s/it]
|
| 577 |
+
2025-06-10 15:40:19,212 - __main__ - INFO - Epoch [24/27], Step [2700/3125], Loss: 2.1185, Perplexity: 8.3184
|
| 578 |
+
Epoch 24 Training: 90%|████████▉ | 2799/3125 [46:19<05:28, 1.01s/it]
|
| 579 |
+
2025-06-10 15:41:59,136 - __main__ - INFO - Epoch [24/27], Step [2800/3125], Loss: 2.5695, Perplexity: 13.0598
|
| 580 |
+
Epoch 24 Training: 93%|█████████▎| 2899/3125 [47:58<03:46, 1.00s/it]
|
| 581 |
+
2025-06-10 15:43:37,941 - __main__ - INFO - Epoch [24/27], Step [2900/3125], Loss: 2.2560, Perplexity: 9.5450
|
| 582 |
+
Epoch 24 Training: 96%|█████████▌| 2999/3125 [49:37<02:04, 1.01it/s]
|
| 583 |
+
2025-06-10 15:45:17,249 - __main__ - INFO - Epoch [24/27], Step [3000/3125], Loss: 2.3286, Perplexity: 10.2635
|
| 584 |
+
Epoch 24 Training: 99%|█████████▉| 3099/3125 [51:16<00:25, 1.02it/s]
|
| 585 |
+
2025-06-10 15:46:56,315 - __main__ - INFO - Epoch [24/27], Step [3100/3125], Loss: 2.2094, Perplexity: 9.1106
|
| 586 |
+
Epoch 24 Training: 100%|██████████| 3125/3125 [51:42<00:00, 1.01it/s]
|
| 587 |
+
2025-06-10 15:47:21,178 - __main__ - INFO - Epoch 24 Training finished. Avg Loss: 2.2160, Time: 3102.40s
|
| 588 |
+
Validation: 100%|██████████| 391/391 [11:40<00:00, 1.79s/it]
|
| 589 |
+
2025-06-10 15:59:02,154 - __main__ - INFO - Validation Avg Loss: 2.5189, Perplexity: 12.4151
|
| 590 |
+
2025-06-10 15:59:11,517 - __main__ - INFO - Validation BLEU-4: 0.1045
|
| 591 |
+
2025-06-10 15:59:11,518 - __main__ - INFO - Performing memory optimization after epoch...
|
| 592 |
+
2025-06-10 15:59:11,789 - __main__ - INFO - CUDA cache emptied.
|
| 593 |
+
2025-06-10 15:59:12,121 - __main__ - INFO - Python garbage collector run.
|
| 594 |
+
Epoch 25 Training: 3%|▎ | 99/3125 [01:40<50:05, 1.01it/s]
|
| 595 |
+
2025-06-10 16:00:53,982 - __main__ - INFO - Epoch [25/27], Step [100/3125], Loss: 2.0074, Perplexity: 7.4441
|
| 596 |
+
Epoch 25 Training: 6%|▋ | 199/3125 [03:20<48:42, 1.00it/s]
|
| 597 |
+
2025-06-10 16:02:33,427 - __main__ - INFO - Epoch [25/27], Step [200/3125], Loss: 2.0555, Perplexity: 7.8107
|
| 598 |
+
Epoch 25 Training: 10%|▉ | 299/3125 [04:59<46:02, 1.02it/s]
|
| 599 |
+
2025-06-10 16:04:12,803 - __main__ - INFO - Epoch [25/27], Step [300/3125], Loss: 2.3032, Perplexity: 10.0063
|
| 600 |
+
Epoch 25 Training: 13%|█▎ | 399/3125 [06:38<44:27, 1.02it/s]
|
| 601 |
+
2025-06-10 16:05:51,698 - __main__ - INFO - Epoch [25/27], Step [400/3125], Loss: 2.1707, Perplexity: 8.7648
|
| 602 |
+
Epoch 25 Training: 16%|█▌ | 499/3125 [08:17<43:04, 1.02it/s]
|
| 603 |
+
2025-06-10 16:07:30,853 - __main__ - INFO - Epoch [25/27], Step [500/3125], Loss: 2.1961, Perplexity: 8.9898
|
| 604 |
+
Epoch 25 Training: 19%|█▉ | 599/3125 [09:56<41:10, 1.02it/s]
|
| 605 |
+
2025-06-10 16:09:10,070 - __main__ - INFO - Epoch [25/27], Step [600/3125], Loss: 2.0564, Perplexity: 7.8181
|
| 606 |
+
Epoch 25 Training: 22%|██▏ | 699/3125 [11:36<39:34, 1.02it/s]
|
| 607 |
+
2025-06-10 16:10:49,506 - __main__ - INFO - Epoch [25/27], Step [700/3125], Loss: 2.0773, Perplexity: 7.9832
|
| 608 |
+
Epoch 25 Training: 26%|██▌ | 799/3125 [13:15<38:18, 1.01it/s]
|
| 609 |
+
2025-06-10 16:12:28,561 - __main__ - INFO - Epoch [25/27], Step [800/3125], Loss: 2.3222, Perplexity: 10.1984
|
| 610 |
+
Epoch 25 Training: 29%|██▉ | 899/3125 [14:54<36:41, 1.01it/s]
|
| 611 |
+
2025-06-10 16:14:07,966 - __main__ - INFO - Epoch [25/27], Step [900/3125], Loss: 2.1284, Perplexity: 8.4017
|
| 612 |
+
Epoch 25 Training: 32%|███▏ | 999/3125 [16:34<35:14, 1.01it/s]
|
| 613 |
+
2025-06-10 16:15:47,098 - __main__ - INFO - Epoch [25/27], Step [1000/3125], Loss: 2.1676, Perplexity: 8.7370
|
| 614 |
+
Epoch 25 Training: 35%|███▌ | 1099/3125 [18:13<33:31, 1.01it/s]
|
| 615 |
+
2025-06-10 16:17:26,645 - __main__ - INFO - Epoch [25/27], Step [1100/3125], Loss: 2.2209, Perplexity: 9.2159
|
| 616 |
+
Epoch 25 Training: 38%|███▊ | 1199/3125 [19:52<32:17, 1.01s/it]
|
| 617 |
+
2025-06-10 16:19:05,907 - __main__ - INFO - Epoch [25/27], Step [1200/3125], Loss: 2.1686, Perplexity: 8.7457
|
| 618 |
+
Epoch 25 Training: 42%|████▏ | 1299/3125 [21:31<30:14, 1.01it/s]
|
| 619 |
+
2025-06-10 16:20:45,059 - __main__ - INFO - Epoch [25/27], Step [1300/3125], Loss: 2.3130, Perplexity: 10.1044
|
| 620 |
+
Epoch 25 Training: 45%|████▍ | 1399/3125 [23:11<28:17, 1.02it/s]
|
| 621 |
+
2025-06-10 16:22:24,187 - __main__ - INFO - Epoch [25/27], Step [1400/3125], Loss: 2.2171, Perplexity: 9.1806
|
| 622 |
+
Epoch 25 Training: 48%|████▊ | 1499/3125 [24:50<26:56, 1.01it/s]
|
| 623 |
+
2025-06-10 16:24:03,698 - __main__ - INFO - Epoch [25/27], Step [1500/3125], Loss: 2.2474, Perplexity: 9.4627
|
| 624 |
+
Epoch 25 Training: 51%|█████ | 1599/3125 [26:29<25:54, 1.02s/it]
|
| 625 |
+
2025-06-10 16:25:42,883 - __main__ - INFO - Epoch [25/27], Step [1600/3125], Loss: 2.2844, Perplexity: 9.8197
|
| 626 |
+
Epoch 25 Training: 54%|█████▍ | 1699/3125 [28:09<23:26, 1.01it/s]
|
| 627 |
+
2025-06-10 16:27:22,497 - __main__ - INFO - Epoch [25/27], Step [1700/3125], Loss: 2.2792, Perplexity: 9.7693
|
| 628 |
+
Epoch 25 Training: 58%|█████▊ | 1799/3125 [29:48<21:54, 1.01it/s]
|
| 629 |
+
2025-06-10 16:29:01,803 - __main__ - INFO - Epoch [25/27], Step [1800/3125], Loss: 2.2396, Perplexity: 9.3897
|
| 630 |
+
Epoch 25 Training: 61%|██████ | 1899/3125 [31:27<20:22, 1.00it/s]
|
| 631 |
+
2025-06-10 16:30:40,803 - __main__ - INFO - Epoch [25/27], Step [1900/3125], Loss: 2.0225, Perplexity: 7.5576
|
| 632 |
+
Epoch 25 Training: 64%|██████▍ | 1999/3125 [33:06<18:29, 1.01it/s]
|
| 633 |
+
2025-06-10 16:32:19,976 - __main__ - INFO - Epoch [25/27], Step [2000/3125], Loss: 2.2360, Perplexity: 9.3554
|
| 634 |
+
Epoch 25 Training: 67%|██████▋ | 2099/3125 [34:45<16:40, 1.03it/s]
|
| 635 |
+
2025-06-10 16:33:58,927 - __main__ - INFO - Epoch [25/27], Step [2100/3125], Loss: 2.0710, Perplexity: 7.9326
|
| 636 |
+
Epoch 25 Training: 70%|███████ | 2199/3125 [36:25<15:18, 1.01it/s]
|
| 637 |
+
2025-06-10 16:35:38,376 - __main__ - INFO - Epoch [25/27], Step [2200/3125], Loss: 2.3347, Perplexity: 10.3267
|
| 638 |
+
Epoch 25 Training: 74%|███████▎ | 2299/3125 [38:04<13:50, 1.01s/it]
|
| 639 |
+
2025-06-10 16:37:17,584 - __main__ - INFO - Epoch [25/27], Step [2300/3125], Loss: 2.0350, Perplexity: 7.6525
|
| 640 |
+
Epoch 25 Training: 77%|███████▋ | 2399/3125 [39:44<12:17, 1.02s/it]
|
| 641 |
+
2025-06-10 16:38:57,181 - __main__ - INFO - Epoch [25/27], Step [2400/3125], Loss: 2.2684, Perplexity: 9.6638
|
| 642 |
+
Epoch 25 Training: 80%|███████▉ | 2499/3125 [41:23<10:17, 1.01it/s]
|
| 643 |
+
2025-06-10 16:40:36,758 - __main__ - INFO - Epoch [25/27], Step [2500/3125], Loss: 2.2548, Perplexity: 9.5332
|
| 644 |
+
Epoch 25 Training: 83%|████████▎ | 2599/3125 [43:03<08:45, 1.00it/s]
|
| 645 |
+
2025-06-10 16:42:16,315 - __main__ - INFO - Epoch [25/27], Step [2600/3125], Loss: 2.0938, Perplexity: 8.1161
|
| 646 |
+
Epoch 25 Training: 86%|████████▋ | 2699/3125 [44:42<07:05, 1.00it/s]
|
| 647 |
+
2025-06-10 16:43:55,636 - __main__ - INFO - Epoch [25/27], Step [2700/3125], Loss: 2.1231, Perplexity: 8.3569
|
| 648 |
+
Epoch 25 Training: 90%|████████▉ | 2799/3125 [46:21<05:27, 1.01s/it]
|
| 649 |
+
2025-06-10 16:45:34,688 - __main__ - INFO - Epoch [25/27], Step [2800/3125], Loss: 2.1211, Perplexity: 8.3405
|
| 650 |
+
Epoch 25 Training: 93%|█████████▎| 2899/3125 [48:00<03:45, 1.00it/s]
|
| 651 |
+
2025-06-10 16:47:13,853 - __main__ - INFO - Epoch [25/27], Step [2900/3125], Loss: 2.2003, Perplexity: 9.0279
|
| 652 |
+
Epoch 25 Training: 96%|█████████▌| 2999/3125 [49:40<02:04, 1.01it/s]
|
| 653 |
+
2025-06-10 16:48:53,644 - __main__ - INFO - Epoch [25/27], Step [3000/3125], Loss: 2.2365, Perplexity: 9.3608
|
| 654 |
+
Epoch 25 Training: 99%|█████████▉| 3099/3125 [51:19<00:25, 1.03it/s]
|
| 655 |
+
2025-06-10 16:50:32,426 - __main__ - INFO - Epoch [25/27], Step [3100/3125], Loss: 2.1602, Perplexity: 8.6729
|
| 656 |
+
Epoch 25 Training: 100%|██████████| 3125/3125 [51:45<00:00, 1.01it/s]
|
| 657 |
+
2025-06-10 16:50:57,431 - __main__ - INFO - Epoch 25 Training finished. Avg Loss: 2.1887, Time: 3105.31s
|
| 658 |
+
Validation: 100%|██████████| 391/391 [11:43<00:00, 1.80s/it]
|
| 659 |
+
2025-06-10 17:02:40,897 - __main__ - INFO - Validation Avg Loss: 2.5252, Perplexity: 12.4939
|
| 660 |
+
2025-06-10 17:02:50,176 - __main__ - INFO - Validation BLEU-4: 0.1035
|
| 661 |
+
2025-06-10 17:02:50,820 - __main__ - INFO - Saved periodic model checkpoint to ./output/model_epoch_25.pth
|
| 662 |
+
2025-06-10 17:02:50,821 - __main__ - INFO - Performing memory optimization after epoch...
|
| 663 |
+
2025-06-10 17:02:51,113 - __main__ - INFO - CUDA cache emptied.
|
| 664 |
+
2025-06-10 17:02:51,455 - __main__ - INFO - Python garbage collector run.
|
| 665 |
+
Epoch 26 Training: 3%|▎ | 99/3125 [01:40<49:39, 1.02it/s]
|
| 666 |
+
2025-06-10 17:04:33,276 - __main__ - INFO - Epoch [26/27], Step [100/3125], Loss: 2.1935, Perplexity: 8.9668
|
| 667 |
+
Epoch 26 Training: 6%|▋ | 199/3125 [03:19<48:02, 1.02it/s]
|
| 668 |
+
2025-06-10 17:06:11,935 - __main__ - INFO - Epoch [26/27], Step [200/3125], Loss: 1.9728, Perplexity: 7.1905
|
| 669 |
+
Epoch 26 Training: 10%|▉ | 299/3125 [04:59<46:10, 1.02it/s]
|
| 670 |
+
2025-06-10 17:07:51,541 - __main__ - INFO - Epoch [26/27], Step [300/3125], Loss: 2.2561, Perplexity: 9.5454
|
| 671 |
+
Epoch 26 Training: 13%|█▎ | 399/3125 [06:37<44:23, 1.02it/s]
|
| 672 |
+
2025-06-10 17:09:30,184 - __main__ - INFO - Epoch [26/27], Step [400/3125], Loss: 2.0493, Perplexity: 7.7628
|
| 673 |
+
Epoch 26 Training: 16%|█▌ | 499/3125 [08:17<43:07, 1.02it/s]
|
| 674 |
+
2025-06-10 17:11:09,536 - __main__ - INFO - Epoch [26/27], Step [500/3125], Loss: 2.2319, Perplexity: 9.3180
|
| 675 |
+
Epoch 26 Training: 19%|█▉ | 599/3125 [09:55<41:37, 1.01it/s]
|
| 676 |
+
2025-06-10 17:12:48,359 - __main__ - INFO - Epoch [26/27], Step [600/3125], Loss: 2.1954, Perplexity: 8.9836
|
| 677 |
+
Epoch 26 Training: 22%|██▏ | 699/3125 [11:35<40:20, 1.00it/s]
|
| 678 |
+
2025-06-10 17:14:27,587 - __main__ - INFO - Epoch [26/27], Step [700/3125], Loss: 2.1557, Perplexity: 8.6338
|
| 679 |
+
Epoch 26 Training: 26%|██▌ | 799/3125 [13:14<38:08, 1.02it/s]
|
| 680 |
+
2025-06-10 17:16:06,635 - __main__ - INFO - Epoch [26/27], Step [800/3125], Loss: 2.4767, Perplexity: 11.9019
|
| 681 |
+
Epoch 26 Training: 29%|██▉ | 899/3125 [14:53<37:20, 1.01s/it]
|
| 682 |
+
2025-06-10 17:17:46,247 - __main__ - INFO - Epoch [26/27], Step [900/3125], Loss: 2.2038, Perplexity: 9.0594
|
| 683 |
+
Epoch 26 Training: 32%|███▏ | 999/3125 [16:32<34:44, 1.02it/s]
|
| 684 |
+
2025-06-10 17:19:24,943 - __main__ - INFO - Epoch [26/27], Step [1000/3125], Loss: 2.1657, Perplexity: 8.7203
|
| 685 |
+
Epoch 26 Training: 35%|███▌ | 1099/3125 [18:11<33:20, 1.01it/s]
|
| 686 |
+
2025-06-10 17:21:03,864 - __main__ - INFO - Epoch [26/27], Step [1100/3125], Loss: 2.0512, Perplexity: 7.7773
|
| 687 |
+
Epoch 26 Training: 38%|███▊ | 1199/3125 [19:50<32:41, 1.02s/it]
|
| 688 |
+
2025-06-10 17:22:42,855 - __main__ - INFO - Epoch [26/27], Step [1200/3125], Loss: 2.2466, Perplexity: 9.4556
|
| 689 |
+
Epoch 26 Training: 42%|████▏ | 1299/3125 [21:29<30:16, 1.01it/s]
|
| 690 |
+
2025-06-10 17:24:21,894 - __main__ - INFO - Epoch [26/27], Step [1300/3125], Loss: 2.1989, Perplexity: 9.0151
|
| 691 |
+
Epoch 26 Training: 45%|████▍ | 1399/3125 [23:09<28:32, 1.01it/s]
|
| 692 |
+
2025-06-10 17:26:01,435 - __main__ - INFO - Epoch [26/27], Step [1400/3125], Loss: 2.2580, Perplexity: 9.5638
|
| 693 |
+
Epoch 26 Training: 48%|████▊ | 1499/3125 [24:48<26:59, 1.00it/s]
|
| 694 |
+
2025-06-10 17:27:40,602 - __main__ - INFO - Epoch [26/27], Step [1500/3125], Loss: 2.3685, Perplexity: 10.6812
|
| 695 |
+
Epoch 26 Training: 51%|█████ | 1599/3125 [26:27<24:55, 1.02it/s]
|
| 696 |
+
2025-06-10 17:29:19,701 - __main__ - INFO - Epoch [26/27], Step [1600/3125], Loss: 2.1787, Perplexity: 8.8347
|
| 697 |
+
Epoch 26 Training: 54%|█████▍ | 1699/3125 [28:06<23:58, 1.01s/it]
|
| 698 |
+
2025-06-10 17:30:59,005 - __main__ - INFO - Epoch [26/27], Step [1700/3125], Loss: 2.2104, Perplexity: 9.1193
|
| 699 |
+
Epoch 26 Training: 58%|█████▊ | 1799/3125 [29:45<21:55, 1.01it/s]
|
| 700 |
+
2025-06-10 17:32:38,342 - __main__ - INFO - Epoch [26/27], Step [1800/3125], Loss: 2.0694, Perplexity: 7.9204
|
| 701 |
+
Epoch 26 Training: 61%|██████ | 1899/3125 [31:25<20:23, 1.00it/s]
|
| 702 |
+
2025-06-10 17:34:17,536 - __main__ - INFO - Epoch [26/27], Step [1900/3125], Loss: 2.1163, Perplexity: 8.3004
|
| 703 |
+
Epoch 26 Training: 64%|██████▍ | 1999/3125 [33:03<18:49, 1.00s/it]
|
| 704 |
+
2025-06-10 17:35:56,419 - __main__ - INFO - Epoch [26/27], Step [2000/3125], Loss: 2.2775, Perplexity: 9.7523
|
| 705 |
+
Epoch 26 Training: 67%|██████▋ | 2099/3125 [34:42<16:56, 1.01it/s]
|
| 706 |
+
2025-06-10 17:37:35,002 - __main__ - INFO - Epoch [26/27], Step [2100/3125], Loss: 2.4668, Perplexity: 11.7850
|
| 707 |
+
Epoch 26 Training: 70%|███████ | 2199/3125 [36:21<15:04, 1.02it/s]
|
| 708 |
+
2025-06-10 17:39:13,937 - __main__ - INFO - Epoch [26/27], Step [2200/3125], Loss: 2.0802, Perplexity: 8.0062
|
| 709 |
+
Epoch 26 Training: 74%|███████▎ | 2299/3125 [38:00<14:06, 1.02s/it]
|
| 710 |
+
2025-06-10 17:40:53,145 - __main__ - INFO - Epoch [26/27], Step [2300/3125], Loss: 2.2296, Perplexity: 9.2964
|
| 711 |
+
Epoch 26 Training: 77%|███████▋ | 2399/3125 [39:39<12:02, 1.00it/s]
|
| 712 |
+
2025-06-10 17:42:32,450 - __main__ - INFO - Epoch [26/27], Step [2400/3125], Loss: 2.0793, Perplexity: 7.9986
|
| 713 |
+
Epoch 26 Training: 80%|███████▉ | 2499/3125 [41:19<10:05, 1.03it/s]
|
| 714 |
+
2025-06-10 17:44:11,811 - __main__ - INFO - Epoch [26/27], Step [2500/3125], Loss: 2.1663, Perplexity: 8.7259
|
| 715 |
+
Epoch 26 Training: 83%|████████▎ | 2599/3125 [42:58<08:47, 1.00s/it]
|
| 716 |
+
2025-06-10 17:45:51,064 - __main__ - INFO - Epoch [26/27], Step [2600/3125], Loss: 1.9672, Perplexity: 7.1505
|
| 717 |
+
Epoch 26 Training: 86%|████████▋ | 2699/3125 [44:37<06:58, 1.02it/s]
|
| 718 |
+
2025-06-10 17:47:30,464 - __main__ - INFO - Epoch [26/27], Step [2700/3125], Loss: 2.3145, Perplexity: 10.1195
|
| 719 |
+
Epoch 26 Training: 90%|████████▉ | 2799/3125 [46:17<05:26, 1.00s/it]
|
| 720 |
+
2025-06-10 17:49:09,938 - __main__ - INFO - Epoch [26/27], Step [2800/3125], Loss: 2.1893, Perplexity: 8.9292
|
| 721 |
+
Epoch 26 Training: 93%|█████████▎| 2899/3125 [47:56<03:43, 1.01it/s]
|
| 722 |
+
2025-06-10 17:50:48,764 - __main__ - INFO - Epoch [26/27], Step [2900/3125], Loss: 2.0229, Perplexity: 7.5600
|
| 723 |
+
Epoch 26 Training: 96%|█████████▌| 2999/3125 [49:35<02:03, 1.02it/s]
|
| 724 |
+
2025-06-10 17:52:27,535 - __main__ - INFO - Epoch [26/27], Step [3000/3125], Loss: 2.4255, Perplexity: 11.3075
|
| 725 |
+
Epoch 26 Training: 99%|█████████▉| 3099/3125 [51:14<00:25, 1.01it/s]
|
| 726 |
+
2025-06-10 17:54:07,103 - __main__ - INFO - Epoch [26/27], Step [3100/3125], Loss: 2.2570, Perplexity: 9.5549
|
| 727 |
+
Epoch 26 Training: 100%|██████████| 3125/3125 [51:40<00:00, 1.01it/s]
|
| 728 |
+
2025-06-10 17:54:31,850 - __main__ - INFO - Epoch 26 Training finished. Avg Loss: 2.1649, Time: 3100.39s
|
| 729 |
+
Validation: 100%|██████████| 391/391 [11:39<00:00, 1.79s/it]
|
| 730 |
+
2025-06-10 18:06:11,797 - __main__ - INFO - Validation Avg Loss: 2.5364, Perplexity: 12.6343
|
| 731 |
+
2025-06-10 18:06:21,178 - __main__ - INFO - Validation BLEU-4: 0.1028
|
| 732 |
+
2025-06-10 18:06:21,179 - __main__ - INFO - Performing memory optimization after epoch...
|
| 733 |
+
2025-06-10 18:06:21,442 - __main__ - INFO - CUDA cache emptied.
|
| 734 |
+
2025-06-10 18:06:21,779 - __main__ - INFO - Python garbage collector run.
|
| 735 |
+
Epoch 27 Training: 3%|▎ | 99/3125 [01:40<50:33, 1.00s/it]
|
| 736 |
+
2025-06-10 18:08:03,665 - __main__ - INFO - Epoch [27/27], Step [100/3125], Loss: 2.0213, Perplexity: 7.5483
|
| 737 |
+
Epoch 27 Training: 6%|▋ | 199/3125 [03:20<48:20, 1.01it/s]
|
| 738 |
+
2025-06-10 18:09:42,825 - __main__ - INFO - Epoch [27/27], Step [200/3125], Loss: 2.0965, Perplexity: 8.1376
|
| 739 |
+
Epoch 27 Training: 10%|▉ | 299/3125 [04:59<46:24, 1.01it/s]
|
| 740 |
+
2025-06-10 18:11:21,959 - __main__ - INFO - Epoch [27/27], Step [300/3125], Loss: 2.1239, Perplexity: 8.3635
|
| 741 |
+
Epoch 27 Training: 13%|█▎ | 399/3125 [06:37<44:53, 1.01it/s]
|
| 742 |
+
2025-06-10 18:13:00,610 - __main__ - INFO - Epoch [27/27], Step [400/3125], Loss: 2.0620, Perplexity: 7.8614
|
| 743 |
+
Epoch 27 Training: 16%|█▌ | 499/3125 [08:17<43:45, 1.00it/s]
|
| 744 |
+
2025-06-10 18:14:40,303 - __main__ - INFO - Epoch [27/27], Step [500/3125], Loss: 2.2273, Perplexity: 9.2751
|
| 745 |
+
Epoch 27 Training: 19%|█▉ | 599/3125 [09:56<42:36, 1.01s/it]
|
| 746 |
+
2025-06-10 18:16:19,474 - __main__ - INFO - Epoch [27/27], Step [600/3125], Loss: 1.9186, Perplexity: 6.8115
|
| 747 |
+
Epoch 27 Training: 22%|██▏ | 699/3125 [11:35<39:33, 1.02it/s]
|
| 748 |
+
2025-06-10 18:17:58,184 - __main__ - INFO - Epoch [27/27], Step [700/3125], Loss: 2.1434, Perplexity: 8.5282
|
| 749 |
+
Epoch 27 Training: 26%|██▌ | 799/3125 [13:14<38:11, 1.02it/s]
|
| 750 |
+
2025-06-10 18:19:37,100 - __main__ - INFO - Epoch [27/27], Step [800/3125], Loss: 2.0196, Perplexity: 7.5353
|
| 751 |
+
Epoch 27 Training: 29%|██▉ | 899/3125 [14:52<36:30, 1.02it/s]
|
| 752 |
+
2025-06-10 18:21:15,710 - __main__ - INFO - Epoch [27/27], Step [900/3125], Loss: 1.9703, Perplexity: 7.1727
|
| 753 |
+
Epoch 27 Training: 32%|███▏ | 999/3125 [16:32<34:55, 1.01it/s]
|
| 754 |
+
2025-06-10 18:22:55,193 - __main__ - INFO - Epoch [27/27], Step [1000/3125], Loss: 1.9125, Perplexity: 6.7700
|
| 755 |
+
Epoch 27 Training: 35%|███▌ | 1099/3125 [18:11<32:38, 1.03it/s]
|
| 756 |
+
2025-06-10 18:24:34,007 - __main__ - INFO - Epoch [27/27], Step [1100/3125], Loss: 2.1512, Perplexity: 8.5948
|
| 757 |
+
Epoch 27 Training: 38%|███▊ | 1199/3125 [19:50<31:47, 1.01it/s]
|
| 758 |
+
2025-06-10 18:26:13,603 - __main__ - INFO - Epoch [27/27], Step [1200/3125], Loss: 2.1597, Perplexity: 8.6683
|
| 759 |
+
Epoch 27 Training: 42%|████▏ | 1299/3125 [21:30<30:53, 1.02s/it]
|
| 760 |
+
2025-06-10 18:27:53,207 - __main__ - INFO - Epoch [27/27], Step [1300/3125], Loss: 2.1628, Perplexity: 8.6955
|
| 761 |
+
Epoch 27 Training: 45%|████▍ | 1399/3125 [23:08<28:29, 1.01it/s]
|
| 762 |
+
2025-06-10 18:29:31,577 - __main__ - INFO - Epoch [27/27], Step [1400/3125], Loss: 2.1293, Perplexity: 8.4093
|
| 763 |
+
Epoch 27 Training: 48%|████▊ | 1499/3125 [24:47<27:13, 1.00s/it]
|
| 764 |
+
2025-06-10 18:31:10,700 - __main__ - INFO - Epoch [27/27], Step [1500/3125], Loss: 1.9977, Perplexity: 7.3723
|
| 765 |
+
Epoch 27 Training: 51%|█████ | 1599/3125 [26:26<25:40, 1.01s/it]
|
| 766 |
+
2025-06-10 18:32:49,710 - __main__ - INFO - Epoch [27/27], Step [1600/3125], Loss: 2.1225, Perplexity: 8.3524
|
| 767 |
+
Epoch 27 Training: 54%|█████▍ | 1699/3125 [28:06<23:27, 1.01it/s]
|
| 768 |
+
2025-06-10 18:34:28,810 - __main__ - INFO - Epoch [27/27], Step [1700/3125], Loss: 2.0431, Perplexity: 7.7143
|
| 769 |
+
Epoch 27 Training: 58%|█████▊ | 1799/3125 [29:45<21:41, 1.02it/s]
|
| 770 |
+
2025-06-10 18:36:08,315 - __main__ - INFO - Epoch [27/27], Step [1800/3125], Loss: 2.1295, Perplexity: 8.4103
|
| 771 |
+
Epoch 27 Training: 61%|██████ | 1899/3125 [31:24<20:10, 1.01it/s]
|
| 772 |
+
2025-06-10 18:37:47,406 - __main__ - INFO - Epoch [27/27], Step [1900/3125], Loss: 2.1814, Perplexity: 8.8590
|
| 773 |
+
Epoch 27 Training: 64%|██████▍ | 1999/3125 [33:03<18:23, 1.02it/s]
|
| 774 |
+
2025-06-10 18:39:26,578 - __main__ - INFO - Epoch [27/27], Step [2000/3125], Loss: 2.1035, Perplexity: 8.1949
|
| 775 |
+
Epoch 27 Training: 67%|██████▋ | 2099/3125 [34:43<17:19, 1.01s/it]
|
| 776 |
+
2025-06-10 18:41:05,955 - __main__ - INFO - Epoch [27/27], Step [2100/3125], Loss: 2.2474, Perplexity: 9.4627
|
| 777 |
+
Epoch 27 Training: 70%|███████ | 2199/3125 [36:22<15:35, 1.01s/it]
|
| 778 |
+
2025-06-10 18:42:45,066 - __main__ - INFO - Epoch [27/27], Step [2200/3125], Loss: 2.1740, Perplexity: 8.7938
|
| 779 |
+
Epoch 27 Training: 74%|███████▎ | 2299/3125 [38:02<13:55, 1.01s/it]
|
| 780 |
+
2025-06-10 18:44:24,893 - __main__ - INFO - Epoch [27/27], Step [2300/3125], Loss: 2.0490, Perplexity: 7.7599
|
| 781 |
+
Epoch 27 Training: 77%|███████▋ | 2399/3125 [39:41<12:00, 1.01it/s]
|
| 782 |
+
2025-06-10 18:46:04,439 - __main__ - INFO - Epoch [27/27], Step [2400/3125], Loss: 2.0989, Perplexity: 8.1575
|
| 783 |
+
Epoch 27 Training: 80%|███████▉ | 2499/3125 [41:21<10:33, 1.01s/it]
|
| 784 |
+
2025-06-10 18:47:44,059 - __main__ - INFO - Epoch [27/27], Step [2500/3125], Loss: 2.1561, Perplexity: 8.6375
|
| 785 |
+
Epoch 27 Training: 83%|████████▎ | 2599/3125 [43:00<08:38, 1.01it/s]
|
| 786 |
+
2025-06-10 18:49:22,937 - __main__ - INFO - Epoch [27/27], Step [2600/3125], Loss: 2.0021, Perplexity: 7.4043
|
| 787 |
+
Epoch 27 Training: 86%|████████▋ | 2699/3125 [44:38<07:00, 1.01it/s]
|
| 788 |
+
2025-06-10 18:51:01,628 - __main__ - INFO - Epoch [27/27], Step [2700/3125], Loss: 2.1921, Perplexity: 8.9542
|
| 789 |
+
Epoch 27 Training: 90%|████████▉ | 2799/3125 [46:18<05:24, 1.01it/s]
|
| 790 |
+
2025-06-10 18:52:41,490 - __main__ - INFO - Epoch [27/27], Step [2800/3125], Loss: 2.0942, Perplexity: 8.1186
|
| 791 |
+
Epoch 27 Training: 93%|█████████▎| 2899/3125 [47:58<03:52, 1.03s/it]
|
| 792 |
+
2025-06-10 18:54:20,942 - __main__ - INFO - Epoch [27/27], Step [2900/3125], Loss: 2.0986, Perplexity: 8.1548
|
| 793 |
+
Epoch 27 Training: 96%|█████████▌| 2999/3125 [49:37<02:03, 1.02it/s]
|
| 794 |
+
2025-06-10 18:56:00,291 - __main__ - INFO - Epoch [27/27], Step [3000/3125], Loss: 2.0972, Perplexity: 8.1434
|
| 795 |
+
Epoch 27 Training: 99%|█████████▉| 3099/3125 [51:16<00:25, 1.02it/s]
|
| 796 |
+
2025-06-10 18:57:39,235 - __main__ - INFO - Epoch [27/27], Step [3100/3125], Loss: 2.3328, Perplexity: 10.3071
|
| 797 |
+
Epoch 27 Training: 100%|██████████| 3125/3125 [51:42<00:00, 1.01it/s]
|
| 798 |
+
2025-06-10 18:58:04,262 - __main__ - INFO - Epoch 27 Training finished. Avg Loss: 2.1058, Time: 3102.48s
|
| 799 |
+
Validation: 100%|██████████| 391/391 [11:40<00:00, 1.79s/it]
|
| 800 |
+
2025-06-10 19:09:45,225 - __main__ - INFO - Validation Avg Loss: 2.5443, Perplexity: 12.7347
|
| 801 |
+
2025-06-10 19:09:54,459 - __main__ - INFO - Validation BLEU-4: 0.1039
|
| 802 |
+
2025-06-10 19:09:54,460 - __main__ - INFO - Performing memory optimization after epoch...
|
| 803 |
+
2025-06-10 19:09:54,737 - __main__ - INFO - CUDA cache emptied.
|
| 804 |
+
2025-06-10 19:09:55,085 - __main__ - INFO - Python garbage collector run.
|
| 805 |
+
2025-06-10 19:09:55,086 - __main__ - INFO - Training complete.
|
| 806 |
+
2025-06-10 19:09:55,087 - __main__ - INFO - Model Training Complete!
|
text_files/training_log_1_18.txt
ADDED
|
@@ -0,0 +1,668 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
2025-06-09 20:01:36,610 - __main__ - INFO - Previous notebook output found at: /kaggle/input/my-image-captioning-model-epochs-1-9/output. Copying to ./output...
|
| 2 |
+
2025-06-09 20:02:22,087 - __main__ - INFO - Previous output copied successfully to current working directory for resumption.
|
| 3 |
+
2025-06-09 20:02:22,088 - __main__ - INFO -
|
| 4 |
+
--- Starting Model Training ---
|
| 5 |
+
2025-06-09 20:02:22,089 - __main__ - INFO - Starting training process...
|
| 6 |
+
2025-06-09 20:02:22,090 - __main__ - INFO - Using device: cuda
|
| 7 |
+
2025-06-09 20:02:22,104 - __main__ - WARNING - Vocabulary source not found at /kaggle/input/vocabulary_s/pytorch/default/1/vocabulary.pkl. Will build new vocabulary.
|
| 8 |
+
2025-06-09 20:02:22,104 - __main__ - INFO - Building new vocabulary from training dataset...
|
| 9 |
+
2025-06-09 20:02:23,082 - __main__ - INFO - Successfully loaded captions from /kaggle/input/coco-2017-dataset/coco2017/annotations/captions_train2017.json
|
| 10 |
+
Processing annotations: 100%|██████████| 591753/591753 [05:53<00:00, 1674.75it/s]
|
| 11 |
+
2025-06-09 20:08:16,457 - __main__ - INFO - Dataset size after filtering: 591753 samples.
|
| 12 |
+
2025-06-09 20:08:16,503 - __main__ - INFO - Building vocabulary...
|
| 13 |
+
Counting word frequencies: 100%|██████████| 591753/591753 [00:01<00:00, 342838.45it/s]
|
| 14 |
+
2025-06-09 20:08:18,236 - __main__ - INFO - Vocabulary size: 14030
|
| 15 |
+
2025-06-09 20:08:18,377 - __main__ - INFO - New vocabulary built.
|
| 16 |
+
2025-06-09 20:08:18,388 - __main__ - INFO - Saved newly built vocabulary to ./output/vocabulary.pkl
|
| 17 |
+
2025-06-09 20:08:19,255 - __main__ - INFO - Successfully loaded captions from /kaggle/input/coco-2017-dataset/coco2017/annotations/captions_train2017.json
|
| 18 |
+
Processing annotations: 100%|██████████| 591753/591753 [01:01<00:00, 9579.54it/s]
|
| 19 |
+
2025-06-09 20:09:21,207 - __main__ - INFO - Using subset of 200000 samples for the dataset.
|
| 20 |
+
2025-06-09 20:09:21,207 - __main__ - INFO - Dataset size after filtering: 200000 samples.
|
| 21 |
+
2025-06-09 20:09:21,308 - __main__ - INFO - Successfully loaded captions from /kaggle/input/coco-2017-dataset/coco2017/annotations/captions_val2017.json
|
| 22 |
+
Processing annotations: 100%|██████████| 25014/25014 [00:12<00:00, 2065.00it/s]
|
| 23 |
+
2025-06-09 20:09:33,425 - __main__ - INFO - Dataset size after filtering: 25014 samples.
|
| 24 |
+
2025-06-09 20:09:33,426 - __main__ - INFO - Training dataset size: 200000
|
| 25 |
+
2025-06-09 20:09:33,427 - __main__ - INFO - Validation dataset size: 25014
|
| 26 |
+
Downloading: "https://download.pytorch.org/models/resnet50-11ad3fa6.pth" to /root/.cache/torch/hub/checkpoints/resnet50-11ad3fa6.pth
|
| 27 |
+
100%|██████████| 97.8M/97.8M [00:00<00:00, 182MB/s]
|
| 28 |
+
2025-06-09 20:09:34,636 - __main__ - INFO - ResNet encoder base layers are fine-tuning enabled.
|
| 29 |
+
2025-06-09 20:09:34,982 - __main__ - INFO - Attempting to resume training from: ./output/best_model_bleu0.1019.pth
|
| 30 |
+
2025-06-09 20:09:35,384 - __main__ - INFO - Resumed training from epoch 9. Best validation score so far: 0.1019
|
| 31 |
+
Epoch 10 Training: 3%|▎ | 99/3125 [01:34<48:01, 1.05it/s]
|
| 32 |
+
2025-06-09 20:11:10,913 - __main__ - INFO - Epoch [10/18], Step [100/3125], Loss: 2.6771, Perplexity: 14.5422
|
| 33 |
+
Epoch 10 Training: 6%|▋ | 199/3125 [03:13<48:34, 1.00it/s]
|
| 34 |
+
2025-06-09 20:12:50,072 - __main__ - INFO - Epoch [10/18], Step [200/3125], Loss: 2.5936, Perplexity: 13.3779
|
| 35 |
+
Epoch 10 Training: 10%|▉ | 299/3125 [04:52<47:27, 1.01s/it]
|
| 36 |
+
2025-06-09 20:14:28,848 - __main__ - INFO - Epoch [10/18], Step [300/3125], Loss: 2.7310, Perplexity: 15.3478
|
| 37 |
+
Epoch 10 Training: 13%|█▎ | 399/3125 [06:32<45:05, 1.01it/s]
|
| 38 |
+
2025-06-09 20:16:08,515 - __main__ - INFO - Epoch [10/18], Step [400/3125], Loss: 2.9600, Perplexity: 19.2978
|
| 39 |
+
Epoch 10 Training: 16%|█▌ | 499/3125 [08:11<43:37, 1.00it/s]
|
| 40 |
+
2025-06-09 20:17:47,682 - __main__ - INFO - Epoch [10/18], Step [500/3125], Loss: 2.6822, Perplexity: 14.6177
|
| 41 |
+
Epoch 10 Training: 19%|█▉ | 599/3125 [09:50<41:42, 1.01it/s]
|
| 42 |
+
2025-06-09 20:19:26,696 - __main__ - INFO - Epoch [10/18], Step [600/3125], Loss: 2.7823, Perplexity: 16.1564
|
| 43 |
+
Epoch 10 Training: 22%|██▏ | 699/3125 [11:29<39:36, 1.02it/s]
|
| 44 |
+
2025-06-09 20:21:05,763 - __main__ - INFO - Epoch [10/18], Step [700/3125], Loss: 2.5442, Perplexity: 12.7334
|
| 45 |
+
Epoch 10 Training: 26%|██▌ | 799/3125 [13:08<38:48, 1.00s/it]
|
| 46 |
+
2025-06-09 20:22:44,621 - __main__ - INFO - Epoch [10/18], Step [800/3125], Loss: 2.6036, Perplexity: 13.5120
|
| 47 |
+
Epoch 10 Training: 29%|██▉ | 899/3125 [14:47<36:19, 1.02it/s]
|
| 48 |
+
2025-06-09 20:24:23,734 - __main__ - INFO - Epoch [10/18], Step [900/3125], Loss: 2.4600, Perplexity: 11.7049
|
| 49 |
+
Epoch 10 Training: 32%|███▏ | 999/3125 [16:26<35:25, 1.00it/s]
|
| 50 |
+
2025-06-09 20:26:02,980 - __main__ - INFO - Epoch [10/18], Step [1000/3125], Loss: 2.8091, Perplexity: 16.5947
|
| 51 |
+
Epoch 10 Training: 35%|███▌ | 1099/3125 [18:05<33:06, 1.02it/s]
|
| 52 |
+
2025-06-09 20:27:41,993 - __main__ - INFO - Epoch [10/18], Step [1100/3125], Loss: 2.6680, Perplexity: 14.4108
|
| 53 |
+
Epoch 10 Training: 38%|███▊ | 1199/3125 [19:44<31:27, 1.02it/s]
|
| 54 |
+
2025-06-09 20:29:20,927 - __main__ - INFO - Epoch [10/18], Step [1200/3125], Loss: 2.7080, Perplexity: 14.9991
|
| 55 |
+
Epoch 10 Training: 42%|████▏ | 1299/3125 [21:23<30:11, 1.01it/s]
|
| 56 |
+
2025-06-09 20:30:59,882 - __main__ - INFO - Epoch [10/18], Step [1300/3125], Loss: 2.6393, Perplexity: 14.0032
|
| 57 |
+
Epoch 10 Training: 45%|████▍ | 1399/3125 [23:02<28:14, 1.02it/s]
|
| 58 |
+
2025-06-09 20:32:39,221 - __main__ - INFO - Epoch [10/18], Step [1400/3125], Loss: 2.7220, Perplexity: 15.2114
|
| 59 |
+
Epoch 10 Training: 48%|████▊ | 1499/3125 [24:41<26:35, 1.02it/s]
|
| 60 |
+
2025-06-09 20:34:17,806 - __main__ - INFO - Epoch [10/18], Step [1500/3125], Loss: 2.9185, Perplexity: 18.5139
|
| 61 |
+
Epoch 10 Training: 51%|█████ | 1599/3125 [26:20<24:57, 1.02it/s]
|
| 62 |
+
2025-06-09 20:35:57,128 - __main__ - INFO - Epoch [10/18], Step [1600/3125], Loss: 2.7292, Perplexity: 15.3205
|
| 63 |
+
Epoch 10 Training: 54%|█████▍ | 1699/3125 [27:59<23:47, 1.00s/it]
|
| 64 |
+
2025-06-09 20:37:36,373 - __main__ - INFO - Epoch [10/18], Step [1700/3125], Loss: 2.7339, Perplexity: 15.3932
|
| 65 |
+
Epoch 10 Training: 58%|█████▊ | 1799/3125 [29:39<22:09, 1.00s/it]
|
| 66 |
+
2025-06-09 20:39:15,864 - __main__ - INFO - Epoch [10/18], Step [1800/3125], Loss: 2.4978, Perplexity: 12.1557
|
| 67 |
+
Epoch 10 Training: 61%|██████ | 1899/3125 [31:18<20:28, 1.00s/it]
|
| 68 |
+
2025-06-09 20:40:55,324 - __main__ - INFO - Epoch [10/18], Step [1900/3125], Loss: 2.5602, Perplexity: 12.9386
|
| 69 |
+
Epoch 10 Training: 64%|██████▍ | 1999/3125 [32:58<18:32, 1.01it/s]
|
| 70 |
+
2025-06-09 20:42:35,029 - __main__ - INFO - Epoch [10/18], Step [2000/3125], Loss: 2.6032, Perplexity: 13.5067
|
| 71 |
+
Epoch 10 Training: 67%|██████▋ | 2099/3125 [34:38<17:02, 1.00it/s]
|
| 72 |
+
2025-06-09 20:44:14,464 - __main__ - INFO - Epoch [10/18], Step [2100/3125], Loss: 2.6049, Perplexity: 13.5293
|
| 73 |
+
Epoch 10 Training: 70%|███████ | 2199/3125 [36:17<15:36, 1.01s/it]
|
| 74 |
+
2025-06-09 20:45:53,664 - __main__ - INFO - Epoch [10/18], Step [2200/3125], Loss: 2.8925, Perplexity: 18.0390
|
| 75 |
+
Epoch 10 Training: 74%|███████▎ | 2299/3125 [37:56<13:32, 1.02it/s]
|
| 76 |
+
2025-06-09 20:47:33,241 - __main__ - INFO - Epoch [10/18], Step [2300/3125], Loss: 2.6391, Perplexity: 14.0000
|
| 77 |
+
Epoch 10 Training: 77%|███████▋ | 2399/3125 [39:36<11:56, 1.01it/s]
|
| 78 |
+
2025-06-09 20:49:12,664 - __main__ - INFO - Epoch [10/18], Step [2400/3125], Loss: 2.6457, Perplexity: 14.0939
|
| 79 |
+
Epoch 10 Training: 80%|███████▉ | 2499/3125 [41:15<10:22, 1.01it/s]
|
| 80 |
+
2025-06-09 20:50:51,988 - __main__ - INFO - Epoch [10/18], Step [2500/3125], Loss: 2.6442, Perplexity: 14.0721
|
| 81 |
+
Epoch 10 Training: 83%|████████▎ | 2599/3125 [42:55<08:47, 1.00s/it]
|
| 82 |
+
2025-06-09 20:52:31,912 - __main__ - INFO - Epoch [10/18], Step [2600/3125], Loss: 2.5336, Perplexity: 12.5989
|
| 83 |
+
Epoch 10 Training: 86%|████████▋ | 2699/3125 [44:34<07:09, 1.01s/it]
|
| 84 |
+
2025-06-09 20:54:11,352 - __main__ - INFO - Epoch [10/18], Step [2700/3125], Loss: 2.6224, Perplexity: 13.7686
|
| 85 |
+
Epoch 10 Training: 90%|████████▉ | 2799/3125 [46:14<05:18, 1.02it/s]
|
| 86 |
+
2025-06-09 20:55:50,824 - __main__ - INFO - Epoch [10/18], Step [2800/3125], Loss: 2.5839, Perplexity: 13.2486
|
| 87 |
+
Epoch 10 Training: 93%|█████████▎| 2899/3125 [47:53<03:42, 1.02it/s]
|
| 88 |
+
2025-06-09 20:57:30,088 - __main__ - INFO - Epoch [10/18], Step [2900/3125], Loss: 2.5405, Perplexity: 12.6863
|
| 89 |
+
Epoch 10 Training: 96%|█████████▌| 2999/3125 [49:32<02:04, 1.01it/s]
|
| 90 |
+
2025-06-09 20:59:09,355 - __main__ - INFO - Epoch [10/18], Step [3000/3125], Loss: 2.7648, Perplexity: 15.8761
|
| 91 |
+
Epoch 10 Training: 99%|█████████▉| 3099/3125 [51:12<00:25, 1.03it/s]
|
| 92 |
+
2025-06-09 21:00:48,884 - __main__ - INFO - Epoch [10/18], Step [3100/3125], Loss: 2.7951, Perplexity: 16.3647
|
| 93 |
+
Epoch 10 Training: 100%|██████████| 3125/3125 [51:38<00:00, 1.01it/s]
|
| 94 |
+
2025-06-09 21:01:14,014 - __main__ - INFO - Epoch 10 Training finished. Avg Loss: 2.6342, Time: 3098.63s
|
| 95 |
+
Validation: 100%|██████████| 391/391 [12:13<00:00, 1.88s/it]
|
| 96 |
+
2025-06-09 21:13:27,613 - __main__ - INFO - Validation Avg Loss: 2.5347, Perplexity: 12.6126
|
| 97 |
+
2025-06-09 21:13:40,932 - __main__ - INFO - Validation BLEU-4: 0.1032
|
| 98 |
+
2025-06-09 21:13:41,690 - __main__ - INFO - Saved best model checkpoint to ./output/best_model_bleu0.1032.pth
|
| 99 |
+
2025-06-09 21:13:42,369 - __main__ - INFO - Saved periodic model checkpoint to ./output/model_epoch_10.pth
|
| 100 |
+
2025-06-09 21:13:42,369 - __main__ - INFO - Performing memory optimization after epoch...
|
| 101 |
+
2025-06-09 21:13:42,654 - __main__ - INFO - CUDA cache emptied.
|
| 102 |
+
2025-06-09 21:13:42,912 - __main__ - INFO - Python garbage collector run.
|
| 103 |
+
Epoch 11 Training: 3%|▎ | 99/3125 [01:42<50:15, 1.00it/s]
|
| 104 |
+
2025-06-09 21:15:26,371 - __main__ - INFO - Epoch [11/18], Step [100/3125], Loss: 2.3691, Perplexity: 10.6873
|
| 105 |
+
Epoch 11 Training: 6%|▋ | 199/3125 [03:22<48:47, 1.00s/it]
|
| 106 |
+
2025-06-09 21:17:06,315 - __main__ - INFO - Epoch [11/18], Step [200/3125], Loss: 2.4723, Perplexity: 11.8502
|
| 107 |
+
Epoch 11 Training: 10%|▉ | 299/3125 [05:01<47:02, 1.00it/s]
|
| 108 |
+
2025-06-09 21:18:45,667 - __main__ - INFO - Epoch [11/18], Step [300/3125], Loss: 2.5049, Perplexity: 12.2420
|
| 109 |
+
Epoch 11 Training: 13%|█▎ | 399/3125 [06:41<45:29, 1.00s/it]
|
| 110 |
+
2025-06-09 21:20:25,533 - __main__ - INFO - Epoch [11/18], Step [400/3125], Loss: 2.5821, Perplexity: 13.2247
|
| 111 |
+
Epoch 11 Training: 16%|█▌ | 499/3125 [08:21<43:37, 1.00it/s]
|
| 112 |
+
2025-06-09 21:22:05,674 - __main__ - INFO - Epoch [11/18], Step [500/3125], Loss: 2.9378, Perplexity: 18.8750
|
| 113 |
+
Epoch 11 Training: 19%|█▉ | 599/3125 [10:01<41:51, 1.01it/s]
|
| 114 |
+
2025-06-09 21:23:45,828 - __main__ - INFO - Epoch [11/18], Step [600/3125], Loss: 2.4629, Perplexity: 11.7391
|
| 115 |
+
Epoch 11 Training: 22%|██▏ | 699/3125 [11:41<40:02, 1.01it/s]
|
| 116 |
+
2025-06-09 21:25:25,654 - __main__ - INFO - Epoch [11/18], Step [700/3125], Loss: 2.6155, Perplexity: 13.6746
|
| 117 |
+
Epoch 11 Training: 26%|██▌ | 799/3125 [13:21<38:43, 1.00it/s]
|
| 118 |
+
2025-06-09 21:27:05,330 - __main__ - INFO - Epoch [11/18], Step [800/3125], Loss: 2.4537, Perplexity: 11.6314
|
| 119 |
+
Epoch 11 Training: 29%|██▉ | 899/3125 [15:01<38:04, 1.03s/it]
|
| 120 |
+
2025-06-09 21:28:45,178 - __main__ - INFO - Epoch [11/18], Step [900/3125], Loss: 2.4852, Perplexity: 12.0030
|
| 121 |
+
Epoch 11 Training: 32%|███▏ | 999/3125 [16:40<34:52, 1.02it/s]
|
| 122 |
+
2025-06-09 21:30:24,859 - __main__ - INFO - Epoch [11/18], Step [1000/3125], Loss: 2.6182, Perplexity: 13.7113
|
| 123 |
+
Epoch 11 Training: 35%|███▌ | 1099/3125 [18:20<33:24, 1.01it/s]
|
| 124 |
+
2025-06-09 21:32:04,811 - __main__ - INFO - Epoch [11/18], Step [1100/3125], Loss: 2.3901, Perplexity: 10.9150
|
| 125 |
+
Epoch 11 Training: 38%|███▊ | 1199/3125 [20:00<31:51, 1.01it/s]
|
| 126 |
+
2025-06-09 21:33:44,653 - __main__ - INFO - Epoch [11/18], Step [1200/3125], Loss: 2.6152, Perplexity: 13.6705
|
| 127 |
+
Epoch 11 Training: 42%|████▏ | 1299/3125 [21:40<30:49, 1.01s/it]
|
| 128 |
+
2025-06-09 21:35:24,568 - __main__ - INFO - Epoch [11/18], Step [1300/3125], Loss: 2.7108, Perplexity: 15.0420
|
| 129 |
+
Epoch 11 Training: 45%|████▍ | 1399/3125 [23:20<28:14, 1.02it/s]
|
| 130 |
+
2025-06-09 21:37:04,192 - __main__ - INFO - Epoch [11/18], Step [1400/3125], Loss: 2.5307, Perplexity: 12.5626
|
| 131 |
+
Epoch 11 Training: 48%|████▊ | 1499/3125 [25:00<27:04, 1.00it/s]
|
| 132 |
+
2025-06-09 21:38:43,960 - __main__ - INFO - Epoch [11/18], Step [1500/3125], Loss: 2.5410, Perplexity: 12.6921
|
| 133 |
+
Epoch 11 Training: 51%|█████ | 1599/3125 [26:39<25:55, 1.02s/it]
|
| 134 |
+
2025-06-09 21:40:23,752 - __main__ - INFO - Epoch [11/18], Step [1600/3125], Loss: 2.5365, Perplexity: 12.6349
|
| 135 |
+
Epoch 11 Training: 54%|█████▍ | 1699/3125 [28:19<23:49, 1.00s/it]
|
| 136 |
+
2025-06-09 21:42:03,735 - __main__ - INFO - Epoch [11/18], Step [1700/3125], Loss: 2.8819, Perplexity: 17.8483
|
| 137 |
+
Epoch 11 Training: 58%|█████▊ | 1799/3125 [29:59<22:08, 1.00s/it]
|
| 138 |
+
2025-06-09 21:43:43,540 - __main__ - INFO - Epoch [11/18], Step [1800/3125], Loss: 2.5707, Perplexity: 13.0754
|
| 139 |
+
Epoch 11 Training: 61%|██████ | 1899/3125 [31:39<20:19, 1.01it/s]
|
| 140 |
+
2025-06-09 21:45:23,225 - __main__ - INFO - Epoch [11/18], Step [1900/3125], Loss: 2.4161, Perplexity: 11.2024
|
| 141 |
+
Epoch 11 Training: 64%|██████▍ | 1999/3125 [33:19<18:37, 1.01it/s]
|
| 142 |
+
2025-06-09 21:47:02,925 - __main__ - INFO - Epoch [11/18], Step [2000/3125], Loss: 2.5705, Perplexity: 13.0728
|
| 143 |
+
Epoch 11 Training: 67%|██████▋ | 2099/3125 [34:58<17:16, 1.01s/it]
|
| 144 |
+
2025-06-09 21:48:42,726 - __main__ - INFO - Epoch [11/18], Step [2100/3125], Loss: 2.4674, Perplexity: 11.7918
|
| 145 |
+
Epoch 11 Training: 70%|███████ | 2199/3125 [36:38<15:29, 1.00s/it]
|
| 146 |
+
2025-06-09 21:50:22,947 - __main__ - INFO - Epoch [11/18], Step [2200/3125], Loss: 2.5938, Perplexity: 13.3808
|
| 147 |
+
Epoch 11 Training: 74%|███████▎ | 2299/3125 [38:18<13:40, 1.01it/s]
|
| 148 |
+
2025-06-09 21:52:02,823 - __main__ - INFO - Epoch [11/18], Step [2300/3125], Loss: 2.6236, Perplexity: 13.7849
|
| 149 |
+
Epoch 11 Training: 77%|███████▋ | 2399/3125 [39:58<12:09, 1.00s/it]
|
| 150 |
+
2025-06-09 21:53:42,643 - __main__ - INFO - Epoch [11/18], Step [2400/3125], Loss: 2.3626, Perplexity: 10.6186
|
| 151 |
+
Epoch 11 Training: 80%|███████▉ | 2499/3125 [41:38<10:29, 1.00s/it]
|
| 152 |
+
2025-06-09 21:55:22,679 - __main__ - INFO - Epoch [11/18], Step [2500/3125], Loss: 2.7776, Perplexity: 16.0800
|
| 153 |
+
Epoch 11 Training: 83%|████████▎ | 2599/3125 [43:18<08:43, 1.00it/s]
|
| 154 |
+
2025-06-09 21:57:02,100 - __main__ - INFO - Epoch [11/18], Step [2600/3125], Loss: 2.3201, Perplexity: 10.1771
|
| 155 |
+
Epoch 11 Training: 86%|████████▋ | 2699/3125 [44:58<07:02, 1.01it/s]
|
| 156 |
+
2025-06-09 21:58:41,997 - __main__ - INFO - Epoch [11/18], Step [2700/3125], Loss: 2.7016, Perplexity: 14.9040
|
| 157 |
+
Epoch 11 Training: 90%|████████▉ | 2799/3125 [46:38<05:25, 1.00it/s]
|
| 158 |
+
2025-06-09 22:00:22,129 - __main__ - INFO - Epoch [11/18], Step [2800/3125], Loss: 2.5685, Perplexity: 13.0467
|
| 159 |
+
Epoch 11 Training: 93%|█████████▎| 2899/3125 [48:18<03:46, 1.00s/it]
|
| 160 |
+
2025-06-09 22:02:02,186 - __main__ - INFO - Epoch [11/18], Step [2900/3125], Loss: 2.5174, Perplexity: 12.3969
|
| 161 |
+
Epoch 11 Training: 96%|█████████▌| 2999/3125 [49:58<02:05, 1.00it/s]
|
| 162 |
+
2025-06-09 22:03:42,251 - __main__ - INFO - Epoch [11/18], Step [3000/3125], Loss: 2.4016, Perplexity: 11.0412
|
| 163 |
+
Epoch 11 Training: 99%|█████████▉| 3099/3125 [51:38<00:25, 1.01it/s]
|
| 164 |
+
2025-06-09 22:05:22,387 - __main__ - INFO - Epoch [11/18], Step [3100/3125], Loss: 2.7063, Perplexity: 14.9733
|
| 165 |
+
Epoch 11 Training: 100%|██████████| 3125/3125 [52:04<00:00, 1.00it/s]
|
| 166 |
+
2025-06-09 22:05:47,454 - __main__ - INFO - Epoch 11 Training finished. Avg Loss: 2.5565, Time: 3124.54s
|
| 167 |
+
Validation: 100%|██████████| 391/391 [13:01<00:00, 2.00s/it]
|
| 168 |
+
2025-06-09 22:18:48,931 - __main__ - INFO - Validation Avg Loss: 2.5207, Perplexity: 12.4378
|
| 169 |
+
2025-06-09 22:18:59,521 - __main__ - INFO - Validation BLEU-4: 0.1024
|
| 170 |
+
2025-06-09 22:18:59,522 - __main__ - INFO - Performing memory optimization after epoch...
|
| 171 |
+
2025-06-09 22:18:59,794 - __main__ - INFO - CUDA cache emptied.
|
| 172 |
+
2025-06-09 22:19:00,165 - __main__ - INFO - Python garbage collector run.
|
| 173 |
+
Epoch 12 Training: 3%|▎ | 99/3125 [01:42<49:19, 1.02it/s]
|
| 174 |
+
2025-06-09 22:20:43,554 - __main__ - INFO - Epoch [12/18], Step [100/3125], Loss: 2.4403, Perplexity: 11.4770
|
| 175 |
+
Epoch 12 Training: 6%|▋ | 199/3125 [03:22<48:16, 1.01it/s]
|
| 176 |
+
2025-06-09 22:22:23,419 - __main__ - INFO - Epoch [12/18], Step [200/3125], Loss: 2.3241, Perplexity: 10.2174
|
| 177 |
+
Epoch 12 Training: 10%|▉ | 299/3125 [05:02<46:39, 1.01it/s]
|
| 178 |
+
2025-06-09 22:24:03,388 - __main__ - INFO - Epoch [12/18], Step [300/3125], Loss: 2.3308, Perplexity: 10.2864
|
| 179 |
+
Epoch 12 Training: 13%|█▎ | 399/3125 [06:41<46:12, 1.02s/it]
|
| 180 |
+
2025-06-09 22:25:43,123 - __main__ - INFO - Epoch [12/18], Step [400/3125], Loss: 2.5223, Perplexity: 12.4575
|
| 181 |
+
Epoch 12 Training: 16%|█▌ | 499/3125 [08:22<43:29, 1.01it/s]
|
| 182 |
+
2025-06-09 22:27:23,173 - __main__ - INFO - Epoch [12/18], Step [500/3125], Loss: 2.4984, Perplexity: 12.1631
|
| 183 |
+
Epoch 12 Training: 19%|█▉ | 599/3125 [10:02<42:15, 1.00s/it]
|
| 184 |
+
2025-06-09 22:29:03,434 - __main__ - INFO - Epoch [12/18], Step [600/3125], Loss: 2.4451, Perplexity: 11.5312
|
| 185 |
+
Epoch 12 Training: 22%|██▏ | 699/3125 [11:42<39:33, 1.02it/s]
|
| 186 |
+
2025-06-09 22:30:43,225 - __main__ - INFO - Epoch [12/18], Step [700/3125], Loss: 2.3790, Perplexity: 10.7946
|
| 187 |
+
Epoch 12 Training: 26%|██▌ | 799/3125 [13:22<38:02, 1.02it/s]
|
| 188 |
+
2025-06-09 22:32:23,192 - __main__ - INFO - Epoch [12/18], Step [800/3125], Loss: 2.3688, Perplexity: 10.6844
|
| 189 |
+
Epoch 12 Training: 29%|██▉ | 899/3125 [15:01<36:38, 1.01it/s]
|
| 190 |
+
2025-06-09 22:34:02,897 - __main__ - INFO - Epoch [12/18], Step [900/3125], Loss: 2.5906, Perplexity: 13.3372
|
| 191 |
+
Epoch 12 Training: 32%|███▏ | 999/3125 [16:41<34:54, 1.02it/s]
|
| 192 |
+
2025-06-09 22:35:43,003 - __main__ - INFO - Epoch [12/18], Step [1000/3125], Loss: 2.5290, Perplexity: 12.5412
|
| 193 |
+
Epoch 12 Training: 35%|███▌ | 1099/3125 [18:21<33:36, 1.00it/s]
|
| 194 |
+
2025-06-09 22:37:22,472 - __main__ - INFO - Epoch [12/18], Step [1100/3125], Loss: 2.3719, Perplexity: 10.7179
|
| 195 |
+
Epoch 12 Training: 38%|███▊ | 1199/3125 [20:01<32:32, 1.01s/it]
|
| 196 |
+
2025-06-09 22:39:03,204 - __main__ - INFO - Epoch [12/18], Step [1200/3125], Loss: 2.5641, Perplexity: 12.9886
|
| 197 |
+
Epoch 12 Training: 42%|████▏ | 1299/3125 [21:42<30:36, 1.01s/it]
|
| 198 |
+
2025-06-09 22:40:43,259 - __main__ - INFO - Epoch [12/18], Step [1300/3125], Loss: 2.5392, Perplexity: 12.6697
|
| 199 |
+
Epoch 12 Training: 45%|████▍ | 1399/3125 [23:22<29:17, 1.02s/it]
|
| 200 |
+
2025-06-09 22:42:23,714 - __main__ - INFO - Epoch [12/18], Step [1400/3125], Loss: 2.6697, Perplexity: 14.4351
|
| 201 |
+
Epoch 12 Training: 48%|████▊ | 1499/3125 [25:02<26:46, 1.01it/s]
|
| 202 |
+
2025-06-09 22:44:03,596 - __main__ - INFO - Epoch [12/18], Step [1500/3125], Loss: 2.3967, Perplexity: 10.9870
|
| 203 |
+
Epoch 12 Training: 51%|█████ | 1599/3125 [26:42<24:59, 1.02it/s]
|
| 204 |
+
2025-06-09 22:45:43,674 - __main__ - INFO - Epoch [12/18], Step [1600/3125], Loss: 2.6011, Perplexity: 13.4780
|
| 205 |
+
Epoch 12 Training: 54%|█████▍ | 1699/3125 [28:22<23:49, 1.00s/it]
|
| 206 |
+
2025-06-09 22:47:23,776 - __main__ - INFO - Epoch [12/18], Step [1700/3125], Loss: 2.5272, Perplexity: 12.5179
|
| 207 |
+
Epoch 12 Training: 58%|█████▊ | 1799/3125 [30:02<22:19, 1.01s/it]
|
| 208 |
+
2025-06-09 22:49:03,471 - __main__ - INFO - Epoch [12/18], Step [1800/3125], Loss: 2.3498, Perplexity: 10.4834
|
| 209 |
+
Epoch 12 Training: 61%|██████ | 1899/3125 [31:41<20:06, 1.02it/s]
|
| 210 |
+
2025-06-09 22:50:43,076 - __main__ - INFO - Epoch [12/18], Step [1900/3125], Loss: 2.8234, Perplexity: 16.8332
|
| 211 |
+
Epoch 12 Training: 64%|██████▍ | 1999/3125 [33:21<18:55, 1.01s/it]
|
| 212 |
+
2025-06-09 22:52:22,767 - __main__ - INFO - Epoch [12/18], Step [2000/3125], Loss: 2.1771, Perplexity: 8.8204
|
| 213 |
+
Epoch 12 Training: 67%|██���███▋ | 2099/3125 [35:02<17:22, 1.02s/it]
|
| 214 |
+
2025-06-09 22:54:03,185 - __main__ - INFO - Epoch [12/18], Step [2100/3125], Loss: 2.3431, Perplexity: 10.4136
|
| 215 |
+
Epoch 12 Training: 70%|███████ | 2199/3125 [36:41<15:18, 1.01it/s]
|
| 216 |
+
2025-06-09 22:55:43,082 - __main__ - INFO - Epoch [12/18], Step [2200/3125], Loss: 2.6427, Perplexity: 14.0514
|
| 217 |
+
Epoch 12 Training: 74%|███████▎ | 2299/3125 [38:21<13:42, 1.00it/s]
|
| 218 |
+
2025-06-09 22:57:22,857 - __main__ - INFO - Epoch [12/18], Step [2300/3125], Loss: 2.4172, Perplexity: 11.2148
|
| 219 |
+
Epoch 12 Training: 77%|███████▋ | 2399/3125 [40:01<11:52, 1.02it/s]
|
| 220 |
+
2025-06-09 22:59:02,397 - __main__ - INFO - Epoch [12/18], Step [2400/3125], Loss: 2.7323, Perplexity: 15.3679
|
| 221 |
+
Epoch 12 Training: 80%|███████▉ | 2499/3125 [41:41<10:30, 1.01s/it]
|
| 222 |
+
2025-06-09 23:00:42,439 - __main__ - INFO - Epoch [12/18], Step [2500/3125], Loss: 2.7351, Perplexity: 15.4109
|
| 223 |
+
Epoch 12 Training: 83%|████████▎ | 2599/3125 [43:20<08:37, 1.02it/s]
|
| 224 |
+
2025-06-09 23:02:21,984 - __main__ - INFO - Epoch [12/18], Step [2600/3125], Loss: 2.4624, Perplexity: 11.7333
|
| 225 |
+
Epoch 12 Training: 86%|████████▋ | 2699/3125 [45:00<07:11, 1.01s/it]
|
| 226 |
+
2025-06-09 23:04:02,074 - __main__ - INFO - Epoch [12/18], Step [2700/3125], Loss: 2.4864, Perplexity: 12.0180
|
| 227 |
+
Epoch 12 Training: 90%|████████▉ | 2799/3125 [46:41<05:23, 1.01it/s]
|
| 228 |
+
2025-06-09 23:05:42,197 - __main__ - INFO - Epoch [12/18], Step [2800/3125], Loss: 2.7285, Perplexity: 15.3102
|
| 229 |
+
Epoch 12 Training: 93%|█████████▎| 2899/3125 [48:20<03:45, 1.00it/s]
|
| 230 |
+
2025-06-09 23:07:21,825 - __main__ - INFO - Epoch [12/18], Step [2900/3125], Loss: 2.2980, Perplexity: 9.9542
|
| 231 |
+
Epoch 12 Training: 96%|█████████▌| 2999/3125 [50:00<02:07, 1.01s/it]
|
| 232 |
+
2025-06-09 23:09:02,083 - __main__ - INFO - Epoch [12/18], Step [3000/3125], Loss: 2.5476, Perplexity: 12.7761
|
| 233 |
+
Epoch 12 Training: 99%|█████████▉| 3099/3125 [51:40<00:25, 1.02it/s]
|
| 234 |
+
2025-06-09 23:10:41,765 - __main__ - INFO - Epoch [12/18], Step [3100/3125], Loss: 2.3022, Perplexity: 9.9965
|
| 235 |
+
Epoch 12 Training: 100%|██████████| 3125/3125 [52:06<00:00, 1.00s/it]
|
| 236 |
+
2025-06-09 23:11:06,691 - __main__ - INFO - Epoch 12 Training finished. Avg Loss: 2.4966, Time: 3126.52s
|
| 237 |
+
Validation: 100%|██████████| 391/391 [12:56<00:00, 1.99s/it]
|
| 238 |
+
2025-06-09 23:24:03,561 - __main__ - INFO - Validation Avg Loss: 2.5151, Perplexity: 12.3681
|
| 239 |
+
2025-06-09 23:24:13,805 - __main__ - INFO - Validation BLEU-4: 0.1011
|
| 240 |
+
2025-06-09 23:24:13,806 - __main__ - INFO - Performing memory optimization after epoch...
|
| 241 |
+
2025-06-09 23:24:14,070 - __main__ - INFO - CUDA cache emptied.
|
| 242 |
+
2025-06-09 23:24:14,429 - __main__ - INFO - Python garbage collector run.
|
| 243 |
+
Epoch 13 Training: 3%|▎ | 99/3125 [01:42<51:15, 1.02s/it]
|
| 244 |
+
2025-06-09 23:25:58,208 - __main__ - INFO - Epoch [13/18], Step [100/3125], Loss: 2.4482, Perplexity: 11.5679
|
| 245 |
+
Epoch 13 Training: 6%|▋ | 199/3125 [03:22<48:21, 1.01it/s]
|
| 246 |
+
2025-06-09 23:27:37,851 - __main__ - INFO - Epoch [13/18], Step [200/3125], Loss: 2.4197, Perplexity: 11.2422
|
| 247 |
+
Epoch 13 Training: 10%|▉ | 299/3125 [05:02<46:30, 1.01it/s]
|
| 248 |
+
2025-06-09 23:29:17,582 - __main__ - INFO - Epoch [13/18], Step [300/3125], Loss: 2.6092, Perplexity: 13.5885
|
| 249 |
+
Epoch 13 Training: 13%|█▎ | 399/3125 [06:42<45:55, 1.01s/it]
|
| 250 |
+
2025-06-09 23:30:57,708 - __main__ - INFO - Epoch [13/18], Step [400/3125], Loss: 2.3414, Perplexity: 10.3956
|
| 251 |
+
Epoch 13 Training: 16%|█▌ | 499/3125 [08:22<44:21, 1.01s/it]
|
| 252 |
+
2025-06-09 23:32:37,419 - __main__ - INFO - Epoch [13/18], Step [500/3125], Loss: 2.3210, Perplexity: 10.1858
|
| 253 |
+
Epoch 13 Training: 19%|█▉ | 599/3125 [10:02<41:59, 1.00it/s]
|
| 254 |
+
2025-06-09 23:34:17,416 - __main__ - INFO - Epoch [13/18], Step [600/3125], Loss: 2.3739, Perplexity: 10.7388
|
| 255 |
+
Epoch 13 Training: 22%|██▏ | 699/3125 [11:42<39:33, 1.02it/s]
|
| 256 |
+
2025-06-09 23:35:57,481 - __main__ - INFO - Epoch [13/18], Step [700/3125], Loss: 2.5507, Perplexity: 12.8167
|
| 257 |
+
Epoch 13 Training: 26%|██▌ | 799/3125 [13:22<38:21, 1.01it/s]
|
| 258 |
+
2025-06-09 23:37:37,545 - __main__ - INFO - Epoch [13/18], Step [800/3125], Loss: 2.4497, Perplexity: 11.5848
|
| 259 |
+
Epoch 13 Training: 29%|██▉ | 899/3125 [15:01<36:56, 1.00it/s]
|
| 260 |
+
2025-06-09 23:39:17,185 - __main__ - INFO - Epoch [13/18], Step [900/3125], Loss: 2.4555, Perplexity: 11.6527
|
| 261 |
+
Epoch 13 Training: 32%|███▏ | 999/3125 [16:41<36:31, 1.03s/it]
|
| 262 |
+
2025-06-09 23:40:56,979 - __main__ - INFO - Epoch [13/18], Step [1000/3125], Loss: 2.2727, Perplexity: 9.7054
|
| 263 |
+
Epoch 13 Training: 35%|███▌ | 1099/3125 [18:21<33:55, 1.00s/it]
|
| 264 |
+
2025-06-09 23:42:36,830 - __main__ - INFO - Epoch [13/18], Step [1100/3125], Loss: 2.4161, Perplexity: 11.2025
|
| 265 |
+
Epoch 13 Training: 38%|███▊ | 1199/3125 [20:01<32:52, 1.02s/it]
|
| 266 |
+
2025-06-09 23:44:16,954 - __main__ - INFO - Epoch [13/18], Step [1200/3125], Loss: 2.5078, Perplexity: 12.2775
|
| 267 |
+
Epoch 13 Training: 42%|████▏ | 1299/3125 [21:41<30:29, 1.00s/it]
|
| 268 |
+
2025-06-09 23:45:57,440 - __main__ - INFO - Epoch [13/18], Step [1300/3125], Loss: 2.3249, Perplexity: 10.2256
|
| 269 |
+
Epoch 13 Training: 45%|████▍ | 1399/3125 [23:21<28:51, 1.00s/it]
|
| 270 |
+
2025-06-09 23:47:37,061 - __main__ - INFO - Epoch [13/18], Step [1400/3125], Loss: 2.4165, Perplexity: 11.2065
|
| 271 |
+
Epoch 13 Training: 48%|████▊ | 1499/3125 [25:01<27:32, 1.02s/it]
|
| 272 |
+
2025-06-09 23:49:16,690 - __main__ - INFO - Epoch [13/18], Step [1500/3125], Loss: 2.6065, Perplexity: 13.5516
|
| 273 |
+
Epoch 13 Training: 51%|█████ | 1599/3125 [26:41<26:01, 1.02s/it]
|
| 274 |
+
2025-06-09 23:50:57,187 - __main__ - INFO - Epoch [13/18], Step [1600/3125], Loss: 2.4175, Perplexity: 11.2178
|
| 275 |
+
Epoch 13 Training: 54%|█████▍ | 1699/3125 [28:22<23:52, 1.00s/it]
|
| 276 |
+
2025-06-09 23:52:37,586 - __main__ - INFO - Epoch [13/18], Step [1700/3125], Loss: 2.6172, Perplexity: 13.6977
|
| 277 |
+
Epoch 13 Training: 58%|█████▊ | 1799/3125 [30:02<22:25, 1.01s/it]
|
| 278 |
+
2025-06-09 23:54:17,784 - __main__ - INFO - Epoch [13/18], Step [1800/3125], Loss: 2.6982, Perplexity: 14.8536
|
| 279 |
+
Epoch 13 Training: 61%|██████ | 1899/3125 [31:42<21:00, 1.03s/it]
|
| 280 |
+
2025-06-09 23:55:57,904 - __main__ - INFO - Epoch [13/18], Step [1900/3125], Loss: 2.5895, Perplexity: 13.3233
|
| 281 |
+
Epoch 13 Training: 64%|██████▍ | 1999/3125 [33:22<18:36, 1.01it/s]
|
| 282 |
+
2025-06-09 23:57:38,406 - __main__ - INFO - Epoch [13/18], Step [2000/3125], Loss: 2.3281, Perplexity: 10.2589
|
| 283 |
+
Epoch 13 Training: 67%|██████▋ | 2099/3125 [35:02<17:31, 1.03s/it]
|
| 284 |
+
2025-06-09 23:59:18,322 - __main__ - INFO - Epoch [13/18], Step [2100/3125], Loss: 2.4475, Perplexity: 11.5592
|
| 285 |
+
Epoch 13 Training: 70%|███████ | 2199/3125 [36:42<15:18, 1.01it/s]
|
| 286 |
+
2025-06-10 00:00:58,023 - __main__ - INFO - Epoch [13/18], Step [2200/3125], Loss: 2.3961, Perplexity: 10.9799
|
| 287 |
+
Epoch 13 Training: 74%|███████▎ | 2299/3125 [38:22<13:59, 1.02s/it]
|
| 288 |
+
2025-06-10 00:02:38,142 - __main__ - INFO - Epoch [13/18], Step [2300/3125], Loss: 2.2835, Perplexity: 9.8108
|
| 289 |
+
Epoch 13 Training: 77%|███████▋ | 2399/3125 [40:02<12:11, 1.01s/it]
|
| 290 |
+
2025-06-10 00:04:17,990 - __main__ - INFO - Epoch [13/18], Step [2400/3125], Loss: 2.4577, Perplexity: 11.6781
|
| 291 |
+
Epoch 13 Training: 80%|███████▉ | 2499/3125 [41:42<10:38, 1.02s/it]
|
| 292 |
+
2025-06-10 00:05:58,212 - __main__ - INFO - Epoch [13/18], Step [2500/3125], Loss: 2.4646, Perplexity: 11.7588
|
| 293 |
+
Epoch 13 Training: 83%|████████▎ | 2599/3125 [43:22<08:52, 1.01s/it]
|
| 294 |
+
2025-06-10 00:07:37,617 - __main__ - INFO - Epoch [13/18], Step [2600/3125], Loss: 2.4594, Perplexity: 11.6975
|
| 295 |
+
Epoch 13 Training: 86%|████████▋ | 2699/3125 [45:02<07:09, 1.01s/it]
|
| 296 |
+
2025-06-10 00:09:17,938 - __main__ - INFO - Epoch [13/18], Step [2700/3125], Loss: 2.1887, Perplexity: 8.9235
|
| 297 |
+
Epoch 13 Training: 90%|████████▉ | 2799/3125 [46:42<05:24, 1.01it/s]
|
| 298 |
+
2025-06-10 00:10:57,572 - __main__ - INFO - Epoch [13/18], Step [2800/3125], Loss: 2.3643, Perplexity: 10.6365
|
| 299 |
+
Epoch 13 Training: 93%|█████████▎| 2899/3125 [48:21<03:44, 1.01it/s]
|
| 300 |
+
2025-06-10 00:12:37,377 - __main__ - INFO - Epoch [13/18], Step [2900/3125], Loss: 2.3395, Perplexity: 10.3765
|
| 301 |
+
Epoch 13 Training: 96%|█████████▌| 2999/3125 [50:01<02:06, 1.00s/it]
|
| 302 |
+
2025-06-10 00:14:17,341 - __main__ - INFO - Epoch [13/18], Step [3000/3125], Loss: 2.6757, Perplexity: 14.5222
|
| 303 |
+
Epoch 13 Training: 99%|█████████▉| 3099/3125 [51:41<00:25, 1.02it/s]
|
| 304 |
+
2025-06-10 00:15:56,947 - __main__ - INFO - Epoch [13/18], Step [3100/3125], Loss: 2.3261, Perplexity: 10.2375
|
| 305 |
+
Epoch 13 Training: 100%|██████████| 3125/3125 [52:07<00:00, 1.00s/it]
|
| 306 |
+
2025-06-10 00:16:21,710 - __main__ - INFO - Epoch 13 Training finished. Avg Loss: 2.4454, Time: 3127.28s
|
| 307 |
+
Validation: 100%|██████████| 391/391 [11:23<00:00, 1.75s/it]
|
| 308 |
+
2025-06-10 00:27:44,952 - __main__ - INFO - Validation Avg Loss: 2.5155, Perplexity: 12.3724
|
| 309 |
+
2025-06-10 00:27:54,230 - __main__ - INFO - Validation BLEU-4: 0.1028
|
| 310 |
+
2025-06-10 00:27:54,231 - __main__ - INFO - Performing memory optimization after epoch...
|
| 311 |
+
2025-06-10 00:27:54,512 - __main__ - INFO - CUDA cache emptied.
|
| 312 |
+
2025-06-10 00:27:54,845 - __main__ - INFO - Python garbage collector run.
|
| 313 |
+
Epoch 14 Training: 3%|▎ | 99/3125 [01:41<49:13, 1.02it/s]
|
| 314 |
+
2025-06-10 00:29:37,110 - __main__ - INFO - Epoch [14/18], Step [100/3125], Loss: 2.2691, Perplexity: 9.6705
|
| 315 |
+
Epoch 14 Training: 6%|▋ | 199/3125 [03:20<48:25, 1.01it/s]
|
| 316 |
+
2025-06-10 00:31:15,892 - __main__ - INFO - Epoch [14/18], Step [200/3125], Loss: 2.2401, Perplexity: 9.3940
|
| 317 |
+
Epoch 14 Training: 10%|▉ | 299/3125 [04:59<46:23, 1.02it/s]
|
| 318 |
+
2025-06-10 00:32:55,407 - __main__ - INFO - Epoch [14/18], Step [300/3125], Loss: 2.2769, Perplexity: 9.7467
|
| 319 |
+
Epoch 14 Training: 13%|█▎ | 399/3125 [06:38<44:38, 1.02it/s]
|
| 320 |
+
2025-06-10 00:34:34,689 - __main__ - INFO - Epoch [14/18], Step [400/3125], Loss: 2.3194, Perplexity: 10.1698
|
| 321 |
+
Epoch 14 Training: 16%|█▌ | 499/3125 [08:17<43:00, 1.02it/s]
|
| 322 |
+
2025-06-10 00:36:13,668 - __main__ - INFO - Epoch [14/18], Step [500/3125], Loss: 2.3454, Perplexity: 10.4371
|
| 323 |
+
Epoch 14 Training: 19%|█▉ | 599/3125 [09:57<42:10, 1.00s/it]
|
| 324 |
+
2025-06-10 00:37:53,169 - __main__ - INFO - Epoch [14/18], Step [600/3125], Loss: 2.3314, Perplexity: 10.2923
|
| 325 |
+
Epoch 14 Training: 22%|██▏ | 699/3125 [11:36<39:46, 1.02it/s]
|
| 326 |
+
2025-06-10 00:39:32,397 - __main__ - INFO - Epoch [14/18], Step [700/3125], Loss: 2.1478, Perplexity: 8.5664
|
| 327 |
+
Epoch 14 Training: 26%|██▌ | 799/3125 [13:15<38:00, 1.02it/s]
|
| 328 |
+
2025-06-10 00:41:11,424 - __main__ - INFO - Epoch [14/18], Step [800/3125], Loss: 2.4812, Perplexity: 11.9557
|
| 329 |
+
Epoch 14 Training: 29%|██▉ | 899/3125 [14:54<37:12, 1.00s/it]
|
| 330 |
+
2025-06-10 00:42:50,444 - __main__ - INFO - Epoch [14/18], Step [900/3125], Loss: 2.5592, Perplexity: 12.9257
|
| 331 |
+
Epoch 14 Training: 32%|███▏ | 999/3125 [16:34<34:52, 1.02it/s]
|
| 332 |
+
2025-06-10 00:44:29,857 - __main__ - INFO - Epoch [14/18], Step [1000/3125], Loss: 2.4252, Perplexity: 11.3050
|
| 333 |
+
Epoch 14 Training: 35%|███▌ | 1099/3125 [18:13<33:43, 1.00it/s]
|
| 334 |
+
2025-06-10 00:46:09,446 - __main__ - INFO - Epoch [14/18], Step [1100/3125], Loss: 2.4280, Perplexity: 11.3366
|
| 335 |
+
Epoch 14 Training: 38%|███▊ | 1199/3125 [19:52<31:57, 1.00it/s]
|
| 336 |
+
2025-06-10 00:47:48,452 - __main__ - INFO - Epoch [14/18], Step [1200/3125], Loss: 2.2805, Perplexity: 9.7818
|
| 337 |
+
Epoch 14 Training: 42%|████▏ | 1299/3125 [21:32<30:13, 1.01it/s]
|
| 338 |
+
2025-06-10 00:49:27,846 - __main__ - INFO - Epoch [14/18], Step [1300/3125], Loss: 2.3755, Perplexity: 10.7560
|
| 339 |
+
Epoch 14 Training: 45%|████▍ | 1399/3125 [23:11<28:21, 1.01it/s]
|
| 340 |
+
2025-06-10 00:51:07,151 - __main__ - INFO - Epoch [14/18], Step [1400/3125], Loss: 2.4423, Perplexity: 11.4991
|
| 341 |
+
Epoch 14 Training: 48%|████▊ | 1499/3125 [24:49<26:28, 1.02it/s]
|
| 342 |
+
2025-06-10 00:52:45,875 - __main__ - INFO - Epoch [14/18], Step [1500/3125], Loss: 2.7027, Perplexity: 14.9202
|
| 343 |
+
Epoch 14 Training: 51%|█████ | 1599/3125 [26:29<25:11, 1.01it/s]
|
| 344 |
+
2025-06-10 00:54:24,994 - __main__ - INFO - Epoch [14/18], Step [1600/3125], Loss: 2.5307, Perplexity: 12.5619
|
| 345 |
+
Epoch 14 Training: 54%|█████▍ | 1699/3125 [28:08<23:33, 1.01it/s]
|
| 346 |
+
2025-06-10 00:56:04,133 - __main__ - INFO - Epoch [14/18], Step [1700/3125], Loss: 2.6793, Perplexity: 14.5745
|
| 347 |
+
Epoch 14 Training: 58%|█████▊ | 1799/3125 [29:47<21:40, 1.02it/s]
|
| 348 |
+
2025-06-10 00:57:43,590 - __main__ - INFO - Epoch [14/18], Step [1800/3125], Loss: 2.3497, Perplexity: 10.4828
|
| 349 |
+
Epoch 14 Training: 61%|██████ | 1899/3125 [31:27<20:19, 1.01it/s]
|
| 350 |
+
2025-06-10 00:59:23,072 - __main__ - INFO - Epoch [14/18], Step [1900/3125], Loss: 2.2267, Perplexity: 9.2696
|
| 351 |
+
Epoch 14 Training: 64%|██████▍ | 1999/3125 [33:06<18:50, 1.00s/it]
|
| 352 |
+
2025-06-10 01:01:02,177 - __main__ - INFO - Epoch [14/18], Step [2000/3125], Loss: 2.1601, Perplexity: 8.6721
|
| 353 |
+
Epoch 14 Training: 67%|██████▋ | 2099/3125 [34:45<16:47, 1.02it/s]
|
| 354 |
+
2025-06-10 01:02:41,309 - __main__ - INFO - Epoch [14/18], Step [2100/3125], Loss: 2.3438, Perplexity: 10.4212
|
| 355 |
+
Epoch 14 Training: 70%|███████ | 2199/3125 [36:24<15:26, 1.00s/it]
|
| 356 |
+
2025-06-10 01:04:20,695 - __main__ - INFO - Epoch [14/18], Step [2200/3125], Loss: 2.3716, Perplexity: 10.7140
|
| 357 |
+
Epoch 14 Training: 74%|███████▎ | 2299/3125 [38:04<13:56, 1.01s/it]
|
| 358 |
+
2025-06-10 01:06:00,048 - __main__ - INFO - Epoch [14/18], Step [2300/3125], Loss: 2.4434, Perplexity: 11.5116
|
| 359 |
+
Epoch 14 Training: 77%|███████▋ | 2399/3125 [39:42<12:12, 1.01s/it]
|
| 360 |
+
2025-06-10 01:07:38,643 - __main__ - INFO - Epoch [14/18], Step [2400/3125], Loss: 2.5465, Perplexity: 12.7625
|
| 361 |
+
Epoch 14 Training: 80%|███████▉ | 2499/3125 [41:22<10:19, 1.01it/s]
|
| 362 |
+
2025-06-10 01:09:18,224 - __main__ - INFO - Epoch [14/18], Step [2500/3125], Loss: 2.2639, Perplexity: 9.6206
|
| 363 |
+
Epoch 14 Training: 83%|████████▎ | 2599/3125 [43:01<08:31, 1.03it/s]
|
| 364 |
+
2025-06-10 01:10:57,528 - __main__ - INFO - Epoch [14/18], Step [2600/3125], Loss: 2.4817, Perplexity: 11.9613
|
| 365 |
+
Epoch 14 Training: 86%|████████▋ | 2699/3125 [44:41<07:03, 1.01it/s]
|
| 366 |
+
2025-06-10 01:12:36,994 - __main__ - INFO - Epoch [14/18], Step [2700/3125], Loss: 2.5853, Perplexity: 13.2677
|
| 367 |
+
Epoch 14 Training: 90%|████████▉ | 2799/3125 [46:20<05:26, 1.00s/it]
|
| 368 |
+
2025-06-10 01:14:16,565 - __main__ - INFO - Epoch [14/18], Step [2800/3125], Loss: 2.4660, Perplexity: 11.7758
|
| 369 |
+
Epoch 14 Training: 93%|█████████▎| 2899/3125 [47:59<03:42, 1.02it/s]
|
| 370 |
+
2025-06-10 01:15:55,419 - __main__ - INFO - Epoch [14/18], Step [2900/3125], Loss: 2.2190, Perplexity: 9.1977
|
| 371 |
+
Epoch 14 Training: 96%|█████████▌| 2999/3125 [49:38<02:06, 1.00s/it]
|
| 372 |
+
2025-06-10 01:17:34,545 - __main__ - INFO - Epoch [14/18], Step [3000/3125], Loss: 2.3681, Perplexity: 10.6775
|
| 373 |
+
Epoch 14 Training: 99%|█████████▉| 3099/3125 [51:18<00:26, 1.01s/it]
|
| 374 |
+
2025-06-10 01:19:14,006 - __main__ - INFO - Epoch [14/18], Step [3100/3125], Loss: 2.3602, Perplexity: 10.5930
|
| 375 |
+
Epoch 14 Training: 100%|██████████| 3125/3125 [51:44<00:00, 1.01it/s]
|
| 376 |
+
2025-06-10 01:19:39,252 - __main__ - INFO - Epoch 14 Training finished. Avg Loss: 2.4006, Time: 3104.41s
|
| 377 |
+
Validation: 100%|██████████| 391/391 [11:33<00:00, 1.77s/it]
|
| 378 |
+
2025-06-10 01:31:12,588 - __main__ - INFO - Validation Avg Loss: 2.5215, Perplexity: 12.4476
|
| 379 |
+
2025-06-10 01:31:21,839 - __main__ - INFO - Validation BLEU-4: 0.1034
|
| 380 |
+
2025-06-10 01:31:22,515 - __main__ - INFO - Saved best model checkpoint to ./output/best_model_bleu0.1034.pth
|
| 381 |
+
2025-06-10 01:31:22,516 - __main__ - INFO - Performing memory optimization after epoch...
|
| 382 |
+
2025-06-10 01:31:22,796 - __main__ - INFO - CUDA cache emptied.
|
| 383 |
+
2025-06-10 01:31:23,124 - __main__ - INFO - Python garbage collector run.
|
| 384 |
+
Epoch 15 Training: 3%|▎ | 99/3125 [01:41<49:40, 1.02it/s]
|
| 385 |
+
2025-06-10 01:33:05,501 - __main__ - INFO - Epoch [15/18], Step [100/3125], Loss: 2.4716, Perplexity: 11.8419
|
| 386 |
+
Epoch 15 Training: 6%|▋ | 199/3125 [03:20<47:52, 1.02it/s]
|
| 387 |
+
2025-06-10 01:34:44,670 - __main__ - INFO - Epoch [15/18], Step [200/3125], Loss: 2.2404, Perplexity: 9.3972
|
| 388 |
+
Epoch 15 Training: 10%|▉ | 299/3125 [04:59<46:22, 1.02it/s]
|
| 389 |
+
2025-06-10 01:36:23,538 - __main__ - INFO - Epoch [15/18], Step [300/3125], Loss: 2.2223, Perplexity: 9.2283
|
| 390 |
+
Epoch 15 Training: 13%|█▎ | 399/3125 [06:38<45:28, 1.00s/it]
|
| 391 |
+
2025-06-10 01:38:02,777 - __main__ - INFO - Epoch [15/18], Step [400/3125], Loss: 2.2692, Perplexity: 9.6715
|
| 392 |
+
Epoch 15 Training: 16%|█▌ | 499/3125 [08:18<43:07, 1.01it/s]
|
| 393 |
+
2025-06-10 01:39:42,121 - __main__ - INFO - Epoch [15/18], Step [500/3125], Loss: 2.3727, Perplexity: 10.7258
|
| 394 |
+
Epoch 15 Training: 19%|█▉ | 599/3125 [09:57<41:57, 1.00it/s]
|
| 395 |
+
2025-06-10 01:41:21,548 - __main__ - INFO - Epoch [15/18], Step [600/3125], Loss: 2.3680, Perplexity: 10.6762
|
| 396 |
+
Epoch 15 Training: 22%|██▏ | 699/3125 [11:36<39:54, 1.01it/s]
|
| 397 |
+
2025-06-10 01:43:00,303 - __main__ - INFO - Epoch [15/18], Step [700/3125], Loss: 2.2971, Perplexity: 9.9450
|
| 398 |
+
Epoch 15 Training: 26%|██▌ | 799/3125 [13:15<37:38, 1.03it/s]
|
| 399 |
+
2025-06-10 01:44:39,409 - __main__ - INFO - Epoch [15/18], Step [800/3125], Loss: 2.2048, Perplexity: 9.0680
|
| 400 |
+
Epoch 15 Training: 29%|██▉ | 899/3125 [14:54<36:39, 1.01it/s]
|
| 401 |
+
2025-06-10 01:46:19,040 - __main__ - INFO - Epoch [15/18], Step [900/3125], Loss: 2.6075, Perplexity: 13.5645
|
| 402 |
+
Epoch 15 Training: 32%|███▏ | 999/3125 [16:34<35:14, 1.01it/s]
|
| 403 |
+
2025-06-10 01:47:58,449 - __main__ - INFO - Epoch [15/18], Step [1000/3125], Loss: 2.4252, Perplexity: 11.3049
|
| 404 |
+
Epoch 15 Training: 35%|███▌ | 1099/3125 [18:12<33:25, 1.01it/s]
|
| 405 |
+
2025-06-10 01:49:37,039 - __main__ - INFO - Epoch [15/18], Step [1100/3125], Loss: 2.4678, Perplexity: 11.7969
|
| 406 |
+
Epoch 15 Training: 38%|███▊ | 1199/3125 [19:52<32:01, 1.00it/s]
|
| 407 |
+
2025-06-10 01:51:16,217 - __main__ - INFO - Epoch [15/18], Step [1200/3125], Loss: 2.4770, Perplexity: 11.9052
|
| 408 |
+
Epoch 15 Training: 42%|████▏ | 1299/3125 [21:31<30:05, 1.01it/s]
|
| 409 |
+
2025-06-10 01:52:55,362 - __main__ - INFO - Epoch [15/18], Step [1300/3125], Loss: 2.6406, Perplexity: 14.0220
|
| 410 |
+
Epoch 15 Training: 45%|████▍ | 1399/3125 [23:09<28:14, 1.02it/s]
|
| 411 |
+
2025-06-10 01:54:34,083 - __main__ - INFO - Epoch [15/18], Step [1400/3125], Loss: 2.5408, Perplexity: 12.6903
|
| 412 |
+
Epoch 15 Training: 48%|████▊ | 1499/3125 [24:49<26:55, 1.01it/s]
|
| 413 |
+
2025-06-10 01:56:13,541 - __main__ - INFO - Epoch [15/18], Step [1500/3125], Loss: 2.2871, Perplexity: 9.8462
|
| 414 |
+
Epoch 15 Training: 51%|█████ | 1599/3125 [26:28<25:24, 1.00it/s]
|
| 415 |
+
2025-06-10 01:57:52,988 - __main__ - INFO - Epoch [15/18], Step [1600/3125], Loss: 2.2426, Perplexity: 9.4179
|
| 416 |
+
Epoch 15 Training: 54%|█████▍ | 1699/3125 [28:08<23:48, 1.00s/it]
|
| 417 |
+
2025-06-10 01:59:32,458 - __main__ - INFO - Epoch [15/18], Step [1700/3125], Loss: 2.4471, Perplexity: 11.5546
|
| 418 |
+
Epoch 15 Training: 58%|█████▊ | 1799/3125 [29:47<22:07, 1.00s/it]
|
| 419 |
+
2025-06-10 02:01:11,761 - __main__ - INFO - Epoch [15/18], Step [1800/3125], Loss: 2.2109, Perplexity: 9.1242
|
| 420 |
+
Epoch 15 Training: 61%|██████ | 1899/3125 [31:27<19:57, 1.02it/s]
|
| 421 |
+
2025-06-10 02:02:51,374 - __main__ - INFO - Epoch [15/18], Step [1900/3125], Loss: 2.2128, Perplexity: 9.1415
|
| 422 |
+
Epoch 15 Training: 64%|██████▍ | 1999/3125 [33:06<18:27, 1.02it/s]
|
| 423 |
+
2025-06-10 02:04:30,402 - __main__ - INFO - Epoch [15/18], Step [2000/3125], Loss: 2.4859, Perplexity: 12.0115
|
| 424 |
+
Epoch 15 Training: 67%|██████▋ | 2099/3125 [34:45<16:45, 1.02it/s]
|
| 425 |
+
2025-06-10 02:06:09,201 - __main__ - INFO - Epoch [15/18], Step [2100/3125], Loss: 2.1893, Perplexity: 8.9290
|
| 426 |
+
Epoch 15 Training: 70%|███████ | 2199/3125 [36:24<15:26, 1.00s/it]
|
| 427 |
+
2025-06-10 02:07:48,565 - __main__ - INFO - Epoch [15/18], Step [2200/3125], Loss: 2.3444, Perplexity: 10.4273
|
| 428 |
+
Epoch 15 Training: 74%|███████▎ | 2299/3125 [38:03<13:51, 1.01s/it]
|
| 429 |
+
2025-06-10 02:09:27,850 - __main__ - INFO - Epoch [15/18], Step [2300/3125], Loss: 2.3961, Perplexity: 10.9804
|
| 430 |
+
Epoch 15 Training: 77%|███████▋ | 2399/3125 [39:42<11:59, 1.01it/s]
|
| 431 |
+
2025-06-10 02:11:06,898 - __main__ - INFO - Epoch [15/18], Step [2400/3125], Loss: 2.4591, Perplexity: 11.6937
|
| 432 |
+
Epoch 15 Training: 80%|███████▉ | 2499/3125 [41:22<10:09, 1.03it/s]
|
| 433 |
+
2025-06-10 02:12:46,565 - __main__ - INFO - Epoch [15/18], Step [2500/3125], Loss: 2.3786, Perplexity: 10.7898
|
| 434 |
+
Epoch 15 Training: 83%|████████▎ | 2599/3125 [43:01<08:43, 1.00it/s]
|
| 435 |
+
2025-06-10 02:14:25,999 - __main__ - INFO - Epoch [15/18], Step [2600/3125], Loss: 2.2436, Perplexity: 9.4268
|
| 436 |
+
Epoch 15 Training: 86%|████████▋ | 2699/3125 [44:41<07:04, 1.00it/s]
|
| 437 |
+
2025-06-10 02:16:05,214 - __main__ - INFO - Epoch [15/18], Step [2700/3125], Loss: 2.5708, Perplexity: 13.0756
|
| 438 |
+
Epoch 15 Training: 90%|████████▉ | 2799/3125 [46:20<05:32, 1.02s/it]
|
| 439 |
+
2025-06-10 02:17:44,978 - __main__ - INFO - Epoch [15/18], Step [2800/3125], Loss: 2.3898, Perplexity: 10.9116
|
| 440 |
+
Epoch 15 Training: 93%|█████████▎| 2899/3125 [48:00<03:44, 1.01it/s]
|
| 441 |
+
2025-06-10 02:19:24,486 - __main__ - INFO - Epoch [15/18], Step [2900/3125], Loss: 2.4656, Perplexity: 11.7705
|
| 442 |
+
Epoch 15 Training: 96%|█████████▌| 2999/3125 [49:39<02:03, 1.02it/s]
|
| 443 |
+
2025-06-10 02:21:03,418 - __main__ - INFO - Epoch [15/18], Step [3000/3125], Loss: 2.3119, Perplexity: 10.0933
|
| 444 |
+
Epoch 15 Training: 99%|█████████▉| 3099/3125 [51:18<00:25, 1.02it/s]
|
| 445 |
+
2025-06-10 02:22:42,495 - __main__ - INFO - Epoch [15/18], Step [3100/3125], Loss: 2.3714, Perplexity: 10.7121
|
| 446 |
+
Epoch 15 Training: 100%|██████████| 3125/3125 [51:44<00:00, 1.01it/s]
|
| 447 |
+
2025-06-10 02:23:07,613 - __main__ - INFO - Epoch 15 Training finished. Avg Loss: 2.3624, Time: 3104.49s
|
| 448 |
+
Validation: 100%|██████████| 391/391 [12:00<00:00, 1.84s/it]
|
| 449 |
+
2025-06-10 02:35:07,702 - __main__ - INFO - Validation Avg Loss: 2.5179, Perplexity: 12.4026
|
| 450 |
+
2025-06-10 02:35:17,310 - __main__ - INFO - Validation BLEU-4: 0.1042
|
| 451 |
+
2025-06-10 02:35:17,952 - __main__ - INFO - Saved best model checkpoint to ./output/best_model_bleu0.1042.pth
|
| 452 |
+
2025-06-10 02:35:18,572 - __main__ - INFO - Saved periodic model checkpoint to ./output/model_epoch_15.pth
|
| 453 |
+
2025-06-10 02:35:18,573 - __main__ - INFO - Performing memory optimization after epoch...
|
| 454 |
+
2025-06-10 02:35:18,838 - __main__ - INFO - CUDA cache emptied.
|
| 455 |
+
2025-06-10 02:35:19,180 - __main__ - INFO - Python garbage collector run.
|
| 456 |
+
Epoch 16 Training: 3%|▎ | 99/3125 [01:41<50:16, 1.00it/s]
|
| 457 |
+
2025-06-10 02:37:01,394 - __main__ - INFO - Epoch [16/18], Step [100/3125], Loss: 2.3317, Perplexity: 10.2956
|
| 458 |
+
Epoch 16 Training: 6%|▋ | 199/3125 [03:21<48:24, 1.01it/s]
|
| 459 |
+
2025-06-10 02:38:41,260 - __main__ - INFO - Epoch [16/18], Step [200/3125], Loss: 2.3495, Perplexity: 10.4806
|
| 460 |
+
Epoch 16 Training: 10%|▉ | 299/3125 [05:00<47:30, 1.01s/it]
|
| 461 |
+
2025-06-10 02:40:20,729 - __main__ - INFO - Epoch [16/18], Step [300/3125], Loss: 2.2306, Perplexity: 9.3058
|
| 462 |
+
Epoch 16 Training: 13%|█▎ | 399/3125 [06:40<45:19, 1.00it/s]
|
| 463 |
+
2025-06-10 02:42:00,751 - __main__ - INFO - Epoch [16/18], Step [400/3125], Loss: 2.3325, Perplexity: 10.3034
|
| 464 |
+
Epoch 16 Training: 16%|█▌ | 499/3125 [08:19<43:00, 1.02it/s]
|
| 465 |
+
2025-06-10 02:43:39,918 - __main__ - INFO - Epoch [16/18], Step [500/3125], Loss: 2.1694, Perplexity: 8.7528
|
| 466 |
+
Epoch 16 Training: 19%|█▉ | 599/3125 [09:59<41:21, 1.02it/s]
|
| 467 |
+
2025-06-10 02:45:19,186 - __main__ - INFO - Epoch [16/18], Step [600/3125], Loss: 2.3946, Perplexity: 10.9643
|
| 468 |
+
Epoch 16 Training: 22%|██▏ | 699/3125 [11:38<40:18, 1.00it/s]
|
| 469 |
+
2025-06-10 02:46:58,656 - __main__ - INFO - Epoch [16/18], Step [700/3125], Loss: 2.3674, Perplexity: 10.6700
|
| 470 |
+
Epoch 16 Training: 26%|██▌ | 799/3125 [13:17<38:25, 1.01it/s]
|
| 471 |
+
2025-06-10 02:48:37,469 - __main__ - INFO - Epoch [16/18], Step [800/3125], Loss: 2.0632, Perplexity: 7.8708
|
| 472 |
+
Epoch 16 Training: 29%|██▉ | 899/3125 [14:57<37:35, 1.01s/it]
|
| 473 |
+
2025-06-10 02:50:17,600 - __main__ - INFO - Epoch [16/18], Step [900/3125], Loss: 2.2940, Perplexity: 9.9146
|
| 474 |
+
Epoch 16 Training: 32%|███▏ | 999/3125 [16:37<34:59, 1.01it/s]
|
| 475 |
+
2025-06-10 02:51:57,234 - __main__ - INFO - Epoch [16/18], Step [1000/3125], Loss: 2.2395, Perplexity: 9.3891
|
| 476 |
+
Epoch 16 Training: 35%|███▌ | 1099/3125 [18:16<33:56, 1.01s/it]
|
| 477 |
+
2025-06-10 02:53:37,095 - __main__ - INFO - Epoch [16/18], Step [1100/3125], Loss: 2.4083, Perplexity: 11.1150
|
| 478 |
+
Epoch 16 Training: 38%|███▊ | 1199/3125 [19:56<31:49, 1.01it/s]
|
| 479 |
+
2025-06-10 02:55:16,212 - __main__ - INFO - Epoch [16/18], Step [1200/3125], Loss: 2.3857, Perplexity: 10.8667
|
| 480 |
+
Epoch 16 Training: 42%|████▏ | 1299/3125 [21:35<30:20, 1.00it/s]
|
| 481 |
+
2025-06-10 02:56:55,657 - __main__ - INFO - Epoch [16/18], Step [1300/3125], Loss: 2.3296, Perplexity: 10.2736
|
| 482 |
+
Epoch 16 Training: 45%|████▍ | 1399/3125 [23:15<28:18, 1.02it/s]
|
| 483 |
+
2025-06-10 02:58:35,348 - __main__ - INFO - Epoch [16/18], Step [1400/3125], Loss: 2.1133, Perplexity: 8.2756
|
| 484 |
+
Epoch 16 Training: 48%|████▊ | 1499/3125 [24:54<26:23, 1.03it/s]
|
| 485 |
+
2025-06-10 03:00:14,587 - __main__ - INFO - Epoch [16/18], Step [1500/3125], Loss: 2.3756, Perplexity: 10.7575
|
| 486 |
+
Epoch 16 Training: 51%|█████ | 1599/3125 [26:33<25:10, 1.01it/s]
|
| 487 |
+
2025-06-10 03:01:53,838 - __main__ - INFO - Epoch [16/18], Step [1600/3125], Loss: 2.3544, Perplexity: 10.5314
|
| 488 |
+
Epoch 16 Training: 54%|█████▍ | 1699/3125 [28:13<23:56, 1.01s/it]
|
| 489 |
+
2025-06-10 03:03:33,780 - __main__ - INFO - Epoch [16/18], Step [1700/3125], Loss: 2.3411, Perplexity: 10.3928
|
| 490 |
+
Epoch 16 Training: 58%|█████▊ | 1799/3125 [29:53<22:03, 1.00it/s]
|
| 491 |
+
2025-06-10 03:05:13,555 - __main__ - INFO - Epoch [16/18], Step [1800/3125], Loss: 2.2282, Perplexity: 9.2828
|
| 492 |
+
Epoch 16 Training: 61%|██████ | 1899/3125 [31:33<20:17, 1.01it/s]
|
| 493 |
+
2025-06-10 03:06:53,528 - __main__ - INFO - Epoch [16/18], Step [1900/3125], Loss: 2.3572, Perplexity: 10.5609
|
| 494 |
+
Epoch 16 Training: 64%|██████▍ | 1999/3125 [33:13<18:40, 1.00it/s]
|
| 495 |
+
2025-06-10 03:08:33,299 - __main__ - INFO - Epoch [16/18], Step [2000/3125], Loss: 2.2650, Perplexity: 9.6316
|
| 496 |
+
Epoch 16 Training: 67%|██████▋ | 2099/3125 [34:52<16:49, 1.02it/s]
|
| 497 |
+
2025-06-10 03:10:12,860 - __main__ - INFO - Epoch [16/18], Step [2100/3125], Loss: 2.4694, Perplexity: 11.8158
|
| 498 |
+
Epoch 16 Training: 70%|███████ | 2199/3125 [36:32<15:30, 1.00s/it]
|
| 499 |
+
2025-06-10 03:11:52,351 - __main__ - INFO - Epoch [16/18], Step [2200/3125], Loss: 2.2784, Perplexity: 9.7614
|
| 500 |
+
Epoch 16 Training: 74%|███████▎ | 2299/3125 [38:11<13:41, 1.01it/s]
|
| 501 |
+
2025-06-10 03:13:31,646 - __main__ - INFO - Epoch [16/18], Step [2300/3125], Loss: 2.3814, Perplexity: 10.8201
|
| 502 |
+
Epoch 16 Training: 77%|███████▋ | 2399/3125 [39:51<12:05, 1.00it/s]
|
| 503 |
+
2025-06-10 03:15:11,562 - __main__ - INFO - Epoch [16/18], Step [2400/3125], Loss: 2.3831, Perplexity: 10.8388
|
| 504 |
+
Epoch 16 Training: 80%|███████▉ | 2499/3125 [41:30<10:24, 1.00it/s]
|
| 505 |
+
2025-06-10 03:16:51,094 - __main__ - INFO - Epoch [16/18], Step [2500/3125], Loss: 2.2298, Perplexity: 9.2982
|
| 506 |
+
Epoch 16 Training: 83%|████████▎ | 2599/3125 [43:10<08:46, 1.00s/it]
|
| 507 |
+
2025-06-10 03:18:30,989 - __main__ - INFO - Epoch [16/18], Step [2600/3125], Loss: 2.4608, Perplexity: 11.7146
|
| 508 |
+
Epoch 16 Training: 86%|████████▋ | 2699/3125 [44:50<07:06, 1.00s/it]
|
| 509 |
+
2025-06-10 03:20:10,419 - __main__ - INFO - Epoch [16/18], Step [2700/3125], Loss: 2.4152, Perplexity: 11.1916
|
| 510 |
+
Epoch 16 Training: 90%|████████▉ | 2799/3125 [46:29<05:25, 1.00it/s]
|
| 511 |
+
2025-06-10 03:21:49,872 - __main__ - INFO - Epoch [16/18], Step [2800/3125], Loss: 2.4860, Perplexity: 12.0134
|
| 512 |
+
Epoch 16 Training: 93%|█████████▎| 2899/3125 [48:09<03:41, 1.02it/s]
|
| 513 |
+
2025-06-10 03:23:29,269 - __main__ - INFO - Epoch [16/18], Step [2900/3125], Loss: 2.1620, Perplexity: 8.6885
|
| 514 |
+
Epoch 16 Training: 96%|█████████▌| 2999/3125 [49:48<02:05, 1.01it/s]
|
| 515 |
+
2025-06-10 03:25:09,144 - __main__ - INFO - Epoch [16/18], Step [3000/3125], Loss: 2.6663, Perplexity: 14.3864
|
| 516 |
+
Epoch 16 Training: 99%|█████████▉| 3099/3125 [51:28<00:26, 1.00s/it]
|
| 517 |
+
2025-06-10 03:26:48,695 - __main__ - INFO - Epoch [16/18], Step [3100/3125], Loss: 2.5140, Perplexity: 12.3541
|
| 518 |
+
Epoch 16 Training: 100%|██████████| 3125/3125 [51:54<00:00, 1.00it/s]
|
| 519 |
+
2025-06-10 03:27:14,007 - __main__ - INFO - Epoch 16 Training finished. Avg Loss: 2.3264, Time: 3114.82s
|
| 520 |
+
Validation: 100%|██████████| 391/391 [12:06<00:00, 1.86s/it]
|
| 521 |
+
2025-06-10 03:39:20,377 - __main__ - INFO - Validation Avg Loss: 2.5298, Perplexity: 12.5513
|
| 522 |
+
2025-06-10 03:39:30,111 - __main__ - INFO - Validation BLEU-4: 0.1047
|
| 523 |
+
2025-06-10 03:39:30,777 - __main__ - INFO - Saved best model checkpoint to ./output/best_model_bleu0.1047.pth
|
| 524 |
+
2025-06-10 03:39:30,778 - __main__ - INFO - Performing memory optimization after epoch...
|
| 525 |
+
2025-06-10 03:39:31,073 - __main__ - INFO - CUDA cache emptied.
|
| 526 |
+
2025-06-10 03:39:31,413 - __main__ - INFO - Python garbage collector run.
|
| 527 |
+
Epoch 17 Training: 3%|▎ | 99/3125 [01:41<49:33, 1.02it/s]
|
| 528 |
+
2025-06-10 03:41:13,434 - __main__ - INFO - Epoch [17/18], Step [100/3125], Loss: 2.1717, Perplexity: 8.7730
|
| 529 |
+
Epoch 17 Training: 6%|▋ | 199/3125 [03:20<47:53, 1.02it/s]
|
| 530 |
+
2025-06-10 03:42:52,934 - __main__ - INFO - Epoch [17/18], Step [200/3125], Loss: 2.2953, Perplexity: 9.9273
|
| 531 |
+
Epoch 17 Training: 10%|▉ | 299/3125 [05:00<46:40, 1.01it/s]
|
| 532 |
+
2025-06-10 03:44:32,435 - __main__ - INFO - Epoch [17/18], Step [300/3125], Loss: 2.1929, Perplexity: 8.9608
|
| 533 |
+
Epoch 17 Training: 13%|█▎ | 399/3125 [06:38<44:54, 1.01it/s]
|
| 534 |
+
2025-06-10 03:46:11,321 - __main__ - INFO - Epoch [17/18], Step [400/3125], Loss: 2.1077, Perplexity: 8.2291
|
| 535 |
+
Epoch 17 Training: 16%|█▌ | 499/3125 [08:18<44:24, 1.01s/it]
|
| 536 |
+
2025-06-10 03:47:50,763 - __main__ - INFO - Epoch [17/18], Step [500/3125], Loss: 2.3065, Perplexity: 10.0394
|
| 537 |
+
Epoch 17 Training: 19%|█▉ | 599/3125 [09:57<41:07, 1.02it/s]
|
| 538 |
+
2025-06-10 03:49:29,973 - __main__ - INFO - Epoch [17/18], Step [600/3125], Loss: 2.0144, Perplexity: 7.4962
|
| 539 |
+
Epoch 17 Training: 22%|██▏ | 699/3125 [11:36<40:13, 1.01it/s]
|
| 540 |
+
2025-06-10 03:51:08,910 - __main__ - INFO - Epoch [17/18], Step [700/3125], Loss: 2.4351, Perplexity: 11.4164
|
| 541 |
+
Epoch 17 Training: 26%|██▌ | 799/3125 [13:15<38:10, 1.02it/s]
|
| 542 |
+
2025-06-10 03:52:47,480 - __main__ - INFO - Epoch [17/18], Step [800/3125], Loss: 2.3415, Perplexity: 10.3965
|
| 543 |
+
Epoch 17 Training: 29%|██▉ | 899/3125 [14:54<36:43, 1.01it/s]
|
| 544 |
+
2025-06-10 03:54:26,563 - __main__ - INFO - Epoch [17/18], Step [900/3125], Loss: 2.1439, Perplexity: 8.5324
|
| 545 |
+
Epoch 17 Training: 32%|███▏ | 999/3125 [16:34<36:04, 1.02s/it]
|
| 546 |
+
2025-06-10 03:56:06,565 - __main__ - INFO - Epoch [17/18], Step [1000/3125], Loss: 2.4303, Perplexity: 11.3623
|
| 547 |
+
Epoch 17 Training: 35%|███▌ | 1099/3125 [18:13<33:49, 1.00s/it]
|
| 548 |
+
2025-06-10 03:57:46,160 - __main__ - INFO - Epoch [17/18], Step [1100/3125], Loss: 2.2407, Perplexity: 9.3998
|
| 549 |
+
Epoch 17 Training: 38%|███▊ | 1199/3125 [19:53<31:51, 1.01it/s]
|
| 550 |
+
2025-06-10 03:59:25,975 - __main__ - INFO - Epoch [17/18], Step [1200/3125], Loss: 2.2660, Perplexity: 9.6408
|
| 551 |
+
Epoch 17 Training: 42%|████▏ | 1299/3125 [21:33<30:11, 1.01it/s]
|
| 552 |
+
2025-06-10 04:01:05,823 - __main__ - INFO - Epoch [17/18], Step [1300/3125], Loss: 2.2952, Perplexity: 9.9262
|
| 553 |
+
Epoch 17 Training: 45%|████▍ | 1399/3125 [23:12<28:26, 1.01it/s]
|
| 554 |
+
2025-06-10 04:02:45,094 - __main__ - INFO - Epoch [17/18], Step [1400/3125], Loss: 2.4064, Perplexity: 11.0944
|
| 555 |
+
Epoch 17 Training: 48%|████▊ | 1499/3125 [24:52<27:26, 1.01s/it]
|
| 556 |
+
2025-06-10 04:04:24,506 - __main__ - INFO - Epoch [17/18], Step [1500/3125], Loss: 2.5295, Perplexity: 12.5467
|
| 557 |
+
Epoch 17 Training: 51%|█████ | 1599/3125 [26:31<25:00, 1.02it/s]
|
| 558 |
+
2025-06-10 04:06:03,514 - __main__ - INFO - Epoch [17/18], Step [1600/3125], Loss: 2.1637, Perplexity: 8.7030
|
| 559 |
+
Epoch 17 Training: 54%|█████▍ | 1699/3125 [28:10<23:23, 1.02it/s]
|
| 560 |
+
2025-06-10 04:07:43,189 - __main__ - INFO - Epoch [17/18], Step [1700/3125], Loss: 2.3608, Perplexity: 10.5998
|
| 561 |
+
Epoch 17 Training: 58%|█████▊ | 1799/3125 [29:50<21:51, 1.01it/s]
|
| 562 |
+
2025-06-10 04:09:22,526 - __main__ - INFO - Epoch [17/18], Step [1800/3125], Loss: 2.1197, Perplexity: 8.3285
|
| 563 |
+
Epoch 17 Training: 61%|██████ | 1899/3125 [31:29<20:36, 1.01s/it]
|
| 564 |
+
2025-06-10 04:11:01,558 - __main__ - INFO - Epoch [17/18], Step [1900/3125], Loss: 2.2632, Perplexity: 9.6134
|
| 565 |
+
Epoch 17 Training: 64%|██████▍ | 1999/3125 [33:08<18:50, 1.00s/it]
|
| 566 |
+
2025-06-10 04:12:40,863 - __main__ - INFO - Epoch [17/18], Step [2000/3125], Loss: 2.0741, Perplexity: 7.9572
|
| 567 |
+
Epoch 17 Training: 67%|██████▋ | 2099/3125 [34:47<16:58, 1.01it/s]
|
| 568 |
+
2025-06-10 04:14:20,125 - __main__ - INFO - Epoch [17/18], Step [2100/3125], Loss: 2.2237, Perplexity: 9.2414
|
| 569 |
+
Epoch 17 Training: 70%|███████ | 2199/3125 [36:27<15:12, 1.01it/s]
|
| 570 |
+
2025-06-10 04:15:59,690 - __main__ - INFO - Epoch [17/18], Step [2200/3125], Loss: 2.1895, Perplexity: 8.9311
|
| 571 |
+
Epoch 17 Training: 74%|███████▎ | 2299/3125 [38:06<13:45, 1.00it/s]
|
| 572 |
+
2025-06-10 04:17:39,132 - __main__ - INFO - Epoch [17/18], Step [2300/3125], Loss: 2.3708, Perplexity: 10.7057
|
| 573 |
+
Epoch 17 Training: 77%|███████▋ | 2399/3125 [39:46<11:50, 1.02it/s]
|
| 574 |
+
2025-06-10 04:19:18,650 - __main__ - INFO - Epoch [17/18], Step [2400/3125], Loss: 2.2712, Perplexity: 9.6909
|
| 575 |
+
Epoch 17 Training: 80%|███████▉ | 2499/3125 [41:25<10:20, 1.01it/s]
|
| 576 |
+
2025-06-10 04:20:58,163 - __main__ - INFO - Epoch [17/18], Step [2500/3125], Loss: 2.3275, Perplexity: 10.2521
|
| 577 |
+
Epoch 17 Training: 83%|████████▎ | 2599/3125 [43:04<08:34, 1.02it/s]
|
| 578 |
+
2025-06-10 04:22:37,221 - __main__ - INFO - Epoch [17/18], Step [2600/3125], Loss: 2.1308, Perplexity: 8.4219
|
| 579 |
+
Epoch 17 Training: 86%|████████▋ | 2699/3125 [44:43<06:55, 1.02it/s]
|
| 580 |
+
2025-06-10 04:24:16,203 - __main__ - INFO - Epoch [17/18], Step [2700/3125], Loss: 2.3833, Perplexity: 10.8407
|
| 581 |
+
Epoch 17 Training: 90%|████████▉ | 2799/3125 [46:22<05:26, 1.00s/it]
|
| 582 |
+
2025-06-10 04:25:55,437 - __main__ - INFO - Epoch [17/18], Step [2800/3125], Loss: 2.4461, Perplexity: 11.5430
|
| 583 |
+
Epoch 17 Training: 93%|█████████▎| 2899/3125 [48:02<03:44, 1.01it/s]
|
| 584 |
+
2025-06-10 04:27:34,464 - __main__ - INFO - Epoch [17/18], Step [2900/3125], Loss: 2.0600, Perplexity: 7.8457
|
| 585 |
+
Epoch 17 Training: 96%|█████████▌| 2999/3125 [49:41<02:05, 1.01it/s]
|
| 586 |
+
2025-06-10 04:29:13,778 - __main__ - INFO - Epoch [17/18], Step [3000/3125], Loss: 2.2095, Perplexity: 9.1108
|
| 587 |
+
Epoch 17 Training: 99%|█████████▉| 3099/3125 [51:20<00:26, 1.02s/it]
|
| 588 |
+
2025-06-10 04:30:53,335 - __main__ - INFO - Epoch [17/18], Step [3100/3125], Loss: 2.0986, Perplexity: 8.1547
|
| 589 |
+
Epoch 17 Training: 100%|██████████| 3125/3125 [51:47<00:00, 1.01it/s]
|
| 590 |
+
2025-06-10 04:31:18,469 - __main__ - INFO - Epoch 17 Training finished. Avg Loss: 2.2938, Time: 3107.05s
|
| 591 |
+
Validation: 100%|██████████| 391/391 [11:31<00:00, 1.77s/it]
|
| 592 |
+
2025-06-10 04:42:50,318 - __main__ - INFO - Validation Avg Loss: 2.5300, Perplexity: 12.5540
|
| 593 |
+
2025-06-10 04:42:59,665 - __main__ - INFO - Validation BLEU-4: 0.1040
|
| 594 |
+
2025-06-10 04:42:59,666 - __main__ - INFO - Performing memory optimization after epoch...
|
| 595 |
+
2025-06-10 04:42:59,930 - __main__ - INFO - CUDA cache emptied.
|
| 596 |
+
2025-06-10 04:43:00,260 - __main__ - INFO - Python garbage collector run.
|
| 597 |
+
Epoch 18 Training: 3%|▎ | 99/3125 [01:41<49:15, 1.02it/s]
|
| 598 |
+
2025-06-10 04:44:42,407 - __main__ - INFO - Epoch [18/18], Step [100/3125], Loss: 2.1066, Perplexity: 8.2205
|
| 599 |
+
Epoch 18 Training: 6%|▋ | 199/3125 [03:20<48:12, 1.01it/s]
|
| 600 |
+
2025-06-10 04:46:21,631 - __main__ - INFO - Epoch [18/18], Step [200/3125], Loss: 2.1505, Perplexity: 8.5893
|
| 601 |
+
Epoch 18 Training: 10%|▉ | 299/3125 [04:59<47:55, 1.02s/it]
|
| 602 |
+
2025-06-10 04:48:01,201 - __main__ - INFO - Epoch [18/18], Step [300/3125], Loss: 2.2280, Perplexity: 9.2809
|
| 603 |
+
Epoch 18 Training: 13%|█▎ | 399/3125 [06:39<45:23, 1.00it/s]
|
| 604 |
+
2025-06-10 04:49:40,603 - __main__ - INFO - Epoch [18/18], Step [400/3125], Loss: 2.2427, Perplexity: 9.4188
|
| 605 |
+
Epoch 18 Training: 16%|█▌ | 499/3125 [08:18<43:50, 1.00s/it]
|
| 606 |
+
2025-06-10 04:51:19,865 - __main__ - INFO - Epoch [18/18], Step [500/3125], Loss: 2.2644, Perplexity: 9.6253
|
| 607 |
+
Epoch 18 Training: 19%|█▉ | 599/3125 [09:57<42:00, 1.00it/s]
|
| 608 |
+
2025-06-10 04:52:58,962 - __main__ - INFO - Epoch [18/18], Step [600/3125], Loss: 2.2968, Perplexity: 9.9419
|
| 609 |
+
Epoch 18 Training: 22%|██▏ | 699/3125 [11:37<40:05, 1.01it/s]
|
| 610 |
+
2025-06-10 04:54:38,562 - __main__ - INFO - Epoch [18/18], Step [700/3125], Loss: 2.4407, Perplexity: 11.4816
|
| 611 |
+
Epoch 18 Training: 26%|██▌ | 799/3125 [13:16<38:41, 1.00it/s]
|
| 612 |
+
2025-06-10 04:56:17,798 - __main__ - INFO - Epoch [18/18], Step [800/3125], Loss: 2.3881, Perplexity: 10.8931
|
| 613 |
+
Epoch 18 Training: 29%|██▉ | 899/3125 [14:56<36:14, 1.02it/s]
|
| 614 |
+
2025-06-10 04:57:57,327 - __main__ - INFO - Epoch [18/18], Step [900/3125], Loss: 2.2182, Perplexity: 9.1906
|
| 615 |
+
Epoch 18 Training: 32%|███▏ | 999/3125 [16:34<34:58, 1.01it/s]
|
| 616 |
+
2025-06-10 04:59:35,897 - __main__ - INFO - Epoch [18/18], Step [1000/3125], Loss: 2.3312, Perplexity: 10.2898
|
| 617 |
+
Epoch 18 Training: 35%|███▌ | 1099/3125 [18:13<34:01, 1.01s/it]
|
| 618 |
+
2025-06-10 05:01:14,940 - __main__ - INFO - Epoch [18/18], Step [1100/3125], Loss: 2.0509, Perplexity: 7.7749
|
| 619 |
+
Epoch 18 Training: 38%|███▊ | 1199/3125 [19:53<32:03, 1.00it/s]
|
| 620 |
+
2025-06-10 05:02:54,567 - __main__ - INFO - Epoch [18/18], Step [1200/3125], Loss: 2.3490, Perplexity: 10.4752
|
| 621 |
+
Epoch 18 Training: 42%|████▏ | 1299/3125 [21:32<30:12, 1.01it/s]
|
| 622 |
+
2025-06-10 05:04:33,867 - __main__ - INFO - Epoch [18/18], Step [1300/3125], Loss: 2.2147, Perplexity: 9.1590
|
| 623 |
+
Epoch 18 Training: 45%|████▍ | 1399/3125 [23:12<28:30, 1.01it/s]
|
| 624 |
+
2025-06-10 05:06:13,537 - __main__ - INFO - Epoch [18/18], Step [1400/3125], Loss: 2.3278, Perplexity: 10.2557
|
| 625 |
+
Epoch 18 Training: 48%|████▊ | 1499/3125 [24:51<27:01, 1.00it/s]
|
| 626 |
+
2025-06-10 05:07:52,776 - __main__ - INFO - Epoch [18/18], Step [1500/3125], Loss: 1.9178, Perplexity: 6.8062
|
| 627 |
+
Epoch 18 Training: 51%|█████ | 1599/3125 [26:30<25:01, 1.02it/s]
|
| 628 |
+
2025-06-10 05:09:31,970 - __main__ - INFO - Epoch [18/18], Step [1600/3125], Loss: 2.2685, Perplexity: 9.6654
|
| 629 |
+
Epoch 18 Training: 54%|█████▍ | 1699/3125 [28:10<23:19, 1.02it/s]
|
| 630 |
+
2025-06-10 05:11:11,387 - __main__ - INFO - Epoch [18/18], Step [1700/3125], Loss: 2.2014, Perplexity: 9.0381
|
| 631 |
+
Epoch 18 Training: 58%|█████▊ | 1799/3125 [29:49<21:54, 1.01it/s]
|
| 632 |
+
2025-06-10 05:12:51,080 - __main__ - INFO - Epoch [18/18], Step [1800/3125], Loss: 2.0424, Perplexity: 7.7092
|
| 633 |
+
Epoch 18 Training: 61%|██████ | 1899/3125 [31:29<20:22, 1.00it/s]
|
| 634 |
+
2025-06-10 05:14:30,955 - __main__ - INFO - Epoch [18/18], Step [1900/3125], Loss: 2.3529, Perplexity: 10.5158
|
| 635 |
+
Epoch 18 Training: 64%|██████▍ | 1999/3125 [33:09<19:06, 1.02s/it]
|
| 636 |
+
2025-06-10 05:16:10,452 - __main__ - INFO - Epoch [18/18], Step [2000/3125], Loss: 2.2688, Perplexity: 9.6676
|
| 637 |
+
Epoch 18 Training: 67%|██████▋ | 2099/3125 [34:48<17:13, 1.01s/it]
|
| 638 |
+
2025-06-10 05:17:49,445 - __main__ - INFO - Epoch [18/18], Step [2100/3125], Loss: 2.1891, Perplexity: 8.9270
|
| 639 |
+
Epoch 18 Training: 70%|███████ | 2199/3125 [36:27<15:05, 1.02it/s]
|
| 640 |
+
2025-06-10 05:19:28,304 - __main__ - INFO - Epoch [18/18], Step [2200/3125], Loss: 2.1682, Perplexity: 8.7424
|
| 641 |
+
Epoch 18 Training: 74%|███████▎ | 2299/3125 [38:05<13:34, 1.01it/s]
|
| 642 |
+
2025-06-10 05:21:07,173 - __main__ - INFO - Epoch [18/18], Step [2300/3125], Loss: 2.3965, Perplexity: 10.9842
|
| 643 |
+
Epoch 18 Training: 77%|███████▋ | 2399/3125 [39:45<12:08, 1.00s/it]
|
| 644 |
+
2025-06-10 05:22:46,706 - __main__ - INFO - Epoch [18/18], Step [2400/3125], Loss: 2.2135, Perplexity: 9.1480
|
| 645 |
+
Epoch 18 Training: 80%|███████▉ | 2499/3125 [41:24<10:26, 1.00s/it]
|
| 646 |
+
2025-06-10 05:24:25,673 - __main__ - INFO - Epoch [18/18], Step [2500/3125], Loss: 2.4143, Perplexity: 11.1821
|
| 647 |
+
Epoch 18 Training: 83%|████████▎ | 2599/3125 [43:03<08:40, 1.01it/s]
|
| 648 |
+
2025-06-10 05:26:04,713 - __main__ - INFO - Epoch [18/18], Step [2600/3125], Loss: 2.3422, Perplexity: 10.4039
|
| 649 |
+
Epoch 18 Training: 86%|████████▋ | 2699/3125 [44:42<07:04, 1.00it/s]
|
| 650 |
+
2025-06-10 05:27:44,011 - __main__ - INFO - Epoch [18/18], Step [2700/3125], Loss: 2.2772, Perplexity: 9.7493
|
| 651 |
+
Epoch 18 Training: 90%|████████▉ | 2799/3125 [46:22<05:21, 1.01it/s]
|
| 652 |
+
2025-06-10 05:29:23,479 - __main__ - INFO - Epoch [18/18], Step [2800/3125], Loss: 2.3167, Perplexity: 10.1422
|
| 653 |
+
Epoch 18 Training: 93%|█████████▎| 2899/3125 [48:01<03:48, 1.01s/it]
|
| 654 |
+
2025-06-10 05:31:02,917 - __main__ - INFO - Epoch [18/18], Step [2900/3125], Loss: 2.3364, Perplexity: 10.3438
|
| 655 |
+
Epoch 18 Training: 96%|█████████▌| 2999/3125 [49:40<02:03, 1.02it/s]
|
| 656 |
+
2025-06-10 05:32:41,879 - __main__ - INFO - Epoch [18/18], Step [3000/3125], Loss: 2.0664, Perplexity: 7.8962
|
| 657 |
+
Epoch 18 Training: 99%|█████████▉| 3099/3125 [51:19<00:25, 1.02it/s]
|
| 658 |
+
2025-06-10 05:34:20,694 - __main__ - INFO - Epoch [18/18], Step [3100/3125], Loss: 2.2455, Perplexity: 9.4448
|
| 659 |
+
Epoch 18 Training: 100%|██████████| 3125/3125 [51:45<00:00, 1.01it/s]
|
| 660 |
+
2025-06-10 05:34:45,854 - __main__ - INFO - Epoch 18 Training finished. Avg Loss: 2.2637, Time: 3105.59s
|
| 661 |
+
Validation: 100%|██████████| 391/391 [11:38<00:00, 1.79s/it]
|
| 662 |
+
2025-06-10 05:46:23,861 - __main__ - INFO - Validation Avg Loss: 2.5381, Perplexity: 12.6555
|
| 663 |
+
2025-06-10 05:46:33,271 - __main__ - INFO - Validation BLEU-4: 0.1029
|
| 664 |
+
2025-06-10 05:46:33,272 - __main__ - INFO - Performing memory optimization after epoch...
|
| 665 |
+
2025-06-10 05:46:33,546 - __main__ - INFO - CUDA cache emptied.
|
| 666 |
+
2025-06-10 05:46:33,877 - __main__ - INFO - Python garbage collector run.
|
| 667 |
+
2025-06-10 05:46:33,878 - __main__ - INFO - Training complete.
|
| 668 |
+
2025-06-10 05:46:33,879 - __main__ - INFO - Model Training Complete!
|
text_files/training_log_21_30.txt
ADDED
|
@@ -0,0 +1,734 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
2025-06-10 20:53:19,604 - __main__ - INFO - Previous notebook output found at: /kaggle/input/part-4-28-36/output. Copying to ./output...
|
| 2 |
+
2025-06-10 20:55:03,275 - __main__ - INFO - Previous output copied successfully to current working directory for resumption.
|
| 3 |
+
2025-06-10 20:55:03,276 - __main__ - INFO -
|
| 4 |
+
--- Starting Model Training ---
|
| 5 |
+
2025-06-10 20:55:03,277 - __main__ - INFO - Starting training process...
|
| 6 |
+
2025-06-10 20:55:03,277 - __main__ - INFO - Using device: cuda
|
| 7 |
+
2025-06-10 20:55:03,284 - __main__ - WARNING - Vocabulary source not found at /kaggle/input/vocabulary_s/pytorch/default/1/vocabulary.pkl. Will build new vocabulary.
|
| 8 |
+
2025-06-10 20:55:03,285 - __main__ - INFO - Building new vocabulary from training dataset...
|
| 9 |
+
2025-06-10 20:55:04,299 - __main__ - INFO - Successfully loaded captions from /kaggle/input/coco-2017-dataset/coco2017/annotations/captions_train2017.json
|
| 10 |
+
Processing annotations: 100%|██████████| 591753/591753 [05:24<00:00, 1824.55it/s]
|
| 11 |
+
2025-06-10 21:00:28,664 - __main__ - INFO - Dataset size after filtering: 591753 samples.
|
| 12 |
+
2025-06-10 21:00:28,711 - __main__ - INFO - Building vocabulary...
|
| 13 |
+
Counting word frequencies: 100%|██████████| 591753/591753 [00:01<00:00, 318528.75it/s]
|
| 14 |
+
2025-06-10 21:00:30,590 - __main__ - INFO - Vocabulary size: 14030
|
| 15 |
+
2025-06-10 21:00:30,741 - __main__ - INFO - New vocabulary built.
|
| 16 |
+
2025-06-10 21:00:30,755 - __main__ - INFO - Saved newly built vocabulary to ./output/vocabulary.pkl
|
| 17 |
+
2025-06-10 21:00:31,712 - __main__ - INFO - Successfully loaded captions from /kaggle/input/coco-2017-dataset/coco2017/annotations/captions_train2017.json
|
| 18 |
+
Processing annotations: 100%|██████████| 591753/591753 [03:24<00:00, 2887.41it/s]
|
| 19 |
+
2025-06-10 21:03:56,848 - __main__ - INFO - Using subset of 200000 samples for the dataset.
|
| 20 |
+
2025-06-10 21:03:56,848 - __main__ - INFO - Dataset size after filtering: 200000 samples.
|
| 21 |
+
2025-06-10 21:03:56,937 - __main__ - INFO - Successfully loaded captions from /kaggle/input/coco-2017-dataset/coco2017/annotations/captions_val2017.json
|
| 22 |
+
Processing annotations: 100%|██████████| 25014/25014 [00:15<00:00, 1607.29it/s]
|
| 23 |
+
2025-06-10 21:04:12,505 - __main__ - INFO - Dataset size after filtering: 25014 samples.
|
| 24 |
+
2025-06-10 21:04:12,506 - __main__ - INFO - Training dataset size: 200000
|
| 25 |
+
2025-06-10 21:04:12,507 - __main__ - INFO - Validation dataset size: 25014
|
| 26 |
+
Downloading: "https://download.pytorch.org/models/resnet50-11ad3fa6.pth" to /root/.cache/torch/hub/checkpoints/resnet50-11ad3fa6.pth
|
| 27 |
+
100%|██████████| 97.8M/97.8M [00:00<00:00, 201MB/s]
|
| 28 |
+
2025-06-10 21:04:13,819 - __main__ - INFO - ResNet encoder base layers are fine-tuning enabled.
|
| 29 |
+
2025-06-10 21:04:14,310 - __main__ - INFO - Attempting to resume training from: ./output/best_model_bleu0.1058.pth
|
| 30 |
+
2025-06-10 21:04:14,909 - __main__ - INFO - Resumed training from epoch 20. Best validation score so far: 0.1058
|
| 31 |
+
Epoch 21 Training: 3%|▎ | 99/3125 [01:41<51:35, 1.02s/it]
|
| 32 |
+
2025-06-10 21:05:56,977 - __main__ - INFO - Epoch [21/30], Step [100/3125], Loss: 2.4415, Perplexity: 11.4905
|
| 33 |
+
Epoch 21 Training: 6%|▋ | 199/3125 [03:27<51:39, 1.06s/it]
|
| 34 |
+
2025-06-10 21:07:43,080 - __main__ - INFO - Epoch [21/30], Step [200/3125], Loss: 2.4132, Perplexity: 11.1694
|
| 35 |
+
Epoch 21 Training: 10%|▉ | 299/3125 [05:13<50:24, 1.07s/it]
|
| 36 |
+
2025-06-10 21:09:29,550 - __main__ - INFO - Epoch [21/30], Step [300/3125], Loss: 2.5896, Perplexity: 13.3244
|
| 37 |
+
Epoch 21 Training: 13%|█▎ | 399/3125 [06:59<48:25, 1.07s/it]
|
| 38 |
+
2025-06-10 21:11:15,424 - __main__ - INFO - Epoch [21/30], Step [400/3125], Loss: 2.4345, Perplexity: 11.4096
|
| 39 |
+
Epoch 21 Training: 16%|█▌ | 499/3125 [08:45<45:43, 1.04s/it]
|
| 40 |
+
2025-06-10 21:13:01,920 - __main__ - INFO - Epoch [21/30], Step [500/3125], Loss: 2.4611, Perplexity: 11.7174
|
| 41 |
+
Epoch 21 Training: 19%|█▉ | 599/3125 [10:32<44:58, 1.07s/it]
|
| 42 |
+
2025-06-10 21:14:48,141 - __main__ - INFO - Epoch [21/30], Step [600/3125], Loss: 2.7550, Perplexity: 15.7210
|
| 43 |
+
Epoch 21 Training: 22%|██▏ | 699/3125 [12:18<42:27, 1.05s/it]
|
| 44 |
+
2025-06-10 21:16:33,948 - __main__ - INFO - Epoch [21/30], Step [700/3125], Loss: 2.3508, Perplexity: 10.4938
|
| 45 |
+
Epoch 21 Training: 26%|██▌ | 799/3125 [14:03<40:56, 1.06s/it]
|
| 46 |
+
2025-06-10 21:18:19,911 - __main__ - INFO - Epoch [21/30], Step [800/3125], Loss: 2.5791, Perplexity: 13.1847
|
| 47 |
+
Epoch 21 Training: 29%|██▉ | 899/3125 [15:50<39:04, 1.05s/it]
|
| 48 |
+
2025-06-10 21:20:06,147 - __main__ - INFO - Epoch [21/30], Step [900/3125], Loss: 2.2819, Perplexity: 9.7949
|
| 49 |
+
Epoch 21 Training: 32%|███▏ | 999/3125 [17:36<37:53, 1.07s/it]
|
| 50 |
+
2025-06-10 21:21:52,490 - __main__ - INFO - Epoch [21/30], Step [1000/3125], Loss: 2.4685, Perplexity: 11.8042
|
| 51 |
+
Epoch 21 Training: 35%|███▌ | 1099/3125 [19:22<36:05, 1.07s/it]
|
| 52 |
+
2025-06-10 21:23:38,264 - __main__ - INFO - Epoch [21/30], Step [1100/3125], Loss: 2.5896, Perplexity: 13.3245
|
| 53 |
+
Epoch 21 Training: 38%|███▊ | 1199/3125 [21:08<33:27, 1.04s/it]
|
| 54 |
+
2025-06-10 21:25:24,152 - __main__ - INFO - Epoch [21/30], Step [1200/3125], Loss: 2.2209, Perplexity: 9.2160
|
| 55 |
+
Epoch 21 Training: 42%|████▏ | 1299/3125 [22:54<32:42, 1.08s/it]
|
| 56 |
+
2025-06-10 21:27:10,347 - __main__ - INFO - Epoch [21/30], Step [1300/3125], Loss: 2.5391, Perplexity: 12.6681
|
| 57 |
+
Epoch 21 Training: 45%|████▍ | 1399/3125 [24:40<30:37, 1.06s/it]
|
| 58 |
+
2025-06-10 21:28:56,226 - __main__ - INFO - Epoch [21/30], Step [1400/3125], Loss: 2.5600, Perplexity: 12.9352
|
| 59 |
+
Epoch 21 Training: 48%|████▊ | 1499/3125 [26:26<28:51, 1.06s/it]
|
| 60 |
+
2025-06-10 21:30:42,131 - __main__ - INFO - Epoch [21/30], Step [1500/3125], Loss: 2.4823, Perplexity: 11.9683
|
| 61 |
+
Epoch 21 Training: 51%|█████ | 1599/3125 [28:12<26:58, 1.06s/it]
|
| 62 |
+
2025-06-10 21:32:28,501 - __main__ - INFO - Epoch [21/30], Step [1600/3125], Loss: 2.6207, Perplexity: 13.7450
|
| 63 |
+
Epoch 21 Training: 54%|█████▍ | 1699/3125 [29:57<24:43, 1.04s/it]
|
| 64 |
+
2025-06-10 21:34:13,930 - __main__ - INFO - Epoch [21/30], Step [1700/3125], Loss: 2.2406, Perplexity: 9.3989
|
| 65 |
+
Epoch 21 Training: 58%|█████▊ | 1799/3125 [31:43<23:20, 1.06s/it]
|
| 66 |
+
2025-06-10 21:35:59,951 - __main__ - INFO - Epoch [21/30], Step [1800/3125], Loss: 2.4947, Perplexity: 12.1177
|
| 67 |
+
Epoch 21 Training: 61%|██████ | 1899/3125 [33:30<21:38, 1.06s/it]
|
| 68 |
+
2025-06-10 21:37:46,093 - __main__ - INFO - Epoch [21/30], Step [1900/3125], Loss: 2.3141, Perplexity: 10.1161
|
| 69 |
+
Epoch 21 Training: 64%|██████▍ | 1999/3125 [35:16<19:59, 1.07s/it]
|
| 70 |
+
2025-06-10 21:39:32,258 - __main__ - INFO - Epoch [21/30], Step [2000/3125], Loss: 2.0813, Perplexity: 8.0148
|
| 71 |
+
Epoch 21 Training: 67%|██████▋ | 2099/3125 [37:02<17:52, 1.05s/it]
|
| 72 |
+
2025-06-10 21:41:18,231 - __main__ - INFO - Epoch [21/30], Step [2100/3125], Loss: 2.5372, Perplexity: 12.6438
|
| 73 |
+
Epoch 21 Training: 70%|███████ | 2199/3125 [38:47<16:14, 1.05s/it]
|
| 74 |
+
2025-06-10 21:43:03,869 - __main__ - INFO - Epoch [21/30], Step [2200/3125], Loss: 2.4665, Perplexity: 11.7807
|
| 75 |
+
Epoch 21 Training: 74%|███████▎ | 2299/3125 [40:34<14:31, 1.06s/it]
|
| 76 |
+
2025-06-10 21:44:50,121 - __main__ - INFO - Epoch [21/30], Step [2300/3125], Loss: 2.4530, Perplexity: 11.6234
|
| 77 |
+
Epoch 21 Training: 77%|███████▋ | 2399/3125 [42:20<12:34, 1.04s/it]
|
| 78 |
+
2025-06-10 21:46:36,332 - __main__ - INFO - Epoch [21/30], Step [2400/3125], Loss: 2.5520, Perplexity: 12.8323
|
| 79 |
+
Epoch 21 Training: 80%|███████▉ | 2499/3125 [44:06<11:06, 1.06s/it]
|
| 80 |
+
2025-06-10 21:48:22,862 - __main__ - INFO - Epoch [21/30], Step [2500/3125], Loss: 2.2327, Perplexity: 9.3254
|
| 81 |
+
Epoch 21 Training: 83%|████████▎ | 2599/3125 [45:52<09:27, 1.08s/it]
|
| 82 |
+
2025-06-10 21:50:08,942 - __main__ - INFO - Epoch [21/30], Step [2600/3125], Loss: 2.3985, Perplexity: 11.0071
|
| 83 |
+
Epoch 21 Training: 86%|████████▋ | 2699/3125 [47:39<07:34, 1.07s/it]
|
| 84 |
+
2025-06-10 21:51:55,620 - __main__ - INFO - Epoch [21/30], Step [2700/3125], Loss: 2.4432, Perplexity: 11.5094
|
| 85 |
+
Epoch 21 Training: 90%|████████▉ | 2799/3125 [49:25<05:41, 1.05s/it]
|
| 86 |
+
2025-06-10 21:53:41,636 - __main__ - INFO - Epoch [21/30], Step [2800/3125], Loss: 2.5233, Perplexity: 12.4703
|
| 87 |
+
Epoch 21 Training: 93%|█████████▎| 2899/3125 [51:11<03:52, 1.03s/it]
|
| 88 |
+
2025-06-10 21:55:27,338 - __main__ - INFO - Epoch [21/30], Step [2900/3125], Loss: 2.4090, Perplexity: 11.1229
|
| 89 |
+
Epoch 21 Training: 96%|█████████▌| 2999/3125 [52:57<02:13, 1.06s/it]
|
| 90 |
+
2025-06-10 21:57:13,693 - __main__ - INFO - Epoch [21/30], Step [3000/3125], Loss: 2.3775, Perplexity: 10.7784
|
| 91 |
+
Epoch 21 Training: 99%|█████████▉| 3099/3125 [54:44<00:28, 1.09s/it]
|
| 92 |
+
2025-06-10 21:59:00,426 - __main__ - INFO - Epoch [21/30], Step [3100/3125], Loss: 2.3746, Perplexity: 10.7470
|
| 93 |
+
Epoch 21 Training: 100%|██████████| 3125/3125 [55:12<00:00, 1.06s/it]
|
| 94 |
+
2025-06-10 21:59:27,122 - __main__ - INFO - Epoch 21 Training finished. Avg Loss: 2.4583, Time: 3312.21s
|
| 95 |
+
Validation: 100%|██████████| 391/391 [12:09<00:00, 1.86s/it]
|
| 96 |
+
2025-06-10 22:11:36,158 - __main__ - INFO - Validation Avg Loss: 2.4595, Perplexity: 11.6989
|
| 97 |
+
2025-06-10 22:11:50,870 - __main__ - INFO - Validation BLEU-4: 0.1050
|
| 98 |
+
2025-06-10 22:11:50,871 - __main__ - INFO - Performing memory optimization after epoch...
|
| 99 |
+
2025-06-10 22:11:51,146 - __main__ - INFO - CUDA cache emptied.
|
| 100 |
+
2025-06-10 22:11:51,395 - __main__ - INFO - Python garbage collector run.
|
| 101 |
+
Epoch 22 Training: 3%|▎ | 99/3125 [01:49<54:20, 1.08s/it]
|
| 102 |
+
2025-06-10 22:13:41,608 - __main__ - INFO - Epoch [22/30], Step [100/3125], Loss: 2.3862, Perplexity: 10.8717
|
| 103 |
+
Epoch 22 Training: 6%|▋ | 199/3125 [03:35<51:35, 1.06s/it]
|
| 104 |
+
2025-06-10 22:15:27,731 - __main__ - INFO - Epoch [22/30], Step [200/3125], Loss: 2.5702, Perplexity: 13.0690
|
| 105 |
+
Epoch 22 Training: 10%|▉ | 299/3125 [05:22<50:17, 1.07s/it]
|
| 106 |
+
2025-06-10 22:17:14,467 - __main__ - INFO - Epoch [22/30], Step [300/3125], Loss: 2.2531, Perplexity: 9.5168
|
| 107 |
+
Epoch 22 Training: 13%|█▎ | 399/3125 [07:08<47:40, 1.05s/it]
|
| 108 |
+
2025-06-10 22:19:00,484 - __main__ - INFO - Epoch [22/30], Step [400/3125], Loss: 2.4486, Perplexity: 11.5717
|
| 109 |
+
Epoch 22 Training: 16%|█▌ | 499/3125 [08:54<46:05, 1.05s/it]
|
| 110 |
+
2025-06-10 22:20:46,614 - __main__ - INFO - Epoch [22/30], Step [500/3125], Loss: 2.4738, Perplexity: 11.8676
|
| 111 |
+
Epoch 22 Training: 19%|█▉ | 599/3125 [10:40<43:56, 1.04s/it]
|
| 112 |
+
2025-06-10 22:22:32,689 - __main__ - INFO - Epoch [22/30], Step [600/3125], Loss: 2.2134, Perplexity: 9.1471
|
| 113 |
+
Epoch 22 Training: 22%|██▏ | 699/3125 [12:26<42:46, 1.06s/it]
|
| 114 |
+
2025-06-10 22:24:19,210 - __main__ - INFO - Epoch [22/30], Step [700/3125], Loss: 2.5602, Perplexity: 12.9386
|
| 115 |
+
Epoch 22 Training: 26%|██▌ | 799/3125 [14:13<41:00, 1.06s/it]
|
| 116 |
+
2025-06-10 22:26:05,595 - __main__ - INFO - Epoch [22/30], Step [800/3125], Loss: 2.2362, Perplexity: 9.3575
|
| 117 |
+
Epoch 22 Training: 29%|██▉ | 899/3125 [15:59<39:51, 1.07s/it]
|
| 118 |
+
2025-06-10 22:27:51,583 - __main__ - INFO - Epoch [22/30], Step [900/3125], Loss: 2.5474, Perplexity: 12.7736
|
| 119 |
+
Epoch 22 Training: 32%|███▏ | 999/3125 [17:45<37:09, 1.05s/it]
|
| 120 |
+
2025-06-10 22:29:37,511 - __main__ - INFO - Epoch [22/30], Step [1000/3125], Loss: 2.0833, Perplexity: 8.0311
|
| 121 |
+
Epoch 22 Training: 35%|███▌ | 1099/3125 [19:31<36:00, 1.07s/it]
|
| 122 |
+
2025-06-10 22:31:23,818 - __main__ - INFO - Epoch [22/30], Step [1100/3125], Loss: 2.2881, Perplexity: 9.8567
|
| 123 |
+
Epoch 22 Training: 38%|███▊ | 1199/3125 [21:17<33:42, 1.05s/it]
|
| 124 |
+
2025-06-10 22:33:10,029 - __main__ - INFO - Epoch [22/30], Step [1200/3125], Loss: 2.4615, Perplexity: 11.7227
|
| 125 |
+
Epoch 22 Training: 42%|████▏ | 1299/3125 [23:04<32:16, 1.06s/it]
|
| 126 |
+
2025-06-10 22:34:56,481 - __main__ - INFO - Epoch [22/30], Step [1300/3125], Loss: 2.2817, Perplexity: 9.7936
|
| 127 |
+
Epoch 22 Training: 45%|████▍ | 1399/3125 [24:49<30:29, 1.06s/it]
|
| 128 |
+
2025-06-10 22:36:42,421 - __main__ - INFO - Epoch [22/30], Step [1400/3125], Loss: 2.5625, Perplexity: 12.9683
|
| 129 |
+
Epoch 22 Training: 48%|████▊ | 1499/3125 [26:35<28:07, 1.04s/it]
|
| 130 |
+
2025-06-10 22:38:28,339 - __main__ - INFO - Epoch [22/30], Step [1500/3125], Loss: 2.1516, Perplexity: 8.5990
|
| 131 |
+
Epoch 22 Training: 51%|█████ | 1599/3125 [28:21<27:05, 1.07s/it]
|
| 132 |
+
2025-06-10 22:40:14,168 - __main__ - INFO - Epoch [22/30], Step [1600/3125], Loss: 2.4977, Perplexity: 12.1545
|
| 133 |
+
Epoch 22 Training: 54%|█████▍ | 1699/3125 [30:08<25:18, 1.06s/it]
|
| 134 |
+
2025-06-10 22:42:00,685 - __main__ - INFO - Epoch [22/30], Step [1700/3125], Loss: 2.2119, Perplexity: 9.1334
|
| 135 |
+
Epoch 22 Training: 58%|█████▊ | 1799/3125 [31:54<23:35, 1.07s/it]
|
| 136 |
+
2025-06-10 22:43:47,004 - __main__ - INFO - Epoch [22/30], Step [1800/3125], Loss: 2.2168, Perplexity: 9.1775
|
| 137 |
+
Epoch 22 Training: 61%|██████ | 1899/3125 [33:41<21:24, 1.05s/it]
|
| 138 |
+
2025-06-10 22:45:34,017 - __main__ - INFO - Epoch [22/30], Step [1900/3125], Loss: 2.4493, Perplexity: 11.5805
|
| 139 |
+
Epoch 22 Training: 64%|██████▍ | 1999/3125 [35:27<19:42, 1.05s/it]
|
| 140 |
+
2025-06-10 22:47:19,916 - __main__ - INFO - Epoch [22/30], Step [2000/3125], Loss: 2.5140, Perplexity: 12.3543
|
| 141 |
+
Epoch 22 Training: 67%|██████▋ | 2099/3125 [37:13<18:13, 1.07s/it]
|
| 142 |
+
2025-06-10 22:49:06,385 - __main__ - INFO - Epoch [22/30], Step [2100/3125], Loss: 2.2537, Perplexity: 9.5231
|
| 143 |
+
Epoch 22 Training: 70%|███████ | 2199/3125 [39:00<16:35, 1.08s/it]
|
| 144 |
+
2025-06-10 22:50:53,063 - __main__ - INFO - Epoch [22/30], Step [2200/3125], Loss: 2.3459, Perplexity: 10.4427
|
| 145 |
+
Epoch 22 Training: 74%|███████▎ | 2299/3125 [40:46<14:28, 1.05s/it]
|
| 146 |
+
2025-06-10 22:52:39,062 - __main__ - INFO - Epoch [22/30], Step [2300/3125], Loss: 2.2346, Perplexity: 9.3426
|
| 147 |
+
Epoch 22 Training: 77%|███████▋ | 2399/3125 [42:33<12:48, 1.06s/it]
|
| 148 |
+
2025-06-10 22:54:25,721 - __main__ - INFO - Epoch [22/30], Step [2400/3125], Loss: 2.4777, Perplexity: 11.9139
|
| 149 |
+
Epoch 22 Training: 80%|███████▉ | 2499/3125 [44:19<11:06, 1.07s/it]
|
| 150 |
+
2025-06-10 22:56:12,322 - __main__ - INFO - Epoch [22/30], Step [2500/3125], Loss: 2.3603, Perplexity: 10.5946
|
| 151 |
+
Epoch 22 Training: 83%|████████▎ | 2599/3125 [46:05<09:17, 1.06s/it]
|
| 152 |
+
2025-06-10 22:57:57,889 - __main__ - INFO - Epoch [22/30], Step [2600/3125], Loss: 2.3461, Perplexity: 10.4452
|
| 153 |
+
Epoch 22 Training: 86%|████████▋ | 2699/3125 [47:51<07:28, 1.05s/it]
|
| 154 |
+
2025-06-10 22:59:44,171 - __main__ - INFO - Epoch [22/30], Step [2700/3125], Loss: 2.3966, Perplexity: 10.9861
|
| 155 |
+
Epoch 22 Training: 90%|████████▉ | 2799/3125 [49:37<05:44, 1.06s/it]
|
| 156 |
+
2025-06-10 23:01:30,177 - __main__ - INFO - Epoch [22/30], Step [2800/3125], Loss: 2.4276, Perplexity: 11.3319
|
| 157 |
+
Epoch 22 Training: 93%|█████████▎| 2899/3125 [51:24<03:57, 1.05s/it]
|
| 158 |
+
2025-06-10 23:03:16,879 - __main__ - INFO - Epoch [22/30], Step [2900/3125], Loss: 2.3832, Perplexity: 10.8394
|
| 159 |
+
Epoch 22 Training: 96%|█████████▌| 2999/3125 [53:10<02:13, 1.06s/it]
|
| 160 |
+
2025-06-10 23:05:02,687 - __main__ - INFO - Epoch [22/30], Step [3000/3125], Loss: 2.3673, Perplexity: 10.6688
|
| 161 |
+
Epoch 22 Training: 99%|█████████▉| 3099/3125 [54:56<00:27, 1.08s/it]
|
| 162 |
+
2025-06-10 23:06:49,083 - __main__ - INFO - Epoch [22/30], Step [3100/3125], Loss: 2.2368, Perplexity: 9.3634
|
| 163 |
+
Epoch 22 Training: 100%|██████████| 3125/3125 [55:24<00:00, 1.06s/it]
|
| 164 |
+
2025-06-10 23:07:15,758 - __main__ - INFO - Epoch 22 Training finished. Avg Loss: 2.3948, Time: 3324.36s
|
| 165 |
+
Validation: 100%|██████████| 391/391 [11:56<00:00, 1.83s/it]
|
| 166 |
+
2025-06-10 23:19:12,047 - __main__ - INFO - Validation Avg Loss: 2.4655, Perplexity: 11.7698
|
| 167 |
+
2025-06-10 23:19:22,587 - __main__ - INFO - Validation BLEU-4: 0.1049
|
| 168 |
+
2025-06-10 23:19:22,588 - __main__ - INFO - Performing memory optimization after epoch...
|
| 169 |
+
2025-06-10 23:19:22,860 - __main__ - INFO - CUDA cache emptied.
|
| 170 |
+
2025-06-10 23:19:23,252 - __main__ - INFO - Python garbage collector run.
|
| 171 |
+
Epoch 23 Training: 3%|▎ | 99/3125 [01:49<54:15, 1.08s/it]
|
| 172 |
+
2025-06-10 23:21:13,874 - __main__ - INFO - Epoch [23/30], Step [100/3125], Loss: 2.2665, Perplexity: 9.6457
|
| 173 |
+
Epoch 23 Training: 6%|▋ | 199/3125 [03:35<51:49, 1.06s/it]
|
| 174 |
+
2025-06-10 23:23:00,151 - __main__ - INFO - Epoch [23/30], Step [200/3125], Loss: 2.1517, Perplexity: 8.5996
|
| 175 |
+
Epoch 23 Training: 10%|▉ | 299/3125 [05:22<49:46, 1.06s/it]
|
| 176 |
+
2025-06-10 23:24:46,702 - __main__ - INFO - Epoch [23/30], Step [300/3125], Loss: 2.2574, Perplexity: 9.5578
|
| 177 |
+
Epoch 23 Training: 13%|█▎ | 399/3125 [07:07<47:28, 1.04s/it]
|
| 178 |
+
2025-06-10 23:26:32,323 - __main__ - INFO - Epoch [23/30], Step [400/3125], Loss: 2.5305, Perplexity: 12.5602
|
| 179 |
+
Epoch 23 Training: 16%|█▌ | 499/3125 [08:54<47:09, 1.08s/it]
|
| 180 |
+
2025-06-10 23:28:18,691 - __main__ - INFO - Epoch [23/30], Step [500/3125], Loss: 2.4340, Perplexity: 11.4045
|
| 181 |
+
Epoch 23 Training: 19%|█▉ | 599/3125 [10:40<44:49, 1.06s/it]
|
| 182 |
+
2025-06-10 23:30:05,103 - __main__ - INFO - Epoch [23/30], Step [600/3125], Loss: 2.1875, Perplexity: 8.9125
|
| 183 |
+
Epoch 23 Training: 22%|██▏ | 699/3125 [12:27<42:33, 1.05s/it]
|
| 184 |
+
2025-06-10 23:31:51,337 - __main__ - INFO - Epoch [23/30], Step [700/3125], Loss: 2.1650, Perplexity: 8.7143
|
| 185 |
+
Epoch 23 Training: 26%|██▌ | 799/3125 [14:12<41:21, 1.07s/it]
|
| 186 |
+
2025-06-10 23:33:37,200 - __main__ - INFO - Epoch [23/30], Step [800/3125], Loss: 2.2312, Perplexity: 9.3107
|
| 187 |
+
Epoch 23 Training: 29%|██▉ | 899/3125 [15:58<38:33, 1.04s/it]
|
| 188 |
+
2025-06-10 23:35:23,133 - __main__ - INFO - Epoch [23/30], Step [900/3125], Loss: 2.3446, Perplexity: 10.4295
|
| 189 |
+
Epoch 23 Training: 32%|███▏ | 999/3125 [17:45<38:01, 1.07s/it]
|
| 190 |
+
2025-06-10 23:37:09,905 - __main__ - INFO - Epoch [23/30], Step [1000/3125], Loss: 2.4275, Perplexity: 11.3308
|
| 191 |
+
Epoch 23 Training: 35%|███▌ | 1099/3125 [19:31<35:55, 1.06s/it]
|
| 192 |
+
2025-06-10 23:38:56,155 - __main__ - INFO - Epoch [23/30], Step [1100/3125], Loss: 2.3552, Perplexity: 10.5405
|
| 193 |
+
Epoch 23 Training: 38%|███▊ | 1199/3125 [21:17<34:35, 1.08s/it]
|
| 194 |
+
2025-06-10 23:40:42,156 - __main__ - INFO - Epoch [23/30], Step [1200/3125], Loss: 2.3776, Perplexity: 10.7791
|
| 195 |
+
Epoch 23 Training: 42%|████▏ | 1299/3125 [23:04<32:11, 1.06s/it]
|
| 196 |
+
2025-06-10 23:42:28,873 - __main__ - INFO - Epoch [23/30], Step [1300/3125], Loss: 2.4015, Perplexity: 11.0394
|
| 197 |
+
Epoch 23 Training: 45%|████▍ | 1399/3125 [24:51<31:06, 1.08s/it]
|
| 198 |
+
2025-06-10 23:44:15,643 - __main__ - INFO - Epoch [23/30], Step [1400/3125], Loss: 2.4753, Perplexity: 11.8853
|
| 199 |
+
Epoch 23 Training: 48%|████▊ | 1499/3125 [26:38<29:06, 1.07s/it]
|
| 200 |
+
2025-06-10 23:46:02,436 - __main__ - INFO - Epoch [23/30], Step [1500/3125], Loss: 2.4314, Perplexity: 11.3750
|
| 201 |
+
Epoch 23 Training: 51%|█████ | 1599/3125 [28:24<27:09, 1.07s/it]
|
| 202 |
+
2025-06-10 23:47:48,633 - __main__ - INFO - Epoch [23/30], Step [1600/3125], Loss: 2.2185, Perplexity: 9.1938
|
| 203 |
+
Epoch 23 Training: 54%|█████▍ | 1699/3125 [30:11<25:15, 1.06s/it]
|
| 204 |
+
2025-06-10 23:49:35,393 - __main__ - INFO - Epoch [23/30], Step [1700/3125], Loss: 2.2120, Perplexity: 9.1336
|
| 205 |
+
Epoch 23 Training: 58%|█████▊ | 1799/3125 [31:57<23:31, 1.06s/it]
|
| 206 |
+
2025-06-10 23:51:21,898 - __main__ - INFO - Epoch [23/30], Step [1800/3125], Loss: 2.2967, Perplexity: 9.9416
|
| 207 |
+
Epoch 23 Training: 61%|██████ | 1899/3125 [33:44<21:31, 1.05s/it]
|
| 208 |
+
2025-06-10 23:53:08,643 - __main__ - INFO - Epoch [23/30], Step [1900/3125], Loss: 2.4373, Perplexity: 11.4426
|
| 209 |
+
Epoch 23 Training: 64%|██████▍ | 1999/3125 [35:30<19:44, 1.05s/it]
|
| 210 |
+
2025-06-10 23:54:54,728 - __main__ - INFO - Epoch [23/30], Step [2000/3125], Loss: 2.3913, Perplexity: 10.9281
|
| 211 |
+
Epoch 23 Training: 67%|██████▋ | 2099/3125 [37:16<18:04, 1.06s/it]
|
| 212 |
+
2025-06-10 23:56:41,305 - __main__ - INFO - Epoch [23/30], Step [2100/3125], Loss: 2.2783, Perplexity: 9.7605
|
| 213 |
+
Epoch 23 Training: 70%|███████ | 2199/3125 [39:03<16:14, 1.05s/it]
|
| 214 |
+
2025-06-10 23:58:27,550 - __main__ - INFO - Epoch [23/30], Step [2200/3125], Loss: 2.6455, Perplexity: 14.0907
|
| 215 |
+
Epoch 23 Training: 74%|███████▎ | 2299/3125 [40:49<14:49, 1.08s/it]
|
| 216 |
+
2025-06-11 00:00:14,133 - __main__ - INFO - Epoch [23/30], Step [2300/3125], Loss: 2.3268, Perplexity: 10.2454
|
| 217 |
+
Epoch 23 Training: 77%|███████▋ | 2399/3125 [42:36<12:45, 1.05s/it]
|
| 218 |
+
2025-06-11 00:02:00,712 - __main__ - INFO - Epoch [23/30], Step [2400/3125], Loss: 2.3324, Perplexity: 10.3022
|
| 219 |
+
Epoch 23 Training: 80%|███████▉ | 2499/3125 [44:22<10:58, 1.05s/it]
|
| 220 |
+
2025-06-11 00:03:46,825 - __main__ - INFO - Epoch [23/30], Step [2500/3125], Loss: 2.1346, Perplexity: 8.4539
|
| 221 |
+
Epoch 23 Training: 83%|████████▎ | 2599/3125 [46:08<09:30, 1.08s/it]
|
| 222 |
+
2025-06-11 00:05:33,242 - __main__ - INFO - Epoch [23/30], Step [2600/3125], Loss: 2.3986, Perplexity: 11.0080
|
| 223 |
+
Epoch 23 Training: 86%|████████▋ | 2699/3125 [47:55<07:32, 1.06s/it]
|
| 224 |
+
2025-06-11 00:07:19,976 - __main__ - INFO - Epoch [23/30], Step [2700/3125], Loss: 2.3777, Perplexity: 10.7800
|
| 225 |
+
Epoch 23 Training: 90%|████████▉ | 2799/3125 [49:42<05:44, 1.06s/it]
|
| 226 |
+
2025-06-11 00:09:06,704 - __main__ - INFO - Epoch [23/30], Step [2800/3125], Loss: 2.4017, Perplexity: 11.0422
|
| 227 |
+
Epoch 23 Training: 93%|█████████▎| 2899/3125 [51:29<03:59, 1.06s/it]
|
| 228 |
+
2025-06-11 00:10:53,384 - __main__ - INFO - Epoch [23/30], Step [2900/3125], Loss: 2.6419, Perplexity: 14.0403
|
| 229 |
+
Epoch 23 Training: 96%|█████████▌| 2999/3125 [53:15<02:14, 1.07s/it]
|
| 230 |
+
2025-06-11 00:12:39,864 - __main__ - INFO - Epoch [23/30], Step [3000/3125], Loss: 2.4274, Perplexity: 11.3291
|
| 231 |
+
Epoch 23 Training: 99%|█████████▉| 3099/3125 [55:01<00:27, 1.05s/it]
|
| 232 |
+
2025-06-11 00:14:26,295 - __main__ - INFO - Epoch [23/30], Step [3100/3125], Loss: 2.4689, Perplexity: 11.8095
|
| 233 |
+
Epoch 23 Training: 100%|██████████| 3125/3125 [55:29<00:00, 1.07s/it]
|
| 234 |
+
2025-06-11 00:14:53,188 - __main__ - INFO - Epoch 23 Training finished. Avg Loss: 2.3468, Time: 3329.93s
|
| 235 |
+
Validation: 100%|██████████| 391/391 [12:24<00:00, 1.90s/it]
|
| 236 |
+
2025-06-11 00:27:17,526 - __main__ - INFO - Validation Avg Loss: 2.4694, Perplexity: 11.8158
|
| 237 |
+
2025-06-11 00:27:27,488 - __main__ - INFO - Validation BLEU-4: 0.1051
|
| 238 |
+
2025-06-11 00:27:27,489 - __main__ - INFO - Performing memory optimization after epoch...
|
| 239 |
+
2025-06-11 00:27:27,784 - __main__ - INFO - CUDA cache emptied.
|
| 240 |
+
2025-06-11 00:27:28,140 - __main__ - INFO - Python garbage collector run.
|
| 241 |
+
Epoch 24 Training: 3%|▎ | 99/3125 [01:48<54:03, 1.07s/it]
|
| 242 |
+
2025-06-11 00:29:17,820 - __main__ - INFO - Epoch [24/30], Step [100/3125], Loss: 2.1095, Perplexity: 8.2443
|
| 243 |
+
Epoch 24 Training: 6%|▋ | 199/3125 [03:35<51:20, 1.05s/it]
|
| 244 |
+
2025-06-11 00:31:04,436 - __main__ - INFO - Epoch [24/30], Step [200/3125], Loss: 2.2281, Perplexity: 9.2821
|
| 245 |
+
Epoch 24 Training: 10%|▉ | 299/3125 [05:21<49:51, 1.06s/it]
|
| 246 |
+
2025-06-11 00:32:51,283 - __main__ - INFO - Epoch [24/30], Step [300/3125], Loss: 2.3703, Perplexity: 10.7003
|
| 247 |
+
Epoch 24 Training: 13%|█▎ | 399/3125 [07:08<49:01, 1.08s/it]
|
| 248 |
+
2025-06-11 00:34:37,996 - __main__ - INFO - Epoch [24/30], Step [400/3125], Loss: 2.3050, Perplexity: 10.0242
|
| 249 |
+
Epoch 24 Training: 16%|█▌ | 499/3125 [08:55<46:28, 1.06s/it]
|
| 250 |
+
2025-06-11 00:36:25,008 - __main__ - INFO - Epoch [24/30], Step [500/3125], Loss: 2.2863, Perplexity: 9.8383
|
| 251 |
+
Epoch 24 Training: 19%|█▉ | 599/3125 [10:42<45:00, 1.07s/it]
|
| 252 |
+
2025-06-11 00:38:11,729 - __main__ - INFO - Epoch [24/30], Step [600/3125], Loss: 2.2520, Perplexity: 9.5070
|
| 253 |
+
Epoch 24 Training: 22%|██▏ | 699/3125 [12:29<42:15, 1.05s/it]
|
| 254 |
+
2025-06-11 00:39:58,355 - __main__ - INFO - Epoch [24/30], Step [700/3125], Loss: 2.2716, Perplexity: 9.6947
|
| 255 |
+
Epoch 24 Training: 26%|██▌ | 799/3125 [14:15<41:47, 1.08s/it]
|
| 256 |
+
2025-06-11 00:41:44,889 - __main__ - INFO - Epoch [24/30], Step [800/3125], Loss: 2.3995, Perplexity: 11.0173
|
| 257 |
+
Epoch 24 Training: 29%|██▉ | 899/3125 [16:02<39:14, 1.06s/it]
|
| 258 |
+
2025-06-11 00:43:31,398 - __main__ - INFO - Epoch [24/30], Step [900/3125], Loss: 2.3343, Perplexity: 10.3224
|
| 259 |
+
Epoch 24 Training: 32%|███▏ | 999/3125 [17:49<38:04, 1.07s/it]
|
| 260 |
+
2025-06-11 00:45:18,449 - __main__ - INFO - Epoch [24/30], Step [1000/3125], Loss: 2.2976, Perplexity: 9.9507
|
| 261 |
+
Epoch 24 Training: 35%|███▌ | 1099/3125 [19:35<35:49, 1.06s/it]
|
| 262 |
+
2025-06-11 00:47:04,619 - __main__ - INFO - Epoch [24/30], Step [1100/3125], Loss: 2.3547, Perplexity: 10.5347
|
| 263 |
+
Epoch 24 Training: 38%|███▊ | 1199/3125 [21:21<33:58, 1.06s/it]
|
| 264 |
+
2025-06-11 00:48:50,972 - __main__ - INFO - Epoch [24/30], Step [1200/3125], Loss: 2.3108, Perplexity: 10.0823
|
| 265 |
+
Epoch 24 Training: 42%|████▏ | 1299/3125 [23:08<32:12, 1.06s/it]
|
| 266 |
+
2025-06-11 00:50:37,638 - __main__ - INFO - Epoch [24/30], Step [1300/3125], Loss: 2.3038, Perplexity: 10.0118
|
| 267 |
+
Epoch 24 Training: 45%|████▍ | 1399/3125 [24:54<31:07, 1.08s/it]
|
| 268 |
+
2025-06-11 00:52:24,182 - __main__ - INFO - Epoch [24/30], Step [1400/3125], Loss: 2.4687, Perplexity: 11.8066
|
| 269 |
+
Epoch 24 Training: 48%|████▊ | 1499/3125 [26:41<28:34, 1.05s/it]
|
| 270 |
+
2025-06-11 00:54:10,798 - __main__ - INFO - Epoch [24/30], Step [1500/3125], Loss: 2.2251, Perplexity: 9.2544
|
| 271 |
+
Epoch 24 Training: 51%|█████ | 1599/3125 [28:28<27:44, 1.09s/it]
|
| 272 |
+
2025-06-11 00:55:57,193 - __main__ - INFO - Epoch [24/30], Step [1600/3125], Loss: 2.4617, Perplexity: 11.7248
|
| 273 |
+
Epoch 24 Training: 54%|█████▍ | 1699/3125 [30:14<24:56, 1.05s/it]
|
| 274 |
+
2025-06-11 00:57:43,842 - __main__ - INFO - Epoch [24/30], Step [1700/3125], Loss: 2.2415, Perplexity: 9.4070
|
| 275 |
+
Epoch 24 Training: 58%|█████▊ | 1799/3125 [32:01<23:13, 1.05s/it]
|
| 276 |
+
2025-06-11 00:59:30,263 - __main__ - INFO - Epoch [24/30], Step [1800/3125], Loss: 2.2795, Perplexity: 9.7719
|
| 277 |
+
Epoch 24 Training: 61%|██████ | 1899/3125 [33:47<21:46, 1.07s/it]
|
| 278 |
+
2025-06-11 01:01:17,186 - __main__ - INFO - Epoch [24/30], Step [1900/3125], Loss: 2.5203, Perplexity: 12.4326
|
| 279 |
+
Epoch 24 Training: 64%|██████▍ | 1999/3125 [35:34<19:54, 1.06s/it]
|
| 280 |
+
2025-06-11 01:03:03,886 - __main__ - INFO - Epoch [24/30], Step [2000/3125], Loss: 2.4630, Perplexity: 11.7403
|
| 281 |
+
Epoch 24 Training: 67%|██████▋ | 2099/3125 [37:21<18:23, 1.08s/it]
|
| 282 |
+
2025-06-11 01:04:50,564 - __main__ - INFO - Epoch [24/30], Step [2100/3125], Loss: 2.3497, Perplexity: 10.4825
|
| 283 |
+
Epoch 24 Training: 70%|███████ | 2199/3125 [39:07<16:16, 1.05s/it]
|
| 284 |
+
2025-06-11 01:06:36,779 - __main__ - INFO - Epoch [24/30], Step [2200/3125], Loss: 2.4901, Perplexity: 12.0629
|
| 285 |
+
Epoch 24 Training: 74%|███████▎ | 2299/3125 [40:54<14:45, 1.07s/it]
|
| 286 |
+
2025-06-11 01:08:23,474 - __main__ - INFO - Epoch [24/30], Step [2300/3125], Loss: 2.1345, Perplexity: 8.4530
|
| 287 |
+
Epoch 24 Training: 77%|███████▋ | 2399/3125 [42:40<12:54, 1.07s/it]
|
| 288 |
+
2025-06-11 01:10:09,974 - __main__ - INFO - Epoch [24/30], Step [2400/3125], Loss: 2.3948, Perplexity: 10.9664
|
| 289 |
+
Epoch 24 Training: 80%|███████▉ | 2499/3125 [44:27<11:02, 1.06s/it]
|
| 290 |
+
2025-06-11 01:11:56,681 - __main__ - INFO - Epoch [24/30], Step [2500/3125], Loss: 2.1817, Perplexity: 8.8612
|
| 291 |
+
Epoch 24 Training: 83%|████████▎ | 2599/3125 [46:14<09:10, 1.05s/it]
|
| 292 |
+
2025-06-11 01:13:43,503 - __main__ - INFO - Epoch [24/30], Step [2600/3125], Loss: 2.4069, Perplexity: 11.0995
|
| 293 |
+
Epoch 24 Training: 86%|████████▋ | 2699/3125 [48:00<07:44, 1.09s/it]
|
| 294 |
+
2025-06-11 01:15:30,157 - __main__ - INFO - Epoch [24/30], Step [2700/3125], Loss: 2.4753, Perplexity: 11.8856
|
| 295 |
+
Epoch 24 Training: 90%|████████▉ | 2799/3125 [49:47<05:48, 1.07s/it]
|
| 296 |
+
2025-06-11 01:17:16,725 - __main__ - INFO - Epoch [24/30], Step [2800/3125], Loss: 2.4636, Perplexity: 11.7471
|
| 297 |
+
Epoch 24 Training: 93%|█████████▎| 2899/3125 [51:34<04:01, 1.07s/it]
|
| 298 |
+
2025-06-11 01:19:03,616 - __main__ - INFO - Epoch [24/30], Step [2900/3125], Loss: 2.6810, Perplexity: 14.5996
|
| 299 |
+
Epoch 24 Training: 96%|█████████▌| 2999/3125 [53:21<02:12, 1.05s/it]
|
| 300 |
+
2025-06-11 01:20:50,647 - __main__ - INFO - Epoch [24/30], Step [3000/3125], Loss: 2.2329, Perplexity: 9.3272
|
| 301 |
+
Epoch 24 Training: 99%|█████████▉| 3099/3125 [55:08<00:27, 1.05s/it]
|
| 302 |
+
2025-06-11 01:22:37,396 - __main__ - INFO - Epoch [24/30], Step [3100/3125], Loss: 2.1047, Perplexity: 8.2049
|
| 303 |
+
Epoch 24 Training: 100%|██████████| 3125/3125 [55:35<00:00, 1.07s/it]
|
| 304 |
+
2025-06-11 01:23:03,915 - __main__ - INFO - Epoch 24 Training finished. Avg Loss: 2.3058, Time: 3335.77s
|
| 305 |
+
Validation: 100%|██████████| 391/391 [13:00<00:00, 2.00s/it]
|
| 306 |
+
2025-06-11 01:36:04,607 - __main__ - INFO - Validation Avg Loss: 2.4789, Perplexity: 11.9279
|
| 307 |
+
2025-06-11 01:36:14,953 - __main__ - INFO - Validation BLEU-4: 0.1056
|
| 308 |
+
2025-06-11 01:36:14,954 - __main__ - INFO - Performing memory optimization after epoch...
|
| 309 |
+
2025-06-11 01:36:15,247 - __main__ - INFO - CUDA cache emptied.
|
| 310 |
+
2025-06-11 01:36:15,640 - __main__ - INFO - Python garbage collector run.
|
| 311 |
+
Epoch 25 Training: 3%|▎ | 99/3125 [01:48<52:42, 1.05s/it]
|
| 312 |
+
2025-06-11 01:38:05,659 - __main__ - INFO - Epoch [25/30], Step [100/3125], Loss: 2.0677, Perplexity: 7.9063
|
| 313 |
+
Epoch 25 Training: 6%|▋ | 199/3125 [03:35<52:05, 1.07s/it]
|
| 314 |
+
2025-06-11 01:39:52,448 - __main__ - INFO - Epoch [25/30], Step [200/3125], Loss: 2.3110, Perplexity: 10.0845
|
| 315 |
+
Epoch 25 Training: 10%|▉ | 299/3125 [05:22<51:13, 1.09s/it]
|
| 316 |
+
2025-06-11 01:41:39,080 - __main__ - INFO - Epoch [25/30], Step [300/3125], Loss: 2.0452, Perplexity: 7.7308
|
| 317 |
+
Epoch 25 Training: 13%|█▎ | 399/3125 [07:09<48:33, 1.07s/it]
|
| 318 |
+
2025-06-11 01:43:25,913 - __main__ - INFO - Epoch [25/30], Step [400/3125], Loss: 2.3708, Perplexity: 10.7054
|
| 319 |
+
Epoch 25 Training: 16%|█▌ | 499/3125 [08:55<46:30, 1.06s/it]
|
| 320 |
+
2025-06-11 01:45:12,427 - __main__ - INFO - Epoch [25/30], Step [500/3125], Loss: 2.2842, Perplexity: 9.8177
|
| 321 |
+
Epoch 25 Training: 19%|█▉ | 599/3125 [10:41<43:54, 1.04s/it]
|
| 322 |
+
2025-06-11 01:46:58,573 - __main__ - INFO - Epoch [25/30], Step [600/3125], Loss: 2.4650, Perplexity: 11.7635
|
| 323 |
+
Epoch 25 Training: 22%|██▏ | 699/3125 [12:28<42:52, 1.06s/it]
|
| 324 |
+
2025-06-11 01:48:44,783 - __main__ - INFO - Epoch [25/30], Step [700/3125], Loss: 2.2797, Perplexity: 9.7735
|
| 325 |
+
Epoch 25 Training: 26%|██▌ | 799/3125 [14:14<40:40, 1.05s/it]
|
| 326 |
+
2025-06-11 01:50:31,173 - __main__ - INFO - Epoch [25/30], Step [800/3125], Loss: 2.4073, Perplexity: 11.1045
|
| 327 |
+
Epoch 25 Training: 29%|██▉ | 899/3125 [16:00<39:29, 1.06s/it]
|
| 328 |
+
2025-06-11 01:52:17,406 - __main__ - INFO - Epoch [25/30], Step [900/3125], Loss: 1.9411, Perplexity: 6.9664
|
| 329 |
+
Epoch 25 Training: 32%|███▏ | 999/3125 [17:47<37:30, 1.06s/it]
|
| 330 |
+
2025-06-11 01:54:04,274 - __main__ - INFO - Epoch [25/30], Step [1000/3125], Loss: 2.1742, Perplexity: 8.7955
|
| 331 |
+
Epoch 25 Training: 35%|███▌ | 1099/3125 [19:35<36:58, 1.10s/it]
|
| 332 |
+
2025-06-11 01:55:51,769 - __main__ - INFO - Epoch [25/30], Step [1100/3125], Loss: 2.2986, Perplexity: 9.9598
|
| 333 |
+
Epoch 25 Training: 38%|███▊ | 1199/3125 [21:21<34:48, 1.08s/it]
|
| 334 |
+
2025-06-11 01:57:38,013 - __main__ - INFO - Epoch [25/30], Step [1200/3125], Loss: 2.2249, Perplexity: 9.2525
|
| 335 |
+
Epoch 25 Training: 42%|████▏ | 1299/3125 [23:08<32:41, 1.07s/it]
|
| 336 |
+
2025-06-11 01:59:24,777 - __main__ - INFO - Epoch [25/30], Step [1300/3125], Loss: 2.2743, Perplexity: 9.7211
|
| 337 |
+
Epoch 25 Training: 45%|████▍ | 1399/3125 [24:54<30:32, 1.06s/it]
|
| 338 |
+
2025-06-11 02:01:11,365 - __main__ - INFO - Epoch [25/30], Step [1400/3125], Loss: 2.4074, Perplexity: 11.1048
|
| 339 |
+
Epoch 25 Training: 48%|████▊ | 1499/3125 [26:41<29:37, 1.09s/it]
|
| 340 |
+
2025-06-11 02:02:57,836 - __main__ - INFO - Epoch [25/30], Step [1500/3125], Loss: 2.3521, Perplexity: 10.5077
|
| 341 |
+
Epoch 25 Training: 51%|█████ | 1599/3125 [28:27<27:13, 1.07s/it]
|
| 342 |
+
2025-06-11 02:04:44,044 - __main__ - INFO - Epoch [25/30], Step [1600/3125], Loss: 2.1566, Perplexity: 8.6420
|
| 343 |
+
Epoch 25 Training: 54%|█████▍ | 1699/3125 [30:14<25:49, 1.09s/it]
|
| 344 |
+
2025-06-11 02:06:30,992 - __main__ - INFO - Epoch [25/30], Step [1700/3125], Loss: 2.5753, Perplexity: 13.1350
|
| 345 |
+
Epoch 25 Training: 58%|█████▊ | 1799/3125 [32:01<23:47, 1.08s/it]
|
| 346 |
+
2025-06-11 02:08:17,923 - __main__ - INFO - Epoch [25/30], Step [1800/3125], Loss: 2.5129, Perplexity: 12.3405
|
| 347 |
+
Epoch 25 Training: 61%|██████ | 1899/3125 [33:47<21:49, 1.07s/it]
|
| 348 |
+
2025-06-11 02:10:04,520 - __main__ - INFO - Epoch [25/30], Step [1900/3125], Loss: 2.1021, Perplexity: 8.1835
|
| 349 |
+
Epoch 25 Training: 64%|██████▍ | 1999/3125 [35:35<20:19, 1.08s/it]
|
| 350 |
+
2025-06-11 02:11:51,758 - __main__ - INFO - Epoch [25/30], Step [2000/3125], Loss: 2.2199, Perplexity: 9.2062
|
| 351 |
+
Epoch 25 Training: 67%|██████▋ | 2099/3125 [37:22<18:24, 1.08s/it]
|
| 352 |
+
2025-06-11 02:13:38,790 - __main__ - INFO - Epoch [25/30], Step [2100/3125], Loss: 2.2128, Perplexity: 9.1416
|
| 353 |
+
Epoch 25 Training: 70%|███████ | 2199/3125 [39:08<16:33, 1.07s/it]
|
| 354 |
+
2025-06-11 02:15:25,639 - __main__ - INFO - Epoch [25/30], Step [2200/3125], Loss: 2.4628, Perplexity: 11.7379
|
| 355 |
+
Epoch 25 Training: 74%|███████▎ | 2299/3125 [40:55<14:31, 1.06s/it]
|
| 356 |
+
2025-06-11 02:17:11,818 - __main__ - INFO - Epoch [25/30], Step [2300/3125], Loss: 2.2937, Perplexity: 9.9117
|
| 357 |
+
Epoch 25 Training: 77%|███████▋ | 2399/3125 [42:42<12:44, 1.05s/it]
|
| 358 |
+
2025-06-11 02:18:58,784 - __main__ - INFO - Epoch [25/30], Step [2400/3125], Loss: 2.3119, Perplexity: 10.0937
|
| 359 |
+
Epoch 25 Training: 80%|███████▉ | 2499/3125 [44:28<11:17, 1.08s/it]
|
| 360 |
+
2025-06-11 02:20:45,531 - __main__ - INFO - Epoch [25/30], Step [2500/3125], Loss: 2.4301, Perplexity: 11.3601
|
| 361 |
+
Epoch 25 Training: 83%|████████▎ | 2599/3125 [46:14<09:22, 1.07s/it]
|
| 362 |
+
2025-06-11 02:22:31,593 - __main__ - INFO - Epoch [25/30], Step [2600/3125], Loss: 2.3248, Perplexity: 10.2245
|
| 363 |
+
Epoch 25 Training: 86%|████████▋ | 2699/3125 [48:01<07:28, 1.05s/it]
|
| 364 |
+
2025-06-11 02:24:18,268 - __main__ - INFO - Epoch [25/30], Step [2700/3125], Loss: 2.1451, Perplexity: 8.5426
|
| 365 |
+
Epoch 25 Training: 90%|████████▉ | 2799/3125 [49:48<05:48, 1.07s/it]
|
| 366 |
+
2025-06-11 02:26:05,182 - __main__ - INFO - Epoch [25/30], Step [2800/3125], Loss: 2.4403, Perplexity: 11.4766
|
| 367 |
+
Epoch 25 Training: 93%|█████████▎| 2899/3125 [51:35<04:02, 1.07s/it]
|
| 368 |
+
2025-06-11 02:27:52,231 - __main__ - INFO - Epoch [25/30], Step [2900/3125], Loss: 2.5203, Perplexity: 12.4329
|
| 369 |
+
Epoch 25 Training: 96%|█████████▌| 2999/3125 [53:22<02:14, 1.07s/it]
|
| 370 |
+
2025-06-11 02:29:39,135 - __main__ - INFO - Epoch [25/30], Step [3000/3125], Loss: 2.2823, Perplexity: 9.7993
|
| 371 |
+
Epoch 25 Training: 99%|█████████▉| 3099/3125 [55:08<00:28, 1.08s/it]
|
| 372 |
+
2025-06-11 02:31:25,479 - __main__ - INFO - Epoch [25/30], Step [3100/3125], Loss: 2.2913, Perplexity: 9.8882
|
| 373 |
+
Epoch 25 Training: 100%|██████████| 3125/3125 [55:36<00:00, 1.07s/it]
|
| 374 |
+
2025-06-11 02:31:52,162 - __main__ - INFO - Epoch 25 Training finished. Avg Loss: 2.2707, Time: 3336.52s
|
| 375 |
+
Validation: 100%|██████████| 391/391 [12:53<00:00, 1.98s/it]
|
| 376 |
+
2025-06-11 02:44:45,366 - __main__ - INFO - Validation Avg Loss: 2.4919, Perplexity: 12.0847
|
| 377 |
+
2025-06-11 02:44:55,839 - __main__ - INFO - Validation BLEU-4: 0.1028
|
| 378 |
+
2025-06-11 02:44:57,085 - __main__ - INFO - Saved periodic model checkpoint to ./output/model_epoch_25.pth
|
| 379 |
+
2025-06-11 02:44:57,087 - __main__ - INFO - Performing memory optimization after epoch...
|
| 380 |
+
2025-06-11 02:44:57,380 - __main__ - INFO - CUDA cache emptied.
|
| 381 |
+
2025-06-11 02:44:57,781 - __main__ - INFO - Python garbage collector run.
|
| 382 |
+
Epoch 26 Training: 3%|▎ | 99/3125 [01:48<54:10, 1.07s/it]
|
| 383 |
+
2025-06-11 02:46:47,510 - __main__ - INFO - Epoch [26/30], Step [100/3125], Loss: 2.1781, Perplexity: 8.8298
|
| 384 |
+
Epoch 26 Training: 6%|▋ | 199/3125 [03:35<51:51, 1.06s/it]
|
| 385 |
+
2025-06-11 02:48:34,182 - __main__ - INFO - Epoch [26/30], Step [200/3125], Loss: 2.1307, Perplexity: 8.4208
|
| 386 |
+
Epoch 26 Training: 10%|▉ | 299/3125 [05:21<49:37, 1.05s/it]
|
| 387 |
+
2025-06-11 02:50:20,758 - __main__ - INFO - Epoch [26/30], Step [300/3125], Loss: 2.1756, Perplexity: 8.8076
|
| 388 |
+
Epoch 26 Training: 13%|█▎ | 399/3125 [07:08<48:45, 1.07s/it]
|
| 389 |
+
2025-06-11 02:52:07,509 - __main__ - INFO - Epoch [26/30], Step [400/3125], Loss: 1.9878, Perplexity: 7.2998
|
| 390 |
+
Epoch 26 Training: 16%|█▌ | 499/3125 [08:55<47:05, 1.08s/it]
|
| 391 |
+
2025-06-11 02:53:54,661 - __main__ - INFO - Epoch [26/30], Step [500/3125], Loss: 2.3650, Perplexity: 10.6442
|
| 392 |
+
Epoch 26 Training: 19%|█▉ | 599/3125 [10:42<45:02, 1.07s/it]
|
| 393 |
+
2025-06-11 02:55:41,126 - __main__ - INFO - Epoch [26/30], Step [600/3125], Loss: 2.5252, Perplexity: 12.4940
|
| 394 |
+
Epoch 26 Training: 22%|██▏ | 699/3125 [12:28<42:59, 1.06s/it]
|
| 395 |
+
2025-06-11 02:57:27,719 - __main__ - INFO - Epoch [26/30], Step [700/3125], Loss: 2.4526, Perplexity: 11.6181
|
| 396 |
+
Epoch 26 Training: 26%|██▌ | 799/3125 [14:15<41:31, 1.07s/it]
|
| 397 |
+
2025-06-11 02:59:14,465 - __main__ - INFO - Epoch [26/30], Step [800/3125], Loss: 2.1245, Perplexity: 8.3691
|
| 398 |
+
Epoch 26 Training: 29%|██▉ | 899/3125 [16:02<39:09, 1.06s/it]
|
| 399 |
+
2025-06-11 03:01:01,100 - __main__ - INFO - Epoch [26/30], Step [900/3125], Loss: 2.0997, Perplexity: 8.1638
|
| 400 |
+
Epoch 26 Training: 32%|███▏ | 999/3125 [17:48<37:49, 1.07s/it]
|
| 401 |
+
2025-06-11 03:02:47,434 - __main__ - INFO - Epoch [26/30], Step [1000/3125], Loss: 2.3237, Perplexity: 10.2132
|
| 402 |
+
Epoch 26 Training: 35%|███▌ | 1099/3125 [19:35<35:20, 1.05s/it]
|
| 403 |
+
2025-06-11 03:04:34,056 - __main__ - INFO - Epoch [26/30], Step [1100/3125], Loss: 2.1471, Perplexity: 8.5599
|
| 404 |
+
Epoch 26 Training: 38%|███▊ | 1199/3125 [21:22<34:25, 1.07s/it]
|
| 405 |
+
2025-06-11 03:06:21,068 - __main__ - INFO - Epoch [26/30], Step [1200/3125], Loss: 2.4894, Perplexity: 12.0542
|
| 406 |
+
Epoch 26 Training: 42%|████▏ | 1299/3125 [23:08<32:10, 1.06s/it]
|
| 407 |
+
2025-06-11 03:08:07,541 - __main__ - INFO - Epoch [26/30], Step [1300/3125], Loss: 2.2348, Perplexity: 9.3447
|
| 408 |
+
Epoch 26 Training: 45%|████▍ | 1399/3125 [24:55<31:03, 1.08s/it]
|
| 409 |
+
2025-06-11 03:09:53,995 - __main__ - INFO - Epoch [26/30], Step [1400/3125], Loss: 2.2782, Perplexity: 9.7595
|
| 410 |
+
Epoch 26 Training: 48%|████▊ | 1499/3125 [26:41<28:26, 1.05s/it]
|
| 411 |
+
2025-06-11 03:11:40,489 - __main__ - INFO - Epoch [26/30], Step [1500/3125], Loss: 2.4081, Perplexity: 11.1129
|
| 412 |
+
Epoch 26 Training: 51%|█████ | 1599/3125 [28:28<27:13, 1.07s/it]
|
| 413 |
+
2025-06-11 03:13:27,420 - __main__ - INFO - Epoch [26/30], Step [1600/3125], Loss: 2.1137, Perplexity: 8.2785
|
| 414 |
+
Epoch 26 Training: 54%|█████▍ | 1699/3125 [30:15<25:21, 1.07s/it]
|
| 415 |
+
2025-06-11 03:15:14,451 - __main__ - INFO - Epoch [26/30], Step [1700/3125], Loss: 2.3987, Perplexity: 11.0087
|
| 416 |
+
Epoch 26 Training: 58%|█████▊ | 1799/3125 [32:02<23:28, 1.06s/it]
|
| 417 |
+
2025-06-11 03:17:01,020 - __main__ - INFO - Epoch [26/30], Step [1800/3125], Loss: 2.0616, Perplexity: 7.8588
|
| 418 |
+
Epoch 26 Training: 61%|██████ | 1899/3125 [33:48<21:49, 1.07s/it]
|
| 419 |
+
2025-06-11 03:18:46,981 - __main__ - INFO - Epoch [26/30], Step [1900/3125], Loss: 2.1317, Perplexity: 8.4295
|
| 420 |
+
Epoch 26 Training: 64%|██████▍ | 1999/3125 [35:34<19:58, 1.06s/it]
|
| 421 |
+
2025-06-11 03:20:33,558 - __main__ - INFO - Epoch [26/30], Step [2000/3125], Loss: 2.2971, Perplexity: 9.9451
|
| 422 |
+
Epoch 26 Training: 67%|██████▋ | 2099/3125 [37:21<17:52, 1.04s/it]
|
| 423 |
+
2025-06-11 03:22:20,224 - __main__ - INFO - Epoch [26/30], Step [2100/3125], Loss: 2.2505, Perplexity: 9.4921
|
| 424 |
+
Epoch 26 Training: 70%|███████ | 2199/3125 [39:08<16:41, 1.08s/it]
|
| 425 |
+
2025-06-11 03:24:06,994 - __main__ - INFO - Epoch [26/30], Step [2200/3125], Loss: 2.1467, Perplexity: 8.5564
|
| 426 |
+
Epoch 26 Training: 74%|███████▎ | 2299/3125 [40:55<14:45, 1.07s/it]
|
| 427 |
+
2025-06-11 03:25:54,174 - __main__ - INFO - Epoch [26/30], Step [2300/3125], Loss: 1.9914, Perplexity: 7.3260
|
| 428 |
+
Epoch 26 Training: 77%|███████▋ | 2399/3125 [42:41<12:45, 1.05s/it]
|
| 429 |
+
2025-06-11 03:27:40,333 - __main__ - INFO - Epoch [26/30], Step [2400/3125], Loss: 2.0928, Perplexity: 8.1075
|
| 430 |
+
Epoch 26 Training: 80%|███████▉ | 2499/3125 [44:28<11:26, 1.10s/it]
|
| 431 |
+
2025-06-11 03:29:27,130 - __main__ - INFO - Epoch [26/30], Step [2500/3125], Loss: 2.4869, Perplexity: 12.0239
|
| 432 |
+
Epoch 26 Training: 83%|████████▎ | 2599/3125 [46:15<09:12, 1.05s/it]
|
| 433 |
+
2025-06-11 03:31:13,925 - __main__ - INFO - Epoch [26/30], Step [2600/3125], Loss: 2.0959, Perplexity: 8.1325
|
| 434 |
+
Epoch 26 Training: 86%|████████▋ | 2699/3125 [48:01<07:29, 1.06s/it]
|
| 435 |
+
2025-06-11 03:32:59,910 - __main__ - INFO - Epoch [26/30], Step [2700/3125], Loss: 2.1937, Perplexity: 8.9682
|
| 436 |
+
Epoch 26 Training: 90%|████████▉ | 2799/3125 [49:48<05:49, 1.07s/it]
|
| 437 |
+
2025-06-11 03:34:46,905 - __main__ - INFO - Epoch [26/30], Step [2800/3125], Loss: 2.1959, Perplexity: 8.9884
|
| 438 |
+
Epoch 26 Training: 93%|█████████▎| 2899/3125 [51:35<04:01, 1.07s/it]
|
| 439 |
+
2025-06-11 03:36:34,047 - __main__ - INFO - Epoch [26/30], Step [2900/3125], Loss: 2.0231, Perplexity: 7.5616
|
| 440 |
+
Epoch 26 Training: 96%|█████████▌| 2999/3125 [53:21<02:14, 1.07s/it]
|
| 441 |
+
2025-06-11 03:38:20,737 - __main__ - INFO - Epoch [26/30], Step [3000/3125], Loss: 2.2614, Perplexity: 9.5964
|
| 442 |
+
Epoch 26 Training: 99%|█████████▉| 3099/3125 [55:08<00:27, 1.05s/it]
|
| 443 |
+
2025-06-11 03:40:07,482 - __main__ - INFO - Epoch [26/30], Step [3100/3125], Loss: 2.3379, Perplexity: 10.3591
|
| 444 |
+
Epoch 26 Training: 100%|██████████| 3125/3125 [55:36<00:00, 1.07s/it]
|
| 445 |
+
2025-06-11 03:40:34,240 - __main__ - INFO - Epoch 26 Training finished. Avg Loss: 2.2387, Time: 3336.46s
|
| 446 |
+
Validation: 100%|██████████| 391/391 [12:57<00:00, 1.99s/it]
|
| 447 |
+
2025-06-11 03:53:32,177 - __main__ - INFO - Validation Avg Loss: 2.4963, Perplexity: 12.1371
|
| 448 |
+
2025-06-11 03:53:42,502 - __main__ - INFO - Validation BLEU-4: 0.1031
|
| 449 |
+
2025-06-11 03:53:42,503 - __main__ - INFO - Performing memory optimization after epoch...
|
| 450 |
+
2025-06-11 03:53:42,769 - __main__ - INFO - CUDA cache emptied.
|
| 451 |
+
2025-06-11 03:53:43,136 - __main__ - INFO - Python garbage collector run.
|
| 452 |
+
Epoch 27 Training: 3%|▎ | 99/3125 [01:49<54:23, 1.08s/it]
|
| 453 |
+
2025-06-11 03:55:33,471 - __main__ - INFO - Epoch [27/30], Step [100/3125], Loss: 2.4510, Perplexity: 11.6003
|
| 454 |
+
Epoch 27 Training: 6%|▋ | 199/3125 [03:35<52:21, 1.07s/it]
|
| 455 |
+
2025-06-11 03:57:19,933 - __main__ - INFO - Epoch [27/30], Step [200/3125], Loss: 2.1434, Perplexity: 8.5288
|
| 456 |
+
Epoch 27 Training: 10%|▉ | 299/3125 [05:22<50:05, 1.06s/it]
|
| 457 |
+
2025-06-11 03:59:06,702 - __main__ - INFO - Epoch [27/30], Step [300/3125], Loss: 2.2218, Perplexity: 9.2243
|
| 458 |
+
Epoch 27 Training: 13%|█▎ | 399/3125 [07:09<48:36, 1.07s/it]
|
| 459 |
+
2025-06-11 04:00:53,717 - __main__ - INFO - Epoch [27/30], Step [400/3125], Loss: 2.3096, Perplexity: 10.0700
|
| 460 |
+
Epoch 27 Training: 16%|█▌ | 499/3125 [08:56<46:17, 1.06s/it]
|
| 461 |
+
2025-06-11 04:02:40,535 - __main__ - INFO - Epoch [27/30], Step [500/3125], Loss: 1.9651, Perplexity: 7.1359
|
| 462 |
+
Epoch 27 Training: 19%|█▉ | 599/3125 [10:42<45:15, 1.08s/it]
|
| 463 |
+
2025-06-11 04:04:27,128 - __main__ - INFO - Epoch [27/30], Step [600/3125], Loss: 2.1665, Perplexity: 8.7279
|
| 464 |
+
Epoch 27 Training: 22%|██▏ | 699/3125 [12:29<44:25, 1.10s/it]
|
| 465 |
+
2025-06-11 04:06:13,909 - __main__ - INFO - Epoch [27/30], Step [700/3125], Loss: 1.9937, Perplexity: 7.3428
|
| 466 |
+
Epoch 27 Training: 26%|██▌ | 799/3125 [14:16<41:57, 1.08s/it]
|
| 467 |
+
2025-06-11 04:08:01,161 - __main__ - INFO - Epoch [27/30], Step [800/3125], Loss: 2.3485, Perplexity: 10.4698
|
| 468 |
+
Epoch 27 Training: 29%|██▉ | 899/3125 [16:03<39:14, 1.06s/it]
|
| 469 |
+
2025-06-11 04:09:47,364 - __main__ - INFO - Epoch [27/30], Step [900/3125], Loss: 2.2921, Perplexity: 9.8954
|
| 470 |
+
Epoch 27 Training: 32%|███▏ | 999/3125 [17:49<38:03, 1.07s/it]
|
| 471 |
+
2025-06-11 04:11:34,152 - __main__ - INFO - Epoch [27/30], Step [1000/3125], Loss: 2.1013, Perplexity: 8.1766
|
| 472 |
+
Epoch 27 Training: 35%|███▌ | 1099/3125 [19:36<36:00, 1.07s/it]
|
| 473 |
+
2025-06-11 04:13:20,882 - __main__ - INFO - Epoch [27/30], Step [1100/3125], Loss: 2.0653, Perplexity: 7.8879
|
| 474 |
+
Epoch 27 Training: 38%|███▊ | 1199/3125 [21:23<33:38, 1.05s/it]
|
| 475 |
+
2025-06-11 04:15:07,329 - __main__ - INFO - Epoch [27/30], Step [1200/3125], Loss: 2.2314, Perplexity: 9.3128
|
| 476 |
+
Epoch 27 Training: 42%|████▏ | 1299/3125 [23:09<32:06, 1.05s/it]
|
| 477 |
+
2025-06-11 04:16:53,655 - __main__ - INFO - Epoch [27/30], Step [1300/3125], Loss: 2.1889, Perplexity: 8.9255
|
| 478 |
+
Epoch 27 Training: 45%|████▍ | 1399/3125 [24:56<30:39, 1.07s/it]
|
| 479 |
+
2025-06-11 04:18:40,202 - __main__ - INFO - Epoch [27/30], Step [1400/3125], Loss: 2.2393, Perplexity: 9.3871
|
| 480 |
+
Epoch 27 Training: 48%|████▊ | 1499/3125 [26:42<28:32, 1.05s/it]
|
| 481 |
+
2025-06-11 04:20:27,025 - __main__ - INFO - Epoch [27/30], Step [1500/3125], Loss: 2.0922, Perplexity: 8.1025
|
| 482 |
+
Epoch 27 Training: 51%|██��██ | 1599/3125 [28:29<27:12, 1.07s/it]
|
| 483 |
+
2025-06-11 04:22:13,704 - __main__ - INFO - Epoch [27/30], Step [1600/3125], Loss: 2.0977, Perplexity: 8.1471
|
| 484 |
+
Epoch 27 Training: 54%|█████▍ | 1699/3125 [30:15<25:23, 1.07s/it]
|
| 485 |
+
2025-06-11 04:24:00,090 - __main__ - INFO - Epoch [27/30], Step [1700/3125], Loss: 2.1646, Perplexity: 8.7110
|
| 486 |
+
Epoch 27 Training: 58%|█████▊ | 1799/3125 [32:02<23:43, 1.07s/it]
|
| 487 |
+
2025-06-11 04:25:46,973 - __main__ - INFO - Epoch [27/30], Step [1800/3125], Loss: 2.0869, Perplexity: 8.0598
|
| 488 |
+
Epoch 27 Training: 61%|██████ | 1899/3125 [33:49<22:11, 1.09s/it]
|
| 489 |
+
2025-06-11 04:27:34,140 - __main__ - INFO - Epoch [27/30], Step [1900/3125], Loss: 2.2150, Perplexity: 9.1616
|
| 490 |
+
Epoch 27 Training: 64%|██████▍ | 1999/3125 [35:36<19:52, 1.06s/it]
|
| 491 |
+
2025-06-11 04:29:20,586 - __main__ - INFO - Epoch [27/30], Step [2000/3125], Loss: 2.3303, Perplexity: 10.2812
|
| 492 |
+
Epoch 27 Training: 67%|██████▋ | 2099/3125 [37:23<18:15, 1.07s/it]
|
| 493 |
+
2025-06-11 04:31:07,237 - __main__ - INFO - Epoch [27/30], Step [2100/3125], Loss: 2.0849, Perplexity: 8.0437
|
| 494 |
+
Epoch 27 Training: 70%|███████ | 2199/3125 [39:10<16:12, 1.05s/it]
|
| 495 |
+
2025-06-11 04:32:54,360 - __main__ - INFO - Epoch [27/30], Step [2200/3125], Loss: 2.1256, Perplexity: 8.3781
|
| 496 |
+
Epoch 27 Training: 74%|███████▎ | 2299/3125 [40:56<14:43, 1.07s/it]
|
| 497 |
+
2025-06-11 04:34:41,095 - __main__ - INFO - Epoch [27/30], Step [2300/3125], Loss: 2.4150, Perplexity: 11.1895
|
| 498 |
+
Epoch 27 Training: 77%|███████▋ | 2399/3125 [42:42<12:44, 1.05s/it]
|
| 499 |
+
2025-06-11 04:36:26,954 - __main__ - INFO - Epoch [27/30], Step [2400/3125], Loss: 2.2232, Perplexity: 9.2372
|
| 500 |
+
Epoch 27 Training: 80%|███████▉ | 2499/3125 [44:29<11:00, 1.05s/it]
|
| 501 |
+
2025-06-11 04:38:13,296 - __main__ - INFO - Epoch [27/30], Step [2500/3125], Loss: 2.0479, Perplexity: 7.7517
|
| 502 |
+
Epoch 27 Training: 83%|████████▎ | 2599/3125 [46:15<09:15, 1.06s/it]
|
| 503 |
+
2025-06-11 04:39:59,872 - __main__ - INFO - Epoch [27/30], Step [2600/3125], Loss: 2.2103, Perplexity: 9.1183
|
| 504 |
+
Epoch 27 Training: 86%|████████▋ | 2699/3125 [48:02<07:37, 1.07s/it]
|
| 505 |
+
2025-06-11 04:41:46,260 - __main__ - INFO - Epoch [27/30], Step [2700/3125], Loss: 2.0779, Perplexity: 7.9875
|
| 506 |
+
Epoch 27 Training: 90%|████████▉ | 2799/3125 [49:48<05:47, 1.06s/it]
|
| 507 |
+
2025-06-11 04:43:32,947 - __main__ - INFO - Epoch [27/30], Step [2800/3125], Loss: 2.2260, Perplexity: 9.2629
|
| 508 |
+
Epoch 27 Training: 93%|█████████▎| 2899/3125 [51:35<03:58, 1.05s/it]
|
| 509 |
+
2025-06-11 04:45:19,449 - __main__ - INFO - Epoch [27/30], Step [2900/3125], Loss: 1.9721, Perplexity: 7.1857
|
| 510 |
+
Epoch 27 Training: 96%|█████████▌| 2999/3125 [53:21<02:17, 1.09s/it]
|
| 511 |
+
2025-06-11 04:47:05,517 - __main__ - INFO - Epoch [27/30], Step [3000/3125], Loss: 2.0447, Perplexity: 7.7268
|
| 512 |
+
Epoch 27 Training: 99%|█████████▉| 3099/3125 [55:07<00:27, 1.06s/it]
|
| 513 |
+
2025-06-11 04:48:52,184 - __main__ - INFO - Epoch [27/30], Step [3100/3125], Loss: 2.3461, Perplexity: 10.4452
|
| 514 |
+
Epoch 27 Training: 100%|██████████| 3125/3125 [55:35<00:00, 1.07s/it]
|
| 515 |
+
2025-06-11 04:49:19,002 - __main__ - INFO - Epoch 27 Training finished. Avg Loss: 2.1767, Time: 3335.86s
|
| 516 |
+
Validation: 100%|██████████| 391/391 [12:56<00:00, 1.99s/it]
|
| 517 |
+
2025-06-11 05:02:15,213 - __main__ - INFO - Validation Avg Loss: 2.5049, Perplexity: 12.2423
|
| 518 |
+
2025-06-11 05:02:25,331 - __main__ - INFO - Validation BLEU-4: 0.1046
|
| 519 |
+
2025-06-11 05:02:25,332 - __main__ - INFO - Performing memory optimization after epoch...
|
| 520 |
+
2025-06-11 05:02:25,616 - __main__ - INFO - CUDA cache emptied.
|
| 521 |
+
2025-06-11 05:02:25,976 - __main__ - INFO - Python garbage collector run.
|
| 522 |
+
Epoch 28 Training: 3%|▎ | 99/3125 [01:49<55:22, 1.10s/it]
|
| 523 |
+
2025-06-11 05:04:16,514 - __main__ - INFO - Epoch [28/30], Step [100/3125], Loss: 2.3226, Perplexity: 10.2017
|
| 524 |
+
Epoch 28 Training: 6%|▋ | 199/3125 [03:36<53:05, 1.09s/it]
|
| 525 |
+
2025-06-11 05:06:03,370 - __main__ - INFO - Epoch [28/30], Step [200/3125], Loss: 2.0446, Perplexity: 7.7264
|
| 526 |
+
Epoch 28 Training: 10%|▉ | 299/3125 [05:22<49:38, 1.05s/it]
|
| 527 |
+
2025-06-11 05:07:49,943 - __main__ - INFO - Epoch [28/30], Step [300/3125], Loss: 2.1842, Perplexity: 8.8834
|
| 528 |
+
Epoch 28 Training: 13%|█▎ | 399/3125 [07:09<49:08, 1.08s/it]
|
| 529 |
+
2025-06-11 05:09:36,606 - __main__ - INFO - Epoch [28/30], Step [400/3125], Loss: 2.1027, Perplexity: 8.1881
|
| 530 |
+
Epoch 28 Training: 16%|█▌ | 499/3125 [08:56<46:24, 1.06s/it]
|
| 531 |
+
2025-06-11 05:11:23,149 - __main__ - INFO - Epoch [28/30], Step [500/3125], Loss: 2.0650, Perplexity: 7.8852
|
| 532 |
+
Epoch 28 Training: 19%|█▉ | 599/3125 [10:43<45:02, 1.07s/it]
|
| 533 |
+
2025-06-11 05:13:10,157 - __main__ - INFO - Epoch [28/30], Step [600/3125], Loss: 2.1477, Perplexity: 8.5651
|
| 534 |
+
Epoch 28 Training: 22%|██▏ | 699/3125 [12:29<42:30, 1.05s/it]
|
| 535 |
+
2025-06-11 05:14:56,988 - __main__ - INFO - Epoch [28/30], Step [700/3125], Loss: 2.2763, Perplexity: 9.7404
|
| 536 |
+
Epoch 28 Training: 26%|██▌ | 799/3125 [14:17<43:15, 1.12s/it]
|
| 537 |
+
2025-06-11 05:16:44,106 - __main__ - INFO - Epoch [28/30], Step [800/3125], Loss: 2.0723, Perplexity: 7.9430
|
| 538 |
+
Epoch 28 Training: 29%|██▉ | 899/3125 [16:04<40:10, 1.08s/it]
|
| 539 |
+
2025-06-11 05:18:31,089 - __main__ - INFO - Epoch [28/30], Step [900/3125], Loss: 2.2289, Perplexity: 9.2896
|
| 540 |
+
Epoch 28 Training: 32%|███▏ | 999/3125 [17:50<38:19, 1.08s/it]
|
| 541 |
+
2025-06-11 05:20:17,225 - __main__ - INFO - Epoch [28/30], Step [1000/3125], Loss: 2.0397, Perplexity: 7.6886
|
| 542 |
+
Epoch 28 Training: 35%|███▌ | 1099/3125 [19:36<36:10, 1.07s/it]
|
| 543 |
+
2025-06-11 05:22:03,933 - __main__ - INFO - Epoch [28/30], Step [1100/3125], Loss: 2.0839, Perplexity: 8.0357
|
| 544 |
+
Epoch 28 Training: 38%|███▊ | 1199/3125 [21:23<34:02, 1.06s/it]
|
| 545 |
+
2025-06-11 05:23:50,178 - __main__ - INFO - Epoch [28/30], Step [1200/3125], Loss: 2.1007, Perplexity: 8.1722
|
| 546 |
+
Epoch 28 Training: 42%|████▏ | 1299/3125 [23:09<32:02, 1.05s/it]
|
| 547 |
+
2025-06-11 05:25:36,305 - __main__ - INFO - Epoch [28/30], Step [1300/3125], Loss: 2.0338, Perplexity: 7.6428
|
| 548 |
+
Epoch 28 Training: 45%|████▍ | 1399/3125 [24:55<30:44, 1.07s/it]
|
| 549 |
+
2025-06-11 05:27:23,028 - __main__ - INFO - Epoch [28/30], Step [1400/3125], Loss: 2.2426, Perplexity: 9.4181
|
| 550 |
+
Epoch 28 Training: 48%|████▊ | 1499/3125 [26:42<29:24, 1.09s/it]
|
| 551 |
+
2025-06-11 05:29:09,790 - __main__ - INFO - Epoch [28/30], Step [1500/3125], Loss: 2.0902, Perplexity: 8.0865
|
| 552 |
+
Epoch 28 Training: 51%|█████ | 1599/3125 [28:29<27:14, 1.07s/it]
|
| 553 |
+
2025-06-11 05:30:56,617 - __main__ - INFO - Epoch [28/30], Step [1600/3125], Loss: 2.0530, Perplexity: 7.7911
|
| 554 |
+
Epoch 28 Training: 54%|█████▍ | 1699/3125 [30:15<25:52, 1.09s/it]
|
| 555 |
+
2025-06-11 05:32:42,683 - __main__ - INFO - Epoch [28/30], Step [1700/3125], Loss: 2.1393, Perplexity: 8.4933
|
| 556 |
+
Epoch 28 Training: 58%|█████▊ | 1799/3125 [32:01<23:19, 1.06s/it]
|
| 557 |
+
2025-06-11 05:34:28,982 - __main__ - INFO - Epoch [28/30], Step [1800/3125], Loss: 2.2889, Perplexity: 9.8640
|
| 558 |
+
Epoch 28 Training: 61%|██████ | 1899/3125 [33:48<21:40, 1.06s/it]
|
| 559 |
+
2025-06-11 05:36:15,579 - __main__ - INFO - Epoch [28/30], Step [1900/3125], Loss: 2.0841, Perplexity: 8.0370
|
| 560 |
+
Epoch 28 Training: 64%|██████▍ | 1999/3125 [35:34<19:31, 1.04s/it]
|
| 561 |
+
2025-06-11 05:38:01,967 - __main__ - INFO - Epoch [28/30], Step [2000/3125], Loss: 2.1644, Perplexity: 8.7093
|
| 562 |
+
Epoch 28 Training: 67%|██████▋ | 2099/3125 [37:20<18:02, 1.06s/it]
|
| 563 |
+
2025-06-11 05:39:47,966 - __main__ - INFO - Epoch [28/30], Step [2100/3125], Loss: 2.3094, Perplexity: 10.0683
|
| 564 |
+
Epoch 28 Training: 70%|███████ | 2199/3125 [39:07<16:35, 1.08s/it]
|
| 565 |
+
2025-06-11 05:41:34,146 - __main__ - INFO - Epoch [28/30], Step [2200/3125], Loss: 2.1274, Perplexity: 8.3931
|
| 566 |
+
Epoch 28 Training: 74%|███████▎ | 2299/3125 [40:53<14:40, 1.07s/it]
|
| 567 |
+
2025-06-11 05:43:20,302 - __main__ - INFO - Epoch [28/30], Step [2300/3125], Loss: 2.1598, Perplexity: 8.6696
|
| 568 |
+
Epoch 28 Training: 77%|███████▋ | 2399/3125 [42:39<12:56, 1.07s/it]
|
| 569 |
+
2025-06-11 05:45:06,835 - __main__ - INFO - Epoch [28/30], Step [2400/3125], Loss: 2.0426, Perplexity: 7.7105
|
| 570 |
+
Epoch 28 Training: 80%|███████▉ | 2499/3125 [44:26<11:20, 1.09s/it]
|
| 571 |
+
2025-06-11 05:46:53,147 - __main__ - INFO - Epoch [28/30], Step [2500/3125], Loss: 2.0391, Perplexity: 7.6833
|
| 572 |
+
Epoch 28 Training: 83%|████████▎ | 2599/3125 [46:12<09:33, 1.09s/it]
|
| 573 |
+
2025-06-11 05:48:39,287 - __main__ - INFO - Epoch [28/30], Step [2600/3125], Loss: 2.1521, Perplexity: 8.6025
|
| 574 |
+
Epoch 28 Training: 86%|████████▋ | 2699/3125 [47:58<07:33, 1.06s/it]
|
| 575 |
+
2025-06-11 05:50:25,247 - __main__ - INFO - Epoch [28/30], Step [2700/3125], Loss: 2.0867, Perplexity: 8.0583
|
| 576 |
+
Epoch 28 Training: 90%|████████▉ | 2799/3125 [49:43<05:47, 1.07s/it]
|
| 577 |
+
2025-06-11 05:52:10,744 - __main__ - INFO - Epoch [28/30], Step [2800/3125], Loss: 1.9385, Perplexity: 6.9486
|
| 578 |
+
Epoch 28 Training: 93%|█████████▎| 2899/3125 [51:29<03:58, 1.06s/it]
|
| 579 |
+
2025-06-11 05:53:56,657 - __main__ - INFO - Epoch [28/30], Step [2900/3125], Loss: 2.1660, Perplexity: 8.7234
|
| 580 |
+
Epoch 28 Training: 96%|█████████▌| 2999/3125 [53:15<02:13, 1.06s/it]
|
| 581 |
+
2025-06-11 05:55:42,755 - __main__ - INFO - Epoch [28/30], Step [3000/3125], Loss: 2.3245, Perplexity: 10.2219
|
| 582 |
+
Epoch 28 Training: 99%|█████████▉| 3099/3125 [55:01<00:27, 1.05s/it]
|
| 583 |
+
2025-06-11 05:57:28,701 - __main__ - INFO - Epoch [28/30], Step [3100/3125], Loss: 2.1882, Perplexity: 8.9189
|
| 584 |
+
Epoch 28 Training: 100%|██████████| 3125/3125 [55:29<00:00, 1.07s/it]
|
| 585 |
+
2025-06-11 05:57:55,002 - __main__ - INFO - Epoch 28 Training finished. Avg Loss: 2.1508, Time: 3329.03s
|
| 586 |
+
Validation: 100%|██████████| 391/391 [11:34<00:00, 1.78s/it]
|
| 587 |
+
2025-06-11 06:09:29,731 - __main__ - INFO - Validation Avg Loss: 2.5089, Perplexity: 12.2919
|
| 588 |
+
2025-06-11 06:09:38,926 - __main__ - INFO - Validation BLEU-4: 0.1039
|
| 589 |
+
2025-06-11 06:09:38,927 - __main__ - INFO - Performing memory optimization after epoch...
|
| 590 |
+
2025-06-11 06:09:39,197 - __main__ - INFO - CUDA cache emptied.
|
| 591 |
+
2025-06-11 06:09:39,519 - __main__ - INFO - Python garbage collector run.
|
| 592 |
+
Epoch 29 Training: 3%|▎ | 99/3125 [01:47<53:33, 1.06s/it]
|
| 593 |
+
2025-06-11 06:11:28,524 - __main__ - INFO - Epoch [29/30], Step [100/3125], Loss: 1.8376, Perplexity: 6.2816
|
| 594 |
+
Epoch 29 Training: 6%|▋ | 199/3125 [03:34<50:54, 1.04s/it]
|
| 595 |
+
2025-06-11 06:13:14,677 - __main__ - INFO - Epoch [29/30], Step [200/3125], Loss: 2.0208, Perplexity: 7.5444
|
| 596 |
+
Epoch 29 Training: 10%|▉ | 299/3125 [05:20<49:39, 1.05s/it]
|
| 597 |
+
2025-06-11 06:15:00,766 - __main__ - INFO - Epoch [29/30], Step [300/3125], Loss: 2.4057, Perplexity: 11.0859
|
| 598 |
+
Epoch 29 Training: 13%|█▎ | 399/3125 [07:05<47:27, 1.04s/it]
|
| 599 |
+
2025-06-11 06:16:46,520 - __main__ - INFO - Epoch [29/30], Step [400/3125], Loss: 1.9454, Perplexity: 6.9966
|
| 600 |
+
Epoch 29 Training: 16%|█▌ | 499/3125 [08:51<45:58, 1.05s/it]
|
| 601 |
+
2025-06-11 06:18:32,435 - __main__ - INFO - Epoch [29/30], Step [500/3125], Loss: 2.0933, Perplexity: 8.1118
|
| 602 |
+
Epoch 29 Training: 19%|█▉ | 599/3125 [10:37<44:17, 1.05s/it]
|
| 603 |
+
2025-06-11 06:20:18,117 - __main__ - INFO - Epoch [29/30], Step [600/3125], Loss: 2.1162, Perplexity: 8.2996
|
| 604 |
+
Epoch 29 Training: 22%|██▏ | 699/3125 [12:23<43:03, 1.06s/it]
|
| 605 |
+
2025-06-11 06:22:03,917 - __main__ - INFO - Epoch [29/30], Step [700/3125], Loss: 2.0233, Perplexity: 7.5629
|
| 606 |
+
Epoch 29 Training: 26%|██▌ | 799/3125 [14:08<41:18, 1.07s/it]
|
| 607 |
+
2025-06-11 06:23:49,332 - __main__ - INFO - Epoch [29/30], Step [800/3125], Loss: 2.1161, Perplexity: 8.2987
|
| 608 |
+
Epoch 29 Training: 29%|██▉ | 899/3125 [15:54<39:17, 1.06s/it]
|
| 609 |
+
2025-06-11 06:25:35,462 - __main__ - INFO - Epoch [29/30], Step [900/3125], Loss: 2.3258, Perplexity: 10.2354
|
| 610 |
+
Epoch 29 Training: 32%|███▏ | 999/3125 [17:40<37:19, 1.05s/it]
|
| 611 |
+
2025-06-11 06:27:21,095 - __main__ - INFO - Epoch [29/30], Step [1000/3125], Loss: 2.0303, Perplexity: 7.6167
|
| 612 |
+
Epoch 29 Training: 35%|███▌ | 1099/3125 [19:26<35:34, 1.05s/it]
|
| 613 |
+
2025-06-11 06:29:07,024 - __main__ - INFO - Epoch [29/30], Step [1100/3125], Loss: 2.2297, Perplexity: 9.2970
|
| 614 |
+
Epoch 29 Training: 38%|███▊ | 1199/3125 [21:12<34:00, 1.06s/it]
|
| 615 |
+
2025-06-11 06:30:53,597 - __main__ - INFO - Epoch [29/30], Step [1200/3125], Loss: 2.1602, Perplexity: 8.6727
|
| 616 |
+
Epoch 29 Training: 42%|████▏ | 1299/3125 [22:58<32:18, 1.06s/it]
|
| 617 |
+
2025-06-11 06:32:39,350 - __main__ - INFO - Epoch [29/30], Step [1300/3125], Loss: 2.0937, Perplexity: 8.1153
|
| 618 |
+
Epoch 29 Training: 45%|████▍ | 1399/3125 [24:44<31:07, 1.08s/it]
|
| 619 |
+
2025-06-11 06:34:25,480 - __main__ - INFO - Epoch [29/30], Step [1400/3125], Loss: 2.1163, Perplexity: 8.3006
|
| 620 |
+
Epoch 29 Training: 48%|████▊ | 1499/3125 [26:30<28:14, 1.04s/it]
|
| 621 |
+
2025-06-11 06:36:10,724 - __main__ - INFO - Epoch [29/30], Step [1500/3125], Loss: 2.1770, Perplexity: 8.8202
|
| 622 |
+
Epoch 29 Training: 51%|█████ | 1599/3125 [28:16<26:56, 1.06s/it]
|
| 623 |
+
2025-06-11 06:37:56,930 - __main__ - INFO - Epoch [29/30], Step [1600/3125], Loss: 2.0694, Perplexity: 7.9199
|
| 624 |
+
Epoch 29 Training: 54%|█████▍ | 1699/3125 [30:01<24:52, 1.05s/it]
|
| 625 |
+
2025-06-11 06:39:42,561 - __main__ - INFO - Epoch [29/30], Step [1700/3125], Loss: 2.2901, Perplexity: 9.8764
|
| 626 |
+
Epoch 29 Training: 58%|█████▊ | 1799/3125 [31:48<23:39, 1.07s/it]
|
| 627 |
+
2025-06-11 06:41:28,770 - __main__ - INFO - Epoch [29/30], Step [1800/3125], Loss: 2.0297, Perplexity: 7.6121
|
| 628 |
+
Epoch 29 Training: 61%|██████ | 1899/3125 [33:33<21:21, 1.05s/it]
|
| 629 |
+
2025-06-11 06:43:13,871 - __main__ - INFO - Epoch [29/30], Step [1900/3125], Loss: 1.9835, Perplexity: 7.2681
|
| 630 |
+
Epoch 29 Training: 64%|██████▍ | 1999/3125 [35:18<19:36, 1.05s/it]
|
| 631 |
+
2025-06-11 06:44:59,278 - __main__ - INFO - Epoch [29/30], Step [2000/3125], Loss: 2.1101, Perplexity: 8.2492
|
| 632 |
+
Epoch 29 Training: 67%|██████▋ | 2099/3125 [37:04<17:57, 1.05s/it]
|
| 633 |
+
2025-06-11 06:46:45,203 - __main__ - INFO - Epoch [29/30], Step [2100/3125], Loss: 2.0714, Perplexity: 7.9361
|
| 634 |
+
Epoch 29 Training: 70%|███████ | 2199/3125 [38:50<16:17, 1.06s/it]
|
| 635 |
+
2025-06-11 06:48:30,789 - __main__ - INFO - Epoch [29/30], Step [2200/3125], Loss: 2.3346, Perplexity: 10.3258
|
| 636 |
+
Epoch 29 Training: 74%|███████▎ | 2299/3125 [40:36<14:44, 1.07s/it]
|
| 637 |
+
2025-06-11 06:50:16,941 - __main__ - INFO - Epoch [29/30], Step [2300/3125], Loss: 2.1250, Perplexity: 8.3732
|
| 638 |
+
Epoch 29 Training: 77%|███████▋ | 2399/3125 [42:22<12:51, 1.06s/it]
|
| 639 |
+
2025-06-11 06:52:02,985 - __main__ - INFO - Epoch [29/30], Step [2400/3125], Loss: 2.2709, Perplexity: 9.6881
|
| 640 |
+
Epoch 29 Training: 80%|███████▉ | 2499/3125 [44:08<10:55, 1.05s/it]
|
| 641 |
+
2025-06-11 06:53:49,065 - __main__ - INFO - Epoch [29/30], Step [2500/3125], Loss: 2.1652, Perplexity: 8.7159
|
| 642 |
+
Epoch 29 Training: 83%|████████▎ | 2599/3125 [45:54<09:09, 1.05s/it]
|
| 643 |
+
2025-06-11 06:55:35,402 - __main__ - INFO - Epoch [29/30], Step [2600/3125], Loss: 2.4139, Perplexity: 11.1778
|
| 644 |
+
Epoch 29 Training: 86%|████████▋ | 2699/3125 [47:40<07:31, 1.06s/it]
|
| 645 |
+
2025-06-11 06:57:21,309 - __main__ - INFO - Epoch [29/30], Step [2700/3125], Loss: 2.1402, Perplexity: 8.5011
|
| 646 |
+
Epoch 29 Training: 90%|████████▉ | 2799/3125 [49:26<05:43, 1.05s/it]
|
| 647 |
+
2025-06-11 06:59:07,135 - __main__ - INFO - Epoch [29/30], Step [2800/3125], Loss: 2.0135, Perplexity: 7.4895
|
| 648 |
+
Epoch 29 Training: 93%|█████████▎| 2899/3125 [51:12<03:56, 1.05s/it]
|
| 649 |
+
2025-06-11 07:00:52,852 - __main__ - INFO - Epoch [29/30], Step [2900/3125], Loss: 2.1379, Perplexity: 8.4812
|
| 650 |
+
Epoch 29 Training: 96%|█████████▌| 2999/3125 [52:58<02:17, 1.09s/it]
|
| 651 |
+
2025-06-11 07:02:39,118 - __main__ - INFO - Epoch [29/30], Step [3000/3125], Loss: 2.2424, Perplexity: 9.4156
|
| 652 |
+
Epoch 29 Training: 99%|█████████▉| 3099/3125 [54:44<00:27, 1.05s/it]
|
| 653 |
+
2025-06-11 07:04:24,904 - __main__ - INFO - Epoch [29/30], Step [3100/3125], Loss: 2.1572, Perplexity: 8.6465
|
| 654 |
+
Epoch 29 Training: 100%|██████████| 3125/3125 [55:11<00:00, 1.06s/it]
|
| 655 |
+
2025-06-11 07:04:51,485 - __main__ - INFO - Epoch 29 Training finished. Avg Loss: 2.1306, Time: 3311.96s
|
| 656 |
+
Validation: 100%|██████████| 391/391 [11:46<00:00, 1.81s/it]
|
| 657 |
+
2025-06-11 07:16:38,260 - __main__ - INFO - Validation Avg Loss: 2.5210, Perplexity: 12.4409
|
| 658 |
+
2025-06-11 07:16:47,455 - __main__ - INFO - Validation BLEU-4: 0.1032
|
| 659 |
+
2025-06-11 07:16:47,456 - __main__ - INFO - Performing memory optimization after epoch...
|
| 660 |
+
2025-06-11 07:16:47,750 - __main__ - INFO - CUDA cache emptied.
|
| 661 |
+
2025-06-11 07:16:48,102 - __main__ - INFO - Python garbage collector run.
|
| 662 |
+
Epoch 30 Training: 3%|▎ | 99/3125 [01:47<52:54, 1.05s/it]
|
| 663 |
+
2025-06-11 07:18:36,828 - __main__ - INFO - Epoch [30/30], Step [100/3125], Loss: 2.1938, Perplexity: 8.9692
|
| 664 |
+
Epoch 30 Training: 6%|▋ | 199/3125 [03:34<51:39, 1.06s/it]
|
| 665 |
+
2025-06-11 07:20:23,162 - __main__ - INFO - Epoch [30/30], Step [200/3125], Loss: 2.1014, Perplexity: 8.1780
|
| 666 |
+
Epoch 30 Training: 10%|▉ | 299/3125 [05:19<49:32, 1.05s/it]
|
| 667 |
+
2025-06-11 07:22:08,720 - __main__ - INFO - Epoch [30/30], Step [300/3125], Loss: 2.2413, Perplexity: 9.4058
|
| 668 |
+
Epoch 30 Training: 13%|█▎ | 399/3125 [07:05<48:04, 1.06s/it]
|
| 669 |
+
2025-06-11 07:23:54,826 - __main__ - INFO - Epoch [30/30], Step [400/3125], Loss: 2.0270, Perplexity: 7.5915
|
| 670 |
+
Epoch 30 Training: 16%|█▌ | 499/3125 [08:51<46:34, 1.06s/it]
|
| 671 |
+
2025-06-11 07:25:40,842 - __main__ - INFO - Epoch [30/30], Step [500/3125], Loss: 1.9092, Perplexity: 6.7479
|
| 672 |
+
Epoch 30 Training: 19%|█▉ | 599/3125 [10:37<44:13, 1.05s/it]
|
| 673 |
+
2025-06-11 07:27:26,885 - __main__ - INFO - Epoch [30/30], Step [600/3125], Loss: 2.1688, Perplexity: 8.7480
|
| 674 |
+
Epoch 30 Training: 22%|██▏ | 699/3125 [12:23<44:03, 1.09s/it]
|
| 675 |
+
2025-06-11 07:29:13,137 - __main__ - INFO - Epoch [30/30], Step [700/3125], Loss: 2.1492, Perplexity: 8.5776
|
| 676 |
+
Epoch 30 Training: 26%|██▌ | 799/3125 [14:10<41:12, 1.06s/it]
|
| 677 |
+
2025-06-11 07:30:59,160 - __main__ - INFO - Epoch [30/30], Step [800/3125], Loss: 2.1651, Perplexity: 8.7158
|
| 678 |
+
Epoch 30 Training: 29%|██▉ | 899/3125 [15:55<39:10, 1.06s/it]
|
| 679 |
+
2025-06-11 07:32:44,756 - __main__ - INFO - Epoch [30/30], Step [900/3125], Loss: 2.0124, Perplexity: 7.4812
|
| 680 |
+
Epoch 30 Training: 32%|███▏ | 999/3125 [17:41<37:03, 1.05s/it]
|
| 681 |
+
2025-06-11 07:34:30,665 - __main__ - INFO - Epoch [30/30], Step [1000/3125], Loss: 2.3341, Perplexity: 10.3199
|
| 682 |
+
Epoch 30 Training: 35%|███▌ | 1099/3125 [19:27<35:36, 1.05s/it]
|
| 683 |
+
2025-06-11 07:36:16,441 - __main__ - INFO - Epoch [30/30], Step [1100/3125], Loss: 2.0736, Perplexity: 7.9533
|
| 684 |
+
Epoch 30 Training: 38%|███▊ | 1199/3125 [21:13<34:42, 1.08s/it]
|
| 685 |
+
2025-06-11 07:38:02,427 - __main__ - INFO - Epoch [30/30], Step [1200/3125], Loss: 2.2919, Perplexity: 9.8934
|
| 686 |
+
Epoch 30 Training: 42%|████▏ | 1299/3125 [22:59<32:05, 1.05s/it]
|
| 687 |
+
2025-06-11 07:39:48,493 - __main__ - INFO - Epoch [30/30], Step [1300/3125], Loss: 1.8976, Perplexity: 6.6700
|
| 688 |
+
Epoch 30 Training: 45%|████▍ | 1399/3125 [24:45<30:39, 1.07s/it]
|
| 689 |
+
2025-06-11 07:41:34,729 - __main__ - INFO - Epoch [30/30], Step [1400/3125], Loss: 2.1037, Perplexity: 8.1963
|
| 690 |
+
Epoch 30 Training: 48%|████▊ | 1499/3125 [26:31<28:54, 1.07s/it]
|
| 691 |
+
2025-06-11 07:43:20,236 - __main__ - INFO - Epoch [30/30], Step [1500/3125], Loss: 1.9812, Perplexity: 7.2515
|
| 692 |
+
Epoch 30 Training: 51%|█████ | 1599/3125 [28:16<26:55, 1.06s/it]
|
| 693 |
+
2025-06-11 07:45:05,806 - __main__ - INFO - Epoch [30/30], Step [1600/3125], Loss: 1.8422, Perplexity: 6.3105
|
| 694 |
+
Epoch 30 Training: 54%|█████▍ | 1699/3125 [30:01<24:47, 1.04s/it]
|
| 695 |
+
2025-06-11 07:46:51,077 - __main__ - INFO - Epoch [30/30], Step [1700/3125], Loss: 2.1148, Perplexity: 8.2879
|
| 696 |
+
Epoch 30 Training: 58%|█████▊ | 1799/3125 [31:47<23:33, 1.07s/it]
|
| 697 |
+
2025-06-11 07:48:36,971 - __main__ - INFO - Epoch [30/30], Step [1800/3125], Loss: 2.0392, Perplexity: 7.6841
|
| 698 |
+
Epoch 30 Training: 61%|██████ | 1899/3125 [33:33<21:36, 1.06s/it]
|
| 699 |
+
2025-06-11 07:50:22,901 - __main__ - INFO - Epoch [30/30], Step [1900/3125], Loss: 2.1974, Perplexity: 9.0015
|
| 700 |
+
Epoch 30 Training: 64%|██████▍ | 1999/3125 [35:20<20:00, 1.07s/it]
|
| 701 |
+
2025-06-11 07:52:09,317 - __main__ - INFO - Epoch [30/30], Step [2000/3125], Loss: 1.9900, Perplexity: 7.3157
|
| 702 |
+
Epoch 30 Training: 67%|██████▋ | 2099/3125 [37:06<18:26, 1.08s/it]
|
| 703 |
+
2025-06-11 07:53:55,343 - __main__ - INFO - Epoch [30/30], Step [2100/3125], Loss: 2.1626, Perplexity: 8.6936
|
| 704 |
+
Epoch 30 Training: 70%|███████ | 2199/3125 [38:51<16:06, 1.04s/it]
|
| 705 |
+
2025-06-11 07:55:40,879 - __main__ - INFO - Epoch [30/30], Step [2200/3125], Loss: 2.0304, Perplexity: 7.6174
|
| 706 |
+
Epoch 30 Training: 74%|███████▎ | 2299/3125 [40:37<14:34, 1.06s/it]
|
| 707 |
+
2025-06-11 07:57:26,744 - __main__ - INFO - Epoch [30/30], Step [2300/3125], Loss: 2.1228, Perplexity: 8.3543
|
| 708 |
+
Epoch 30 Training: 77%|███████▋ | 2399/3125 [42:22<12:59, 1.07s/it]
|
| 709 |
+
2025-06-11 07:59:12,098 - __main__ - INFO - Epoch [30/30], Step [2400/3125], Loss: 2.1954, Perplexity: 8.9837
|
| 710 |
+
Epoch 30 Training: 80%|███████▉ | 2499/3125 [44:08<10:49, 1.04s/it]
|
| 711 |
+
2025-06-11 08:00:57,947 - __main__ - INFO - Epoch [30/30], Step [2500/3125], Loss: 2.1629, Perplexity: 8.6964
|
| 712 |
+
Epoch 30 Training: 83%|████████▎ | 2599/3125 [45:55<09:26, 1.08s/it]
|
| 713 |
+
2025-06-11 08:02:44,387 - __main__ - INFO - Epoch [30/30], Step [2600/3125], Loss: 2.4293, Perplexity: 11.3511
|
| 714 |
+
Epoch 30 Training: 86%|████████▋ | 2699/3125 [47:41<07:26, 1.05s/it]
|
| 715 |
+
2025-06-11 08:04:30,330 - __main__ - INFO - Epoch [30/30], Step [2700/3125], Loss: 1.8879, Perplexity: 6.6057
|
| 716 |
+
Epoch 30 Training: 90%|████████▉ | 2799/3125 [49:27<05:51, 1.08s/it]
|
| 717 |
+
2025-06-11 08:06:16,399 - __main__ - INFO - Epoch [30/30], Step [2800/3125], Loss: 2.2829, Perplexity: 9.8055
|
| 718 |
+
Epoch 30 Training: 93%|█████████▎| 2899/3125 [51:13<04:01, 1.07s/it]
|
| 719 |
+
2025-06-11 08:08:02,721 - __main__ - INFO - Epoch [30/30], Step [2900/3125], Loss: 2.2601, Perplexity: 9.5845
|
| 720 |
+
Epoch 30 Training: 96%|█████████▌| 2999/3125 [53:00<02:13, 1.06s/it]
|
| 721 |
+
2025-06-11 08:09:49,266 - __main__ - INFO - Epoch [30/30], Step [3000/3125], Loss: 1.9881, Perplexity: 7.3020
|
| 722 |
+
Epoch 30 Training: 99%|█████████▉| 3099/3125 [54:46<00:27, 1.06s/it]
|
| 723 |
+
2025-06-11 08:11:35,190 - __main__ - INFO - Epoch [30/30], Step [3100/3125], Loss: 2.1743, Perplexity: 8.7960
|
| 724 |
+
Epoch 30 Training: 100%|██████████| 3125/3125 [55:13<00:00, 1.06s/it]
|
| 725 |
+
2025-06-11 08:12:01,688 - __main__ - INFO - Epoch 30 Training finished. Avg Loss: 2.1133, Time: 3313.58s
|
| 726 |
+
Validation: 100%|██████████| 391/391 [11:49<00:00, 1.81s/it]
|
| 727 |
+
2025-06-11 08:23:51,320 - __main__ - INFO - Validation Avg Loss: 2.5266, Perplexity: 12.5108
|
| 728 |
+
2025-06-11 08:24:00,605 - __main__ - INFO - Validation BLEU-4: 0.1039
|
| 729 |
+
2025-06-11 08:24:01,277 - __main__ - INFO - Saved periodic model checkpoint to ./output/model_epoch_30.pth
|
| 730 |
+
2025-06-11 08:24:01,278 - __main__ - INFO - Performing memory optimization after epoch...
|
| 731 |
+
2025-06-11 08:24:01,543 - __main__ - INFO - CUDA cache emptied.
|
| 732 |
+
2025-06-11 08:24:01,902 - __main__ - INFO - Python garbage collector run.
|
| 733 |
+
2025-06-11 08:24:01,904 - __main__ - INFO - Training complete.
|
| 734 |
+
2025-06-11 08:24:01,904 - __main__ - INFO - Model Training Complete!
|
text_files/training_metrics.csv
ADDED
|
@@ -0,0 +1,1190 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Epoch,Step,Loss,Perplexity
|
| 2 |
+
1,100,5.4706,237.609
|
| 3 |
+
1,200,5.1889,179.2651
|
| 4 |
+
1,300,4.7951,120.9148
|
| 5 |
+
1,400,4.1438,63.0419
|
| 6 |
+
1,500,4.0644,58.2316
|
| 7 |
+
1,600,4.1386,62.7179
|
| 8 |
+
1,700,4.4148,82.6655
|
| 9 |
+
1,800,4.0775,58.9954
|
| 10 |
+
1,900,3.8928,49.0485
|
| 11 |
+
1,1000,3.7069,40.7267
|
| 12 |
+
1,1100,3.7165,41.1201
|
| 13 |
+
1,1200,3.6987,40.396
|
| 14 |
+
1,1300,3.8443,46.7262
|
| 15 |
+
1,1400,3.7788,43.7654
|
| 16 |
+
1,1500,3.9427,51.5586
|
| 17 |
+
1,1600,3.9204,50.4209
|
| 18 |
+
1,1700,3.6418,38.16
|
| 19 |
+
1,1800,3.5172,33.6913
|
| 20 |
+
1,1900,3.6409,38.1244
|
| 21 |
+
1,2000,3.2969,27.0292
|
| 22 |
+
1,2100,3.4517,31.5544
|
| 23 |
+
1,2200,3.492,32.8529
|
| 24 |
+
1,2300,3.7028,40.5603
|
| 25 |
+
1,2400,3.6794,39.6238
|
| 26 |
+
1,2500,3.4977,33.0382
|
| 27 |
+
1,2600,3.4883,32.7311
|
| 28 |
+
1,2700,3.4596,31.8036
|
| 29 |
+
1,2800,3.4043,30.092
|
| 30 |
+
1,2900,3.1842,24.1488
|
| 31 |
+
1,3000,3.2843,26.6914
|
| 32 |
+
1,3100,3.195,24.41
|
| 33 |
+
2,100,3.1401,23.1065
|
| 34 |
+
2,200,3.0563,21.2493
|
| 35 |
+
2,300,3.2782,26.5282
|
| 36 |
+
2,400,3.1834,24.1295
|
| 37 |
+
2,500,3.3472,28.4244
|
| 38 |
+
2,600,3.1609,23.5928
|
| 39 |
+
2,700,2.9984,20.0538
|
| 40 |
+
2,800,3.2494,25.7758
|
| 41 |
+
2,900,3.1955,24.4232
|
| 42 |
+
2,1000,3.4101,30.2673
|
| 43 |
+
2,1100,3.3706,29.0971
|
| 44 |
+
2,1200,3.168,23.7608
|
| 45 |
+
2,1300,3.0362,20.8251
|
| 46 |
+
2,1400,3.0925,22.0321
|
| 47 |
+
2,1500,3.1057,22.3241
|
| 48 |
+
2,1600,3.3277,27.873
|
| 49 |
+
2,1700,3.161,23.5945
|
| 50 |
+
2,1800,3.2718,26.3582
|
| 51 |
+
2,1900,3.1425,23.1612
|
| 52 |
+
2,2000,3.0522,21.1619
|
| 53 |
+
2,2100,2.9711,19.5126
|
| 54 |
+
2,2200,3.0638,21.4079
|
| 55 |
+
2,2300,3.1867,24.2093
|
| 56 |
+
2,2400,3.006,20.207
|
| 57 |
+
2,2500,3.1718,23.8494
|
| 58 |
+
2,2600,3.0628,21.3874
|
| 59 |
+
2,2700,3.3898,29.6609
|
| 60 |
+
2,2800,2.7914,16.3038
|
| 61 |
+
2,2900,2.8758,17.7403
|
| 62 |
+
2,3000,3.0766,21.6847
|
| 63 |
+
2,3100,3.0787,21.7303
|
| 64 |
+
3,100,3.1375,23.0468
|
| 65 |
+
3,200,2.9503,19.1119
|
| 66 |
+
3,300,2.9096,18.3486
|
| 67 |
+
3,400,2.9213,18.5648
|
| 68 |
+
3,500,2.7807,16.1304
|
| 69 |
+
3,600,2.9757,19.6029
|
| 70 |
+
3,700,2.7691,15.9448
|
| 71 |
+
3,800,2.629,13.8597
|
| 72 |
+
3,900,2.7852,16.2028
|
| 73 |
+
3,1000,2.9282,18.6934
|
| 74 |
+
3,1100,3.0185,20.4607
|
| 75 |
+
3,1200,3.1393,23.0879
|
| 76 |
+
3,1300,2.9986,20.058
|
| 77 |
+
3,1400,2.849,17.2704
|
| 78 |
+
3,1500,3.1596,23.561
|
| 79 |
+
3,1600,2.9312,18.7505
|
| 80 |
+
3,1700,2.8247,16.8555
|
| 81 |
+
3,1800,2.9927,19.9386
|
| 82 |
+
3,1900,2.7951,16.3638
|
| 83 |
+
3,2000,2.8393,17.1032
|
| 84 |
+
3,2100,3.0383,20.8706
|
| 85 |
+
3,2200,3.158,23.5244
|
| 86 |
+
3,2300,2.9753,19.5955
|
| 87 |
+
3,2400,2.7754,16.0452
|
| 88 |
+
3,2500,2.5844,13.2559
|
| 89 |
+
3,2600,2.9575,19.249
|
| 90 |
+
3,2700,2.7714,15.9803
|
| 91 |
+
3,2800,2.6014,13.4829
|
| 92 |
+
3,2900,2.924,18.6159
|
| 93 |
+
3,3000,2.8361,17.0495
|
| 94 |
+
3,3100,2.9557,19.2145
|
| 95 |
+
4,100,2.8362,17.0513
|
| 96 |
+
4,200,2.5668,13.0241
|
| 97 |
+
4,300,2.7211,15.1978
|
| 98 |
+
4,400,2.9763,19.6153
|
| 99 |
+
4,500,2.7447,15.5594
|
| 100 |
+
4,600,2.6688,14.4227
|
| 101 |
+
4,700,2.756,15.737
|
| 102 |
+
4,800,2.7199,15.1782
|
| 103 |
+
4,900,2.9431,18.9745
|
| 104 |
+
4,1000,2.7849,16.1979
|
| 105 |
+
4,1100,2.6553,14.2291
|
| 106 |
+
4,1200,2.7191,15.1662
|
| 107 |
+
4,1300,2.7089,15.0125
|
| 108 |
+
4,1400,2.9824,19.7352
|
| 109 |
+
4,1500,2.7723,15.9946
|
| 110 |
+
4,1600,2.8024,16.4847
|
| 111 |
+
4,1700,2.7457,15.5758
|
| 112 |
+
4,1800,2.9873,19.8314
|
| 113 |
+
4,1900,2.6393,14.0032
|
| 114 |
+
4,2000,2.6532,14.1999
|
| 115 |
+
4,2100,2.7995,16.4372
|
| 116 |
+
4,2200,2.7488,15.6245
|
| 117 |
+
4,2300,2.8463,17.2242
|
| 118 |
+
4,2400,2.6901,14.7335
|
| 119 |
+
4,2500,2.889,17.9762
|
| 120 |
+
4,2600,2.6551,14.227
|
| 121 |
+
4,2700,2.8474,17.2437
|
| 122 |
+
4,2800,2.7218,15.2075
|
| 123 |
+
4,2900,2.6753,14.5169
|
| 124 |
+
4,3000,2.8698,17.6342
|
| 125 |
+
4,3100,2.5715,13.0854
|
| 126 |
+
5,100,2.7858,16.2124
|
| 127 |
+
5,200,2.5799,13.1955
|
| 128 |
+
5,300,2.7141,15.091
|
| 129 |
+
5,400,2.6322,13.9042
|
| 130 |
+
5,500,2.992,19.9248
|
| 131 |
+
5,600,2.5876,13.2972
|
| 132 |
+
5,700,2.6221,13.7644
|
| 133 |
+
5,800,2.5546,12.8666
|
| 134 |
+
5,900,2.7899,16.2789
|
| 135 |
+
5,1000,2.718,15.1505
|
| 136 |
+
5,1100,2.6338,13.9268
|
| 137 |
+
5,1200,2.9994,20.0732
|
| 138 |
+
5,1300,2.5138,12.3518
|
| 139 |
+
5,1400,2.7708,15.9718
|
| 140 |
+
5,1500,2.6756,14.5208
|
| 141 |
+
5,1600,2.6377,13.9804
|
| 142 |
+
5,1700,2.6101,13.6009
|
| 143 |
+
5,1800,2.6736,14.4918
|
| 144 |
+
5,1900,2.6328,13.9123
|
| 145 |
+
5,2000,2.5901,13.3318
|
| 146 |
+
5,2100,2.9779,19.6469
|
| 147 |
+
5,2200,2.5809,13.2096
|
| 148 |
+
5,2300,2.736,15.4247
|
| 149 |
+
5,2400,2.5268,12.5135
|
| 150 |
+
5,2500,2.8699,17.6357
|
| 151 |
+
5,2600,2.7812,16.1382
|
| 152 |
+
5,2700,2.654,14.2111
|
| 153 |
+
5,2800,2.6715,14.4612
|
| 154 |
+
5,2900,2.878,17.7783
|
| 155 |
+
5,3000,2.6441,14.0706
|
| 156 |
+
5,3100,2.6745,14.5049
|
| 157 |
+
6,100,2.9338,18.7981
|
| 158 |
+
6,200,2.746,15.5799
|
| 159 |
+
6,300,2.3894,10.9066
|
| 160 |
+
6,400,2.6891,14.7191
|
| 161 |
+
6,500,2.7032,14.9273
|
| 162 |
+
6,600,2.6848,14.6553
|
| 163 |
+
6,700,2.4991,12.1715
|
| 164 |
+
6,800,2.5794,13.1892
|
| 165 |
+
6,900,2.5044,12.2366
|
| 166 |
+
6,1000,2.6207,13.7448
|
| 167 |
+
6,1100,2.5424,12.7103
|
| 168 |
+
6,1200,2.554,12.8587
|
| 169 |
+
6,1300,2.5427,12.7145
|
| 170 |
+
6,1400,2.6368,13.9681
|
| 171 |
+
6,1500,2.5717,13.0879
|
| 172 |
+
6,1600,2.4953,12.1255
|
| 173 |
+
6,1700,2.73,15.3336
|
| 174 |
+
6,1800,2.6784,14.5613
|
| 175 |
+
6,1900,2.6738,14.4946
|
| 176 |
+
6,2000,2.6148,13.6649
|
| 177 |
+
6,2100,2.8018,16.4748
|
| 178 |
+
6,2200,2.6942,14.794
|
| 179 |
+
6,2300,2.4844,11.9935
|
| 180 |
+
6,2400,2.4125,11.1615
|
| 181 |
+
6,2500,2.5616,12.9564
|
| 182 |
+
6,2600,2.5049,12.2425
|
| 183 |
+
6,2700,2.4866,12.0206
|
| 184 |
+
6,2800,2.3411,10.3931
|
| 185 |
+
6,2900,2.6441,14.0713
|
| 186 |
+
6,3000,2.5855,13.2695
|
| 187 |
+
6,3100,2.7371,15.4419
|
| 188 |
+
7,100,2.6545,14.218
|
| 189 |
+
7,200,2.3907,10.9206
|
| 190 |
+
7,300,2.3964,10.9837
|
| 191 |
+
7,400,2.2917,9.8918
|
| 192 |
+
7,500,2.546,12.7565
|
| 193 |
+
7,600,2.7165,15.1276
|
| 194 |
+
7,700,2.316,10.135
|
| 195 |
+
7,800,2.4257,11.3097
|
| 196 |
+
7,900,2.8313,16.9669
|
| 197 |
+
7,1000,2.4841,11.9898
|
| 198 |
+
7,1100,2.4737,11.8667
|
| 199 |
+
7,1200,2.3904,10.9178
|
| 200 |
+
7,1300,2.4815,11.9595
|
| 201 |
+
7,1400,2.7324,15.3697
|
| 202 |
+
7,1500,2.7363,15.4298
|
| 203 |
+
7,1600,2.7751,16.0397
|
| 204 |
+
7,1700,2.5598,12.9329
|
| 205 |
+
7,1800,2.7369,15.4388
|
| 206 |
+
7,1900,2.8117,16.6374
|
| 207 |
+
7,2000,2.636,13.9572
|
| 208 |
+
7,2100,2.4383,11.4533
|
| 209 |
+
7,2200,2.7142,15.0932
|
| 210 |
+
7,2300,2.459,11.6927
|
| 211 |
+
7,2400,2.6457,14.0935
|
| 212 |
+
7,2500,2.6708,14.4518
|
| 213 |
+
7,2600,2.5663,13.0179
|
| 214 |
+
7,2700,2.802,16.4769
|
| 215 |
+
7,2800,2.6069,13.5576
|
| 216 |
+
7,2900,2.5213,12.4453
|
| 217 |
+
7,3000,2.5426,12.7128
|
| 218 |
+
7,3100,2.6069,13.5576
|
| 219 |
+
8,100,2.5949,13.3954
|
| 220 |
+
8,200,2.3867,10.8772
|
| 221 |
+
8,300,2.4636,11.7471
|
| 222 |
+
8,400,2.5906,13.3381
|
| 223 |
+
8,500,2.5785,13.1772
|
| 224 |
+
8,600,2.5902,13.333
|
| 225 |
+
8,700,2.6504,14.1599
|
| 226 |
+
8,800,2.5812,13.2125
|
| 227 |
+
8,900,2.3477,10.4617
|
| 228 |
+
8,1000,2.5416,12.7004
|
| 229 |
+
8,1100,2.5581,12.9117
|
| 230 |
+
8,1200,2.6781,14.5574
|
| 231 |
+
8,1300,2.4678,11.7967
|
| 232 |
+
8,1400,2.7964,16.3863
|
| 233 |
+
8,1500,2.5617,12.9583
|
| 234 |
+
8,1600,2.4647,11.7597
|
| 235 |
+
8,1700,2.5186,12.4108
|
| 236 |
+
8,1800,2.7458,15.5764
|
| 237 |
+
8,1900,2.4218,11.2661
|
| 238 |
+
8,2000,2.4996,12.1774
|
| 239 |
+
8,2100,2.4715,11.84
|
| 240 |
+
8,2200,2.7304,15.3395
|
| 241 |
+
8,2300,2.6088,13.5826
|
| 242 |
+
8,2400,2.2952,9.9266
|
| 243 |
+
8,2500,2.6801,14.5865
|
| 244 |
+
8,2600,2.6453,14.0877
|
| 245 |
+
8,2700,2.498,12.1576
|
| 246 |
+
8,2800,2.4855,12.0065
|
| 247 |
+
8,2900,2.7647,15.8748
|
| 248 |
+
8,3000,2.3954,10.9722
|
| 249 |
+
8,3100,2.5672,13.0291
|
| 250 |
+
9,100,2.4885,12.0428
|
| 251 |
+
9,200,2.4464,11.5461
|
| 252 |
+
9,300,2.5567,12.8926
|
| 253 |
+
9,400,2.5434,12.7234
|
| 254 |
+
9,500,2.4282,11.338
|
| 255 |
+
9,600,2.4907,12.0691
|
| 256 |
+
9,700,2.5079,12.2789
|
| 257 |
+
9,800,2.4735,11.8636
|
| 258 |
+
9,900,2.5014,12.2001
|
| 259 |
+
9,1000,2.7705,15.9662
|
| 260 |
+
9,1100,2.6952,14.8082
|
| 261 |
+
10,100,2.6771,14.5422
|
| 262 |
+
10,200,2.5936,13.3779
|
| 263 |
+
10,300,2.731,15.3478
|
| 264 |
+
10,400,2.96,19.2978
|
| 265 |
+
10,500,2.6822,14.6177
|
| 266 |
+
10,600,2.7823,16.1564
|
| 267 |
+
10,700,2.5442,12.7334
|
| 268 |
+
10,800,2.6036,13.512
|
| 269 |
+
10,900,2.46,11.7049
|
| 270 |
+
10,1000,2.8091,16.5947
|
| 271 |
+
10,1100,2.668,14.4108
|
| 272 |
+
10,1200,2.708,14.9991
|
| 273 |
+
10,1300,2.6393,14.0032
|
| 274 |
+
10,1400,2.722,15.2114
|
| 275 |
+
10,1500,2.9185,18.5139
|
| 276 |
+
10,1600,2.7292,15.3205
|
| 277 |
+
10,1700,2.7339,15.3932
|
| 278 |
+
10,1800,2.4978,12.1557
|
| 279 |
+
10,1900,2.5602,12.9386
|
| 280 |
+
10,2000,2.6032,13.5067
|
| 281 |
+
10,2100,2.6049,13.5293
|
| 282 |
+
10,2200,2.8925,18.039
|
| 283 |
+
10,2300,2.6391,14.0
|
| 284 |
+
10,2400,2.6457,14.0939
|
| 285 |
+
10,2500,2.6442,14.0721
|
| 286 |
+
10,2600,2.5336,12.5989
|
| 287 |
+
10,2700,2.6224,13.7686
|
| 288 |
+
10,2800,2.5839,13.2486
|
| 289 |
+
10,2900,2.5405,12.6863
|
| 290 |
+
10,3000,2.7648,15.8761
|
| 291 |
+
10,3100,2.7951,16.3647
|
| 292 |
+
11,100,2.3691,10.6873
|
| 293 |
+
11,200,2.4723,11.8502
|
| 294 |
+
11,300,2.5049,12.242
|
| 295 |
+
11,400,2.5821,13.2247
|
| 296 |
+
11,500,2.9378,18.875
|
| 297 |
+
11,600,2.4629,11.7391
|
| 298 |
+
11,700,2.6155,13.6746
|
| 299 |
+
11,800,2.4537,11.6314
|
| 300 |
+
11,900,2.4852,12.003
|
| 301 |
+
11,1000,2.6182,13.7113
|
| 302 |
+
11,1100,2.3901,10.915
|
| 303 |
+
11,1200,2.6152,13.6705
|
| 304 |
+
11,1300,2.7108,15.042
|
| 305 |
+
11,1400,2.5307,12.5626
|
| 306 |
+
11,1500,2.541,12.6921
|
| 307 |
+
11,1600,2.5365,12.6349
|
| 308 |
+
11,1700,2.8819,17.8483
|
| 309 |
+
11,1800,2.5707,13.0754
|
| 310 |
+
11,1900,2.4161,11.2024
|
| 311 |
+
11,2000,2.5705,13.0728
|
| 312 |
+
11,2100,2.4674,11.7918
|
| 313 |
+
11,2200,2.5938,13.3808
|
| 314 |
+
11,2300,2.6236,13.7849
|
| 315 |
+
11,2400,2.3626,10.6186
|
| 316 |
+
11,2500,2.7776,16.08
|
| 317 |
+
11,2600,2.3201,10.1771
|
| 318 |
+
11,2700,2.7016,14.904
|
| 319 |
+
11,2800,2.5685,13.0467
|
| 320 |
+
11,2900,2.5174,12.3969
|
| 321 |
+
11,3000,2.4016,11.0412
|
| 322 |
+
11,3100,2.7063,14.9733
|
| 323 |
+
12,100,2.4403,11.477
|
| 324 |
+
12,200,2.3241,10.2174
|
| 325 |
+
12,300,2.3308,10.2864
|
| 326 |
+
12,400,2.5223,12.4575
|
| 327 |
+
12,500,2.4984,12.1631
|
| 328 |
+
12,600,2.4451,11.5312
|
| 329 |
+
12,700,2.379,10.7946
|
| 330 |
+
12,800,2.3688,10.6844
|
| 331 |
+
12,900,2.5906,13.3372
|
| 332 |
+
12,1000,2.529,12.5412
|
| 333 |
+
12,1100,2.3719,10.7179
|
| 334 |
+
12,1200,2.5641,12.9886
|
| 335 |
+
12,1300,2.5392,12.6697
|
| 336 |
+
12,1400,2.6697,14.4351
|
| 337 |
+
12,1500,2.3967,10.987
|
| 338 |
+
12,1600,2.6011,13.478
|
| 339 |
+
12,1700,2.5272,12.5179
|
| 340 |
+
12,1800,2.3498,10.4834
|
| 341 |
+
12,1900,2.8234,16.8332
|
| 342 |
+
12,2000,2.1771,8.8204
|
| 343 |
+
12,2100,2.3431,10.4136
|
| 344 |
+
12,2200,2.6427,14.0514
|
| 345 |
+
12,2300,2.4172,11.2148
|
| 346 |
+
12,2400,2.7323,15.3679
|
| 347 |
+
12,2500,2.7351,15.4109
|
| 348 |
+
12,2600,2.4624,11.7333
|
| 349 |
+
12,2700,2.4864,12.018
|
| 350 |
+
12,2800,2.7285,15.3102
|
| 351 |
+
12,2900,2.298,9.9542
|
| 352 |
+
12,3000,2.5476,12.7761
|
| 353 |
+
12,3100,2.3022,9.9965
|
| 354 |
+
13,100,2.4482,11.5679
|
| 355 |
+
13,200,2.4197,11.2422
|
| 356 |
+
13,300,2.6092,13.5885
|
| 357 |
+
13,400,2.3414,10.3956
|
| 358 |
+
13,500,2.321,10.1858
|
| 359 |
+
13,600,2.3739,10.7388
|
| 360 |
+
13,700,2.5507,12.8167
|
| 361 |
+
13,800,2.4497,11.5848
|
| 362 |
+
13,900,2.4555,11.6527
|
| 363 |
+
13,1000,2.2727,9.7054
|
| 364 |
+
13,1100,2.4161,11.2025
|
| 365 |
+
13,1200,2.5078,12.2775
|
| 366 |
+
13,1300,2.3249,10.2256
|
| 367 |
+
13,1400,2.4165,11.2065
|
| 368 |
+
13,1500,2.6065,13.5516
|
| 369 |
+
13,1600,2.4175,11.2178
|
| 370 |
+
13,1700,2.6172,13.6977
|
| 371 |
+
13,1800,2.6982,14.8536
|
| 372 |
+
13,1900,2.5895,13.3233
|
| 373 |
+
13,2000,2.3281,10.2589
|
| 374 |
+
13,2100,2.4475,11.5592
|
| 375 |
+
13,2200,2.3961,10.9799
|
| 376 |
+
13,2300,2.2835,9.8108
|
| 377 |
+
13,2400,2.4577,11.6781
|
| 378 |
+
13,2500,2.4646,11.7588
|
| 379 |
+
13,2600,2.4594,11.6975
|
| 380 |
+
13,2700,2.1887,8.9235
|
| 381 |
+
13,2800,2.3643,10.6365
|
| 382 |
+
13,2900,2.3395,10.3765
|
| 383 |
+
13,3000,2.6757,14.5222
|
| 384 |
+
13,3100,2.3261,10.2375
|
| 385 |
+
14,100,2.2691,9.6705
|
| 386 |
+
14,200,2.2401,9.394
|
| 387 |
+
14,300,2.2769,9.7467
|
| 388 |
+
14,400,2.3194,10.1698
|
| 389 |
+
14,500,2.3454,10.4371
|
| 390 |
+
14,600,2.3314,10.2923
|
| 391 |
+
14,700,2.1478,8.5664
|
| 392 |
+
14,800,2.4812,11.9557
|
| 393 |
+
14,900,2.5592,12.9257
|
| 394 |
+
14,1000,2.4252,11.305
|
| 395 |
+
14,1100,2.428,11.3366
|
| 396 |
+
14,1200,2.2805,9.7818
|
| 397 |
+
14,1300,2.3755,10.756
|
| 398 |
+
14,1400,2.4423,11.4991
|
| 399 |
+
14,1500,2.7027,14.9202
|
| 400 |
+
14,1600,2.5307,12.5619
|
| 401 |
+
14,1700,2.6793,14.5745
|
| 402 |
+
14,1800,2.3497,10.4828
|
| 403 |
+
14,1900,2.2267,9.2696
|
| 404 |
+
14,2000,2.1601,8.6721
|
| 405 |
+
14,2100,2.3438,10.4212
|
| 406 |
+
14,2200,2.3716,10.714
|
| 407 |
+
14,2300,2.4434,11.5116
|
| 408 |
+
14,2400,2.5465,12.7625
|
| 409 |
+
14,2500,2.2639,9.6206
|
| 410 |
+
14,2600,2.4817,11.9613
|
| 411 |
+
14,2700,2.5853,13.2677
|
| 412 |
+
14,2800,2.466,11.7758
|
| 413 |
+
14,2900,2.219,9.1977
|
| 414 |
+
14,3000,2.3681,10.6775
|
| 415 |
+
14,3100,2.3602,10.593
|
| 416 |
+
15,100,2.4716,11.8419
|
| 417 |
+
15,200,2.2404,9.3972
|
| 418 |
+
15,300,2.2223,9.2283
|
| 419 |
+
15,400,2.2692,9.6715
|
| 420 |
+
15,500,2.3727,10.7258
|
| 421 |
+
15,600,2.368,10.6762
|
| 422 |
+
15,700,2.2971,9.945
|
| 423 |
+
15,800,2.2048,9.068
|
| 424 |
+
15,900,2.6075,13.5645
|
| 425 |
+
15,1000,2.4252,11.3049
|
| 426 |
+
15,1100,2.4678,11.7969
|
| 427 |
+
15,1200,2.477,11.9052
|
| 428 |
+
15,1300,2.6406,14.022
|
| 429 |
+
15,1400,2.5408,12.6903
|
| 430 |
+
15,1500,2.2871,9.8462
|
| 431 |
+
15,1600,2.2426,9.4179
|
| 432 |
+
15,1700,2.4471,11.5546
|
| 433 |
+
15,1800,2.2109,9.1242
|
| 434 |
+
15,1900,2.2128,9.1415
|
| 435 |
+
15,2000,2.4859,12.0115
|
| 436 |
+
15,2100,2.1893,8.929
|
| 437 |
+
15,2200,2.3444,10.4273
|
| 438 |
+
15,2300,2.3961,10.9804
|
| 439 |
+
15,2400,2.4591,11.6937
|
| 440 |
+
15,2500,2.3786,10.7898
|
| 441 |
+
15,2600,2.2436,9.4268
|
| 442 |
+
15,2700,2.5708,13.0756
|
| 443 |
+
15,2800,2.3898,10.9116
|
| 444 |
+
15,2900,2.4656,11.7705
|
| 445 |
+
15,3000,2.3119,10.0933
|
| 446 |
+
15,3100,2.3714,10.7121
|
| 447 |
+
16,100,2.3317,10.2956
|
| 448 |
+
16,200,2.3495,10.4806
|
| 449 |
+
16,300,2.2306,9.3058
|
| 450 |
+
16,400,2.3325,10.3034
|
| 451 |
+
16,500,2.1694,8.7528
|
| 452 |
+
16,600,2.3946,10.9643
|
| 453 |
+
16,700,2.3674,10.67
|
| 454 |
+
16,800,2.0632,7.8708
|
| 455 |
+
16,900,2.294,9.9146
|
| 456 |
+
16,1000,2.2395,9.3891
|
| 457 |
+
16,1100,2.4083,11.115
|
| 458 |
+
16,1200,2.3857,10.8667
|
| 459 |
+
16,1300,2.3296,10.2736
|
| 460 |
+
16,1400,2.1133,8.2756
|
| 461 |
+
16,1500,2.3756,10.7575
|
| 462 |
+
16,1600,2.3544,10.5314
|
| 463 |
+
16,1700,2.3411,10.3928
|
| 464 |
+
16,1800,2.2282,9.2828
|
| 465 |
+
16,1900,2.3572,10.5609
|
| 466 |
+
16,2000,2.265,9.6316
|
| 467 |
+
16,2100,2.4694,11.8158
|
| 468 |
+
16,2200,2.2784,9.7614
|
| 469 |
+
16,2300,2.3814,10.8201
|
| 470 |
+
16,2400,2.3831,10.8388
|
| 471 |
+
16,2500,2.2298,9.2982
|
| 472 |
+
16,2600,2.4608,11.7146
|
| 473 |
+
16,2700,2.4152,11.1916
|
| 474 |
+
16,2800,2.486,12.0134
|
| 475 |
+
16,2900,2.162,8.6885
|
| 476 |
+
16,3000,2.6663,14.3864
|
| 477 |
+
16,3100,2.514,12.3541
|
| 478 |
+
17,100,2.1717,8.773
|
| 479 |
+
17,100,2.3526,10.5128
|
| 480 |
+
17,200,2.2953,9.9273
|
| 481 |
+
17,200,2.4604,11.709
|
| 482 |
+
17,300,2.1929,8.9608
|
| 483 |
+
17,300,2.576,13.1449
|
| 484 |
+
17,400,2.1077,8.2291
|
| 485 |
+
17,400,2.5386,12.6615
|
| 486 |
+
17,500,2.3065,10.0394
|
| 487 |
+
17,500,2.4724,11.8508
|
| 488 |
+
17,600,2.0144,7.4962
|
| 489 |
+
17,600,3.0153,20.3955
|
| 490 |
+
17,700,2.4351,11.4164
|
| 491 |
+
17,700,2.6407,14.0232
|
| 492 |
+
17,800,2.3415,10.3965
|
| 493 |
+
17,800,2.5756,13.1391
|
| 494 |
+
17,900,2.1439,8.5324
|
| 495 |
+
17,900,2.205,9.0706
|
| 496 |
+
17,1000,2.4303,11.3623
|
| 497 |
+
17,1000,2.3957,10.9755
|
| 498 |
+
17,1100,2.2407,9.3998
|
| 499 |
+
17,1100,2.2961,9.9352
|
| 500 |
+
17,1200,2.266,9.6408
|
| 501 |
+
17,1200,2.2552,9.5371
|
| 502 |
+
17,1300,2.2952,9.9262
|
| 503 |
+
17,1300,2.5,12.1825
|
| 504 |
+
17,1400,2.4064,11.0944
|
| 505 |
+
17,1400,2.7185,15.1579
|
| 506 |
+
17,1500,2.5295,12.5467
|
| 507 |
+
17,1500,2.5459,12.7545
|
| 508 |
+
17,1600,2.1637,8.703
|
| 509 |
+
17,1600,2.3916,10.9307
|
| 510 |
+
17,1700,2.3608,10.5998
|
| 511 |
+
17,1700,2.5494,12.7994
|
| 512 |
+
17,1800,2.1197,8.3285
|
| 513 |
+
17,1800,2.4654,11.7682
|
| 514 |
+
17,1900,2.2632,9.6134
|
| 515 |
+
17,1900,2.6649,14.3659
|
| 516 |
+
17,2000,2.0741,7.9572
|
| 517 |
+
17,2000,2.2949,9.9233
|
| 518 |
+
17,2100,2.2237,9.2414
|
| 519 |
+
17,2100,2.6354,13.9489
|
| 520 |
+
17,2200,2.1895,8.9311
|
| 521 |
+
17,2200,2.5667,13.0228
|
| 522 |
+
17,2300,2.3708,10.7057
|
| 523 |
+
17,2300,2.4153,11.1936
|
| 524 |
+
17,2400,2.2712,9.6909
|
| 525 |
+
17,2400,2.5093,12.2963
|
| 526 |
+
17,2500,2.3275,10.2521
|
| 527 |
+
17,2500,2.3697,10.6938
|
| 528 |
+
17,2600,2.1308,8.4219
|
| 529 |
+
17,2600,2.5674,13.032
|
| 530 |
+
17,2700,2.3833,10.8407
|
| 531 |
+
17,2700,2.4103,11.1374
|
| 532 |
+
17,2800,2.4461,11.543
|
| 533 |
+
17,2800,2.4239,11.2903
|
| 534 |
+
17,2900,2.06,7.8457
|
| 535 |
+
17,2900,2.6061,13.5467
|
| 536 |
+
17,3000,2.2095,9.1108
|
| 537 |
+
17,3000,2.3188,10.1634
|
| 538 |
+
17,3100,2.0986,8.1547
|
| 539 |
+
17,3100,2.3833,10.8402
|
| 540 |
+
18,100,2.1066,8.2205
|
| 541 |
+
18,100,2.5242,12.4803
|
| 542 |
+
18,200,2.1505,8.5893
|
| 543 |
+
18,200,2.5674,13.0321
|
| 544 |
+
18,300,2.228,9.2809
|
| 545 |
+
18,300,2.4194,11.2394
|
| 546 |
+
18,400,2.2427,9.4188
|
| 547 |
+
18,400,2.8139,16.6747
|
| 548 |
+
18,500,2.2644,9.6253
|
| 549 |
+
18,500,2.3331,10.3095
|
| 550 |
+
18,600,2.2968,9.9419
|
| 551 |
+
18,600,2.3093,10.0678
|
| 552 |
+
18,700,2.4407,11.4816
|
| 553 |
+
18,700,2.3935,10.9519
|
| 554 |
+
18,800,2.3881,10.8931
|
| 555 |
+
18,800,2.4676,11.7936
|
| 556 |
+
18,900,2.2182,9.1906
|
| 557 |
+
18,900,2.4923,12.089
|
| 558 |
+
18,1000,2.3312,10.2898
|
| 559 |
+
18,1000,2.346,10.4438
|
| 560 |
+
18,1100,2.0509,7.7749
|
| 561 |
+
18,1100,2.3353,10.3324
|
| 562 |
+
18,1200,2.349,10.4752
|
| 563 |
+
18,1200,2.6501,14.1561
|
| 564 |
+
18,1300,2.2147,9.159
|
| 565 |
+
18,1300,2.5033,12.2222
|
| 566 |
+
18,1400,2.3278,10.2557
|
| 567 |
+
18,1400,2.5552,12.8738
|
| 568 |
+
18,1500,1.9178,6.8062
|
| 569 |
+
18,1500,2.1927,8.9596
|
| 570 |
+
18,1600,2.2685,9.6654
|
| 571 |
+
18,1600,2.497,12.1465
|
| 572 |
+
18,1700,2.2014,9.0381
|
| 573 |
+
18,1700,2.4935,12.1037
|
| 574 |
+
18,1800,2.0424,7.7092
|
| 575 |
+
18,1800,2.4783,11.9213
|
| 576 |
+
18,1900,2.3529,10.5158
|
| 577 |
+
18,1900,2.3436,10.4189
|
| 578 |
+
18,2000,2.2688,9.6676
|
| 579 |
+
18,2000,2.5853,13.2677
|
| 580 |
+
18,2100,2.1891,8.927
|
| 581 |
+
18,2100,2.5161,12.3804
|
| 582 |
+
18,2200,2.1682,8.7424
|
| 583 |
+
18,2200,2.6254,13.8102
|
| 584 |
+
18,2300,2.3965,10.9842
|
| 585 |
+
18,2300,2.4902,12.0631
|
| 586 |
+
18,2400,2.2135,9.148
|
| 587 |
+
18,2400,2.4329,11.3913
|
| 588 |
+
18,2500,2.4143,11.1821
|
| 589 |
+
18,2500,2.4294,11.352
|
| 590 |
+
18,2600,2.3422,10.4039
|
| 591 |
+
18,2600,2.5354,12.621
|
| 592 |
+
18,2700,2.2772,9.7493
|
| 593 |
+
18,2700,2.4877,12.0333
|
| 594 |
+
18,2800,2.3167,10.1422
|
| 595 |
+
18,2800,2.4673,11.7911
|
| 596 |
+
18,2900,2.3364,10.3438
|
| 597 |
+
18,2900,2.3145,10.1199
|
| 598 |
+
18,3000,2.0664,7.8962
|
| 599 |
+
18,3000,2.5194,12.4214
|
| 600 |
+
18,3100,2.2455,9.4448
|
| 601 |
+
18,3100,2.6512,14.1717
|
| 602 |
+
19,100,2.3789,10.7934
|
| 603 |
+
19,200,2.4119,11.1547
|
| 604 |
+
19,300,2.4709,11.8328
|
| 605 |
+
19,400,2.3014,9.9881
|
| 606 |
+
19,500,2.5112,12.3191
|
| 607 |
+
19,600,2.4034,11.061
|
| 608 |
+
19,700,2.4421,11.4974
|
| 609 |
+
19,800,2.4358,11.4253
|
| 610 |
+
19,900,2.4511,11.6007
|
| 611 |
+
19,1000,2.3752,10.7536
|
| 612 |
+
19,1100,2.2818,9.7943
|
| 613 |
+
19,1200,2.526,12.5039
|
| 614 |
+
19,1300,2.235,9.3461
|
| 615 |
+
19,1400,2.5668,13.0242
|
| 616 |
+
19,1500,2.438,11.4499
|
| 617 |
+
19,1600,2.1895,8.9306
|
| 618 |
+
19,1700,2.3286,10.264
|
| 619 |
+
19,1800,2.3863,10.8737
|
| 620 |
+
19,1900,2.4867,12.0217
|
| 621 |
+
19,2000,2.3649,10.643
|
| 622 |
+
19,2100,2.3546,10.5342
|
| 623 |
+
19,2200,2.3941,10.9579
|
| 624 |
+
19,2300,2.1938,8.9695
|
| 625 |
+
19,2400,2.4041,11.0679
|
| 626 |
+
19,2500,2.5131,12.3433
|
| 627 |
+
19,2600,2.2205,9.2123
|
| 628 |
+
19,2700,2.293,9.9044
|
| 629 |
+
19,2800,2.5673,13.0307
|
| 630 |
+
19,2900,2.4287,11.3445
|
| 631 |
+
19,3000,2.3494,10.4788
|
| 632 |
+
19,3100,2.6807,14.5951
|
| 633 |
+
20,100,2.2876,9.851
|
| 634 |
+
20,200,2.3219,10.1953
|
| 635 |
+
20,300,2.318,10.1558
|
| 636 |
+
20,400,2.2775,9.7521
|
| 637 |
+
20,500,2.3627,10.6199
|
| 638 |
+
20,600,2.584,13.2502
|
| 639 |
+
20,700,2.3991,11.013
|
| 640 |
+
20,800,2.32,10.1755
|
| 641 |
+
20,900,2.1218,8.3458
|
| 642 |
+
20,1000,2.3538,10.5252
|
| 643 |
+
20,1100,2.222,9.2257
|
| 644 |
+
20,1200,2.2933,9.9077
|
| 645 |
+
20,1300,2.4057,11.0867
|
| 646 |
+
20,1400,2.4458,11.5401
|
| 647 |
+
20,1500,2.283,9.8058
|
| 648 |
+
20,1600,2.3211,10.1873
|
| 649 |
+
20,1700,2.4251,11.3038
|
| 650 |
+
20,1800,2.3395,10.3759
|
| 651 |
+
20,1900,2.591,13.3425
|
| 652 |
+
20,2000,2.2993,9.9669
|
| 653 |
+
20,2100,2.1527,8.6081
|
| 654 |
+
20,2200,2.3867,10.8779
|
| 655 |
+
20,2300,2.3479,10.4636
|
| 656 |
+
20,2400,2.234,9.3375
|
| 657 |
+
20,2500,2.3098,10.0721
|
| 658 |
+
20,2600,2.3198,10.1732
|
| 659 |
+
20,2700,2.3959,10.9776
|
| 660 |
+
20,2800,2.7605,15.808
|
| 661 |
+
20,2900,2.4974,12.1514
|
| 662 |
+
20,3000,2.4413,11.4875
|
| 663 |
+
20,3100,2.3338,10.3173
|
| 664 |
+
21,100,2.1393,8.4933
|
| 665 |
+
21,100,2.4415,11.4905
|
| 666 |
+
21,200,2.3351,10.3309
|
| 667 |
+
21,200,2.4132,11.1694
|
| 668 |
+
21,300,2.0899,8.0842
|
| 669 |
+
21,300,2.5896,13.3244
|
| 670 |
+
21,400,2.1491,8.5775
|
| 671 |
+
21,400,2.4345,11.4096
|
| 672 |
+
21,500,2.2872,9.8477
|
| 673 |
+
21,500,2.4611,11.7174
|
| 674 |
+
21,600,2.4272,11.3273
|
| 675 |
+
21,600,2.755,15.721
|
| 676 |
+
21,700,2.1416,8.513
|
| 677 |
+
21,700,2.3508,10.4938
|
| 678 |
+
21,800,2.3899,10.9122
|
| 679 |
+
21,800,2.5791,13.1847
|
| 680 |
+
21,900,2.3071,10.045
|
| 681 |
+
21,900,2.2819,9.7949
|
| 682 |
+
21,1000,2.1995,9.0203
|
| 683 |
+
21,1000,2.4685,11.8042
|
| 684 |
+
21,1100,2.3339,10.3183
|
| 685 |
+
21,1100,2.5896,13.3245
|
| 686 |
+
21,1200,2.4029,11.0547
|
| 687 |
+
21,1200,2.2209,9.216
|
| 688 |
+
21,1300,2.2694,9.674
|
| 689 |
+
21,1300,2.5391,12.6681
|
| 690 |
+
21,1400,2.1527,8.6082
|
| 691 |
+
21,1400,2.56,12.9352
|
| 692 |
+
21,1500,2.2131,9.1442
|
| 693 |
+
21,1500,2.4823,11.9683
|
| 694 |
+
21,1600,2.1473,8.5615
|
| 695 |
+
21,1600,2.6207,13.745
|
| 696 |
+
21,1700,2.249,9.4778
|
| 697 |
+
21,1700,2.2406,9.3989
|
| 698 |
+
21,1800,2.3484,10.4684
|
| 699 |
+
21,1800,2.4947,12.1177
|
| 700 |
+
21,1900,2.369,10.6865
|
| 701 |
+
21,1900,2.3141,10.1161
|
| 702 |
+
21,2000,2.1483,8.5702
|
| 703 |
+
21,2000,2.0813,8.0148
|
| 704 |
+
21,2100,2.4676,11.7938
|
| 705 |
+
21,2100,2.5372,12.6438
|
| 706 |
+
21,2200,2.5696,13.0607
|
| 707 |
+
21,2200,2.4665,11.7807
|
| 708 |
+
21,2300,2.3604,10.5955
|
| 709 |
+
21,2300,2.453,11.6234
|
| 710 |
+
21,2400,2.4663,11.7783
|
| 711 |
+
21,2400,2.552,12.8323
|
| 712 |
+
21,2500,2.4053,11.0819
|
| 713 |
+
21,2500,2.2327,9.3254
|
| 714 |
+
21,2600,2.3557,10.5451
|
| 715 |
+
21,2600,2.3985,11.0071
|
| 716 |
+
21,2700,2.2723,9.7018
|
| 717 |
+
21,2700,2.4432,11.5094
|
| 718 |
+
21,2800,2.2502,9.4895
|
| 719 |
+
21,2800,2.5233,12.4703
|
| 720 |
+
21,2900,2.4847,11.9973
|
| 721 |
+
21,2900,2.409,11.1229
|
| 722 |
+
21,3000,2.2226,9.2317
|
| 723 |
+
21,3000,2.3775,10.7784
|
| 724 |
+
21,3100,2.1203,8.334
|
| 725 |
+
21,3100,2.3746,10.747
|
| 726 |
+
22,100,2.0841,8.0371
|
| 727 |
+
22,100,2.3862,10.8717
|
| 728 |
+
22,200,2.2103,9.1183
|
| 729 |
+
22,200,2.5702,13.069
|
| 730 |
+
22,300,2.2659,9.6397
|
| 731 |
+
22,300,2.2531,9.5168
|
| 732 |
+
22,400,2.4005,11.0286
|
| 733 |
+
22,400,2.4486,11.5717
|
| 734 |
+
22,500,2.1922,8.9553
|
| 735 |
+
22,500,2.4738,11.8676
|
| 736 |
+
22,600,2.3171,10.1463
|
| 737 |
+
22,600,2.2134,9.1471
|
| 738 |
+
22,700,2.1564,8.6396
|
| 739 |
+
22,700,2.5602,12.9386
|
| 740 |
+
22,800,2.3937,10.9535
|
| 741 |
+
22,800,2.2362,9.3575
|
| 742 |
+
22,900,2.3248,10.2245
|
| 743 |
+
22,900,2.5474,12.7736
|
| 744 |
+
22,1000,2.0701,7.9253
|
| 745 |
+
22,1000,2.0833,8.0311
|
| 746 |
+
22,1100,2.1329,8.4391
|
| 747 |
+
22,1100,2.2881,9.8567
|
| 748 |
+
22,1200,2.194,8.9706
|
| 749 |
+
22,1200,2.4615,11.7227
|
| 750 |
+
22,1300,2.4257,11.3102
|
| 751 |
+
22,1300,2.2817,9.7936
|
| 752 |
+
22,1400,2.2594,9.5774
|
| 753 |
+
22,1400,2.5625,12.9683
|
| 754 |
+
22,1500,2.2953,9.9279
|
| 755 |
+
22,1500,2.1516,8.599
|
| 756 |
+
22,1600,2.3245,10.2215
|
| 757 |
+
22,1600,2.4977,12.1545
|
| 758 |
+
22,1700,2.3146,10.1208
|
| 759 |
+
22,1700,2.2119,9.1334
|
| 760 |
+
22,1800,2.3918,10.9335
|
| 761 |
+
22,1800,2.2168,9.1775
|
| 762 |
+
22,1900,2.4785,11.9235
|
| 763 |
+
22,1900,2.4493,11.5805
|
| 764 |
+
22,2000,2.2433,9.4248
|
| 765 |
+
22,2000,2.514,12.3543
|
| 766 |
+
22,2100,2.3151,10.1256
|
| 767 |
+
22,2100,2.2537,9.5231
|
| 768 |
+
22,2200,2.1862,8.9009
|
| 769 |
+
22,2200,2.3459,10.4427
|
| 770 |
+
22,2300,2.4228,11.2773
|
| 771 |
+
22,2300,2.2346,9.3426
|
| 772 |
+
22,2400,2.2062,9.0816
|
| 773 |
+
22,2400,2.4777,11.9139
|
| 774 |
+
22,2500,2.1243,8.3674
|
| 775 |
+
22,2500,2.3603,10.5946
|
| 776 |
+
22,2600,2.3792,10.7965
|
| 777 |
+
22,2600,2.3461,10.4452
|
| 778 |
+
22,2700,2.3259,10.2359
|
| 779 |
+
22,2700,2.3966,10.9861
|
| 780 |
+
22,2800,2.4015,11.0399
|
| 781 |
+
22,2800,2.4276,11.3319
|
| 782 |
+
22,2900,2.5032,12.2218
|
| 783 |
+
22,2900,2.3832,10.8394
|
| 784 |
+
22,3000,2.1186,8.3195
|
| 785 |
+
22,3000,2.3673,10.6688
|
| 786 |
+
22,3100,2.3263,10.2401
|
| 787 |
+
22,3100,2.2368,9.3634
|
| 788 |
+
23,100,2.2735,9.7134
|
| 789 |
+
23,100,2.2665,9.6457
|
| 790 |
+
23,200,2.185,8.8906
|
| 791 |
+
23,200,2.1517,8.5996
|
| 792 |
+
23,300,2.2903,9.8783
|
| 793 |
+
23,300,2.2574,9.5578
|
| 794 |
+
23,400,2.4636,11.7469
|
| 795 |
+
23,400,2.5305,12.5602
|
| 796 |
+
23,500,2.262,9.6028
|
| 797 |
+
23,500,2.434,11.4045
|
| 798 |
+
23,600,2.2474,9.4631
|
| 799 |
+
23,600,2.1875,8.9125
|
| 800 |
+
23,700,2.1001,8.1667
|
| 801 |
+
23,700,2.165,8.7143
|
| 802 |
+
23,800,2.1119,8.2638
|
| 803 |
+
23,800,2.2312,9.3107
|
| 804 |
+
23,900,2.2211,9.2171
|
| 805 |
+
23,900,2.3446,10.4295
|
| 806 |
+
23,1000,2.242,9.412
|
| 807 |
+
23,1000,2.4275,11.3308
|
| 808 |
+
23,1100,2.1189,8.3216
|
| 809 |
+
23,1100,2.3552,10.5405
|
| 810 |
+
23,1200,2.1247,8.37
|
| 811 |
+
23,1200,2.3776,10.7791
|
| 812 |
+
23,1300,2.1127,8.2704
|
| 813 |
+
23,1300,2.4015,11.0394
|
| 814 |
+
23,1400,2.102,8.1822
|
| 815 |
+
23,1400,2.4753,11.8853
|
| 816 |
+
23,1500,2.2269,9.2714
|
| 817 |
+
23,1500,2.4314,11.375
|
| 818 |
+
23,1600,2.1121,8.2657
|
| 819 |
+
23,1600,2.2185,9.1938
|
| 820 |
+
23,1700,1.9466,7.0051
|
| 821 |
+
23,1700,2.212,9.1336
|
| 822 |
+
23,1800,2.2108,9.1232
|
| 823 |
+
23,1800,2.2967,9.9416
|
| 824 |
+
23,1900,2.2285,9.2856
|
| 825 |
+
23,1900,2.4373,11.4426
|
| 826 |
+
23,2000,2.2417,9.4092
|
| 827 |
+
23,2000,2.3913,10.9281
|
| 828 |
+
23,2100,2.2783,9.7597
|
| 829 |
+
23,2100,2.2783,9.7605
|
| 830 |
+
23,2200,2.1256,8.3781
|
| 831 |
+
23,2200,2.6455,14.0907
|
| 832 |
+
23,2300,2.4059,11.0888
|
| 833 |
+
23,2300,2.3268,10.2454
|
| 834 |
+
23,2400,2.2476,9.4653
|
| 835 |
+
23,2400,2.3324,10.3022
|
| 836 |
+
23,2500,1.9663,7.1443
|
| 837 |
+
23,2500,2.1346,8.4539
|
| 838 |
+
23,2600,2.2005,9.0293
|
| 839 |
+
23,2600,2.3986,11.008
|
| 840 |
+
23,2700,2.2762,9.7399
|
| 841 |
+
23,2700,2.3777,10.78
|
| 842 |
+
23,2800,2.3507,10.493
|
| 843 |
+
23,2800,2.4017,11.0422
|
| 844 |
+
23,2900,2.1719,8.7753
|
| 845 |
+
23,2900,2.6419,14.0403
|
| 846 |
+
23,3000,2.1339,8.4474
|
| 847 |
+
23,3000,2.4274,11.3291
|
| 848 |
+
23,3100,2.3432,10.414
|
| 849 |
+
23,3100,2.4689,11.8095
|
| 850 |
+
24,100,2.3766,10.7685
|
| 851 |
+
24,100,2.1095,8.2443
|
| 852 |
+
24,200,2.2492,9.4799
|
| 853 |
+
24,200,2.2281,9.2821
|
| 854 |
+
24,300,2.0896,8.0816
|
| 855 |
+
24,300,2.3703,10.7003
|
| 856 |
+
24,400,2.123,8.356
|
| 857 |
+
24,400,2.305,10.0242
|
| 858 |
+
24,500,2.2929,9.9039
|
| 859 |
+
24,500,2.2863,9.8383
|
| 860 |
+
24,600,2.2186,9.1948
|
| 861 |
+
24,600,2.252,9.507
|
| 862 |
+
24,700,2.3652,10.6457
|
| 863 |
+
24,700,2.2716,9.6947
|
| 864 |
+
24,800,2.4291,11.349
|
| 865 |
+
24,800,2.3995,11.0173
|
| 866 |
+
24,900,2.0992,8.1598
|
| 867 |
+
24,900,2.3343,10.3224
|
| 868 |
+
24,1000,2.2295,9.2953
|
| 869 |
+
24,1000,2.2976,9.9507
|
| 870 |
+
24,1100,2.2423,9.4153
|
| 871 |
+
24,1100,2.3547,10.5347
|
| 872 |
+
24,1200,2.1982,9.0089
|
| 873 |
+
24,1200,2.3108,10.0823
|
| 874 |
+
24,1300,2.3898,10.9117
|
| 875 |
+
24,1300,2.3038,10.0118
|
| 876 |
+
24,1400,2.4188,11.2319
|
| 877 |
+
24,1400,2.4687,11.8066
|
| 878 |
+
24,1500,2.2394,9.3875
|
| 879 |
+
24,1500,2.2251,9.2544
|
| 880 |
+
24,1600,2.3871,10.8814
|
| 881 |
+
24,1600,2.4617,11.7248
|
| 882 |
+
24,1700,2.4062,11.0917
|
| 883 |
+
24,1700,2.2415,9.407
|
| 884 |
+
24,1800,2.2069,9.0873
|
| 885 |
+
24,1800,2.2795,9.7719
|
| 886 |
+
24,1900,2.1929,8.9615
|
| 887 |
+
24,1900,2.5203,12.4326
|
| 888 |
+
24,2000,2.2991,9.9652
|
| 889 |
+
24,2000,2.463,11.7403
|
| 890 |
+
24,2100,2.2047,9.0674
|
| 891 |
+
24,2100,2.3497,10.4825
|
| 892 |
+
24,2200,2.1788,8.836
|
| 893 |
+
24,2200,2.4901,12.0629
|
| 894 |
+
24,2300,2.3368,10.3484
|
| 895 |
+
24,2300,2.1345,8.453
|
| 896 |
+
24,2400,2.3685,10.6811
|
| 897 |
+
24,2400,2.3948,10.9664
|
| 898 |
+
24,2500,2.1582,8.6555
|
| 899 |
+
24,2500,2.1817,8.8612
|
| 900 |
+
24,2600,2.2999,9.9734
|
| 901 |
+
24,2600,2.4069,11.0995
|
| 902 |
+
24,2700,2.1185,8.3184
|
| 903 |
+
24,2700,2.4753,11.8856
|
| 904 |
+
24,2800,2.5695,13.0598
|
| 905 |
+
24,2800,2.4636,11.7471
|
| 906 |
+
24,2900,2.256,9.545
|
| 907 |
+
24,2900,2.681,14.5996
|
| 908 |
+
24,3000,2.3286,10.2635
|
| 909 |
+
24,3000,2.2329,9.3272
|
| 910 |
+
24,3100,2.2094,9.1106
|
| 911 |
+
24,3100,2.1047,8.2049
|
| 912 |
+
25,100,2.0074,7.4441
|
| 913 |
+
25,100,2.0677,7.9063
|
| 914 |
+
25,200,2.0555,7.8107
|
| 915 |
+
25,200,2.311,10.0845
|
| 916 |
+
25,300,2.3032,10.0063
|
| 917 |
+
25,300,2.0452,7.7308
|
| 918 |
+
25,400,2.1707,8.7648
|
| 919 |
+
25,400,2.3708,10.7054
|
| 920 |
+
25,500,2.1961,8.9898
|
| 921 |
+
25,500,2.2842,9.8177
|
| 922 |
+
25,600,2.0564,7.8181
|
| 923 |
+
25,600,2.465,11.7635
|
| 924 |
+
25,700,2.0773,7.9832
|
| 925 |
+
25,700,2.2797,9.7735
|
| 926 |
+
25,800,2.3222,10.1984
|
| 927 |
+
25,800,2.4073,11.1045
|
| 928 |
+
25,900,2.1284,8.4017
|
| 929 |
+
25,900,1.9411,6.9664
|
| 930 |
+
25,1000,2.1676,8.737
|
| 931 |
+
25,1000,2.1742,8.7955
|
| 932 |
+
25,1100,2.2209,9.2159
|
| 933 |
+
25,1100,2.2986,9.9598
|
| 934 |
+
25,1200,2.1686,8.7457
|
| 935 |
+
25,1200,2.2249,9.2525
|
| 936 |
+
25,1300,2.313,10.1044
|
| 937 |
+
25,1300,2.2743,9.7211
|
| 938 |
+
25,1400,2.2171,9.1806
|
| 939 |
+
25,1400,2.4074,11.1048
|
| 940 |
+
25,1500,2.2474,9.4627
|
| 941 |
+
25,1500,2.3521,10.5077
|
| 942 |
+
25,1600,2.2844,9.8197
|
| 943 |
+
25,1600,2.1566,8.642
|
| 944 |
+
25,1700,2.2792,9.7693
|
| 945 |
+
25,1700,2.5753,13.135
|
| 946 |
+
25,1800,2.2396,9.3897
|
| 947 |
+
25,1800,2.5129,12.3405
|
| 948 |
+
25,1900,2.0225,7.5576
|
| 949 |
+
25,1900,2.1021,8.1835
|
| 950 |
+
25,2000,2.236,9.3554
|
| 951 |
+
25,2000,2.2199,9.2062
|
| 952 |
+
25,2100,2.071,7.9326
|
| 953 |
+
25,2100,2.2128,9.1416
|
| 954 |
+
25,2200,2.3347,10.3267
|
| 955 |
+
25,2200,2.4628,11.7379
|
| 956 |
+
25,2300,2.035,7.6525
|
| 957 |
+
25,2300,2.2937,9.9117
|
| 958 |
+
25,2400,2.2684,9.6638
|
| 959 |
+
25,2400,2.3119,10.0937
|
| 960 |
+
25,2500,2.2548,9.5332
|
| 961 |
+
25,2500,2.4301,11.3601
|
| 962 |
+
25,2600,2.0938,8.1161
|
| 963 |
+
25,2600,2.3248,10.2245
|
| 964 |
+
25,2700,2.1231,8.3569
|
| 965 |
+
25,2700,2.1451,8.5426
|
| 966 |
+
25,2800,2.1211,8.3405
|
| 967 |
+
25,2800,2.4403,11.4766
|
| 968 |
+
25,2900,2.2003,9.0279
|
| 969 |
+
25,2900,2.5203,12.4329
|
| 970 |
+
25,3000,2.2365,9.3608
|
| 971 |
+
25,3000,2.2823,9.7993
|
| 972 |
+
25,3100,2.1602,8.6729
|
| 973 |
+
25,3100,2.2913,9.8882
|
| 974 |
+
26,100,2.1935,8.9668
|
| 975 |
+
26,100,2.1781,8.8298
|
| 976 |
+
26,200,1.9728,7.1905
|
| 977 |
+
26,200,2.1307,8.4208
|
| 978 |
+
26,300,2.2561,9.5454
|
| 979 |
+
26,300,2.1756,8.8076
|
| 980 |
+
26,400,2.0493,7.7628
|
| 981 |
+
26,400,1.9878,7.2998
|
| 982 |
+
26,500,2.2319,9.318
|
| 983 |
+
26,500,2.365,10.6442
|
| 984 |
+
26,600,2.1954,8.9836
|
| 985 |
+
26,600,2.5252,12.494
|
| 986 |
+
26,700,2.1557,8.6338
|
| 987 |
+
26,700,2.4526,11.6181
|
| 988 |
+
26,800,2.4767,11.9019
|
| 989 |
+
26,800,2.1245,8.3691
|
| 990 |
+
26,900,2.2038,9.0594
|
| 991 |
+
26,900,2.0997,8.1638
|
| 992 |
+
26,1000,2.1657,8.7203
|
| 993 |
+
26,1000,2.3237,10.2132
|
| 994 |
+
26,1100,2.0512,7.7773
|
| 995 |
+
26,1100,2.1471,8.5599
|
| 996 |
+
26,1200,2.2466,9.4556
|
| 997 |
+
26,1200,2.4894,12.0542
|
| 998 |
+
26,1300,2.1989,9.0151
|
| 999 |
+
26,1300,2.2348,9.3447
|
| 1000 |
+
26,1400,2.258,9.5638
|
| 1001 |
+
26,1400,2.2782,9.7595
|
| 1002 |
+
26,1500,2.3685,10.6812
|
| 1003 |
+
26,1500,2.4081,11.1129
|
| 1004 |
+
26,1600,2.1787,8.8347
|
| 1005 |
+
26,1600,2.1137,8.2785
|
| 1006 |
+
26,1700,2.2104,9.1193
|
| 1007 |
+
26,1700,2.3987,11.0087
|
| 1008 |
+
26,1800,2.0694,7.9204
|
| 1009 |
+
26,1800,2.0616,7.8588
|
| 1010 |
+
26,1900,2.1163,8.3004
|
| 1011 |
+
26,1900,2.1317,8.4295
|
| 1012 |
+
26,2000,2.2775,9.7523
|
| 1013 |
+
26,2000,2.2971,9.9451
|
| 1014 |
+
26,2100,2.4668,11.785
|
| 1015 |
+
26,2100,2.2505,9.4921
|
| 1016 |
+
26,2200,2.0802,8.0062
|
| 1017 |
+
26,2200,2.1467,8.5564
|
| 1018 |
+
26,2300,2.2296,9.2964
|
| 1019 |
+
26,2300,1.9914,7.326
|
| 1020 |
+
26,2400,2.0793,7.9986
|
| 1021 |
+
26,2400,2.0928,8.1075
|
| 1022 |
+
26,2500,2.1663,8.7259
|
| 1023 |
+
26,2500,2.4869,12.0239
|
| 1024 |
+
26,2600,1.9672,7.1505
|
| 1025 |
+
26,2600,2.0959,8.1325
|
| 1026 |
+
26,2700,2.3145,10.1195
|
| 1027 |
+
26,2700,2.1937,8.9682
|
| 1028 |
+
26,2800,2.1893,8.9292
|
| 1029 |
+
26,2800,2.1959,8.9884
|
| 1030 |
+
26,2900,2.0229,7.56
|
| 1031 |
+
26,2900,2.0231,7.5616
|
| 1032 |
+
26,3000,2.4255,11.3075
|
| 1033 |
+
26,3000,2.2614,9.5964
|
| 1034 |
+
26,3100,2.257,9.5549
|
| 1035 |
+
26,3100,2.3379,10.3591
|
| 1036 |
+
27,100,2.0213,7.5483
|
| 1037 |
+
27,100,2.451,11.6003
|
| 1038 |
+
27,200,2.0965,8.1376
|
| 1039 |
+
27,200,2.1434,8.5288
|
| 1040 |
+
27,300,2.1239,8.3635
|
| 1041 |
+
27,300,2.2218,9.2243
|
| 1042 |
+
27,400,2.062,7.8614
|
| 1043 |
+
27,400,2.3096,10.07
|
| 1044 |
+
27,500,2.2273,9.2751
|
| 1045 |
+
27,500,1.9651,7.1359
|
| 1046 |
+
27,600,1.9186,6.8115
|
| 1047 |
+
27,600,2.1665,8.7279
|
| 1048 |
+
27,700,2.1434,8.5282
|
| 1049 |
+
27,700,1.9937,7.3428
|
| 1050 |
+
27,800,2.0196,7.5353
|
| 1051 |
+
27,800,2.3485,10.4698
|
| 1052 |
+
27,900,1.9703,7.1727
|
| 1053 |
+
27,900,2.2921,9.8954
|
| 1054 |
+
27,1000,1.9125,6.77
|
| 1055 |
+
27,1000,2.1013,8.1766
|
| 1056 |
+
27,1100,2.1512,8.5948
|
| 1057 |
+
27,1100,2.0653,7.8879
|
| 1058 |
+
27,1200,2.1597,8.6683
|
| 1059 |
+
27,1200,2.2314,9.3128
|
| 1060 |
+
27,1300,2.1628,8.6955
|
| 1061 |
+
27,1300,2.1889,8.9255
|
| 1062 |
+
27,1400,2.1293,8.4093
|
| 1063 |
+
27,1400,2.2393,9.3871
|
| 1064 |
+
27,1500,1.9977,7.3723
|
| 1065 |
+
27,1500,2.0922,8.1025
|
| 1066 |
+
27,1600,2.1225,8.3524
|
| 1067 |
+
27,1600,2.0977,8.1471
|
| 1068 |
+
27,1700,2.0431,7.7143
|
| 1069 |
+
27,1700,2.1646,8.711
|
| 1070 |
+
27,1800,2.1295,8.4103
|
| 1071 |
+
27,1800,2.0869,8.0598
|
| 1072 |
+
27,1900,2.1814,8.859
|
| 1073 |
+
27,1900,2.215,9.1616
|
| 1074 |
+
27,2000,2.1035,8.1949
|
| 1075 |
+
27,2000,2.3303,10.2812
|
| 1076 |
+
27,2100,2.2474,9.4627
|
| 1077 |
+
27,2100,2.0849,8.0437
|
| 1078 |
+
27,2200,2.174,8.7938
|
| 1079 |
+
27,2200,2.1256,8.3781
|
| 1080 |
+
27,2300,2.049,7.7599
|
| 1081 |
+
27,2300,2.415,11.1895
|
| 1082 |
+
27,2400,2.0989,8.1575
|
| 1083 |
+
27,2400,2.2232,9.2372
|
| 1084 |
+
27,2500,2.1561,8.6375
|
| 1085 |
+
27,2500,2.0479,7.7517
|
| 1086 |
+
27,2600,2.0021,7.4043
|
| 1087 |
+
27,2600,2.2103,9.1183
|
| 1088 |
+
27,2700,2.1921,8.9542
|
| 1089 |
+
27,2700,2.0779,7.9875
|
| 1090 |
+
27,2800,2.0942,8.1186
|
| 1091 |
+
27,2800,2.226,9.2629
|
| 1092 |
+
27,2900,2.0986,8.1548
|
| 1093 |
+
27,2900,1.9721,7.1857
|
| 1094 |
+
27,3000,2.0972,8.1434
|
| 1095 |
+
27,3000,2.0447,7.7268
|
| 1096 |
+
27,3100,2.3328,10.3071
|
| 1097 |
+
27,3100,2.3461,10.4452
|
| 1098 |
+
28,100,2.3226,10.2017
|
| 1099 |
+
28,200,2.0446,7.7264
|
| 1100 |
+
28,300,2.1842,8.8834
|
| 1101 |
+
28,400,2.1027,8.1881
|
| 1102 |
+
28,500,2.065,7.8852
|
| 1103 |
+
28,600,2.1477,8.5651
|
| 1104 |
+
28,700,2.2763,9.7404
|
| 1105 |
+
28,800,2.0723,7.943
|
| 1106 |
+
28,900,2.2289,9.2896
|
| 1107 |
+
28,1000,2.0397,7.6886
|
| 1108 |
+
28,1100,2.0839,8.0357
|
| 1109 |
+
28,1200,2.1007,8.1722
|
| 1110 |
+
28,1300,2.0338,7.6428
|
| 1111 |
+
28,1400,2.2426,9.4181
|
| 1112 |
+
28,1500,2.0902,8.0865
|
| 1113 |
+
28,1600,2.053,7.7911
|
| 1114 |
+
28,1700,2.1393,8.4933
|
| 1115 |
+
28,1800,2.2889,9.864
|
| 1116 |
+
28,1900,2.0841,8.037
|
| 1117 |
+
28,2000,2.1644,8.7093
|
| 1118 |
+
28,2100,2.3094,10.0683
|
| 1119 |
+
28,2200,2.1274,8.3931
|
| 1120 |
+
28,2300,2.1598,8.6696
|
| 1121 |
+
28,2400,2.0426,7.7105
|
| 1122 |
+
28,2500,2.0391,7.6833
|
| 1123 |
+
28,2600,2.1521,8.6025
|
| 1124 |
+
28,2700,2.0867,8.0583
|
| 1125 |
+
28,2800,1.9385,6.9486
|
| 1126 |
+
28,2900,2.166,8.7234
|
| 1127 |
+
28,3000,2.3245,10.2219
|
| 1128 |
+
28,3100,2.1882,8.9189
|
| 1129 |
+
29,100,1.8376,6.2816
|
| 1130 |
+
29,200,2.0208,7.5444
|
| 1131 |
+
29,300,2.4057,11.0859
|
| 1132 |
+
29,400,1.9454,6.9966
|
| 1133 |
+
29,500,2.0933,8.1118
|
| 1134 |
+
29,600,2.1162,8.2996
|
| 1135 |
+
29,700,2.0233,7.5629
|
| 1136 |
+
29,800,2.1161,8.2987
|
| 1137 |
+
29,900,2.3258,10.2354
|
| 1138 |
+
29,1000,2.0303,7.6167
|
| 1139 |
+
29,1100,2.2297,9.297
|
| 1140 |
+
29,1200,2.1602,8.6727
|
| 1141 |
+
29,1300,2.0937,8.1153
|
| 1142 |
+
29,1400,2.1163,8.3006
|
| 1143 |
+
29,1500,2.177,8.8202
|
| 1144 |
+
29,1600,2.0694,7.9199
|
| 1145 |
+
29,1700,2.2901,9.8764
|
| 1146 |
+
29,1800,2.0297,7.6121
|
| 1147 |
+
29,1900,1.9835,7.2681
|
| 1148 |
+
29,2000,2.1101,8.2492
|
| 1149 |
+
29,2100,2.0714,7.9361
|
| 1150 |
+
29,2200,2.3346,10.3258
|
| 1151 |
+
29,2300,2.125,8.3732
|
| 1152 |
+
29,2400,2.2709,9.6881
|
| 1153 |
+
29,2500,2.1652,8.7159
|
| 1154 |
+
29,2600,2.4139,11.1778
|
| 1155 |
+
29,2700,2.1402,8.5011
|
| 1156 |
+
29,2800,2.0135,7.4895
|
| 1157 |
+
29,2900,2.1379,8.4812
|
| 1158 |
+
29,3000,2.2424,9.4156
|
| 1159 |
+
29,3100,2.1572,8.6465
|
| 1160 |
+
30,100,2.1938,8.9692
|
| 1161 |
+
30,200,2.1014,8.178
|
| 1162 |
+
30,300,2.2413,9.4058
|
| 1163 |
+
30,400,2.027,7.5915
|
| 1164 |
+
30,500,1.9092,6.7479
|
| 1165 |
+
30,600,2.1688,8.748
|
| 1166 |
+
30,700,2.1492,8.5776
|
| 1167 |
+
30,800,2.1651,8.7158
|
| 1168 |
+
30,900,2.0124,7.4812
|
| 1169 |
+
30,1000,2.3341,10.3199
|
| 1170 |
+
30,1100,2.0736,7.9533
|
| 1171 |
+
30,1200,2.2919,9.8934
|
| 1172 |
+
30,1300,1.8976,6.67
|
| 1173 |
+
30,1400,2.1037,8.1963
|
| 1174 |
+
30,1500,1.9812,7.2515
|
| 1175 |
+
30,1600,1.8422,6.3105
|
| 1176 |
+
30,1700,2.1148,8.2879
|
| 1177 |
+
30,1800,2.0392,7.6841
|
| 1178 |
+
30,1900,2.1974,9.0015
|
| 1179 |
+
30,2000,1.99,7.3157
|
| 1180 |
+
30,2100,2.1626,8.6936
|
| 1181 |
+
30,2200,2.0304,7.6174
|
| 1182 |
+
30,2300,2.1228,8.3543
|
| 1183 |
+
30,2400,2.1954,8.9837
|
| 1184 |
+
30,2500,2.1629,8.6964
|
| 1185 |
+
30,2600,2.4293,11.3511
|
| 1186 |
+
30,2700,1.8879,6.6057
|
| 1187 |
+
30,2800,2.2829,9.8055
|
| 1188 |
+
30,2900,2.2601,9.5845
|
| 1189 |
+
30,3000,1.9881,7.302
|
| 1190 |
+
30,3100,2.1743,8.796
|
text_files/validation_metrics.csv
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Epoch,Validation_Loss,Validation_Perplexity
|
| 2 |
+
1,3.1313,22.9038
|
| 3 |
+
2,2.8683,17.6076
|
| 4 |
+
3,2.7487,15.6226
|
| 5 |
+
4,2.6835,14.6358
|
| 6 |
+
5,2.6448,14.08
|
| 7 |
+
6,2.6184,13.7138
|
| 8 |
+
7,2.6021,13.4918
|
| 9 |
+
8,2.5887,13.3131
|
| 10 |
+
10,2.5347,12.6126
|
| 11 |
+
11,2.5207,12.4378
|
| 12 |
+
12,2.5151,12.3681
|
| 13 |
+
13,2.5155,12.3724
|
| 14 |
+
14,2.5215,12.4476
|
| 15 |
+
15,2.5179,12.4026
|
| 16 |
+
16,2.5298,12.5513
|
| 17 |
+
17,2.4818,11.9623
|
| 18 |
+
18,2.4807,11.95
|
| 19 |
+
19,2.4842,11.9914
|
| 20 |
+
20,2.4874,12.0298
|
| 21 |
+
21,2.4595,11.6989
|
| 22 |
+
22,2.4655,11.7698
|
| 23 |
+
23,2.4694,11.8158
|
| 24 |
+
24,2.4789,11.9279
|
| 25 |
+
25,2.4919,12.0847
|
| 26 |
+
26,2.4963,12.1371
|
| 27 |
+
27,2.5049,12.2423
|
| 28 |
+
28,2.5089,12.2919
|
| 29 |
+
29,2.521,12.4409
|
| 30 |
+
30,2.5266,12.5108
|
text_files/validation_script.py
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import re
|
| 2 |
+
import pandas as pd
|
| 3 |
+
import os
|
| 4 |
+
|
| 5 |
+
|
| 6 |
+
# Define a list of your log file names
|
| 7 |
+
log_files = [
|
| 8 |
+
'training (2).txt',
|
| 9 |
+
'training_log_1_18.txt',
|
| 10 |
+
'training_log_17_27.txt',
|
| 11 |
+
'training_log_21_30.txt'
|
| 12 |
+
|
| 13 |
+
]
|
| 14 |
+
|
| 15 |
+
# Create an empty list to store parsed validation data
|
| 16 |
+
validation_data = []
|
| 17 |
+
|
| 18 |
+
# Regex to capture the Epoch number from training progress lines
|
| 19 |
+
epoch_pattern = re.compile(r"Epoch\s\[(\d+)/\d+],")
|
| 20 |
+
|
| 21 |
+
# Regex to capture Validation Avg Loss and Perplexity
|
| 22 |
+
validation_pattern = re.compile(
|
| 23 |
+
r"Validation Avg Loss:\s([\d.]+),\sPerplexity:\s([\d.]+)"
|
| 24 |
+
)
|
| 25 |
+
|
| 26 |
+
current_epoch = None # Variable to keep track of the current epoch
|
| 27 |
+
|
| 28 |
+
print("Starting validation metrics parsing...")
|
| 29 |
+
|
| 30 |
+
# Loop through each log file
|
| 31 |
+
for file_name in log_files:
|
| 32 |
+
if not os.path.exists(file_name):
|
| 33 |
+
print(f"Warning: File not found - {file_name}. Skipping.")
|
| 34 |
+
continue
|
| 35 |
+
|
| 36 |
+
print(f"Processing {file_name} for validation metrics...")
|
| 37 |
+
with open(file_name, 'r', encoding='utf-8') as f: # Use UTF-8 encoding
|
| 38 |
+
for line in f:
|
| 39 |
+
# Check for epoch line first to update current_epoch
|
| 40 |
+
epoch_match = epoch_pattern.search(line)
|
| 41 |
+
if epoch_match:
|
| 42 |
+
current_epoch = int(epoch_match.group(1))
|
| 43 |
+
|
| 44 |
+
# Check for validation metrics line
|
| 45 |
+
validation_match = validation_pattern.search(line)
|
| 46 |
+
if validation_match:
|
| 47 |
+
val_loss = float(validation_match.group(1))
|
| 48 |
+
val_perplexity = float(validation_match.group(2))
|
| 49 |
+
|
| 50 |
+
# Only add if we have an associated epoch
|
| 51 |
+
if current_epoch is not None:
|
| 52 |
+
validation_data.append({
|
| 53 |
+
'Epoch': current_epoch,
|
| 54 |
+
'Validation_Loss': val_loss,
|
| 55 |
+
'Validation_Perplexity': val_perplexity
|
| 56 |
+
})
|
| 57 |
+
else:
|
| 58 |
+
print(f"Warning: Found validation metrics without a preceding epoch in {file_name}. Skipping this entry.")
|
| 59 |
+
|
| 60 |
+
# Create a Pandas DataFrame from the parsed validation data
|
| 61 |
+
df_validation = pd.DataFrame(validation_data)
|
| 62 |
+
|
| 63 |
+
# In case multiple validation metrics are logged per epoch (e.g., if re-running part of a log),
|
| 64 |
+
# we'll keep the last entry for that epoch.
|
| 65 |
+
df_validation_unique = df_validation.drop_duplicates(subset=['Epoch'], keep='last')
|
| 66 |
+
|
| 67 |
+
# Sort the data by Epoch
|
| 68 |
+
df_validation_sorted = df_validation_unique.sort_values(by=['Epoch']).reset_index(drop=True)
|
| 69 |
+
|
| 70 |
+
# Save the DataFrame to a CSV file
|
| 71 |
+
output_csv_file = 'validation_metrics.csv'
|
| 72 |
+
df_validation_sorted.to_csv(output_csv_file, index=False)
|
| 73 |
+
|
| 74 |
+
print(f"\nSuccessfully parsed validation metrics and saved data to {output_csv_file}")
|
| 75 |
+
print("You can now import this CSV file into Power BI to create your visualizations.")
|
| 76 |
+
print("\nFirst few rows of the generated CSV:")
|
| 77 |
+
print(df_validation_sorted.head())
|
web_app.py
ADDED
|
@@ -0,0 +1,650 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import base64
|
| 3 |
+
import json
|
| 4 |
+
import numpy as np
|
| 5 |
+
import cv2 # For image manipulation and plotting segmentation results
|
| 6 |
+
import pickle # To load vocabulary (for captioning internal loading)
|
| 7 |
+
import logging
|
| 8 |
+
from io import BytesIO
|
| 9 |
+
import sys
|
| 10 |
+
# import jsonify # This was the missing import causing issues!
|
| 11 |
+
import face_recognition # For facial recognition tasks
|
| 12 |
+
import torch
|
| 13 |
+
from werkzeug.utils import secure_filename
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
from flask import Flask, render_template, request, redirect, url_for, session, flash, g, jsonify # Corrected import: added jsonify
|
| 17 |
+
from flask_sqlalchemy import SQLAlchemy
|
| 18 |
+
from werkzeug.security import generate_password_hash, check_password_hash
|
| 19 |
+
from functools import wraps
|
| 20 |
+
from PIL import Image # Used for both image processing and face_recognition
|
| 21 |
+
|
| 22 |
+
# Add the 'src' directory to Python's path so we can import from it.
|
| 23 |
+
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), 'src')))
|
| 24 |
+
|
| 25 |
+
# IMPORTANT: Explicitly import the CLASSES directly into the __main__ scope.
|
| 26 |
+
# This ensures their definitions are available to torch.load when it attempts
|
| 27 |
+
# to deserialize pickled objects (like COCOVocabulary or ImageCaptioningModel
|
| 28 |
+
# instances) that might have been saved with a __main__ module reference.
|
| 29 |
+
from src.data_preprocessing import COCOVocabulary
|
| 30 |
+
from src.model import ImageCaptioningModel
|
| 31 |
+
|
| 32 |
+
# Now import the necessary functions and modules from your project
|
| 33 |
+
from src.inference_api import generate_caption_for_image # Your existing captioning function
|
| 34 |
+
from src.utils import get_logger # Your existing logger utility
|
| 35 |
+
|
| 36 |
+
# Import YOLO for segmentation - adapted from your file.py
|
| 37 |
+
try:
|
| 38 |
+
from ultralytics import YOLO
|
| 39 |
+
# Logger initialization moved here to ensure it's after all necessary imports
|
| 40 |
+
logger = get_logger(__name__)
|
| 41 |
+
except ImportError:
|
| 42 |
+
logger = get_logger(__name__)
|
| 43 |
+
logger.error("ultralytics library not found. Please install it: pip install ultralytics")
|
| 44 |
+
YOLO = None # Set to None if import fails
|
| 45 |
+
|
| 46 |
+
# --- Flask App Setup ---
|
| 47 |
+
app = Flask(__name__)
|
| 48 |
+
|
| 49 |
+
# --- Configuration ---
|
| 50 |
+
# Strong secret key for session management (IMPORTANT: Change this in production!)
|
| 51 |
+
app.config['SECRET_KEY'] = os.urandom(24)
|
| 52 |
+
# SQLite database for users
|
| 53 |
+
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///users.db'
|
| 54 |
+
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
|
| 55 |
+
|
| 56 |
+
# Define the folder to store uploaded images temporarily within the static directory
|
| 57 |
+
UPLOAD_FOLDER = os.path.join('static', 'uploads')
|
| 58 |
+
ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'gif'}
|
| 59 |
+
|
| 60 |
+
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
|
| 61 |
+
|
| 62 |
+
# Ensure the upload folder exists
|
| 63 |
+
os.makedirs(os.path.join(app.root_path, UPLOAD_FOLDER), exist_ok=True)
|
| 64 |
+
logger.info(f"Upload folder '{UPLOAD_FOLDER}' ensured at {os.path.join(app.root_path, UPLOAD_FOLDER)}")
|
| 65 |
+
|
| 66 |
+
# --- Database Initialization ---
|
| 67 |
+
db = SQLAlchemy(app)
|
| 68 |
+
|
| 69 |
+
# Suppress some logging for cleaner output, but keep our custom prints
|
| 70 |
+
logging.getLogger("werkzeug").setLevel(logging.ERROR)
|
| 71 |
+
|
| 72 |
+
# --- Database Model (from auth_app.py) ---
|
| 73 |
+
class User(db.Model):
|
| 74 |
+
id = db.Column(db.Integer, primary_key=True)
|
| 75 |
+
email = db.Column(db.String(120), unique=True, nullable=False)
|
| 76 |
+
password_hash = db.Column(db.String(256), nullable=False)
|
| 77 |
+
# Store face encodings as JSON string of a list of floats (numpy arrays are not directly JSON serializable)
|
| 78 |
+
face_encodings_json = db.Column(db.Text, nullable=True)
|
| 79 |
+
|
| 80 |
+
def __repr__(self):
|
| 81 |
+
return f'<User {self.email}>'
|
| 82 |
+
|
| 83 |
+
# Create database tables if they don't exist
|
| 84 |
+
with app.app_context():
|
| 85 |
+
db.create_all()
|
| 86 |
+
print("Database tables created/checked.") # Kept print from your auth_app.py
|
| 87 |
+
|
| 88 |
+
# --- Global Segmentation Model Loading ---
|
| 89 |
+
# Captioning model is assumed to be loaded/handled by generate_caption_for_image internally.
|
| 90 |
+
segmentation_model_yolo = None
|
| 91 |
+
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
| 92 |
+
logger.info(f"Using device for models: {device}")
|
| 93 |
+
|
| 94 |
+
try:
|
| 95 |
+
if YOLO: # Only try to load if ultralytics import was successful
|
| 96 |
+
segmentation_model_yolo = YOLO('yolov8x-seg.pt') # YOLOv8x-seg is a large segmentation model
|
| 97 |
+
segmentation_model_yolo.to(device) # Move model to appropriate device
|
| 98 |
+
logger.info("Segmentation Model (YOLOv8x-seg) loaded successfully.")
|
| 99 |
+
else:
|
| 100 |
+
logger.warning("YOLO library not available, skipping segmentation model loading.")
|
| 101 |
+
except Exception as e:
|
| 102 |
+
logger.critical(f"Error loading Segmentation Model (YOLOv8x-seg): {e}", exc_info=True)
|
| 103 |
+
segmentation_model_yolo = None
|
| 104 |
+
|
| 105 |
+
# --- Helper Functions for Facial Recognition (Copied directly from your working auth_app.py) ---
|
| 106 |
+
def get_face_encoding_from_image(image_data_b64):
|
| 107 |
+
"""
|
| 108 |
+
Decodes base64 image data, finds faces, and returns the first face's encoding.
|
| 109 |
+
Returns None if no face is found or on error.
|
| 110 |
+
"""
|
| 111 |
+
try:
|
| 112 |
+
print(f"Processing image data of length: {len(image_data_b64)}") # From your auth_app.py
|
| 113 |
+
|
| 114 |
+
# Handle both formats: with and without data URL prefix
|
| 115 |
+
if ',' in image_data_b64:
|
| 116 |
+
# Remove data URL prefix (e.g., "data:image/jpeg;base64,")
|
| 117 |
+
image_data_clean = image_data_b64.split(',')[1]
|
| 118 |
+
else:
|
| 119 |
+
image_data_clean = image_data_b64
|
| 120 |
+
|
| 121 |
+
# Add padding if needed (base64 strings must be multiples of 4)
|
| 122 |
+
missing_padding = len(image_data_clean) % 4
|
| 123 |
+
if missing_padding:
|
| 124 |
+
image_data_clean += '=' * (4 - missing_padding)
|
| 125 |
+
|
| 126 |
+
try:
|
| 127 |
+
image_bytes = base64.b64decode(image_data_clean)
|
| 128 |
+
except Exception as decode_error:
|
| 129 |
+
print(f"Base64 decode error: {decode_error}") # From your auth_app.py
|
| 130 |
+
return None
|
| 131 |
+
|
| 132 |
+
print(f"Decoded image bytes length: {len(image_bytes)}") # From your auth_app.py
|
| 133 |
+
|
| 134 |
+
# Open and convert image
|
| 135 |
+
try:
|
| 136 |
+
img = Image.open(BytesIO(image_bytes))
|
| 137 |
+
print(f"Image opened successfully. Format: {img.format}, Size: {img.size}, Mode: {img.mode}") # From your auth_app.py
|
| 138 |
+
|
| 139 |
+
# Convert to RGB if needed
|
| 140 |
+
if img.mode != 'RGB':
|
| 141 |
+
img = img.convert('RGB')
|
| 142 |
+
print(f"Converted image to RGB mode") # From your auth_app.py
|
| 143 |
+
|
| 144 |
+
except Exception as img_error:
|
| 145 |
+
print(f"Image opening/conversion error: {img_error}") # From your auth_app.py
|
| 146 |
+
return None
|
| 147 |
+
|
| 148 |
+
# Convert PIL Image to numpy array (face_recognition expects numpy array)
|
| 149 |
+
img_np = np.array(img)
|
| 150 |
+
print(f"Numpy array shape: {img_np.shape}") # From your auth_app.py
|
| 151 |
+
|
| 152 |
+
# Find face encodings
|
| 153 |
+
try:
|
| 154 |
+
face_locations = face_recognition.face_locations(img_np)
|
| 155 |
+
print(f"Found {len(face_locations)} face location(s)") # From your auth_app.py
|
| 156 |
+
|
| 157 |
+
if len(face_locations) == 0:
|
| 158 |
+
print("No faces detected in the image") # From your auth_app.py
|
| 159 |
+
return None
|
| 160 |
+
|
| 161 |
+
face_encodings = face_recognition.face_encodings(img_np, face_locations)
|
| 162 |
+
print(f"Generated {len(face_encodings)} face encoding(s)") # From your auth_app.py
|
| 163 |
+
|
| 164 |
+
if len(face_encodings) > 0:
|
| 165 |
+
encoding = face_encodings[0]
|
| 166 |
+
print(f"Face encoding shape: {encoding.shape}") # From your auth_app.py
|
| 167 |
+
return encoding.tolist() # Convert numpy array to list for JSON serialization
|
| 168 |
+
else:
|
| 169 |
+
print("No face encodings generated despite face locations found") # From your auth_app.py
|
| 170 |
+
return None
|
| 171 |
+
|
| 172 |
+
except Exception as face_error:
|
| 173 |
+
print(f"Face recognition processing error: {face_error}") # From your auth_app.py
|
| 174 |
+
return None
|
| 175 |
+
|
| 176 |
+
except Exception as e:
|
| 177 |
+
print(f"General error processing image for face encoding: {e}") # From your auth_app.py
|
| 178 |
+
return None
|
| 179 |
+
|
| 180 |
+
def compare_face_encoding_to_stored(live_encoding, stored_encodings_json):
|
| 181 |
+
"""
|
| 182 |
+
Compares a live face encoding to a list of stored encodings for a user.
|
| 183 |
+
Returns True if a match is found, False otherwise.
|
| 184 |
+
"""
|
| 185 |
+
if not live_encoding:
|
| 186 |
+
print("Live encoding is None, cannot compare.") # From your auth_app.py
|
| 187 |
+
return False
|
| 188 |
+
if not stored_encodings_json:
|
| 189 |
+
print("Stored encodings JSON is None, cannot compare.") # From your auth_app.py
|
| 190 |
+
return False
|
| 191 |
+
|
| 192 |
+
try:
|
| 193 |
+
# Convert JSON string back to a list of numpy arrays
|
| 194 |
+
stored_encodings_list = json.loads(stored_encodings_json)
|
| 195 |
+
if not stored_encodings_list:
|
| 196 |
+
print("No stored encodings found in JSON") # From your auth_app.py
|
| 197 |
+
return False
|
| 198 |
+
|
| 199 |
+
stored_encodings = [np.array(e) for e in stored_encodings_list]
|
| 200 |
+
print(f"Comparing against {len(stored_encodings)} stored encodings") # From your auth_app.py
|
| 201 |
+
|
| 202 |
+
# Compare the live encoding against all stored encodings for this user
|
| 203 |
+
# tolerance: lower value means stricter match (0.6 is common default)
|
| 204 |
+
matches = face_recognition.compare_faces(stored_encodings, np.array(live_encoding), tolerance=0.6)
|
| 205 |
+
|
| 206 |
+
match_found = True in matches
|
| 207 |
+
print(f"Face comparison result: {match_found}. Matches: {matches}") # From your auth_app.py
|
| 208 |
+
|
| 209 |
+
return match_found
|
| 210 |
+
except Exception as e:
|
| 211 |
+
print(f"Error comparing face encodings: {e}") # From your auth_app.py
|
| 212 |
+
return False
|
| 213 |
+
|
| 214 |
+
# --- Segmentation Helper Functions (from web_app.py, adapted from file.py) ---
|
| 215 |
+
def calculate_segmentation_metrics(results, segmentation_model_ref):
|
| 216 |
+
"""
|
| 217 |
+
Calculates basic segmentation metrics (detected objects).
|
| 218 |
+
Adapted to remove Streamlit dependencies and reliance on mock GT.
|
| 219 |
+
"""
|
| 220 |
+
metrics = {
|
| 221 |
+
'detected_objects': [],
|
| 222 |
+
'num_objects': 0,
|
| 223 |
+
'status': 'Processed',
|
| 224 |
+
'error': None
|
| 225 |
+
}
|
| 226 |
+
|
| 227 |
+
if not segmentation_model_ref:
|
| 228 |
+
metrics['error'] = "Segmentation model not loaded."
|
| 229 |
+
metrics['status'] = "Error: Segmentation model unavailable."
|
| 230 |
+
return metrics
|
| 231 |
+
|
| 232 |
+
if not results or results[0].masks is None or len(results[0].masks) == 0:
|
| 233 |
+
metrics['status'] = "No objects detected."
|
| 234 |
+
return metrics
|
| 235 |
+
|
| 236 |
+
try:
|
| 237 |
+
detected_objects_info = []
|
| 238 |
+
for r_box in results[0].boxes.data.tolist():
|
| 239 |
+
class_id = int(r_box[5])
|
| 240 |
+
confidence = round(r_box[4], 2)
|
| 241 |
+
# Ensure class_id exists in model.names
|
| 242 |
+
class_name = segmentation_model_ref.names.get(class_id, f"Class {class_id}")
|
| 243 |
+
detected_objects_info.append(f"{class_name} (Conf: {confidence})")
|
| 244 |
+
|
| 245 |
+
metrics['detected_objects'] = detected_objects_info
|
| 246 |
+
metrics['num_objects'] = len(detected_objects_info)
|
| 247 |
+
|
| 248 |
+
except Exception as e:
|
| 249 |
+
metrics['error'] = f"Metric calculation failed: {str(e)}"
|
| 250 |
+
metrics['status'] = "Error during metric calculation."
|
| 251 |
+
logger.error(f"Metric calculation failed: {e}", exc_info=True)
|
| 252 |
+
|
| 253 |
+
return metrics
|
| 254 |
+
|
| 255 |
+
def perform_segmentation(image_path, model_ref, upload_folder, filename_stem):
|
| 256 |
+
"""
|
| 257 |
+
Performs segmentation on an image and returns the URL of the segmented image
|
| 258 |
+
and a dictionary of metrics.
|
| 259 |
+
"""
|
| 260 |
+
segmented_image_url = None
|
| 261 |
+
metrics = {}
|
| 262 |
+
|
| 263 |
+
if not model_ref:
|
| 264 |
+
metrics = {'error': "Segmentation model not loaded."}
|
| 265 |
+
return segmented_image_url, metrics
|
| 266 |
+
|
| 267 |
+
try:
|
| 268 |
+
img_pil = Image.open(image_path).convert('RGB')
|
| 269 |
+
img_np = np.array(img_pil) # Convert to NumPy array
|
| 270 |
+
img_cv2 = cv2.cvtColor(img_np, cv2.COLOR_RGB2BGR) # YOLO expects BGR
|
| 271 |
+
|
| 272 |
+
# Perform inference
|
| 273 |
+
results = model_ref(img_cv2, verbose=False) # verbose=False suppresses console output
|
| 274 |
+
|
| 275 |
+
if results and results[0].masks is not None and len(results[0].masks) > 0:
|
| 276 |
+
# Plot results directly onto the image
|
| 277 |
+
annotated_image = results[0].plot() # This returns a numpy array (BGR)
|
| 278 |
+
|
| 279 |
+
# Convert BGR (OpenCV default) to RGB for PIL and saving
|
| 280 |
+
annotated_image_rgb = cv2.cvtColor(annotated_image, cv2.COLOR_BGR2RGB)
|
| 281 |
+
img_segmented_pil = Image.fromarray(annotated_image_rgb)
|
| 282 |
+
|
| 283 |
+
# Save the segmented image
|
| 284 |
+
segmented_filename = f"segmented_{filename_stem}.png" # Ensure .png extension for segmented output
|
| 285 |
+
segmented_filepath = os.path.join(upload_folder, segmented_filename)
|
| 286 |
+
img_segmented_pil.save(segmented_filepath)
|
| 287 |
+
segmented_image_url = url_for('static', filename=f'uploads/{segmented_filename}')
|
| 288 |
+
logger.info(f"Segmented image saved to: {segmented_filepath}")
|
| 289 |
+
|
| 290 |
+
# Calculate and return metrics
|
| 291 |
+
metrics = calculate_segmentation_metrics(results, model_ref)
|
| 292 |
+
metrics['status'] = "Segmentation successful."
|
| 293 |
+
else:
|
| 294 |
+
metrics['status'] = "No objects detected for segmentation."
|
| 295 |
+
logger.info(f"No objects detected for segmentation in {image_path}.")
|
| 296 |
+
|
| 297 |
+
except Exception as e:
|
| 298 |
+
metrics['error'] = str(e)
|
| 299 |
+
metrics['status'] = "Error during segmentation processing."
|
| 300 |
+
logger.critical(f"Error in perform_segmentation for {image_path}: {e}", exc_info=True)
|
| 301 |
+
|
| 302 |
+
return segmented_image_url, metrics
|
| 303 |
+
|
| 304 |
+
# --- Helper for file extension check ---
|
| 305 |
+
def allowed_file(filename):
|
| 306 |
+
return '.' in filename and \
|
| 307 |
+
filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
|
| 308 |
+
|
| 309 |
+
# --- Before/After Request Hooks ---
|
| 310 |
+
@app.before_request
|
| 311 |
+
def load_logged_in_user():
|
| 312 |
+
user_id = session.get('user_id')
|
| 313 |
+
if user_id is None:
|
| 314 |
+
g.user = None
|
| 315 |
+
else:
|
| 316 |
+
g.user = User.query.get(user_id)
|
| 317 |
+
|
| 318 |
+
# --- Authentication Decorator ---
|
| 319 |
+
def login_required(view):
|
| 320 |
+
@wraps(view)
|
| 321 |
+
def wrapped_view(**kwargs):
|
| 322 |
+
if g.user is None:
|
| 323 |
+
flash("Please log in to access this page.", "info")
|
| 324 |
+
return redirect(url_for('auth_page'))
|
| 325 |
+
return view(**kwargs)
|
| 326 |
+
return wrapped_view
|
| 327 |
+
|
| 328 |
+
|
| 329 |
+
# --- Routes (Combined from both previous apps, authentication parts use print for logs) ---
|
| 330 |
+
|
| 331 |
+
# Authentication Page Route (Root)
|
| 332 |
+
@app.route('/')
|
| 333 |
+
def auth_page():
|
| 334 |
+
"""Serves the authentication HTML page. Redirects to main_app if logged in."""
|
| 335 |
+
if 'user_id' in session: # Use session directly as in your original auth_app.py
|
| 336 |
+
user = User.query.get(session['user_id'])
|
| 337 |
+
if user:
|
| 338 |
+
# If already logged in, redirect to main_app
|
| 339 |
+
print(f"User {user.email} already logged in, redirecting to main_app.")
|
| 340 |
+
return redirect(url_for('main_app'))
|
| 341 |
+
else:
|
| 342 |
+
session.pop('user_id', None) # Clear invalid session
|
| 343 |
+
print("Invalid user_id in session, redirecting to auth_page.")
|
| 344 |
+
return redirect(url_for('auth_page'))
|
| 345 |
+
print("Serving auth.html for login/registration.")
|
| 346 |
+
return render_template('auth.html')
|
| 347 |
+
|
| 348 |
+
@app.route('/register', methods=['POST'])
|
| 349 |
+
def register():
|
| 350 |
+
"""Handles traditional email/password registration."""
|
| 351 |
+
email = request.form['email'].strip() # Use .strip() to remove whitespace
|
| 352 |
+
password = request.form['password']
|
| 353 |
+
print(f"Received traditional registration request for: {email}") # Kept print from your auth_app.py
|
| 354 |
+
|
| 355 |
+
if not email or not password:
|
| 356 |
+
print("Error: Email or password missing for traditional registration.") # From auth_app.py
|
| 357 |
+
return jsonify({'success': False, 'message': 'Email and password are required.'}), 400
|
| 358 |
+
|
| 359 |
+
import re # Make sure re is imported
|
| 360 |
+
email_pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
|
| 361 |
+
if not re.match(email_pattern, email):
|
| 362 |
+
print(f"Error: Invalid email format: {email}")
|
| 363 |
+
return jsonify({'success': False, 'message': 'Please enter a valid email address.'}), 400
|
| 364 |
+
|
| 365 |
+
if len(password) < 6:
|
| 366 |
+
print("Error: Password too short.") # From auth_app.py
|
| 367 |
+
return jsonify({'success': False, 'message': 'Password must be at least 6 characters long.'}), 400
|
| 368 |
+
|
| 369 |
+
existing_user = User.query.filter_by(email=email).first()
|
| 370 |
+
if existing_user:
|
| 371 |
+
print(f"Error: Email {email} already registered.") # From auth_app.py
|
| 372 |
+
return jsonify({'success': False, 'message': 'Email already registered.'}), 409
|
| 373 |
+
|
| 374 |
+
hashed_password = generate_password_hash(password)
|
| 375 |
+
new_user = User(email=email, password_hash=hashed_password)
|
| 376 |
+
|
| 377 |
+
try:
|
| 378 |
+
db.session.add(new_user)
|
| 379 |
+
db.session.commit()
|
| 380 |
+
print(f"Traditional registration successful for: {email}") # From auth_app.py
|
| 381 |
+
return jsonify({'success': True, 'message': 'Registration successful. You can now log in.'})
|
| 382 |
+
except Exception as e:
|
| 383 |
+
db.session.rollback()
|
| 384 |
+
print(f"Database error during traditional registration: {e}") # From auth_app.py
|
| 385 |
+
return jsonify({'success': False, 'message': 'Database error during registration.'}), 500
|
| 386 |
+
|
| 387 |
+
|
| 388 |
+
@app.route('/login', methods=['POST'])
|
| 389 |
+
def login():
|
| 390 |
+
"""Handles traditional email/password login."""
|
| 391 |
+
email = request.form['email'].strip() # Use .strip()
|
| 392 |
+
password = request.form['password']
|
| 393 |
+
print(f"Received traditional login request for: {email}") # From auth_app.py
|
| 394 |
+
|
| 395 |
+
user = User.query.filter_by(email=email).first()
|
| 396 |
+
|
| 397 |
+
if user and check_password_hash(user.password_hash, password):
|
| 398 |
+
session['user_id'] = user.id
|
| 399 |
+
print(f"Traditional login successful for: {email}") # From auth_app.py
|
| 400 |
+
return jsonify({'success': True, 'message': 'Login successful.'})
|
| 401 |
+
else:
|
| 402 |
+
print(f"Traditional login failed for: {email}") # From auth_app.py
|
| 403 |
+
return jsonify({'success': False, 'message': 'Invalid email or password.'}), 401
|
| 404 |
+
|
| 405 |
+
@app.route('/face_register', methods=['POST'])
|
| 406 |
+
def face_register():
|
| 407 |
+
"""
|
| 408 |
+
Receives face images for registration.
|
| 409 |
+
Expects email, password, and a list of base64 image data from the frontend.
|
| 410 |
+
"""
|
| 411 |
+
try:
|
| 412 |
+
if not request.is_json:
|
| 413 |
+
print("Error: Request is not JSON for face_register") # From auth_app.py
|
| 414 |
+
return jsonify({'success': False, 'message': 'Invalid request format. JSON expected.'}), 400
|
| 415 |
+
|
| 416 |
+
data = request.get_json()
|
| 417 |
+
if not data:
|
| 418 |
+
print("Error: No JSON data received for face_register") # From auth_app.py
|
| 419 |
+
return jsonify({'success': False, 'message': 'No data received.'}), 400
|
| 420 |
+
|
| 421 |
+
email = data.get('email', '').strip() # Use .strip()
|
| 422 |
+
password = data.get('password', '')
|
| 423 |
+
image_data_list = data.get('images', [])
|
| 424 |
+
|
| 425 |
+
print(f"Received face registration request for: {email} with {len(image_data_list)} images.") # From auth_app.py
|
| 426 |
+
|
| 427 |
+
if not email or not password or not image_data_list:
|
| 428 |
+
print("Error: Missing email, password or image data for face registration.") # From auth_app.py
|
| 429 |
+
return jsonify({'success': False, 'message': 'Email, password, and face images are required.'}), 400
|
| 430 |
+
|
| 431 |
+
import re # Make sure re is imported
|
| 432 |
+
email_pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
|
| 433 |
+
if not re.match(email_pattern, email):
|
| 434 |
+
print(f"Error: Invalid email format: {email}")
|
| 435 |
+
return jsonify({'success': False, 'message': 'Please enter a valid email address.'}), 400
|
| 436 |
+
|
| 437 |
+
if len(password) < 6:
|
| 438 |
+
print("Error: Password too short for face registration.") # From auth_app.py
|
| 439 |
+
return jsonify({'success': False, 'message': 'Password must be at least 6 characters long.'}), 400
|
| 440 |
+
|
| 441 |
+
existing_user = User.query.filter_by(email=email).first()
|
| 442 |
+
if existing_user:
|
| 443 |
+
print(f"Error: Email {email} already registered for face registration.") # From auth_app.py
|
| 444 |
+
return jsonify({'success': False, 'message': 'Email already registered.'}), 409
|
| 445 |
+
|
| 446 |
+
all_encodings = []
|
| 447 |
+
for i, img_b64 in enumerate(image_data_list):
|
| 448 |
+
print(f"Processing image {i+1}/{len(image_data_list)} for face encoding...") # From auth_app.py
|
| 449 |
+
|
| 450 |
+
if not img_b64:
|
| 451 |
+
print(f"Warning: Image {i+1} is empty, skipping.") # From auth_app.py
|
| 452 |
+
continue
|
| 453 |
+
|
| 454 |
+
encoding = get_face_encoding_from_image(img_b64)
|
| 455 |
+
if encoding:
|
| 456 |
+
all_encodings.append(encoding)
|
| 457 |
+
print(f"Successfully processed image {i+1}") # From auth_app.py
|
| 458 |
+
else:
|
| 459 |
+
print(f"Failed to process image {i+1} - no face detected or processing error.") # From auth_app.py
|
| 460 |
+
|
| 461 |
+
if not all_encodings:
|
| 462 |
+
print("Error: No detectable faces found in any of the provided images for face registration.") # From auth_app.py
|
| 463 |
+
return jsonify({'success': False, 'message': 'No detectable faces in the provided images. Please try again with clearer images showing your face clearly.'}), 400
|
| 464 |
+
|
| 465 |
+
hashed_password = generate_password_hash(password)
|
| 466 |
+
face_encodings_json = json.dumps(all_encodings)
|
| 467 |
+
|
| 468 |
+
new_user = User(email=email, password_hash=hashed_password, face_encodings_json=face_encodings_json)
|
| 469 |
+
|
| 470 |
+
try:
|
| 471 |
+
db.session.add(new_user)
|
| 472 |
+
db.session.commit()
|
| 473 |
+
print(f"Face registration successful for: {email}. Stored {len(all_encodings)} encodings.") # From auth_app.py
|
| 474 |
+
return jsonify({'success': True, 'message': f'Face registration successful with {len(all_encodings)} face samples. You can now log in with your face.'})
|
| 475 |
+
except Exception as db_error:
|
| 476 |
+
db.session.rollback()
|
| 477 |
+
print(f"Database error during face registration: {db_error}") # From auth_app.py
|
| 478 |
+
return jsonify({'success': False, 'message': 'Database error during registration. Please try again.'}), 500
|
| 479 |
+
|
| 480 |
+
except Exception as e:
|
| 481 |
+
print(f"Unexpected error during face registration: {e}") # From auth_app.py
|
| 482 |
+
import traceback
|
| 483 |
+
traceback.print_exc()
|
| 484 |
+
return jsonify({'success': False, 'message': 'An unexpected error occurred. Please try again.'}), 500
|
| 485 |
+
|
| 486 |
+
|
| 487 |
+
@app.route('/face_login', methods=['POST'])
|
| 488 |
+
def face_login():
|
| 489 |
+
"""
|
| 490 |
+
Receives a single live face image for login.
|
| 491 |
+
Compares it against all registered users' face encodings.
|
| 492 |
+
"""
|
| 493 |
+
try:
|
| 494 |
+
if not request.is_json:
|
| 495 |
+
print("Error: Request is not JSON for face_login") # From auth_app.py
|
| 496 |
+
return jsonify({'success': False, 'message': 'Invalid request format. JSON expected.'}), 400
|
| 497 |
+
|
| 498 |
+
data = request.get_json()
|
| 499 |
+
if not data:
|
| 500 |
+
print("Error: No JSON data received for face_login") # From auth_app.py
|
| 501 |
+
return jsonify({'success': False, 'message': 'No data received.'}), 400
|
| 502 |
+
|
| 503 |
+
image_data = data.get('image')
|
| 504 |
+
print("Received face login request.") # From auth_app.py
|
| 505 |
+
|
| 506 |
+
if not image_data:
|
| 507 |
+
print("Error: Face image required for login.") # From auth_app.py
|
| 508 |
+
return jsonify({'success': False, 'message': 'Face image required for login.'}), 400
|
| 509 |
+
|
| 510 |
+
live_encoding = get_face_encoding_from_image(image_data)
|
| 511 |
+
if not live_encoding:
|
| 512 |
+
print("No face detected in the live image for login.") # From auth_app.py
|
| 513 |
+
return jsonify({'success': False, 'message': 'No face detected. Please position your face clearly in the camera and ensure good lighting.'}), 400
|
| 514 |
+
|
| 515 |
+
users = User.query.filter(User.face_encodings_json.isnot(None)).all()
|
| 516 |
+
print(f"Attempting to match against {len(users)} registered users with face data...") # From auth_app.py
|
| 517 |
+
|
| 518 |
+
for user in users:
|
| 519 |
+
if user.face_encodings_json:
|
| 520 |
+
print(f"Comparing live encoding with stored encodings for user: {user.email}") # From auth_app.py
|
| 521 |
+
if compare_face_encoding_to_stored(live_encoding, user.face_encodings_json):
|
| 522 |
+
session['user_id'] = user.id
|
| 523 |
+
print(f"Face login successful for user: {user.email}") # From auth_app.py
|
| 524 |
+
return jsonify({'success': True, 'message': f'Welcome back, {user.email}!'})
|
| 525 |
+
|
| 526 |
+
print("Face not recognized against any registered user.") # From auth_app.py
|
| 527 |
+
return jsonify({'success': False, 'message': 'Face not recognized. Please try again or use email/password login.'}), 401
|
| 528 |
+
|
| 529 |
+
except Exception as e:
|
| 530 |
+
print(f"Unexpected error during face login: {e}") # From auth_app.py
|
| 531 |
+
import traceback
|
| 532 |
+
traceback.print_exc()
|
| 533 |
+
return jsonify({'success': False, 'message': 'An error occurred during face login. Please try again.'}), 500
|
| 534 |
+
|
| 535 |
+
@app.route('/logout')
|
| 536 |
+
def logout():
|
| 537 |
+
"""Logs out the current user."""
|
| 538 |
+
print(f"User {session.get('user_id')} logging out.") # From auth_app.py
|
| 539 |
+
session.pop('user_id', None)
|
| 540 |
+
flash("You have been logged out.", "info") # Added for consistency with other parts
|
| 541 |
+
return redirect(url_for('auth_page'))
|
| 542 |
+
|
| 543 |
+
# Main application route (protected)
|
| 544 |
+
@app.route('/main_app')
|
| 545 |
+
@login_required
|
| 546 |
+
def main_app():
|
| 547 |
+
"""
|
| 548 |
+
Renders the main image processing page only if the user is authenticated.
|
| 549 |
+
"""
|
| 550 |
+
return render_template('index.html',
|
| 551 |
+
caption=None,
|
| 552 |
+
uploaded_image_url=None,
|
| 553 |
+
segmentation_image_url=None,
|
| 554 |
+
segmentation_metrics={})
|
| 555 |
+
|
| 556 |
+
# Predict route (protected)
|
| 557 |
+
@app.route('/predict', methods=['POST'])
|
| 558 |
+
@login_required
|
| 559 |
+
def predict():
|
| 560 |
+
"""
|
| 561 |
+
Handles image upload, performs captioning and segmentation,
|
| 562 |
+
and renders the results.
|
| 563 |
+
"""
|
| 564 |
+
logger.info("Received request to /predict.")
|
| 565 |
+
|
| 566 |
+
# Initialize variables for the template
|
| 567 |
+
generated_caption = "N/A"
|
| 568 |
+
uploaded_image_url = None
|
| 569 |
+
segmentation_image_url = None
|
| 570 |
+
segmentation_metrics = {}
|
| 571 |
+
|
| 572 |
+
if 'file' not in request.files:
|
| 573 |
+
flash('No file part in the request.', 'error')
|
| 574 |
+
logger.warning("No file part.")
|
| 575 |
+
return redirect(request.url)
|
| 576 |
+
|
| 577 |
+
file = request.files['file']
|
| 578 |
+
if file.filename == '':
|
| 579 |
+
flash('No selected file.', 'error')
|
| 580 |
+
logger.warning("Empty filename.")
|
| 581 |
+
return redirect(request.url)
|
| 582 |
+
|
| 583 |
+
if file and allowed_file(file.filename):
|
| 584 |
+
filename = secure_filename(file.filename)
|
| 585 |
+
# Extract filename stem (without extension) for segmented image naming
|
| 586 |
+
filename_stem, file_ext = os.path.splitext(filename)
|
| 587 |
+
|
| 588 |
+
# Construct the full path to save the original image
|
| 589 |
+
original_filepath = os.path.join(app.root_path, app.config['UPLOAD_FOLDER'], filename)
|
| 590 |
+
file.save(original_filepath)
|
| 591 |
+
uploaded_image_url = url_for('static', filename=f'uploads/{filename}')
|
| 592 |
+
logger.info(f"Original image saved to: {original_filepath}")
|
| 593 |
+
|
| 594 |
+
# --- Perform Image Captioning (using your provided correct method) ---
|
| 595 |
+
try:
|
| 596 |
+
logger.info(f"Starting caption generation for {original_filepath}...")
|
| 597 |
+
# This is your original working call for captioning
|
| 598 |
+
generated_caption = generate_caption_for_image(original_filepath)
|
| 599 |
+
logger.info(f"Caption generated: '{generated_caption}'")
|
| 600 |
+
flash("Image caption generated successfully!", 'success')
|
| 601 |
+
except FileNotFoundError:
|
| 602 |
+
flash(f"Error: Captioning model or vocabulary file not found for {original_filepath}. Check server logs.", 'error')
|
| 603 |
+
logger.error(f"Captioning model/vocab not found during inference for {original_filepath}.")
|
| 604 |
+
generated_caption = "Error: Captioning model/vocab not found."
|
| 605 |
+
except RuntimeError as re:
|
| 606 |
+
flash(f"Error: Captioning model not initialized or device issue. Check server logs.", 'error')
|
| 607 |
+
logger.critical(f"Captioning model not initialized: {re}", exc_info=True)
|
| 608 |
+
generated_caption = "Error: Captioning service unavailable."
|
| 609 |
+
except Exception as e:
|
| 610 |
+
flash(f"An unexpected error occurred during caption generation. Check server logs.", 'error')
|
| 611 |
+
logger.critical(f"Error generating caption for {original_filepath}: {e}", exc_info=True)
|
| 612 |
+
generated_caption = "Error: Could not generate caption."
|
| 613 |
+
|
| 614 |
+
|
| 615 |
+
# --- Perform Image Segmentation ---
|
| 616 |
+
if segmentation_model_yolo:
|
| 617 |
+
logger.info(f"Starting segmentation for {original_filepath} using YOLO...")
|
| 618 |
+
segmentation_image_url, segmentation_metrics = perform_segmentation(
|
| 619 |
+
image_path=original_filepath,
|
| 620 |
+
model_ref=segmentation_model_yolo,
|
| 621 |
+
upload_folder=os.path.join(app.root_path, app.config['UPLOAD_FOLDER']),
|
| 622 |
+
filename_stem=filename_stem
|
| 623 |
+
)
|
| 624 |
+
if 'error' in segmentation_metrics and segmentation_metrics['error']:
|
| 625 |
+
flash(f"Segmentation Error: {segmentation_metrics['error']}", 'error')
|
| 626 |
+
elif segmentation_image_url:
|
| 627 |
+
flash("Image segmentation performed successfully!", 'success')
|
| 628 |
+
else:
|
| 629 |
+
flash(f"Segmentation: {segmentation_metrics.get('status', 'No specific status.')}", 'info')
|
| 630 |
+
else:
|
| 631 |
+
flash("Segmentation model not initialized. Ensure 'ultralytics' is installed and model loaded.", 'error')
|
| 632 |
+
logger.error("Segmentation model (YOLO) is not available.")
|
| 633 |
+
segmentation_metrics['error'] = "Segmentation service unavailable."
|
| 634 |
+
|
| 635 |
+
|
| 636 |
+
# Render the template with results for both tasks
|
| 637 |
+
return render_template('index.html',
|
| 638 |
+
caption=generated_caption,
|
| 639 |
+
uploaded_image_url=uploaded_image_url,
|
| 640 |
+
segmentation_image_url=segmentation_image_url,
|
| 641 |
+
segmentation_metrics=segmentation_metrics)
|
| 642 |
+
else:
|
| 643 |
+
flash('Allowed image types are png, jpg, jpeg, gif.', 'error')
|
| 644 |
+
logger.warning(f"Disallowed file type uploaded: {file.filename}")
|
| 645 |
+
return redirect(request.url)
|
| 646 |
+
|
| 647 |
+
if __name__ == '__main__':
|
| 648 |
+
logger.info("Starting Flask web application with integrated auth...")
|
| 649 |
+
# This app will run on port 5000, handling both auth and image processing.
|
| 650 |
+
# app.run(debug=True, host='0.0.0.0', port=5000)
|