AIM-PIbd-31-Ievlewa-M-D/lab3/lab3.ipynb
2024-11-09 11:05:06 +04:00

641 KiB
Raw Blame History

Датасет: Цены на акции

https://www.kaggle.com/datasets/nancyalaswad90/yamana-gold-inc-stock-Volume

О наборе данных:

Yamana Gold Inc. — это канадская компания, которая занимается разработкой и управлением золотыми, серебряными и медными рудниками, расположенными в Канаде, Чили, Бразилии и Аргентине. Головной офис компании находится в Торонто.

Yamana Gold была основана в 1994 году и уже через год была зарегистрирована на фондовой бирже Торонто. В 2007 году она стала участником Нью-Йоркской фондовой биржи, а в 2020 году — Лондонской. В 2003 году компания претерпела значительные изменения: была проведена реструктуризация, в результате которой Питер Марроне занял пост главного исполнительного директора. Кроме того, Yamana объединилась с бразильской компанией Santa Elina Mines Corporation. Благодаря этому слиянию Yamana получила доступ к капиталу, накопленному Santa Elina, что позволило ей начать разработку и эксплуатацию рудника Чапада. Затем компания объединилась с другими организациями, зарегистрированными на бирже TSX: RNC Gold, Desert Sun Mining, Viceroy Exploration, Northern Orion Resources, Meridian Gold, Osisko Mining и Extorre Gold Mines. Каждая из них внесла свой вклад в разработку месторождения или проект, который в итоге был успешно запущен.

Таким образом:
  • Объект наблюдения - цены и объемы акций компании
  • Атрибуты: 'Date', 'Open', 'High', 'Low', 'Close', 'Adj Close', 'Volume'
Бизнес цели:
  • Прогнозирование будущей цены акций. Использование данных для создания модели, которая будет предсказывать цену акций компании в будущем.
  • Определение волатильности акций. Определение, колебаний цен акций, что поможет инвесторам понять риски.
Технические цели:
  • Разработать модель машинного обучения для прогноза цены акций на основе имеющихся данных.
  • Разработать метрику и модель для оценки волатильности акций на основе исторических данных.
In [ ]:
import pandas as pd
df = pd.read_csv(".//static//csv//Stocks.csv", sep=",")
print('Количество колонок: ' + str(df.columns.size))  
print('Колонки: ' + ', '.join(df.columns)+'\n')
df['Date'] = pd.to_datetime(df['Date'], errors='coerce')

df.info()
df.head()
Количество колонок: 7
Колонки: Date, Open, High, Low, Close, Adj Close, Volume

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 5251 entries, 0 to 5250
Data columns (total 7 columns):
 #   Column     Non-Null Count  Dtype         
---  ------     --------------  -----         
 0   Date       5251 non-null   datetime64[ns]
 1   Open       5251 non-null   float64       
 2   High       5251 non-null   float64       
 3   Low        5251 non-null   float64       
 4   Close      5251 non-null   float64       
 5   Adj Close  5251 non-null   float64       
 6   Volume     5251 non-null   int64         
dtypes: datetime64[ns](1), float64(5), int64(1)
memory usage: 287.3 KB
Out[ ]:
Date Open High Low Close Adj Close Volume
0 2001-06-22 3.428571 3.428571 3.428571 3.428571 2.806002 0
1 2001-06-25 3.428571 3.428571 3.428571 3.428571 2.806002 0
2 2001-06-26 3.714286 3.714286 3.714286 3.714286 3.039837 0
3 2001-06-27 3.714286 3.714286 3.714286 3.714286 3.039837 0
4 2001-06-28 3.714286 3.714286 3.714286 3.714286 3.039837 0

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

1. Получение сведений о пропущенных данных

Типы пропущенных данных:

  • None - представление пустых данных в Python
  • NaN - представление пустых данных в Pandas
  • '' - пустая строка
In [ ]:
import numpy as np
# Количество пустых значений признаков
print(df.isnull().sum())
print()

# Есть ли пустые значения признаков
print(df.isnull().any())
print()

# Проверка на бесконечные значения
print("Количество бесконечных значений в каждом столбце:")
print(np.isinf(df).sum())

# Процент пустых значений признаков
for i in df.columns:
    null_rate = df[i].isnull().sum() / len(df) * 100
    print(f"{i} процент пустых значений: %{null_rate:.2f}")
Date         0
Open         0
High         0
Low          0
Close        0
Adj Close    0
Volume       0
dtype: int64

Date         False
Open         False
High         False
Low          False
Close        False
Adj Close    False
Volume       False
dtype: bool

Количество бесконечных значений в каждом столбце:
Date         0
Open         0
High         0
Low          0
Close        0
Adj Close    0
Volume       0
dtype: int64
Date процент пустых значений: %0.00
Open процент пустых значений: %0.00
High процент пустых значений: %0.00
Low процент пустых значений: %0.00
Close процент пустых значений: %0.00
Adj Close процент пустых значений: %0.00
Volume процент пустых значений: %0.00

Таким образом, пропущенных значений не найдено.

2. Проверка выбросов данных и устранение их при наличии:

In [3]:
numeric_columns = ['Open', 'High', 'Low', 'Close', 'Adj Close', 'Volume']

for column in numeric_columns:
    if pd.api.types.is_numeric_dtype(df[column]):  # Проверяем, является ли колонка числовой
        q1 = df[column].quantile(0.25)  # Находим 1-й квартиль (Q1)
        q3 = df[column].quantile(0.75)  # Находим 3-й квартиль (Q3)
        iqr = q3 - q1  # Вычисляем межквартильный размах (IQR)

        # Определяем границы для выбросов
        lower_bound = q1 - 1.5 * iqr  # Нижняя граница
        upper_bound = q3 + 1.5 * iqr  # Верхняя граница

        # Подсчитываем количество выбросов
        outliers = df[(df[column] < lower_bound) | (df[column] > upper_bound)]
        outlier_count = outliers.shape[0]

        print("До устранения выбросов:")
        print(f"Колонка {column}:")
        print(f"  Есть выбросы: {'Да' if outlier_count > 0 else 'Нет'}")
        print(f"  Количество выбросов: {outlier_count}")
        print(f"  Минимальное значение: {df[column].min()}")
        print(f"  Максимальное значение: {df[column].max()}")
        print(f"  1-й квартиль (Q1): {q1}")
        print(f"  3-й квартиль (Q3): {q3}\n")

        # Устраняем выбросы: заменяем значения ниже нижней границы на саму нижнюю границу, а выше верхней — на верхнюю
        if outlier_count != 0:
            df[column] = df[column].apply(lambda x: lower_bound if x < lower_bound else upper_bound if x > upper_bound else x)
        
        # Подсчитываем количество выбросов
        outliers = df[(df[column] < lower_bound) | (df[column] > upper_bound)]
        outlier_count = outliers.shape[0]

        print("После устранения выбросов:")
        print(f"Колонка {column}:")
        print(f"  Есть выбросы: {'Да' if outlier_count > 0 else 'Нет'}")
        print(f"  Количество выбросов: {outlier_count}")
        print(f"  Минимальное значение: {df[column].min()}")
        print(f"  Максимальное значение: {df[column].max()}")
        print(f"  1-й квартиль (Q1): {q1}")
        print(f"  3-й квартиль (Q3): {q3}\n")
До устранения выбросов:
Колонка Open:
  Есть выбросы: Нет
  Количество выбросов: 0
  Минимальное значение: 1.142857
  Максимальное значение: 20.42
  1-й квартиль (Q1): 2.857143
  3-й квартиль (Q3): 10.65

После устранения выбросов:
Колонка Open:
  Есть выбросы: Нет
  Количество выбросов: 0
  Минимальное значение: 1.142857
  Максимальное значение: 20.42
  1-й квартиль (Q1): 2.857143
  3-й квартиль (Q3): 10.65

До устранения выбросов:
Колонка High:
  Есть выбросы: Нет
  Количество выбросов: 0
  Минимальное значение: 1.142857
  Максимальное значение: 20.59
  1-й квартиль (Q1): 2.88
  3-й квартиль (Q3): 10.86

После устранения выбросов:
Колонка High:
  Есть выбросы: Нет
  Количество выбросов: 0
  Минимальное значение: 1.142857
  Максимальное значение: 20.59
  1-й квартиль (Q1): 2.88
  3-й квартиль (Q3): 10.86

До устранения выбросов:
Колонка Low:
  Есть выбросы: Нет
  Количество выбросов: 0
  Минимальное значение: 1.142857
  Максимальное значение: 20.09
  1-й квартиль (Q1): 2.81
  3-й квартиль (Q3): 10.425

После устранения выбросов:
Колонка Low:
  Есть выбросы: Нет
  Количество выбросов: 0
  Минимальное значение: 1.142857
  Максимальное значение: 20.09
  1-й квартиль (Q1): 2.81
  3-й квартиль (Q3): 10.425

До устранения выбросов:
Колонка Close:
  Есть выбросы: Нет
  Количество выбросов: 0
  Минимальное значение: 1.142857
  Максимальное значение: 20.389999
  1-й квартиль (Q1): 2.857143
  3-й квартиль (Q3): 10.64

После устранения выбросов:
Колонка Close:
  Есть выбросы: Нет
  Количество выбросов: 0
  Минимальное значение: 1.142857
  Максимальное значение: 20.389999
  1-й квартиль (Q1): 2.857143
  3-й квартиль (Q3): 10.64

