def make_training_step_method(classifier, num_positive_regions, positive_fraction, lr=1e-3, l2=0, method='GE-binomial', pi=0, slack=-1, autoencoder=0): import topaz.methods as methods criteria = nn.BCEWithLogitsLoss() optim = torch.optim.Adam # pi sets the expected fraction of positives # but during training, we iterate over unlabeled data with labeled positives removed # therefore, we expected the fraction of positives in the unlabeled data # to be pi - fraction of labeled positives # if we are using the 'GE-KL' or 'GE-binomial' loss functions p_observed = positive_fraction if pi <= p_observed and method in ['GE-KL', 'GE-binomial']: # if pi <= p_observed, then we think the unlabeled data is all negatives # report this to the user and switch method to 'PN' if it isn't already print( 'WARNING: pi={} but the observed fraction of positives is {} and method is set to {}.' .format(pi, p_observed, method), file=sys.stderr) print('WARNING: setting method to PN with pi={} instead.'.format( p_observed), file=sys.stderr) print('WARNING: if you meant to use {}, please set pi > {}.'.format( method, p_observed), file=sys.stderr) pi = p_observed method = 'PN' elif method in ['GE-KL', 'GE-binomial']: pi = pi - p_observed split = 'pn' if method == 'PN': optim = optim(classifier.parameters(), lr=lr) trainer = methods.PN(classifier, optim, criteria, pi=pi, l2=l2, autoencoder=autoencoder) elif method == 'GE-KL': if slack < 0: slack = 10 optim = optim(classifier.parameters(), lr=lr) trainer = methods.GE_KL(classifier, optim, criteria, pi, l2=l2, slack=slack) elif method == 'GE-binomial': if slack < 0: slack = 1 optim = optim(classifier.parameters(), lr=lr) trainer = methods.GE_binomial(classifier, optim, criteria, pi, l2=l2, slack=slack, autoencoder=autoencoder) elif method == 'PU': split = 'pu' optim = optim(classifier.parameters(), lr=lr) trainer = methods.PU(classifier, optim, criteria, pi, l2=l2, autoencoder=autoencoder) else: raise Exception('Invalid method: ' + method) return trainer, criteria, split
def make_training_step_method(classifier, num_positive_regions, positive_fraction, args): import topaz.methods as methods criteria = nn.BCEWithLogitsLoss() optim = torch.optim.Adam lr = args.learning_rate l2 = args.l2 pi = args.pi slack = args.slack split = 'pn' if args.method == 'PN': optim = optim(classifier.parameters(), lr=lr) trainer = methods.PN(classifier, optim, criteria, pi=pi, l2=l2, autoencoder=args.autoencoder) elif args.method == 'GE-KL': #split = 'pu' if slack < 0: slack = 10 * num_positive_regions assert positive_fraction <= pi pi = pi - positive_fraction optim = optim(classifier.parameters(), lr=lr) trainer = methods.GE_KL(classifier, optim, criteria, pi, l2=l2, slack=slack) elif args.method == 'GE-binomial': #split = 'pu' if slack < 0: slack = 1 assert positive_fraction <= pi pi = pi - positive_fraction optim = optim(classifier.parameters(), lr=lr) trainer = methods.GE_binomial(classifier, optim, criteria, pi, l2=l2, slack=slack, autoencoder=args.autoencoder) elif args.method == 'PU': split = 'pu' optim = optim(classifier.parameters(), lr=lr) trainer = methods.PU(classifier, optim, criteria, pi, l2=l2, autoencoder=args.autoencoder) else: raise Exception('Invalid method: ' + args.method) return trainer, criteria, split