250 KiB
250 KiB
Загружаем датасет по варианту и выводим информацию о столбцах:¶
In [71]:
import pandas as pd
df = pd.read_csv("..//..//static//csv//healthcare-dataset-stroke-data.csv")
df
Out[71]:
Заменим пустые значения в столбце bmi на медиану:
In [72]:
df["bmi"] = df["bmi"].fillna(df["bmi"].median())
Создадим лингвистические переменные¶
Входные: age (возраст пациента) и bmi (индекс массы тела пациента)
Выходные: avg_glucose_level (средний уровень глюкозы в крови)
In [73]:
import numpy as np
from skfuzzy import control as ctrl
age = ctrl.Antecedent(np.arange(df["age"].min(), df["age"].max() + 1, 1), "age")
bmi = ctrl.Antecedent(np.arange(df["bmi"].min(), df["bmi"].max() + 0.1, 0.1), "bmi")
avg_glucose_level = ctrl.Consequent(np.arange(df["avg_glucose_level"].min(), df["avg_glucose_level"].max() + 0.01, 0.01), "avg_glucose_level")
Далее произведем их настройку:
In [74]:
import skfuzzy as fuzz
age["young"] = fuzz.zmf(age.universe, 7, 30)
age["middle-aged"] = fuzz.trapmf(age.universe, [18, 30, 48, 60])
age["old"] = fuzz.smf(age.universe, 48, 60)
age.view()
bmi["low"] = fuzz.zmf(bmi.universe, 12, 18)
bmi["normal"] = fuzz.trapmf(bmi.universe, [16, 19, 24, 27])
bmi["high"] = fuzz.smf(bmi.universe, 25, 27)
bmi.view()
avg_glucose_level["low"] = fuzz.zmf(avg_glucose_level.universe, 60, 75)
avg_glucose_level["normal"] = fuzz.trapmf(avg_glucose_level.universe, [65, 75, 120, 135])
avg_glucose_level["high"] = fuzz.smf(avg_glucose_level.universe, 120, 160)
avg_glucose_level.view()
Сформируем базу нечетких правил:¶
In [75]:
rule1 = ctrl.Rule(age["young"] & bmi["low"], avg_glucose_level["low"])
rule2 = ctrl.Rule(age["young"] & bmi["normal"], avg_glucose_level["normal"])
rule3 = ctrl.Rule(age["young"] & bmi["high"], avg_glucose_level["normal"])
rule4 = ctrl.Rule(age["middle-aged"] & bmi["low"], avg_glucose_level["normal"])
rule5 = ctrl.Rule(age["middle-aged"] & bmi["normal"], avg_glucose_level["normal"])
rule6 = ctrl.Rule(age["middle-aged"] & bmi["high"], avg_glucose_level["high"])
rule7 = ctrl.Rule(age["old"] & bmi["low"], avg_glucose_level["low"])
rule8 = ctrl.Rule(age["old"] & bmi["normal"], avg_glucose_level["normal"])
rule9 = ctrl.Rule(age["old"] & bmi["high"], avg_glucose_level["high"])
rule1.view()
Out[75]:
Создадим нечеткую систему и добавим созданные нечеткие правила в ее базу знаний:
In [76]:
glucose_ctrl = ctrl.ControlSystem(
[
rule1,
rule2,
rule3,
rule4,
rule5,
rule6,
rule7,
rule8,
rule9
]
)
glucose_simulation = ctrl.ControlSystemSimulation(glucose_ctrl)
glucose_ctrl.view()
Теперь можно выполнить оценку качества полученной нечеткой системы.¶
Для начала проверим работу системы на единичном примере:
In [77]:
glucose_simulation.input["age"] = 25
glucose_simulation.input["bmi"] = 26
glucose_simulation.compute()
glucose_simulation.print_state()
glucose_simulation.output["avg_glucose_level"]
Out[77]:
In [78]:
avg_glucose_level.view(sim=glucose_simulation)
Также сравним результаты работы системы с реальными данными:
In [79]:
def fuzzy_pred(row):
glucose_simulation.input["age"] = row["age"]
glucose_simulation.input["bmi"] = row["bmi"]
glucose_simulation.compute()
return glucose_simulation.output["avg_glucose_level"]
In [80]:
result = df.copy()
result["avg_glucose_level_pred"] = result.apply(fuzzy_pred, axis=1)
result.loc[240:260, ["age", "bmi", "avg_glucose_level", "avg_glucose_level_pred"]]
Out[80]:
И оценим эти результаты с помощью метрик для задачи регрессии:
In [81]:
import math
from sklearn import metrics
rmetrics = {}
rmetrics["RMSE"] = math.sqrt(
metrics.mean_squared_error(result["avg_glucose_level"], result["avg_glucose_level_pred"])
)
rmetrics["RMAE"] = math.sqrt(
metrics.mean_absolute_error(result["avg_glucose_level"], result["avg_glucose_level_pred"])
)
rmetrics["R2"] = metrics.r2_score(
result["avg_glucose_level"], result["avg_glucose_level_pred"]
)
rmetrics
Out[81]:
Как можно заметить, нечеткая система с такими переменными и настройками со своей задачей справляется плохо