AIM-PIbd-31-Zhirnova-A-E/lab_3/lab3.ipynb
2024-10-18 21:03:16 +04:00

393 KiB
Raw Blame History

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

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

Бизнес-цели

  1. Предсказание цены закрытия акций (Close) Максимизация прибыли путем предсказания изменения цены акций, что может помочь в принятии инвестиционных решений.
  2. Предсказание объема торгов (Volume) Оптимизация торговых операций и улучшение ликвидности на рынке, что помогает в планировании запасов и управлении финансовыми потоками.

Технические цели проекта:

Сбор и подготовка данных Разработка подхода для сбора исторических данных о ценах акций и объемах торгов. Обеспечение качества данных: устранение дубликатов, обработка пропусков и аномалий. Факторизация данных: создание дополнительных признаков, таких как скользящие средние, индекс относительной силы (RSI) и другие технические индикаторы.

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

Валидация и тестирование моделей Разработка стратегий кросс-валидации для оценки производительности моделей на различных временных интервалах и рыночных условиях. Оценка устойчивости моделей к различным сценариям (например, резкие падения или росты рынков).

In [6]:
import pandas as pd
df = pd.read_csv(".//static//csv//Starbucks Dataset.csv")
print(df.columns)
Index(['Date', 'Open', 'High', 'Low', 'Close', 'Adj Close', 'Volume'], dtype='object')

Подготовка данных

In [8]:
# Процент пропущенных значений признаков
for i in df.columns:
    null_rate = df[i].isnull().sum() / len(df) * 100
    if null_rate > 0:
        print(f'{i} Процент пустых значений: %{null_rate:.2f}')

# Проверка на пропущенные данные
print(df.isnull().sum())

df.isnull().any()
Date         0
Open         0
High         0
Low          0
Close        0
Adj Close    0
Volume       0
dtype: int64
Out[8]:
Date         False
Open         False
High         False
Low          False
Close        False
Adj Close    False
Volume       False
dtype: bool

Пропущенных значений нет.

Разбиение набора данных на обучающую, контрольную и тестовую выборки для устранения проблемы просачивания данных

In [10]:
from sklearn.model_selection import train_test_split

# Разделение данных на обучающую и тестовую выборки (80% - обучение, 20% - тест)
train_data, test_data = train_test_split(df, test_size=0.2, random_state=42)

# Разделение обучающей выборки на обучающую и контрольную (80% - обучение, 20% - контроль)
train_data, val_data = train_test_split(train_data, test_size=0.2, random_state=42)

print("Размер обучающей выборки:", len(train_data))
print("Размер контрольной выборки:", len(val_data))
print("Размер тестовой выборки:", len(test_data))
Размер обучающей выборки: 5142
Размер контрольной выборки: 1286
Размер тестовой выборки: 1608
In [8]:
import pandas as pd
from sklearn.model_selection import train_test_split

# Загрузим данные
df = pd.read_csv(".//static//csv//Starbucks Dataset.csv")

# Определяем целевую переменную и признаки
target_column = 'Close'
X = df.drop(columns=[target_column, 'Date'])
y = df[target_column]

X_train, X_temp, y_train, y_temp = train_test_split(X, y, test_size=0.3, random_state=42)

X_val, X_test, y_val, y_test = train_test_split(X_temp, y_temp, test_size=0.5, random_state=42)

# Создаём DataFrame для каждой выборки
train_data = pd.DataFrame(X_train, columns=X.columns)
train_data['Close'] = y_train.reset_index(drop=True)

val_data = pd.DataFrame(X_val, columns=X.columns)
val_data['Close'] = y_val.reset_index(drop=True)

test_data = pd.DataFrame(X_test, columns=X.columns)
test_data['Close'] = y_test.reset_index(drop=True)
In [9]:
import seaborn as sns
import matplotlib.pyplot as plt

# Гистограмма распределения объема в обучающей выборке
sns.histplot(train_data['Volume'], kde=True)
plt.title('Распределение объема в обучающей выборке')
plt.show()

# Гистограмма распределения объема в контрольной выборке
sns.histplot(val_data['Volume'], kde=True)
plt.title('Распределение объема в контрольной выборке')
plt.show()

