Антон, привет!👋
Меня зовут Алексей Гриб, и я буду ревьюером твоего проекта.
Сразу хочу предложить в дальнейшем общаться на "ты" - надеюсь, так будет комфортнее:) Но если это неудобно, обязательно дай знать, и мы придумаем что-нибудь ещё!
Цель ревью - не искать ошибки в твоём проекте, а помочь тебе сделать твою работу ещё лучше, устранив недочёты и приблизив её к реальным задачам аналитика. Поэтому не расстраивайся, если что-то не получилось с первого раза - это нормально, и это поможет тебе вырасти!
Ты можешь найти мои комментарии, обозначенные зеленым, желтым и красным цветами, например:
Комментарий ревьюера
Все отлично!👍: похвала, рекомендации «со звёздочкой», полезные лайфхаки, которые сделают и без того красивое решение ещё более элегантным.
Комментарий ревьюера
Некоторые замечания и рекомендации⚠️: некритичные ошибки или развивающие рекомендации на будущее.
Я не смогу принять проект, если в нём будет хотя бы одна критичная ошибка или несколько некритичных ошибок - тогда проект нужно будет немного доработать. Но это нестрашно - я обязательно дам тебе подсказку или укажу верное направление.
Пожалуйста, не удаляй мои комментарии, они будут особенно полезны для нашей работы в случае повторной проверки проекта.
Ты также можешь задавать свои вопросы, реагировать на мои комментарии, делать пометки и пояснения - полная творческая свобода! Но маленькая просьба - пускай они будут отличаться от моих комментариев, это поможет избежать путаницы в нашем общении:) Например, вот так:
Давай посмотрим на твой проект!
Описание проекта¶
Данные находятся в трёх файлах:
gold_recovery_train_new.csv — обучающая выборка;
gold_recovery_test_new.csv — тестовая выборка;
gold_recovery_full_new.csv — исходные данные.
Данные индексируются датой и временем получения информации (признак date). Соседние по времени параметры часто похожи.
Некоторые параметры недоступны, потому что замеряются и/или рассчитываются значительно позже. Из-за этого в тестовой выборке отсутствуют некоторые признаки, которые могут быть в обучающей. Также в тестовом наборе нет целевых признаков.
Исходный датасет содержит обучающую и тестовую выборки со всеми признаками. В вашем распоряжении сырые данные: их просто выгрузили из хранилища. Прежде чем приступить к построению модели, проверьте по нашей инструкции их на корректность.
Восстановление золота из руды¶
Подготовьте прототип модели машинного обучения для «Цифры». Компания разрабатывает решения для эффективной работы промышленных предприятий.
Модель должна предсказать коэффициент восстановления золота из золотосодержащей руды. Используйте данные с параметрами добычи и очистки.
Модель поможет оптимизировать производство, чтобы не запускать предприятие с убыточными характеристиками.
Вам нужно:
- Подготовить данные;
- Провести исследовательский анализ данных;
- Построить и обучить модель.
Чтобы выполнить проект, обращайтесь к библиотекам pandas, matplotlib и sklearn. Вам поможет их документация.
Возможные значения для блока [этап]:
rougher — флотация
primary_cleaner — первичная очистка
secondary_cleaner — вторичная очистка
final — финальные характеристики
Возможные значения для блока [тип_параметра]:
input — параметры сырья
output — параметры продукта
state — параметры, характеризующие текущее состояние этапа
calculation — расчётные характеристики
Подготовка данных¶
Откроем файлы и изучим¶
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import sklearn
from sklearn.linear_model import LinearRegression
from sklearn.tree import DecisionTreeRegressor
from sklearn.ensemble import RandomForestRegressor
from sklearn.dummy import DummyRegressor
from sklearn.model_selection import cross_val_score,GridSearchCV
from sklearn.metrics import mean_absolute_error, make_scorer
df_train = pd.read_csv('/datasets/gold_recovery_train_new.csv', index_col='date')
df_test = pd.read_csv('/datasets/gold_recovery_test_new.csv', index_col='date')
df_full = pd.read_csv('/datasets/gold_recovery_full_new.csv', index_col='date')
Комментарий ревьюера
Все отлично!👍
Данные загрузили.
При считывании данных из файла здорово перестраховывать себя от ошибок, связанных, например, с неверным указанием пути к файлу. А иногда бывает, что работаешь с файлом локально, выгружаешь его на сервер, ожидая, что он будет принимать данные, которые лежат на том же сервере, а код падает с ошибкой, потому что путь к файлу не поменялся с локального на серверный.
Для этого, например, можно использовать конструкцию try-except: сначала пробуешь локальный путь, при возникновении ошибки используется серверный путь (подробнее можешь почитать тут: https://pythonworld.ru/tipy-dannyx-v-python/isklyucheniya-v-python-konstrukciya-try-except-dlya-obrabotki-isklyuchenij.html).
Но еще лучше использовать библиотеку os - её использование позволит тебе проверять существование указанных директорий (что может быть актуально при одновременной работа на локальном и сетевом окружении) и загружать данные из существующей директории, избегая ошибок. Как пример:
import os
pth1 = '/folder_1/data.csv'
pth2 = '/folder_2/data.csv'
if os.path.exists(pth1):
query_1 = pd.read_csv(pth1)
elif os.path.exists(pth2):
query_1 = pd.read_csv(pth2)
else:
print('Something is wrong')
Также ещё на этапе считывания данных можно спарсить дату: за это действие отвечает параметр parse_dates метода read_csv(), в него нужно передать список с названием полей-дат, и в большинстве случаев дата будет корректно преобразована в нужный формат сразу:)
def vision(df):
pd.options.display.max_rows = 100
print(f'Размер ДФ: {df.shape}\n')
print(f'Пропуски: {df.isna().sum()}\n')
print(f'Типы данных: {df.info()}')
display(df.head())
vision(df_train)
Размер ДФ: (14149, 86) Пропуски: final.output.concentrate_ag 1 final.output.concentrate_pb 1 final.output.concentrate_sol 211 final.output.concentrate_au 0 final.output.recovery 0 final.output.tail_ag 0 final.output.tail_pb 100 final.output.tail_sol 5 final.output.tail_au 0 primary_cleaner.input.sulfate 20 primary_cleaner.input.depressant 32 primary_cleaner.input.feed_size 0 primary_cleaner.input.xanthate 100 primary_cleaner.output.concentrate_ag 0 primary_cleaner.output.concentrate_pb 86 primary_cleaner.output.concentrate_sol 286 primary_cleaner.output.concentrate_au 0 primary_cleaner.output.tail_ag 1 primary_cleaner.output.tail_pb 15 primary_cleaner.output.tail_sol 46 primary_cleaner.output.tail_au 0 primary_cleaner.state.floatbank8_a_air 4 primary_cleaner.state.floatbank8_a_level 1 primary_cleaner.state.floatbank8_b_air 4 primary_cleaner.state.floatbank8_b_level 1 primary_cleaner.state.floatbank8_c_air 2 primary_cleaner.state.floatbank8_c_level 1 primary_cleaner.state.floatbank8_d_air 3 primary_cleaner.state.floatbank8_d_level 1 rougher.calculation.sulfate_to_au_concentrate 1 rougher.calculation.floatbank10_sulfate_to_au_feed 1 rougher.calculation.floatbank11_sulfate_to_au_feed 1 rougher.calculation.au_pb_ratio 0 rougher.input.feed_ag 0 rougher.input.feed_pb 100 rougher.input.feed_rate 8 rougher.input.feed_size 144 rougher.input.feed_sol 78 rougher.input.feed_au 0 rougher.input.floatbank10_sulfate 29 rougher.input.floatbank10_xanthate 8 rougher.input.floatbank11_sulfate 36 rougher.input.floatbank11_xanthate 428 rougher.output.concentrate_ag 0 rougher.output.concentrate_pb 0 rougher.output.concentrate_sol 22 rougher.output.concentrate_au 0 rougher.output.recovery 0 rougher.output.tail_ag 1 rougher.output.tail_pb 0 rougher.output.tail_sol 0 rougher.output.tail_au 0 rougher.state.floatbank10_a_air 1 rougher.state.floatbank10_a_level 1 rougher.state.floatbank10_b_air 1 rougher.state.floatbank10_b_level 1 rougher.state.floatbank10_c_air 1 rougher.state.floatbank10_c_level 1 rougher.state.floatbank10_d_air 0 rougher.state.floatbank10_d_level 0 rougher.state.floatbank10_e_air 436 rougher.state.floatbank10_e_level 0 rougher.state.floatbank10_f_air 0 rougher.state.floatbank10_f_level 0 secondary_cleaner.output.tail_ag 2 secondary_cleaner.output.tail_pb 10 secondary_cleaner.output.tail_sol 1605 secondary_cleaner.output.tail_au 0 secondary_cleaner.state.floatbank2_a_air 217 secondary_cleaner.state.floatbank2_a_level 1 secondary_cleaner.state.floatbank2_b_air 21 secondary_cleaner.state.floatbank2_b_level 1 secondary_cleaner.state.floatbank3_a_air 4 secondary_cleaner.state.floatbank3_a_level 1 secondary_cleaner.state.floatbank3_b_air 1 secondary_cleaner.state.floatbank3_b_level 1 secondary_cleaner.state.floatbank4_a_air 6 secondary_cleaner.state.floatbank4_a_level 1 secondary_cleaner.state.floatbank4_b_air 1 secondary_cleaner.state.floatbank4_b_level 1 secondary_cleaner.state.floatbank5_a_air 1 secondary_cleaner.state.floatbank5_a_level 1 secondary_cleaner.state.floatbank5_b_air 1 secondary_cleaner.state.floatbank5_b_level 1 secondary_cleaner.state.floatbank6_a_air 2 secondary_cleaner.state.floatbank6_a_level 1 dtype: int64 <class 'pandas.core.frame.DataFrame'> Index: 14149 entries, 2016-01-15 00:00:00 to 2018-08-18 10:59:59 Data columns (total 86 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 final.output.concentrate_ag 14148 non-null float64 1 final.output.concentrate_pb 14148 non-null float64 2 final.output.concentrate_sol 13938 non-null float64 3 final.output.concentrate_au 14149 non-null float64 4 final.output.recovery 14149 non-null float64 5 final.output.tail_ag 14149 non-null float64 6 final.output.tail_pb 14049 non-null float64 7 final.output.tail_sol 14144 non-null float64 8 final.output.tail_au 14149 non-null float64 9 primary_cleaner.input.sulfate 14129 non-null float64 10 primary_cleaner.input.depressant 14117 non-null float64 11 primary_cleaner.input.feed_size 14149 non-null float64 12 primary_cleaner.input.xanthate 14049 non-null float64 13 primary_cleaner.output.concentrate_ag 14149 non-null float64 14 primary_cleaner.output.concentrate_pb 14063 non-null float64 15 primary_cleaner.output.concentrate_sol 13863 non-null float64 16 primary_cleaner.output.concentrate_au 14149 non-null float64 17 primary_cleaner.output.tail_ag 14148 non-null float64 18 primary_cleaner.output.tail_pb 14134 non-null float64 19 primary_cleaner.output.tail_sol 14103 non-null float64 20 primary_cleaner.output.tail_au 14149 non-null float64 21 primary_cleaner.state.floatbank8_a_air 14145 non-null float64 22 primary_cleaner.state.floatbank8_a_level 14148 non-null float64 23 primary_cleaner.state.floatbank8_b_air 14145 non-null float64 24 primary_cleaner.state.floatbank8_b_level 14148 non-null float64 25 primary_cleaner.state.floatbank8_c_air 14147 non-null float64 26 primary_cleaner.state.floatbank8_c_level 14148 non-null float64 27 primary_cleaner.state.floatbank8_d_air 14146 non-null float64 28 primary_cleaner.state.floatbank8_d_level 14148 non-null float64 29 rougher.calculation.sulfate_to_au_concentrate 14148 non-null float64 30 rougher.calculation.floatbank10_sulfate_to_au_feed 14148 non-null float64 31 rougher.calculation.floatbank11_sulfate_to_au_feed 14148 non-null float64 32 rougher.calculation.au_pb_ratio 14149 non-null float64 33 rougher.input.feed_ag 14149 non-null float64 34 rougher.input.feed_pb 14049 non-null float64 35 rougher.input.feed_rate 14141 non-null float64 36 rougher.input.feed_size 14005 non-null float64 37 rougher.input.feed_sol 14071 non-null float64 38 rougher.input.feed_au 14149 non-null float64 39 rougher.input.floatbank10_sulfate 14120 non-null float64 40 rougher.input.floatbank10_xanthate 14141 non-null float64 41 rougher.input.floatbank11_sulfate 14113 non-null float64 42 rougher.input.floatbank11_xanthate 13721 non-null float64 43 rougher.output.concentrate_ag 14149 non-null float64 44 rougher.output.concentrate_pb 14149 non-null float64 45 rougher.output.concentrate_sol 14127 non-null float64 46 rougher.output.concentrate_au 14149 non-null float64 47 rougher.output.recovery 14149 non-null float64 48 rougher.output.tail_ag 14148 non-null float64 49 rougher.output.tail_pb 14149 non-null float64 50 rougher.output.tail_sol 14149 non-null float64 51 rougher.output.tail_au 14149 non-null float64 52 rougher.state.floatbank10_a_air 14148 non-null float64 53 rougher.state.floatbank10_a_level 14148 non-null float64 54 rougher.state.floatbank10_b_air 14148 non-null float64 55 rougher.state.floatbank10_b_level 14148 non-null float64 56 rougher.state.floatbank10_c_air 14148 non-null float64 57 rougher.state.floatbank10_c_level 14148 non-null float64 58 rougher.state.floatbank10_d_air 14149 non-null float64 59 rougher.state.floatbank10_d_level 14149 non-null float64 60 rougher.state.floatbank10_e_air 13713 non-null float64 61 rougher.state.floatbank10_e_level 14149 non-null float64 62 rougher.state.floatbank10_f_air 14149 non-null float64 63 rougher.state.floatbank10_f_level 14149 non-null float64 64 secondary_cleaner.output.tail_ag 14147 non-null float64 65 secondary_cleaner.output.tail_pb 14139 non-null float64 66 secondary_cleaner.output.tail_sol 12544 non-null float64 67 secondary_cleaner.output.tail_au 14149 non-null float64 68 secondary_cleaner.state.floatbank2_a_air 13932 non-null float64 69 secondary_cleaner.state.floatbank2_a_level 14148 non-null float64 70 secondary_cleaner.state.floatbank2_b_air 14128 non-null float64 71 secondary_cleaner.state.floatbank2_b_level 14148 non-null float64 72 secondary_cleaner.state.floatbank3_a_air 14145 non-null float64 73 secondary_cleaner.state.floatbank3_a_level 14148 non-null float64 74 secondary_cleaner.state.floatbank3_b_air 14148 non-null float64 75 secondary_cleaner.state.floatbank3_b_level 14148 non-null float64 76 secondary_cleaner.state.floatbank4_a_air 14143 non-null float64 77 secondary_cleaner.state.floatbank4_a_level 14148 non-null float64 78 secondary_cleaner.state.floatbank4_b_air 14148 non-null float64 79 secondary_cleaner.state.floatbank4_b_level 14148 non-null float64 80 secondary_cleaner.state.floatbank5_a_air 14148 non-null float64 81 secondary_cleaner.state.floatbank5_a_level 14148 non-null float64 82 secondary_cleaner.state.floatbank5_b_air 14148 non-null float64 83 secondary_cleaner.state.floatbank5_b_level 14148 non-null float64 84 secondary_cleaner.state.floatbank6_a_air 14147 non-null float64 85 secondary_cleaner.state.floatbank6_a_level 14148 non-null float64 dtypes: float64(86) memory usage: 9.4+ MB Типы данных: None
| final.output.concentrate_ag | final.output.concentrate_pb | final.output.concentrate_sol | final.output.concentrate_au | final.output.recovery | final.output.tail_ag | final.output.tail_pb | final.output.tail_sol | final.output.tail_au | primary_cleaner.input.sulfate | ... | secondary_cleaner.state.floatbank4_a_air | secondary_cleaner.state.floatbank4_a_level | secondary_cleaner.state.floatbank4_b_air | secondary_cleaner.state.floatbank4_b_level | secondary_cleaner.state.floatbank5_a_air | secondary_cleaner.state.floatbank5_a_level | secondary_cleaner.state.floatbank5_b_air | secondary_cleaner.state.floatbank5_b_level | secondary_cleaner.state.floatbank6_a_air | secondary_cleaner.state.floatbank6_a_level | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| date | |||||||||||||||||||||
| 2016-01-15 00:00:00 | 6.055403 | 9.889648 | 5.507324 | 42.192020 | 70.541216 | 10.411962 | 0.895447 | 16.904297 | 2.143149 | 127.092003 | ... | 14.016835 | -502.488007 | 12.099931 | -504.715942 | 9.925633 | -498.310211 | 8.079666 | -500.470978 | 14.151341 | -605.841980 |
| 2016-01-15 01:00:00 | 6.029369 | 9.968944 | 5.257781 | 42.701629 | 69.266198 | 10.462676 | 0.927452 | 16.634514 | 2.224930 | 125.629232 | ... | 13.992281 | -505.503262 | 11.950531 | -501.331529 | 10.039245 | -500.169983 | 7.984757 | -500.582168 | 13.998353 | -599.787184 |
| 2016-01-15 02:00:00 | 6.055926 | 10.213995 | 5.383759 | 42.657501 | 68.116445 | 10.507046 | 0.953716 | 16.208849 | 2.257889 | 123.819808 | ... | 14.015015 | -502.520901 | 11.912783 | -501.133383 | 10.070913 | -500.129135 | 8.013877 | -500.517572 | 14.028663 | -601.427363 |
| 2016-01-15 03:00:00 | 6.047977 | 9.977019 | 4.858634 | 42.689819 | 68.347543 | 10.422762 | 0.883763 | 16.532835 | 2.146849 | 122.270188 | ... | 14.036510 | -500.857308 | 11.999550 | -501.193686 | 9.970366 | -499.201640 | 7.977324 | -500.255908 | 14.005551 | -599.996129 |
| 2016-01-15 04:00:00 | 6.148599 | 10.142511 | 4.939416 | 42.774141 | 66.927016 | 10.360302 | 0.792826 | 16.525686 | 2.055292 | 117.988169 | ... | 14.027298 | -499.838632 | 11.953070 | -501.053894 | 9.925709 | -501.686727 | 7.894242 | -500.356035 | 13.996647 | -601.496691 |
5 rows × 86 columns
vision(df_test)
Размер ДФ: (5290, 52) Пропуски: primary_cleaner.input.sulfate 4 primary_cleaner.input.depressant 5 primary_cleaner.input.feed_size 0 primary_cleaner.input.xanthate 4 primary_cleaner.state.floatbank8_a_air 0 primary_cleaner.state.floatbank8_a_level 0 primary_cleaner.state.floatbank8_b_air 0 primary_cleaner.state.floatbank8_b_level 0 primary_cleaner.state.floatbank8_c_air 0 primary_cleaner.state.floatbank8_c_level 0 primary_cleaner.state.floatbank8_d_air 0 primary_cleaner.state.floatbank8_d_level 0 rougher.input.feed_ag 0 rougher.input.feed_pb 0 rougher.input.feed_rate 3 rougher.input.feed_size 1 rougher.input.feed_sol 21 rougher.input.feed_au 0 rougher.input.floatbank10_sulfate 5 rougher.input.floatbank10_xanthate 0 rougher.input.floatbank11_sulfate 8 rougher.input.floatbank11_xanthate 25 rougher.state.floatbank10_a_air 0 rougher.state.floatbank10_a_level 0 rougher.state.floatbank10_b_air 0 rougher.state.floatbank10_b_level 0 rougher.state.floatbank10_c_air 0 rougher.state.floatbank10_c_level 0 rougher.state.floatbank10_d_air 0 rougher.state.floatbank10_d_level 0 rougher.state.floatbank10_e_air 0 rougher.state.floatbank10_e_level 0 rougher.state.floatbank10_f_air 0 rougher.state.floatbank10_f_level 0 secondary_cleaner.state.floatbank2_a_air 3 secondary_cleaner.state.floatbank2_a_level 0 secondary_cleaner.state.floatbank2_b_air 2 secondary_cleaner.state.floatbank2_b_level 0 secondary_cleaner.state.floatbank3_a_air 9 secondary_cleaner.state.floatbank3_a_level 0 secondary_cleaner.state.floatbank3_b_air 0 secondary_cleaner.state.floatbank3_b_level 0 secondary_cleaner.state.floatbank4_a_air 0 secondary_cleaner.state.floatbank4_a_level 0 secondary_cleaner.state.floatbank4_b_air 0 secondary_cleaner.state.floatbank4_b_level 0 secondary_cleaner.state.floatbank5_a_air 0 secondary_cleaner.state.floatbank5_a_level 0 secondary_cleaner.state.floatbank5_b_air 0 secondary_cleaner.state.floatbank5_b_level 0 secondary_cleaner.state.floatbank6_a_air 0 secondary_cleaner.state.floatbank6_a_level 0 dtype: int64 <class 'pandas.core.frame.DataFrame'> Index: 5290 entries, 2016-09-01 00:59:59 to 2017-12-31 23:59:59 Data columns (total 52 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 primary_cleaner.input.sulfate 5286 non-null float64 1 primary_cleaner.input.depressant 5285 non-null float64 2 primary_cleaner.input.feed_size 5290 non-null float64 3 primary_cleaner.input.xanthate 5286 non-null float64 4 primary_cleaner.state.floatbank8_a_air 5290 non-null float64 5 primary_cleaner.state.floatbank8_a_level 5290 non-null float64 6 primary_cleaner.state.floatbank8_b_air 5290 non-null float64 7 primary_cleaner.state.floatbank8_b_level 5290 non-null float64 8 primary_cleaner.state.floatbank8_c_air 5290 non-null float64 9 primary_cleaner.state.floatbank8_c_level 5290 non-null float64 10 primary_cleaner.state.floatbank8_d_air 5290 non-null float64 11 primary_cleaner.state.floatbank8_d_level 5290 non-null float64 12 rougher.input.feed_ag 5290 non-null float64 13 rougher.input.feed_pb 5290 non-null float64 14 rougher.input.feed_rate 5287 non-null float64 15 rougher.input.feed_size 5289 non-null float64 16 rougher.input.feed_sol 5269 non-null float64 17 rougher.input.feed_au 5290 non-null float64 18 rougher.input.floatbank10_sulfate 5285 non-null float64 19 rougher.input.floatbank10_xanthate 5290 non-null float64 20 rougher.input.floatbank11_sulfate 5282 non-null float64 21 rougher.input.floatbank11_xanthate 5265 non-null float64 22 rougher.state.floatbank10_a_air 5290 non-null float64 23 rougher.state.floatbank10_a_level 5290 non-null float64 24 rougher.state.floatbank10_b_air 5290 non-null float64 25 rougher.state.floatbank10_b_level 5290 non-null float64 26 rougher.state.floatbank10_c_air 5290 non-null float64 27 rougher.state.floatbank10_c_level 5290 non-null float64 28 rougher.state.floatbank10_d_air 5290 non-null float64 29 rougher.state.floatbank10_d_level 5290 non-null float64 30 rougher.state.floatbank10_e_air 5290 non-null float64 31 rougher.state.floatbank10_e_level 5290 non-null float64 32 rougher.state.floatbank10_f_air 5290 non-null float64 33 rougher.state.floatbank10_f_level 5290 non-null float64 34 secondary_cleaner.state.floatbank2_a_air 5287 non-null float64 35 secondary_cleaner.state.floatbank2_a_level 5290 non-null float64 36 secondary_cleaner.state.floatbank2_b_air 5288 non-null float64 37 secondary_cleaner.state.floatbank2_b_level 5290 non-null float64 38 secondary_cleaner.state.floatbank3_a_air 5281 non-null float64 39 secondary_cleaner.state.floatbank3_a_level 5290 non-null float64 40 secondary_cleaner.state.floatbank3_b_air 5290 non-null float64 41 secondary_cleaner.state.floatbank3_b_level 5290 non-null float64 42 secondary_cleaner.state.floatbank4_a_air 5290 non-null float64 43 secondary_cleaner.state.floatbank4_a_level 5290 non-null float64 44 secondary_cleaner.state.floatbank4_b_air 5290 non-null float64 45 secondary_cleaner.state.floatbank4_b_level 5290 non-null float64 46 secondary_cleaner.state.floatbank5_a_air 5290 non-null float64 47 secondary_cleaner.state.floatbank5_a_level 5290 non-null float64 48 secondary_cleaner.state.floatbank5_b_air 5290 non-null float64 49 secondary_cleaner.state.floatbank5_b_level 5290 non-null float64 50 secondary_cleaner.state.floatbank6_a_air 5290 non-null float64 51 secondary_cleaner.state.floatbank6_a_level 5290 non-null float64 dtypes: float64(52) memory usage: 2.1+ MB Типы данных: None
| primary_cleaner.input.sulfate | primary_cleaner.input.depressant | primary_cleaner.input.feed_size | primary_cleaner.input.xanthate | primary_cleaner.state.floatbank8_a_air | primary_cleaner.state.floatbank8_a_level | primary_cleaner.state.floatbank8_b_air | primary_cleaner.state.floatbank8_b_level | primary_cleaner.state.floatbank8_c_air | primary_cleaner.state.floatbank8_c_level | ... | secondary_cleaner.state.floatbank4_a_air | secondary_cleaner.state.floatbank4_a_level | secondary_cleaner.state.floatbank4_b_air | secondary_cleaner.state.floatbank4_b_level | secondary_cleaner.state.floatbank5_a_air | secondary_cleaner.state.floatbank5_a_level | secondary_cleaner.state.floatbank5_b_air | secondary_cleaner.state.floatbank5_b_level | secondary_cleaner.state.floatbank6_a_air | secondary_cleaner.state.floatbank6_a_level | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| date | |||||||||||||||||||||
| 2016-09-01 00:59:59 | 210.800909 | 14.993118 | 8.080000 | 1.005021 | 1398.981301 | -500.225577 | 1399.144926 | -499.919735 | 1400.102998 | -500.704369 | ... | 12.023554 | -497.795834 | 8.016656 | -501.289139 | 7.946562 | -432.317850 | 4.872511 | -500.037437 | 26.705889 | -499.709414 |
| 2016-09-01 01:59:59 | 215.392455 | 14.987471 | 8.080000 | 0.990469 | 1398.777912 | -500.057435 | 1398.055362 | -499.778182 | 1396.151033 | -499.240168 | ... | 12.058140 | -498.695773 | 8.130979 | -499.634209 | 7.958270 | -525.839648 | 4.878850 | -500.162375 | 25.019940 | -499.819438 |
| 2016-09-01 02:59:59 | 215.259946 | 12.884934 | 7.786667 | 0.996043 | 1398.493666 | -500.868360 | 1398.860436 | -499.764529 | 1398.075709 | -502.151509 | ... | 11.962366 | -498.767484 | 8.096893 | -500.827423 | 8.071056 | -500.801673 | 4.905125 | -499.828510 | 24.994862 | -500.622559 |
| 2016-09-01 03:59:59 | 215.336236 | 12.006805 | 7.640000 | 0.863514 | 1399.618111 | -498.863574 | 1397.440120 | -499.211024 | 1400.129303 | -498.355873 | ... | 12.033091 | -498.350935 | 8.074946 | -499.474407 | 7.897085 | -500.868509 | 4.931400 | -499.963623 | 24.948919 | -498.709987 |
| 2016-09-01 04:59:59 | 199.099327 | 10.682530 | 7.530000 | 0.805575 | 1401.268123 | -500.808305 | 1398.128818 | -499.504543 | 1402.172226 | -500.810606 | ... | 12.025367 | -500.786497 | 8.054678 | -500.397500 | 8.107890 | -509.526725 | 4.957674 | -500.360026 | 25.003331 | -500.856333 |
5 rows × 52 columns
vision(df_full)
Размер ДФ: (19439, 86) Пропуски: final.output.concentrate_ag 1 final.output.concentrate_pb 1 final.output.concentrate_sol 211 final.output.concentrate_au 0 final.output.recovery 0 final.output.tail_ag 1 final.output.tail_pb 101 final.output.tail_sol 6 final.output.tail_au 0 primary_cleaner.input.sulfate 24 primary_cleaner.input.depressant 37 primary_cleaner.input.feed_size 0 primary_cleaner.input.xanthate 104 primary_cleaner.output.concentrate_ag 0 primary_cleaner.output.concentrate_pb 116 primary_cleaner.output.concentrate_sol 370 primary_cleaner.output.concentrate_au 0 primary_cleaner.output.tail_ag 4 primary_cleaner.output.tail_pb 21 primary_cleaner.output.tail_sol 62 primary_cleaner.output.tail_au 0 primary_cleaner.state.floatbank8_a_air 4 primary_cleaner.state.floatbank8_a_level 1 primary_cleaner.state.floatbank8_b_air 4 primary_cleaner.state.floatbank8_b_level 1 primary_cleaner.state.floatbank8_c_air 2 primary_cleaner.state.floatbank8_c_level 1 primary_cleaner.state.floatbank8_d_air 3 primary_cleaner.state.floatbank8_d_level 1 rougher.calculation.sulfate_to_au_concentrate 2 rougher.calculation.floatbank10_sulfate_to_au_feed 2 rougher.calculation.floatbank11_sulfate_to_au_feed 2 rougher.calculation.au_pb_ratio 0 rougher.input.feed_ag 0 rougher.input.feed_pb 100 rougher.input.feed_rate 11 rougher.input.feed_size 145 rougher.input.feed_sol 99 rougher.input.feed_au 0 rougher.input.floatbank10_sulfate 34 rougher.input.floatbank10_xanthate 8 rougher.input.floatbank11_sulfate 44 rougher.input.floatbank11_xanthate 453 rougher.output.concentrate_ag 0 rougher.output.concentrate_pb 0 rougher.output.concentrate_sol 23 rougher.output.concentrate_au 0 rougher.output.recovery 0 rougher.output.tail_ag 1 rougher.output.tail_pb 0 rougher.output.tail_sol 0 rougher.output.tail_au 0 rougher.state.floatbank10_a_air 1 rougher.state.floatbank10_a_level 1 rougher.state.floatbank10_b_air 1 rougher.state.floatbank10_b_level 1 rougher.state.floatbank10_c_air 1 rougher.state.floatbank10_c_level 1 rougher.state.floatbank10_d_air 0 rougher.state.floatbank10_d_level 0 rougher.state.floatbank10_e_air 436 rougher.state.floatbank10_e_level 0 rougher.state.floatbank10_f_air 0 rougher.state.floatbank10_f_level 0 secondary_cleaner.output.tail_ag 2 secondary_cleaner.output.tail_pb 12 secondary_cleaner.output.tail_sol 1748 secondary_cleaner.output.tail_au 0 secondary_cleaner.state.floatbank2_a_air 220 secondary_cleaner.state.floatbank2_a_level 1 secondary_cleaner.state.floatbank2_b_air 23 secondary_cleaner.state.floatbank2_b_level 1 secondary_cleaner.state.floatbank3_a_air 13 secondary_cleaner.state.floatbank3_a_level 1 secondary_cleaner.state.floatbank3_b_air 1 secondary_cleaner.state.floatbank3_b_level 1 secondary_cleaner.state.floatbank4_a_air 6 secondary_cleaner.state.floatbank4_a_level 1 secondary_cleaner.state.floatbank4_b_air 1 secondary_cleaner.state.floatbank4_b_level 1 secondary_cleaner.state.floatbank5_a_air 1 secondary_cleaner.state.floatbank5_a_level 1 secondary_cleaner.state.floatbank5_b_air 1 secondary_cleaner.state.floatbank5_b_level 1 secondary_cleaner.state.floatbank6_a_air 2 secondary_cleaner.state.floatbank6_a_level 1 dtype: int64 <class 'pandas.core.frame.DataFrame'> Index: 19439 entries, 2016-01-15 00:00:00 to 2018-08-18 10:59:59 Data columns (total 86 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 final.output.concentrate_ag 19438 non-null float64 1 final.output.concentrate_pb 19438 non-null float64 2 final.output.concentrate_sol 19228 non-null float64 3 final.output.concentrate_au 19439 non-null float64 4 final.output.recovery 19439 non-null float64 5 final.output.tail_ag 19438 non-null float64 6 final.output.tail_pb 19338 non-null float64 7 final.output.tail_sol 19433 non-null float64 8 final.output.tail_au 19439 non-null float64 9 primary_cleaner.input.sulfate 19415 non-null float64 10 primary_cleaner.input.depressant 19402 non-null float64 11 primary_cleaner.input.feed_size 19439 non-null float64 12 primary_cleaner.input.xanthate 19335 non-null float64 13 primary_cleaner.output.concentrate_ag 19439 non-null float64 14 primary_cleaner.output.concentrate_pb 19323 non-null float64 15 primary_cleaner.output.concentrate_sol 19069 non-null float64 16 primary_cleaner.output.concentrate_au 19439 non-null float64 17 primary_cleaner.output.tail_ag 19435 non-null float64 18 primary_cleaner.output.tail_pb 19418 non-null float64 19 primary_cleaner.output.tail_sol 19377 non-null float64 20 primary_cleaner.output.tail_au 19439 non-null float64 21 primary_cleaner.state.floatbank8_a_air 19435 non-null float64 22 primary_cleaner.state.floatbank8_a_level 19438 non-null float64 23 primary_cleaner.state.floatbank8_b_air 19435 non-null float64 24 primary_cleaner.state.floatbank8_b_level 19438 non-null float64 25 primary_cleaner.state.floatbank8_c_air 19437 non-null float64 26 primary_cleaner.state.floatbank8_c_level 19438 non-null float64 27 primary_cleaner.state.floatbank8_d_air 19436 non-null float64 28 primary_cleaner.state.floatbank8_d_level 19438 non-null float64 29 rougher.calculation.sulfate_to_au_concentrate 19437 non-null float64 30 rougher.calculation.floatbank10_sulfate_to_au_feed 19437 non-null float64 31 rougher.calculation.floatbank11_sulfate_to_au_feed 19437 non-null float64 32 rougher.calculation.au_pb_ratio 19439 non-null float64 33 rougher.input.feed_ag 19439 non-null float64 34 rougher.input.feed_pb 19339 non-null float64 35 rougher.input.feed_rate 19428 non-null float64 36 rougher.input.feed_size 19294 non-null float64 37 rougher.input.feed_sol 19340 non-null float64 38 rougher.input.feed_au 19439 non-null float64 39 rougher.input.floatbank10_sulfate 19405 non-null float64 40 rougher.input.floatbank10_xanthate 19431 non-null float64 41 rougher.input.floatbank11_sulfate 19395 non-null float64 42 rougher.input.floatbank11_xanthate 18986 non-null float64 43 rougher.output.concentrate_ag 19439 non-null float64 44 rougher.output.concentrate_pb 19439 non-null float64 45 rougher.output.concentrate_sol 19416 non-null float64 46 rougher.output.concentrate_au 19439 non-null float64 47 rougher.output.recovery 19439 non-null float64 48 rougher.output.tail_ag 19438 non-null float64 49 rougher.output.tail_pb 19439 non-null float64 50 rougher.output.tail_sol 19439 non-null float64 51 rougher.output.tail_au 19439 non-null float64 52 rougher.state.floatbank10_a_air 19438 non-null float64 53 rougher.state.floatbank10_a_level 19438 non-null float64 54 rougher.state.floatbank10_b_air 19438 non-null float64 55 rougher.state.floatbank10_b_level 19438 non-null float64 56 rougher.state.floatbank10_c_air 19438 non-null float64 57 rougher.state.floatbank10_c_level 19438 non-null float64 58 rougher.state.floatbank10_d_air 19439 non-null float64 59 rougher.state.floatbank10_d_level 19439 non-null float64 60 rougher.state.floatbank10_e_air 19003 non-null float64 61 rougher.state.floatbank10_e_level 19439 non-null float64 62 rougher.state.floatbank10_f_air 19439 non-null float64 63 rougher.state.floatbank10_f_level 19439 non-null float64 64 secondary_cleaner.output.tail_ag 19437 non-null float64 65 secondary_cleaner.output.tail_pb 19427 non-null float64 66 secondary_cleaner.output.tail_sol 17691 non-null float64 67 secondary_cleaner.output.tail_au 19439 non-null float64 68 secondary_cleaner.state.floatbank2_a_air 19219 non-null float64 69 secondary_cleaner.state.floatbank2_a_level 19438 non-null float64 70 secondary_cleaner.state.floatbank2_b_air 19416 non-null float64 71 secondary_cleaner.state.floatbank2_b_level 19438 non-null float64 72 secondary_cleaner.state.floatbank3_a_air 19426 non-null float64 73 secondary_cleaner.state.floatbank3_a_level 19438 non-null float64 74 secondary_cleaner.state.floatbank3_b_air 19438 non-null float64 75 secondary_cleaner.state.floatbank3_b_level 19438 non-null float64 76 secondary_cleaner.state.floatbank4_a_air 19433 non-null float64 77 secondary_cleaner.state.floatbank4_a_level 19438 non-null float64 78 secondary_cleaner.state.floatbank4_b_air 19438 non-null float64 79 secondary_cleaner.state.floatbank4_b_level 19438 non-null float64 80 secondary_cleaner.state.floatbank5_a_air 19438 non-null float64 81 secondary_cleaner.state.floatbank5_a_level 19438 non-null float64 82 secondary_cleaner.state.floatbank5_b_air 19438 non-null float64 83 secondary_cleaner.state.floatbank5_b_level 19438 non-null float64 84 secondary_cleaner.state.floatbank6_a_air 19437 non-null float64 85 secondary_cleaner.state.floatbank6_a_level 19438 non-null float64 dtypes: float64(86) memory usage: 12.9+ MB Типы данных: None
| final.output.concentrate_ag | final.output.concentrate_pb | final.output.concentrate_sol | final.output.concentrate_au | final.output.recovery | final.output.tail_ag | final.output.tail_pb | final.output.tail_sol | final.output.tail_au | primary_cleaner.input.sulfate | ... | secondary_cleaner.state.floatbank4_a_air | secondary_cleaner.state.floatbank4_a_level | secondary_cleaner.state.floatbank4_b_air | secondary_cleaner.state.floatbank4_b_level | secondary_cleaner.state.floatbank5_a_air | secondary_cleaner.state.floatbank5_a_level | secondary_cleaner.state.floatbank5_b_air | secondary_cleaner.state.floatbank5_b_level | secondary_cleaner.state.floatbank6_a_air | secondary_cleaner.state.floatbank6_a_level | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| date | |||||||||||||||||||||
| 2016-01-15 00:00:00 | 6.055403 | 9.889648 | 5.507324 | 42.192020 | 70.541216 | 10.411962 | 0.895447 | 16.904297 | 2.143149 | 127.092003 | ... | 14.016835 | -502.488007 | 12.099931 | -504.715942 | 9.925633 | -498.310211 | 8.079666 | -500.470978 | 14.151341 | -605.841980 |
| 2016-01-15 01:00:00 | 6.029369 | 9.968944 | 5.257781 | 42.701629 | 69.266198 | 10.462676 | 0.927452 | 16.634514 | 2.224930 | 125.629232 | ... | 13.992281 | -505.503262 | 11.950531 | -501.331529 | 10.039245 | -500.169983 | 7.984757 | -500.582168 | 13.998353 | -599.787184 |
| 2016-01-15 02:00:00 | 6.055926 | 10.213995 | 5.383759 | 42.657501 | 68.116445 | 10.507046 | 0.953716 | 16.208849 | 2.257889 | 123.819808 | ... | 14.015015 | -502.520901 | 11.912783 | -501.133383 | 10.070913 | -500.129135 | 8.013877 | -500.517572 | 14.028663 | -601.427363 |
| 2016-01-15 03:00:00 | 6.047977 | 9.977019 | 4.858634 | 42.689819 | 68.347543 | 10.422762 | 0.883763 | 16.532835 | 2.146849 | 122.270188 | ... | 14.036510 | -500.857308 | 11.999550 | -501.193686 | 9.970366 | -499.201640 | 7.977324 | -500.255908 | 14.005551 | -599.996129 |
| 2016-01-15 04:00:00 | 6.148599 | 10.142511 | 4.939416 | 42.774141 | 66.927016 | 10.360302 | 0.792826 | 16.525686 | 2.055292 | 117.988169 | ... | 14.027298 | -499.838632 | 11.953070 | -501.053894 | 9.925709 | -501.686727 | 7.894242 | -500.356035 | 13.996647 | -601.496691 |
5 rows × 86 columns
Данные представлены типом "float". И соответсвует действительности.
Данные имеют пропуски. Пропуски возникли по нескольким причинам: расчетные значения просто были не подсчитаны, есть возможность простой ошибки оператора или ошибки оборудования.
Нет пропусков в колонках наших целевых признаков "rougher.output.recovery", "final.output.recovery"
Размеры обучающей и тестовых выборок разный. Для обучения модели придется приводить к одному "масштабу".
Расчет метрики MAE на обучающей выборке по признаку "rougher.output.recovery"¶
Эффективность обогащения рассчитывается по формуле
C — доля золота в концентрате после флотации/очистки;
F — доля золота в сырье/концентрате до флотации/очистки;
T — доля золота в отвальных хвостах после флотации/очистки.
def calculate_1(rougher_output, rougher_input, rougher_tail):
recovery = (rougher_output * (rougher_input - rougher_tail))/(rougher_input * (rougher_output - rougher_tail)) * 100
return recovery
recovery_train = calculate_1(df_train['rougher.output.concentrate_au'],
df_train['rougher.input.feed_au'],
df_train['rougher.output.tail_au'])
print(recovery_train.describe(),'\n') # проверка, того что мы не выходим за рамки 100% (ошибки они такие)
MAE_train = mean_absolute_error(df_train['rougher.output.recovery'], recovery_train)
print(f'Средне квадратичная ошибка: {MAE_train}' )
count 14149.000000 mean 82.704502 std 14.479156 min -0.000000 25% 79.993067 50% 85.299462 75% 90.165021 max 100.000000 dtype: float64 Средне квадратичная ошибка: 9.73512347450521e-15
Отсутствующие колонки в тестовой выборке¶
count = 0
for i in df_train.columns:
if i in df_test:
count +=1
else:
print(i)
print(count)
final.output.concentrate_ag final.output.concentrate_pb final.output.concentrate_sol final.output.concentrate_au final.output.recovery final.output.tail_ag final.output.tail_pb final.output.tail_sol final.output.tail_au primary_cleaner.output.concentrate_ag primary_cleaner.output.concentrate_pb primary_cleaner.output.concentrate_sol primary_cleaner.output.concentrate_au primary_cleaner.output.tail_ag primary_cleaner.output.tail_pb primary_cleaner.output.tail_sol primary_cleaner.output.tail_au rougher.calculation.sulfate_to_au_concentrate rougher.calculation.floatbank10_sulfate_to_au_feed rougher.calculation.floatbank11_sulfate_to_au_feed rougher.calculation.au_pb_ratio rougher.output.concentrate_ag rougher.output.concentrate_pb rougher.output.concentrate_sol rougher.output.concentrate_au rougher.output.recovery rougher.output.tail_ag rougher.output.tail_pb rougher.output.tail_sol rougher.output.tail_au secondary_cleaner.output.tail_ag secondary_cleaner.output.tail_pb secondary_cleaner.output.tail_sol secondary_cleaner.output.tail_au 52
Предобработка данных¶
Посмотрим пропуски в процентном соотношение, для гипотетического определения возможных потерь.
Заполним пропуски или устраним.
Посмотри размах данных по важным этапам (не только целевые признаки). Определим, что можно исправить.
Проверим есть аорреляция в данных.
print(df_test.isna().sum().sort_values(ascending =False) / len(df_test.index) * 100)
rougher.input.floatbank11_xanthate 0.472590 rougher.input.feed_sol 0.396975 secondary_cleaner.state.floatbank3_a_air 0.170132 rougher.input.floatbank11_sulfate 0.151229 primary_cleaner.input.depressant 0.094518 rougher.input.floatbank10_sulfate 0.094518 primary_cleaner.input.sulfate 0.075614 primary_cleaner.input.xanthate 0.075614 rougher.input.feed_rate 0.056711 secondary_cleaner.state.floatbank2_a_air 0.056711 secondary_cleaner.state.floatbank2_b_air 0.037807 rougher.input.feed_size 0.018904 secondary_cleaner.state.floatbank3_b_level 0.000000 secondary_cleaner.state.floatbank3_b_air 0.000000 rougher.state.floatbank10_f_air 0.000000 rougher.state.floatbank10_f_level 0.000000 secondary_cleaner.state.floatbank6_a_air 0.000000 secondary_cleaner.state.floatbank5_b_level 0.000000 secondary_cleaner.state.floatbank2_a_level 0.000000 secondary_cleaner.state.floatbank5_b_air 0.000000 secondary_cleaner.state.floatbank2_b_level 0.000000 secondary_cleaner.state.floatbank5_a_level 0.000000 secondary_cleaner.state.floatbank5_a_air 0.000000 secondary_cleaner.state.floatbank4_b_level 0.000000 secondary_cleaner.state.floatbank4_b_air 0.000000 secondary_cleaner.state.floatbank3_a_level 0.000000 secondary_cleaner.state.floatbank4_a_level 0.000000 rougher.state.floatbank10_e_air 0.000000 secondary_cleaner.state.floatbank4_a_air 0.000000 rougher.state.floatbank10_e_level 0.000000 rougher.state.floatbank10_c_air 0.000000 rougher.state.floatbank10_d_level 0.000000 primary_cleaner.state.floatbank8_d_level 0.000000 primary_cleaner.input.feed_size 0.000000 primary_cleaner.state.floatbank8_a_air 0.000000 primary_cleaner.state.floatbank8_a_level 0.000000 primary_cleaner.state.floatbank8_b_air 0.000000 primary_cleaner.state.floatbank8_b_level 0.000000 primary_cleaner.state.floatbank8_c_air 0.000000 primary_cleaner.state.floatbank8_c_level 0.000000 primary_cleaner.state.floatbank8_d_air 0.000000 rougher.input.feed_ag 0.000000 rougher.state.floatbank10_d_air 0.000000 rougher.input.feed_pb 0.000000 rougher.input.feed_au 0.000000 rougher.input.floatbank10_xanthate 0.000000 rougher.state.floatbank10_a_air 0.000000 rougher.state.floatbank10_a_level 0.000000 rougher.state.floatbank10_b_air 0.000000 rougher.state.floatbank10_b_level 0.000000 rougher.state.floatbank10_c_level 0.000000 secondary_cleaner.state.floatbank6_a_level 0.000000 dtype: float64
print(df_train.isna().sum().sort_values(ascending =False) / len(df_train.index) * 100)
secondary_cleaner.output.tail_sol 11.343558 rougher.state.floatbank10_e_air 3.081490 rougher.input.floatbank11_xanthate 3.024949 primary_cleaner.output.concentrate_sol 2.021344 secondary_cleaner.state.floatbank2_a_air 1.533677 final.output.concentrate_sol 1.491271 rougher.input.feed_size 1.017740 rougher.input.feed_pb 0.706764 final.output.tail_pb 0.706764 primary_cleaner.input.xanthate 0.706764 primary_cleaner.output.concentrate_pb 0.607817 rougher.input.feed_sol 0.551276 primary_cleaner.output.tail_sol 0.325111 rougher.input.floatbank11_sulfate 0.254435 primary_cleaner.input.depressant 0.226164 rougher.input.floatbank10_sulfate 0.204961 rougher.output.concentrate_sol 0.155488 secondary_cleaner.state.floatbank2_b_air 0.148420 primary_cleaner.input.sulfate 0.141353 primary_cleaner.output.tail_pb 0.106015 secondary_cleaner.output.tail_pb 0.070676 rougher.input.floatbank10_xanthate 0.056541 rougher.input.feed_rate 0.056541 secondary_cleaner.state.floatbank4_a_air 0.042406 final.output.tail_sol 0.035338 primary_cleaner.state.floatbank8_b_air 0.028271 primary_cleaner.state.floatbank8_a_air 0.028271 secondary_cleaner.state.floatbank3_a_air 0.028271 primary_cleaner.state.floatbank8_d_air 0.021203 secondary_cleaner.output.tail_ag 0.014135 secondary_cleaner.state.floatbank6_a_air 0.014135 primary_cleaner.state.floatbank8_c_air 0.014135 rougher.state.floatbank10_c_level 0.007068 rougher.state.floatbank10_c_air 0.007068 rougher.state.floatbank10_b_level 0.007068 rougher.state.floatbank10_b_air 0.007068 final.output.concentrate_ag 0.007068 secondary_cleaner.state.floatbank2_a_level 0.007068 secondary_cleaner.state.floatbank2_b_level 0.007068 secondary_cleaner.state.floatbank3_a_level 0.007068 rougher.state.floatbank10_a_air 0.007068 secondary_cleaner.state.floatbank3_b_air 0.007068 secondary_cleaner.state.floatbank3_b_level 0.007068 secondary_cleaner.state.floatbank4_a_level 0.007068 secondary_cleaner.state.floatbank4_b_air 0.007068 secondary_cleaner.state.floatbank4_b_level 0.007068 secondary_cleaner.state.floatbank5_a_air 0.007068 secondary_cleaner.state.floatbank5_a_level 0.007068 secondary_cleaner.state.floatbank5_b_air 0.007068 secondary_cleaner.state.floatbank5_b_level 0.007068 rougher.state.floatbank10_a_level 0.007068 secondary_cleaner.state.floatbank6_a_level 0.007068 rougher.calculation.floatbank11_sulfate_to_au_feed 0.007068 rougher.calculation.floatbank10_sulfate_to_au_feed 0.007068 primary_cleaner.state.floatbank8_d_level 0.007068 primary_cleaner.state.floatbank8_c_level 0.007068 primary_cleaner.state.floatbank8_b_level 0.007068 primary_cleaner.state.floatbank8_a_level 0.007068 final.output.concentrate_pb 0.007068 primary_cleaner.output.tail_ag 0.007068 rougher.calculation.sulfate_to_au_concentrate 0.007068 rougher.output.tail_ag 0.007068 primary_cleaner.output.concentrate_ag 0.000000 primary_cleaner.input.feed_size 0.000000 primary_cleaner.output.tail_au 0.000000 final.output.tail_au 0.000000 final.output.tail_ag 0.000000 final.output.recovery 0.000000 final.output.concentrate_au 0.000000 primary_cleaner.output.concentrate_au 0.000000 rougher.output.tail_au 0.000000 rougher.output.tail_sol 0.000000 rougher.calculation.au_pb_ratio 0.000000 secondary_cleaner.output.tail_au 0.000000 rougher.input.feed_ag 0.000000 rougher.input.feed_au 0.000000 rougher.state.floatbank10_f_level 0.000000 rougher.state.floatbank10_f_air 0.000000 rougher.state.floatbank10_e_level 0.000000 rougher.output.concentrate_pb 0.000000 rougher.state.floatbank10_d_level 0.000000 rougher.state.floatbank10_d_air 0.000000 rougher.output.concentrate_au 0.000000 rougher.output.recovery 0.000000 rougher.output.tail_pb 0.000000 rougher.output.concentrate_ag 0.000000 dtype: float64
Заполним пропуски¶
Т.к. соседние по времени параметры часто похожи заполним пропуски используя метод fillna с атрибутом "ffill". И количество пропусков относительно не велико, значит ошибки которые мы можем внести, минимальны.
df_train.fillna(method='ffill', inplace = True)
df_test.fillna(method='ffill', inplace = True)
print(f'Кол-во пропусков в обучающем ДФ: {df_train.isna().sum().sum()}')
print(f'Кол-во пропусков в тестовом ДФ: {df_test.isna().sum().sum()}')
Кол-во пропусков в обучающем ДФ: 0 Кол-во пропусков в тестовом ДФ: 0
Посмотрим на распределения по этапам и материалам¶
list_parametrs = list_parametrs =['rougher.input.feed_', 'rougher.output.concentrate_',
'primary_cleaner.output.concentrate_', 'final.output.concentrate_']
for i in list_parametrs:
for j in ['au','ag','pb','sol']:
df_train.boxplot(column=[i+j],figsize =(8,4))
plt.title('Диаграмма размаха значений: ' + i +j)
plt.ylabel('Values')
plt.show()
df_train.boxplot(column=['final.output.recovery'])
plt.title('Распределение по данным AU после финальной обработки')
plt.ylabel('Values')
plt.show()
df_train['final.output.recovery'].hist(bins=200)
plt.title('Распределение концентрата AU после финальной обработки')
plt.ylabel('Frequency')
plt.xlabel('Concetrate')
plt.show()
df_train.boxplot(column=['rougher.output.recovery'])
plt.ylabel('Values')
plt.title('Распределение по данным AU после первичной обработки')
plt.show()
df_train['rougher.output.recovery'].hist(bins=200, grid =True)
plt.title('Распределение концентрата AU после первичной обработки')
plt.ylabel('Frequency')
plt.xlabel('Concetrate')
plt.show()
df_train[['rougher.input.feed_au', 'rougher.output.concentrate_au','primary_cleaner.output.concentrate_au','final.output.concentrate_au','final.output.recovery','rougher.output.recovery']].corr()
| rougher.input.feed_au | rougher.output.concentrate_au | primary_cleaner.output.concentrate_au | final.output.concentrate_au | final.output.recovery | rougher.output.recovery | |
|---|---|---|---|---|---|---|
| rougher.input.feed_au | 1.000000 | 0.216925 | -0.081709 | 0.010324 | 0.308561 | 0.156173 |
| rougher.output.concentrate_au | 0.216925 | 1.000000 | 0.140787 | 0.072396 | -0.033718 | 0.556946 |
| primary_cleaner.output.concentrate_au | -0.081709 | 0.140787 | 1.000000 | 0.220862 | -0.145282 | -0.114044 |
| final.output.concentrate_au | 0.010324 | 0.072396 | 0.220862 | 1.000000 | 0.253067 | 0.084274 |
| final.output.recovery | 0.308561 | -0.033718 | -0.145282 | 0.253067 | 1.000000 | 0.328307 |
| rougher.output.recovery | 0.156173 | 0.556946 | -0.114044 | 0.084274 | 0.328307 | 1.000000 |
1) Пропуски заполнили используя метод fillna(method='ffill'), что позволительно было при постановке задачи.
2) Сильных линейных взаимосвязей по этапам и материалам не выявленно.
3) Исходя из вида граффиков целевых показателей, можно судить о нормальности распределения.
4) Имеются аномалии-выбросы, но на данном этапе от них избавлятся не стоит. Потеря данных будет велика. Нужно будет ввести связующее значение. После чего отталкиваясь от этого устранить аномалии.
Анализ данных¶
Изменение концентрации на различных этапах очистки¶
list_parametrs =['rougher.input.feed_', 'rougher.output.concentrate_',
'primary_cleaner.output.concentrate_', 'final.output.concentrate_']
def plot_materials(df, list_p, material):
for i in list_p:
df[i+material].plot(kind='hist',
bins=200,
grid=True,
legend=True,
figsize=(15, 5),
alpha=0.5,
title =('Концентрация '+ material.upper()))
plt.xlabel('Concetration')
plot_materials(df_train, list_parametrs, 'au')
plot_materials(df_train, list_parametrs, 'ag')
plot_materials(df_train, list_parametrs, 'pb')
plt.show()
Сравнение распределения размеров гранул сырья на обучающей и тестовой выборках¶
list_parametrs = ['rougher.input.feed_size', 'primary_cleaner.input.feed_size']
for i in list_parametrs:
sns.kdeplot(data =df_test, x = i, label ='Тестовая выборка')
sns.kdeplot(data =df_train, x = i, label ='Обучающая выборка')
plt.plot(figsize=(7,4))
plt.grid(True,color='black', linestyle='-.')
plt.legend()
plt.title('Распределение плотности ' + i)
plt.xlabel('Values')
plt.show()
# plt.legend()
# plt.ylim(0,0.08)
# df_train[i].plot(kind='hist',
# bins=200,
# legend = True,
# alpha=0.5)
# df_test[i].plot(kind='hist',
# bins=200,
# alpha=0.5,
# legend = True,
# grid = True,
# #xlim =(0,125),
# #figsize =(12,5),
# title ='Распределение размера частиц')
# plt.xlabel('Size')
# plt.show()
Исследование суммарной концентрации всех веществ на разных стадиях: в сырье, в черновом и финальном концентрата¶
Добавим 4 колонки по суммарным значениям на каждом этапе. И здесь же можно будет обработать выбивающиеся значения. Это очень важно при обучении моделей.
list_parametrs =['rougher.input.feed', 'rougher.output.concentrate',
'primary_cleaner.output.concentrate', 'final.output.concentrate']
materials = ['_au', '_ag', '_pb', '_sol']
for i in list_parametrs:
df_train[i+'_sum'] = 0
for j in materials:
df_train[i+'_sum'] += df_train[i+j]
df_train[i+'_sum'].plot(kind='hist',
bins = 80,
grid =True,
legend =True,
title ='Суммарная концентрация на этапе ' + i)
plt.xlabel('Concentration')
plt.show()
print(df_train[i+'_sum'].describe())
df_train.boxplot(column=[i+'_sum'])
plt.ylabel('Values')
plt.title('Диаграмма размаха для '+ i)
plt.show()
count 14149.000000 mean 56.242170 std 7.029808 min 0.040000 25% 52.573579 50% 56.627635 75% 60.763234 max 74.458253 Name: rougher.input.feed_sum, dtype: float64
count 14149.000000 mean 67.173145 std 12.713129 min 0.000000 25% 64.914390 50% 69.175663 75% 73.429261 max 88.140119 Name: rougher.output.concentrate_sum, dtype: float64
count 14149.000000 mean 60.172546 std 10.448165 min 0.000000 25% 58.046816 50% 61.786946 75% 65.355951 max 76.918076 Name: primary_cleaner.output.concentrate_sum, dtype: float64
count 14149.000000 mean 68.387872 std 7.023723 min 0.000000 25% 67.559819 50% 69.141502 75% 70.974661 max 80.210644 Name: final.output.concentrate_sum, dtype: float64
Вывод:
1) Суммарная концентрация растет от этапа к этапу.
2) Основание под графиком становиться уже, разброс значений по концентрации уменьшается.
3) Частота появления максимальной концентрации тоже возрастает.
4)Имеются аномальные маленькие и большие значения концентрации и имеются выбросы около 0. Для корректного обучения
модели эти "хвосты" нам необходимо убрать.
print(df_train.shape)
df_train = df_train.loc[(df_train['rougher.input.feed_sum'] >= 42)&
(df_train['rougher.input.feed_sum'] <= 73)]
df_train = df_train.loc[(df_train['rougher.output.concentrate_sum'] >= 54.9)&
(df_train['rougher.output.concentrate_sum'] <= 83.5)]
df_train = df_train.loc[(df_train['primary_cleaner.output.concentrate_sum'] >= 49)&
(df_train['primary_cleaner.output.concentrate_sum'] <= 75.3)]
df_train = df_train.loc[(df_train['final.output.concentrate_sum'] >= 63)&
(df_train['final.output.concentrate_sum'] <= 75.8)]
print(df_train.shape)
print(f'Потери:{1-11397/14149:.2%}')
(14149, 90) (11397, 90) Потери:19.45%
Модель¶
Обработаем выборки для наших моделей¶
# Добавим целевые признакми в тестовую выборку
df_test = df_test.merge(df_full[['rougher.output.recovery',
'final.output.recovery']],
left_index=True, right_index=True, how='left')
df_train = df_train[df_test.columns]
print(df_test.shape)
print(df_train.shape)
(5290, 54) (11397, 54)
Комментарий ревьюера
На доработку❌: Целевые признаки в тестовую выборку добавлены некорректно: в таком виде присоединение происходит сначала по индексам, при этом в тестовой выборке нумерация индексов начинается с нуля и по возрастанию, а в полной выборки наблюдения, относящиеся к тестовой выборке, расположены ближе к концу таблицы, и нумерация индексов у них уже другая - значениями индексов от нуля и по возрастанию нумеруются наблюдения, относящиеся к тренировочной выборке. По итогу, делая присваивание по индексу, ты передаёшь в тестовую выборку целевые признаки обучающей выборки - таким образом происходит утечка целевого признака, и модель будет давать оптимистичные предсказания.
Соединение по индексу допустимо в том случае, если индексы соответствуют друг другу в разных таблицах - например, в качестве индекса можно задать дату. Альтернатива - использовать соединение merge() с датой в качестве ключа, как сейчас, но без фильтрации через loc.
# Приведем в соответствие обучающую выборку к тестовой
features_train = df_train.drop(['rougher.output.recovery', 'final.output.recovery'], axis='columns')
target_train = df_train[['rougher.output.recovery', 'final.output.recovery']]
features_test = df_test.drop(['rougher.output.recovery', 'final.output.recovery'], axis='columns')
target_test = df_test[['rougher.output.recovery', 'final.output.recovery']]
Функции sMAPE¶
def smape(target,target_predictions):
numerator = np.abs(target - target_predictions)
denominator = (np.abs(target) + np.abs(target_predictions))/2
return 1/len(target) * np.sum(numerator / denominator) * 100
def full_smape(target,target_predictions):
target_rougher = target[target.columns[0]]
target_final = target[target.columns[1]]
target_predictions_rougher = target_predictions[:, 0]
target_predictions_final = target_predictions[:, 1]
result = (0.25 * smape(target_rougher,target_predictions_rougher) + 0.75 * smape(target_final, target_predictions_final))
return result
Скорринг¶
sMAPE_scorer = make_scorer(full_smape, greater_is_better=True)
Линейная регрессия¶
model = LinearRegression()
model.fit(features_train, target_train)
scores = cross_val_score(model, features_train, target_train, cv=5, n_jobs=-1, scoring = sMAPE_scorer)
print('sMAPE:', np.abs(scores).mean())
sMAPE: 8.674810420651458
Комментарий ревьюера
Все отлично!👍: Оценили линейную регрессию на кросс-валидации - отлично!
При работе с cross_val_score, а также с GridSearchCV или RandomizedSearchCV есть несколько полезных действий, которые сделают нашу жизнь проще и лучше:)
- Можно настроить параметр
n_jobs=-1, чтобы для вычислений использовались все доступные ядра - это ускорит процесс. - Можно настроить параметр
verbose=10, чтобы инструмент взаимодействовал с логом и выдавал сообщения о прогрессе обучения - так мы будем понимать, что процесс идёт, а не что, например, у нас упало ядро, и процесс завис. - Для кросс-валидации (параметр
cv) вполне можно использовать и 3 фолда: мы немного потеряем в качестве, но процесс будет происходить гораздо быстрее. Для учебного проекта более чем достаточно:)
Комментарий ревьюера
На доработку❌:
Довольно важным моментом является настройка параметра scoring - именно он отвечает за метрику, которая будет оценивать промежуточное качество моделей в ходе кросс-валидации и/или оптимизации гиперпараметров.
Метрика нашего проекта - sMAPE, и в базовом наборе метрик sklearn она отсутствует - нам придётся сделать свой скорринг. Для этого можно использовать инструмент make_scorer (https://scikit-learn.org/stable/modules/generated/sklearn.metrics.make_scorer.html).
Так как метрика sMAPE применяется для задач регрессии, то она тем лучше, чем ниже - это нужно учитывать при создании скорринга для кросс-валидации, так как по умолчанию инструменты кросс-валидации вроде cross_val_score и GridSearchCV/RandomizedSearchCV умеют только максимизировать метрику качества. Поэтому при создании скорринга с помощью make_scorer важно настроить параметр greater_is_better=False, чтобы оптимизируемая метрика минимизировалась, а не максимизировалась - таким образом задача максимизации будет решаться через задачу минимизации обратной функции.
Также при настройке этого параметра получаемая метрика будет отрицательной: это особеность работы make_scorer с настроенным параметром greater_is_better=False. Поэтому при выводе метрики на экран её стоит сделать положительной: взять по модулю, домножить на -1 или просто указать - при выводе на экран, вроде print(-a).
Рeшающее дерево¶
best_result = 10
depth_me = 0
for i in range(1,10):
model = DecisionTreeRegressor(random_state=12345, max_depth = i)
scores = np.abs(cross_val_score(model, features_train, target_train,
cv=5, n_jobs=-1, scoring = sMAPE_scorer)).mean()
if scores < best_result:
best_result = scores
depth_me = i
print(f'sMape: {np.abs(best_result):.3f} Глубина = {depth_me}')
sMape: 8.431 Глубина = 2
Комментарий ревьюера
На доработку❌:
Сейчас твой код выводит значение метрики на последней итерации подбора гиперпараметров - не факт, что при этом данное значение является оптимальным.
В код стоит добавить функционал по поиску лучшего значения метрики, а также гиперпараметров, с помощью которых эта метрика была достигнута - это реализовано ниже для случайного леса.
Случайный лес регрессии¶
best_result = 10
depth_me = 0
est =0
for depth in range(1, 10):
for j in np.arange(10, 50, 10):
model = RandomForestRegressor(n_estimators=j, max_depth=depth, random_state=12345)
scores = np.abs(cross_val_score(model, features_train, target_train,
cv=5, n_jobs=-1, scoring = sMAPE_scorer)).mean()
if best_result > scores:
depth_me = depth
best_result = scores
est =j
print(f'Параметры лучшей модели')
print(f'Глубина:{depth_me}, кол-во деревьев:{est}, sMAPE: {best_result}')
Параметры лучшей модели Глубина:2, кол-во деревьев:40, sMAPE: 8.226789086305422
sMAPE = 8.227
Строим лучшую модель +sMAPE¶
model = RandomForestRegressor(n_estimators=40, max_depth=2, random_state=12345)
model.fit(features_train, target_train)
predictions_test = model.predict(features_test)
print(f'Итоговая sMAPE: {full_smape(target_test, predictions_test):.2f}')
Итоговая sMAPE: 8.80
Проверка на адекватность¶
model = DummyRegressor(strategy="median")
model.fit(features_train, target_train)
predictions_test = model.predict(features_test)
print(f'Итоговая sMAPE: {full_smape(target_test, predictions_test):.2f}')
Итоговая sMAPE: 9.33
Модель имеет следующие характеристики:
1)Тип -RandomForestRegressor
2)Глубина - max_depth=2
3) Кол-во деревьев - n_estimators=40
4) Итоговая sMAPE на тестовой выборке: 8.80
5) Проверка на адекватность прошла успешно. Метрика константной модели составила sMAPE=9.33, а метрика нашей
модели sMAPE=8.80. Исследование проводили на тестовой выборке.
Комментарий ревьюера
На доработку❌: Очень важно также проверить лучшую модель на адекватность, сравнив качество её предсказаний с качеством модели, которая предсказывала бы константу - вдруг окажется, что не было бы большого смысла заниматься созданием новых признаков, тюнингом и кросс-валидацией моделей, если можно было бы просто предсказывать среднее значение тренировочной выборки?
В качестве константной модели можно использовать DummyRegressor (https://scikit-learn.org/stable/modules/generated/sklearn.dummy.DummyRegressor.html) - эта модель как раз создана для генерирования константных предсказаний.
Важно, чтобы результат тестирования нашей модели на тествой выборке был лучше, чем результат константной модели - в противном случае наша модель является бесполезной, так как все наши усилия над проектом не принесли результата, а можель, просто предсказывющая среднее на train, делает нашу работу лучше.
Комментарий ревьюера: общий вывод по проекту.¶
Антон, проект получился на довольно хорошем уровне - ты хорошо постарался, молодец!
Мне нравится твой аналитический подход к выполнению проекта, ты соблюдаешь структуру работы, выполняешь её последовательно - это очень хорошо! Шаги проекта выполнены по порядку согласно плану проекта, нет смысловых и структурных ям. Важно, что не забываешь про выводы.
Работа с моделями также выполнена отлично: исследовано несколько алгоритмов, проведён подбор гиперпараметров, выполнена промежуточная оценка моделей на кросс-валидации - молодец!
Над проектом ещё стоит поработать - есть рекомендации по дополнению некоторых твоих шагов проекта. Такие рекомендации я отметил жёлтыми комментариями. Будет здорово, если ты учтёшь их - так проект станет структурно и содержательно более совершенным.
Также в работе есть критические замечания. К этим замечаниям я оставил пояснительные комментарии красного цвета, в которых перечислил возможные варианты дальнейших действий. Уверен, ты быстро с этим управишься:)
Если о том, что нужно сделать в рамках комментариев, будут возникать вопросы - оставь их, пожалуйста, в комментариях, и я отвечу на них во время следующего ревью.
Также буду рад ответить на любые твои вопросы по проекту или на какие-либо другие, если они у тебя имеются - оставь их в комментариях, и я постараюсь ответить:)
Жду твой проект на повторном ревью. До встречи:)
Комментарий ревьюера: общий вывод по проекту v.2.¶
Антон, все замечания учтены - проект принят!
Спасибо за работу над проектом, желаю успехов в дальнейшем обучении:)