Ошибка атрибута при проверке, был ли инициализирован RandomForestClassifier

#python #scikit-learn

#python #scikit-learn

Вопрос:

У меня есть класс, который содержит scikitlearn-RandomForestClassifier в качестве переменной-члена. В __init__ -методе сначала инициализируется значение None,

 def __init__(self):
   self.classifier = None
  

и
позже, когда все необходимые параметры будут доступны, RandomForestClassifier создается и
присвоено этой переменной-члену:

 def init_classifier(self):
    self.classifier = RandomForestClassifier(**params)
  

(В отладчике я вижу, что self.classifier было инициализировано что-то значимое.)
В методе класса, который должен соответствовать классификатору данным, сначала проверяется, был ли
классификатор уже инициализирован:

 if not self.classifier:
    self.init_classifier()
  

Это приводит к AttributeError: 'RandomForestClassifier' object has no attribute 'estimators_'.
Если проверка выполняется путем сравнения с None явно,

 if self.classifier is None:
    self.init_classifier()
  

он выполняется. Может кто-нибудь объяснить мне, откуда берется эта ошибка атрибута?

Ответ №1:

Чтобы понять, почему такое поведение, вам нужно посмотреть, как работает логическое сравнение объекта в Python. (т. Е. при вызове if A ).

  1. Сначала интерпретатор попытается проверить, реализует ли объект специальный метод __bool__ . Это специальный метод, который либо вернет True , либо False .

  2. Если __bool__ специальный метод не определен, интерпретатор попытается использовать __len__ функцию. Если результат равен 0, то выражение вычисляется в False . Отсюда и возникает исключение.

  3. Если __len__ функция также не определена, то оператор оценивается как True .

Если мы посмотрим на BaseEnsemble класс, от которого наследуется RandomForestClassifier , мы увидим, что он не реализует __bool__ специальный метод, но реализует __len__ специальный метод :

 def __len__(self):
    """Return the number of estimators in the ensemble."""
    return len(self.estimators_)
  

Итак, когда вы вызываете if not self.classifier: , вы вызываете эту __len__ функцию. На данный момент в вашем коде RandomForestClassifier еще не создан экземпляр должным образом (это мое предположение) и не имеет estimators_ атрибута, следовательно, исключение.

Если вы хотите проверить, что экземпляр объекта не создан, всегда явно вызывайте сравнение с None . В этом случае интерпретатор проверит объект на None .