# Гистограмма распределения объема в тестовой выборке
sns.histplot(test_data['Volume'], kde=True)
plt.title('Распределение объема в тестовой выборке')
plt.show()
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
In [11]:
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt
from sklearn.utils import resample

# Загрузим данные
df = pd.read_csv(".//static//csv//Starbucks Dataset.csv")

# Определяем целевую переменную и признаки
target_column_close = 'Close'
target_column_volume = 'Volume'  # Здесь используем колонку Volume
X = df.drop(columns=[target_column_close, target_column_volume, 'Date'])
y_close = df[target_column_close]
y_volume = df[target_column_volume]

# Сначала разделяем на учебную и временную выборки
X_train, X_temp, y_train_close, y_temp_close = train_test_split(X, y_close, test_size=0.3, random_state=42)
y_train_volume, y_temp_volume = train_test_split(y_volume, test_size=0.3, random_state=42)

# Затем разделяем временную выборку на валидационную и тестовую
X_val, X_test, y_val_close, y_test_close = train_test_split(X_temp, y_temp_close, test_size=0.5, random_state=42)
y_val_volume, y_test_volume = train_test_split(y_temp_volume, test_size=0.5, random_state=42)

# Создаем DataFrame для каждой выборки
train_data = pd.DataFrame(X_train, columns=X.columns)
train_data['Close'] = y_train_close.reset_index(drop=True)
train_data['Volume'] = y_train_volume.reset_index(drop=True)

val_data = pd.DataFrame(X_val, columns=X.columns)
val_data['Close'] = y_val_close.reset_index(drop=True)
val_data['Volume'] = y_val_volume.reset_index(drop=True)

test_data = pd.DataFrame(X_test, columns=X.columns)
test_data['Close'] = y_test_close.reset_index(drop=True)
test_data['Volume'] = y_test_volume.reset_index(drop=True)

# Шаг 1: Оценка сбалансированности выборок с использованием Volume
def plot_distribution(data, column, title):
    plt.figure(figsize=(10, 4))
    plt.title(f'Distribution of "{column}" for {title}')
    data[column].hist(bins=30, color='blue', alpha=0.7)
    plt.xlabel(column)
    plt.ylabel('Frequency')
    plt.grid()
    plt.show()

# График для каждой выборки
plot_distribution(train_data, 'Volume', 'Training Data')
plot_distribution(val_data, 'Volume', 'Validation Data')
plot_distribution(test_data, 'Volume', 'Test Data')

# Проверка на сбалансированность
def print_statistics(data, name):
    print(f"{name} Statistics for 'Close':")
    print(data['Close'].describe())
    print(f"{name} Statistics for 'Volume':")
    print(data['Volume'].describe())
    print("\n")

print_statistics(train_data, 'Training Data')
print_statistics(val_data, 'Validation Data')
print_statistics(test_data, 'Test Data')

# Шаг 2: Применение аугментации данных для 'Volume'
def augment_data(data, target_column, n_samples):
    # Увеличим выборку путем бутстреппинга
    augmented_data = resample(data, replace=True, n_samples=n_samples, random_state=42)
    return augmented_data

# Оценим нужно ли нам увеличение выборки по обучающим данным
if train_data['Volume'].value_counts(normalize=True).max() < 0.75:  # 75% как порог
    # Допустим, мы хотим увеличить обучающую выборку до 2000 примеров
    augmented_train_data = augment_data(train_data, 'Volume', n_samples=2000)

    # Объединяем оригинальные и увеличенные данные
    train_data = pd.concat([train_data, augmented_train_data]).drop_duplicates().reset_index(drop=True)
    print("Аугментация данных успешно применена для обучающей выборки.")

# Проверяем новую распределение после аугментации
plot_distribution(train_data, 'Volume', 'Augmented Training Data')
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
Training Data Statistics for 'Close':
count    3935.000000
mean       30.118718
std        33.588282
min         0.347656
25%         4.505000
50%        13.627500
75%        55.299999
max       126.059998
Name: Close, dtype: float64
Training Data Statistics for 'Volume':
count    3.935000e+03
mean     1.483718e+07
std      1.475393e+07
min      1.847800e+06
25%      7.912000e+06
50%      1.182380e+07
75%      1.789760e+07
max      5.855088e+08
Name: Volume, dtype: float64


