Beispiel #1
0
def test():
    """
    Test model accuracy on test dataset.
    测试模型在测试集上的准确率。
    """
    print("Start to test...")
    ctx = mx.gpu() if args.use_gpu else mx.cpu()

    _, test_iter = data_loader(args.batch_size)

    model = LeNetPlus()
    model.load_parameters(os.path.join(args.ckpt_dir,
                                       args.prefix + "-best.params"),
                          ctx=ctx,
                          allow_missing=True)
    #
    center_net = CenterLoss(num_classes=args.num_classes,
                            feature_size=args.feature_size,
                            lmbd=args.lmbd,
                            ctx=mx.cpu())
    center_net.load_parameters(os.path.join(
        args.ckpt_dir, args.prefix + "-feature_matrix.params"),
                               ctx=ctx)

    start_time = time.time()
    test_accuracy, features, predictions, labels = evaluate_accuracy(
        test_iter, model, center_net, args.eval_method, ctx)
    elapsed_time = time.time() - start_time
    print("Test_acc: %s, Elapsed_time: %f s" % (test_accuracy, elapsed_time))

    # make directory
    if not os.path.exists(args.out_dir):
        os.makedirs(args.out_dir)
    # draw feature map
    if args.plotting:
        plot_features(features,
                      labels,
                      num_classes=args.num_classes,
                      fpath=os.path.join(args.out_dir, "%s.png" % args.prefix))
Beispiel #2
0
def second_train():
    """
    Train a model using only center loss based on pretrained model.
    In order to avoid feature matrix becoming zero matrix, fix CenterLoss' parameters not to train it.
    基于之前训练的模型,仅使用center loss对模型进行训练。
    为了避免在训练的过程,CenterLoss中的特征矩阵变为0矩阵,将其参数固定不对其进行训练。
    """
    print("Start to train LeNet++ with CenterLoss...")

    train_iter, test_iter = data_loader(args.batch_size)
    ctx = mx.gpu() if args.use_gpu else mx.cpu()

    # main model (LeNetPlus), loss, trainer
    model = LeNetPlus(classes=args.num_classes, feature_size=args.feature_size)
    model.load_parameters(os.path.join(args.ckpt_dir,
                                       args.prefix + "-best.params"),
                          ctx=ctx,
                          allow_missing=True)
    network_trainer = gluon.Trainer(model.collect_params(),
                                    optimizer="sgd",
                                    optimizer_params={
                                        "learning_rate": args.lr,
                                        "wd": args.wd
                                    })

    center_loss = CenterLoss(num_classes=args.num_classes,
                             feature_size=args.feature_size,
                             lmbd=args.lmbd,
                             ctx=ctx)
    center_loss.load_parameters(os.path.join(
        args.ckpt_dir, args.prefix + "-feature_matrix.params"),
                                ctx=ctx)
    center_loss.params.setattr("grad_req", "null")  #

    smoothing_constant, moving_loss = .01, 0.0
    best_acc = 0.0
    for epoch in range(args.epochs):
        # using learning rate decay during training process
        if (epoch > 0) and (epoch % args.lr_step == 0):
            network_trainer.set_learning_rate(network_trainer.learning_rate *
                                              args.lr_factor)

        start_time = time.time()
        for i, (data, label) in enumerate(train_iter):
            data = data.as_in_context(ctx)
            label = label.as_in_context(ctx)
            # only calculate loss with center loss
            with autograd.record():
                output, features = model(data)
                loss = center_loss(features, label)

            loss.backward()
            # only update parameters of LeNet++
            network_trainer.step(
                args.batch_size, ignore_stale_grad=True
            )  # without ignore_stale_grad=True, it will raise warning information
            # 去除ignore_stale_grad=True后,模型训练会出错,梯度无法进行更新

            # calculate smoothed loss value
            curr_loss = nd.mean(loss).asscalar()
            moving_loss = (curr_loss if ((i == 0) and (epoch == 0)) else
                           (1 - smoothing_constant) * moving_loss +
                           smoothing_constant * curr_loss)

        # training cost time
        elapsed_time = time.time() - start_time
        train_accuracy, train_ft, _, train_lb = evaluate_accuracy(
            train_iter, model, center_loss, args.eval_method, ctx)
        test_accuracy, test_ft, _, test_lb = evaluate_accuracy(
            test_iter, model, center_loss, args.eval_method, ctx)

        # draw feature map with different prefix, to make it convenient to compare features
        if args.plotting:
            plot_features(train_ft,
                          train_lb,
                          num_classes=args.num_classes,
                          fpath=os.path.join(
                              args.out_dir, "%s-second-train-epoch-%d.png" %
                              (args.prefix, epoch)))
            plot_features(test_ft,
                          test_lb,
                          num_classes=args.num_classes,
                          fpath=os.path.join(
                              args.out_dir, "%s-second-test-epoch-%d.png" %
                              (args.prefix, epoch)))

        logging.warning(
            "Epoch [%d]: Loss=%f, Train-Acc=%f, Test-Acc=%f, Epoch-time=%f" %
            (epoch, moving_loss, train_accuracy, test_accuracy, elapsed_time))

        if test_accuracy > best_acc:
            best_acc = test_accuracy
            model.save_parameters(
                os.path.join(args.ckpt_dir,
                             args.prefix + "-second-best.params"))