# Мониторинг метрик на валидационном наборе во время обучения для предотвращения переобучения

Одной из ключевых проблем при обучении моделей машинного обучения, включая нейронные сети, является переобучение (overfitting). Оно возникает, когда модель слишком тесно "подогнана" под особенности тренировочных данных и теряет способность обобщать знания на новых, неизвестных данных. Мониторинг метрик производительности на отдельном валидационном наборе во время обучения позволяет отслеживать признаки переобучения и принимать соответствующие меры.

### Что такое переобучение?

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

### Роль валидационного набора

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

Во время обучения модели ее производительность периодически оценивается на валидационном наборе с помощью различных метрик, таких как точность, кросс-энтропийная потеря, метрики Precision, Recall и F1-score для задач классификации.

### Признаки переобучения при мониторинге

При мониторинге метрик на валидационном наборе можно заметить следующие признаки переобучения:

1. **Расхождение метрик на тренировочном и валидационном наборах**: Если производительность на тренировочных данных продолжает улучшаться, а на валидационных данных стагнирует или ухудшается, это явный признак переобучения.
2. **Высокая дисперсия метрик на валидационном наборе**: Значительные колебания метрик на валидационном наборе могут указывать на нестабильность модели и ее чувствительность к особенностям данных.

### Методы предотвращения переобучения

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

1. **Регуляризация**: Добавление штрафных членов в функцию потерь (L1, L2) или использование техник, таких как Dropout, для ограничения сложности модели.
2. **Ранняя остановка обучения (Early Stopping)**: Прекращение обучения, когда метрики на валидационном наборе перестают улучшаться в течение заданного количества эпох.
3. **Уменьшение сложности модели**: Снижение количества слоев, нейронов или других параметров модели для уменьшения ее способности к запоминанию деталей данных.
4. **Увеличение регуляризации данных**: Применение техник augmentation (увеличения) данных, добавление шума или искажений для повышения обобщающей способности модели.

### Пример мониторинга на Python

Рассмотрим пример мониторинга точности и кросс-энтропийной потери на валидационном наборе во время обучения нейронной сети для задачи классификации:

```python
import numpy as np
from sklearn.datasets import make_blobs
from sklearn.model_selection import train_test_split
import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
from tensorflow.keras.callbacks import EarlyStopping

# Генерация тестовых данных
X, y = make_blobs(n_samples=1000, centers=2, n_features=10, random_state=1)

# Разделение на тренировочный и валидационный наборы
X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.2, random_state=42)

# Создание модели
model = Sequential([
    Dense(16, activation='relu', input_shape=(10,)),
    Dense(8, activation='relu'),
    Dense(1, activation='sigmoid')
])

model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])

# Ранняя остановка при ухудшении валидационной кросс-энтропии
early_stop = EarlyStopping(monitor='val_loss', patience=5, restore_best_weights=True)

# Обучение модели с мониторингом валидационных метрик
history = model.fit(X_train, y_train, epochs=100, batch_size=32, validation_data=(X_val, y_val), callbacks=[early_stop])
```

В этом примере:

1. Мы генерируем тестовые данные с помощью `make_blobs` и разделяем их на тренировочный и валидационный наборы.
2. Создаем последовательную нейронную сеть с помощью Keras.
3. Компилируем модель, указывая функцию потерь, оптимизатор и метрики для мониторинга.
4. Создаем объект `EarlyStopping` для ранней остановки обучения, если кросс-энтропийная потеря на валидационном наборе не уменьшается в течение 5 эпох.
5. Обучаем модель, передавая валидационные данные в параметр `validation_data` и объект ранней остановки в `callbacks`.

Во время обучения значения точности и кросс-энтропийной потери на тренировочном и валидационном наборах будут отслеживаться. Если валидационная кросс-энтропия перестанет уменьшаться в течение 5 эпох, обучение прекратится благодаря ранней остановке, предотвращая дальнейшее переобучение.

Пример с использованием котировок BTC из yfinance, демонстрирующий визуализацию обучения нейронной сети с нормальным обучением и с переобучением.

