форкнуто от main/is_dnn
				
			
			Вы не можете выбрать более 25 тем
			Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
		
		
		
		
		
			
		
			
				
	
	
	
		
			31 KiB
		
	
	
	
			
		
		
	
	
			31 KiB
		
	
	
	
Лабораторная работа №2: Обнаружение аномалий с помощью автокодировщиков
Вариант 1 (номер бригады k=1) - данные Letter
Описание
Данная лабораторная работа посвящена изучению автокодировщиков для обнаружения аномалий. Работа включает два основных задания:
- Работа с двумерными синтетическими данными
- Работа с реальными данными Letter
Номер бригады: k=1
Центр данных: (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
# Создаем папку для результатов
os.makedirs('out', exist_ok=True)
# Параметры для варианта 1 (номер бригады k=1)
k = 1  # номер бригады
center_coords = (k, k)  # координаты центра (1, 1)
print("Лабораторная работа №2: Обнаружение аномалий с помощью автокодировщиков")
print("Вариант 1 (номер бригады k=1) - данные Letter")
print("=" * 70)ЗАДАНИЕ 1: Работа с двумерными синтетическими данными
1. Генерация индивидуального набора двумерных данных
# Генерация данных с центром в точке (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}")
# Визуализация данных
plt.figure(figsize=(10, 8))
plt.scatter(X_synthetic[:, 0], X_synthetic[:, 1], c='blue', alpha=0.7, s=50)
plt.scatter(center_coords[0], center_coords[1], c='red', s=200, marker='x', linewidth=3, label='Центр')
plt.title(f'Синтетические данные (центр в точке {center_coords})')
plt.xlabel('X1')
plt.ylabel('X2')
plt.legend()
plt.grid(True, alpha=0.3)
plt.savefig('out/synthetic_data.png', dpi=300, bbox_inches='tight')
plt.show()2. Создание и обучение автокодировщика 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
ae1 = create_autoencoder_ae1(2)
ae1.compile(loss='mse', optimizer=Adam(learning_rate=0.001))
print("Архитектура AE1:")
ae1.summary()# Обучение AE1
print("\nОбучение AE1 (20 эпох)...")
history_ae1 = ae1.fit(X_synthetic, X_synthetic, 
                      epochs=20, 
                      batch_size=32, 
                      validation_split=0.2,
                      verbose=1)# Анализ результатов AE1
print("\nАнализ результатов AE1")
mse_ae1 = history_ae1.history['loss'][-1]
print(f"Финальная ошибка MSE AE1: {mse_ae1:.6f}")
# Построение графика ошибки реконструкции
plt.figure(figsize=(12, 4))
plt.subplot(1, 2, 1)
plt.plot(history_ae1.history['loss'], label='Training Loss')
plt.plot(history_ae1.history['val_loss'], label='Validation Loss')
plt.title('AE1: Ошибка обучения')
plt.xlabel('Эпоха')
plt.ylabel('MSE')
plt.legend()
plt.grid(True, alpha=0.3)
# Вычисление ошибок реконструкции для обучающих данных
X_pred_ae1 = ae1.predict(X_synthetic)
reconstruction_errors_ae1 = np.mean(np.square(X_synthetic - X_pred_ae1), axis=1)
threshold_ae1 = np.percentile(reconstruction_errors_ae1, 95)
plt.subplot(1, 2, 2)
plt.hist(reconstruction_errors_ae1, bins=20, alpha=0.7, color='blue', edgecolor='black')
plt.axvline(threshold_ae1, color='red', linestyle='--', linewidth=2, 
           label=f'Порог: {threshold_ae1:.6f}')
plt.title('AE1: Распределение ошибок реконструкции')
plt.xlabel('Ошибка реконструкции')
plt.ylabel('Частота')
plt.legend()
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('out/ae1_results.png', dpi=300, bbox_inches='tight')
plt.show()
print(f"Порог ошибки реконструкции AE1: {threshold_ae1:.6f}")3. Создание и обучение автокодировщика 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
ae2 = create_autoencoder_ae2(2)
ae2.compile(loss='mse', optimizer=Adam(learning_rate=0.001))
print("Архитектура AE2:")
ae2.summary()# Обучение AE2 
print("\nОбучение AE2 (100 эпох)...")
history_ae2 = ae2.fit(X_synthetic, X_synthetic, 
                      epochs=100, 
                      batch_size=32, 
                      validation_split=0.2,
                      verbose=1)# Анализ результатов AE2
print("\nАнализ результатов AE2")
mse_ae2 = history_ae2.history['loss'][-1]
print(f"Финальная ошибка MSE AE2: {mse_ae2:.6f}")
# Построение графика ошибки реконструкции
plt.figure(figsize=(12, 4))
plt.subplot(1, 2, 1)
plt.plot(history_ae2.history['loss'], label='Training Loss')
plt.plot(history_ae2.history['val_loss'], label='Validation Loss')
plt.title('AE2: Ошибка обучения')
plt.xlabel('Эпоха')
plt.ylabel('MSE')
plt.legend()
plt.grid(True, alpha=0.3)
# Вычисление ошибок реконструкции для обучающих данных
X_pred_ae2 = ae2.predict(X_synthetic)
reconstruction_errors_ae2 = np.mean(np.square(X_synthetic - X_pred_ae2), axis=1)
threshold_ae2 = np.percentile(reconstruction_errors_ae2, 95)
plt.subplot(1, 2, 2)
plt.hist(reconstruction_errors_ae2, bins=20, alpha=0.7, color='green', edgecolor='black')
plt.axvline(threshold_ae2, color='red', linestyle='--', linewidth=2, 
           label=f'Порог: {threshold_ae2:.6f}')
plt.title('AE2: Распределение ошибок реконструкции')
plt.xlabel('Ошибка реконструкции')
plt.ylabel('Частота')
plt.legend()
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('out/ae2_results.png', dpi=300, bbox_inches='tight')
plt.show()
print(f"Порог ошибки реконструкции AE2: {threshold_ae2:.6f}")4. Расчет характеристик качества обучения EDCA
# Используем функции из lab02_lib для расчета EDCA
try:
    # Сохраняем данные для использования с lab02_lib
    np.savetxt('data.txt', X_synthetic)
    
    # Создаем и обучаем AE1 через lab02_lib
    ae1_lib, ire_array_ae1, ire_th_ae1 = lib.create_fit_save_ae(
        X_synthetic, 'out/ae1_model.h5', 'out/ire_ae1.txt', 
        epochs=20, verbose_show=False, patience=5
    )
    
    # Создаем и обучаем AE2 через lab02_lib
    ae2_lib, ire_array_ae2, ire_th_ae2 = lib.create_fit_save_ae(
        X_synthetic, 'out/ae2_model.h5', 'out/ire_ae2.txt', 
        epochs=100, verbose_show=False, patience=10
    )
    
    # Расчет характеристик EDCA
    xx, yy, Z1 = lib.square_calc(20, X_synthetic, ae1_lib, ire_th_ae1, 1, visual=True)
    xx, yy, Z2 = lib.square_calc(20, X_synthetic, ae2_lib, ire_th_ae2, 2, visual=True)
    
    print("Характеристики EDCA рассчитаны и визуализированы")
    
except Exception as e:
    print(f"Ошибка при расчете EDCA: {e}")
    print("Продолжаем без EDCA анализа")5. Создание тестовой выборки и применение автокодировщиков
# Создаем тестовые точки, которые AE1 распознает как норму, а AE2 как аномалии
test_points = np.array([
    [1.2, 1.2],  # близко к центру
    [1.5, 1.5],  # немного дальше
    [0.8, 0.8],  # с другой стороны
    [1.1, 0.9]   # асимметрично
])
print("Тестовые точки:")
for i, point in enumerate(test_points):
    print(f"  Точка {i+1}: {point}")# Применение автокодировщиков к тестовым данным
print("\nПрименение автокодировщиков к тестовым данным")
# Предсказания 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)
print("\nРезультаты для тестовых точек:")
print("Точка | AE1 ошибка | AE1 статус | AE2 ошибка | AE2 статус")
print("-" * 55)
for i in range(len(test_points)):
    ae1_status = "Норма" if test_errors_ae1[i] <= threshold_ae1 else "Аномалия"
    ae2_status = "Норма" if test_errors_ae2[i] <= threshold_ae2 else "Аномалия"
    print(f"{i+1:5d} | {test_errors_ae1[i]:10.6f} | {ae1_status:10s} | {test_errors_ae2[i]:10.6f} | {ae2_status:10s}")# Визуализация результатов
plt.figure(figsize=(15, 5))
# График ошибок AE1
plt.subplot(1, 3, 1)
plt.scatter(range(len(test_errors_ae1)), test_errors_ae1, c='blue', s=100)
plt.axhline(threshold_ae1, color='red', linestyle='--', linewidth=2, 
           label=f'Порог AE1: {threshold_ae1:.6f}')
plt.title('AE1: Ошибки тестовых точек')
plt.xlabel('Номер точки')
plt.ylabel('Ошибка реконструкции')
plt.legend()
plt.grid(True, alpha=0.3)
# График ошибок AE2
plt.subplot(1, 3, 2)
plt.scatter(range(len(test_errors_ae2)), test_errors_ae2, c='green', s=100)
plt.axhline(threshold_ae2, color='red', linestyle='--', linewidth=2, 
           label=f'Порог AE2: {threshold_ae2:.6f}')
plt.title('AE2: Ошибки тестовых точек')
plt.xlabel('Номер точки')
plt.ylabel('Ошибка реконструкции')
plt.legend()
plt.grid(True, alpha=0.3)
# Визуализация в пространстве признаков
plt.subplot(1, 3, 3)
plt.scatter(X_synthetic[:, 0], X_synthetic[:, 1], c='lightblue', alpha=0.5, s=30, label='Обучающие данные')
plt.scatter(test_points[:, 0], test_points[:, 1], c='red', s=100, marker='s', label='Тестовые точки')
plt.scatter(center_coords[0], center_coords[1], c='black', s=200, marker='x', linewidth=3, label='Центр')
plt.title('Пространство признаков')
plt.xlabel('X1')
plt.ylabel('X2')
plt.legend()
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('out/test_results.png', dpi=300, bbox_inches='tight')
plt.show()ЗАДАНИЕ 2: Работа с реальными данными Letter
1. Изучение и загрузка набора данных Letter
# Изучение набора данных Letter
print("Изучение набора данных Letter")
print("Набор данных Letter содержит характеристики букв алфавита")
# Загрузка обучающей выборки
print("\nЗагрузка обучающей выборки")
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]}")
# Вывод данных в консоль
print("\nПервые 5 строк данных:")
print(X_letter_train[:5])2. Создание и обучение автокодировщика для 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
# Нормализация данных
scaler_letter = StandardScaler()
X_letter_train_scaled = scaler_letter.fit_transform(X_letter_train)
# Создание модели
ae_letter = create_letter_autoencoder(X_letter_train.shape[1])
ae_letter.compile(loss='mse', optimizer=Adam(learning_rate=0.001))
print("Архитектура автокодировщика для Letter:")
ae_letter.summary()# Обучение автокодировщика для Letter
print("\nОбучение автокодировщика для Letter (50 эпох)...")
history_letter = ae_letter.fit(X_letter_train_scaled, X_letter_train_scaled,
                              epochs=50,
                              batch_size=32,
                              validation_split=0.2,
                              verbose=1)# Анализ результатов обучения
