diff --git a/arutunyan_dmitry_lab_6/1.png b/arutunyan_dmitry_lab_6/1.png new file mode 100644 index 0000000..d2d6c4b Binary files /dev/null and b/arutunyan_dmitry_lab_6/1.png differ diff --git a/arutunyan_dmitry_lab_6/2.png b/arutunyan_dmitry_lab_6/2.png new file mode 100644 index 0000000..ad16223 Binary files /dev/null and b/arutunyan_dmitry_lab_6/2.png differ diff --git a/arutunyan_dmitry_lab_6/README.md b/arutunyan_dmitry_lab_6/README.md new file mode 100644 index 0000000..2176e11 --- /dev/null +++ b/arutunyan_dmitry_lab_6/README.md @@ -0,0 +1,110 @@ + +## Лабораторная работа 6. Вариант 4. +### Задание +Использовать нейронную сеть `MLPRegressor` для данных из курсовой работы. Самостоятельно сформулировав задачу. Интерпретировать результаты и оценить, насколько хорошо он подходит для решения сформулированной задачи. + +### Как запустить +Для запуска программы необходимо с помощью командной строки в корневой директории файлов прокета прописать: +``` +python main.py +``` +После этого в папке `static` сгенерируются график, по которому оценивается результат выполнения программы. + +### Используемые технологии +- Библиотека `numpy`, используемая для обработки массивов данных и вычислений +- Библиотека `pyplot`, используемая для построения графиков. +- Библиотека `pandas`, используемая для работы с данными для анализа scv формата. +- Библиотека `sklearn` - большой набор функционала для анализа данных. Из неё были использованы инструменты: + - `train_test_split` - разделитель данных на обучающиую и тестовую выборки + - `metrics` - набор инструменов для оценки моделей + - `MLPRegressor` - инструмент работы с моделью "Многослойный перцептрон для задачи регрессии" + +`MLPRegressor` - это тип искусственной нейронной сети, состоящей из нескольких слоев нейронов, включая входной слой, скрытые слои и выходной слой. +Этот класс позволяет создавать и обучать MLP-модель для предсказания непрерывных числовых значений. + +### Описание работы +#### Описание набора данных +Набор данных - набор для определения возможности наличия ССЗ заболеваний у челоека + +Названия столбцов набора данных и их описание: + + * HeartDisease - Имеет ли человек ССЗ (No / Yes), + * BMI - Индекс массы тела человека (float), + * Smoking - Выкурил ли человек хотя бы 5 пачек сигарет за всю жизнь (No / Yes), + * AlcoholDrinking - Сильно ли человек употребляет алкоголь (No / Yes), + * Stroke - Был ли у человека инсульт (No / Yes), + * PhysicalHealth - Сколько дней за последний месяц человек чувствовал себя плохо (0-30), + * MentalHealth - Сколько дней за последний месяц человек чувствовал себя удручённо (0-30), + * DiffWalking - Ииспытывает ли человек трудности при ходьбе (No / Yes), + * Sex - Пол (female, male), + * AgeCategory - Возрастная категория (18-24, 25-29, 30-34, 35-39, 40-44, 45-49, 50-54, 55-59, 60-64, 65-69, 70-74, 75-79, 80 or older), + * Race - Национальная принадлежность человека (White, Black, Hispanic, American Indian/Alaskan Native, Asian, Other), + * Diabetic - Был ли у человека диабет (No / Yes), + * PhysicalActivity - Занимался ли человек спротом за последний месяц (No / Yes), + * GenHealth - Общее самочувствие человека (Excellent, Very good, Good, Fair, Poor), + * SleepTime - Сколько человек в среднем спит за 24 часа (0-24), + * Asthma - Была ли у человека астма (No / Yes), + * KidneyDisease - Было ли у человека заболевание почек (No / Yes), + * SkinCancer - Был ли у человека рак кожи (No / Yes). + +Ссылка на страницу набора на kuggle: [Indicators of Heart Disease](https://www.kaggle.com/datasets/kamilpytlak/personal-key-indicators-of-heart-disease/data) + +#### Формулировка задачи +Поскольку модель `MLPRegressor` используется для решения задачи регресси, то попробуем на ней предсказать поведение параметров при обучении на всех признаках, варьируя конфигурации модели. Сформулируем задачу: +> "Решить задачу предсказания с помощью нейронной сети, обученной на всех признаках при различных конфигурациях. Сравнить результаты работы моделей" + +#### Решение задачи предсказания +Из csv файла выргузим набор данных, выделим параметр для предсказания - (столбец `HeartDisease`), и его признаки - все остальные столбцы. Разделим данные на обучающую и тестовые выборки, при условии, что 99.9% данных - для обучения, а остальные для тестов: +```python +х, y = [df.drop("HeartDisease", axis=1).values, df["HeartDisease"].values] +x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.001, random_state=42) +``` +Создадим класс нейронной сети и определим варьируемые конфигурации. + +`hidden_layer_sizes ` - параметр, принимающий на вход количество скрытых слоёв нейронной сети и количество нейронов в каждом слое. Для определения его наилучшего значения необходимо взять минимальное количество слоёв и нейронов в слое и постепенно увеличивать его, до тех пор, пока качество модели не перестанет улучшаться или не будет достаточным. +> **Note** +> +> Экспериментально для нейронной сети `MLPRegressor` было выявленно наилучшее значение равное 100 слоям нейронной сети по 50 нейронов в каждой. Для прелоставления данных процесс оказался очень длительным, поэтому будет указан только наилучший результат. + +`activation` - функция активации. В классе представлена 4мя решениями: +- `identity` - функция `f(x) = x`, абсолютно линейная идентичная функция для приведения работы нейронной сети ближе к модели линейной регрессии, +- `logistic` - логистическая сигмовидная функция вида `f(x) = 1 / (1 + exp(-x))`, +- `tanh` - гиперболическая функция тангенса `f(x) = tanh(x)`, +- `relu` - функция выпрямленной линейной единицы измерения `f(x) = max(0, x)`, проверяет больше ли х нуля (используется чаще всего). + +`solver` - метод оптимизации весов. Существует в 3х вариациях: +- `Bfgs` - оптимизатор из семейства квазиньютоновских методов, +> **Warning** +> +> Оптимизатор из семейства квазиньютоновских методов показал себя как очень жадный по времени выполнения алгоритм при этом использующий большие коэфициенты весов, что приводило к едиичным, но слишком большим погрешностям на данных. Поэтому в эксперименте варьирования он не принимал участия. + +- `sgd` - метод стозастического градиентного спуска (классика), +- `adam` - оптимизированный метод стозастического градиентного спуска Кингмы, Дидерика и Джимми Барнсома. + +```python +mlp = MLPRegressor(hidden_layer_sizes=(100, 50), activation='relu', solver='adam', random_state=42) +mlp.fit(x_train, y_train) +y_predict = mlp.predict(x_test) +err = pred_errors(y_predict, y_test) +``` +Проведём эксперимент варьирования конфигураций, посчитаем ошибки предсказания и выберем наилучшую нейронную сеть. + +#### Эксперимент варьирования +Рассмотрим различные функции активации. + +Графики решения задачи предсказания на разных функциях активации: + +![](1.png "") + +Теперь для выбранной функции подберём лучший метод оптимизации весов. + +Грфики решения задачи предсказания на разных методах оптимизации весов: + +![](2.png "") + +### Вывод +Согласно графиком, наилучшие результаты показала нейронаая сеть с функцией активации гиперболического тангенса `tanh` и методом оптимизации весов путём оптимизированного стозастического градиентного спуска Кингмы, Дидерика и Джимми Барнсома `adam`. + +В целом нейронная сеть справилась неудовлетворительно с задачей предсказания, показав хоть и небольшую среднеквадратическую ошибку в 0.25, но очень низкий коэфициент детерминации в 0.23 максимально. + +Это значит, что теоретически модель может предсказать результат по признакам, однако понимания зависимостей результата от последних у неё мало. \ No newline at end of file diff --git a/arutunyan_dmitry_lab_6/main.py b/arutunyan_dmitry_lab_6/main.py new file mode 100644 index 0000000..0543cd0 --- /dev/null +++ b/arutunyan_dmitry_lab_6/main.py @@ -0,0 +1,46 @@ +import pandas as pd +import numpy as np +from matplotlib import pyplot as plt +from sklearn import metrics +from sklearn.model_selection import train_test_split +from sklearn.neural_network import MLPRegressor + +filein = "P:\\ULSTU\\ИИС\\Datasets\\heart_2020_norm.csv" + + +# Метод обучения нейронной сети +def reg_neural_net(): + df = pd.read_csv(filein, sep=',') + x, y = [df.drop("HeartDisease", axis=1).values, + df["HeartDisease"].values] + + x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.001, random_state=42) + + mlp = MLPRegressor(hidden_layer_sizes=(100, 50), activation='tanh', solver='adam', random_state=15000) + mlp.fit(x_train, y_train) + y_predict = mlp.predict(x_test) + err = pred_errors(y_predict, y_test) + make_plots(y_test, y_predict, err[0], err[1], "Нейронная сеть") + + +# Метод рассчёта ошибок +def pred_errors(y_predict, y_test): + mid_square = np.round(np.sqrt(metrics.mean_squared_error(y_test, y_predict)),3) # Рассчёт среднеквадратичной ошибки модели + det_kp = np.round(metrics.r2_score(y_test, y_predict), 2) # Рассчёт коэфициента детерминации модели + return mid_square, det_kp + + +# Метод отрисовки графиков +def make_plots(y_test, y_predict, mid_sqrt, det_kp, title): + plt.plot(y_test, c="red", label="\"y\" исходная") # Создание графика исходной функции + plt.plot(y_predict, c="green", label="\"y\" предсказанная \n" + "Ср^2 = " + str(mid_sqrt) + "\n" + "Кд = " + str(det_kp)) # Создание графика предсказанной функции + plt.legend(loc='lower left') + plt.title(title) + plt.savefig('static/' + title + '.png') + plt.close() + + +if __name__ == '__main__': + reg_neural_net()