2025-02-13 21:31:43 +04:00

337 KiB
Raw Blame History

Начало лабораторной

Цены на кофе - https://www.kaggle.com/datasets/mayankanand2701/starbucks-stock-price-dataset

Выгрузка данных

In [35]:
import pandas as pd
df = pd.read_csv("./static/csv/Starbucks Dataset.csv")
df
Out[35]:
Date Open High Low Close Adj Close Volume
0 1992-06-26 0.328125 0.347656 0.320313 0.335938 0.260703 224358400
1 1992-06-29 0.339844 0.367188 0.332031 0.359375 0.278891 58732800
2 1992-06-30 0.367188 0.371094 0.343750 0.347656 0.269797 34777600
3 1992-07-01 0.351563 0.359375 0.339844 0.355469 0.275860 18316800
4 1992-07-02 0.359375 0.359375 0.347656 0.355469 0.275860 13996800
... ... ... ... ... ... ... ...
8031 2024-05-17 75.269997 78.000000 74.919998 77.849998 77.849998 14436500
8032 2024-05-20 77.680000 78.320000 76.709999 77.540001 77.540001 11183800
8033 2024-05-21 77.559998 78.220001 77.500000 77.720001 77.720001 8916600
8034 2024-05-22 77.699997 81.019997 77.440002 80.720001 80.720001 22063400
8035 2024-05-23 80.099998 80.699997 79.169998 79.260002 79.260002 4651418

8036 rows × 7 columns

Атрибуты

Date — Дата

Open — Цена открытия

High — Макс. цена

Low — Мин. цена

Close — Цена закрытия

Adj Close — Скорректированная цена закрытия

Volume — Объем торгов

Выбор входных и выходных переменных

Входные переменные будут Open (цена открытия) и Volume (объем торгов)

Выходная переменная - Close (цена закрытия)

Настройка параметров лингвистических переменных

Термы: Низкий (Low) Средний (Medium) Высокий (High)

In [ ]:
import numpy as np
import matplotlib.pyplot as plt
import skfuzzy as fuzz

# Определяем диапазон значений для объема торгов
volume_range = np.arange(0, 585508801, 10000)  

# Определение функций принадлежности для термов
low = fuzz.trapmf(volume_range, [0, 0, 30000000, 30000000])  
medium = fuzz.trimf(volume_range, [25000000, 250000000, 250000000])  
high = fuzz.trapmf(volume_range, [200000000, 250000000, 585508800, 585508800])  

# Визуализация функций принадлежности
plt.figure(figsize=(10, 6))
plt.plot(volume_range, low, label='Низкий (Low)', color='blue')
plt.plot(volume_range, medium, label='Средний (Medium)', color='orange')
plt.plot(volume_range, high, label='Высокий (High)', color='green')
plt.title('Функции принадлежности для объема торгов')
plt.xlabel('Объем торгов')
plt.ylabel('Принадлежность')
plt.ylim(-0.1, 1.1)
plt.axhline(0, color='black', lw=0.5)
plt.axvline(0, color='black', lw=0.5)
plt.legend()
plt.grid()

# Отображаем график
plt.show()
No description has been provided for this image

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

In [ ]:
import numpy as np
import skfuzzy as fuzz
import matplotlib.pyplot as plt

x_open = np.linspace(0, 126, 100)  
x_volume = np.linspace(0, 585508800, 100)  
x_close = np.linspace(0, 130, 100)  

# Определение функций принадлежности для цены открытия
low_open = fuzz.trapmf(x_open, [0, 0, 10, 40])
medium_open = fuzz.trimf(x_open, [35, 63, 90])
high_open = fuzz.trapmf(x_open, [85, 90, 126, 126])

# Определение функций принадлежности для объема торгов
low_volume = fuzz.trapmf(x_volume, [0, 0, 30000000, 30000000])
medium_volume = fuzz.trimf(x_volume, [25000000, 250000000, 250000000])
high_volume = fuzz.trapmf(x_volume, [200000000, 250000000, 585508800, 585508800])

# Определение функций принадлежности для цены закрытия
low_close = fuzz.trapmf(x_close, [0, 0, 10, 40])
medium_close = fuzz.trimf(x_close, [35, 80, 115])
high_close = fuzz.trapmf(x_close, [110, 120, 130, 130])

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