До устранения выбросов:
Колонка Adj Close:
  Есть выбросы: Нет
  Количество выбросов: 0
  Минимальное значение: 0.935334
  Максимальное значение: 17.543156
  1-й квартиль (Q1): 2.537094
  3-й квартиль (Q3): 8.951944999999998

После устранения выбросов:
Колонка Adj Close:
  Есть выбросы: Нет
  Количество выбросов: 0
  Минимальное значение: 0.935334
  Максимальное значение: 17.543156
  1-й квартиль (Q1): 2.537094
  3-й квартиль (Q3): 8.951944999999998

До устранения выбросов:
Колонка Volume:
  Есть выбросы: Да
  Количество выбросов: 95
  Минимальное значение: 0
  Максимальное значение: 76714000
  1-й квартиль (Q1): 2845900.0
  3-й квартиль (Q3): 13272450.0

После устранения выбросов:
Колонка Volume:
  Есть выбросы: Нет
  Количество выбросов: 0
  Минимальное значение: 0.0
  Максимальное значение: 28912275.0
  1-й квартиль (Q1): 2845900.0
  3-й квартиль (Q3): 13272450.0

Выбросы присутствовали, но мы их устранили.

Разбиение на выборки:

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

In [4]:
from sklearn.model_selection import train_test_split

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

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

print("Размер обучающей выборки: ", len(X_train))
print("Размер контрольной выборки: ", len(X_test))
print("Размер тестовой выборки: ", len(X_val))
Размер обучающей выборки:  4200
Размер контрольной выборки:  1051
Размер тестовой выборки:  1051
In [5]:
import seaborn as sns
import matplotlib.pyplot as plt

# Гистограмма распределения цены закрытия в обучающей выборке
plt.figure(figsize=(12, 6))
sns.histplot(X_train['Close'], bins=30, kde=False)
plt.title("Распределение классов (до балансировки)")
plt.xlabel('Целевая переменная: Close')
plt.ylabel('Частота')
plt.show()

# Гистограмма распределения цены закрытия в контрольной выборке
plt.figure(figsize=(12, 6))
sns.histplot(X_val['Close'], bins=30, kde=False)
plt.title("Распределение классов (до балансировки)")
plt.xlabel('Целевая переменная: Close')
plt.ylabel('Частота')
plt.show()

# Гистограмма распределения цены закрытия в тестовой выборке
plt.figure(figsize=(12, 6))
sns.histplot(X_test['Close'], bins=30, kde=False)
plt.title("Распределение классов (до балансировки)")
plt.xlabel('Целевая переменная: Close')
plt.ylabel('Частота')
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 [6]:
from sklearn.model_selection import train_test_split
from imblearn.over_sampling import RandomOverSampler
from imblearn.under_sampling import RandomUnderSampler
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt

# Преобразование целевой переменной (цены) в категориальные диапазоны с использованием квантилей
X_train['closePrice_category'] = pd.qcut(X_train['Close'], q=4, labels=['low', 'medium', 'high', 'very_high'])
print(X_train.head())

# Визуализация распределения цен после преобразования в категории
sns.countplot(x=X_train['closePrice_category'])
plt.title('Распределение категорий закрывающей цены в обучающей выборке')
plt.xlabel('Категория закрывающей цены')
plt.ylabel('Частота')
plt.show()

# Балансировка категорий с помощью RandomOverSampler (увеличение меньшинств)
ros = RandomOverSampler(random_state=42)
y_train = X_train['closePrice_category']
X_train = X_train.drop(columns=['closePrice_category'])


# Применяем oversampling. Здесь важно, что мы используем X_train как DataFrame и y_train_categories как целевую переменную
X_resampled, y_resampled = ros.fit_resample(X_train, y_train)

# Визуализация распределения цен после oversampling
sns.countplot(x=y_resampled)
plt.title('Распределение категорий закрывающей цены после oversampling')
plt.xlabel('Категория закрывающей цены')
plt.ylabel('Частота')
plt.show()

# Применение RandomUnderSampler для уменьшения большего класса
rus = RandomUnderSampler(random_state=42)
X_resampled, y_resampled = rus.fit_resample(X_resampled, y_resampled)

# Визуализация распределения цен после undersampling
sns.countplot(x=y_resampled)
plt.title('Распределение категорий закрывающей цены после undersampling')
plt.xlabel('Категория закрывающей цены')
plt.ylabel('Частота')
plt.show()


print("Размер обучающей выборки до oversampling и undersampling: ", len(X_train))


print("Размер обучающей выборки после oversampling и undersampling: ", len(X_resampled))
X_resampled.head()
           Date   Open   High    Low      Close  Adj Close      Volume  \
4789 2020-07-08   5.66   5.73   5.47   5.560000   5.341250  23355100.0   
3469 2015-04-10   3.86   3.93   3.81   3.880000   3.513961   7605300.0   
2503 2011-06-07  12.19  12.28  11.95  12.020000  10.138681   7243200.0   
1580 2007-10-08  11.77  11.84  11.53  11.570000   9.509553   3025900.0   
2759 2012-06-12  15.77  16.17  15.76  16.120001  13.771020   6113400.0   

     closePrice_category  
4789                high  
3469              medium  
2503           very_high  
1580           very_high  
2759           very_high  
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
Размер обучающей выборки до oversampling и undersampling:  4200
Размер обучающей выборки после oversampling и undersampling:  4232
Out[6]:
Date Open High Low Close Adj Close Volume
0 2020-07-08 5.66 5.73 5.47 5.56 5.341250 23355100.0
20 2021-01-19 5.15 5.15 5.02 5.13 4.966732 15906300.0
21 2010-04-08 10.60 10.65 10.48 10.52 8.794909 10456400.0
24 2020-12-07 5.47 5.80 5.47 5.75 5.541336 12929600.0
28 2021-01-05 6.15 6.16 5.98 6.04 5.847770 15080900.0

По сути, балансировка так то не требовалась, но все же мы ее провели, добавив в обучающую выборку 5 значений (ーー;)

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

  1. Унитарное кодирование категориальных признаков. Преобразование категориальных признаков в бинарные векторы.
  • В данном датасете категориальные признаки отсутствуют, так что пропустим этот пункт.
  1. Дискретизация числовых признаков. Преобразование непрерывных числовых значений в дискретные категории или интервалы (бины).
In [ ]:
#Пример дискретизации по цене закрытия
# Проверка на наличие числовых признаков
print("Названия столбцов в датасете:")
print(df.columns)

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

# Дискретизация столбца 'Close' на группы
bins = [0, 2, 4, 6, 8, 10, 12, 14, 16, 30]  # Определяем границы корзин
labels = ['0-2', '2-4', '4-6', '6-8', '8-10', '10-12', '12-14', '14-16', '16+']  # Названия категорий

# Создание нового столбца 'Close_Disc' на основе дискретизации
df['Close_Disc'] = pd.cut(df['Close'], bins=bins, labels=labels, include_lowest=True) #pd.cut выполняет дискретизацию переменной
#include_lowest=True: Этот параметр гарантирует, что самое нижнее значение (в данном случае 0), будет входить в первую категорию.



# Проверка результата
print("После дискретизации 'Close':")
print(df.head())
n = len(df)
middle_index = n // 2
print(df.iloc[middle_index - 2: middle_index + 3])
print(df.tail())
Названия столбцов в датасете:
Index(['Date', 'Open', 'High', 'Low', 'Close', 'Adj Close', 'Volume'], dtype='object')
Статистические параметры:
                                Date         Open         High          Low  \
count                           5251  5251.000000  5251.000000  5251.000000   
mean   2011-12-01 11:59:51.772995840     6.863639     6.986071     6.720615   
min              2001-06-22 00:00:00     1.142857     1.142857     1.142857   
25%              2006-09-13 12:00:00     2.857143     2.880000     2.810000   
50%              2011-11-29 00:00:00     4.600000     4.710000     4.490000   
75%              2017-02-16 12:00:00    10.650000    10.860000    10.425000   
max              2022-05-05 00:00:00    20.420000    20.590000    20.090000   
std                              NaN     4.753836     4.832010     4.662891   

             Close    Adj Close        Volume  
count  5251.000000  5251.000000  5.251000e+03  
mean      6.850606     5.895644  8.976705e+06  
min       1.142857     0.935334  0.000000e+00  
25%       2.857143     2.537094  2.845900e+06  
50%       4.600000     4.337419  8.216200e+06  
75%      10.640000     8.951945  1.327245e+07  
max      20.389999    17.543156  2.891228e+07  
std       4.746055     3.941634  7.251098e+06  
После дискретизации 'Close':
        Date      Open      High       Low     Close  Adj Close  Volume  \
0 2001-06-22  3.428571  3.428571  3.428571  3.428571   2.806002     0.0   
1 2001-06-25  3.428571  3.428571  3.428571  3.428571   2.806002     0.0   
2 2001-06-26  3.714286  3.714286  3.714286  3.714286   3.039837     0.0   
3 2001-06-27  3.714286  3.714286  3.714286  3.714286   3.039837     0.0   
4 2001-06-28  3.714286  3.714286  3.714286  3.714286   3.039837     0.0   

  Close_Disc  
0        2-4  
1        2-4  
2        2-4  
3        2-4  
4        2-4  
           Date       Open       High    Low      Close  Adj Close     Volume  \
2623 2011-11-25  14.730000  15.050000  14.65  14.650000  12.429751  2433000.0   
2624 2011-11-28  15.150000  15.370000  15.04  15.200000  12.896397  4348600.0   
2625 2011-11-29  15.270000  15.710000  15.21  15.600000  13.235776  4576500.0   
2626 2011-11-30  16.120001  16.850000  16.07  16.830000  14.279361  9537100.0   
2627 2011-12-01  16.770000  16.940001  16.58  16.809999  14.262395  5111500.0   

     Close_Disc  
