Varsha Dewangan commited on
Commit
ee1d4aa
·
0 Parent(s):

Initial clean commit for project deployment

Browse files
.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)