# Вывод правил
print("Нечеткие правила:")
for rule in fuzzy_rules:
    print(f"Если Цена открытия {rule[0]} И Объем {rule[1]}, Тогда Цена закрытия {rule[2]}.")

# Визуализация функций принадлежности
fig, axs = plt.subplots(3, 1, figsize=(10, 12))

# Цена открытия
axs[0].plot(x_open, low_open, label='Низкий (Low)', color='blue')
axs[0].plot(x_open, medium_open, label='Средний (Medium)', color='green')
axs[0].plot(x_open, high_open, label='Высокий (High)', color='red')
axs[0].set_title('Функции принадлежности для цены открытия')
axs[0].set_xlabel('Цена открытия')
axs[0].set_ylabel('Степень принадлежности')
axs[0].legend()
axs[0].grid()

# Объем торгов
axs[1].plot(x_volume, low_volume, label='Низкий (Low)', color='blue')
axs[1].plot(x_volume, medium_volume, label='Средний (Medium)', color='orange')
axs[1].plot(x_volume, high_volume, label='Высокий (High)', color='green')
axs[1].set_title('Функции принадлежности для объема торгов')
axs[1].set_xlabel('Объем торгов')
axs[1].set_ylabel('Степень принадлежности')
axs[1].legend()
axs[1].grid()

# Цена закрытия
axs[2].plot(x_close, low_close, label='Низкая', color='blue')
axs[2].plot(x_close, medium_close, label='Средняя', color='green')
axs[2].plot(x_close, high_close, label='Высокая', color='red')
axs[2].set_title('Функции принадлежности для цены закрытия')
axs[2].set_xlabel('Цена закрытия')
axs[2].set_ylabel('Степень принадлежности')
axs[2].legend()
axs[2].grid()

plt.tight_layout()
plt.show()

# Визуализация нечетких правил (пример)
fig, ax = plt.subplots(figsize=(10, 6))
x_rule = np.linspace(0, 126, 100)

# Пример нечеткого вывода для визуализации (примерные значения)
for rule in fuzzy_rules:
    # Определение степени уверенности для каждого правила
    if rule[0] == "Низкая" and rule[1] == "Низкий":
        ax.fill_between(x_open, low_open, low_close, color='lightblue', alpha=0.5, label='Низкий #1')
    elif rule[0] == "Низкая" and rule[1] == "Средний":
        ax.fill_between(x_open, medium_open, medium_close, color='lightgreen', alpha=0.5, label='Средний #2')
    elif rule[0] == "Низкая" and rule[1] == "Высокий":
        ax.fill_between(x_open, low_open, medium_close, color='lightcoral', alpha=0.5, label='Высокий #3')
    elif rule[0] == "Средняя" and rule[1] == "Низкий":
        ax.fill_between(x_open, medium_open, medium_close, color='orange', alpha=0.5, label='Низкий #4')
    elif rule[0] == "Высокая" and rule[1] == "Высокий":
        ax.fill_between(x_open, high_open, high_close, color='salmon', alpha=0.5, label='Высокий #5')

ax.set_title('Визуализация нечетких правил')
ax.set_xlabel('Цена открытия')
ax.set_ylabel('Цена закрытия')
ax.legend()
ax.grid()

plt.tight_layout()
plt.show()
Нечеткие правила:
Если Цена открытия Низкая И Объем Низкий, Тогда Цена закрытия Низкая.
Если Цена открытия Низкая И Объем Средний, Тогда Цена закрытия Средняя.
Если Цена открытия Низкая И Объем Высокий, Тогда Цена закрытия Средняя.
Если Цена открытия Средняя И Объем Низкий, Тогда Цена закрытия Средняя.
Если Цена открытия Средняя И Объем Средний, Тогда Цена закрытия Высокая.
Если Цена открытия Средняя И Объем Высокий, Тогда Цена закрытия Высокая.
Если Цена открытия Высокая И Объем Низкий, Тогда Цена закрытия Средняя.
Если Цена открытия Высокая И Объем Средний, Тогда Цена закрытия Высокая.
Если Цена открытия Высокая И Объем Высокий, Тогда Цена закрытия Высокая.
No description has been provided for this image
No description has been provided for this image

