432 KiB
Лабораторная 7¶
import numpy as np
import pandas as pd
import skfuzzy as fuzz
import skfuzzy.control as ctrl
df = pd.read_csv(".//static//csv//Diamonds Prices2022.csv")
df
Определение входных и выходных переменных¶
выведем все уникальные значения встолбце глубина
unique_values = df['clarity'].unique()
print(unique_values)
Закодируем глубину и в дальнейшем будем использовать новый столбец
clarity_mapping = {
'I1': 1,
'SI2': 2,
'SI1': 3,
'VS2': 4,
'VS1': 5,
'VVS2': 6,
'VVS1': 7,
'IF': 8
}
df['clarity_encoded'] = df['clarity'].map(clarity_mapping)
df
определим минимальные и максимальные значения
carat_min = df["carat"].min()
carat_max = df["carat"].max()
clarity_min = df["clarity_encoded"].min()
clarity_max = df["clarity_encoded"].max()
price_min = df["price"].min()
price_max = df["price"].max()
print(carat_min)
print(carat_max)
print(clarity_min)
print(clarity_max)
print(price_min)
print(price_max)
определим входные и выходные переменные
carat = ctrl.Antecedent(np.linspace(carat_min, carat_max, 100), 'carat')
clarity = ctrl.Antecedent(np.arange(clarity_min, clarity_max + 1, 1), 'clarity')
price = ctrl.Consequent(np.linspace(price_min, price_max+100, 100), 'price')
создание лингвистических переменных¶
carat["малый"] = fuzz.zmf(carat.universe, carat_min, carat_min + 1.6)
carat["средний"] = fuzz.trapmf(carat.universe, [1, 2, 3, 4])
carat["большой"] = fuzz.smf(carat.universe, carat_max - 1.6, carat_max)
carat.view()
clarity["низкий"] = fuzz.zmf(clarity.universe, 1, 3)
clarity["средний"] = fuzz.trapmf(clarity.universe, [2, 4, 5, 7])
clarity["высокий"] = fuzz.smf(clarity.universe, 6, 8)
clarity.view()
price["дешевый"] = fuzz.zmf(price.universe, price_min, price_min + 8000)
price["средний"] = fuzz.trapmf(price.universe, [price_min + 2000, price_min + 8000, price_max - 8000, price_max - 2000])
price["дорогой"] = fuzz.smf(price.universe, price_max - 8000, price_max)
price.view()
Определение правил¶
rule1 = ctrl.Rule(carat["малый"] & clarity["низкий"], price["дешевый"])
rule2 = ctrl.Rule(carat["малый"] & clarity["средний"], price["средний"])
rule3 = ctrl.Rule(carat["малый"] & clarity["высокий"], price["средний"])
rule4 = ctrl.Rule(carat["средний"] & clarity["низкий"], price["средний"])
rule5 = ctrl.Rule(carat["средний"] & clarity["средний"], price["средний"])
rule6 = ctrl.Rule(carat["средний"] & clarity["высокий"], price["дорогой"])
rule7 = ctrl.Rule(carat["большой"] & clarity["низкий"], price["средний"])
rule8 = ctrl.Rule(carat["большой"] & clarity["средний"], price["дорогой"])
rule9 = ctrl.Rule(carat["большой"] & clarity["высокий"], price["дорогой"])
rule1.view()
Создание нечеткой системы и добавление нечетких правил в базу знаний нечеткой системы¶
# Создание нечеткой системы управления
price_ctrl = ctrl.ControlSystem([
rule1, rule2, rule3,
rule4, rule5, rule6,
rule7, rule8, rule9
])
# Создание симулятора системы управления
price_simulation = ctrl.ControlSystemSimulation(price_ctrl)
Расчета выходной переменной¶
# Установка входных значений
price_simulation.input["carat"] = 4
price_simulation.input["clarity"] = 4
# Выполнение вычислений
price_simulation.compute()
# Вывод текущего состояния системы
price_simulation.print_state()
# Получение предсказанного значения цены
predicted_price = price_simulation.output["price"]
print(f"Предсказанная цена бриллианта: {predicted_price}")
Визуализация функции принадлежности для выходной переменной¶
price.view(sim=price_simulation)
Оценка качества полученной нечеткой системы¶
Визуализация поверхностей вывода
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
carat_values = np.linspace(carat_min, carat_max, 30)
clarity_values = np.linspace(clarity_min, clarity_max, 30)
price_results = np.zeros((len(carat_values), len(clarity_values)))
for i, c in enumerate(carat_values):
for j, cl in enumerate(clarity_values):
price_simulation.input["carat"] = c
price_simulation.input["clarity"] = cl
price_simulation.compute()
price_results[i, j] = price_simulation.output["price"]
X, Y = np.meshgrid(carat_values, clarity_values)
fig = plt.figure(figsize=(10, 7))
ax = fig.add_subplot(111, projection="3d")
ax.plot_surface(X, Y, price_results.T, cmap="viridis")
ax.set_xlabel("Carat")
ax.set_ylabel("Clarity")
ax.set_zlabel("Predicted Price")
ax.set_title("Fuzzy System Output Surface")
plt.show()
Вывод: на графике видно, что с увеличением карат и чистоты цены растет.
Расчёт метрики ошибки (MSE, RMSE, MAE)
import pandas as pd
import numpy as np
import skfuzzy as fuzz
import math
from sklearn import metrics
def fuzzy_pred(row):
price_simulation.input["carat"] = row["carat"]
price_simulation.input["clarity"] = row["clarity_encoded"] # Используйте закодированное значение для clarity
price_simulation.compute()
return price_simulation.output["price"]
# Создание столбца с предсказанными значениями
df["predicted_price"] = df.apply(lambda row: fuzzy_pred(row), axis=1)
df.head(15)
metrics_results = {}
metrics_results["RMSE"] = math.sqrt(metrics.mean_squared_error(df["price"], df["predicted_price"]))
metrics_results["RMAE"] = math.sqrt(metrics.mean_absolute_error(df["price"], df["predicted_price"]))
metrics_results["R2"] = metrics.r2_score(df["price"], df["predicted_price"])
print(metrics_results)
На основе результатов модели (RMSE, RMAE и R²), можно сделать следующие выводы:
RMSE: Это среднеквадратичная ошибка модели, которая измеряет среднее отклонение предсказанных значений от фактических. В данном случае значение RMSE составляет 6462.18, что указывает на то, что модель в среднем ошибается на эту величину, в ъорошей можели этот показатель должен быть меньше
RMAE: Это корень из среднего абсолютного отклонения, который также показывает ошибку модели, но в терминах абсолютных отклонений, а не квадратов. В данном случае RMAE составляет 75.51, что также указывает на значительную ошибку в предсказаниях.
R²: Этот показатель измеряет, насколько хорошо модель объясняет вариацию зависимой переменной. В данном случае значение R² = -1.62 — это очень низкое значение, что говорит о том, что модель плохо объясняет данные и может быть неадекватной для предсказания цен. Обычно R² должно быть как можно ближе к 1 для хорошей модели, и значения меньше 0 указывают на крайне слабую модель.