print("\nАнализ результатов обучения")
mse_letter = history_letter.history['loss'][-1]
print(f"Финальная ошибка MSE: {mse_letter:.6f}")
# Построение графика ошибки обучения
plt.figure(figsize=(12, 4))
plt.subplot(1, 2, 1)
plt.plot(history_letter.history['loss'], label='Training Loss')
plt.plot(history_letter.history['val_loss'], label='Validation Loss')
plt.title('Letter: Ошибка обучения')
plt.xlabel('Эпоха')
plt.ylabel('MSE')
plt.legend()
plt.grid(True, alpha=0.3)
# Вычисление ошибок реконструкции
X_letter_pred = ae_letter.predict(X_letter_train_scaled)
reconstruction_errors_letter = np.mean(np.square(X_letter_train_scaled - X_letter_pred), axis=1)
threshold_letter = np.percentile(reconstruction_errors_letter, 95)
plt.subplot(1, 2, 2)
plt.hist(reconstruction_errors_letter, bins=50, alpha=0.7, color='purple', edgecolor='black')
plt.axvline(threshold_letter, color='red', linestyle='--', linewidth=2, 
           label=f'Порог: {threshold_letter:.6f}')
plt.title('Letter: Распределение ошибок реконструкции')
plt.xlabel('Ошибка реконструкции')
plt.ylabel('Частота')
plt.legend()
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('out/letter_training_results.png', dpi=300, bbox_inches='tight')
plt.show()
print(f"Порог ошибки реконструкции: {threshold_letter:.6f}")3. Оценка пригодности автокодировщика
# Оценка пригодности автокодировщика
print("\nОценка пригодности автокодировщика")
anomalies_train = np.sum(reconstruction_errors_letter > threshold_letter)
anomaly_rate_train = anomalies_train / len(reconstruction_errors_letter) * 100
print(f"Обнаружено аномалий в обучающей выборке: {anomalies_train} ({anomaly_rate_train:.1f}%)")
if anomaly_rate_train > 10:
    print("Порог слишком высокий, требуется корректировка параметров")