Оценка качества полученной нечеткой системы, используя метрики регрессии

In [ ]:
import numpy as np
import skfuzzy as fuzz
import matplotlib.pyplot as plt

# Определяем диапазоны значений для входных переменных
x_open = np.linspace(0, 126, 100)  # Цена открытия
x_volume = np.linspace(0, 585508800, 100)  # Объем торгов
x_close = np.linspace(0, 130, 100)  # Цена закрытия

# Определение функций принадлежности для цены открытия
low_open = fuzz.trapmf(x_open, [0, 0, 10, 40])
medium_open = fuzz.trimf(x_open, [35, 63, 90])
high_open = fuzz.trapmf(x_open, [85, 90, 126, 126])

# Определение функций принадлежности для объема торгов
low_volume = fuzz.trapmf(x_volume, [0, 0, 30000000, 30000000])
medium_volume = fuzz.trimf(x_volume, [30000000, 250000000, 300000000])
high_volume = fuzz.trapmf(x_volume, [250000000, 450000000, 585508800, 585508800])

# Определение функций принадлежности для цены закрытия
low_close = fuzz.trapmf(x_close, [0, 0, 10, 40])
medium_close = fuzz.trimf(x_close, [35, 80, 115])
high_close = fuzz.trapmf(x_close, [110, 120, 130, 130])

# Создаем тестовые данные (цена открытия, объем, эталонная цена закрытия)
test_data = [
  (50, 150000000, 60),  # Низкая цена открытия, средний объем и цена закрытия
    (100, 300000000, 120), # Высокая цена открытия, средний объем и высокая цена закрытия
    (85, 450000000, 110),  # Высокая цена открытия и высокая цена закрытия
    (40, 100000000, 30)    # Средняя цена открытия и низкий объем
]

# Функция для вычисления нечеткой оценки
def fuzzy_inference(open_price, volume):
    open_low = fuzz.interp_membership(x_open, low_open, open_price)
    open_medium = fuzz.interp_membership(x_open, medium_open, open_price)
    open_high = fuzz.interp_membership(x_open, high_open, open_price)

    volume_low = fuzz.interp_membership(x_volume, low_volume, volume)
    volume_medium = fuzz.interp_membership(x_volume, medium_volume, volume)
    volume_high = fuzz.interp_membership(x_volume, high_volume, volume)

    close_low = np.fmin(open_low, volume_low)
    close_medium = np.fmin(open_medium, volume_medium)
    close_high = np.fmin(open_high, volume_high)

    close0 = fuzz.defuzz(x_close, low_close, 'centroid') * close_low if close_low > 0 else 0
    close1 = fuzz.defuzz(x_close, medium_close, 'centroid') * close_medium if close_medium > 0 else 0
    close2 = fuzz.defuzz(x_close, high_close, 'centroid') * close_high if close_high > 0 else 0

    return max(close0, close1, close2)

# Список для хранения результатов
results = []

# Оценка системы на тестовом наборе данных
for open_price, volume, actual_close in test_data:
    inferred_close = fuzzy_inference(open_price, volume)
    results.append((open_price, volume, actual_close, inferred_close))

# Вывод результатов
print(f"{'Цена открытия':<18} | {'Объем торгов':<10} | {'Фактическая цена закрытия':<30} | {'Полученная цена закрытия':<30}")
print("=" * 92)

for open_price, volume, actual_close, inferred_close in results:
    print(f"{open_price:<18} | {volume:<10} | {actual_close:<30} | {inferred_close:<30.2f}")

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

mae = np.mean(np.abs(np.array(actual_closes) - np.array(inferred_closes)))
rmse = np.sqrt(np.mean((np.array(actual_closes) - np.array(inferred_closes)) ** 2))

# Вывод метрик
print(f"\nСредняя абсолютная ошибка (MAE): {mae:.2f}")
print(f"Среднеквадратичная ошибка (RMSE): {rmse:.2f}")
Цена открытия      | Объем торгов | Фактическая цена закрытия      | Полученная цена закрытия      
============================================================================================
50                 | 150000000  | 60                             | 41.07                         
100                | 300000000  | 120                            | 30.55                         
85                 | 450000000  | 110                            | 5.24                          
40                 | 100000000  | 30                             | 13.69                         

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