Merge pull request 'arutunyan_dmitry_lab_3 is ready' (#54) from arutunyan_dmitry_lab_3 into main
Reviewed-on: http://student.git.athene.tech/Alexey/IIS_2023_1/pulls/54
This commit is contained in:
commit
c20695af79
BIN
arutunyan_dmitry_lab_3/FullParam.png
Normal file
BIN
arutunyan_dmitry_lab_3/FullParam.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 154 KiB |
BIN
arutunyan_dmitry_lab_3/ImpParam.png
Normal file
BIN
arutunyan_dmitry_lab_3/ImpParam.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 178 KiB |
170
arutunyan_dmitry_lab_3/README.md
Normal file
170
arutunyan_dmitry_lab_3/README.md
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
|
||||||
|
## Лабораторная работа 3. Вариант 4.
|
||||||
|
### Задание
|
||||||
|
Выполнить ранжирование признаков и решить с помощью библиотечной реализации дерева решений
|
||||||
|
задачу классификации на 99% данных из курсовой работы. Проверить
|
||||||
|
работу модели на оставшемся проценте, сделать вывод.
|
||||||
|
|
||||||
|
Модель:
|
||||||
|
|
||||||
|
- Дерево решений `DecisionTreeClassifier`.
|
||||||
|
|
||||||
|
### Как запустить
|
||||||
|
Для запуска программы необходимо с помощью командной строки в корневой директории файлов прокета прописать:
|
||||||
|
```
|
||||||
|
python main.py
|
||||||
|
```
|
||||||
|
После этого в папке `static` сгенерируются 2 графика, по которым оценивается результат выполнения программы.
|
||||||
|
|
||||||
|
### Используемые технологии
|
||||||
|
- Библиотека `numpy`, используемая для обработки массивов данных и вычислений
|
||||||
|
- Библиотека `pyplot`, используемая для построения графиков.
|
||||||
|
- Библиотека `pandas`, используемая для работы с данными для анализа scv формата.
|
||||||
|
- Библиотека `sklearn` - большой набор функционала для анализа данных. Из неё были использованы инструменты:
|
||||||
|
- `DecisionTreeClassifier` - инструмент работы с моделью "Дерево решений"
|
||||||
|
- `metrics` - набор инструменов для оценки моделей
|
||||||
|
- `MinMaxScaler` - инструмент масштабирования значений в заданный диапазон
|
||||||
|
|
||||||
|
### Описание работы
|
||||||
|
#### Описание набора данных
|
||||||
|
Набор данных - набор для определения возможности наличия ССЗ заболеваний у челоека
|
||||||
|
|
||||||
|
Названия столбцов набора данных и их описание:
|
||||||
|
|
||||||
|
* 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)
|
||||||
|
|
||||||
|
#### Оцифровка и нормализация данных
|
||||||
|
Для нормальной работы с данными, необходимо исключить из них все нечисловые значения. После этого, представить все строковые значения параметров как числовые и очистить датасет от "мусора". Для удаления нечисловых значений воспользуемся функцией `.dropna()`. Мы исключаем строки с нечисловыми значениями, поскольку данные предварительно были очищены (указано в описании датасета) и строк данных достаточно с избытком для обучение модели: `400.000`.
|
||||||
|
|
||||||
|
После этого, переведём все строковые значения данных в числовые методами прямой оцифровки, разделения на группы, ранжирования.
|
||||||
|
|
||||||
|
Процесс оцифровки данных столбцов со строковыми значениями:
|
||||||
|
|
||||||
|
- Имеет ли человек ССЗ (0 / 1)
|
||||||
|
- Выкурил ли человек хотя бы 5 пачек сигарет за всю жизнь (0 / 1)
|
||||||
|
- Сильно ли человек употребляет алкоголь (0 / 1)
|
||||||
|
- Был ли у человека инсульт (0 / 1)
|
||||||
|
- Ииспытывает ли человек трудности при ходьбе (0 / 1)
|
||||||
|
- Пол (Ж - 0 / М - 1)
|
||||||
|
- Возрастная категория (средний возраст каждого диапазона)
|
||||||
|
- Национальная принадлежность человека
|
||||||
|
- White - Европиойды - 0
|
||||||
|
- Black - Негройды - 1
|
||||||
|
- Hispanic - Испанцы - 2
|
||||||
|
- American Indian/Alaskan Native - Индусы - 3
|
||||||
|
- Asian - Азиаты - 4
|
||||||
|
- Other - Другие - 5
|
||||||
|
- Был ли у человека диабет (0 / 1)
|
||||||
|
- Занимался ли человек спротом за последний месяц (0 / 1)
|
||||||
|
- Общее самочувствие человека
|
||||||
|
- Excellent - Отлично - 4
|
||||||
|
- Very good - Очень хорошо - 3
|
||||||
|
- Good - Хорошо - 2
|
||||||
|
- Fair - Нормально - 1
|
||||||
|
- "Poor" / "Other..." - Плохое или другое - 0
|
||||||
|
- Была ли у человека астма (0 / 1)
|
||||||
|
- Было ли у человека заболевание почек (0 /1)
|
||||||
|
- Был ли у человека рак кожи (0 / 1)
|
||||||
|
|
||||||
|
После оцифровки значений необходимо избавиться от строк с возможными остаточнымии данными ("мусором"). Для этого переведём автоматически все значения датасета в числовые функцией `to_numeric` и непереводимые отметим как `NaN` (параметр `errors='coerce'`). После снова сотрём строки содержащие нечисловые значения методом `.dropna()` и сохраним нормализованный датасет в новый csv файл:
|
||||||
|
```python
|
||||||
|
df = df.applymap(pd.to_numeric, errors='coerce').dropna()
|
||||||
|
df.to_csv(fileout, index=False)
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Выявление значимых параметров
|
||||||
|
В выбранном датасете параметром предсказания `y` выступает столбец данных `HeartDisease`. Остальные столбцы считаются параметрами для решения задачи предсказания `x`, которые необходимо проранжировать по важности. Чтобы разделить выборку данных на обучаемую и тестовую, воспользуемся функцией `.iloc`.
|
||||||
|
```python
|
||||||
|
x_train = df[["BMI", "Smoking", "AlcoholDrinking", "Stroke", "PhysicalHealth",
|
||||||
|
"MentalHealth", "DiffWalking", "Sex", "AgeCategory", "Race", "Diabetic",
|
||||||
|
"PhysicalActivity", "GenHealth", "SleepTime", "Asthma", "KidneyDisease", "SkinCancer"]].iloc[
|
||||||
|
0:round(len(df) / 100 * 99)]
|
||||||
|
y_train = df["HeartDisease"].iloc[0:round(len(df) / 100 * 99)]
|
||||||
|
x_test = df[["BMI", "Smoking", "AlcoholDrinking", "Stroke", "PhysicalHealth",
|
||||||
|
"MentalHealth", "DiffWalking", "Sex", "AgeCategory", "Race", "Diabetic",
|
||||||
|
"PhysicalActivity", "GenHealth", "SleepTime", "Asthma", "KidneyDisease", "SkinCancer"]].iloc[
|
||||||
|
round(len(df) / 100 * 99):len(df)]
|
||||||
|
y_test = df["HeartDisease"].iloc[round(len(df) / 100 * 99):len(df)]
|
||||||
|
```
|
||||||
|
Где `round(len(df) / 100 * 99)` - 99ти процентная строка в датасете.
|
||||||
|
|
||||||
|
Теперь, обучим модель на данных `x_train` и `y_train` и получим значимость каждого признака в модели с помощью метода `.feature_importances_`. После отмасштабируем значения важности признаков.
|
||||||
|
```python
|
||||||
|
ranks = np.abs(dtc.feature_importances_)
|
||||||
|
minmax = MinMaxScaler()
|
||||||
|
ranks = minmax.fit_transform(np.array(ranks).reshape(len(x_train.columns), 1)).ravel()
|
||||||
|
ranks = map(lambda x: round(x, 2), ranks)
|
||||||
|
ranks = dict(zip(x_train.columns, ranks))
|
||||||
|
ranks = dict(sorted(ranks.items(), key=lambda x: x[1], reverse=True))
|
||||||
|
```
|
||||||
|
|
||||||
|
Чтобы отсеять значимые параметры от незначимых, условимся, что параметры, с оценкой значимости меньше `0.05` будут считаться незначимыми. Выведем список параметров с пометками:
|
||||||
|
```
|
||||||
|
X ranging results:
|
||||||
|
* BMI: 1.0 - Approved
|
||||||
|
* SleepTime: 0.26 - Approved
|
||||||
|
* PhysicalHealth: 0.18 - Approved
|
||||||
|
* GenHealth: 0.16 - Approved
|
||||||
|
* MentalHealth: 0.15 - Approved
|
||||||
|
* AgeCategory: 0.14 - Approved
|
||||||
|
* Race: 0.07 - Approved
|
||||||
|
* PhysicalActivity: 0.06 - Approved
|
||||||
|
* Stroke: 0.04 - Eliminated
|
||||||
|
* Smoking: 0.03 - Eliminated
|
||||||
|
* Asthma: 0.03 - Eliminated
|
||||||
|
* SkinCancer: 0.03 - Eliminated
|
||||||
|
* DiffWalking: 0.02 - Eliminated
|
||||||
|
* Sex: 0.02 - Eliminated
|
||||||
|
* AlcoholDrinking: 0.0 - Eliminated
|
||||||
|
* Diabetic: 0.0 - Eliminated
|
||||||
|
* KidneyDisease: 0.0 - Eliminated
|
||||||
|
```
|
||||||
|
|
||||||
|
Где `Approved` - параметр значим и будет использоваться в предсказании, а `Eliminated` - параметр незначим и будет исключён.
|
||||||
|
|
||||||
|
#### Решение задачи кластеризации на полном наборе признаков
|
||||||
|
Чтобы решить задачу кластеризации моделью `DecisionTreeClassifier`, воспользуемся методом `.predict()`. Оценку качества решения и графики будем строить теми же методами, что в 1й лабораторной работе.
|
||||||
|
|
||||||
|
График решения задачи классификации на полном наборе признаков:
|
||||||
|
|
||||||
|
![](FullParam.png "")
|
||||||
|
|
||||||
|
#### Решение задачи кластеризации, используя только значимые признаки
|
||||||
|
Согласно предыдущему пункту, значимыми признаками модели были выявлены:
|
||||||
|
* BMI
|
||||||
|
* SleepTime
|
||||||
|
* PhysicalHealth
|
||||||
|
* GenHealth
|
||||||
|
* MentalHealth
|
||||||
|
* AgeCategory
|
||||||
|
* Race
|
||||||
|
* PhysicalActivity
|
||||||
|
Обучим модель только с их использованием, решим задачу классификации и построим график.
|
||||||
|
|
||||||
|
График решения задачи классификации, используя только значимые признаки:
|
||||||
|
|
||||||
|
![](ImpParam.png "")
|
||||||
|
|
||||||
|
### Вывод
|
||||||
|
Согласно среднеквадратической ошибке и коэфициенту детерминации, модель, обученная только на значимых признаков отработала точнее, чем модель, обученная на полном наборе признаков. Это значит, что ранжирование было проведено верно и дало полезный результат. О логической оценке исключённых данных сказать ничего не получится, поскольку действительную зависимость результата от параметров значет только медицинский эксперт.
|
||||||
|
|
||||||
|
Исходя их общих значений точности, обе модели показали хорошие результаты и могут быть применимы к решению задачи классификации на данном наборе данных.
|
221
arutunyan_dmitry_lab_3/main.py
Normal file
221
arutunyan_dmitry_lab_3/main.py
Normal file
@ -0,0 +1,221 @@
|
|||||||
|
import pandas as pd
|
||||||
|
import numpy as np
|
||||||
|
from matplotlib import pyplot as plt
|
||||||
|
from sklearn import metrics
|
||||||
|
from sklearn.preprocessing import MinMaxScaler
|
||||||
|
from sklearn.tree import DecisionTreeClassifier
|
||||||
|
|
||||||
|
'''
|
||||||
|
Названия столбцов набора данных и их описание:
|
||||||
|
|
||||||
|
* 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).
|
||||||
|
'''
|
||||||
|
|
||||||
|
|
||||||
|
# Метод оцифровки и нормализации данных
|
||||||
|
def normalisation(filename):
|
||||||
|
fileout = "P:\\ULSTU\\ИИС\\Datasets\\heart_2020_norm.csv"
|
||||||
|
df = pd.read_csv(filename, sep=',').dropna() # Считываем данные с csv файла и удаляем строки, содержащие NaN
|
||||||
|
|
||||||
|
for index, row in df.iterrows():
|
||||||
|
if index % 10000 == 0:
|
||||||
|
print("normalisation running . . . " + str(round((index / len(df) * 100), 2)) +'%')
|
||||||
|
if "Yes" in row["HeartDisease"]: # Имеет ли человек ССЗ (0 / 1)
|
||||||
|
df.at[index, "HeartDisease"] = 1
|
||||||
|
else:
|
||||||
|
df.at[index, "HeartDisease"] = 0
|
||||||
|
if "Yes" in row["Smoking"]: # Выкурил ли человек хотя бы 5 пачек сигарет за всю жизнь (0 / 1)
|
||||||
|
df.at[index, "Smoking"] = 1
|
||||||
|
else:
|
||||||
|
df.at[index, "Smoking"] = 0
|
||||||
|
if "Yes" in row["AlcoholDrinking"]: # Сильно ли человек употребляет алкоголь (0 / 1)
|
||||||
|
df.at[index, "AlcoholDrinking"] = 1
|
||||||
|
else:
|
||||||
|
df.at[index, "AlcoholDrinking"] = 0
|
||||||
|
if "Yes" in row["Stroke"]: # Был ли у человека инсульт (0 / 1)
|
||||||
|
df.at[index, "Stroke"] = 1
|
||||||
|
else:
|
||||||
|
df.at[index, "Stroke"] = 0
|
||||||
|
if "Yes" in row["DiffWalking"]: # Ииспытывает ли человек трудности при ходьбе (0 / 1)
|
||||||
|
df.at[index, "DiffWalking"] = 1
|
||||||
|
else:
|
||||||
|
df.at[index, "DiffWalking"] = 0
|
||||||
|
if "Female" in row["Sex"]: # Пол (Ж - 0 / М - 1)
|
||||||
|
df.at[index, "Sex"] = 0
|
||||||
|
else:
|
||||||
|
df.at[index, "Sex"] = 1
|
||||||
|
if "18-24" in row["AgeCategory"]: # Возрастная категория (средний возраст каждого диапазона)
|
||||||
|
df.at[index, "AgeCategory"] = (18 + 24) / 2
|
||||||
|
elif "25-29" in row["AgeCategory"]:
|
||||||
|
df.at[index, "AgeCategory"] = (25 + 29) / 2
|
||||||
|
elif "30-34" in row["AgeCategory"]:
|
||||||
|
df.at[index, "AgeCategory"] = (30 + 34) / 2
|
||||||
|
elif "35-39" in row["AgeCategory"]:
|
||||||
|
df.at[index, "AgeCategory"] = (35 + 39) / 2
|
||||||
|
elif "40-44" in row["AgeCategory"]:
|
||||||
|
df.at[index, "AgeCategory"] = (40 + 44) / 2
|
||||||
|
elif "45-49" in row["AgeCategory"]:
|
||||||
|
df.at[index, "AgeCategory"] = (45 + 49) / 2
|
||||||
|
elif "50-54" in row["AgeCategory"]:
|
||||||
|
df.at[index, "AgeCategory"] = (50 + 54) / 2
|
||||||
|
elif "55-59" in row["AgeCategory"]:
|
||||||
|
df.at[index, "AgeCategory"] = (55 + 59) / 2
|
||||||
|
elif "60-64" in row["AgeCategory"]:
|
||||||
|
df.at[index, "AgeCategory"] = (60 + 64) / 2
|
||||||
|
elif "65-69" in row["AgeCategory"]:
|
||||||
|
df.at[index, "AgeCategory"] = (65 + 69) / 2
|
||||||
|
elif "70-74" in row["AgeCategory"]:
|
||||||
|
df.at[index, "AgeCategory"] = (70 + 74) / 2
|
||||||
|
elif "75-79" in row["AgeCategory"]:
|
||||||
|
df.at[index, "AgeCategory"] = (75 + 79) / 2
|
||||||
|
else:
|
||||||
|
df.at[index, "AgeCategory"] = (25 + 29) / 2
|
||||||
|
if "White" in row["Race"]: # Национальная принадлежность человека
|
||||||
|
df.at[index, "Race"] = 0 # White - Европиойды - 0
|
||||||
|
elif "Black" in row["Race"]: # Black - Негройды - 1
|
||||||
|
df.at[index, "Race"] = 1 # Hispanic - Испанцы - 2
|
||||||
|
elif "Hispanic" in row["Race"]: # American Indian/Alaskan Native - Индусы - 3
|
||||||
|
df.at[index, "Race"] = 2 # Asian - Азиаты - 4
|
||||||
|
elif "American Indian/Alaskan Native" in row["Race"]: # Other - Другие - 5
|
||||||
|
df.at[index, "Race"] = 3
|
||||||
|
elif "Asian" in row["Race"]:
|
||||||
|
df.at[index, "Race"] = 4
|
||||||
|
else:
|
||||||
|
df.at[index, "Race"] = 5
|
||||||
|
if "Yes" in row["Diabetic"]: # Был ли у человека диабет (0 / 1)
|
||||||
|
df.at[index, "Diabetic"] = 1
|
||||||
|
else:
|
||||||
|
df.at[index, "Diabetic"] = 0
|
||||||
|
if "Yes" in row["PhysicalActivity"]: # Занимался ли человек спротом за последний месяц (0 / 1)
|
||||||
|
df.at[index, "PhysicalActivity"] = 1
|
||||||
|
else:
|
||||||
|
df.at[index, "PhysicalActivity"] = 0
|
||||||
|
if "Excellent" in row["GenHealth"]: # Общее самочувствие человека
|
||||||
|
df.at[index, "GenHealth"] = 4 # Excellent - Отлично - 4
|
||||||
|
elif "Very good" in row["GenHealth"]: # Very good - Очень хорошо - 3
|
||||||
|
df.at[index, "GenHealth"] = 3 # Good - Хорошо - 2
|
||||||
|
elif "Good" in row["GenHealth"]: # Fair - Нормально - 1
|
||||||
|
df.at[index, "GenHealth"] = 2 # "Poor" / "Other..." - Плохое или другое - 0
|
||||||
|
elif "Fair" in row["GenHealth"]:
|
||||||
|
df.at[index, "GenHealth"] = 1
|
||||||
|
else:
|
||||||
|
df.at[index, "GenHealth"] = 0
|
||||||
|
if "Yes" in row["Asthma"]: # Была ли у человека астма (0 / 1)
|
||||||
|
df.at[index, "Asthma"] = 1
|
||||||
|
else:
|
||||||
|
df.at[index, "Asthma"] = 0
|
||||||
|
if "Yes" in row["KidneyDisease"]: # Было ли у человека заболевание почек (0 /1)
|
||||||
|
df.at[index, "KidneyDisease"] = 1
|
||||||
|
else:
|
||||||
|
df.at[index, "KidneyDisease"] = 0
|
||||||
|
if "Yes" in row["SkinCancer"]: # Был ли у человека рак кожи (0 / 1)
|
||||||
|
df.at[index, "SkinCancer"] = 1
|
||||||
|
else:
|
||||||
|
df.at[index, "SkinCancer"] = 0
|
||||||
|
|
||||||
|
df = df.applymap(pd.to_numeric, errors='coerce').dropna() # Гарантированно убираем все нечисловые значения из датасета
|
||||||
|
df.to_csv(fileout, index=False) # Сохраняем нормализованный датасет для дальнейшей работы
|
||||||
|
return fileout
|
||||||
|
|
||||||
|
|
||||||
|
# Метод ранжирования параметров по степени важности
|
||||||
|
def param_range(filename, elim_kp):
|
||||||
|
df = pd.read_csv(filename, sep=',') # Считываем нормализованные данные и разделяем их на выборки
|
||||||
|
x_train = df[["BMI", "Smoking", "AlcoholDrinking", "Stroke", "PhysicalHealth",
|
||||||
|
"MentalHealth", "DiffWalking", "Sex", "AgeCategory", "Race", "Diabetic",
|
||||||
|
"PhysicalActivity", "GenHealth", "SleepTime", "Asthma", "KidneyDisease", "SkinCancer"]].iloc[
|
||||||
|
0:round(len(df) / 100 * 99)]
|
||||||
|
y_train = df["HeartDisease"].iloc[0:round(len(df) / 100 * 99)]
|
||||||
|
x_test = df[["BMI", "Smoking", "AlcoholDrinking", "Stroke", "PhysicalHealth",
|
||||||
|
"MentalHealth", "DiffWalking", "Sex", "AgeCategory", "Race", "Diabetic",
|
||||||
|
"PhysicalActivity", "GenHealth", "SleepTime", "Asthma", "KidneyDisease", "SkinCancer"]].iloc[
|
||||||
|
round(len(df) / 100 * 99):len(df)]
|
||||||
|
y_test = df["HeartDisease"].iloc[round(len(df) / 100 * 99):len(df)]
|
||||||
|
|
||||||
|
dtc = DecisionTreeClassifier(random_state=241) # Создаём модель дерева решений
|
||||||
|
dtc.fit(x_train.values, y_train.values) # Обучаем модель на данных
|
||||||
|
y_predict = dtc.predict(x_test.values) # Решаем задачу классификации на полном наборе признаков
|
||||||
|
err = pred_errors(y_predict, y_test.values) # Рассчитываем ошибки предсказания
|
||||||
|
make_plots(y_test.values, y_predict, err[0], err[1], "Полный набор данных") # Строим графики
|
||||||
|
|
||||||
|
ranks = np.abs(dtc.feature_importances_) # Получаем значимость каждого признака в модели
|
||||||
|
minmax = MinMaxScaler() # Шкалируем и нормализуем значимость
|
||||||
|
ranks = minmax.fit_transform(np.array(ranks).reshape(len(x_train.columns), 1)).ravel()
|
||||||
|
ranks = map(lambda x: round(x, 2), ranks)
|
||||||
|
ranks = dict(zip(x_train.columns, ranks))
|
||||||
|
ranks = dict(sorted(ranks.items(), key=lambda x: x[1], reverse=True)) # Сортируем оценки по максимуму и записываем в словарь
|
||||||
|
|
||||||
|
print("X ranging results: \n")
|
||||||
|
del_keys = [] # Исключаем параметры, важность которых меньше elim_kp
|
||||||
|
for key, value in ranks.items():
|
||||||
|
if value >= elim_kp:
|
||||||
|
print(" * " + key + ": " + str(value) + " - Approved")
|
||||||
|
else:
|
||||||
|
print(" * " + key + ": " + str(value) + " - Eliminated")
|
||||||
|
del_keys.append(key)
|
||||||
|
|
||||||
|
for key in del_keys:
|
||||||
|
ranks.pop(key)
|
||||||
|
|
||||||
|
return filename, ranks.keys()
|
||||||
|
|
||||||
|
|
||||||
|
# Метод решения задачи классификации, основанный только на значимых параметрах
|
||||||
|
def most_valuable_prediction(params):
|
||||||
|
filename = params[0]
|
||||||
|
val_p = params[1]
|
||||||
|
df = pd.read_csv(filename, sep=',')
|
||||||
|
x_train = df[val_p].iloc[0:round(len(df) / 100 * 99)]
|
||||||
|
y_train = df["HeartDisease"].iloc[0:round(len(df) / 100 * 99)]
|
||||||
|
x_test = df[val_p].iloc[round(len(df) / 100 * 99):len(df)]
|
||||||
|
y_test = df["HeartDisease"].iloc[round(len(df) / 100 * 99):len(df)]
|
||||||
|
|
||||||
|
dtc = DecisionTreeClassifier(random_state=241)
|
||||||
|
dtc.fit(x_train.values, y_train.values)
|
||||||
|
y_predict = dtc.predict(x_test.values)
|
||||||
|
err = pred_errors(y_predict, y_test.values)
|
||||||
|
make_plots(y_test.values, 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.accuracy_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__':
|
||||||
|
# Работа системы в комплексе
|
||||||
|
# Здесь elim_kp - значение пороговой значимости параметра (выбран эмпирически)
|
||||||
|
most_valuable_prediction(param_range(normalisation("P:\\ULSTU\\ИИС\\Datasets\\heart_2020_cleaned.csv"), 0.05))
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user