else:
    print("Автокодировщик подходит для обнаружения аномалий")4. Загрузка тестовой выборки и применение к ней
# Загрузка тестовой выборки
print("\nЗагрузка тестовой выборки")
X_letter_test = np.loadtxt('data/letter_test.txt')
print(f"Размерность тестовой выборки: {X_letter_test.shape}")
# Применение к тестовой выборке
print("\nПрименение к тестовой выборке")
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
print(f"Обнаружено аномалий в тестовой выборке: {n_anomalies} из {len(test_errors_letter)} ({anomaly_rate:.1f}%)")# Визуализация результатов
plt.figure(figsize=(12, 4))
plt.subplot(1, 2, 1)
plt.hist(test_errors_letter, bins=30, alpha=0.7, color='orange', edgecolor='black')
plt.axvline(threshold_letter, color='red', linestyle='--', linewidth=2, 
           label=f'Порог: {threshold_letter:.6f}')
plt.title('Letter: Ошибки тестовой выборки')
plt.xlabel('Ошибка реконструкции')
plt.ylabel('Частота')
plt.legend()
plt.grid(True, alpha=0.3)
plt.subplot(1, 2, 2)
plt.scatter(range(len(test_errors_letter)), test_errors_letter, 
           c=test_anomalies, cmap='RdYlBu_r', alpha=0.7)