Validation Data Statistics for 'Close':
count    199.000000
mean      22.080320
std       29.184280
min        0.359375
25%        2.698243
50%        7.840000
75%       32.589999
max      119.800003
Name: Close, dtype: float64
Validation Data Statistics for 'Volume':
count    1.990000e+02
mean     1.516312e+07
std      9.809615e+06
min      2.659200e+06
25%      8.404200e+06
50%      1.236850e+07
75%      1.983870e+07
max      6.235520e+07
Name: Volume, dtype: float64


Test Data Statistics for 'Close':
count    189.000000
mean      39.538342
std       37.190211
min        0.425781
25%        5.460000
50%       27.674999
75%       70.669998
max      122.629997
Name: Close, dtype: float64
Test Data Statistics for 'Volume':
count    1.890000e+02
mean     1.363519e+07
std      9.243478e+06
min      1.504000e+06
25%      7.248100e+06
50%      1.056700e+07
75%      1.726080e+07
max      5.744800e+07
Name: Volume, dtype: float64


Аугментация данных успешно применена для обучающей выборки.
No description has been provided for this image

Обучающая выборка содержит 3935 примеров, валидационная — 199, тестовая — 199. Основные статистики по целевой переменной Close показывают, что значения варьируются от 0.35 до 126.06 с учетом значительного разброса (стандартное отклонение 33.59). Распределение объема торгов в обучающей выборке имеет большой разброс с минимумом в 1.85 миллиона и максимумом в 585.51 миллиона. Среднее значение объема составляет примерно 14.84 миллиона. Это говорит о разнообразии торговой активности.

In [19]:
import pandas as pd
import numpy as np

# Загрузим данные
df = pd.read_csv("./static/csv/Starbucks Dataset.csv")

# Убедимся, что дата в нужном формате
df['Date'] = pd.to_datetime(df['Date'])

# Конструирование признаков

df['Year'] = df['Date'].dt.year
df['Month'] = df['Date'].dt.month

# Условия для создания категорий
categorical_features = ['Year', 'Month']

# Применение one-hot encoding к новым категориальным признакам
train_data_encoded = pd.get_dummies(df, columns=categorical_features)

# Отделяем метки 'Close' и 'Volume'
y_close = df['Close']
y_volume = df['Volume']


X = train_data_encoded.drop(columns=['Date', 'Close', 'Volume', 'Adj Close'])

# Дискретизация числовых признаков (например, 'Close').
# Создадим категории для 'Close' на 5 категорий
train_data_encoded['Close_Category'] = pd.cut(train_data_encoded['Close'], bins=5, labels=False)

# Выводим информацию о столбцах
print("Столбцы train_data_encoded:")
print(train_data_encoded.columns.tolist())

# Пример вывода первых нескольких строк закодированного датафрейма
print("Первые 5 строк закодированного датафрейма:")
print(train_data_encoded.head())
Столбцы train_data_encoded:
['Date', 'Open', 'High', 'Low', 'Close', 'Adj Close', 'Volume', 'Year_1992', 'Year_1993', 'Year_1994', 'Year_1995', 'Year_1996', 'Year_1997', 'Year_1998', 'Year_1999', 'Year_2000', 'Year_2001', 'Year_2002', 'Year_2003', 'Year_2004', 'Year_2005', 'Year_2006', 'Year_2007', 'Year_2008', 'Year_2009', 'Year_2010', 'Year_2011', 'Year_2012', 'Year_2013', 'Year_2014', 'Year_2015', 'Year_2016', 'Year_2017', 'Year_2018', 'Year_2019', 'Year_2020', 'Year_2021', 'Year_2022', 'Year_2023', 'Year_2024', 'Month_1', 'Month_2', 'Month_3', 'Month_4', 'Month_5', 'Month_6', 'Month_7', 'Month_8', 'Month_9', 'Month_10', 'Month_11', 'Month_12', 'Close_Category']
Первые 5 строк закодированного датафрейма:
        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   

   Year_1992  Year_1993  Year_1994  ...  Month_4  Month_5  Month_6  Month_7  \
0       True      False      False  ...    False    False     True    False   
1       True      False      False  ...    False    False     True    False   
2       True      False      False  ...    False    False     True    False   
3       True      False      False  ...    False    False    False     True   
4       True      False      False  ...    False    False    False     True   

   Month_8  Month_9  Month_10  Month_11  Month_12  Close_Category  
