コード例 #1
0
    def __init__(self, dataloader, cfg_data, pwd):

        self.cfg_data = cfg_data

        self.data_mode = cfg.DATASET
        self.exp_name = cfg.EXP_NAME
        self.exp_path = cfg.EXP_PATH
        self.pwd = pwd

        self.net_name = cfg.NET

        self.train_loader, self.val_loader, self.restore_transform = dataloader(
        )

        if self.net_name in ['CMTL']:

            # use for gt's class labeling
            self.max_gt_count = 0.
            self.min_gt_count = 0x7f7f7f
            self.num_classes = 10
            self.bin_val = 0.

            self.pre_max_min_bin_val()
            ce_weights = torch.from_numpy(self.pre_weights()).float()

            loss_1_fn = nn.MSELoss()

            loss_2_fn = nn.BCELoss(weight=ce_weights)

        self.net = CrowdCounter(cfg.GPU_ID, self.net_name, loss_1_fn,
                                loss_2_fn).cuda()
        self.optimizer = optim.Adam(self.net.CCN.parameters(),
                                    lr=cfg.LR,
                                    weight_decay=1e-4)
        # self.optimizer = optim.SGD(self.net.parameters(), cfg.LR, momentum=0.95,weight_decay=5e-4)
        self.scheduler = StepLR(self.optimizer,
                                step_size=cfg.NUM_EPOCH_LR_DECAY,
                                gamma=cfg.LR_DECAY)

        self.train_record = {
            'best_mae': 1e20,
            'best_mse': 1e20,
            'best_model_name': ''
        }
        self.timer = {
            'iter time': Timer(),
            'train time': Timer(),
            'val time': Timer()
        }
        self.writer, self.log_txt = logger(self.exp_path, self.exp_name,
                                           self.pwd, 'exp')

        self.i_tb = 0
        self.epoch = -1

        if cfg.PRE_GCC:
            net.load_state_dict(torch.load(cfg.PRE_GCC_MODEL))
