411 KiB
Начало лабораторной работы¶
- Цены на кофе (12 варик)
- Цены на акции (13 варик)
- Цены на золото (14 варик)
Цены на кофе
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
df = pd.read_csv("C:/Users/TIGR228/Desktop/МИИ/Lab1/AIM-PIbd-31-Afanasev-S-S/static/csv/Starbucks.csv")
print(df.columns, "\n")
Столбцы на русском
- date: Дата
- open: Цена открытия
- high: Самая высокая цена дня
- low: Самая низкая цена дня
- Close: Цена закрытия
- Adj Close: Скорректированная цена закрытия
- Volume: Объем торгов
Проблемная область: Прогнозирование динамики цен акций Starbucks на основе исторических данных о ценах и объемах торгов.
print(df.info, "\n")
Объектом наблюдения является - цена акций Starbucks
Атрибуты — содержит набор информации о ценах акций Starbucks, такие как: дата, цена открытия, максимальная цена дня, минимальная цена дня, цена закрытия, скорректированная цена закрытия и объем торгов.
import matplotlib.pyplot as plt
plt.figure(figsize=(10, 6))
plt.scatter(df['Volume'], df['Close'], c=df['Close'], alpha=0.6)
plt.colorbar(label='Close Price')
plt.title("Зависимость цены закрытия от объема торгов")
plt.ylabel("Цена закрытия")
plt.xlabel("Объем торгов")
plt.grid(visible=True)
plt.show()
import matplotlib.pyplot as plt
df['Year'] = pd.to_datetime(df['Date']).dt.year
year_close = df.groupby('Year')['Close'].mean().reset_index()
plt.figure(figsize=(12, 6))
plt.plot(year_close['Year'], year_close['Close'], marker='.')
plt.title("Средняя цена закрытия акций Starbucks по годам")
plt.xlabel("Год")
plt.ylabel("Средняя цена закрытия")
plt.show()
Связь между объектами есть. Цена связана почти со всеми характеристиками акций. Например, на графике номер один показана зависимость между ценой закрытия и объемом торгов. А на графике номер два показана зависимость средней цены закрытия от года.
Примеры бизнес-целей
- Прогнозирование динамики цен акций Starbucks на основе исторических данных о ценах и объемах торгов.
- Наблюдение за изменениями цен акций Starbucks с годами.
Эффект для бизнеса: Оценка и оптимизация цен, оценка и планирование затрат, выявление тенденций на рынке, стратегия планирования.
Цели технического проекта
- Для первой цели:
- Для второй цели:
Код ниже нужен для определения проблем данных
import pandas as pd
max_value = df.max(axis=0)
columns_with_zero = df.columns[(df == 0).any()]
numeric_data = df.select_dtypes(include='number')
shum = numeric_data.var()
low_dispers = 0.1
low_var_columns = shum[shum < low_dispers]
df['Year'] = pd.to_datetime(df['Date']).dt.year
print("Максимальные значения:\n", max_value, "\n")
print("Столбцы с нулевыми значениями:\n", columns_with_zero, "\n")
print("Признаки с низкой дисперсией:\n", low_var_columns, "\n")
print("Годы:\n", df['Year'])
Из полученных данных выяснилось:
- Date: 2024-05-23
- Open: 126.080002
- High: 126.32
- Low: 124.809998
- Close: 126.059998
- Adj Close: 118.010414
- Volume: 585508800
- Year: 2024
Примеры решения проблем для набора данных
Оценка качества данных
1. Информативность. Набор данных предоставляет достаточную информацию для анализа цен на недвижимость. 2. Степень покрытия. Набор данных затрагивает только один райно, не включая информацию о других райнов. 3. Соответствие реальным данным. Данные вполне кажутся реальными, не считая некоторых редких выбросов. 4. Согласованность меток. Метки состояние и оценка вида, имеют четкие значения.Разбиение данных на обучающую, контрольную и тестовую выборки
df_numeric = df.select_dtypes(include='number')
x = df_numeric.drop(['Close'], axis=1)
y = df_numeric['Close']
x_train, x_temp, y_train, y_temp = train_test_split(x, y, test_size=0.3, random_state=14)
x_val, x_test, y_val, y_test = train_test_split(x_temp, y_temp, test_size=0.5, random_state=14)
print(f"Исходный размер строк: {df_numeric.shape[0]} строк")
print(f"Размер обучающей выборки: {x_train.shape[0]} строк")
print(f"Размер валидационной выборки: {x_val.shape[0]} строк")
print(f"Размер тестовой выборки: {x_test.shape[0]} строк")
import seaborn as sns
import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
# Логарифмирование целевой переменной
df['Close_log'] = np.log(df['Close'])
# Выбор признаков и целевой переменной
X = df.drop(['Close', 'Close_log'], axis=1)
y = df['Close_log']
# Выбор только числовых признаков
X = X.select_dtypes(include='number')
# Разделение данных на обучающую, валидационную и тестовую выборки
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)
# Функция для построения гистограммы распределения целевого признака
def plot_distribution(data, title):
"""Построение гистограммы распределения целевого признака"""
plt.figure(figsize=(10, 6))
sns.histplot(data, kde=True, bins=30, color='skyblue')
plt.title(title)
plt.xlabel('Logarithm of Close Price')
plt.ylabel('Count')
plt.grid(True)
plt.show()
# Построение гистограмм распределения целевого признака
plot_distribution(y_train, 'Распределение логарифма цены закрытия в обучающей выборке')
plot_distribution(y_val, 'Распределение логарифма цены закрытия в валидационной выборке')
plot_distribution(y_test, 'Распределение логарифма цены закрытия в тестовой выборке')
# Функция для вывода статистических показателей
def get_statistics(df, name):
print(f"Статистические показатели для {name} выборки:")
print(f"Среднее значение: {df.mean():.2f}")
print(f"Стандартное отклонение: {df.std():.2f}")
print(f"Минимальное значение: {df.min():.2f}")
print(f"Максимальное значение: {df.max():.2f}")
print(f"Количество наблюдений: {df.count()}\n")
# Вывод статистических показателей для обучающей, валидационной и тестовой выборок
get_statistics(y_train, "обучающей")
get_statistics(y_val, "валидационной")
get_statistics(y_test, "тестовой")
Oversampling и undersampling
from imblearn.over_sampling import SMOTE
from imblearn.under_sampling import RandomUnderSampler
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
# Проверка наличия столбца 'Date' и создание столбца 'Year'
if 'Date' in df.columns:
df['Year'] = pd.to_datetime(df['Date'], errors='coerce').dt.year
df = df.drop(['Date'], axis=1)
# Логарифмирование целевой переменной
df['Close_log'] = np.log(df['Close'])
# Создание категорий для целевой переменной
df['Close_category'] = pd.qcut(df['Close_log'], q=5, labels=[0, 1, 2, 3, 4])
# Выбор признаков и целевой переменной
X = df.drop(['Close', 'Close_log', 'Close_category'], axis=1)
y = df['Close_category']
# Разделение данных на обучающую и тестовую выборки
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
# Применение SMOTE для oversampling
smote = SMOTE(random_state=42)
X_train_smote, y_train_smote = smote.fit_resample(X_train, y_train)
print("Распределение классов после SMOTE (oversampling):")
print(pd.Series(y_train_smote).value_counts())
# Применение RandomUnderSampler для undersampling
undersampler = RandomUnderSampler(random_state=42)
X_train_under, y_train_under = undersampler.fit_resample(X_train, y_train)
print("Распределение классов после RandomUnderSampler (undersampling):")
print(pd.Series(y_train_under).value_counts())
Оценка сбалансированности выборок
Оценка необходимости аугментации данных
import numpy as np
import pandas as pd
def check_augmentation_need(data, name):
"""Проверка необходимости аугментации данных"""
# Проверка на наличие числовых значений
if isinstance(data.dtype, pd.CategoricalDtype):
print(f"Данные в выборке {name} являются категориальными.")
return
elif not np.issubdtype(data.dtype, np.number):
print(f"Данные в выборке {name} не являются числовыми.")
return
# Проверка на наличие пустых значений
if data.isnull().any():
print(f"Выборка {name} содержит пустые значения.")
return
quantiles = data.quantile([0.25, 0.5, 0.75])
mean = data.mean()
std = data.std()
print(f"Проверка необходимости аугментации для {name} выборки:")
print(f"Среднее значение: {mean:.2f}, Стандартное отклонение: {std:.2f}")
print(f"25-й квантиль: {quantiles[0.25]:.2f}")
print(f"50-й квантиль (медиана): {quantiles[0.5]:.2f}")
print(f"75-й квантиль: {quantiles[0.75]:.2f}")
if std > mean * 0.5:
print(f"Выборка {name} несбалансирована, рекомендуется аугментация.\n")
else:
print(f"Выборка {name} сбалансирована, аугментация не требуется.\n")
# Пример использования функции
# y_train, y_val, y_test должны быть определены заранее
check_augmentation_need(y_train, "обучающей")
check_augmentation_need(y_val, "валидационной")
check_augmentation_need(y_test, "тестовой")
Поскольку выборка валидационной несбалансирована и демонстрирует значительный разброс значений, что подтверждается квантилями и стандартным отклонением, применение методов аугментации рекомендуется для улучшения сбалансированности и качества модели.
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from imblearn.over_sampling import SMOTE
from imblearn.under_sampling import RandomUnderSampler
# Логарифмирование целевой переменной
df['Close_log'] = np.log(df['Close'])
# Создание категорий для целевой переменной
df['Close_category'] = pd.qcut(df['Close_log'], q=5, labels=[0, 1, 2, 3, 4])
# Выбор признаков и целевой переменной
X = df.drop(['Close', 'Close_log', 'Close_category'], axis=1)
y = df['Close_category']
# Разделение данных на обучающую, валидационную и тестовую выборки
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)
def analyze_close_category_distribution(data, name):
"""Проверка и визуализация распределения признака 'Close_category'"""
category_counts = data.value_counts()
print(f"Распределение 'Close_category' в {name} выборке:\n", category_counts)
plt.figure(figsize=(8, 6))
sns.barplot(x=category_counts.index, y=category_counts.values, palette='viridis')
plt.title(f"Распределение признака 'Close_category' в {name} выборке")
plt.xlabel('Close Category')
plt.ylabel('Count')
plt.grid(True)
plt.show()
analyze_close_category_distribution(y_train, 'обучающей')
analyze_close_category_distribution(y_val, 'валидационной')
analyze_close_category_distribution(y_test, 'тестовой')
def check_close_category_augmentation(data, name):
print(f"Проверка необходимости аугментации для признака 'Close_category' в {name} выборке:")
min_count = data.value_counts().min()
max_count = data.value_counts().max()
print(f"Минимальное количество наблюдений в классе: {min_count}")
print(f"Максимальное количество наблюдений в классе: {max_count}")
if max_count > min_count * 1.5:
print(f"Выборка '{name}' несбалансирована, рекомендуется аугментация.\n")
else:
print(f"Выборка '{name}' сбалансирована, аугментация не требуется.\n")
check_close_category_augmentation(y_train, 'обучающей')
check_close_category_augmentation(y_val, 'валидационной')
check_close_category_augmentation(y_test, 'тестовой')
# Применение SMOTE для oversampling
smote = SMOTE(random_state=42)
X_train_smote, y_train_smote = smote.fit_resample(X_train, y_train)
print("Распределение классов после SMOTE (oversampling):")
print(pd.Series(y_train_smote).value_counts())
# Применение RandomUnderSampler для undersampling
undersampler = RandomUnderSampler(random_state=42)
X_train_under, y_train_under = undersampler.fit_resample(X_train, y_train)
print("Распределение классов после RandomUnderSampler (undersampling):")
print(pd.Series(y_train_under).value_counts())
В этом исследование данные сбалансированы, поэтому аугментация не требуется .