2623      14-16  
2624      14-16  
2625      14-16  
2626        16+  
2627        16+  
           Date  Open  High   Low  Close  Adj Close      Volume Close_Disc
5246 2022-04-29  5.66  5.69  5.50   5.51       5.51  16613300.0        4-6
5247 2022-05-02  5.33  5.39  5.18   5.30       5.30  27106700.0        4-6
5248 2022-05-03  5.32  5.53  5.32   5.47       5.47  18914200.0        4-6
5249 2022-05-04  5.47  5.61  5.37   5.60       5.60  20530700.0        4-6
5250 2022-05-05  5.63  5.66  5.34   5.44       5.44  19879200.0        4-6

Конструирование новых признаков:

In [ ]:
print('\nИсходный датасет: ')
print(df.tail())
print('\nОбучающая выборка: ')
print(X_resampled.tail())
print('\nТестовая выборка: ')
print(X_test.tail())
print('\nКонтрольная выборка: ')
print(X_val.tail())

#Объем изменений
df['Volume_Change'] = df['Volume'].pct_change()
X_resampled['Volume_Change'] = X_resampled['Volume'].pct_change()
X_test['Volume_Change'] = X_test['Volume'].pct_change()
X_val['Volume_Change'] = X_val['Volume'].pct_change()
# Результатом работы pct_change() является серия, где каждое значение представляет собой 
# процентное изменение относительно предыдущего значения. Первое значение всегда будет NaN, 
# так как для него нет предшествующего значения для сравнения.

# Проверка создания новых признаков
print("\nНовые признаки в обучающей выборке:")
print(X_resampled[['Volume_Change']].tail())

print("\nНовые признаки в тестовой выборке:")
print(X_test[['Volume_Change']].tail())

print("\nНовые признаки в контрольной выборке:")
print(X_val[['Volume_Change']].tail())

print("\nНовые признаки в датасете:")
print(df[['Volume_Change']].tail())
Исходный датасет: 
           Date  Open  High   Low  Close  Adj Close      Volume Close_Disc
5246 2022-04-29  5.66  5.69  5.50   5.51       5.51  16613300.0        4-6
5247 2022-05-02  5.33  5.39  5.18   5.30       5.30  27106700.0        4-6
5248 2022-05-03  5.32  5.53  5.32   5.47       5.47  18914200.0        4-6
5249 2022-05-04  5.47  5.61  5.37   5.60       5.60  20530700.0        4-6
5250 2022-05-05  5.63  5.66  5.34   5.44       5.44  19879200.0        4-6

Обучающая выборка: 
           Date       Open   High        Low      Close  Adj Close      Volume
2435 2011-04-14  12.530000  12.84  12.480000  12.750000  10.754427  10527200.0
1756 2013-05-30  11.510000  11.76  11.480000  11.720000  10.166282   9028100.0
3296 2009-11-20  13.100000  13.28  12.870000  13.220000  11.031483  17024900.0
1243 2012-09-17  18.870001  19.00  18.469999  18.870001  16.178450   6652400.0
343  2006-12-12  12.920000  13.00  12.580000  12.800000  10.487218   3981100.0

Тестовая выборка: 
           Date       Open       High        Low      Close  Adj Close  \
3095 2013-10-14   9.290000   9.350000   9.070000   9.130000   8.025586   
859  2004-11-24   3.090000   3.160000   3.040000   3.100000   2.537094   
3134 2013-12-09   8.550000   8.770000   8.550000   8.770000   7.709136   
2577 2011-09-21  16.709999  17.070000  16.379999  16.400000  13.869872   
378  2002-12-27   2.571429   2.571429   2.571429   2.571429   2.104502   

          Volume  
3095   5861400.0  
859     211300.0  
3134   5335400.0  
2577  14524400.0  
378          0.0  

Контрольная выборка: 
           Date       Open       High        Low      Close  Adj Close  \
3095 2013-10-14   9.290000   9.350000   9.070000   9.130000   8.025586   
859  2004-11-24   3.090000   3.160000   3.040000   3.100000   2.537094   
3134 2013-12-09   8.550000   8.770000   8.550000   8.770000   7.709136   
2577 2011-09-21  16.709999  17.070000  16.379999  16.400000  13.869872   
378  2002-12-27   2.571429   2.571429   2.571429   2.571429   2.104502   

          Volume  
3095   5861400.0  
859     211300.0  
3134   5335400.0  
2577  14524400.0  
378          0.0  

Новые признаки в обучающей выборке:
      Volume_Change
2435       0.977868
1756      -0.142403
3296       0.885768
1243      -0.609255
343       -0.401554

Новые признаки в тестовой выборке:
      Volume_Change
3095            inf
859       -0.963951
3134      24.250355
2577       1.722270
378       -1.000000

Новые признаки в контрольной выборке:
      Volume_Change
3095            inf
859       -0.963951
3134      24.250355
2577       1.722270
378       -1.000000

Новые признаки в датасете:
      Volume_Change
5246      -0.218393
5247       0.631626
5248      -0.302232
5249       0.085465
5250      -0.031733
Проверим новые признаки:
In [9]:
print('\nИсходный датасет: ')
print(df[['Volume_Change']].isnull().sum())
print('\nОбучающая выборка: ')
print(X_resampled[['Volume_Change']].isnull().sum())
print('\nТестовая выборка: ')
print(X_test[['Volume_Change']].isnull().sum())
print('\nКонтрольная выборка: ')
print(X_val[['Volume_Change']].isnull().sum())
print()

# Есть ли пустые значения признаков
print('Есть ли пустые значения признаков: ')
print('\nИсходный датасет: ')
print(df[['Volume_Change']].isnull().any())
print('\nОбучающая выорка: ')
print(X_resampled[['Volume_Change']].isnull().any())
print('\nТестовая выборка: ')
print(X_test[['Volume_Change']].isnull().any())
print('\nКонтрольная выборка: ')
print(X_val[['Volume_Change']].isnull().any())
print()

# Проверка на бесконечные значения
print("Количество бесконечных значений в каждом столбце:")
print('\nИсходный датасет: ')
print(np.isinf(df[['Volume_Change']]).sum())
print('\nОбучающая выборка: ')
print(np.isinf(X_resampled[['Volume_Change']]).sum())
print('\nТестовая выборка: ')
print(np.isinf(X_test[['Volume_Change']]).sum())
print('\nКонтрольная выборка: ')
print(np.isinf(X_val[['Volume_Change']]).sum())

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

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

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

# Процент пустых значений признаков
for i in X_val[['Volume_Change']].columns:
    null_rate = X_val[['Volume_Change']][i].isnull().sum() / len(X_val[['Volume_Change']]) * 100
    print(f"{i} процент пустых значений в контрольной выборке: %{null_rate:.2f}")
Исходный датасет: 
Volume_Change    501
dtype: int64

Обучающая выборка: 
Volume_Change    102
dtype: int64

Тестовая выборка: 
Volume_Change    16
dtype: int64

Контрольная выборка: 
Volume_Change    16
dtype: int64

Есть ли пустые значения признаков: 

Исходный датасет: 
Volume_Change    True
dtype: bool

Обучающая выорка: 
Volume_Change    True
dtype: bool

Тестовая выборка: 
Volume_Change    True
dtype: bool

Контрольная выборка: 
Volume_Change    True
dtype: bool

Количество бесконечных значений в каждом столбце:

Исходный датасет: 
Volume_Change    32
dtype: int64

Обучающая выборка: 
Volume_Change    310
dtype: int64

Тестовая выборка: 
Volume_Change    107
dtype: int64

Контрольная выборка: 
Volume_Change    107
dtype: int64
Volume_Change процент пустых значений в датасете: %9.54
Volume_Change процент пустых значений в обучающей выборке: %2.41
Volume_Change процент пустых значений в тестовой выборке: %1.52
Volume_Change процент пустых значений в контрольной выборке: %1.52

Заполним пустые данные

In [ ]:
# Заменяем бесконечные значения на NaN
df.replace([np.inf, -np.inf], np.nan, inplace=True)
X_resampled.replace([np.inf, -np.inf], np.nan, inplace=True)
X_test.replace([np.inf, -np.inf], np.nan, inplace=True)
X_val.replace([np.inf, -np.inf], np.nan, inplace=True)

fillna_df = df[['Volume_Change']].fillna(0)
fillna_X_resampled = X_resampled[['Volume_Change']].fillna(0)
fillna_X_test = X_test[['Volume_Change']].fillna(0)
fillna_X_val = X_val[['Volume_Change']].fillna(0)
# используется для заполнения всех значений NaN 
# (Not a Number) в DataFrame или Series указанным значением. 
# В данном случае, fillna(0) заполняет все ячейки, содержащие NaN, значением 0.


print(fillna_df.shape)
print(fillna_X_resampled.shape)
print(fillna_X_test.shape)
print(fillna_X_val.shape)

print(fillna_df.isnull().any())
print(fillna_X_resampled.isnull().any())
print(fillna_X_test.isnull().any())
print(fillna_X_val.isnull().any())

# Замена пустых данных на 0
df["Volume_Change"] = df["Volume_Change"].fillna(0)
X_resampled["Volume_Change"] = X_resampled["Volume_Change"].fillna(0)
X_test["Volume_Change"] = X_test["Volume_Change"].fillna(0)
X_val["Volume_Change"] = X_val["Volume_Change"].fillna(0)