コード例 #2
0
class Trainer():
    def __init__(self, dataloader, cfg_data, pwd):

        self.cfg_data = cfg_data

        self.data_mode = cfg.DATASET
        self.exp_name = cfg.EXP_NAME
        self.exp_path = cfg.EXP_PATH
        self.pwd = pwd

        self.net_name = cfg.NET

        self.train_loader, self.val_loader, self.restore_transform = dataloader()


        if self.net_name in ['CMTL']:

            # use for gt's class labeling
            self.max_gt_count = 0.
            self.min_gt_count = 0x7f7f7f
            self.num_classes = 10
            self.bin_val = 0.

            self.pre_max_min_bin_val()
            ce_weights = torch.from_numpy(self.pre_weights()).float()

            loss_1_fn = nn.MSELoss()
            
            loss_2_fn = nn.BCELoss(weight=ce_weights)

        self.net = CrowdCounter(cfg.GPU_ID, self.net_name,loss_1_fn,loss_2_fn).cuda()
        self.optimizer = optim.Adam(self.net.CCN.parameters(), lr=cfg.LR, weight_decay=1e-4)
        # self.optimizer = optim.SGD(self.net.parameters(), cfg.LR, momentum=0.95,weight_decay=5e-4)
        self.scheduler = StepLR(self.optimizer, step_size=cfg.NUM_EPOCH_LR_DECAY, gamma=cfg.LR_DECAY)

        self.train_record = {'best_mae': 1e20, 'best_mse': 1e20, 'best_model_name': ''}
        self.timer = {'iter time': Timer(), 'train time': Timer(), 'val time': Timer()}
        # self.writer, self.log_txt = logger(self.exp_path, self.exp_name, self.pwd, 'exp')
        self.log_txt = logger_for_CMTL(self.exp_path, self.exp_name, self.pwd, 'exp')
        self.i_tb = 0
        self.epoch = -1

        if cfg.PRE_GCC:
            net.load_state_dict(torch.load(cfg.PRE_GCC_MODEL))





    def pre_max_min_bin_val(self):
        for i, data in enumerate(self.train_loader, 0):
            if i < 100:
                # the first 10 epoch use for get the max and min people count
                _, gt_map = data

                for j in range(0, gt_map.size()[0]):
                    temp_count = gt_map[j].sum() / self.cfg_data.LOG_PARA
                    if temp_count > self.max_gt_count:
                        self.max_gt_count = temp_count
                    elif temp_count < self.min_gt_count:
                        self.min_gt_count = temp_count

        print '[max_gt: %.2f min_gt: %.2f]' % (self.max_gt_count, self.min_gt_count)
        self.bin_val = (self.max_gt_count - self.min_gt_count)/float(self.num_classes)

    def pre_weights(self):
        count_class_hist = np.zeros(self.num_classes)
        for i, data in enumerate(self.train_loader, 0):
            if i < 100:
                _, gt_map = data
                for j in range(0, gt_map.size()[0]):
                    temp_count = gt_map[j].sum() / self.cfg_data.LOG_PARA
                    class_idx = np.round(temp_count/self.bin_val)
                    class_idx = int(min(class_idx,self.num_classes-1))
                    count_class_hist[class_idx] += 1

        wts = count_class_hist
        wts = 1-wts/(sum(wts));
        wts = wts/sum(wts);
        print 'pre_wts:'
        print wts

        return wts


    def online_assign_gt_class_labels(self, gt_map_batch):
        batch = gt_map_batch.size()[0]
        # pdb.set_trace()
        label = np.zeros((batch, self.num_classes), dtype=np.int)

        for i in range(0, batch):

            # pdb.set_trace()
            gt_count = gt_map_batch[i].sum().data[0] / self.cfg_data.LOG_PARA

            # generate gt's label same as implement of CMTL by Viswa
            gt_class_label = np.zeros(self.num_classes, dtype=np.int)
            bin_val = (self.max_gt_count - self.min_gt_count)/float(self.num_classes)
            class_idx = np.round(gt_count/bin_val)
            class_idx = int(min(class_idx, self.num_classes-1))
            gt_class_label[class_idx] = 1
            # pdb.set_trace()
            label[i] = gt_class_label.reshape(1, gt_class_label.shape[0])

        return torch.from_numpy(label).float()

    def forward(self):

        # self.validate_V1()
        for epoch in range(cfg.MAX_EPOCH):
            self.epoch = epoch
            if epoch > cfg.LR_DECAY_START:
                self.scheduler.step()

            # training
            self.timer['train time'].tic()
            self.train()
            self.timer['train time'].toc(average=False)

            print 'train time: {:.2f}s'.format(self.timer['train time'].diff)
            print '=' * 20

            # validation
            if epoch % cfg.VAL_FREQ == 0 or epoch > cfg.VAL_DENSE_START:
                self.timer['val time'].tic()
                if self.data_mode in ['SHHA', 'SHHB', 'QNRF', 'UCF50']:
                    self.validate_V1()
                elif self.data_mode is 'WE':
                    self.validate_V2()
                elif self.data_mode is 'GCC':
                    self.validate_V3()
                self.timer['val time'].toc(average=False)
                print 'val time: {:.2f}s'.format(self.timer['val time'].diff)

    def train(self):  # training for all datasets
        self.net.train()
        for i, data in enumerate(self.train_loader, 0):
            # train net
            self.timer['iter time'].tic()
            img, gt_map = data
            img = Variable(img).cuda()
            gt_map = Variable(gt_map).cuda()

            gt_label = self.online_assign_gt_class_labels(gt_map)
            gt_label = Variable(gt_label).cuda()
            

            self.optimizer.zero_grad()
            pred_map = self.net(img, gt_map, gt_label)
            loss1,loss2 = self.net.loss
            loss = loss1+loss2
            loss.backward()
            self.optimizer.step()

            if (i + 1) % cfg.PRINT_FREQ == 0:
                self.i_tb += 1
                # self.writer.add_scalar('train_loss', loss.data[0], self.i_tb)
                # self.writer.add_scalar('train_loss1', loss1.data[0], self.i_tb)
                # self.writer.add_scalar('train_loss2', loss2.data[0], self.i_tb)
                self.timer['iter time'].toc(average=False)
                print '[ep %d][it %d][loss %.8f, %.8f, %.8f][lr %.4f][%.2fs]' % \
                        (self.epoch + 1, i + 1, loss.data[0],loss1.data[0],loss2.data[0], self.optimizer.param_groups[0]['lr'] * 10000,
                 self.timer['iter time'].diff)
                # pdb.set_trace()
                print '        [cnt: gt: %.1f pred: %.2f]' % (
                        gt_map[0].sum().data.cpu().numpy()[0] / self.cfg_data.LOG_PARA, pred_map[0].sum().data.cpu().numpy()[0] / self.cfg_data.LOG_PARA)

    def validate_V1(self):  # validate_V1 for SHHA, SHHB, UCF-QNRF, UCF50

        self.net.eval()

        losses = AverageMeter()
        maes = AverageMeter()
        mses = AverageMeter()

        for vi, data in enumerate(self.val_loader, 0):
            img, gt_map = data

            # with torch.no_grad():
            img = Variable(img, volatile=True).cuda()
            gt_map = Variable(gt_map, volatile=True).cuda()

            gt_label = self.online_assign_gt_class_labels(gt_map)
            gt_label = Variable(gt_label).cuda()

            pred_map = self.net.forward(img, gt_map, gt_label)

            pred_map = pred_map.data.cpu().numpy()
            gt_map = gt_map.data.cpu().numpy()

            pred_cnt = np.sum(pred_map) / self.cfg_data.LOG_PARA
            gt_count = np.sum(gt_map) / self.cfg_data.LOG_PARA

            loss1,loss2 = self.net.loss
            loss = loss1.data[0]+loss2.data[0]
            losses.update(loss)
            maes.update(abs(gt_count - pred_cnt))
            mses.update((gt_count - pred_cnt) * (gt_count - pred_cnt))
            # if vi == 0:
            #     vis_results(self.exp_name, self.epoch, self.writer, self.restore_transform, img, pred_map, gt_map)

        mae = maes.avg
        mse = np.sqrt(mses.avg)
        loss = losses.avg

        # self.writer.add_scalar('val_loss', loss, self.epoch + 1)
        # self.writer.add_scalar('mae', mae, self.epoch + 1)
        # self.writer.add_scalar('mse', mse, self.epoch + 1)

        self.train_record = update_model(self.net, self.epoch, self.exp_path, self.exp_name, [mae, mse, loss],
                                         self.train_record, self.log_txt)
        print_summary(self.exp_name, [mae, mse, loss], self.train_record)

    def validate_V2(self):  # validate_V2 for WE

        self.net.eval()

        losses = AverageCategoryMeter(5)
        maes = AverageCategoryMeter(5)

        for i_sub, i_loader in enumerate(self.val_loader, 0):

            for vi, data in enumerate(i_loader, 0):
                img, gt_map = data

                with torch.no_grad():
                    img = Variable(img).cuda()
                    gt_map = Variable(gt_map).cuda()

                    pred_map = self.net.forward(img, gt_map)

                    pred_map = pred_map.data.cpu().numpy()
                    gt_map = gt_map.data.cpu().numpy()

                    pred_cnt = np.sum(pred_map) / self.cfg_data.LOG_PARA
                    gt_count = np.sum(gt_map) / self.cfg_data.LOG_PARA

                    losses.update(self.net.loss.data[0], i_sub)
                    maes.update(abs(gt_count - pred_cnt), i_sub)
                    # if vi == 0:
                    #     vis_results(self.exp_name, self.epoch, self.writer, self.restore_transform, img, pred_map,
                    #                 gt_map)

        mae = np.average(maes.avg)
        loss = np.average(losses.avg)

        # self.writer.add_scalar('val_loss', loss, self.epoch + 1)
        # self.writer.add_scalar('mae', mae, self.epoch + 1)

        self.train_record = update_model(self.net, self.epoch, self.exp_path, self.exp_name, [mae, 0, loss],
                                         self.train_record, self.log_txt)
        print_summary(self.exp_name, [mae, 0, loss], self.train_record)

    def validate_V3(self):  # validate_V3 for GCC

        self.net.eval()

        losses = AverageMeter()
        maes = AverageMeter()
        mses = AverageMeter()

        c_maes = {'level': AverageCategoryMeter(9), 'time': AverageCategoryMeter(8), 'weather': AverageCategoryMeter(7)}
        c_mses = {'level': AverageCategoryMeter(9), 'time': AverageCategoryMeter(8), 'weather': AverageCategoryMeter(7)}

        for vi, data in enumerate(self.val_loader, 0):
            img, gt_map, attributes_pt = data
            with torch.no_grad():
                img = Variable(img).cuda()
                gt_map = Variable(gt_map).cuda()

                pred_map = self.net.forward(img, gt_map)

                pred_map = pred_map.data.cpu().numpy()
                gt_map = gt_map.data.cpu().numpy()

                pred_cnt = np.sum(pred_map) / self.cfg_data.LOG_PARA
                gt_count = np.sum(gt_map) / self.cfg_data.LOG_PARA

                s_mae = abs(gt_count - pred_cnt)
                s_mse = (gt_count - pred_cnt) * (gt_count - pred_cnt)

                losses.update(self.net.loss.data[0])
                maes.update(s_mae)
                mses.update(s_mse)
                c_maes['level'].update(s_mae, attributes_pt[i_img][0])
                c_mses['level'].update(s_mse, attributes_pt[i_img][0])
                c_maes['time'].update(s_mae, attributes_pt[i_img][1] / 3)
                c_mses['time'].update(s_mse, attributes_pt[i_img][1] / 3)
                c_maes['weather'].update(s_mae, attributes_pt[i_img][2])
                c_mses['weather'].update(s_mse, attributes_pt[i_img][2])

                # if vi == 0:
                #     vis_results(self.exp_name, self.epoch, self.writer, self.restore_transform, img, pred_map, gt_map)

        loss = losses.avg
        mae = maes.avg
        mse = np.sqrt(mses.avg)

        # self.writer.add_scalar('val_loss', loss, self.epoch + 1)
        # self.writer.add_scalar('mae', mae, self.epoch + 1)
        # self.writer.add_scalar('mse', mse, self.epoch + 1)

        self.train_record = update_model(self.net, self.epoch, self.exp_path, self.exp_name, [mae, mse, loss],
                                         self.train_record, self.log_txt)

        c_mses['level'] = np.sqrt(c_mses['level'].avg)
        c_mses['time'] = np.sqrt(c_mses['time'].avg)
        c_mses['weather'] = np.sqrt(c_mses['weather'].avg)
        print_GCC_summary(self.exp_name, [mae, mse, loss], self.train_record, c_maes, c_mses)