Safetensors
mhassanch's picture
Add GeoText inference endpoint support
4d3c316
Raw History Blame Contribute Delete
14.8 kB
# Multi-Grained Vision Language Pre-Training: Aligning Texts with Visual Concepts (https://arxiv.org/abs/2111.08276)
# Github: https://github.com/zengyan-97/X-VLM
# Copyright (c) 2022, ByteDance Inc.
# All rights reserved.
import os
import sys
import time
import random
import argparse
import torch
from utils.hdfs_io import HADOOP_BIN, hexists, hmkdir, hcopy
# torch.autograd.set_detect_anomaly(True)
############ Set it correctly for distributed training across nodes
NNODES = 1 # e.g. 1/2/3/4
NPROC_PER_NODE = 8 # e.g. 8 gpus
MASTER_ADDR = 'SET_IT'
MASTER_PORT = 12345
NODE_RANK = 0 # e.g. 0/1/2
############
print("NNODES, ", NNODES)
print("NPROC_PER_NODE, ", NPROC_PER_NODE)
print("MASTER_ADDR, ", MASTER_ADDR)
print("MASTER_PORT, ", MASTER_PORT)
print("NODE_RANK, ", NODE_RANK)
def get_nnodes(args): # when using only part of nodes
if args.dist == 'all':
return NNODES
else:
return 1
def get_dist_launch(args): # some examples
if args.dist == 'all': # use all nodes
return "python3 -m torch.distributed.launch --nproc_per_node={:} " \
"--nnodes={:} --node_rank={:} --master_addr={:} --master_port={:}".format(
NPROC_PER_NODE, NNODES, NODE_RANK, MASTER_ADDR, MASTER_PORT)
elif args.dist == '1':
return "python3 -m torch.distributed.launch --nproc_per_node={:} " \
"--nnodes=1 ".format(NPROC_PER_NODE)
elif args.dist == 'f4':
return "CUDA_VISIBLE_DEVICES=4,5,6,7 WORLD_SIZE=1 python3 -m torch.distributed.launch --nproc_per_node=4 " \
"--nnodes=1 "
elif args.dist == 'l4':
return "CUDA_VISIBLE_DEVICES=0,1 WORLD_SIZE=1 python3 -m torch.distributed.launch --master_port=12345 --nproc_per_node=2 " \
"--nnodes=1 "
elif args.dist.startswith('gpu'): # use one gpu, --dist "gpu0"
num = int(args.dist[3:])
assert 0 <= num <= 8
return "CUDA_VISIBLE_DEVICES={:} WORLD_SIZE=1 python3 -m torch.distributed.launch --nproc_per_node=1 " \
"--nnodes=1 ".format(num)
else:
raise ValueError
def get_from_hdfs(file_hdfs):
"""
compatible to HDFS path or local path
"""
if file_hdfs.startswith('hdfs'):
file_local = os.path.split(file_hdfs)[-1]
if os.path.exists(file_local):
print(f"rm existing {file_local}")
os.system(f"rm {file_local}")
hcopy(file_hdfs, file_local)
else:
file_local = file_hdfs
assert os.path.exists(file_local)
return file_local
def run_pretrain(args):
print("### Start pre-training", flush=True)
dist_launch = get_dist_launch(args)
os.system(f"{dist_launch} --use_env Pretrain.py --config {args.config} --output_dir {args.output_dir}")
def run_pretrain_nlvr(args):
print("### Start nlvr domain pre-training", flush=True)
dist_launch = get_dist_launch(args)
if len(args.load_ckpt_from):
print(f"### Loading domain pre-trained results from: {args.load_ckpt_from}")
args.checkpoint = get_from_hdfs(args.load_ckpt_from)
else: # domain pre-train
if not os.path.exists(args.config): args.config = 'configs/NLVR_pretrain_O1.yaml'
os.system(f"{dist_launch} --use_env NLVR_pretrain.py --config {args.config} "
f"--output_dir {args.output_dir} --checkpoint {args.checkpoint}")
args.checkpoint = get_from_hdfs(f"{args.output_dir}/model_state_epoch_latest.th")
# run fine-tune
if len(args.output_dir): args.output_dir += '_nlvr2'
args.config = 'configs/NLVR.yaml'
run_nlvr2(args, load_nlvr_pretrain=True)
def run_pretrain_refcoco_bbox(args):
print("### Start refcoco bbox domain pre-training", flush=True)
dist_launch = get_dist_launch(args)
if len(args.load_ckpt_from):
print(f"### Loading domain pre-trained results from: {args.load_ckpt_from}")
args.checkpoint = get_from_hdfs(args.load_ckpt_from)
else: # domain pre-train
if not os.path.exists(args.config): args.config = './configs/Grounding_bbox_pretrain_O1.yaml'
os.system(f"{dist_launch} "
f"--use_env Grounding_bbox_pretrain.py --config {args.config} "
f"--output_dir {args.output_dir} --checkpoint {args.checkpoint}")
args.checkpoint = get_from_hdfs(f"{args.output_dir}/model_state_epoch_latest.th")
# run fine-tune
if len(args.output_dir): args.output_dir += '_refcoco'
args.config = 'configs/Grounding_bbox.yaml'
run_refcoco(args, use_bbox=True, load_bbox_pretrain=True)
def run_nlvr2(args, load_nlvr_pretrain=False):
dist_launch = get_dist_launch(args)
print("### Training NLVR2", flush=True)
os.system(f"{dist_launch} "
f"--use_env NLVR.py --config {args.config} "
f"--output_dir {args.output_dir} --bs {args.bs} --checkpoint {args.checkpoint} {'--load_nlvr_pretrain' if load_nlvr_pretrain else ''} "
f"{'--evaluate' if args.evaluate else ''}")
def run_retrieval(args):
dist_launch = get_dist_launch(args)
os.system(f"{dist_launch} "
f"--use_env Retrieval.py --config {args.config} "
f"--output_dir {args.output_dir} --bs {args.bs} --checkpoint {args.checkpoint} {'--evaluate' if args.evaluate else ''}")
def run_vqa(args):
dist_launch = get_dist_launch(args)
print("### Training VQA", flush=True)
if not os.path.exists(args.config): args.config = './configs/VQA.yaml'
os.system(f"{dist_launch} "
f"--use_env VQA.py --config {args.config} "
f"{f'--output_hdfs {args.output_hdfs}' if len(args.output_hdfs) else ''} --output_dir {args.output_dir} "
f"--bs {args.bs} --checkpoint {args.checkpoint} {'--evaluate' if args.evaluate else ''}")
def run_refcoco(args, use_bbox=False, block_num=-1, load_bbox_pretrain=False, epochs=-1):
dist_launch = get_dist_launch(args)
if use_bbox:
print("### Training RefCOCO with bbox", flush=True)
os.system(f"{dist_launch} "
f"--use_env Grounding_bbox.py --config {args.config} "
f"--output_dir {args.output_dir} {f'--output_hdfs {args.output_hdfs}' if len(args.output_hdfs) else ''} "
f"--bs {args.bs} {'--load_bbox_pretrain' if load_bbox_pretrain else ''} --checkpoint {args.checkpoint} "
f"{'--evaluate' if args.evaluate else ''}")
else:
print("### Training RefCOCO", flush=True)
os.system(f"{dist_launch} "
f"--use_env Grounding.py --config {args.config} "
f"--output_dir {args.output_dir} --bs {args.bs} {f'--output_hdfs {args.output_hdfs}' if len(args.output_hdfs) else ''} "
f"--gradcam_mode itm --block_num {block_num} --epochs {epochs} --checkpoint {args.checkpoint} "
f"{'--evaluate' if args.evaluate else ''}")
def run_pretrain_captioning(args):
print("### Start captioning domain pre-training", flush=True)
dist_launch = get_dist_launch(args)
if len(args.load_ckpt_from):
print(f"### Loading domain pre-trained results from: {args.load_ckpt_from}")
domain_ckpt = get_from_hdfs(args.load_ckpt_from)
else: # domain pre-train
if not os.path.exists(args.config): args.config = f'configs/Captioning_pretrain_O1.yaml'
os.system(f"{dist_launch} --use_env Captioning_pretrain.py --seed {args.seed} --config {args.config} "
f"--output_dir {args.output_dir} --checkpoint {args.checkpoint}")
domain_ckpt = get_from_hdfs(f"{args.output_dir}/model_state_epoch_latest.th")
return domain_ckpt
def run_coco_captioning(args, load_capt_pretrain=False, scst=False):
dist_launch = get_dist_launch(args)
assert os.path.exists("images/coco")
print("### Training COCO Captioning", flush=True)
if not os.path.exists(args.config):
args.config = f'./configs/Captioning.yaml'
if scst:
load_capt_pretrain = True # same way to load ckpt;
os.system(f"{dist_launch} "
f"--use_env {'Captioning_scst.py' if scst else 'Captioning.py'} --config {args.config} "
f"{f'--output_hdfs {args.output_hdfs}' if len(args.output_hdfs) else ''} --output_dir {args.output_dir} "
f"--bs {args.bs} --seed {args.seed} --checkpoint {args.checkpoint} "
f"{'--scst' if scst else ''} {'--load_capt_pretrain' if load_capt_pretrain else ''} {'--evaluate' if args.evaluate else ''}")
def run_re_bbox(args):
dist_launch = get_dist_launch(args)
os.system(f"{dist_launch} "
f"--use_env re_bbox.py --config {args.config} "
f"--output_dir {args.output_dir} --bs {args.bs} --checkpoint {args.checkpoint} {'--evaluate' if args.evaluate else ''}")
def run(args):
if args.task not in ['pretrain_4m_base']:
assert hexists(args.checkpoint) or hexists(args.load_ckpt_from)
if args.task == 'pretrain_4m_base':
args.config = 'configs/Pretrain_XVLM_base_4m.yaml'
run_pretrain(args)
elif args.task == 'itr_coco':
# assert os.path.exists("images/coco")
args.config = 'configs/Retrieval_coco.yaml'
run_retrieval(args)
elif args.task == 'itr_flickr':
assert os.path.exists("images/flickr30k-images")
args.config = 'configs/Retrieval_flickr.yaml'
run_retrieval(args)
elif args.task == 'vqa':
assert os.path.exists("images/coco") and os.path.exists("images/visualgenome")
run_vqa(args)
elif args.task == 'vqa_480':
assert os.path.exists("images/coco") and os.path.exists("images/visualgenome")
# if use 480x480 (the accuracy will increase 0.5%):
args.config = "configs/VQA_480.yaml"
run_vqa(args)
elif args.task == 'nlvr':
assert os.path.exists("images/nlvr2")
run_pretrain_nlvr(args)
elif args.task == 'refcoco_weakly':
assert os.path.exists("images/coco")
args.config = './configs/Grounding.yaml'
run_refcoco(args, block_num=9) # 9 for X-VLM base
elif args.task == 'refcoco_block_num_search': # for refcoco_weakly
assert os.path.exists("images/coco")
# block_num: use which layer of the cross-modal encoder for calculation
# it is a critical hyper-param for refcoco without bbox annotations
for num in [8, 9, 10, 7]:
print(f"### block_num {num}")
args.config = './configs/Grounding.yaml'
run_refcoco(args, block_num=num, epochs=1)
elif args.task == 'refcoco_bbox':
assert os.path.exists("images/coco")
run_pretrain_refcoco_bbox(args)
elif args.task.startswith('coco_capt_domain'):
domain_ckpt = run_pretrain_captioning(args)
# run fine-tune, reset args
args.checkpoint = domain_ckpt
if hexists(args.output_dir): args.output_dir = os.path.join(args.output_dir, 'coco_capt_ft')
args.config = f'./configs/Captioning.yaml'
run_coco_captioning(args, load_capt_pretrain=True)
elif args.task == 'coco_captioning':
run_coco_captioning(args, load_capt_pretrain=True)
elif args.task == 'coco_captioning_scst': # load checkpoint of 'coco_captioning' results
args.config = f'./configs/Captioning_scst.yaml'
run_coco_captioning(args, scst=True)
elif args.task == 'eval_vlue_itr':
assert os.path.exists("images/marvl")
args.config = f"configs/vlue-base-test/Retrieval.yaml"
args.evaluate = True
run_retrieval(args)
elif args.task == 'eval_vlue_vqa':
assert os.path.exists("images/marvl")
# args.config = f"configs/vlue-base-test/VQA.yaml"
args.config = f"configs/vlue-base-test/VQA_480.yaml"
args.evaluate = True
run_vqa(args)
elif args.task == 'eval_vlue_nlvr':
assert os.path.exists("images/marvl")
args.evaluate = True
args.config = f"configs/vlue-base-test/NLVR.yaml"
run_nlvr2(args)
elif args.task == 'eval_vlue_refcoco':
assert os.path.exists("images/marvl")
args.evaluate = True
args.config = f"configs/vlue-base-test/Grounding_bbox.yaml"
run_refcoco(args, use_bbox=True)
elif args.task == 'eval_vlue_refcoco_weakly':
assert os.path.exists("images/marvl")
args.evaluate = True
args.config = f"configs/vlue-base-test/Grounding_weakly.yaml"
run_refcoco(args)
elif args.task == 're_bbox':
args.config = 'configs/re_bbox.yaml'
run_re_bbox(args)
else:
raise NotImplementedError(f"task == {args.task}")
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('--task', type=str, required=True)
parser.add_argument('--dist', type=str, required=True, help="see func get_dist_launch for details")
parser.add_argument('--config', default='', type=str, help="if not given, use default")
parser.add_argument('--bs', default=-1, type=int, help="for each gpu, batch_size = bs // num_gpus; "
"this option only works for fine-tuning scripts.")
parser.add_argument('--seed', default=42, type=int)
parser.add_argument('--checkpoint', default='', type=str, help="for fine-tuning")
parser.add_argument('--load_ckpt_from', default='', type=str, help="load domain pre-trained params")
# write path: local or HDFS
parser.add_argument('--output_dir', type=str, required=True, help='for fine-tuning, local path; '
'for pre-training, local and HDFS are both allowed.')
parser.add_argument('--output_hdfs', type=str, default='', help="HDFS path required by VQA and Refcoco, "
"to collect eval results among nodes")
parser.add_argument('--evaluate', action='store_true', help="evaluation on downstream tasks")
args = parser.parse_args()
if MASTER_ADDR == 'SET_IT':
print("### warning: the settings for distributed training is not filled (ignore this if you only use one node)")
if '/SET/PATH/TO/hadoop/bin/hdfs' in HADOOP_BIN:
print("### warning: you have not set the path to hadoop_bin (ignore this if you don't use HDFS)")
assert hexists(os.path.dirname(args.output_dir))
hmkdir(args.output_dir)
if len(args.output_hdfs):
assert hexists(os.path.dirname(args.output_hdfs))
if len(args.config):
assert hexists(args.config)
if args.config.startswith('hdfs://'):
args.config = get_from_hdfs(args.config)
if args.checkpoint.startswith('hdfs://'):
args.checkpoint = get_from_hdfs(args.checkpoint)
run(args)