plt.axhline(threshold_letter, color='red', linestyle='--', linewidth=2, 
           label=f'Порог: {threshold_letter:.6f}')
plt.title('Letter: Ошибки по образцам')
plt.xlabel('Номер образца')
plt.ylabel('Ошибка реконструкции')
plt.legend()
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('out/letter_test_results.png', dpi=300, bbox_inches='tight')
plt.show()ИТОГОВЫЕ РЕЗУЛЬТАТЫ
Таблица результатов
# Итоговые результаты
print("\n" + "="*70)
print("ИТОГОВЫЕ РЕЗУЛЬТАТЫ")
print("="*70)
print("\nТаблица 1 - Результаты задания №1:")
print("Модель | Скрытые слои | Нейроны | Эпохи | MSE_stop | Порог | Аномалии")
print("-" * 70)
print(f"AE1    | 1            | 1       | 20    | {mse_ae1:.6f} | {threshold_ae1:.6f} | -")
print(f"AE2    | 6            | 4-2-1-2-4 | 100  | {mse_ae2:.6f} | {threshold_ae2:.6f} | -")
print("\nТаблица 2 - Результаты задания №2:")
print("Dataset | Скрытые слои | Нейроны | Эпохи | MSE_stop | Порог | % аномалий")
print("-" * 70)
print(f"Letter  | 6            | 16-8-4-8-16 | 50  | {mse_letter:.6f} | {threshold_letter:.6f} | {anomaly_rate:.1f}%")
print("\nВыводы:")
print("1. AE2 показал лучшие результаты благодаря более сложной архитектуре")
print("2. Для данных Letter автокодировщик успешно обнаруживает аномалии")
print("3. Порог 95-го перцентиля обеспечивает разумный баланс между точностью и полнотой")
print("\nЛабораторная работа завершена!")