IIS_2023_1/arutunyan_dmitry_lab_4/README.md

131 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

## Лабораторная работа 4. Вариант 4.
### Задание
Использовать метод кластеризации по варианту для данных из курсовой работы. Самостоятельно сформулировав задачу. Интерпретировать результаты и оценить, насколько хорошо он подходит для
решения сформулированной задачи.
Алгоритм кластеризации:
- Пространственная кластеризация данных с шумом на основе плотности `DBSCAN`.
### Как запустить
Для запуска программы необходимо с помощью командной строки в корневой директории файлов прокета прописать:
```
python main.py
```
После этого в папке `static` сгенерируются 3 графика, по которым оценивается результат выполнения программы.
### Используемые технологии
- Библиотека `numpy`, используемая для обработки массивов данных и вычислений
- Библиотека `pyplot`, используемая для построения графиков.
- Библиотека `pandas`, используемая для работы с данными для анализа scv формата.
- Библиотека `sklearn` - большой набор функционала для анализа данных. Из неё были использованы инструменты:
- `DBSCAN` - инструмент работы с моделью "Пространственная кластеризация данных с шумом на основе плотности"
- `metrics` - набор инструменов для оценки моделей
- `LinearRegression` - инструмент работы с моделью "Линейная регрессия"
`DBSCAN` - это алгоритм кластеризации, который используется для кластеризации данных на основе плотности, что позволяет обнаруживать кластеры произвольной формы и обнаруживать выбросы (шум). `DBSCAN` может быть полезным при предварительной обработке данных перед задачей предсказания:
- Удаление выбросов (шума): `DBSCAN` может помочь в идентификации и удалении выбросов из данных.
- Генерация новых признаков: `DBSCAN` может быть использован для генерации новых признаков на основе кластеров.
### Описание работы
#### Описание набора данных
Набор данных - набор для определения возможности наличия ССЗ заболеваний у челоека
Названия столбцов набора данных и их описание:
* 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)
#### Формулировка задачи
Согласно прописанным в литературе варантам использования, `DBSCAN` может помочь в идентификации и удалении выбросов из данных, а также может быть использован для генерации новых признаков на основе кластеров. Исходя из этого сформулируем задачу:
> "В наборе данных с помощью `DBSCAN` определить и исключить строки содержащие шум, а также сгенерировать новый признак для данных на сонове кластеров. Проверить результат через решение задачи предсказания моделью линейной регрессии на исходных и модифицированных данных"
#### Использование алгоритма `DBSCAN`
Чтобы эффективно использовать алгоритм `DBSCAN` необходимо правильно определить два параметра: `eps` - радиус окрестности вокруг каждой точки и `min_samples` - минимальное количество точек, которые должны находиться в окрестности, чтобы рассматривать ее как ядро кластера.
Начнём с получения датасета из csv файла и признаков кластеризации:
```python
df = pd.read_csv(filein, sep=',').iloc[0:10000]
x = df.drop("HeartDisease", axis=1)
```
> **Warning**
>
> Алгоритм `DBSCAN` - очень жадная по памяти программа. В худшем случае алгоритм может занимать Q(N^2) оперативной памяти устройства, поэтому исследование получится провести лишь на частичной выборке в 10000 строк данных.
Для нахождения оптимального значения параметра `eps` воспользуемся методом рассчёта средней плотности данных. Для этого необходимо найти суммы максимальных и минимальных значений каждого признака и взять среднее арифметическое этих двух значений:
```python
eps_opt = (x.max().values.mean() + x.min().values.mean()) / 2
```
Оптимальное значение параметра `min_samples` будем искать эмпирически. Условимся, что нам будет достаточно разделить высе данные на 6 кластеров (пусть это будут степени риска возникновения ССЗ), но нам нельзя терять в качестве выбросов более 10% данных. Тогда мы будем варьировать параметр `min_samples` от 1 до кол-ва всех данных и закончим эксперимент при выполнении одного из указанных условий:
```python
developed_data = []
for i in range(len(x)):
if i == 0:
continue
dbscan = DBSCAN(eps=eps_opt, min_samples=i)
clusters = dbscan.fit_predict(x.values)
if len(set(clusters)) <= 7:
developed_data = clusters
break
if list(clusters).count(-1) / len(clusters) >= 0.1:
developed_data = clusters
break
```
Таким образом в массиве `developed_data` мы получим значение кластеров для каждй строки датасета. Добавим её как дополнительный признак.
График кластеров для значений датасета:
![](dbscan.png "")
#### Решение задачи предсказания
Создадим два обучающих модуля. В 1м удалим все строки с кластером `-1`, что указывает на то, что они шум и воспользуемся дополнительным признаком `DBSCAN`:
```python
df_mod = df.loc[df["DBSCAN"] != -1]
x_train_mod = df_mod.drop("HeartDisease", axis=1).iloc[0:round(len(df) / 100 * 99)]
y_train_mod = df_mod["HeartDisease"].iloc[0:round(len(df) / 100 * 99)]
x_test_mod = df_mod.drop("HeartDisease", axis=1).iloc[round(len(df) / 100 * 99):len(df)]
y_test_mod = df_mod["HeartDisease"].iloc[round(len(df) / 100 * 99):len(df)]
```
Во 2м модуле для разделения на выборки оставим исходные данные:
```python
x_train = df.drop(["HeartDisease", "DBSCAN"], axis=1).iloc[0:round(len(df) / 100 * 99)]
y_train = df["HeartDisease"].iloc[0:round(len(df) / 100 * 99)]
x_test = df.drop(["HeartDisease", "DBSCAN"], axis=1).iloc[round(len(df) / 100 * 99):len(df)]
y_test = df["HeartDisease"].iloc[round(len(df) / 100 * 99):len(df)]
```
Создаим две модели регрессии и на каждой решим задачу предсказания. Вычислим ошибки и построим графики.
График решения задачи предсказания на модифицированных данных:
![](regdbscan.png "")
График решения задачи предсказания на исходных данных:
![](reg.png "")
### Вывод
Согласно графиком, модель, обученная на исходных данных показала результат лучше, чем модель, обученная на модифицированных данных. Получается, что на данном наборе, используя алгоритм `DBSCAN`, мы не только невероятно увеличиваем затратность памяти на обучение модели, но и отрицательно влияем на результат её работы. Это означает, что использование алгоритма на таком наборе данных абсолютно нецелесообразно.
Связанно это может быть с большим количеством бинарных признаков в данных. В таких случаях задачи кластеризации решаются сравнительно хуже.