0    False    False     False     False     False               0  
1    False    False     False     False     False               0  
2    False    False     False     False     False               0  
3    False    False     False     False     False               0  
4    False    False     False     False     False               0  

[5 rows x 53 columns]
In [20]:
import pandas as pd

# Загружаем данные
df = pd.read_csv(".//static//csv//Starbucks Dataset.csv")

# Проверка на наличие числовых признаков
print("Названия столбцов в датасете:")
print(df.columns)

# Выводим основные статистические параметры для количественных признаков
print("Статистические параметры:")
print(df.describe())

# Дискретизация столбца 'Close' на группы
bins = [0, 50, 100, 150, 200, 250, 300]  # Определяем границы корзин
labels = ['0-50', '51-100', '101-150', '151-200', '201-250', '251-300']  # Названия категорий

# Создание нового столбца 'Close_Disc' на основе дискретизации
df['Close_Disc'] = pd.cut(df['Close'], bins=bins, labels=labels, include_lowest=True)

# Проверка результата
print("После дискретизации 'Close':")
print(df[['Close', 'Close_Disc']].head())

# Если нужно, можно повторить дискретизацию для других числовых признаков
Названия столбцов в датасете:
Index(['Date', 'Open', 'High', 'Low', 'Close', 'Adj Close', 'Volume'], dtype='object')
Статистические параметры:
              Open         High          Low        Close    Adj Close  \
count  8036.000000  8036.000000  8036.000000  8036.000000  8036.000000   
mean     30.054280    30.351487    29.751322    30.058857    26.674025   
std      33.615577    33.906613    33.314569    33.615911    31.728090   
min       0.328125     0.347656     0.320313     0.335938     0.260703   
25%       4.392031     4.531250     4.304922     4.399610     3.414300   
50%      13.325000    13.493750    13.150000    13.330000    10.352452   
75%      55.250000    55.722501    54.852499    55.267499    47.464829   
max     126.080002   126.320000   124.809998   126.059998   118.010414   

             Volume  
count  8.036000e+03  
mean   1.470459e+07  
std    1.340021e+07  
min    1.504000e+06  
25%    7.817750e+06  
50%    1.169815e+07  
75%    1.778795e+07  
max    5.855088e+08  
После дискретизации 'Close':
      Close Close_Disc
0  0.335938       0-50
1  0.359375       0-50
2  0.347656       0-50
3  0.355469       0-50
4  0.355469       0-50
In [21]:
import pandas as pd

# Загружаем данные
df = pd.read_csv(".//static//csv//Starbucks Dataset.csv")

# Просмотр первых строк, чтобы понять структуру данных
print("Первые строки данных:")
print(df.head())

# 1. Изменение цены
df['Price_Change'] = df['Close'] - df['Open']

# 2. Процентное изменение
df['Percentage_Change'] = (df['Price_Change'] / df['Open']) * 100

# 3. Средняя цена
df['Average_Price'] = (df['High'] + df['Low'] + df['Open'] + df['Close']) / 4

# 4. Диапазон цены
df['Price_Range'] = df['High'] - df['Low']

# 5. Объем изменений
df['Volume_Impact'] = df['Price_Range'] * df['Volume']

# Проверка создания новых признаков
print("Новые признаки:")
print(df[['Price_Change', 'Percentage_Change', 'Average_Price', 'Price_Range', 'Volume_Impact']].head())
Первые строки данных:
         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
Новые признаки:
   Price_Change  Percentage_Change  Average_Price  Price_Range  Volume_Impact
0      0.007813           2.381105       0.333008     0.027343   6.134632e+06
1      0.019531           5.747049       0.349610     0.035157   2.064869e+06
2     -0.019532          -5.319346       0.357422     0.027344   9.509587e+05
3      0.003906           1.111038       0.351563     0.019531   3.577454e+05
4     -0.003906          -1.086887       0.355469     0.011719   1.640285e+05
In [22]:
import pandas as pd
from sklearn.preprocessing import MinMaxScaler, StandardScaler

# Шаг 1: Загрузка обработанных данных
df = pd.read_csv(".//static//csv//Starbucks_Dataset_Processed.csv")

