форкнуто от main/is_dnn
Вы не можете выбрать более 25 тем
Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
743 строки
31 KiB
Plaintext
743 строки
31 KiB
Plaintext
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"# Лабораторная работа №2\n",
|
|
"## Обнаружение аномалий с помощью автокодировщиков\n",
|
|
"\n",
|
|
"**Выполнили:** Троянов Даниил Сергеевич, Чернов Данила Евгеньевич \n",
|
|
"**Группа:** А-01-22 \n",
|
|
"**Бригада:** 1\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Задание 1\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### 1) Импорт необходимых библиотек и модулей\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"import os\n",
|
|
"import numpy as np\n",
|
|
"import matplotlib.pyplot as plt\n",
|
|
"import lab02_lib as lib\n",
|
|
"from unittest.mock import patch\n",
|
|
"import builtins\n",
|
|
"\n",
|
|
"# Создаем директорию для выходных файлов\n",
|
|
"os.makedirs('out', exist_ok=True)\n",
|
|
"\n",
|
|
"print('Библиотеки успешно импортированы')\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### 2) Генерация индивидуального набора двумерных данных\n",
|
|
"\n",
|
|
"Сгенерируем набор данных с координатами центра (1, 1), где 1 – номер бригады.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Генерация датасета для бригады 1\n",
|
|
"brigade_num = 1\n",
|
|
"data = lib.datagen(brigade_num, brigade_num, 1000, 2)\n",
|
|
"\n",
|
|
"# Вывод данных и размерности\n",
|
|
"print('Исходные данные (первые 10 строк):')\n",
|
|
"print(data[:10])\n",
|
|
"print('\\nРазмерность данных:')\n",
|
|
"print(data.shape)\n",
|
|
"print(f'\\nЦентр кластера: ({brigade_num}, {brigade_num})')\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### 3) Создание и обучение автокодировщика AE1 простой архитектуры\n",
|
|
"\n",
|
|
"Создадим простой автокодировщик с минимальной архитектурой и небольшим количеством эпох обучения.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Обучение AE1 с использованием функции из lab02_lib\n",
|
|
"# Для простой архитектуры используем вариант с пользовательской архитектурой\n",
|
|
"# Архитектура: 2 -> 1 -> 2 (1 скрытый слой с 1 нейроном)\n",
|
|
"\n",
|
|
"print('Обучение автокодировщика AE1...')\n",
|
|
"print('Архитектура: 2 -> 1 -> 2 (простая)')\n",
|
|
"\n",
|
|
"# Автоматизируем ввод для выбора пользовательской архитектуры\n",
|
|
"with patch('builtins.input', side_effect=['1', '1', '1']):\n",
|
|
" ae1_trained, IRE1, IREth1 = lib.create_fit_save_ae(\n",
|
|
" data, \n",
|
|
" 'out/AE1.h5', \n",
|
|
" 'out/AE1_ire_th.txt',\n",
|
|
" 1000, # epochs\n",
|
|
" True, # verbose_show\n",
|
|
" 300, # patience\n",
|
|
" early_stopping_delta=0.001\n",
|
|
" )\n",
|
|
"\n",
|
|
"# Вычисление MSE из истории обучения (приблизительно)\n",
|
|
"# Для точного значения нужно сохранить историю, но функция не возвращает её\n",
|
|
"# Используем предсказание для оценки\n",
|
|
"X_pred_ae1 = ae1_trained.predict(data, verbose=0)\n",
|
|
"mse_ae1 = np.mean((data - X_pred_ae1) ** 2)\n",
|
|
"\n",
|
|
"print(f'\\nОбучение завершено!')\n",
|
|
"print(f'MSE_stop (приблизительно): {mse_ae1:.6f}')\n",
|
|
"print(f'Порог IRE: {IREth1:.6f}')\n",
|
|
"print(f'Количество скрытых слоев: 1')\n",
|
|
"print(f'Количество нейронов в скрытых слоях: 1')\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### 4) Построение графика ошибки реконструкции для AE1\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Построение графика ошибки реконструкции\n",
|
|
"lib.ire_plot('training', IRE1, IREth1, 'AE1')\n",
|
|
"print(f'Порог ошибки реконструкции (IREth1): {IREth1:.6f}')\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### 5) Создание и обучение автокодировщика AE2 с усложненной архитектурой\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Обучение AE2 с использованием функции из lab02_lib\n",
|
|
"# Для усложненной архитектуры используем вариант с пользовательской архитектурой\n",
|
|
"# Архитектура: 2 -> 8 -> 4 -> 2 -> 1 -> 2 -> 4 -> 8 -> 2 (6 скрытых слоев)\n",
|
|
"\n",
|
|
"print('Обучение автокодировщика AE2...')\n",
|
|
"print('Архитектура: 2 -> 8 -> 4 -> 2 -> 1 -> 2 -> 4 -> 8 -> 2 (усложненная)')\n",
|
|
"\n",
|
|
"# Автоматизируем ввод для выбора пользовательской архитектуры\n",
|
|
"# 7 скрытых слоев: 8 4 2 1 2 4 8\n",
|
|
"with patch('builtins.input', side_effect=['1', '7', '8 4 2 1 2 4 8']):\n",
|
|
" ae2_trained, IRE2, IREth2 = lib.create_fit_save_ae(\n",
|
|
" data, \n",
|
|
" 'out/AE2.h5', \n",
|
|
" 'out/AE2_ire_th.txt',\n",
|
|
" 3000, # epochs\n",
|
|
" True, # verbose_show\n",
|
|
" 300, # patience\n",
|
|
" early_stopping_delta=0.001\n",
|
|
" )\n",
|
|
"\n",
|
|
"# Вычисление MSE из предсказания\n",
|
|
"X_pred_ae2 = ae2_trained.predict(data, verbose=0)\n",
|
|
"mse_ae2 = np.mean((data - X_pred_ae2) ** 2)\n",
|
|
"\n",
|
|
"print(f'\\nОбучение завершено!')\n",
|
|
"print(f'MSE_stop (приблизительно): {mse_ae2:.6f}')\n",
|
|
"print(f'Порог IRE: {IREth2:.6f}')\n",
|
|
"print(f'Количество скрытых слоев: 6')\n",
|
|
"print(f'Количество нейронов в скрытых слоях: 8-4-2-1-2-4-8')\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### 6) Построение графика ошибки реконструкции для AE2\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Построение графика ошибки реконструкции\n",
|
|
"lib.ire_plot('training', IRE2, IREth2, 'AE2')\n",
|
|
"print(f'Порог ошибки реконструкции (IREth2): {IREth2:.6f}')\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### 7) Расчет характеристик качества обучения EDCA для AE1 и AE2\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Расчет EDCA для AE1\n",
|
|
"numb_square = 20\n",
|
|
"xx, yy, Z1 = lib.square_calc(numb_square, data, ae1_trained, IREth1, '1', True)\n",
|
|
"\n",
|
|
"# Сохраняем результаты EDCA для AE1 сразу после расчета\n",
|
|
"excess_ae1 = None\n",
|
|
"approx_ae1 = None\n",
|
|
"try:\n",
|
|
" with open('out/result.txt', 'r') as f:\n",
|
|
" content = f.read()\n",
|
|
" if 'AE1' in content:\n",
|
|
" lines = content.split('\\n')\n",
|
|
" for line in lines:\n",
|
|
" if 'Excess' in line and excess_ae1 is None:\n",
|
|
" excess_ae1 = float(line.split('=')[1].strip())\n",
|
|
" elif 'Approx' in line and approx_ae1 is None:\n",
|
|
" approx_ae1 = float(line.split('=')[1].strip())\n",
|
|
"except:\n",
|
|
" pass\n",
|
|
"\n",
|
|
"print(f'\\nСохраненные результаты для AE1:')\n",
|
|
"print(f'Excess: {excess_ae1}')\n",
|
|
"print(f'Approx: {approx_ae1}')\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Расчет EDCA для AE2\n",
|
|
"xx, yy, Z2 = lib.square_calc(numb_square, data, ae2_trained, IREth2, '2', True)\n",
|
|
"\n",
|
|
"# Сохраняем результаты EDCA для AE2 сразу после расчета\n",
|
|
"excess_ae2 = None\n",
|
|
"approx_ae2 = None\n",
|
|
"try:\n",
|
|
" with open('out/result.txt', 'r') as f:\n",
|
|
" content = f.read()\n",
|
|
" if 'AE2' in content:\n",
|
|
" lines = content.split('\\n')\n",
|
|
" for line in lines:\n",
|
|
" if 'Excess' in line and excess_ae2 is None:\n",
|
|
" excess_ae2 = float(line.split('=')[1].strip())\n",
|
|
" elif 'Approx' in line and approx_ae2 is None:\n",
|
|
" approx_ae2 = float(line.split('=')[1].strip())\n",
|
|
"except:\n",
|
|
" pass\n",
|
|
"\n",
|
|
"print(f'\\nСохраненные результаты для AE2:')\n",
|
|
"print(f'Excess: {excess_ae2}')\n",
|
|
"print(f'Approx: {approx_ae2}')\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Сравнение характеристик качества обучения и областей аппроксимации\n",
|
|
"lib.plot2in1(data, xx, yy, Z1, Z2)\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### 8) Создание тестовой выборки\n",
|
|
"\n",
|
|
"Создадим тестовую выборку из элементов, которые AE1 распознает как норму, а AE2 детектирует как аномалии.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Создание тестовой выборки\n",
|
|
"# Точки, которые находятся на среднем расстоянии от центра (1, 1)\n",
|
|
"# чтобы AE1 их не распознал как аномалии (IRE < порог AE1 ~2.06),\n",
|
|
"# но AE2 распознал как аномалии (IRE > порог AE2 ~0.41)\n",
|
|
"# Выбираем точки на расстоянии примерно 1-1.5 от центра\n",
|
|
"data_test = np.array([\n",
|
|
" [-0.5, 0.5], \n",
|
|
" [1, 0.5], \n",
|
|
" [0.2, 1.2], \n",
|
|
" [0, 0.1] \n",
|
|
"])\n",
|
|
"\n",
|
|
"print('Тестовая выборка:')\n",
|
|
"print(data_test)\n",
|
|
"print(f'\\nРазмерность: {data_test.shape}')\n",
|
|
"print(f'\\nЦентр обучающих данных: (1, 1)')\n",
|
|
"print(f'Расстояния от центра:')\n",
|
|
"for i, point in enumerate(data_test):\n",
|
|
" dist = np.sqrt((point[0] - 1)**2 + (point[1] - 1)**2)\n",
|
|
" print(f' Точка {i+1} {point}: расстояние = {dist:.3f}')\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### 9) Применение автокодировщиков к тестовым данным\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Тестирование AE1\n",
|
|
"predicted_labels1, ire1_test = lib.predict_ae(ae1_trained, data_test, IREth1)\n",
|
|
"lib.anomaly_detection_ae(predicted_labels1, ire1_test, IREth1)\n",
|
|
"lib.ire_plot('test', ire1_test, IREth1, 'AE1')\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Тестирование AE2\n",
|
|
"predicted_labels2, ire2_test = lib.predict_ae(ae2_trained, data_test, IREth2)\n",
|
|
"lib.anomaly_detection_ae(predicted_labels2, ire2_test, IREth2)\n",
|
|
"lib.ire_plot('test', ire2_test, IREth2, 'AE2')\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Визуализация элементов обучающей и тестовой выборки\n",
|
|
"lib.plot2in1_anomaly(data, xx, yy, Z1, Z2, data_test)\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": []
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Подсчет обнаруженных аномалий\n",
|
|
"anomalies_ae1 = int(predicted_labels1.sum())\n",
|
|
"anomalies_ae2 = int(predicted_labels2.sum())\n",
|
|
"\n",
|
|
"# Используем сохраненные ранее значения EDCA метрик\n",
|
|
"# (они были сохранены в ячейках после вызова square_calc)\n",
|
|
"# Если переменные не определены, пытаемся прочитать из файла\n",
|
|
"try:\n",
|
|
" excess_ae1_val = excess_ae1 if excess_ae1 is not None else None\n",
|
|
"except NameError:\n",
|
|
" excess_ae1_val = None\n",
|
|
"\n",
|
|
"try:\n",
|
|
" approx_ae1_val = approx_ae1 if approx_ae1 is not None else None\n",
|
|
"except NameError:\n",
|
|
" approx_ae1_val = None\n",
|
|
"\n",
|
|
"try:\n",
|
|
" excess_ae2_val = excess_ae2 if excess_ae2 is not None else None\n",
|
|
"except NameError:\n",
|
|
" excess_ae2_val = None\n",
|
|
"\n",
|
|
"try:\n",
|
|
" approx_ae2_val = approx_ae2 if approx_ae2 is not None else None\n",
|
|
"except NameError:\n",
|
|
" approx_ae2_val = None\n",
|
|
"\n",
|
|
"print('Таблица 1 - Результаты задания №1')\n",
|
|
"print('=' * 120)\n",
|
|
"print(f'{\"Модель\":<10} {\"Скрытых слоев\":<15} {\"Нейроны\":<25} {\"Эпох\":<10} {\"MSE_stop\":<12} {\"Порог IRE\":<12} {\"Excess\":<10} {\"Approx\":<10} {\"Аномалий\":<10}')\n",
|
|
"print('-' * 120)\n",
|
|
"print(f'AE1 {1:<15} {1:<25} {1000:<10} {mse_ae1:<12.6f} {IREth1:<12.6f} {excess_ae1_val if excess_ae1_val is not None else \"N/A\":<10} {approx_ae1_val if approx_ae1_val is not None else \"N/A\":<10} {anomalies_ae1}/{len(data_test):<10}')\n",
|
|
"print(f'AE2 {6:<15} {\"8-4-2-1-2-4-8\":<25} {3000:<10} {mse_ae2:<12.6f} {IREth2:<12.6f} {excess_ae2_val if excess_ae2_val is not None else \"N/A\":<10} {approx_ae2_val if approx_ae2_val is not None else \"N/A\":<10} {anomalies_ae2}/{len(data_test):<10}')\n",
|
|
"print('=' * 120)\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Задание 2\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### 1) Изучение набора реальных данных Letter\n",
|
|
"\n",
|
|
"Набор данных Letter представляет собой характеристики букв английского алфавита. Для обнаружения аномалий нормальные примеры используются для обучения, а аномальные - для тестирования.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Загрузка обучающей и тестовой выборки Letter\n",
|
|
"train_letter = np.loadtxt('data/letter_train.txt', dtype=float)\n",
|
|
"test_letter = np.loadtxt('data/letter_test.txt', dtype=float)\n",
|
|
"\n",
|
|
"print('Обучающая выборка Letter:')\n",
|
|
"print(f'Размерность: {train_letter.shape}')\n",
|
|
"print(f'Количество признаков: {train_letter.shape[1]}')\n",
|
|
"print(f'Количество примеров: {train_letter.shape[0]}')\n",
|
|
"print(f'\\nПервые 5 строк:')\n",
|
|
"print(train_letter[:5])\n",
|
|
"\n",
|
|
"print(f'\\nТестовая выборка Letter:')\n",
|
|
"print(f'Размерность: {test_letter.shape}')\n",
|
|
"print(f'Количество примеров: {test_letter.shape[0]}')\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### 2.1) Нормализация данных (дополнительное исследование, для сравнения)\n",
|
|
"\n",
|
|
"Создадим нормализованную версию данных для сравнения результатов обучения.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Нормализация данных для сравнения результатов\n",
|
|
"from sklearn.preprocessing import StandardScaler\n",
|
|
"\n",
|
|
"# Создаем нормализованные версии данных\n",
|
|
"scaler = StandardScaler()\n",
|
|
"train_letter_normalized = scaler.fit_transform(train_letter)\n",
|
|
"test_letter_normalized = scaler.transform(test_letter)\n",
|
|
"\n",
|
|
"print('Нормализация данных выполнена')\n",
|
|
"print(f'\\nИсходные данные (первые 3 признака первого примера):')\n",
|
|
"print(f' train_letter[0, :3] = {train_letter[0, :3]}')\n",
|
|
"print(f'\\nНормализованные данные (первые 3 признака первого примера):')\n",
|
|
"print(f' train_letter_normalized[0, :3] = {train_letter_normalized[0, :3]}')\n",
|
|
"print(f'\\nСтатистика нормализованных данных:')\n",
|
|
"print(f' Среднее: {train_letter_normalized.mean(axis=0)[:5]}...')\n",
|
|
"print(f' Стд. отклонение: {train_letter_normalized.std(axis=0)[:5]}...')\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### 2.2) Обучение автокодировщика на ненормализованных данных\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Обучение автокодировщика для Letter на НЕнормализованных данных\n",
|
|
"# Входной и выходной слои создаются автоматически по размеру данных (32 признака)\n",
|
|
"# Мы задаем только скрытые слои\n",
|
|
"# Полная архитектура: 32(вход) -> 100 -> 68 -> 48 -> 32 -> 24 -> 16 -> 8 -> 16 -> 24 -> 32 -> 48 -> 64 -> 100 -> 32(выход)\n",
|
|
"# 11 скрытых слоев: 100 64 48 32 24 16 8 16 24 32 48 64 100 \n",
|
|
"\n",
|
|
"import warnings\n",
|
|
"# Подавляем предупреждение о формате сохранения HDF5\n",
|
|
"warnings.filterwarnings('ignore', category=UserWarning, module='absl')\n",
|
|
"\n",
|
|
"print('Обучение автокодировщика для данных Letter (НЕнормализованные данные)...')\n",
|
|
"print('Архитектура: 32(вход) -> 100 -> 68 -> 48 -> 32 -> 24 -> 16 -> 8 -> 16 -> 24 -> 32 -> 48 -> 64 -> 100 -> 32(выход)')\n",
|
|
"\n",
|
|
"# Автоматизируем ввод для выбора пользовательской архитектуры\n",
|
|
"with patch('builtins.input', side_effect=['1', '17', ' 100 86 72 64 48 32 24 16 8 16 24 32 48 64 72 86 100']):\n",
|
|
" ae_letter_raw, IRE_letter_raw, IREth_letter_raw = lib.create_fit_save_ae(\n",
|
|
" train_letter, \n",
|
|
" 'out/Letter_AE_raw.h5', \n",
|
|
" 'out/Letter_AE_raw_ire_th.txt',\n",
|
|
" 100000, # epochs\n",
|
|
" False, # verbose_show\n",
|
|
" 10000, # patience\n",
|
|
" verbose_every_n_epochs=500\n",
|
|
" )\n",
|
|
"\n",
|
|
"# Вычисление MSE из предсказания\n",
|
|
"X_pred_letter_raw = ae_letter_raw.predict(train_letter, verbose=0)\n",
|
|
"mse_letter_raw = np.mean((train_letter - X_pred_letter_raw) ** 2)\n",
|
|
"\n",
|
|
"print(f'\\nОбучение завершено (НЕнормализованные данные)!')\n",
|
|
"print(f'MSE_stop (приблизительно): {mse_letter_raw:.6f}')\n",
|
|
"print(f'Порог IRE: {IREth_letter_raw:.6f}')\n",
|
|
"print(f'Количество скрытых слоев: 11')\n",
|
|
"print(f'Количество нейронов в скрытых слоях: 100 -> 68 -> 48 -> 32 -> 24 -> 16 -> 8 -> 16 -> 24 -> 32 -> 48 -> 64 -> 100')\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### 2.3) Обучение автокодировщика на нормализованных данных\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Обучение автокодировщика для Letter на нормализованных данных\n",
|
|
"# Та же архитектура для сравнения: 32(вход) -> 100 -> 68 -> 48 -> 32 -> 24 -> 16 -> 8 -> 16 -> 24 -> 32 -> 48 -> 64 -> 100 -> 32(выход)\n",
|
|
"# 11 скрытых слоев: 100 86 72 64 48 32 24 16 8 16 24 32 48 64 72 86 100\n",
|
|
"\n",
|
|
"print('Обучение автокодировщика для данных Letter (нормализованные данные)...')\n",
|
|
"print('Архитектура: 32(вход) -> 100 -> 68 -> 48 -> 32 -> 24 -> 16 -> 8 -> 16 -> 24 -> 32 -> 48 -> 64 -> 100 -> 32(выход)')\n",
|
|
"\n",
|
|
"# Автоматизируем ввод для выбора пользовательской архитектуры\n",
|
|
"with patch('builtins.input', side_effect=['1', '17', ' 100 86 72 64 48 32 24 16 8 16 24 32 48 64 72 86 100']):\n",
|
|
" ae_letter_norm, IRE_letter_norm, IREth_letter_norm = lib.create_fit_save_ae(\n",
|
|
" train_letter_normalized, \n",
|
|
" 'out/Letter_AE_norm.h5', \n",
|
|
" 'out/Letter_AE_norm_ire_th.txt',\n",
|
|
" 20000, # epochs\n",
|
|
" True, # verbose_show\n",
|
|
" 200, # patience\n",
|
|
" verbose_every_n_epochs=500\n",
|
|
" )\n",
|
|
"\n",
|
|
"# Вычисление MSE из предсказания\n",
|
|
"X_pred_letter_norm = ae_letter_norm.predict(train_letter_normalized, verbose=0)\n",
|
|
"mse_letter_norm = np.mean((train_letter_normalized - X_pred_letter_norm) ** 2)\n",
|
|
"\n",
|
|
"print(f'\\nОбучение завершено (нормализованные данные)!')\n",
|
|
"print(f'MSE_stop (приблизительно): {mse_letter_norm:.6f}')\n",
|
|
"print(f'Порог IRE: {IREth_letter_norm:.6f}')\n",
|
|
"print(f'Количество скрытых слоев: 11')\n",
|
|
"print(f'Количество нейронов в скрытых слоях: 100 -> 68 -> 48 -> 32 -> 24 -> 16 -> 8 -> 16 -> 24 -> 32 -> 48 -> 64 -> 100')\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### 2.4) Сравнение результатов обучения на нормализованных и ненормализованных данных\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Сравнение результатов\n",
|
|
"print('=' * 100)\n",
|
|
"print('СРАВНЕНИЕ РЕЗУЛЬТАТОВ ОБУЧЕНИЯ')\n",
|
|
"print('=' * 100)\n",
|
|
"print(f'{\"Параметр\"} {\"НЕнормализованные\"} {\"Нормализованные\"}')\n",
|
|
"print('-' * 100)\n",
|
|
"print(f'{\"MSE_stop\"} {mse_letter_raw} {mse_letter_norm}')\n",
|
|
"print(f'{\"Порог IRE\"} {IREth_letter_raw} {IREth_letter_norm:}')\n",
|
|
"print(f'{\"Архитектура\":<30} {\"17 слоев\"} {\"17 слоев\"}')\n",
|
|
"print(f'{\"Нейроны\"} {\"32(вход) -> 100 -> 68 -> 48 -> 32 -> 24 -> 16 -> 8 -> 16 -> 24 -> 32 -> 48 -> 64 -> 100 -> 32(выход)\"} {\"32(вход) -> 100 -> 68 -> 48 -> 32 -> 24 -> 16 -> 8 -> 16 -> 24 -> 32 -> 48 -> 64 -> 100 -> 32(выход)\"}')\n",
|
|
"print('=' * 100)\n",
|
|
"\n",
|
|
"# Выбираем лучшую модель для дальнейшей работы\n",
|
|
"if mse_letter_norm < mse_letter_raw:\n",
|
|
" print('\\nЛучшая модель: НОРМАЛИЗОВАННЫЕ данные')\n",
|
|
" ae_letter = ae_letter_norm\n",
|
|
" IRE_letter = IRE_letter_norm\n",
|
|
" IREth_letter = IREth_letter_norm\n",
|
|
" mse_letter = mse_letter_norm\n",
|
|
" test_letter_used = test_letter_normalized\n",
|
|
" print(f'Используем эту модель для дальнейших экспериментов')\n",
|
|
"else:\n",
|
|
" print('\\nЛучшая модель: НЕнормализованные данные')\n",
|
|
" ae_letter = ae_letter_raw\n",
|
|
" IRE_letter = IRE_letter_raw\n",
|
|
" IREth_letter = IREth_letter_raw\n",
|
|
" mse_letter = mse_letter_raw\n",
|
|
" test_letter_used = test_letter\n",
|
|
" print(f'Используем эту модель для дальнейших экспериментов')\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### 3) Построение графика ошибки реконструкции для Letter\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Построение графика ошибки реконструкции для выбранной модели\n",
|
|
"lib.ire_plot('training', IRE_letter, IREth_letter, 'Letter_AE')\n",
|
|
"print(f'Порог ошибки реконструкции: {IREth_letter:.6f}')\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### 4) Применение автокодировщика к тестовой выборке Letter\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Тестирование автокодировщика на тестовой выборке\n",
|
|
"# Используем выбранную модель (лучшую из нормализованных/ненормализованных)\n",
|
|
"predicted_labels_letter, ire_letter_test = lib.predict_ae(ae_letter, test_letter_used, IREth_letter)\n",
|
|
"\n",
|
|
"# Подсчет обнаруженных аномалий\n",
|
|
"num_anomalies = int(predicted_labels_letter.sum())\n",
|
|
"total_test = len(test_letter_used)\n",
|
|
"anomaly_percentage = (num_anomalies / total_test) * 100\n",
|
|
"\n",
|
|
"print(f'Обнаружено аномалий: {num_anomalies} из {total_test}')\n",
|
|
"print(f'Процент обнаруженных аномалий: {anomaly_percentage:.1f}%')\n",
|
|
"\n",
|
|
"lib.anomaly_detection_ae(predicted_labels_letter, ire_letter_test, IREth_letter)\n",
|
|
"lib.ire_plot('test', ire_letter_test, IREth_letter, 'Letter_AE')\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### 5) Результаты задания №2\n",
|
|
"\n",
|
|
"Результаты исследования занесены в таблицу:\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"print('Таблица 2 - Результаты задания №2')\n",
|
|
"print('=' * 100)\n",
|
|
"print(f'{\"Dataset\":<15} {\"Скрытых слоев\":<15} {\"Нейроны\":<40} {\"Эпох\":<10} {\"MSE_stop\":<12} {\"Порог IRE\":<12} {\"% аномалий\":<12}')\n",
|
|
"print('-' * 100)\n",
|
|
"print(f'Letter {11:<15} {\"32(вход) -> 100 -> 68 -> 48 -> 32 -> 24 -> 16 -> 8 -> 16 -> 24 -> 32 -> 48 -> 64 -> 100 -> 32(выход)\":<40} {20000:<10} {mse_letter:<12.6f} {IREth_letter:<12.6f} {anomaly_percentage:.1f}%')\n",
|
|
"print('=' * 100)\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Выводы\n",
|
|
"\n",
|
|
"### Требования к данным для обучения:\n",
|
|
"- Данные для обучения должны быть без аномалий, чтобы автокодировщик смог рассчитать верное пороговое значение\n",
|
|
"\n",
|
|
"### Требования к архитектуре автокодировщика:\n",
|
|
"- Архитектура должна постепенно сужаться к бутылочному горлышку, а затем постепенно возвращаться к исходным выходным размерам\n",
|
|
"- Для двумерных данных оптимальное количество скрытых слоев: 3-6\n",
|
|
"- Для многомерных данных (32 признака) оптимальное количество скрытых слоев: от 7-ми\n",
|
|
"\n",
|
|
"### Требования к количеству эпох обучения:\n",
|
|
"- Для простых данных (2D): 1000-3000 эпох\n",
|
|
"- Для сложных данных (многомерных): до 100000 эпох\n",
|
|
"\n",
|
|
"### Требования к ошибке MSE_stop:\n",
|
|
"- Для двумерных данных: оптимальная ошибка MSE-stop в районе 0.01\n",
|
|
"- Для многомерных данных: оптимальная ошибка MSE-stop в районе 0.1-0.01\n",
|
|
"\n",
|
|
"### Требования к порогу обнаружения аномалий:\n",
|
|
"- Для двумерных данных: значение порога в районе 0.4-2.5\n",
|
|
"- Для многомерных данных: значение порога не больше 1.6\n",
|
|
"\n",
|
|
"### Требования к характеристикам качества обучения EDCA:\n",
|
|
"- Значение Excess должно быть как можно ближе к 0\n",
|
|
"- Значение Deficit должно быть как можно ближе к 0 \n",
|
|
"- Значение Coating должно быть как можно ближе к 1 \n",
|
|
"- Значение Approx должно быть как можно ближе к 1\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": []
|
|
}
|
|
],
|
|
"metadata": {
|
|
"kernelspec": {
|
|
"display_name": "Python 3",
|
|
"language": "python",
|
|
"name": "python3"
|
|
},
|
|
"language_info": {
|
|
"codemirror_mode": {
|
|
"name": "ipython",
|
|
"version": 3
|
|
},
|
|
"file_extension": ".py",
|
|
"mimetype": "text/x-python",
|
|
"name": "python",
|
|
"nbconvert_exporter": "python",
|
|
"pygments_lexer": "ipython3",
|
|
"version": "3.11.9"
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 2
|
|
}
|