-
Notifications
You must be signed in to change notification settings - Fork 21
/
train.py
87 lines (76 loc) · 3.42 KB
/
train.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
import os
import argparse
import random
import numpy as np
import torch
import torch.optim as opt
import torch.nn.functional as F
from torch.utils.data import DataLoader
from torch.optim.lr_scheduler import CosineAnnealingLR
from dataset import FullDataset
from SAM2UNet import SAM2UNet
parser = argparse.ArgumentParser("SAM2-UNet")
parser.add_argument("--hiera_path", type=str, required=True,
help="path to the sam2 pretrained hiera")
parser.add_argument("--train_image_path", type=str, required=True,
help="path to the image that used to train the model")
parser.add_argument("--train_mask_path", type=str, required=True,
help="path to the mask file for training")
parser.add_argument('--save_path', type=str, required=True,
help="path to store the checkpoint")
parser.add_argument("--epoch", type=int, default=20,
help="training epochs")
parser.add_argument("--lr", type=float, default=0.001, help="learning rate")
parser.add_argument("--batch_size", default=12, type=int)
parser.add_argument("--weight_decay", default=5e-4, type=float)
args = parser.parse_args()
def structure_loss(pred, mask):
weit = 1 + 5*torch.abs(F.avg_pool2d(mask, kernel_size=31, stride=1, padding=15) - mask)
wbce = F.binary_cross_entropy_with_logits(pred, mask, reduce='none')
wbce = (weit*wbce).sum(dim=(2, 3)) / weit.sum(dim=(2, 3))
pred = torch.sigmoid(pred)
inter = ((pred * mask)*weit).sum(dim=(2, 3))
union = ((pred + mask)*weit).sum(dim=(2, 3))
wiou = 1 - (inter + 1)/(union - inter+1)
return (wbce + wiou).mean()
def main(args):
dataset = FullDataset(args.train_image_path, args.train_mask_path, 352, mode='train')
dataloader = DataLoader(dataset, batch_size=args.batch_size, shuffle=True, num_workers=8)
device = torch.device("cuda")
model = SAM2UNet(args.hiera_path)
model.to(device)
optim = opt.AdamW([{"params":model.parameters(), "initia_lr": args.lr}], lr=args.lr, weight_decay=args.weight_decay)
scheduler = CosineAnnealingLR(optim, args.epoch, eta_min=1.0e-7)
os.makedirs(args.save_path, exist_ok=True)
for epoch in range(args.epoch):
for i, batch in enumerate(dataloader):
x = batch['image']
target = batch['label']
x = x.to(device)
target = target.to(device)
optim.zero_grad()
pred0, pred1, pred2 = model(x)
loss0 = structure_loss(pred0, target)
loss1 = structure_loss(pred1, target)
loss2 = structure_loss(pred2, target)
loss = loss0 + loss1 + loss2
loss.backward()
optim.step()
if i % 50 == 0:
print("epoch:{}-{}: loss:{}".format(epoch + 1, i + 1, loss.item()))
scheduler.step()
if (epoch+1) % 5 == 0 or (epoch+1) == args.epoch:
torch.save(model.state_dict(), os.path.join(args.save_path, 'SAM2-UNet-%d.pth' % (epoch + 1)))
print('[Saving Snapshot:]', os.path.join(args.save_path, 'SAM2-UNet-%d.pth'% (epoch + 1)))
# def seed_torch(seed=1024):
# random.seed(seed)
# os.environ['PYTHONHASHSEED'] = str(seed)
# np.random.seed(seed)
# torch.manual_seed(seed)
# torch.cuda.manual_seed(seed)
# torch.cuda.manual_seed_all(seed)
# torch.backends.cudnn.benchmark = False
# torch.backends.cudnn.deterministic = True
if __name__ == "__main__":
# seed_torch(1024)
main(args)