2025-02-28 16:43:15 +04:00

130 KiB
Raw Blame History

In [113]:
import pandas as pd
from pandas import DataFrame
import numpy as np
import skfuzzy as fuzz
import matplotlib.pyplot as plt

df: DataFrame = pd.read_csv(".//static//csv//Starbucks Dataset.csv")

Формирование базы нечетких правил

Сформируем базу нечетких правил, которые связывают входные и выходные переменные.

In [ ]:
# Определение диапазонов значений для входных переменных
x_high = np.linspace(0, 0.95, 100)
x_open = np.linspace(0, 0.95, 100)
x_volume = np.linspace(0, 3000000, 100)

# Определение функций принадлежности для high
high_low = fuzz.trapmf(x_high, [0, 0, 0.1, 0.45])
high_medium = fuzz.trimf(x_high, [0.4, 0.5, 0.75])
high_high = fuzz.smf(x_high, 0.7, 0.9)

# Определение функций принадлежности для Open
open_low = fuzz.trapmf(x_open, [0, 0, 0.1, 0.55])
open_medium = fuzz.trimf(x_open, [0.4, 0.6, 0.85])
open_high = fuzz.smf(x_open, 0.7, 0.9)

# Определение функций принадлежности для Value
volume_low = fuzz.trapmf(x_volume, [0, 0, 500000, 1000000])
volume_medium = fuzz.trimf(x_volume, [800000, 1500000, 2000000])
volume_high = fuzz.smf(x_volume, 1800000, 3000000)

# Определение нечетких правил
fuzzy_rules = [
    ("Низкий", "Мало", "Низкий"),
    ("Низкий", "Средне", "Средний"),
    ("Низкий", "Много", "Высокий"),
    ("Средний", "Мало", "Средний"),
    ("Средний", "Средне", "Высокий"),
    ("Средний", "Много", "Высокий"),
    ("Высокий", "Мало", "Высокий"),
    ("Высокий", "Средне", "Высокий"),
    ("Высокий", "Много", "Высокий")
]

# Визуализация функций принадлежности
fig, (ax0, ax1, ax2) = plt.subplots(nrows=3, figsize=(8, 9))

ax0.plot(x_high, high_low, 'b', linewidth=1.5, label='Низкий')
ax0.plot(x_high, high_medium, 'g', linewidth=1.5, label='Средний')
ax0.plot(x_high, high_high, 'r', linewidth=1.5, label='Высокий')
ax0.set_title('Функции принадлежности для Hight')
ax0.legend()

ax1.plot(x_open, open_low, 'b', linewidth=1.5, label='Мало')
ax1.plot(x_open, open_medium, 'g', linewidth=1.5, label='Средне')
ax1.plot(x_open, open_high, 'r', linewidth=1.5, label='Много')
ax1.set_title('Функции принадлежности для Open')
ax1.legend()

ax2.plot(x_volume, volume_low, 'b', linewidth=1.5, label='Низкий')
ax2.plot(x_volume, volume_medium, 'g', linewidth=1.5, label='Средний')
ax2.plot(x_volume, volume_high, 'r', linewidth=1.5, label='Высокий')
ax2.set_title('Функции принадлежности для Value')
ax2.legend() 

plt.tight_layout()
plt.show()
No description has been provided for this image

База нечётких правил

Для оценки качества системы создадим тестовые данные и применим нечеткие правила для получения предсказанных значений. Затем сравним их с реальными значениями.

In [115]:
# Функция для вычисления нечеткой оценки
def fuzzy_inference(high, open):
    # Определение степени принадлежности
    high_low_degree = fuzz.interp_membership(x_high, high_low, high)
    high_medium_degree = fuzz.interp_membership(x_high, high_medium, high)
    high_high_degree = fuzz.interp_membership(x_high, high_high, high)

    open_low_degree = fuzz.interp_membership(x_open, open_low, open)
    open_medium_degree = fuzz.interp_membership(x_open, open_medium, open)
    open_high_degree = fuzz.interp_membership(x_open, open_high, open)

    # Применяем правила
    # Активируем термы выходной переменной с использованием степени принадлежности
    volume_low_activated = np.fmin(high_low_degree, volume_low)
    volume_medium_activated = np.fmin(high_medium_degree, volume_medium)
    volume_high_activated = np.fmin(high_high_degree, volume_high)

    # Агрегируем все активированные термы
    aggregated = np.fmax(volume_low_activated, np.fmax(volume_medium_activated, volume_high_activated))

    # Дефуззификация
    volume_defuzz = fuzz.defuzz(x_volume, aggregated, 'centroid')

    return volume_defuzz

# Оценка системы на тестовом наборе данных
results = []
test_data = [
    (0.347656, 224358400, 0.328125),
    (0.367188, 58732800, 0.339844),
    (0.367188, 34777600, 0.371094),
    (0.644531, 11148800, 0.640625),
]
for high,  actual_volume, open in test_data:
    inferred_volume = fuzzy_inference(high, open)
    results.append((high, open, actual_volume, inferred_volume))

# Вывод результатов
print("High | Open | Value | Оцененная Value")
for high, open, actual_volume, inferred_volume in results:
    print(f"{high:4} | {open:6} | {actual_volume:15} | {inferred_volume:.2f}")

# Вычисление метрик качества
actual_volumes = [actual for _, _, actual, _ in results]
inferred_volumes = [inferred for _, _, _, inferred in results]

mae = np.mean(np.abs(np.array(actual_volumes) - np.array(inferred_volumes)))
rmse = np.sqrt(np.mean((np.array(actual_volumes) - np.array(inferred_volumes)) ** 2))

print(f"\nСредняя абсолютная ошибка (MAE): {mae:.2f}")
print(f"Среднеквадратичная ошибка (RMSE): {rmse:.2f}")
High | Open | Value | Оцененная Value
0.347656 | 0.328125 |       224358400 | 464215.53
0.367188 | 0.339844 |        58732800 | 470894.11
0.367188 | 0.371094 |        34777600 | 470894.11
0.644531 | 0.640625 |        11148800 | 1419002.85

Средняя абсолютная ошибка (MAE): 81548148.35
Среднеквадратичная ошибка (RMSE): 117041311.66

В результате выполнения лабораторной работы была создана нечеткая система, которая позволяет оценивать общую стоимость транзакции на основе открытия акции и количества продаж акций. Система была протестирована на тестовых данных, и были вычислены метрики качества (MAE и RMSE). Полученные результаты указывают на необходимость дальнейшей настройки системы для повышения точности предсказаний.