# Шаг 2: Признаки для масштабирования
features_to_scale = ['Price_Change', 'Percentage_Change', 'Average_Price', 'Price_Range', 'Volume_Impact']

# Шаг 3: Нормализация (Min-Max Scaling)
min_max_scaler = MinMaxScaler()
df[features_to_scale] = min_max_scaler.fit_transform(df[features_to_scale])

# Шаг 4: Стандартизация (Z-score Scaling)
standard_scaler = StandardScaler()
df[features_to_scale] = standard_scaler.fit_transform(df[features_to_scale])

# Вывод результатов после масштабирования
print("Результаты после масштабирования:")
print(df[features_to_scale].head())
Результаты после масштабирования:
   Price_Change  Percentage_Change  Average_Price  Price_Range  Volume_Impact
0      0.005718           1.121421      -0.884290    -0.751681      -0.099935
1      0.026425           2.750040      -0.883796    -0.741427      -0.403159
2     -0.042603          -2.604458      -0.883564    -0.751680      -0.486153
3     -0.001186           0.506897      -0.883738    -0.761932      -0.530351
4     -0.014990          -0.556574      -0.883622    -0.772183      -0.544784

В целом, результаты масштабирования показывают высокую волатильность рынка, однако стабильность в среднем значении цены может указывать на определенные тренды, которые стоит учитывать в дальнейших аналитических прогнозах и торговых стратегиях

In [28]:
import pandas as pd
import featuretools as ft

# Загрузка данных
df = pd.read_csv(".//static//csv//Starbucks Dataset.csv")
print(df.columns)

# Преобразование колонки 'Date' в datetime формат
df['Date'] = pd.to_datetime(df['Date'])
df['id'] = df.index  # Добавляем уникальный идентификатор

# Создание сущности
es = ft.EntitySet(id='starbucks_data')
es = es.add_dataframe(dataframe_name='prices', dataframe=df, index='id', make_index=False)

# Конструирование признаков
features, feature_defs = ft.dfs(entityset=es,
                                 target_dataframe_name='prices',
                                 agg_primitives=['count', 'mean', 'sum'],
                                 trans_primitives=['month', 'year', 'weekday'],
                                 verbose=True)

# Печать созданных признаков
print(features.head())
c:\Users\a3012\AIM-PIbd-31-Zhirnova-A-E\aimenv\Lib\site-packages\featuretools\synthesis\deep_feature_synthesis.py:169: UserWarning: Only one dataframe in entityset, changing max_depth to 1 since deeper features cannot be created
  warnings.warn(
c:\Users\a3012\AIM-PIbd-31-Zhirnova-A-E\aimenv\Lib\site-packages\featuretools\synthesis\dfs.py:321: UnusedPrimitiveWarning: Some specified primitives were not used during DFS:
  agg_primitives: ['count', 'mean', 'sum']
This may be caused by a using a value of max_depth that is too small, not setting interesting values, or it may indicate no compatible columns for the primitive were found in the data. If the DFS call contained multiple instances of a primitive in the list above, none of them were used.
  warnings.warn(warning_msg, UnusedPrimitiveWarning)
Index(['Date', 'Open', 'High', 'Low', 'Close', 'Adj Close', 'Volume'], dtype='object')
Built 9 features
Elapsed: 00:00 | Progress: 100%|██████████
        Open      High       Low     Close  Adj Close     Volume MONTH(Date)  \
id                                                                             
0   0.328125  0.347656  0.320313  0.335938   0.260703  224358400           6   
1   0.339844  0.367188  0.332031  0.359375   0.278891   58732800           6   
2   0.367188  0.371094  0.343750  0.347656   0.269797   34777600           6   
3   0.351563  0.359375  0.339844  0.355469   0.275860   18316800           7   
4   0.359375  0.359375  0.347656  0.355469   0.275860   13996800           7   

   WEEKDAY(Date) YEAR(Date)  
id                           
0              4       1992  
1              0       1992  
2              1       1992  
3              2       1992  
4              3       1992  

Система смогла успешно сгенерировать 9 признаков, среди которых температуры открытия, закрытия акций, а также даты с разбивкой по месяцам и дням недели. Это может помочь в анализе сезонных и временных закономерностей, но также требует более глубокого исследования для выявления значимых корреляций

In [29]:
import time
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error

# Разделение данных на обучающую и валидационную выборки. Удаляем целевую переменную
X = feature_matrix.drop('Volume', axis=1)
y = feature_matrix['Volume']

# One-hot encoding для категориальных переменных (преобразование категориальных объектов в числовые)
X = pd.get_dummies(X, drop_first=True)

# Проверяем, есть ли пропущенные значения, и заполняем их медианой или другим подходящим значением
X.fillna(X.median(), inplace=True)

X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.2, random_state=42)