# Вычисляем медиану для колонки "Volume_Change"
median_Volume_Change_df = df["Volume_Change"].median()
median_Volume_Change_train = X_resampled["Volume_Change"].median()
median_Volume_Change_test = X_test["Volume_Change"].median()
median_Volume_Change_val = X_val["Volume_Change"].median()

# Заменяем значения 0 на медиану
df[['Volume_Change']].loc[df["Volume_Change"] == 0, "Volume_Change"] = median_Volume_Change_df
X_resampled[['Volume_Change']].loc[X_resampled["Volume_Change"] == 0, "Volume_Change"] = median_Volume_Change_train
X_test[['Volume_Change']].loc[X_test["Volume_Change"] == 0, "Volume_Change"] = median_Volume_Change_test
X_val[['Volume_Change']].loc[X_val["Volume_Change"] == 0, "Volume_Change"] = median_Volume_Change_val

print(df[['Volume_Change']].tail())
print(X_resampled[['Volume_Change']].tail())
print(X_test[['Volume_Change']].tail())
print(X_val[['Volume_Change']].tail())
(5251, 1)
(4232, 1)
(1051, 1)
(1051, 1)
Volume_Change    False
dtype: bool
Volume_Change    False
dtype: bool
Volume_Change    False
dtype: bool
Volume_Change    False
dtype: bool
      Volume_Change
5246      -0.218393
5247       0.631626
5248      -0.302232
5249       0.085465
5250      -0.031733
      Volume_Change
2435       0.977868
1756      -0.142403
3296       0.885768
1243      -0.609255
343       -0.401554
      Volume_Change
3095       0.000000
859       -0.963951
3134      24.250355
2577       1.722270
378       -1.000000
      Volume_Change
3095       0.000000
859       -0.963951
3134      24.250355
2577       1.722270
378       -1.000000
C:\Users\K\AppData\Local\Temp\ipykernel_1752\2904461267.py:36: FutureWarning: ChainedAssignmentError: behaviour will change in pandas 3.0!
You are setting values through chained assignment. Currently this works in certain cases, but when using Copy-on-Write (which will become the default behaviour in pandas 3.0) this will never work to update the original DataFrame or Series, because the intermediate object on which we are setting values will behave as a copy.
A typical example is when you are setting values in a column of a DataFrame, like:

df["col"][row_indexer] = value

Use `df.loc[row_indexer, "col"] = values` instead, to perform the assignment in a single step and ensure this keeps updating the original `df`.

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy

  df[['Volume_Change']].loc[df["Volume_Change"] == 0, "Volume_Change"] = median_Volume_Change_df
C:\Users\K\AppData\Local\Temp\ipykernel_1752\2904461267.py:36: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
  df[['Volume_Change']].loc[df["Volume_Change"] == 0, "Volume_Change"] = median_Volume_Change_df
C:\Users\K\AppData\Local\Temp\ipykernel_1752\2904461267.py:37: FutureWarning: ChainedAssignmentError: behaviour will change in pandas 3.0!
You are setting values through chained assignment. Currently this works in certain cases, but when using Copy-on-Write (which will become the default behaviour in pandas 3.0) this will never work to update the original DataFrame or Series, because the intermediate object on which we are setting values will behave as a copy.
A typical example is when you are setting values in a column of a DataFrame, like:

df["col"][row_indexer] = value

Use `df.loc[row_indexer, "col"] = values` instead, to perform the assignment in a single step and ensure this keeps updating the original `df`.

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy

  X_resampled[['Volume_Change']].loc[X_resampled["Volume_Change"] == 0, "Volume_Change"] = median_Volume_Change_train
C:\Users\K\AppData\Local\Temp\ipykernel_1752\2904461267.py:37: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
  X_resampled[['Volume_Change']].loc[X_resampled["Volume_Change"] == 0, "Volume_Change"] = median_Volume_Change_train
C:\Users\K\AppData\Local\Temp\ipykernel_1752\2904461267.py:38: FutureWarning: ChainedAssignmentError: behaviour will change in pandas 3.0!
You are setting values through chained assignment. Currently this works in certain cases, but when using Copy-on-Write (which will become the default behaviour in pandas 3.0) this will never work to update the original DataFrame or Series, because the intermediate object on which we are setting values will behave as a copy.
A typical example is when you are setting values in a column of a DataFrame, like:

df["col"][row_indexer] = value

Use `df.loc[row_indexer, "col"] = values` instead, to perform the assignment in a single step and ensure this keeps updating the original `df`.

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy

  X_test[['Volume_Change']].loc[X_test["Volume_Change"] == 0, "Volume_Change"] = median_Volume_Change_test
C:\Users\K\AppData\Local\Temp\ipykernel_1752\2904461267.py:38: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
  X_test[['Volume_Change']].loc[X_test["Volume_Change"] == 0, "Volume_Change"] = median_Volume_Change_test
C:\Users\K\AppData\Local\Temp\ipykernel_1752\2904461267.py:39: FutureWarning: ChainedAssignmentError: behaviour will change in pandas 3.0!
You are setting values through chained assignment. Currently this works in certain cases, but when using Copy-on-Write (which will become the default behaviour in pandas 3.0) this will never work to update the original DataFrame or Series, because the intermediate object on which we are setting values will behave as a copy.
A typical example is when you are setting values in a column of a DataFrame, like:

df["col"][row_indexer] = value

Use `df.loc[row_indexer, "col"] = values` instead, to perform the assignment in a single step and ensure this keeps updating the original `df`.

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy

  X_val[['Volume_Change']].loc[X_val["Volume_Change"] == 0, "Volume_Change"] = median_Volume_Change_val
C:\Users\K\AppData\Local\Temp\ipykernel_1752\2904461267.py:39: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
  X_val[['Volume_Change']].loc[X_val["Volume_Change"] == 0, "Volume_Change"] = median_Volume_Change_val

Удалим наблюдения с пропусками

In [11]:
dropna_df = df[['Volume_Change']].dropna()
dropna_X_resampled = X_resampled[['Volume_Change']].dropna()
dropna_X_test = X_test[['Volume_Change']].dropna()
dropna_X_val = X_val[['Volume_Change']].dropna()

print(dropna_df.shape)
print(dropna_X_resampled.shape)
print(dropna_X_test.shape)
print(dropna_X_val.shape)

print(dropna_df.isnull().any())
print(df[['Volume_Change']].tail())
print(dropna_X_resampled.isnull().any())
print(X_resampled[['Volume_Change']].tail())
print(dropna_X_test.isnull().any())
print(X_test[['Volume_Change']].tail())
print(dropna_X_val.isnull().any())
print(X_val[['Volume_Change']].tail())
(5251, 1)
(4232, 1)
(1051, 1)
(1051, 1)
Volume_Change    False
dtype: bool
      Volume_Change
5246      -0.218393
5247       0.631626
5248      -0.302232
5249       0.085465
5250      -0.031733
Volume_Change    False
dtype: bool
      Volume_Change
2435       0.977868
1756      -0.142403
3296       0.885768
1243      -0.609255
343       -0.401554
Volume_Change    False
dtype: bool
      Volume_Change
3095       0.000000
859       -0.963951
3134      24.250355
2577       1.722270
378       -1.000000
Volume_Change    False
dtype: bool
      Volume_Change
3095       0.000000
859       -0.963951
3134      24.250355
2577       1.722270
378       -1.000000
Масштабируем новые признаки:
In [ ]:
from sklearn.preprocessing import StandardScaler, MinMaxScaler

# Пример масштабирования числовых признаков
numerical_features = ['Volume_Change']

scaler = StandardScaler()
df[numerical_features] = scaler.fit_transform(df[numerical_features])
X_resampled[numerical_features] = scaler.fit_transform(X_resampled[numerical_features])
X_val[numerical_features] = scaler.transform(X_val[numerical_features])
X_test[numerical_features] = scaler.transform(X_test[numerical_features])
#  fit() - вычисляет среднее и стандартное отклонение для каждого признака в наборе данных.
# transform() - применяет расчеты, чтобы стандартизировать данные по приведенной выше формуле.

# Вывод результатов после масштабирования
print("Результаты после масштабирования:")
print("\n Датафрейм:")
print(df[numerical_features].tail())
print("\n Обучающая:")
print(X_resampled[numerical_features].tail())
print("\n Тестовая:")
print(X_val[numerical_features].tail())
print("\n Контрольная:")
print(X_test[numerical_features].tail())
Результаты после масштабирования:

 Датафрейм:
      Volume_Change
5246      -0.176620
5247       0.224373
5248      -0.216171
5249      -0.033276
5250      -0.088564

 Обучающая:
      Volume_Change
2435      -0.033736
1756      -0.033805
3296      -0.033742
1243      -0.033834
343       -0.033821

 Тестовая:
      Volume_Change
3095      -0.033796
859       -0.033856
3134      -0.032301
2577      -0.033690
378       -0.033858

 Контрольная:
      Volume_Change
3095      -0.033796
859       -0.033856
3134      -0.032301
2577      -0.033690
378       -0.033858

Данные признаки предоставляют важную информацию о текущем тренде и возможных изменениях в будущих ценах. Положительные значения Price_Change и Percentage_Change, наряду с высоким Volume_Change, могут поддерживать гипотезу о росте цен на акции.

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

Применим featuretools для конструирования признаков:

In [ ]:
import featuretools as ft