```python
import yfinance as yf
import numpy as np
import pandas as pd
from sklearn.preprocessing import MinMaxScaler
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import LSTM, Dense, Dropout
import matplotlib.pyplot as plt

# Загрузка данных котировок BTC
ticker = "BTC-USD"
data = yf.download(ticker, start="2017-01-01", end="2021-01-01")
data = data["Adj Close"].to_frame()

# Нормализация данных
scaler = MinMaxScaler()
data_scaled = scaler.fit_transform(data)

# Разделение данных на тренировочный и тестовый наборы
train_size = int(len(data_scaled) * 0.8)
train_data = data_scaled[:train_size]
test_data = data_scaled[train_size:]

# Подготовка данных для обучения нейронной сети
window_size = 30
X_train = []
y_train = []
for i in range(window_size, len(train_data)):
    X_train.append(train_data[i - window_size:i, 0])
    y_train.append(train_data[i, 0])
X_train, y_train = np.array(X_train), np.array(y_train)
X_train = np.reshape(X_train, (X_train.shape[0], X_train.shape[1], 1))

# Создание и обучение моделей
# Модель без переобучения
model_normal = Sequential([
    LSTM(50, return_sequences=True, input_shape=(window_size, 1)),
    LSTM(50, return_sequences=True),
    LSTM(50),
    Dense(1)
])
model_normal.compile(loss='mean_squared_error', optimizer='adam')
history_normal = model_normal.fit(X_train, y_train, epochs=50, batch_size=32, verbose=0)

# Модель с переобучением
model_overfit = Sequential([
    LSTM(100, return_sequences=True, input_shape=(window_size, 1)),
    LSTM(100, return_sequences=True),
    LSTM(100, return_sequences=True),
    LSTM(100),
    Dense(1)
])
model_overfit.compile(loss='mean_squared_error', optimizer='adam')
history_overfit = model_overfit.fit(X_train, y_train, epochs=200, batch_size=32, verbose=0)

# Визуализация потерь на обучении
plt.figure(figsize=(12, 6))
plt.plot(history_normal.history['loss'], label='Нормальное обучение')
plt.plot(history_overfit.history['loss'], label='Переобучение')
plt.title('Потери на обучении')
plt.xlabel('Эпоха')
plt.ylabel('Потеря')
plt.legend()
plt.show()
```

В этом примере мы:

1. Загружаем исторические котировки BTC с помощью yfinance.
2. Нормализуем данные с помощью MinMaxScaler.
3. Разделяем данные на тренировочный и тестовый наборы.
4. Подготавливаем данные для обучения нейронной сети, создавая окна временных рядов размером 30.
5. Создаем две модели нейронных сетей: одну с меньшим количеством слоев и нейронов (model\_normal) и другую с большим количеством слоев и нейронов (model\_overfit).
6. Обучаем обе модели на тренировочных данных, но с разным количеством эпох (50 для model\_normal и 200 для model\_overfit).
7. Визуализируем потери на обучении для обеих моделей.

При выполнении кода будет построен график потерь на обучении для обеих моделей. Вы должны увидеть, что потери для модели с нормальным обучением (model\_normal) стабилизируются и достигают минимума, в то время как потери для переобученной модели (model\_overfit) продолжают уменьшаться, указывая на переобучение.

Этот пример демонстрирует, как визуализировать и отслеживать потери на обучении для обнаружения переобучения. В реальных сценариях следует также отслеживать метрики на валидационном наборе для более надежного контроля переобучения.

Мониторинг метрик на валидационном наборе во время обучения является важным инструментом для контроля качества модели и предотвращения переобучения. Он позволяет своевременно обнаруживать признаки переобучения и применять соответствующие методы регуляризации, ранней остановки или уменьшения сложности модели для повышения ее обобщающей способности.

[Ссылка на код статьи.](https://github.com/BeMindYou/Lesson/blob/main/Assessment_Tools/%D0%9C%D0%BE%D0%BD%D0%B8%D1%82%D0%BE%D1%80%D0%B8%D0%BD%D0%B3_%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D0%BA_%D0%BD%D0%B0_%D0%B2%D0%B0%D0%BB%D0%B8%D0%B4%D0%B0%D1%86%D0%B8%D0%BE%D0%BD%D0%BD%D0%BE%D0%BC_%D0%BD%D0%B0%D0%B1%D0%BE%D1%80%D0%B5.ipynb)&#x20;
