<commit_before>import numpy
import random
from sklearn.svm import LinearSVC
from .train import TrainMentionClassifier

import logging
log = logging.getLogger()

def sample_by_magnitude(_, negatives, limit):
    # learn from candidates with highest feature vector magnitude
    # given feature vectors are standardised to have 0 mean and unit standard deviation, this  
    # should be like selecting instances with the strongest feature activation
    return sorted(negatives, key=lambda fv: numpy.abs(fv).sum(), reverse=True)[:limit]

def sample_by_mag_difference(positive, negatives, limit):
    return sorted(negatives, key=lambda fv: numpy.abs(positive - fv).sum(), reverse=True)[:limit]

def sample_randomly(_, negatives, limit):
    random.shuffle(negatives)
    return negatives[:limit]

def sample_by_std(_, negatives, limit):
    # diversity in feature activation
    return sorted(negatives, key=numpy.std, reverse=True)[:limit]

class TrainLinearRanker(TrainMentionClassifier):
    """ Trains a linear candidate ranker over a corpus of documents. """
    def __init__(self, **kwargs):
        kwargs['mapping'] = 'PolynomialMapper'
        super(TrainLinearRanker, self).__init__(**kwargs)

        # todo: parameterise instance selection parameters
        self.sample_instances = sample_by_magnitude
        self.instance_limit = 10

    def iter_instances(self, docs):
        return self.iter_pairwise_instances_with_sampling(docs, self.sample_instances, self.instance_limit)

    def init_model(self):
        # todo: parameterise hyperparams
        hparams = {
            'C': 0.0316228,
            'penalty': 'l2',
            'loss': 'l1',
            'class_weight': 'auto',
            'fit_intercept': True
        }

        hparams['dual'] = hparams['penalty'] == 'l2' and hparams['loss'] == 'l1'
        return LinearSVC(**hparams)

    @staticmethod
    def iter_pairwise_instances_with_sampling(docs, sampler, limit):
        toggle = True

        for doc in docs:
            for mention in doc.chains:
                if mention.resolution == None:<commit_msg>Switch to hinge loss in linear ranker<commit_after>import numpy
import random
from sklearn.svm import LinearSVC
from .train import TrainMentionClassifier

import logging
log = logging.getLogger()

def sample_by_magnitude(_, negatives, limit):
    # learn from candidates with highest feature vector magnitude
    # given feature vectors are standardised to have 0 mean and unit standard deviation, this  
    # should be like selecting instances with the strongest feature activation
    return sorted(negatives, key=lambda fv: numpy.abs(fv).sum(), reverse=True)[:limit]

def sample_by_mag_difference(positive, negatives, limit):
    return sorted(negatives, key=lambda fv: numpy.abs(positive - fv).sum(), reverse=True)[:limit]

def sample_randomly(_, negatives, limit):
    random.shuffle(negatives)
    return negatives[:limit]

def sample_by_std(_, negatives, limit):
    # diversity in feature activation
    return sorted(negatives, key=numpy.std, reverse=True)[:limit]

class TrainLinearRanker(TrainMentionClassifier):
    """ Trains a linear candidate ranker over a corpus of documents. """
    def __init__(self, **kwargs):
        kwargs['mapping'] = 'PolynomialMapper'
        super(TrainLinearRanker, self).__init__(**kwargs)

        # todo: parameterise instance selection parameters
        self.sample_instances = sample_by_magnitude
        self.instance_limit = 10

    def iter_instances(self, docs):
        return self.iter_pairwise_instances_with_sampling(docs, self.sample_instances, self.instance_limit)

    def init_model(self):
        # todo: parameterise hyperparams
        hparams = {
            'C': 0.0316228,
            'penalty': 'l2',
            'loss': 'hinge',
            'class_weight': 'auto',
            'fit_intercept': True
        }

        return LinearSVC(**hparams)

    @staticmethod
    def iter_pairwise_instances_with_sampling(docs, sampler, limit):
        toggle = True

        for doc in docs:
            for mention in doc.chains:
                if mention.resolution == None:
{'fraction_non_alphanumeric': 0.09365924491771539, 'fraction_numerical': 0.006534365924491772, 'mean_word_length': 3.434549356223176, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5246177', 'n_tokens_mistral': 1219, 'n_tokens_neox': 1145, 'n_words': 329}