df['id'] = df.index 
X_resampled['id'] = X_resampled.index
X_val['id'] = X_val.index
X_test['id'] = X_test.index
 # Добавляем уникальный идентификатор
# Предобработка данных (например, кодирование категориальных признаков, удаление дубликатов)
# Удаление дубликатов по идентификатору
df = df.drop_duplicates(subset='id')
duplicates = X_resampled[X_resampled['id'].duplicated(keep=False)]

# Удаление дубликатов из столбца "id", сохранив первое вхождение
df = df.drop_duplicates(subset='id', keep='first')

print(duplicates)


# Создание EntitySet
es = ft.EntitySet(id='stock_data')

# Добавление датафрейма с акциями
es = es.add_dataframe(dataframe_name='stocks', dataframe=df, index='id')

# Генерация признаков с помощью глубокой синтезы признаков
feature_matrix, feature_defs = ft.dfs(entityset=es, target_dataframe_name='stocks', max_depth=2)

# Выводим первые 5 строк сгенерированного набора признаков
print(feature_matrix.head())

X_resampled = X_resampled.drop_duplicates(subset='id')
X_resampled = X_resampled.drop_duplicates(subset='id', keep='first')  # or keep='last'

# Определение сущностей (Создание EntitySet)
es = ft.EntitySet(id='stock_data')

es = es.add_dataframe(dataframe_name='stocks', dataframe=X_resampled, index='id')

# Генерация признаков
feature_matrix, feature_defs = ft.dfs(entityset=es, target_dataframe_name='stocks', max_depth=2)
# Она автоматически генерирует новые признаки из исходного датафрейма и производит агрегацию по связям.

# Преобразование признаков для контрольной и тестовой выборок
val_feature_matrix = ft.calculate_feature_matrix(features=feature_defs, entityset=es, instance_ids=X_val.index)
test_feature_matrix = ft.calculate_feature_matrix(features=feature_defs, entityset=es, instance_ids=X_test.index)
#генерирует матрицы признаков для контрольной и тестовой выборок, используя идентификаторы экземпляров из X_val.index и X_test.index соответственно.

print(feature_matrix.head())
Empty DataFrame
Columns: [Date, Open, High, Low, Close, Adj Close, Volume, Volume_Change, id]
Index: []
        Open      High       Low     Close  Adj Close  Volume Close_Disc  \
id                                                                         
0   3.428571  3.428571  3.428571  3.428571   2.806002     0.0        2-4   
1   3.428571  3.428571  3.428571  3.428571   2.806002     0.0        2-4   
2   3.714286  3.714286  3.714286  3.714286   3.039837     0.0        2-4   
3   3.714286  3.714286  3.714286  3.714286   3.039837     0.0        2-4   
4   3.714286  3.714286  3.714286  3.714286   3.039837     0.0        2-4   

    Volume_Change DAY(Date) MONTH(Date) WEEKDAY(Date) YEAR(Date)  
