cham-ocr-studio / ocr-training /scripts /prepare_v24_notebook.py
phucsd's picture
Upload folder using huggingface_hub
75b8dbb verified
Raw History Blame Contribute Delete
10.6 kB
import os
import sys
import json
if sys.stdout and hasattr(sys.stdout, 'reconfigure'):
sys.stdout.reconfigure(encoding='utf-8')
def read_file(path):
with open(path, 'r', encoding='utf-8') as f:
return f.read()
def main():
print("📦 Bắt đầu đóng gói Kaggle Notebook huấn luyện V24...")
# 1. Đọc mã nguồn các script cục bộ
dict_extension_code = read_file('ocr-training/scripts/dict_extension_v24.py')
weight_surgery_code = read_file('ocr-training/scripts/weight_surgery_v24.py')
generate_data_v24_code = read_file('ocr-training/scripts/generate_data_v24.py')
config_v24_code = read_file('ocr-training/configs/rec_cham_v24.yml')
kaggle_dict_extension = dict_extension_code
kaggle_weight_surgery = weight_surgery_code
cells = []
def add_md(text):
cells.append({
"cell_type": "markdown",
"metadata": {},
"source": [line + '\n' for line in text.splitlines()]
})
def add_code(code_str):
cells.append({
"cell_type": "code",
"execution_count": None,
"metadata": {},
"outputs": [],
"source": [line + '\n' for line in code_str.splitlines()]
})
# Tiêu đề
add_md("""# Huấn Luyện Mô Hình Nhận Diện Chữ Chăm PP-OCRv4 V24 (Dual GPU T4x2)
Mô hình giải quyết triệt để:
- Số thứ tự khổ thơ Chăm 1-99 (`꩑꩞` - `꩙꩙꩞`)
- Dấu kết thúc câu kép Double Danda (`꩝꩝`)
- Dấu phụ đối kháng `ꨲ` (Au, U+AA32) vs `ꨶ` (O, U+AA36)
- Tổ hợp 3 tầng dấu phụ và bảo toàn nguyên âm trước `ꨯ`, `ꨯꨱ`
- Khả năng chống chịu Mờ rung (Motion Blur) và Nhiễu giấy cổ""")
# Phase 1: Environment & GPU Check
add_md("## Phase 1: Cài đặt thư viện & Kiểm tra GPU T4x2")
add_code("""# 1. Cài đặt PaddlePaddle GPU và các thư viện phụ trợ
!pip install --quiet "paddlepaddle-gpu>=2.6.0" "albumentations>=1.4.0" fonttools pyyaml opencv-python Pillow
# 2. Kiểm tra môi trường GPU
import os
import sys
import paddle
print("="*60)
print("PADDLE ENVIRONMENT STATUS:")
print("Paddle Version:", paddle.__version__)
print("Compiled with CUDA:", paddle.is_compiled_with_cuda())
gpu_count = paddle.device.cuda.device_count()
print(f"Detected GPU Count: {gpu_count}")
print("="*60)
if gpu_count < 1:
print("⚠️ CẢNH BÁO: Không tìm thấy GPU! Vui lòng chọn Accelerator = GPU T4 x2 trong Settings.")
else:
for i in range(gpu_count):
print(f" - GPU {i}: {paddle.device.cuda.get_device_name(i)}")
""")
# Phase 2: Setup Workspace & PaddleOCR
add_md("## Phase 2: Khởi tạo thư mục làm việc & Clone PaddleOCR")
add_code("""import os
import shutil
os.makedirs('/kaggle/working/data/fonts', exist_ok=True)
os.makedirs('/kaggle/working/data/output_v24_temp', exist_ok=True)
os.makedirs('/kaggle/working/configs', exist_ok=True)
os.makedirs('/kaggle/working/scripts', exist_ok=True)
os.makedirs('/kaggle/working/output/rec_cham_v24', exist_ok=True)
os.makedirs('/kaggle/working/output/v24_training', exist_ok=True)
# Tự động phát hiện đường dẫn Assets Input trên Kaggle
candidate_asset_dirs = [
"/kaggle/input/cham-ocr-v5-assets",
"/kaggle/input/datasets/gustavnguyen/cham-ocr-v5-assets"
]
ASSETS_DIR = None
for d in candidate_asset_dirs:
if os.path.exists(d):
ASSETS_DIR = d
break
if not ASSETS_DIR and os.path.exists('/kaggle/input'):
for root, dirs, files in os.walk('/kaggle/input'):
if 'v23_checkpoint' in dirs:
ASSETS_DIR = root
break
if not ASSETS_DIR:
raise FileNotFoundError(f"❌ LỖI: Không tìm thấy thư mục Assets trong /kaggle/input")
print(f"✅ Đã tìm thấy Assets Input tại: {ASSETS_DIR}")
# Copy fonts
fonts_src = os.path.join(ASSETS_DIR, "fonts", "fonts")
if not os.path.exists(fonts_src):
fonts_src = os.path.join(ASSETS_DIR, "fonts")
for f in os.listdir(fonts_src):
if f.endswith(('.ttf', '.otf')):
shutil.copy2(os.path.join(fonts_src, f), os.path.join('/kaggle/working/data/fonts', f))
print("✅ Đã sao chép fonts:", os.listdir('/kaggle/working/data/fonts'))
# Clone PaddleOCR nếu chưa có
if not os.path.exists('/kaggle/working/PaddleOCR'):
print("⏳ Đang clone PaddleOCR...")
!git clone --depth 1 https://github.com/PaddlePaddle/PaddleOCR.git /kaggle/working/PaddleOCR
!pip install --quiet -r /kaggle/working/PaddleOCR/requirements.txt
else:
print("✅ PaddleOCR đã tồn tại sẵn.")
""")
# Phase 3: Ghi mã nguồn các script
add_md("## Phase 3: Nạp kịch bản Sinh dữ liệu, Mở rộng từ điển & Phẫu thuật trọng số")
add_code(f"%%writefile /kaggle/working/scripts/dict_extension_v24.py\n{kaggle_dict_extension}")
add_code(f"%%writefile /kaggle/working/scripts/weight_surgery_v24.py\n{kaggle_weight_surgery}")
add_code(f"%%writefile /kaggle/working/scripts/generate_data_v24.py\n{generate_data_v24_code}")
add_code(f"%%writefile /kaggle/working/configs/rec_cham_v24.yml\n{config_v24_code}")
# Phase 4: Chạy chuẩn bị dữ liệu và phẫu thuật trọng số
add_md("## Phase 4: Mở rộng từ điển, Phẫu thuật trọng số & Sinh 50K dữ liệu V24 đặc trị")
add_code("""import os, sys, time
%cd /kaggle/working
print("=== BƯỚC 1: MỞ RỘNG TỪ ĐIỂN V24 ===")
!python3 scripts/dict_extension_v24.py
print("\\n=== BƯỚC 2: PHẪU THUẬT TRỌNG SỐ V24 ===")
!python3 scripts/weight_surgery_v24.py
print("\\n=== BƯỚC 3: SINH DỮ LIỆU TỔNG HỢP V24 ĐẶC TRỊ (45K TRAIN, 4.5K VAL) ===")
t_start = time.time()
# Chạy với 4 vCPU
!python3 scripts/generate_data_v24.py --output-dir /kaggle/working/data/cham_synthetic_v24 --fonts-dir /kaggle/working/data/fonts --num-train 45000 --num-val 4500 --num-workers 4
print(f"🎉 Hoàn thành toàn bộ dữ liệu trong {(time.time()-t_start)/60:.2f} phút!")
""")
# Phase 5: Khởi chạy huấn luyện song song phân tán trên GPU T4x2
add_md("## Phase 5: Huấn luyện phân tán song song trên Dual GPU Tesla T4x2 (20 Epochs)")
add_code("""import os
import paddle
gpu_count = paddle.device.cuda.device_count()
print(f"🔥 Khởi chạy huấn luyện với {gpu_count} GPU...")
os.environ["PYTHONUNBUFFERED"] = "1"
os.environ["FLAGS_fraction_of_gpu_memory_to_use"] = "0.90"
%cd /kaggle/working/PaddleOCR
if gpu_count > 1:
print("🚀 Sử dụng lệnh phân tán song song đa GPU (paddle.distributed.launch --gpus '0,1'):")
!python3 -m paddle.distributed.launch --gpus '0,1' tools/train.py -c /kaggle/working/configs/rec_cham_v24.yml
else:
print("⚡ Huấn luyện trên Single GPU:")
!python3 tools/train.py -c /kaggle/working/configs/rec_cham_v24.yml
""")
# Phase 6: Xuất mô hình Inference & Đóng gói ZIP
add_md("## Phase 6: Xuất mô hình Inference & Đóng gói rec_cham_v24_best.zip")
add_code("""import os
import shutil
import zipfile
%cd /kaggle/working/PaddleOCR
best_ckpt = "/kaggle/working/output/rec_cham_v24/best_accuracy"
latest_ckpt = "/kaggle/working/output/rec_cham_v24/latest"
target_ckpt = best_ckpt if os.path.exists(best_ckpt + ".pdparams") else latest_ckpt
print(f"🎯 Sử dụng checkpoint: {target_ckpt}")
infer_dir = "/kaggle/working/output/rec_cham_inference_v24"
os.makedirs(infer_dir, exist_ok=True)
# Xuất mô hình inference
!python3 tools/export_model.py -c /kaggle/working/configs/rec_cham_v24.yml -o Global.pretrained_model={target_ckpt} Global.save_inference_dir={infer_dir} Global.export_with_pir=False
# Copy từ điển vào thư mục inference
shutil.copy2('/kaggle/working/data/cham_dict_v24.txt', os.path.join(infer_dir, 'cham_dict_v24.txt'))
print("✅ Thư mục Inference:", os.listdir(infer_dir))
# Đóng gói toàn bộ kết quả thành file zip trong /kaggle/working
zip_path = "/kaggle/working/rec_cham_v24_best.zip"
print(f"📦 Đang nén kết quả vào {zip_path}...")
with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
# Nén inference model
for root, dirs, files in os.walk(infer_dir):
for f in files:
full_p = os.path.join(root, f)
rel_p = os.path.relpath(full_p, "/kaggle/working")
zipf.write(full_p, rel_p)
# Nén best accuracy pdparams
for ext in [".pdparams", ".pdopt", ".states"]:
p = target_ckpt + ext
if os.path.exists(p):
zipf.write(p, os.path.join("best_checkpoint", os.path.basename(p)))
# Nén từ điển
zipf.write('/kaggle/working/data/cham_dict_v24.txt', 'cham_dict_v24.txt')
print(f"🎉 HOÀN TẤT TRỌN GÓI! File zip sẵn sàng ({os.path.getsize(zip_path) / (1024*1024):.2f} MB): {zip_path}")
""")
# 5. Lưu Notebook JSON
notebook_dict = {
"cells": cells,
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"name": "python",
"version": "3.10.12"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
submission_dir = 'ocr-training/output/kaggle_v24_submission'
os.makedirs(submission_dir, exist_ok=True)
nb_path = os.path.join(submission_dir, 'paddleocr_cham_v24_train.ipynb')
with open(nb_path, 'w', encoding='utf-8') as f:
json.dump(notebook_dict, f, indent=1, ensure_ascii=False)
meta_path = os.path.join(submission_dir, 'kernel-metadata.json')
metadata = {
"id": "gustavnguyen/paddleocr-cham-finetune",
"title": "paddleocr-cham-finetune",
"code_file": "paddleocr_cham_v24_train.ipynb",
"language": "python",
"kernel_type": "notebook",
"is_private": "true",
"enable_gpu": "true",
"enable_tpu": "false",
"enable_internet": "true",
"dataset_sources": [
"gustavnguyen/cham-ocr-v5-assets"
],
"competition_sources": [],
"kernel_sources": [],
"model_sources": []
}
with open(meta_path, 'w', encoding='utf-8') as f:
json.dump(metadata, f, indent=2)
print(f"✅ Đã tạo thành công Notebook tại: {nb_path}")
print(f"✅ Đã tạo kernel-metadata tại: {meta_path}")
return nb_path, meta_path
if __name__ == '__main__':
main()