**Импорты**

Код использует несколько библиотек:

- **`matplotlib.patches`, `matplotlib.colors`**: Для визуализации.
- **`collections.Counter`**: Для подсчета количества элементов (например, в целевых переменных).
- **`graphviz.Digraph`**: Для графического представления дерева решений.
- **`pandas` и `numpy`**: Для работы с данными и числовыми вычислениями.

---

### **Конструктор класса `DecisionTree`**

- **`model_type`**: Тип модели — либо `Classifier`, либо `Regressor`.
  - Влияет на критерии оценки качества разбиений и финальные метрики (например, большинство классов или среднее значение).
- **`max_depth`**: Максимальная глубина дерева. Позволяет ограничить рост дерева.
- **`min_samples_leaf`**: Минимальное количество объектов в листе.
- **`max_leaves`**: Максимальное количество листьев. Если достигнуто, дерево больше не растет.
- **`criterion`**: Критерий оценки качества разбиений. Поддерживаются:
  - Классификация: `gini`, `entropy`, `misclassification`.
  - Регрессия: `mae`, `mse`.
- **`min_gain`**: Минимальное улучшение качества для принятия разбиения.
- **`class_weights`**:  Словарь вида {class: weight}, определяющий веса для классов. Если `None` - веса равны.
- **`check_k_threshold`** — позволяет определять, сколько уникальных объектов использовать для оценки качества разбиения. Значение `k=0` проверяет все объекты, а `k>=1` ограничивает проверку `k` объектами.
- **`chek_k_features`** — ограничивает выбор случайных признаков для построения дерева на каждой итерации.

---

### Примеры использования

#### Классификация

```python
from sklearn.datasets import make_classification


X, Y = make_classification(10000,n_features=2,n_informative=2,n_redundant = 0, n_classes=2)
# Обучение дерева
tree = DecisionTree(max_depth=10)
tree.fit(X, Y)

# Прогноз
predictions = tree.predict(X)

print('Акураси = ',(Y==predictions).sum()/Y.size)

tree.plot_decision_boundaries(X, Y)
```

Акураси =  0.9774

![1732183291803](image/README/1732183291803.png)

#### Регрессия

```python
from sklearn.datasets import make_regression
from sklearn.metrics import r2_score

X, Y = make_regression(10000,n_features=4)

# Обучение дерева
tree = DecisionTree('Regressor', criterion='mse', max_depth=10)
tree.fit(X, Y)

# Прогноз
predictions = tree.predict(X)

print('R2 = ',r2_score(Y,predictions))


tree.plot_decision_boundaries(X, Y)

tree.plot_regr(Y, predictions)
```

R2 =  0.9768931916957224
![1732183431372](image/README/1732183431372.png)

![1732183442813](image/README/1732183442813.png)

### **Основные методы**

#### 1. **`fit(X, y)`**

Обучает дерево на данных.

- Сбрасывает количество листьев перед началом обучения.
- Вызывает рекурсивный метод `build_tree` для построения дерева.

---

#### 2. **`build_tree(X, y, depth=0)`**

Рекурсивно строит дерево:

- Условия остановки:
  - Достигнута максимальная глубина (`max_depth`).
  - Все целевые значения одинаковы.
  - Размер выборки меньше `min_samples_leaf`.
  - Превышено число листьев (`max_leaves`).
- Если разбиение невозможно, создается лист, содержащий либо большинство классов (для классификации), либо среднее значение (для регрессии).
- Ищет лучшее разбиение с помощью `best_split`.
- Делит данные и создает поддеревья (левое и правое).

---

#### 3. **`best_split(X, y)`**

Находит лучшее разбиение на основе критерия (`criterion`):

- Для каждого признака и порога:
  - Данные делятся на левое и правое поддеревья.
  - Рассчитывается метрика качества разбиения (с помощью `split_metric`).
- Учитывается минимальное улучшение качества (`min_gain`) и минимальное количество объектов в листе (`min_samples_leaf`).

---

#### 4. **Метрики качества разбиений**

Каждая метрика вычисляется с помощью метода `split_metric`, который вызывает соответствующую функцию:

- **`gini_index`**: Индекс Джини для классификации.
- **`entropy_index`**: Энтропия для классификации.
- **`misclassification_error`**: Ошибка классификации.
- **`mean_absolute_error` (MAE)**: Средняя абсолютная ошибка для регрессии.
- **`mean_squared_error` (MSE)**: Средняя квадратичная ошибка для регрессии.

Каждая функция делит данные на две группы (левое и правое поддеревья) и вычисляет взвешенное значение метрики.

---

#### 5. **`majority_class(y)`**

Возвращает:

- Большинство классов (для классификации).
- Среднее значение (для регрессии).

---

#### 6. **`predict(X)`**

- Предсказывает значения для данных.
- Рекурсивно проходит по узлам дерева (`_predict`).

---

### **Визуализация**

#### 1. **`visualize_tree()`**

Создает графическое представление дерева с помощью `graphviz.Digraph`.

- Узлы:
  - Внутренние: Условие разбиения (`X[feature] < threshold`).
  - Листовые: Предсказанное значение.
- Ребра: Метки ("True", "False"), соответствующие условиям перехода в дерево.

#### 2. **`plot_decision_boundaries(X, y)`**

Строит границы решений для двух признаков:

- Создает сетку значений в пространстве двух признаков.
- Предсказывает класс для каждой точки сетки.
- Визуализирует области решений и исходные точки данных.

#### 3. **`plot_regr(y_true, y_pred)`**

Визуализация для регрессии:

- Строит график рассеяния истинных и предсказанных значений.
