276 KiB
Загрузка данных¶
import pandas as pd
df = pd.read_csv("../static/csv/FINAL_USO.csv")
print(df.columns)
df
1-я бизнес-цель (регрессия):¶
Предсказание цены на золото с целью принятия инвесторами решения о покупке товаров.
Целевой признак: цена закрытия Adj Close.
Вход: Volume, Hight, Low, Close, Open.
Достижимый уровень качества: предсказания должны иметь погрешность в среднем не более 5$. Для проверки будет использоваться метрика MAE (средняя абсолютная ошибка)
import pandas as pd
from sklearn.compose import ColumnTransformer
from sklearn.discriminant_analysis import StandardScaler
from sklearn.impute import SimpleImputer
from sklearn.pipeline import Pipeline
from sklearn.model_selection import GridSearchCV, train_test_split
from sklearn.metrics import roc_auc_score, confusion_matrix, accuracy_score
from sklearn.ensemble import RandomForestClassifier, GradientBoostingClassifier
import seaborn as sns
from sklearn.model_selection import cross_val_predict
from sklearn.metrics import mean_squared_error
import numpy as np
from sklearn import metrics
import sklearn.preprocessing as preproc
from sklearn.linear_model import LinearRegression, Ridge
from sklearn.metrics import mean_absolute_error
from mlxtend.evaluate import bias_variance_decomp
from sklearn.neural_network import MLPRegressor
# Загрузка данных
df = pd.read_csv("..//static//csv//FINAL_USO.csv")
data = df['Volume', 'High', 'Open', 'Close', 'Low','Adj Close']
X = data.drop('Adj Close', axis=1)
y = data['Adj Close']
# Разделение данных на обучающую и тестовую выборки
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# Преобразование числовых данных
#заполнение пустых значений медианой
num_imputer = SimpleImputer(strategy="median")
preprocessing_num = Pipeline(
[
("imputer", num_imputer)
]
)
#Категориальных данных нет, поэтому преобразовывать их не надо
# Общая предобработка (только числовые данные)
preprocessing = ColumnTransformer(
[
("nums", preprocessing_num, X.columns)
]
)
Лнейная регрессия:¶
pipeline_lin_reg = Pipeline([
('preprocessing', preprocessing),
('model', LinearRegression())]
)
# Определение сетки гиперпараметров (возможных знач-ий гиперпараметров) для перебора
param_grid = {
#как будут масштабироваться признаки
'preprocessing': [StandardScaler(), preproc.MinMaxScaler(), preproc.MaxAbsScaler(), None]
}
# Создание объекта GridSearchCV для поиска лучших гиперпараметров по сетке с максимальным знач-ием
# отрицательного корня из среднеквадратичной ошибки (отриц., чтобы искался не минимум, а максимум)
grid_search = GridSearchCV(pipeline_lin_reg, param_grid, cv=5, scoring='neg_root_mean_squared_error', n_jobs=-1)
# Обучение модели с перебором гиперпараметров
grid_search.fit(X_train, y_train)
print("Лучшие гиперпараметры: ", grid_search.best_params_)
# Лучшая модель лин. регрессии
best_model = grid_search.best_estimator_
y_pred = best_model.predict(X_test)
print(f'Cредняя абсолютная ошибка (MAE) = {mean_absolute_error(y_test, y_pred)}')
# Оценка дисперсии и смещения
cv_results = grid_search.cv_results_
mean_test_score = cv_results['mean_test_score']
std_test_score = cv_results['std_test_score']
print(f"Смещение: {mean_test_score.mean()}")
print(f"Дисперсия: {std_test_score.mean()}")
from sklearn.metrics import r2_score
print(f'R^2 = {r2_score(y_test, y_pred)}')
Гребневая регрессия¶
pipeline_ridge = Pipeline([
('preprocessing', preprocessing),
('model', Ridge())]
)
# Определение сетки гиперпараметров (возможных знач-ий гиперпараметров) для перебора
param_grid = {
#как будут масштабироваться признаки
'preprocessing': [StandardScaler(), preproc.MinMaxScaler(), preproc.MaxAbsScaler(), None],
#сила регуляризации
'model__alpha': [0, 0.5, 1.0, 1.5, 2.0, 5.0, 10.0]
}
# Создание объекта GridSearchCV для поиска лучших гиперпараметров по сетке с максимальным знач-ием
# отрицательного корня из среднеквадратичной ошибки (отриц., чтобы искался не минимум, а максимум)
grid_search = GridSearchCV(pipeline_ridge, param_grid, cv=5, scoring='neg_root_mean_squared_error', n_jobs=-1, verbose=0)
# Обучение модели с перебором гиперпараметров
grid_search.fit(X_train, y_train)
print("Лучшие гиперпараметры: ", grid_search.best_params_)
# Лучшая модель регрессии
best_model = grid_search.best_estimator_
y_pred = best_model.predict(X_test)
print(f'Cредняя абсолютная ошибка (MAE) = {mean_absolute_error(y_test, y_pred)}')
cv_results = grid_search.cv_results_
mean_test_score = cv_results['mean_test_score']
std_test_score = cv_results['std_test_score']
print(f"Смещение: {mean_test_score.mean()}")
print(f"Дисперсия: {std_test_score.mean()}")
print(f'R^2 = {r2_score(y_test, y_pred)}')
Гребнавая регрессия дала более точные результаты, чем линейная.
Метод градиентного бустинга (набор деревьев решений)¶
from sklearn.metrics import roc_auc_score, confusion_matrix, accuracy_score
from sklearn.ensemble import GradientBoostingRegressor, RandomForestClassifier, GradientBoostingClassifier
# Конвейер
pipeline_grad = Pipeline([
('preprocessing', preprocessing),
('model', GradientBoostingRegressor())
])
# Определение сетки гиперпараметров
param_grid = {
'preprocessing': [StandardScaler(), preproc.MinMaxScaler(), preproc.MaxAbsScaler(), None],
'model__n_estimators': [100, 200, 300],
#Скорость обучения
'model__learning_rate': [0.1, 0.2],
#Максимальная глубина дерева
'model__max_depth': [3, 5, 7]
}
# Создание объекта GridSearchCV
grid_search = GridSearchCV(pipeline_grad, param_grid, cv=2, scoring='neg_root_mean_squared_error', n_jobs=-1)
# Обучение модели с перебором гиперпараметров
grid_search.fit(X_train, y_train)
print("Лучшие гиперпараметры: ", grid_search.best_params_)
# Лучшая модель случайного леса
best_model = grid_search.best_estimator_
y_pred = best_model.predict(X_test)
print(f'Cредняя абсолютная ошибка (MAE) = {mean_absolute_error(y_test, y_pred)}')
# Получение предсказаний на кросс-валидации
y_cv_pred = cross_val_predict(best_model, X_train, y_train, cv=3)
cv_results = grid_search.cv_results_
mean_test_score = cv_results['mean_test_score']
std_test_score = cv_results['std_test_score']
print(f"Смещение: {mean_test_score.mean()}")
print(f"Дисперсия: {std_test_score.mean()}")
print(f'R^2 = {r2_score(y_test, y_pred)}')
Вывод:
Все 3 модели регрессии показали допустимый уровень "погрешности".
R² (коэффициент детерминации): 0.99 — это очень высокий уровень, указывающий на то, что модель объясняет 99% вариации целевой переменной. Это свидетельствует о высокой предсказательной способности модели.
Из всех моделей градиентный бустинг показал самую низкую "погрешность".
2-я бизнес-цель (классификация):¶
Определить оптимальные коэффициенты для различных факторов, влияющих на цену золота.
Целевой признак: Adj Close.
Вход: Volume, Hight, Low, Close, Open.
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LinearRegression, LogisticRegression
from sklearn.ensemble import RandomForestRegressor, RandomForestClassifier
from sklearn.ensemble import GradientBoostingRegressor, GradientBoostingClassifier
from sklearn.pipeline import Pipeline
from sklearn.compose import ColumnTransformer
from sklearn.preprocessing import OneHotEncoder
from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score, accuracy_score, precision_score, recall_score, f1_score, confusion_matrix, ConfusionMatrixDisplay
# Загружаем набор данных
df = pd.read_csv("..//static//csv//FINAL_USO.csv")
numerical_cols = ['Volume', 'High', 'Open', 'Close', 'Low']
# Создаем преобразователь для категориальных и числовых столбцов
preprocessor = ColumnTransformer(
transformers=[
('num', StandardScaler(), numerical_cols)
])
# Список моделей и их гиперпараметров для задачи регрессии
models_reg = {
"Linear Regression": (LinearRegression(), {}),
"Random Forest Regression": (RandomForestRegressor(), {
'model__n_estimators': [100, 200],
'model__max_depth': [None, 10, 20]
}),
"Gradient Boosting Regression": (GradientBoostingRegressor(), {
'model__n_estimators': [100, 200],
'model__learning_rate': [0.01, 0.1],
'model__max_depth': [3, 5]
})
}
# Разделяем данные на признаки (X) и целевую переменную (y) для задачи регрессии
X_reg = df[numerical_cols]
y_reg = df['Adj Close']
# Разделяем данные на обучающую и тестовую выборки для задачи регрессии
X_train_reg, X_test_reg, y_train_reg, y_test_reg = train_test_split(X_reg, y_reg, test_size=0.2, random_state=42)
# Список моделей и их гиперпараметров для задачи классификации
models_class = {
"Logistic Regression": (LogisticRegression(), {
'model__C': [0.1, 1, 10],
'model__solver': ['liblinear', 'lbfgs']
}),
"Random Forest Classification": (RandomForestClassifier(), {
'model__n_estimators': [100, 200],
'model__max_depth': [None, 10, 20]
}),
"Gradient Boosting Classification": (GradientBoostingClassifier(), {
'model__n_estimators': [100, 200],
'model__learning_rate': [0.01, 0.1],
'model__max_depth': [3, 5]
})
}
# Разделяем данные на признаки (X) и целевую переменную (y) для задачи классификации
X_class = df[ numerical_cols]
y_class = (df['Adj Close'] > df['Adj Close'].mean()).astype(int)
# Разделяем данные на обучающую и тестовую выборки для задачи классификации
X_train_class, X_test_class, y_train_class, y_test_class = train_test_split(X_class, y_class, test_size=0.2, random_state=42)
# Обучаем и оцениваем модели для задачи классификации
print("Результаты для задачи классификации:")
for name, (model, params) in models_class.items():
pipeline = Pipeline(steps=[
('preprocessor', preprocessor),
('model', model)
])
grid_search = GridSearchCV(pipeline, params, cv=5, scoring='accuracy')
grid_search.fit(X_train_class, y_train_class)
best_model = grid_search.best_estimator_
y_pred_class = best_model.predict(X_test_class)
accuracy = accuracy_score(y_test_class, y_pred_class)
precision = precision_score(y_test_class, y_pred_class)
recall = recall_score(y_test_class, y_pred_class)
f1 = f1_score(y_test_class, y_pred_class)
print(f"Model: {name}")
print(f"Best Parameters: {grid_search.best_params_}")
print(f"Accuracy: {accuracy}")
print(f"Precision: {precision}")
print(f"Recall: {recall}")
print(f"F1-score: {f1}")
print()
# Визуализация матрицы ошибок
cm = confusion_matrix(y_test_class, y_pred_class)
disp = ConfusionMatrixDisplay(confusion_matrix=cm, display_labels=['Less', 'More'])
disp.plot(cmap=plt.cm.Blues)
plt.title(f'Confusion Matrix for {name}')
plt.show()
Вывод:
Градиентный бустинг и случайный лес выдали наилучшие результаты.
Давайте проанализируем полученные значения метрик и определим, являются ли они нормальными или их можно улучшить.
Оценка смещения и дисперсии для задачи регрессии:¶
Вывод для задачи регрессии:¶
- Random Forest Regression демонстрирует наилучшие результаты по метрикам MAE и R², что указывает на высокую точность и стабильность модели.
- Linear Regression и Gradient Boosting Regression также показывают хорошие результаты, но уступают случайному лесу.
Вывод для задачи классификации:¶
- Random Forest Classification демонстрирует наилучшие результаты по всем метрикам (Accuracy, Precision, Recall, F1-score), что указывает на высокую точность и стабильность модели.
- Logistic Regression и Gradient Boosting Classification также показывают хорошие результаты, но уступают случайному лесу.
Для оценки смещения (bias) и дисперсии (variance) моделей можно использовать метод перекрестной проверки (cross-validation). Этот метод позволяет оценить, насколько хорошо модель обобщается на новых данных.
Оценка смещения и дисперсии для задачи регрессии: Для задачи регрессии мы будем использовать метрики MAE (Mean Absolute Error) и R² (R-squared) для оценки смещения и дисперсии.
Оценка смещения и дисперсии для задачи классификации: Для задачи классификации мы будем использовать метрики Accuracy, Precision, Recall и F1-score для оценки смещения и дисперсии.
Пример кода для оценки смещения и дисперсии:
import pandas as pd
from sklearn.model_selection import cross_val_score
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LinearRegression, LogisticRegression
from sklearn.ensemble import RandomForestRegressor, RandomForestClassifier
from sklearn.ensemble import GradientBoostingRegressor, GradientBoostingClassifier
from sklearn.pipeline import Pipeline
from sklearn.compose import ColumnTransformer
from sklearn.preprocessing import OneHotEncoder
# Загружаем набор данных
df = pd.read_csv("..//static//csv//FINAL_USO.csv")
# Определяем категориальные и числовые столбцы
numerical_cols = ['Volume', 'High', 'Open', 'Close', 'Low']
# Создаем преобразователь для категориальных и числовых столбцов
preprocessor = ColumnTransformer(
transformers=[
('num', StandardScaler(), numerical_cols)
])
# Разделяем данные на признаки (X) и целевую переменную (y) для задачи регрессии
X_reg = df[numerical_cols]
y_reg = df['Adj Close']
# Список моделей для задачи регрессии
models_reg = {
"Linear Regression": LinearRegression(),
"Random Forest Regression": RandomForestRegressor(),
"Gradient Boosting Regression": GradientBoostingRegressor()
}
# Оценка смещения и дисперсии для задачи регрессии
print("Оценка смещения и дисперсии для задачи регрессии:")
for name, model in models_reg.items():
pipeline = Pipeline(steps=[
('preprocessor', preprocessor),
('model', model)
])
mae_scores = -cross_val_score(pipeline, X_reg, y_reg, cv=5, scoring='neg_mean_absolute_error')
r2_scores = cross_val_score(pipeline, X_reg, y_reg, cv=5, scoring='r2')
print(f"Model: {name}")
print(f"MAE (Cross-Validation): Mean = {mae_scores.mean()}, Std = {mae_scores.std()}")
print(f"R² (Cross-Validation): Mean = {r2_scores.mean()}, Std = {r2_scores.std()}")
print()
# Разделяем данные на признаки (X) и целевую переменную (y) для задачи классификации
X_class = df[numerical_cols]
y_class = (df['Adj Close'] > df['Adj Close'].mean()).astype(int)
# Список моделей для задачи классификации
models_class = {
"Logistic Regression": LogisticRegression(),
"Random Forest Classification": RandomForestClassifier(),
"Gradient Boosting Classification": GradientBoostingClassifier()
}
# Оценка смещения и дисперсии для задачи классификации
print("Оценка смещения и дисперсии для задачи классификации:")
for name, model in models_class.items():
pipeline = Pipeline(steps=[
('preprocessor', preprocessor),
('model', model)
])
accuracy_scores = cross_val_score(pipeline, X_class, y_class, cv=5, scoring='accuracy')
precision_scores = cross_val_score(pipeline, X_class, y_class, cv=5, scoring='precision')
recall_scores = cross_val_score(pipeline, X_class, y_class, cv=5, scoring='recall')
f1_scores = cross_val_score(pipeline, X_class, y_class, cv=5, scoring='f1')
print(f"Model: {name}")
print(f"Accuracy (Cross-Validation): Mean = {accuracy_scores.mean()}, Std = {accuracy_scores.std()}")
print(f"Precision (Cross-Validation): Mean = {precision_scores.mean()}, Std = {precision_scores.std()}")
print(f"Recall (Cross-Validation): Mean = {recall_scores.mean()}, Std = {recall_scores.std()}")
print(f"F1-score (Cross-Validation): Mean = {f1_scores.mean()}, Std = {f1_scores.std()}")
print()
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.model_selection import cross_val_score
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LinearRegression, LogisticRegression
from sklearn.ensemble import RandomForestRegressor, RandomForestClassifier
from sklearn.ensemble import GradientBoostingRegressor, GradientBoostingClassifier
from sklearn.pipeline import Pipeline
from sklearn.compose import ColumnTransformer
from sklearn.preprocessing import OneHotEncoder
# Загружаем набор данных
df = pd.read_csv("..//static//csv//FINAL_USO.csv")
# Определяем категориальные и числовые столбцы
numerical_cols = ['Volume', 'High', 'Open', 'Close', 'Low']
# Создаем преобразователь для категориальных и числовых столбцов
preprocessor = ColumnTransformer(
transformers=[
('num', StandardScaler(), numerical_cols)
])
# Разделяем данные на признаки (X) и целевую переменную (y) для задачи регрессии
X_reg = df[ numerical_cols]
y_reg = df['Adj Close']
# Список моделей для задачи регрессии
models_reg = {
"Linear Regression": LinearRegression(),
"Random Forest Regression": RandomForestRegressor(),
"Gradient Boosting Regression": GradientBoostingRegressor()
}
# Оценка смещения и дисперсии для задачи регрессии
mae_means = []
mae_stds = []
r2_means = []
r2_stds = []
for name, model in models_reg.items():
pipeline = Pipeline(steps=[
('preprocessor', preprocessor),
('model', model)
])
mae_scores = -cross_val_score(pipeline, X_reg, y_reg, cv=5, scoring='neg_mean_absolute_error')
r2_scores = cross_val_score(pipeline, X_reg, y_reg, cv=5, scoring='r2')
mae_means.append(mae_scores.mean())
mae_stds.append(mae_scores.std())
r2_means.append(r2_scores.mean())
r2_stds.append(r2_scores.std())
# Визуализация результатов для задачи регрессии
fig, ax = plt.subplots(1, 2, figsize=(15, 6))
ax[0].bar(models_reg.keys(), mae_means, yerr=mae_stds, align='center', alpha=0.5, ecolor='black', capsize=10)
ax[0].set_ylabel('MAE')
ax[0].set_title('Mean Absolute Error (MAE) for Regression Models')
ax[0].yaxis.grid(True)
ax[1].bar(models_reg.keys(), r2_means, yerr=r2_stds, align='center', alpha=0.5, ecolor='black', capsize=10)
ax[1].set_ylabel('R²')
ax[1].set_title('R-squared (R²) for Regression Models')
ax[1].yaxis.grid(True)
plt.tight_layout()
plt.show()
# Разделяем данные на признаки (X) и целевую переменную (y) для задачи классификации
X_class = df[numerical_cols]
y_class = (df['Adj Close'] > df['Adj Close'].mean()).astype(int)
# Список моделей для задачи классификации
models_class = {
"Logistic Regression": LogisticRegression(),
"Random Forest Classification": RandomForestClassifier(),
"Gradient Boosting Classification": GradientBoostingClassifier()
}
# Оценка смещения и дисперсии для задачи классификации
accuracy_means = []
accuracy_stds = []
precision_means = []
precision_stds = []
recall_means = []
recall_stds = []
f1_means = []
f1_stds = []
for name, model in models_class.items():
pipeline = Pipeline(steps=[
('preprocessor', preprocessor),
('model', model)
])
accuracy_scores = cross_val_score(pipeline, X_class, y_class, cv=5, scoring='accuracy')
precision_scores = cross_val_score(pipeline, X_class, y_class, cv=5, scoring='precision')
recall_scores = cross_val_score(pipeline, X_class, y_class, cv=5, scoring='recall')
f1_scores = cross_val_score(pipeline, X_class, y_class, cv=5, scoring='f1')
accuracy_means.append(accuracy_scores.mean())
accuracy_stds.append(accuracy_scores.std())
precision_means.append(precision_scores.mean())
precision_stds.append(precision_scores.std())
recall_means.append(recall_scores.mean())
recall_stds.append(recall_scores.std())
f1_means.append(f1_scores.mean())
f1_stds.append(f1_scores.std())
# Визуализация результатов для задачи классификации
fig, ax = plt.subplots(2, 2, figsize=(17, 12))
ax[0, 0].bar(models_class.keys(), accuracy_means, yerr=accuracy_stds, align='center', alpha=0.5, ecolor='black', capsize=10)
ax[0, 0].set_ylabel('Accuracy')
ax[0, 0].set_title('Accuracy for Classification Models')
ax[0, 0].yaxis.grid(True)
ax[0, 1].bar(models_class.keys(), precision_means, yerr=precision_stds, align='center', alpha=0.5, ecolor='black', capsize=10)
ax[0, 1].set_ylabel('Precision')
ax[0, 1].set_title('Precision for Classification Models')
ax[0, 1].yaxis.grid(True)
ax[1, 0].bar(models_class.keys(), recall_means, yerr=recall_stds, align='center', alpha=0.5, ecolor='black', capsize=10)
ax[1, 0].set_ylabel('Recall')
ax[1, 0].set_title('Recall for Classification Models')
ax[1, 0].yaxis.grid(True)
ax[1, 1].bar(models_class.keys(), f1_means, yerr=f1_stds, align='center', alpha=0.5, ecolor='black', capsize=10)
ax[1, 1].set_ylabel('F1-score')
ax[1, 1].set_title('F1-score for Classification Models')
ax[1, 1].yaxis.grid(True)
plt.tight_layout()
plt.show()