id                                                                
0       -0.073594        22           6             4       2001  
1       -0.073594        25           6             0       2001  
2       -0.073594        26           6             1       2001  
3       -0.073594        27           6             2       2001  
4       -0.073594        28           6             3       2001  
c:\Users\K\source\repos\AIM-PIbd-31-Ievlewa-M-D\aimenv\Lib\site-packages\woodwork\type_sys\utils.py:33: UserWarning: Could not infer format, so each element will be parsed individually, falling back to `dateutil`. To ensure parsing is consistent and as-expected, please specify a format.
  pd.to_datetime(
c:\Users\K\source\repos\AIM-PIbd-31-Ievlewa-M-D\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\K\source\repos\AIM-PIbd-31-Ievlewa-M-D\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(
     Open   High    Low  Close  Adj Close      Volume  Volume_Change  \
id                                                                     
0    5.66   5.73   5.47   5.56   5.341250  23355100.0      -0.033796   
20   5.15   5.15   5.02   5.13   4.966732  15906300.0      -0.033816   
21  10.60  10.65  10.48  10.52   8.794909  10456400.0      -0.033817   
24   5.47   5.80   5.47   5.75   5.541336  12929600.0      -0.033782   
28   6.15   6.16   5.98   6.04   5.847770  15080900.0      -0.033786   

   DAY(Date) MONTH(Date) WEEKDAY(Date) YEAR(Date)  
id                                                 
0          8           7             2       2020  
20        19           1             1       2021  
21         8           4             3       2010  
24         7          12             0       2020  
28         5           1             1       2021  
c:\Users\K\source\repos\AIM-PIbd-31-Ievlewa-M-D\aimenv\Lib\site-packages\featuretools\computational_backends\feature_set_calculator.py:143: FutureWarning: The behavior of DataFrame concatenation with empty or all-NA entries is deprecated. In a future version, this will no longer exclude empty or all-NA columns when determining the result dtypes. To retain the old behavior, exclude the relevant entries before the concat operation.
  df = pd.concat([df, default_df], sort=True)
c:\Users\K\source\repos\AIM-PIbd-31-Ievlewa-M-D\aimenv\Lib\site-packages\featuretools\computational_backends\feature_set_calculator.py:143: FutureWarning: The behavior of DataFrame concatenation with empty or all-NA entries is deprecated. In a future version, this will no longer exclude empty or all-NA columns when determining the result dtypes. To retain the old behavior, exclude the relevant entries before the concat operation.
  df = pd.concat([df, default_df], sort=True)

Система сгенерировала следующие признаки:

  1. Open, High, Low, Close, Adj Close: Это стандартные финансовые параметры акций, отражающие цены открытия, максимальные, минимальные и закрытия за определенный период. Volume: Объем торгов акциями, который показывает, сколько акций было куплено/продано за определенный период.

  2. Сложные признаки: Close_Disc: Это диапазон цены закрытия. Price_Change: Изменение цены, т.е. разница между ценой закрытия и ценой открытия акций. Percentage_Change: Процентное изменение цен, которое позволяет оценить относительное изменение стоимости акций. Average_Price: Средняя цена акций за указанный период. Этот показатель может быть использован для оценки общей тенденции рынка.

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

Оценим качество каждого набора признаков:

In [ ]:
import time
from sklearn.model_selection import train_test_split
from sklearn.metrics import r2_score, mean_absolute_error
from sklearn.linear_model import LinearRegression
from sklearn.tree import DecisionTreeRegressor
from sklearn.ensemble import RandomForestRegressor
from sklearn.linear_model import Lasso
from sklearn.linear_model import Ridge
from sklearn.metrics import mean_squared_error
from sklearn.model_selection import cross_val_score

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

# Удаление строк с NaN
feature_matrix = feature_matrix.dropna()
val_feature_matrix = val_feature_matrix.dropna()
test_feature_matrix = test_feature_matrix.dropna()

feature_matrix = pd.get_dummies(feature_matrix, drop_first=True)
val_feature_matrix = pd.get_dummies(val_feature_matrix, drop_first=True)
test_feature_matrix = pd.get_dummies(test_feature_matrix, drop_first=True)

feature_matrix.fillna(feature_matrix.median(), inplace=True)
val_feature_matrix.fillna(val_feature_matrix.median(), inplace=True)
test_feature_matrix.fillna(test_feature_matrix.median(), inplace=True)

# Разделение данных на обучающую и тестовую выборки
y_train = feature_matrix['Close']
X_train = feature_matrix.drop('Close', axis=1)
y_test = test_feature_matrix['Close']
X_test = test_feature_matrix.drop('Close', axis=1)

# Обучение модели
model1 = LinearRegression()
#Линейная регрессия — это простая модель, которая пытается установить связь между двумя переменными, рисуя прямую линию на графике. 
# Она прогнозирует значение зависимой переменной (Y) на основе одной или нескольких независимых переменных (X).
model2 = DecisionTreeRegressor()
#Это модель, которая принимает решения, дробя данные на «ветви», как дерево. На каждом уровне дерева модель выбирает, 
# какой признак (фактор) использовать для разделения данных.
model3 = RandomForestRegressor(n_estimators=100) 
#Случайный лес — это ансамблевая модель, которая использует множество деревьев решений. 
# Вместо того чтобы полагаться на одно дерево, она комбинирует результаты нескольких деревьев, чтобы получить более точные предсказания.
model4 = Lasso(alpha=0.1)
#Lasso регрессия — это разновидность линейной регрессии с добавлением регуляризации. 
# Она помогает избежать переобучения модели, уменьшая влияние некоторых признаков.
model5 = Ridge(alpha=0.1)
#Ridge регрессия похожа на Lasso, но вместо полного исключения некоторых переменных она уменьшает значения всех коэффициентов.

print('\nLinearRegression:')
start_time = time.time()
model1.fit(X_train, y_train)
#Метод fit обучает модель на обучающем наборе данных, состоящем из X_train (набор данных) и y_train (целевая переменная).

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

y_predict = model1.predict(X_test)

mse = mean_squared_error(y_test, y_predict, squared=False)
# Этот показатель показывает, насколько в среднем наши предсказания отклоняются от фактических значений. Чем меньше RMSE, тем лучше модель.
r2 = r2_score(y_test, y_predict)
# Коффициент детерминации - показывает, насколько модель объясняет разброс значений в наборе данных
mae = mean_absolute_error(y_test, y_predict)
# Измеряет среднее расстояние между предсказанными значениями и фактическими значениями, игнорируя направление ошибок.
print(f'Коэффициент детерминации R²: {r2:.2f}')
print(f'Время обучения модели: {train_time:.2f} секунд')
print(f'Среднеквадратичная ошибка: {mse:.2f}')
print(f'Средняя абсолютная ошибка: {mae:.2f}')
# Кросс-валидация
scores = cross_val_score(model1, X_train, y_train, cv=5, scoring='neg_mean_squared_error')
rmse_cv = (-scores.mean())**0.5
print(f"Кросс-валидация RMSE: {rmse_cv} \n")
# Здесь мы используем метод cross_val_score для оценки модели с помощью кросс-валидации. 
# cv=5 означает, что мы будем разбивать наш обучающий набор на 5 частей (фолдов) и 
# использовать каждую часть для тестирования модели, обученной на остальных частях. 
# (по сути разбивка на выборки но несколько раз с использованием разных разбиений, чтобы получить норм оценку)

# Параметр scoring='neg_mean_squared_error' говорит о том, что мы хотим получать отрицательные значения среднеквадратичной ошибки, 
# так как cross_val_score возвращает лучшие результаты как положительные значения. Таким образом, использование отрицательного 
# значения MSE позволяет "перевернуть" метрику так, чтобы более низкие значения (более точные предсказания) приводили 
# к более высоким (в терминах абсолютного значения) результатам.

# После этого мы берем среднее значение отрицательной MSE и берем его корень (RMSE) 
# для получения усредненной оценки ошибки модели через кросс-валидацию.


# Визуализация результатов
plt.figure(figsize=(10, 6))
plt.scatter(y_test, y_predict, 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()

#//////////////////////////

print('\nDecisionTreeRegressor:')
start_time = time.time()
model2.fit(X_train, y_train)

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

y_predict = model2.predict(X_test)

mse = mean_squared_error(y_test, y_predict, squared=False)
r2 = r2_score(y_test, y_predict)
mae = mean_absolute_error(y_test, y_predict)
print(f'Коэффициент детерминации R²: {r2:.2f}')
print(f'Время обучения модели: {train_time:.2f} секунд')
print(f'Среднеквадратичная ошибка: {mse:.2f}')
print(f'Средняя абсолютная ошибка: {mae:.2f}')
# Кросс-валидация
scores = cross_val_score(model2, X_train, y_train, cv=5, scoring='neg_mean_squared_error')
rmse_cv = (-scores.mean())**0.5
print(f"Кросс-валидация RMSE: {rmse_cv} \n")

# Анализ важности признаков
feature_importances = model2.feature_importances_
feature_names = X_train.columns
# Визуализация результатов
plt.figure(figsize=(10, 6))
plt.scatter(y_test, y_predict, 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()

#//////////////////////////

print('\nRandomForestRegressor:')
start_time = time.time()
model3.fit(X_train, y_train)

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

y_predict = model3.predict(X_test)

mse = mean_squared_error(y_test, y_predict, squared=False)
r2 = r2_score(y_test, y_predict)
mae = mean_absolute_error(y_test, y_predict)
print(f'Коэффициент детерминации R²: {r2:.2f}')
print(f'Время обучения модели: {train_time:.2f} секунд')
print(f'Среднеквадратичная ошибка: {mse:.2f}')
print(f'Средняя абсолютная ошибка: {mae:.2f}')
# Кросс-валидация
scores = cross_val_score(model3, X_train, y_train, cv=5, scoring='neg_mean_squared_error')
rmse_cv = (-scores.mean())**0.5
print(f"Кросс-валидация RMSE: {rmse_cv} \n")

# Анализ важности признаков
feature_importances = model3.feature_importances_
feature_names = X_train.columns
# Визуализация результатов
plt.figure(figsize=(10, 6))
plt.scatter(y_test, y_predict, 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()

#//////////////////////////

print('\nLasso:')
start_time = time.time()
model4.fit(X_train, y_train)

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

y_predict = model4.predict(X_test)

mse = mean_squared_error(y_test, y_predict, squared=False)
r2 = r2_score(y_test, y_predict)
mae = mean_absolute_error(y_test, y_predict)
print(f'Коэффициент детерминации R²: {r2:.2f}')
print(f'Время обучения модели: {train_time:.2f} секунд')
print(f'Среднеквадратичная ошибка: {mse:.2f}')
print(f'Средняя абсолютная ошибка: {mae:.2f}')
# Кросс-валидация
scores = cross_val_score(model4, X_train, y_train, cv=5, scoring='neg_mean_squared_error')
rmse_cv = (-scores.mean())**0.5
print(f"Кросс-валидация RMSE: {rmse_cv} \n")

# Визуализация результатов
plt.figure(figsize=(10, 6))
plt.scatter(y_test, y_predict, 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()

#//////////////////////////

print('\nRidge:')
start_time = time.time()
model5.fit(X_train, y_train)

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

y_predict = model5.predict(X_test)
print(y_predict)
print(y_test.head())

mse = mean_squared_error(y_test, y_predict, squared=False)
r2 = r2_score(y_test, y_predict)
mae = mean_absolute_error(y_test, y_predict)
print(f'Коэффициент детерминации R²: {r2:.2f}')
print(f'Время обучения модели: {train_time:.2f} секунд')
print(f'Среднеквадратичная ошибка: {mse:.2f}')
print(f'Средняя абсолютная ошибка: {mae:.2f}')
# Кросс-валидация
scores = cross_val_score(model5, X_train, y_train, cv=5, scoring='neg_mean_squared_error')
rmse_cv = (-scores.mean())**0.5
print(f"Кросс-валидация RMSE: {rmse_cv} \n")

# Визуализация результатов
plt.figure(figsize=(10, 6))
plt.scatter(y_test, y_predict, 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()
LinearRegression:
c:\Users\K\source\repos\AIM-PIbd-31-Ievlewa-M-D\aimenv\Lib\site-packages\sklearn\metrics\_regression.py:492: FutureWarning: 'squared' is deprecated in version 1.4 and will be removed in 1.6. To calculate the root mean squared error, use the function'root_mean_squared_error'.
  warnings.warn(
Коэффициент детерминации R²: 1.00
Время обучения модели: 56.77 секунд
Среднеквадратичная ошибка: 0.05
Средняя абсолютная ошибка: 0.04
Кросс-валидация RMSE: 0.06955321972025767 

No description has been provided for this image
DecisionTreeRegressor:
c:\Users\K\source\repos\AIM-PIbd-31-Ievlewa-M-D\aimenv\Lib\site-packages\sklearn\metrics\_regression.py:492: FutureWarning: 'squared' is deprecated in version 1.4 and will be removed in 1.6. To calculate the root mean squared error, use the function'root_mean_squared_error'.
  warnings.warn(
Коэффициент детерминации R²: 1.00
Время обучения модели: 0.31 секунд
Среднеквадратичная ошибка: 0.00
Средняя абсолютная ошибка: 0.00
Кросс-валидация RMSE: 0.15865311270509808 

No description has been provided for this image
RandomForestRegressor:
c:\Users\K\source\repos\AIM-PIbd-31-Ievlewa-M-D\aimenv\Lib\site-packages\sklearn\metrics\_regression.py:492: FutureWarning: 'squared' is deprecated in version 1.4 and will be removed in 1.6. To calculate the root mean squared error, use the function'root_mean_squared_error'.
  warnings.warn(
Коэффициент детерминации R²: 1.00
Время обучения модели: 14.12 секунд
Среднеквадратичная ошибка: 0.03
Средняя абсолютная ошибка: 0.02
Кросс-валидация RMSE: 0.12050880197633333 

No description has been provided for this image
Lasso:
c:\Users\K\source\repos\AIM-PIbd-31-Ievlewa-M-D\aimenv\Lib\site-packages\sklearn\linear_model\_coordinate_descent.py:697: ConvergenceWarning: Objective did not converge. You might want to increase the number of iterations, check the scale of the features or consider increasing regularisation. Duality gap: 2.444e+01, tolerance: 9.545e+00
  model = cd_fast.enet_coordinate_descent(
c:\Users\K\source\repos\AIM-PIbd-31-Ievlewa-M-D\aimenv\Lib\site-packages\sklearn\metrics\_regression.py:492: FutureWarning: 'squared' is deprecated in version 1.4 and will be removed in 1.6. To calculate the root mean squared error, use the function'root_mean_squared_error'.
  warnings.warn(
Коэффициент детерминации R²: 1.00
Время обучения модели: 0.64 секунд
Среднеквадратичная ошибка: 0.15
Средняя абсолютная ошибка: 0.10
c:\Users\K\source\repos\AIM-PIbd-31-Ievlewa-M-D\aimenv\Lib\site-packages\sklearn\linear_model\_coordinate_descent.py:697: ConvergenceWarning: Objective did not converge. You might want to increase the number of iterations, check the scale of the features or consider increasing regularisation. Duality gap: 2.330e+01, tolerance: 9.123e+00
  model = cd_fast.enet_coordinate_descent(
c:\Users\K\source\repos\AIM-PIbd-31-Ievlewa-M-D\aimenv\Lib\site-packages\sklearn\linear_model\_coordinate_descent.py:697: ConvergenceWarning: Objective did not converge. You might want to increase the number of iterations, check the scale of the features or consider increasing regularisation. Duality gap: 1.844e+01, tolerance: 7.834e+00
  model = cd_fast.enet_coordinate_descent(
c:\Users\K\source\repos\AIM-PIbd-31-Ievlewa-M-D\aimenv\Lib\site-packages\sklearn\linear_model\_coordinate_descent.py:697: ConvergenceWarning: Objective did not converge. You might want to increase the number of iterations, check the scale of the features or consider increasing regularisation. Duality gap: 1.789e+01, tolerance: 7.848e+00
  model = cd_fast.enet_coordinate_descent(
c:\Users\K\source\repos\AIM-PIbd-31-Ievlewa-M-D\aimenv\Lib\site-packages\sklearn\linear_model\_coordinate_descent.py:697: ConvergenceWarning: Objective did not converge. You might want to increase the number of iterations, check the scale of the features or consider increasing regularisation. Duality gap: 1.893e+01, tolerance: 7.706e+00
  model = cd_fast.enet_coordinate_descent(
Кросс-валидация RMSE: 0.14816158181157554 

c:\Users\K\source\repos\AIM-PIbd-31-Ievlewa-M-D\aimenv\Lib\site-packages\sklearn\linear_model\_coordinate_descent.py:697: ConvergenceWarning: Objective did not converge. You might want to increase the number of iterations, check the scale of the features or consider increasing regularisation. Duality gap: 8.478e+00, tolerance: 4.075e+00
  model = cd_fast.enet_coordinate_descent(
No description has been provided for this image
Ridge:
c:\Users\K\source\repos\AIM-PIbd-31-Ievlewa-M-D\aimenv\Lib\site-packages\sklearn\linear_model\_ridge.py:216: LinAlgWarning: Ill-conditioned matrix (rcond=4.52541e-19): result may not be accurate.
  return linalg.solve(A, Xy, assume_a="pos", overwrite_a=True).T
c:\Users\K\source\repos\AIM-PIbd-31-Ievlewa-M-D\aimenv\Lib\site-packages\sklearn\metrics\_regression.py:492: FutureWarning: 'squared' is deprecated in version 1.4 and will be removed in 1.6. To calculate the root mean squared error, use the function'root_mean_squared_error'.
  warnings.warn(
[18.53835972  3.02015664 12.61628667  2.90463617 15.50833261  3.52896844
  4.48748051  4.63958216  8.68196839  1.74873254  9.20514286  8.47989483
  2.58190809 17.08764245  8.55417677 15.33708822 16.41262996  2.58698205
 14.3010449  12.34692824  9.25519508 12.41656262 11.99359427  5.66512081
  2.38719333 12.26227744  6.05023814  2.66589584  2.70345542  5.964079
  6.22816714 10.34137019 11.51700786  5.58517202  8.65205276  2.3460804
  4.26479846  5.33712394  1.14710216  1.71608533 16.32955154 15.43209408
  2.87442811  2.34765255  5.63198832  1.80827126 11.16627919  9.49829252
  3.06416135  8.63872529 16.20075921  9.22693767 11.59973333  2.96131937
  5.38377786  2.03008836 11.00039614 15.61757236  9.16666362  8.41083742
  2.00373929  2.06287786  2.99954165  4.10065289  4.00877304  3.97321885
 13.59597539  1.40790586  2.41256628  6.39209759  2.81312245  3.10132338
 15.42511366  5.94643324  9.61579166 10.56492684  1.71759088 18.88228792
  8.05540212  3.56264735  3.82692764 12.38823319  6.05270239 12.00332481
  1.74086769  5.89288081  2.26264139  3.71532583  6.35786331 11.23384554
  5.45126529  2.94152123  1.46216163 12.4333095   1.94823683  2.61723697
  4.29052409  2.85243147  4.34693161  7.75903026  1.47957735  2.64745738
  2.92764333  3.92477508  1.46188826  6.73850242 10.12033775 12.36907916
  5.78680952  8.88212259  2.6207355   2.91355609  1.7150175   3.87183976
 10.38956052  2.10033845  9.7789235   5.9518523   6.72768585  3.8733813
  2.47072558  4.97819957 14.72779601 13.00943717  4.27660505  4.05121985
  9.58757433  4.39987831  2.28963043  2.38275134  9.85194738  1.72535424
  3.0769887  10.30207713  8.61146578 12.90911924 11.36712701 15.50623345
 13.7589026  12.26527187  1.58603345  2.30532972  8.87056489  3.13362005
  3.52305632  3.67792632  3.89649612  1.4386125   1.71897963 16.02063149
  5.58214334 12.0190435   2.95246444 14.46332073  3.13793354  8.35731731
 12.8190229   1.75046918  6.8243075  13.8579805   3.32922829  5.86296698
 11.90112905 12.93140955 14.42031785  5.3216482  10.14847492 17.3251465
  2.47138994  3.96190681 18.32627855  9.86892096  1.41331525 10.64773288
  9.09088555 17.20324969  3.57395915  2.81320472  3.67705031  9.48759433
  3.95038135  2.46245273  3.12790097  1.83174667  5.75616587  4.76223002
  2.29396539  3.50878545 16.44701112  2.56198802  3.03031246  3.60246817
 10.07925548  2.55678468  3.41922207 12.81354395  2.03218368  2.18411881
  5.71737479 10.5187821   9.8243807   5.31478036  9.31603096  9.10138797
  3.05260546 14.61014811  2.95722431  2.53560441 12.02355853 10.43694612
  3.74326294 14.4808655   1.43951577  5.58075845 14.91277029  5.228079
 11.88416143  4.76215204  2.75428552  3.89022373  9.16522942 13.05572311
  9.70863685  2.95688892 17.62382334 11.02667669  9.46154392  4.51952775
  2.28900873 12.89384822  4.27548303 13.28473553  1.14315432  3.55814162
  4.08884875 14.30471291  1.81601334 18.80676865  2.3751151  13.26443122
  3.75552258  9.37745094  6.04970249  2.08571758 18.48641005  3.90175208
  7.94228462  2.85694027 15.98069971  3.49704604 10.64585213  2.8258999
  9.09735439  5.04798097  2.34820756  3.98234323  3.05687448  9.78621841
  2.8982907   9.72068384  2.06609795  8.4708919   2.55512651  5.80843487
 11.58212182 14.7659963   9.90972259  2.03636776  7.38400216  2.28270996
  6.73525348 12.67320166  3.00927587  9.77745413  4.02872521 14.59123614
  5.67976841 11.84854574  2.53005349  4.32053876  3.00515769  8.17868205
  2.91033416  1.44360989  2.61775999 10.2059313   4.41104931  4.51101966
  6.32294616  3.5798359  14.29298242 10.1850001   7.58348729  4.28934805
  4.1439929   7.1227075   3.50184952  2.87101774  4.87187746  3.75846851
  2.00289192 12.2322784   3.82984137  1.6002216  10.87064848  6.02427509
 12.19193643 10.45019334  3.20778262  2.81201506  3.79449686  2.46022196
  9.31467235  2.15239862  2.92910412  8.51832994  2.61877179  5.04802801
  5.69180959  2.30174729  2.78591436 13.26958071 16.64394446  8.87999939
  2.49981874 14.93269447  4.45081163  8.23200249  3.55687264 15.62632032
 12.35393654 18.94154334  2.4851807   1.71703064 11.80745358  2.29174295
  4.33087948  8.8071983   8.89762856  3.76659625  9.01661689  3.8378286
  2.13722881  9.02591117  7.26601453  8.50650449 12.79463264  4.12517895
 11.63249865  9.66210348  3.15261767  4.41986823  3.44998087 10.98001111
  4.60746822  3.59134612 14.06455102  2.99038467  2.71795072  2.56293166
  2.86380398 10.39300275 11.23770423  4.95716077  1.46285195  4.53518564
  4.030694   16.57787437  2.18449096  3.63219595  5.10131515 13.69275973
  6.48100525  2.70557808  5.39534656  9.45176473  3.38046424  3.90224131
 12.59789779 12.46234039  1.70942088  5.43824785  1.47168759 18.16270268
 11.96367623  1.79205494  2.58470531  2.68016219 14.74912196 10.1040361
  3.26318155  2.6378777   2.60610772  3.62567306  2.84074939 10.75006159
  7.39066186  3.06160376  1.26314304  3.88996936  1.14486011 15.17777613
  2.86507824 10.02941764 11.21523506  3.56782758  2.57867046  1.2635082
 12.70475784 11.78453449  2.30180443  1.17985582  2.47902327  2.58727762
  4.16686036  3.95105243 15.43508779  2.81761054  4.0322251   3.07596467
 12.82461871  2.81444631 19.33636867  3.69986094  1.99687652  4.80581687
  2.27689069 12.22263126  2.08777775  2.60298631 17.12802364 12.52639565
 11.69244796  2.00589312  1.98988765 16.28233571  9.10732225 13.0165149
  5.92164221  2.2505696   2.44209013 10.34767538  5.98523168 16.26028586
  8.33935586 16.8204904   2.03558767  2.77620724  4.30384591  3.00854596
 10.17185727  3.72924572  3.7670771   4.28711491 11.08123194 11.35512171
 12.71567246 15.30622396  3.15587055  4.08257799  2.03327719  3.41659174
 14.13036958  3.54284787  2.69887027  9.317551    7.91886701  5.82956199
 11.2956263   4.05641343 11.15385568 10.89295838 11.36479919  2.86273986
  4.80262184 10.58436197  9.18243093  1.80435676  3.35755569  1.73762343
  2.02772398  9.05409416  3.00025958  5.328892    2.87397055 17.43294837
  2.82128031  9.12124743  3.45413876  3.08416112  2.08600945 10.071014
  2.35476915 10.81477834 13.69733219 11.06620676  6.04497979 15.14030966
 14.91813751  3.32817428  8.57679193 17.13660103  8.38872085 14.42368735
 15.28424061  2.75288466 14.33051295  2.73651334 10.16033205  7.3391554
  2.42042554 16.73487862  2.57350632  3.524343    3.28983093  3.20648722
  2.58769438 14.80494598  3.82870434  2.53057771  3.27421328  6.25488245
  2.97443497  3.67971006  4.83441897  4.25943544  3.43624859 16.67124463
  2.98236856  8.24938713 19.46524322  2.55245492 11.80036833  2.54928389
 16.2374949   9.54536837  4.93137021  3.7290861   4.03051892 11.84523524
  2.58673756 14.97983755  2.57569308 16.81738772 12.28515101  2.14814742
  3.42051089  9.01921055  9.49621653  2.95933914  3.75237644  2.23972066
  2.49277755  1.7958297   3.86582093  2.8674885  11.42639942  3.06073274
  3.13961257  4.07270659 11.3555383   3.12213356  4.21349249  8.6944528
  1.76443633  2.1899131   4.18629277  8.88741747  8.33202173  7.56865056
  5.43031759  2.00601233  2.32724761  2.77278376  5.25002215  2.13399159
 10.57578629 11.58732585  2.86180112  2.07601269  9.77807231  2.9222822
 16.49825749  5.2869834   3.11327626  6.17030198 10.02044606  9.51853346
  4.15921692  3.1338318   1.99023388  5.07213763  3.66805146 14.2182649
 15.27840034 13.79492613  8.7106045  10.17749474 10.40411274  9.22057205
  8.76561824 12.97598282  9.1910614  17.96203867  2.12718709  4.04214711
  9.56797976 15.27220032 16.99049874 11.3642939   5.91326291  2.45308319
  4.46940539 20.19433041 12.69880519  5.50994035  2.6682945   5.52958319
 12.42290534 14.56567536  1.67923754  9.78182321 10.14994473  2.00056631
 11.91937116 11.448476    3.00603484  4.37674718 18.29810163 10.22220423
 11.76327836 11.7443404   6.22308342  5.81977575 10.74629097  2.64957524
 14.18339329  5.28790528  4.21960812  2.46020194 12.78135003  2.81262627
  3.56482063  9.18548323 10.77509061  2.11414128 11.74135626  5.59792502
  8.51753377  2.14325374 17.29903726  5.36609587 12.94339358  3.12628909
 14.37527003 11.23391531 15.23465018  8.32416306 19.23496585 10.72728053
  6.25323716  5.54923781  3.42075517 15.17046362  1.74005129  1.82091277
 15.78389194 10.02145557  1.86770706 15.23353752  2.77126333 12.98051255
  1.99018252 14.74476653  1.71875456  4.12341993  3.19630416  3.17907961
  2.86272064 14.0146559   5.94243459  1.27345519 15.139857    3.19217053
  2.84853572  2.2721021   2.88287568  3.5868594  15.50908541 11.71567681
  4.8065892   3.19212114  2.57103734 11.67912572  3.70752448  2.51133544
  4.76364981  3.27797006  2.12666216  3.99289363  2.55004679 10.4122718
  3.41915544  3.45791773  4.27428329  2.16475035  2.24357662 20.27107131
  2.6211838  15.62812531  2.50006029  9.73341343 11.62414759  8.98773249
  2.82862895  2.00722094  9.88201667  2.1846998   1.50637995  2.32878985
 14.11192293 13.41634497 14.28146237  1.4591491   2.75790525  2.83246229
  4.07144576  3.79653033  9.44913553  3.90219151  4.0168187   4.1243992
  9.80958254  5.3800075   9.46195049  1.97717373  8.34077912 12.43010474
  3.38649636 10.02097508 11.49680925 13.97190463  3.60431429  7.37584679
  4.33912419 11.84222445  1.44089012  4.85941981  3.39159309  3.13357328
  2.47096887  3.94502129  4.15493405 18.49504618  9.08651191  2.95832372
  2.52244627  5.99553625  2.11520684  1.89749755  2.6973316   2.54822468
 10.94537441  2.84587429 12.62276847 10.15800164  2.10079835 15.30418953
 10.94837016 12.40484611 11.14575664 14.59172598 12.7621914   3.05184364
  1.14525931 11.08995653  8.08010737 11.35478585  8.82251206 11.58877523
  2.74174474  1.72758415  2.73267471 10.97797436  9.23096251 10.99237774
  5.60784631  1.43780359  2.71939508 12.29089903 11.65782657 11.7466421
 12.60767642  3.36428522 10.63306574  1.52817038  3.40656569 10.39742458
  4.76747207  9.39296795  1.52353529  9.34627711  3.18889881 11.42316406
  1.39855096  2.46862897  3.40834961  4.85487296  5.60442383  9.39185753
  5.42768172  2.22885825  3.48311119  3.03352602 13.742788    2.18855936
  8.85964886  7.3666449   5.94596985  1.91490109  5.15930417  2.2872242
 15.50775001  4.19582067 11.82081366  3.0231326   3.81860312  5.49153365
  8.99019113  3.41449445  8.55043021 15.14574943  2.30922244 18.83958163
  4.0470322  11.25874087  4.40418921  5.87370827 16.54006959 12.39198049
  2.79055698  5.0799784   2.6037895 ]
id
1437    18.559999
2700     3.100000
3647    12.650000
2512     2.910000
2902    15.520000
Name: Close, dtype: float64
Коэффициент детерминации R²: 1.00
Время обучения модели: 1.91 секунд
Среднеквадратичная ошибка: 0.05
Средняя абсолютная ошибка: 0.04
c:\Users\K\source\repos\AIM-PIbd-31-Ievlewa-M-D\aimenv\Lib\site-packages\sklearn\linear_model\_ridge.py:216: LinAlgWarning: Ill-conditioned matrix (rcond=5.67566e-19): result may not be accurate.
  return linalg.solve(A, Xy, assume_a="pos", overwrite_a=True).T
c:\Users\K\source\repos\AIM-PIbd-31-Ievlewa-M-D\aimenv\Lib\site-packages\sklearn\linear_model\_ridge.py:216: LinAlgWarning: Ill-conditioned matrix (rcond=5.85088e-19): result may not be accurate.
  return linalg.solve(A, Xy, assume_a="pos", overwrite_a=True).T
c:\Users\K\source\repos\AIM-PIbd-31-Ievlewa-M-D\aimenv\Lib\site-packages\sklearn\linear_model\_ridge.py:216: LinAlgWarning: Ill-conditioned matrix (rcond=6.03205e-19): result may not be accurate.
  return linalg.solve(A, Xy, assume_a="pos", overwrite_a=True).T
c:\Users\K\source\repos\AIM-PIbd-31-Ievlewa-M-D\aimenv\Lib\site-packages\sklearn\linear_model\_ridge.py:216: LinAlgWarning: Ill-conditioned matrix (rcond=5.92069e-19): result may not be accurate.
  return linalg.solve(A, Xy, assume_a="pos", overwrite_a=True).T
c:\Users\K\source\repos\AIM-PIbd-31-Ievlewa-M-D\aimenv\Lib\site-packages\sklearn\linear_model\_ridge.py:216: LinAlgWarning: Ill-conditioned matrix (rcond=4.94481e-19): result may not be accurate.
  return linalg.solve(A, Xy, assume_a="pos", overwrite_a=True).T
Кросс-валидация RMSE: 0.06936831513332838 

No description has been provided for this image

На основании представленных данных можно сделать несколько выводов:

  1. Общие выводы по точности В данном случае среднеквадратичные ошибки близки или равны нулю, к тому же коэффициент детерминации 1.00 - это говорит либо о том, что модель обучается идеально, либо о том, что модель запомнила значения. Поэтому я проверила ее на нескольких моделях и отдельно вывела для сравнения список предсказанной целевой переменной и тестовую(с которой сравниваем) целевую переменную - результаты оказались весьма близки к тестовым показателям, но не точь в точь, что, скорее всего, говорит о том, что модель все же обучается идеально... Среднеквадратичная ошибка (RMSE) и Средняя абсолютная ошибка (MAE)
  • LinearRegression: MAE = 0.04 и RMSE = 0.05 указывает на весьма точные предсказания.
  • DecisionTreeRegressor: MAE и RMSE равны 0.00, что может указывать на чрезмерное подстраивание модели к обучающим данным.
  • RandomForestRegressor: MAE = 0.02 и RMSE = 0.03 показывают высокую точность прогнозов, но не столь идеальные результаты, как у дерева решений.
  • Lasso и Ridge: Обе модели имеют MAE = 0.10 и 0.04 соответственно, что также предполагает приемлемую точность, но с возможностью недопущения переобучения.
  1. Переобучение модели Высокие значения R² и нулевые ошибки (MAE и RMSE) у DecisionTreeRegressor могут указывать на переобучение модели. Это значит, что модель отлично работает на обучающих данных, но может быть неэффективной на новых, невидимых данных. Для линейной регрессии и других регуляризованных моделей (например, Lasso и Ridge) результаты более сбалансированы, что делает их менее подверженными переобучению.
  2. Производительность модели Время обучения у моделей варьируется значительно. Например, DecisionTreeRegressor обучается за короткое время (0.31 секунды), в то время как LinearRegression и RandomForestRegressor требуют больше времени. Это может быть критичным для сценариев, требующих частых обновлений модели.
  3. Соответствие бизнес-целям Учитывая высокую точность модели и ее способность к обучению на исторических данных, можно использовать ее для прогнозирования цен на акции. Однако рекомендуется дополнительно проверять результаты на тестовых данных, чтобы избежать проблем с переобучением.