Модели в списке не передаются как соответствующие (но на самом деле они подходят) - PullRequest
0 голосов
/ 19 сентября 2019

Это длинная проблема, но я надеюсь, что кто-то знает ответ.Я получаю ошибку в коде, который мне не следует, и после проверки GitHub scikit-learn обнаружил, что код scikit-learn на моем компьютере не совпадает с кодом в репозитории, даже если я полностью обновлен (как проверено с помощью__version__ метод).Не уверен, действительно ли это актуально или нет, я позволю вам попытаться определить это.Основная проблема изложена ниже в прикрепленном коде:


class ModelCollection(BaseEstimator):

    def __init__(self, models, **model_params):
        '''

        Class to allow collections of models to be easily fit together and predict outcome of each model

        :param model_list: List of tuples of form (name, model).  Similar to the setup for a scitkit-learn pipeline
        '''
        import numpy as np
        self.np = np
        self.models = models
        self.__set_params(models)
        self.set_params(**model_params)

    def model_index(self, model_name):
        '''
        Returns index of model given model name
        :param model_name: name of model
        :return: index of model in self.model_list
        '''
        try:
            return self.name_list.index(model_name)
        except:
            raise ValueError("Model name not found in model list.")

    def __get_X(self, X, key):
        '''
        Workaround to allow different models to be trained on different sets concurrently

        :param X: Either a single dataset or list of datasets
        :param key: Index of dataset in list
        :return: returns X if X is not a list, returns the key-th dataset if X is a list of datasets
        '''
        if type(X)==list:
            return X[key]
        else:
            return X

    def fit(self, X, y, names=None, verbose=False):
        '''
        Fits each model

        :param X: Feature set or list of feature sets
        :param y: Labels
        :param names: names of models to train.  If None, trains all models
        :param verbose: True to return tqdm progress bar
        :return: self
        '''
        temp_list = []
        if names is None:
            names = self.name_list
        for key, name in self.tqdm(enumerate(names), disable=(not verbose)):
            index = self.name_list.index(name)
            temp_model = self.model_list[key].fit(self.__get_X(X, key), y)
            temp_list.append(temp_model)
        self.model_list = temp_list
        return self

    def predict(self, X, verbose=False):
        '''
        Create a prediction array

        :param X: Features
        :param verbose: True to return tqdm progress bar
        :return: returns an array of predictions, where each column represents the prediction of it's corresponding model
        '''
        for model_col in self.tqdm(range(self.num_models), disable=(not verbose)):
            if model_col == 0:
                predict_array = self.model_list[model_col].predict(self.__get_X(X, model_col))
            else:
                temp_array = self.model_list[model_col].predict(self.__get_X(X, model_col))
                predict_array = self.np.vstack((predict_array, temp_array))
        return self.np.transpose(predict_array)

    def predict_proba(self, X, shorten_array=True, verbose=False):
        '''
        Create a probability prediction array

        :param X: Features
        :param verbose: True to return tqdm progress bar
        :return: returns an array of prediction probabilities, where each column represents the prediction of it's corresponding model
        '''
        if shorten_array:
            slice = 1
        else:
            slice = 0
        for model_col in self.tqdm(range(self.num_models), disable=(not verbose)):
            if model_col == 0:
                try:
                    prob_array = self.model_list[model_col].predict_proba(self.__get_X(X, model_col))[:,slice:]
                except:
                    prob_array = self.model_list[model_col].predict(self.__get_X(X, model_col))
            else:
                try:
                    temp_array = self.model_list[model_col].predict_proba(self.__get_X(X, model_col))[:,slice:]
                except:
                    temp_array = self.model_list[model_col].predict(self.__get_X(X, model_col))
                prob_array = self.np.hstack((prob_array, temp_array))
        return prob_array


if __name__ == "__main__":
    from sklearn.linear_model import LogisticRegression
    from sklearn.naive_bayes import MultinomialNB
    from sklearn.ensemble import RandomForestClassifier

    #generate random numbers to train on
    np.random.seed(0)
    x_train = np.random.randint(0, 10, (80, 3))
    x_test = np.random.randint(0, 10, (20, 3))
    y_train = np.random.randint(0, 2, 80)
    y_test = np.random.randint(0, 2, 20)

    test = ModelCollection([('log', LogisticRegression(random_state=0)), ('nb', MultinomialNB())])

    test.fit(x_train, y_train)

После этого я могу отлично использовать методы класса .predict () и .predict_proba () класса.Сами модели обучены и работают по назначению.Однако, когда я пытаюсь вызвать этот класс в другом классе, все модели в test.model_list по отдельности завершают работу с методом .decision_function () в LinearClassifierMixin.Последняя строка сообщения об ошибке гласит:

~\Anaconda3\lib\site-packages\sklearn\linear_model\base.py in predict(self, X)
    287             Predicted class label per sample.
    288         """
--> 289         scores = self.decision_function(X)
    290         if len(scores.shape) == 1:
    291             indices = (scores > 0).astype(np.int)

~\Anaconda3\lib\site-packages\sklearn\linear_model\base.py in decision_function(self, X)
    253         if not hasattr(self, 'coef_') or self.coef_ is None:
    254             raise NotFittedError("This %(name)s instance is not fitted "
--> 255                                  "yet" % {'name': type(self).__name__})
    256 
    257         X = check_array(X, accept_sparse='csr')

NotFittedError: This LogisticRegression instance is not fitted yet

Когда я проверяю это, отдельные условия в условной строке 253 для каждой модели, однако, они не соответствуют обоим условиям, поэтому никогда не следует переходить к строке 254.Некоторое время я заходил в исходный код для этого, и исходный код выше не не соответствует репозиторию scikit-learn GitHub, хотя я полностью обновлен и использую __version__, подтверждающий это.Я, честно говоря, понятия не имею, что происходит, моя функция не должна соответствовать условиям выражения «или» в строке 253, но это по какой-то причине.Как я уже сказал, обе модели на самом деле подходят , и функция прекрасно работает, вызывая методы .predict () и .predict_proba () моего класса.

Я предполагаю, что смогу заставить его работать, просто перебив тесты соответствия, используемые scikit-learn и пропуская их, но я хочу, чтобы классы работали так, чтобы другие люди могли использовать их безтакже зарезать библиотеку на своем компьютере.Буду признателен за любую помощь.

(есть еще кое-что из вышеперечисленного класса, которое я вырезал по космическим причинам, которое не должно быть релевантным. Если вам нужны они или класс ансамбля, в котором я использую этот класс, позвольте мнезнаю).Спасибо!

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