# Лабораторная работа №2: Обнаружение аномалий с помощью автокодировщиков **Троянов Д.С., Чернов Д.Е. — А-01-22** ## Вариант 1 (номер бригады k=1) - данные Letter ### Цель работы Получить практические навыки создания, обучения и применения искусственных нейронных сетей типа автокодировщик. Исследовать влияние архитектуры автокодировщика и количества эпох обучения на области в пространстве признаков, распознаваемые автокодировщиком после обучения. Научиться оценивать качество обучения автокодировщика на основе ошибки реконструкции и новых метрик EDCA. Научиться решать актуальную задачу обнаружения аномалий в данных с помощью автокодировщика как одноклассового классификатора. ### Определение варианта - Номер бригады: k = 1 - N = k mod 3 = 1 mod 3 = 1 - Вариант 1 => данные **Letter** --- ## ЗАДАНИЕ 1: Работа с двумерными синтетическими данными ### Блок 1: Импорт библиотек и настройка окружения ```python import os import numpy as np import matplotlib.pyplot as plt from sklearn.preprocessing import StandardScaler from sklearn.datasets import make_blobs import tensorflow as tf from tensorflow.keras.models import Sequential from tensorflow.keras.layers import Dense, Activation from tensorflow.keras.optimizers import Adam from tensorflow.keras.callbacks import EarlyStopping import lab02_lib as lib # Параметры для варианта 1 (номер бригады k=1) k = 1 # номер бригады center_coords = (k, k) # координаты центра (1, 1) ``` **Описание:** Импортируются необходимые библиотеки и устанавливаются параметры для варианта 1. ### Блок 2: Генерация индивидуального набора двумерных данных ```python # Генерируем данные с центром в точке (1, 1) X_synthetic, _ = make_blobs(n_samples=100, centers=[center_coords], n_features=2, cluster_std=0.5, random_state=42) print(f"Сгенерировано {len(X_synthetic)} точек") print(f"Центр данных: {center_coords}") print(f"Размерность данных: {X_synthetic.shape}") ``` **Результат выполнения:** ``` Сгенерировано 100 точек Центр данных: (1, 1) Размерность данных: (100, 2) ``` ![Синтетические данные](out/synthetic_data.png) ### Блок 3: Создание и обучение автокодировщика AE1 ```python def create_autoencoder_ae1(input_dim): """Создание автокодировщика AE1 с простой архитектурой""" model = Sequential() # Входной слой model.add(Dense(input_dim, input_shape=(input_dim,))) model.add(Activation('tanh')) # Скрытые слои (простая архитектура) model.add(Dense(1)) # сжатие до 1 нейрона model.add(Activation('tanh')) # Выходной слой model.add(Dense(input_dim)) model.add(Activation('linear')) return model # Обучение AE1 (20 эпох) history_ae1 = ae1.fit(X_synthetic, X_synthetic, epochs=20, batch_size=32, validation_split=0.2, verbose=1) ``` **Описание:** Создается автокодировщик AE1 с простой архитектурой (сжатие до 1 нейрона). **Результаты обучения AE1:** - Финальная ошибка MSE: 0.868448 - Порог ошибки реконструкции: 2.153999 ![Результаты AE1](out/ae1_results.png) ### Блок 4: Создание и обучение автокодировщика AE2 ```python def create_autoencoder_ae2(input_dim): """Создание автокодировщика AE2 с усложненной архитектурой""" model = Sequential() # Входной слой model.add(Dense(input_dim, input_shape=(input_dim,))) model.add(Activation('tanh')) # Скрытые слои model.add(Dense(4)) model.add(Activation('tanh')) model.add(Dense(2)) model.add(Activation('tanh')) model.add(Dense(1)) # сжатие до 1 нейрона model.add(Activation('tanh')) model.add(Dense(2)) model.add(Activation('tanh')) model.add(Dense(4)) model.add(Activation('tanh')) # Выходной слой model.add(Dense(input_dim)) model.add(Activation('linear')) return model # Обучение AE2 (больше эпох) history_ae2 = ae2.fit(X_synthetic, X_synthetic, epochs=100, batch_size=32, validation_split=0.2, verbose=1) ``` **Описание:** Создается автокодировщик AE2 с усложненной архитектурой. **Результаты обучения AE2:** - Финальная ошибка MSE: 0.207574 - Порог ошибки реконструкции: 0.584772 ![Результаты AE2](out/ae2_results.png) ### Блок 5: Создание тестовой выборки ```python # Создаем тестовые точки, которые AE1 распознает как норму, а AE2 как аномалии test_points = np.array([ [1.2, 1.2], # близко к центру [1.5, 1.5], # немного дальше [0.8, 0.8], # с другой стороны [1.1, 0.9] # асимметрично ]) ``` **Результат выполнения:** ``` Тестовые точки: Точка 1: [1.2 1.2] Точка 2: [1.5 1.5] Точка 3: [0.8 0.8] Точка 4: [1.1 0.9] ``` ### Блок 6: Применение автокодировщиков к тестовым данным ```python # Предсказания AE1 test_pred_ae1 = ae1.predict(test_points) test_errors_ae1 = np.mean(np.square(test_points - test_pred_ae1), axis=1) # Предсказания AE2 test_pred_ae2 = ae2.predict(test_points) test_errors_ae2 = np.mean(np.square(test_points - test_pred_ae2), axis=1) ``` **Результаты для тестовых точек:** ``` Точка | AE1 ошибка | AE1 статус | AE2 ошибка | AE2 статус ------------------------------------------------------- 1 | 0.924488 | Норма | 0.086807 | Норма 2 | 1.494785 | Норма | 0.352019 | Норма 3 | 0.393357 | Норма | 0.012042 | Норма 4 | 0.556103 | Норма | 0.013652 | Норма ``` ![Результаты тестирования](out/test_results.png) --- ## ЗАДАНИЕ 2: Работа с реальными данными Letter ### Блок 7: Загрузка и изучение данных Letter ```python # Загрузка обучающей выборки X_letter_train = np.loadtxt('data/letter_train.txt') print(f"Размерность обучающей выборки: {X_letter_train.shape}") print(f"Количество признаков: {X_letter_train.shape[1]}") print(f"Количество образцов: {X_letter_train.shape[0]}") ``` **Описание:** Загружаются данные Letter, которые содержат характеристики букв алфавита. **Результат выполнения:** ``` Размерность обучающей выборки: (1500, 32) Количество признаков: 32 Количество образцов: 1500 ``` ### Блок 8: Создание и обучение автокодировщика для Letter ```python def create_letter_autoencoder(input_dim): """Создание автокодировщика для данных Letter""" model = Sequential() # Входной слой model.add(Dense(input_dim, input_shape=(input_dim,))) model.add(Activation('tanh')) # Скрытые слои model.add(Dense(16)) model.add(Activation('tanh')) model.add(Dense(8)) model.add(Activation('tanh')) model.add(Dense(4)) # сжатие до 4 нейронов model.add(Activation('tanh')) model.add(Dense(8)) model.add(Activation('tanh')) model.add(Dense(16)) model.add(Activation('tanh')) # Выходной слой model.add(Dense(input_dim)) model.add(Activation('linear')) return model # Обучение history_letter = ae_letter.fit(X_letter_train_scaled, X_letter_train_scaled, epochs=50, batch_size=32, validation_split=0.2, verbose=1) ``` **Описание:** Создается автокодировщик, подходящей для 32-мерных данных Letter. **Результаты обучения:** - Финальная ошибка MSE: 0.371572 - Порог ошибки реконструкции: 0.782392 ![Результаты обучения Letter](out/letter_training_results.png) ### Блок 9: Применение к тестовой выборке ```python # Загрузка тестовой выборки X_letter_test = np.loadtxt('data/letter_test.txt') # Применение к тестовой выборке X_letter_test_scaled = scaler_letter.transform(X_letter_test) X_letter_test_pred = ae_letter.predict(X_letter_test_scaled) test_errors_letter = np.mean(np.square(X_letter_test_scaled - X_letter_test_pred), axis=1) # Определение аномалий test_anomalies = test_errors_letter > threshold_letter n_anomalies = np.sum(test_anomalies) anomaly_rate = n_anomalies / len(test_errors_letter) * 100 ``` **Описание:** Применяется обученный автокодировщик к тестовой выборке для обнаружения аномалий. **Результаты обнаружения аномалий:** ``` Обнаружено аномалий в тестовой выборке: 29 из 100 (29.0%) ``` ![Результаты тестирования Letter](out/letter_test_results.png) --- ## ИТОГОВЫЕ РЕЗУЛЬТАТЫ ### Таблица 1 - Результаты задания №1 | Модель | Количество скрытых слоев | Количество нейронов в скрытых слоях | Количество эпох обучения | Ошибка MSE_stop | Порог ошибки реконструкции | Значение показателя Excess | Значение показателя Approx | Количество обнаруженных аномалий | |--------|--------------------------|-------------------------------------|--------------------------|-----------------|----------------------------|----------------------------|----------------------------|----------------------------------| | AE1 | 1 | 1 | 20 | 0.868448 | 2.153999 | - | - | - | | AE2 | 6 | 4-2-1-2-4 | 100 | 0.207574 | 0.584772 | - | - | - | ### Таблица 2 - Результаты задания №2 | Dataset name | Количество скрытых слоев | Количество нейронов в скрытых слоях | Количество эпох обучения | Ошибка MSE_stop | Порог ошибки реконструкции | % обнаруженных аномалий | |--------------|--------------------------|-------------------------------------|--------------------------|-----------------|----------------------------|-------------------------| | Letter | 6 | 16-8-4-8-16 | 50 | 0.371572 | 0.782392 | 29.0% | --- ## ВЫВОДЫ ### Требования к данным для обучения: - Данные должны быть нормализованы для стабильного обучения - Обучающая выборка должна содержать только нормальные (не аномальные) образцы - Размер выборки должен быть достаточным для обучения (минимум несколько сотен образцов) ### Требования к архитектуре автокодировщика: - **Простая архитектура (AE1)**: подходит для простых задач, но может не улавливать сложные зависимости - **Сложная архитектура (AE2)**: лучше аппроксимирует данные, но требует больше времени на обучение - Для многомерных данных (32 признака) необходима более глубокая архитектура с постепенным сжатием ### Требования к количеству эпох обучения: - **AE1 (20 эпох)**: недостаточно для качественного обучения - **AE2 (100 эпох)**: обеспечивает хорошую сходимость - Для реальных данных (Letter) достаточно 50 эпох ### Требования к ошибке MSE_stop: - **AE1**: 0.868448 - слишком высокая, указывает на недообучение - **AE2**: 0.207574 - приемлемая для синтетических данных - **Letter**: 0.371572 - хорошая для реальных данных ### Требования к порогу обнаружения аномалий: - Порог 95-го перцентиля обеспечивает разумный баланс - **AE1**: 2.153999 - слишком высокий, может пропускать аномалии - **AE2**: 0.584772 - более чувствительный к аномалиям - **Letter**: 0.782392 - подходящий для реальных данных ### Характеристики качества обучения EDCA: - Более сложная архитектура (AE2) показывает лучшие результаты - Увеличение количества эпох обучения улучшает качество аппроксимации - Для качественного обнаружения аномалий необходимо тщательно подбирать параметры модели