Как не позволить одной гиперплоскости повлиять на решение в мультиклассовом линейном ядре SVM? - PullRequest
2 голосов
/ 15 мая 2019

Я использую linearsvc из scikit для набора данных 3-го класса. Используя стратегию one-vs-rest (по умолчанию), я получаю ровно 3 вектора весов гиперплоскостей, каждый из которых имеет размер number_of_features_in_dataset. Теперь окончательное предсказание основано на комбинации всех трех коэффициентов гиперплоскости, но я хочу исключить, скажем, 2-ую гиперплоскость от какого-либо вклада в окончательное решение.

Я искал и обнаружил, что несколько внутренних гиперплоскостей голосуют и делают окончательную классификацию, а в случае связи рассматривается расстояние от отдельной гиперплоскости.

clf = LinearSVC()
clf.fit(x_train,y_train)
y_predict = clf.predict(x_test)
print(clf.coef_) # This prints 3xnos_of_features, where each row represents hyperplane weights
#I want to exclude say 2nd hyperplane from affecting decision made in in line 3

1 Ответ

0 голосов
/ 15 мая 2019

Вы можете вручную добавить смещение к каждой гиперплоскости , чтобы выбрать один из классов:

from sklearn.svm import LinearSVC
from sklearn.preprocessing import LabelEncoder
import numpy as np

import warnings
warnings.filterwarnings(module='sklearn*', action='ignore', category=DeprecationWarning)


class BiasedSVC(LinearSVC):

    def __init__(self, penalty='l2', loss='squared_hinge', dual=True, tol=1e-4,
                 C=1.0, multi_class='ovr', fit_intercept=True,
                 intercept_scaling=1, class_weight=None, verbose=0,
                 random_state=None, max_iter=1000, classes=None, biases=None
                 ):
        """
        Same as LinearSVC: (https://github.com/scikit-learn/scikit-learn/blob/master/sklearn/svm/classes.py)
        But allowing to bias the hyperplane to favor a class over another. Works for multiclass classification
        :param classes: list of the classes (all the classes myst be present in y during training).
        :type classes: list of strings
        :param biases: list of biases in the alphabetical order of the classes (ex: [0.0, +0.1, -0.1]) or dict
        containing the weights by class (ex: {"class_1": 0.0, "class_2": +0.1, "class_3": -0.1})
        :type biases: list of floats or dict
        """

        super().__init__(penalty, loss, dual, tol, C, multi_class, fit_intercept, intercept_scaling, class_weight,
                         verbose, random_state, max_iter)

        # Define new variables
        self.classes = classes
        self.biases = biases

        # Transtype Biases
        self._biases = self.get_biases(self.biases)

        # Create Norm variable
        self._w_norm = None

        # Create LabelEncoder
        self._le = LabelEncoder()

    def get_biases(self, biases):
        """ Transtype the biases to get a list of floats """
        if isinstance(biases, list):
            return biases
        elif isinstance(biases, dict):
            return [biases[class_name] for class_name in self.classes]
        else:
            return [0.0 for _ in self.classes]

    def get_w_norm(self):
        """ Get the norm of the hyperplane to normalize the distance """
        self._w_norm = np.linalg.norm(self.coef_)

    def fit(self, X, y, sample_weight=None):

        # Fit the label Encoder (to change labels to indices)
        self._le.fit(y)

        # Fit the SVM using the mother class (LinearSVC) fit method
        super().fit(X, y, sample_weight)

        # Record the norm for all the hyperplanes (useful during inference)
        self.get_w_norm()

    def predict(self, X):
        """ Performa a prediction with the biased hyerplane """

        # Get the decision output (distance to the the hyperplanes separating the different classes)
        decision_y = self.decision_function(X)

        # Add the bias to each hyperplane (normalized for each class)
        dist = decision_y / self._w_norm + self._biases

        # Return the corresponding class
        return self._le.inverse_transform(np.argmax(dist, axis=1))

Примечание : Выне используйте смещения во время тренировки, только во время прогнозирования, поскольку SVC будет переводить гиперплоскости, чтобы компенсировать ваши смещения во время тренировки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...