# Обучение модели
model = LinearRegression()

# Начинаем отсчет времени
start_time = time.time()
model.fit(X_train, y_train)

# Время обучения модели
train_time = time.time() - start_time

# Предсказания и оценка модели и вычисляем среднеквадратичную ошибку
predictions = model.predict(X_val)
mse = mean_squared_error(y_val, predictions)

print(f'Время обучения модели: {train_time:.2f} секунд')
print(f'Среднеквадратичная ошибка: {mse:.2f}')
Время обучения модели: 9.94 секунд
Среднеквадратичная ошибка: 66373961335213.34

Время обучения модели составило 9.94 секунд. Это говорит о том, что процесс обучения с использованием линейной регрессии не является очень затратным по времени

Среднеквадратичная ошибка (MSE) равна 66373961335213.34. Это значение является крайне высоким, что сигнализирует о том, что модель требует дополнительной настройки или улучшения.

In [36]:
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.tree import DecisionTreeRegressor
from sklearn.metrics import  r2_score
import matplotlib.pyplot as plt
import seaborn as sns

# Загрузка данных
data = pd.read_csv('.//static//csv//Starbucks Dataset.csv')

# Предварительная обработка
data['Date'] = pd.to_datetime(data['Date'])  # Преобразуем в datetime
data.set_index('Date', inplace=True)

# Отбираем признаки и целевую переменную
features = ['Open', 'High', 'Low', 'Volume']  # Исключаем 'Close' из признаков
target = 'Close'

# Разделение данных на обучающую и тестовую выборки
X = data[features]
y = data[target]
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# Модель линейной регрессии
lin_reg = LinearRegression()
lin_reg.fit(X_train, y_train)
y_pred_lin = lin_reg.predict(X_test)

# Оценка производительности
r2_lin = r2_score(y_test, y_pred_lin)

print("Линейная регрессия:")
print("MSE:", mse_lin)
print("R^2:", r2_lin)

# Модель дерева решений
tree_reg = DecisionTreeRegressor()
tree_reg.fit(X_train, y_train)
y_pred_tree = tree_reg.predict(X_test)

# Оценка производительности
r2_tree = r2_score(y_test, y_pred_tree)

print("\nДерево решений:")
print("MSE:", mse_tree)
print("R^2:", r2_tree)

# Визуализация важности признаков
feature_importance = np.abs(lin_reg.coef_)
features_names = X.columns
importance_df = pd.DataFrame({
    'Feature': features_names,
    'Importance': feature_importance
}).sort_values(by='Importance', ascending=False)

plt.figure(figsize=(10, 6))
sns.barplot(x='Importance', y='Feature', data=importance_df)
plt.title('Важность признаков (Линейная регрессия)')
plt.show()
Линейная регрессия:
MSE: 0.05698523693575633
R^2: 0.999949312678354

Дерево решений:
MSE: 0.1502495406307128
R^2: 0.999866355793138
No description has been provided for this image
In [43]:
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.metrics import  r2_score
import matplotlib.pyplot as plt
import seaborn as sns

# 1. Загрузка данных
data = pd.read_csv('.//static//csv//Starbucks Dataset.csv')

# 2. Предварительная обработка данных
data['Date'] = pd.to_datetime(data['Date'])
data.sort_values('Date', inplace=True)

# 3. Оценка корреляции между признаками и целевой переменной
correlation_matrix = data.corr()
plt.figure(figsize=(10, 8))
sns.heatmap(correlation_matrix, annot=True, fmt='.2f', cmap='coolwarm', square=True)
plt.title('Корреляционная матрица')
plt.show()

# Рассмотрим корреляцию с целевой переменной 'Close'
correlation_with_close = correlation_matrix['Close'].sort_values(ascending=False)
print("Корреляция признаков с 'Close':")
print(correlation_with_close)

