Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

15 KiB

Лабораторная работа №2: Обнаружение аномалий с помощью автокодировщиков

Троянов Д.С., Чернов Д.Е. — А-01-22

Вариант 1 (номер бригады k=1) - данные Letter

Цель работы

Получить практические навыки создания, обучения и применения искусственных нейронных сетей типа автокодировщик. Исследовать влияние архитектуры автокодировщика и количества эпох обучения на области в пространстве признаков, распознаваемые автокодировщиком после обучения. Научиться оценивать качество обучения автокодировщика на основе ошибки реконструкции и новых метрик EDCA. Научиться решать актуальную задачу обнаружения аномалий в данных с помощью автокодировщика как одноклассового классификатора.

Определение варианта

  • Номер бригады: k = 1
  • N = k mod 3 = 1 mod 3 = 1
  • Вариант 1 => данные Letter

ЗАДАНИЕ 1: Работа с двумерными синтетическими данными

Блок 1: Импорт библиотек и настройка окружения

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: Генерация индивидуального набора двумерных данных

# Генерируем данные с центром в точке (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)

Синтетические данные

Блок 3: Создание и обучение автокодировщика AE1

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

Блок 4: Создание и обучение автокодировщика AE2

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

Блок 5: Создание тестовой выборки

# Создаем тестовые точки, которые 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: Применение автокодировщиков к тестовым данным

# Предсказания 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 | Норма     

Результаты тестирования


ЗАДАНИЕ 2: Работа с реальными данными Letter

Блок 7: Загрузка и изучение данных Letter

# Загрузка обучающей выборки
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

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

Блок 9: Применение к тестовой выборке

# Загрузка тестовой выборки
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


ИТОГОВЫЕ РЕЗУЛЬТАТЫ

Таблица 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) показывает лучшие результаты
  • Увеличение количества эпох обучения улучшает качество аппроксимации
  • Для качественного обнаружения аномалий необходимо тщательно подбирать параметры модели