# 4. Обучение модели и оценка предсказательной способности
# Выберем признаки для модели: Open, High, Low и Volume
features = data[['Open', 'High', 'Low', 'Volume']]
target = data['Close']

# Разделим данные на обучающую и тестовую выборки
X_train, X_test, y_train, y_test = train_test_split(features, target, test_size=0.2, random_state=42)

# Обучим линейную регрессию
model = LinearRegression()
model.fit(X_train, y_train)

# Предсказание
y_pred = model.predict(X_test)

# Оценка качества
r2 = r2_score(y_test, y_pred)

print("Mean Squared Error:", mse)
print("R^2 Score:", r2)



# Визуализация результатов
plt.figure(figsize=(10, 6))
plt.scatter(y_test, y_pred, alpha=0.5)
plt.plot([y_test.min(), y_test.max()], [y_test.min(), y_test.max()], 'k--', lw=2)
plt.xlabel('Фактическая цена закрытия')
plt.ylabel('Прогнозируемая цена закрытия')
plt.title('Фактическая цена закрытия по сравнению с прогнозируемой')
plt.show()
No description has been provided for this image
Корреляция признаков с 'Close':
Close        1.000000
High         0.999931
Low          0.999930
Open         0.999858
Adj Close    0.997965
Date         0.889680
Volume      -0.319534
Name: Close, dtype: float64
Mean Squared Error: 0.05698523693575633
R^2 Score: 0.999949312678354
No description has been provided for this image

На основании представленных данных о корреляции признаков с целевой переменной 'Close', а также значений Mean Squared Error (MSE), можно сделать несколько важных выводов:

Высокая корреляция признаков

Показатели High, Low, Open и Adj Close имеют крайне высокую положительную корреляцию с целевой переменной Close: High: 0.999931 Low: 0.999930 Open: 0.999858 Adj Close: 0.997965 Это говорит о том, что данные переменные практически линейно зависимы от значения Close. Таким образом, знание значений этих признаков позволяет с высокой степенью уверенности предсказывать значение Close.

Date имеет также значимую корреляцию (0.889680), что может указывать на временную зависимость или тренды в данных по мере их изменений. Volume имеет отрицательную корреляцию (-0.319534) с Close, что может говорить о том, что увеличение объема торгов не всегда приводит к росту цен, хотя эта зависимость слабая.

Эффективность модели Значение Mean Squared Error (MSE) составляет 0.05698523693575633, что указывает на очень низкий уровень ошибок предсказания, подтверждая хорошую точность модели.

Из последнего графика видно, что результаты прогнозируемые и фактические практически совпали. Это говорит о том, что модель будет давать неплохой результат на практике.

На основании проведенного анализа с использованием моделей линейной регрессии и дерева решений на наборе данных Starbucks, можно сделать следующие выводы:

1. Модели и их производительность

Линейная регрессия показала отличные результаты с значениям: MSE (среднеквадратичная ошибка): 0.05698523693575633, что указывает на низкий уровень ошибок предсказания по сравнению с реальными значениями. R² (коэффициент детерминации): 0.999949312678354, что свидетельствует о том, что модель объясняет почти 100% дисперсии целевой переменной, показывая великолепную подгонку данных. Дерево решений также продемонстрировало высокие показатели: MSE: 0.1502495406307128, однако это значение значительно выше, чем у линейной регрессии. R²: 0.999866355793138, что, несмотря на немного менее удачную подгонку по сравнению с линейной регрессией, все еще указывает на очень хорошую соответствие модели данным.

2. Сравнение моделей

Хотя обе модели показали исключительные результаты, линейная регрессия в этом случае оказалась более точной, что можно объяснить ее способностью находить прямые зависимости в данных и меньшей склонностью к переобучению в данном контексте. Деревья решений могут быть полезны для выявления более сложных закономерностей, однако в данной задаче они не продемонстрировали такой же уровень точности.

3. Важность признаков

Результаты визуализации важности признаков, полученные из линейной регрессии, помогают понять, какие из входных переменных (Open, High, Low, Volume) наибольшим образом влияют на целевую переменную (Close). Это может быть полезным для дальнейшего анализа и при принятии бизнес-решений, связанных с управлением и стратегией Starbucks.