File size: 24,700 Bytes
fccbfb8
940c1fc
f496f49
a22630b
940c1fc
3fd6b1d
 
 
 
e46d7eb
fccbfb8
3fd6b1d
b5a495b
0546d21
 
 
 
 
 
 
 
a22630b
e46d7eb
a22630b
 
 
 
 
 
 
 
 
 
 
 
 
 
bbc09e3
3fd6b1d
 
fccbfb8
 
9fc95ec
fccbfb8
 
 
 
 
44e7893
 
fccbfb8
455282f
 
fccbfb8
 
 
 
 
 
 
e46d7eb
fccbfb8
a22630b
fccbfb8
a22630b
fccbfb8
a22630b
fccbfb8
 
 
 
 
 
 
455282f
fccbfb8
 
 
 
 
455282f
fccbfb8
 
 
 
 
 
 
 
 
a22630b
fccbfb8
a22630b
fccbfb8
a22630b
 
455282f
fccbfb8
a22630b
 
455282f
a22630b
fccbfb8
a22630b
 
455282f
a22630b
455282f
 
fccbfb8
a22630b
 
3a9a180
 
a22630b
3a9a180
 
a22630b
44e7893
3a9a180
 
 
44e7893
 
e46d7eb
a22630b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e46d7eb
3a9a180
44e7893
a22630b
44e7893
 
a22630b
 
e46d7eb
a22630b
e46d7eb
 
a22630b
 
 
 
 
 
 
 
 
e46d7eb
a22630b
44e7893
 
 
b61f7d0
a22630b
 
b5a495b
e46d7eb
a22630b
 
 
 
b61f7d0
f496f49
e46d7eb
a22630b
 
784c3eb
a22630b
b61f7d0
a22630b
 
 
 
 
 
e46d7eb
 
5624d07
e46d7eb
 
b5a495b
 
 
 
f496f49
e46d7eb
 
0546d21
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5624d07
e46d7eb
 
 
0546d21
e46d7eb
0546d21
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f496f49
0546d21
b61f7d0
 
 
0546d21
b61f7d0
0546d21
f496f49
0546d21
 
 
e46d7eb
0546d21
 
 
 
 
 
 
 
 
f496f49
0546d21
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f496f49
 
 
0546d21
f496f49
0546d21
f496f49
0546d21
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
import pandas as pd

from sklift.metrics import uplift_at_k, uplift_by_percentile, qini_auc_score, qini_curve, uplift_curve
from sklift.viz import plot_qini_curve, plot_uplift_curve

import streamlit as st

import tools

# загрузим датасет
dataset, target, treatment = tools.get_data()

# загрузим предикты моделей
ct_cbc = pd.read_csv('src/model_predictions/catboost/ct_cbc.csv', index_col='Unnamed: 0')
sm_cbc = pd.read_csv('src/model_predictions/catboost/sm_cbc.csv', index_col='Unnamed: 0')
tm_dependend_cbc = pd.read_csv('src/model_predictions/catboost/tm_dependend_cbc.csv', index_col='Unnamed: 0')
tm_independend_cbc = pd.read_csv('src/model_predictions/catboost/tm_independend_cbc.csv', index_col='Unnamed: 0')

tm_rfc = pd.read_csv('src/model_predictions/random_forest/tm_rfc.csv', index_col='Unnamed: 0')

sm_xgboost = pd.read_csv('src/model_predictions/xgboost/sm_xgb.csv', index_col='Unnamed: 0')

# загрузим данные
data_train_index = pd.read_csv('data/data_train_index.csv')
data_test_index = pd.read_csv('data/data_test_index.csv')
treatment_train_index = pd.read_csv('data/treatment_train_index.csv')
treatment_test_index = pd.read_csv('data/treatment_test_index.csv')
target_train_index = pd.read_csv('data/target_train_index.csv')
target_test_index = pd.read_csv('data/target_test_index.csv')

# фиксируем выборки, чтобы результат работы ML был предсказуем
data_train = dataset.loc[data_train_index['0']]
data_test = dataset.loc[data_test_index['0']]
treatment_train = treatment.loc[treatment_train_index['0']]
treatment_test = treatment.loc[treatment_test_index['0']]
target_train = target.loc[target_train_index['0']]
target_test = target.loc[target_test_index['0']]

st.title('Uplift lab')

st.markdown(
	"""
	#### Рассмотрим применение одного из подходов прогнозирования _uplift_.
	
	Данные для примера взяты из [_The MineThatData E-Mail Analytics And Data Mining Challenge_](https://blog.minethatdata.com/2008/03/minethatdata-e-mail-analytics-and-data.html)
	
	Этот набор данных содержит 42 693 строк с данными клиентов, которые в последний раз совершали покупки в течение двенадцати месяцев.
	
	Из данных уже отделена тестовая выборка в виде 30% записей клиентов, так что данных в предоставленной выборке будет меньше.
	
	Среди клиентов была проведена рекламная кампания с помощью _email_ рассылки:
	- 1/2 клиентов были выбраны случайным образом для получения электронного письма, рекламирующего женскую продукцию;
	- С оставшейся 1/2 коммуникацию не проводили.
	
	Для каждого клиента из выборки замерили факт перехода по ссылке в письме, факт совершения покупки и сумму трат за
	две недели, следующими после получения письма.
	
	Пример данных приведен ниже.
	"""
)

refresh = st.button('Обновить выборку')
title_subsample = data_train.sample(7)
if refresh:
	title_subsample = data_train.sample(7)
st.dataframe(title_subsample, width=700)
st.write(f"Всего записей: {data_train.shape[0]}")

st.write('Описание данных')
st.markdown(
	"""
		| Колонка           | Обозначение                                                            |
		|-------------------|------------------------------------------------------------------------|
		| _recency_         | Месяцев с момента последней покупки                                    |
		| _history_segment_ | Классификация клиентов в долларах, потраченных в прошлом году          |
		| _history_         | Фактическая стоимость в долларах, потраченная в прошлом году           |
		| _mens_            | Флаг 1/0, 1 = клиент приобрел мужские товары в прошлом году            |
		| _womens_          | Флаг 1/0, 1 = клиент приобрел женские товары в прошлом году            |
		| _zip_code_        | Классифицирует почтовый индекс как городской, пригородный или сельский |
		| _newbie_          | Флаг 1/0, 1 = Новый клиент за последние двенадцать месяцев             |
		| _channel_         | Описывает каналы, через которые клиент приобрел тоовар в прошлом году  |

		---
	"""
)
st.write("Для того, чтобы лучше понять на какую аудиторию лучше запустить рекламную кампанию, проведем небольшой \
		  анализ данных")

with st.expander('Развернуть блок анализа данных'):

	st.plotly_chart(tools.get_newbie_plot(data_train), use_container_width=True)
	st.write(f'В данных примерно одинаковое количество новых и "старых клиентов". '
			 f'Отношение новых клиентов к старым: {(data_train["newbie"] == 1).sum() / (data_train["newbie"] == 0).sum():.2f}')

	st.plotly_chart(tools.get_zipcode_plot(data_train), use_container_width=True)
	tmp_res = data_train.zip_code.value_counts(normalize=True) * 100
	st.write(f'Большинство клиентов из пригорода: {tmp_res["Surburban"]:.2f}%, из города: {tmp_res["Urban"]:.2f}% и из села: {tmp_res["Rural"]:.2f}%')

	tmp_res = data_train.channel.value_counts(normalize=True) * 100
	st.plotly_chart(tools.get_channel_plot(data_train), use_container_width=True)
	st.write(f'В прошлом году почти одинаковое количество клиентов покупало товары через телефон и сайт, {tmp_res["Phone"]:.2f}% и {tmp_res["Web"]:.2f}% соответственно,'
			 f' а {tmp_res["Multichannel"]:.2f}% клиентов покупали товары воспользовавшись двумя платформами.')

	tmp_res = data_train.history_segment.value_counts(normalize=True) * 100
	st.plotly_chart(tools.get_history_segment_plot(data_train), use_container_width=True)
	st.write(f'Как мы видим, большинство пользователей относится к сегменту \$0-\$100 ({tmp_res[0]:.2f}%), второй и '
			 f'третий по количеству пользователей сегменты \$100-\$200 ({tmp_res[1]:.2f}%) и \$200-\$350 ({tmp_res[2]:.2f}%).')
	st.write(f'К сегментам \$350-\$500 и \$500-\$750 относится {tmp_res[3]:.2f}% и {tmp_res[4]:.2f}% пользователей соответственно.')
	st.write(f'Меньше всего пользователей в сегментах \$750-\$1.000 ({tmp_res[-2]:.2f}%) и \$1.000+ ({tmp_res[-1]:.2f}%).')

	tmp_res = list(data_train.recency.value_counts(normalize=True) * 100)
	st.plotly_chart(tools.get_recency_plot(data_train), use_container_width=True)
	st.write(f'Большинство клиентов являются активными клиентами платформы, и совершали покупки в течение месяца ({tmp_res[0]:.2f}%)')
	st.write('Также заметно, что 9 и 10 месяцев назад, много клиентов совершали покупки. Это может свидетельствовать о проведении'
			 'рекламной кампании в это время или чего-то еще.')
	st.write('Также интересно понаблюдать за долями новых клиентов в данном распределении.')

	st.plotly_chart(tools.get_history_plot(data_train), use_container_width=True)
	st.markdown('_График интерактивный. Двойной клик вернет в начальное состояние._')
	st.write('Абсолютное большинство клиентов тратят \$25-\$35 на покупки, но есть и малая доля тех, кто тратит более \$3.000')
	st.write('Интересный факт: все покупки более \$500 совершают только новые клиенты')

filters = {}

# блок фильтров
with st.form(key='filter-clients'):
	st.subheader('Выберем клиентов, которым отправим рекламу.')

	col1, col2, col3 = st.columns(3)

	channel_filter = col1.radio('Канал покупки прошлом году', options=['Все', 'Phone', 'Web', 'Multichannel'])
	filters['channel_filter'] = channel_filter

	newbie_filter = col2.radio('Тип клиента', options=['Все', 'Только новые', 'Только старые'])
	filters['newbie_filter'] = newbie_filter

	mens_filter = col3.radio('Клиенты, приобретавшие товары', options=['Любые', 'Мужские', 'Женские'])
	filters['mens_filter'] = mens_filter

	filters['history_segments'] = {}

	col1, col2 = st.columns(2)

	with col1:
		st.write('Класс клиентов по объему денег, потраченных в прошлом году (history segments)')
		first_group = st.checkbox('$0-$100', value=True)
		if first_group:
			filters['history_segments']['1) $0 - $100'] = True
		second_group = st.checkbox('$100-$200', value=True)
		if second_group:
			filters['history_segments']['2) $100 - $200'] = True
		third_group = st.checkbox('$200-$350', value=True)
		if third_group:
			filters['history_segments']['3) $200 - $350'] = True
		fourth_group = st.checkbox('$350-$500', value=True)
		if fourth_group:
			filters['history_segments']['4) $350 - $500'] = True
		fifth_group = st.checkbox('$500-$750', value=True)
		if fifth_group:
			filters['history_segments']['5) $500 - $750'] = True
		sixth_group = st.checkbox('$750-$1.000', value=True)
		if sixth_group:
			filters['history_segments']['6) $750 - $1,000'] = True
		seventh_group = st.checkbox('$1.000+', value=True)
		if seventh_group:
			filters['history_segments']['7) $1,000 +'] = True

	with col2:
		st.write('Каких пользователей по почтовому коду выберем')
		filters['zip_code'] = {}
		surburban = st.checkbox('Surburban', value=True)
		if surburban:
			filters['zip_code']['surburban'] = True
		urban = st.checkbox('Urban', value=True)
		if urban:
			filters['zip_code']['urban'] = True
		rural = st.checkbox('Rural', value=True)
		if rural:
			filters['zip_code']['rural'] = True

	recency = st.slider(label='Месяцев с момента покупки', min_value=int(data_test.recency.min()), max_value=int(data_test.recency.max()), value=(int(data_test.recency.min()), int(data_test.recency.max())))
	filters['recency'] = recency

	st.write('Если известно на какой процент аудитории необходимо повлиять, измените значение')
	k = st.slider(label='Процент аудитории', min_value=1, max_value=100, value=100)

	filter_form_submit_button = st.form_submit_button('Применить фильтр')

# проверка корректности заполнения форм
if not first_group and not second_group and not third_group and not fourth_group and not fifth_group and not sixth_group and not seventh_group:
	st.error('Необходимо выбрать хотя бы один класс')
	st.stop()
elif not surburban and not urban and not rural:
	st.error('Необходимо выбрать хотя бы один почтовый индекс')
	st.stop()

# фильтруем тестовые данные по пользовательскому выбору
filtered_dataset = tools.filter_data(data_test, filters)

# проверяем, что данные отфильтровались
if filtered_dataset is None:
	st.error('Не найдено пользователей для данных фильтров. Попробуйте изменить фильтры.')
	st.stop()

# значение uplift для записей тех клиентов, который выбрал пользователь равен 1
uplift = [1 for _ in filtered_dataset.index]
target_filtered = target_test.loc[filtered_dataset.index]
treatment_filtered = treatment_test.loc[filtered_dataset.index]

# блок с демонстрацией отфильтрованных данных
with st.expander(label='Посмотреть пример пользователей, которым будет отправлена реклама'):
	sample_size = 7 if filtered_dataset.shape[0] >= 7 else filtered_dataset.shape[0]
	example = filtered_dataset.sample(sample_size)
	st.dataframe(example)
	st.info(f'Количество пользователей, попавших в выборку: {filtered_dataset.shape[0]} ({filtered_dataset.shape[0] / data_test.shape[0] * 100 :.2f}%)')
	res = st.button('Обновить')

with st.expander('Результаты ручной фильтрации', expanded=True):
	# считаем метрики для пользователя
	user_metric_uplift_at_k = uplift_at_k(target_filtered, uplift, treatment_filtered, strategy='overall', k=k)
	user_metric_uplift_by_percentile = uplift_by_percentile(target_filtered, uplift, treatment_filtered)
	user_metric_qini_auc_score = qini_auc_score(target_filtered, uplift, treatment_filtered)
	user_metric_weighted_average_uplift = tools.get_weighted_average_uplift(target_filtered, uplift, treatment_filtered)
	qini_curve_user_score = qini_curve(target_filtered, uplift, treatment_filtered)
	uplift_curve_user_score = uplift_curve(target_filtered, uplift, treatment_filtered)
	# отображаем метрики
	col1, col2, col3 = st.columns(3)
	col1.metric(label=f'Uplift для {k}% пользователей', value=f'{user_metric_uplift_at_k:.4f}')
	col2.metric(label=f'Qini AUC score', value=f'{user_metric_qini_auc_score:.4f}')
	col3.metric(label=f'Weighted average uplift', value=f'{user_metric_weighted_average_uplift:.4f}')

	st.write('Uplift по процентилям')
	st.write(user_metric_uplift_by_percentile)

show_ml_reasons = st.checkbox('Показать решения с помощью ML')
if show_ml_reasons:
	with st.expander('Решение с помощью CatBoost'):
		with st.form(key='catboost_metricks'):

			final_uplift = sm_cbc.loc[filtered_dataset.index]['0']

			# считаем метрики для ML
			catboost_uplift_at_k = uplift_at_k(target_filtered, final_uplift, treatment_filtered, strategy='overall', k=k)
			catboost_uplift_by_percentile = uplift_by_percentile(target_filtered, final_uplift, treatment_filtered)
			catboost_qini_auc_score = qini_auc_score(target_filtered, final_uplift, treatment_filtered)
			catboost_weighted_average_uplift = tools.get_weighted_average_uplift(target_filtered, final_uplift, treatment_filtered)

			# отображаем метрики
			col1, col2, col3 = st.columns(3)
			col1.metric(
				label=f'Uplift для {k}% пользователей',
				value=f'{catboost_uplift_at_k:.4f}',
				delta=f'{catboost_uplift_at_k - user_metric_uplift_at_k:.4f}'
			)
			col2.metric(
				label=f'Qini AUC score',
				value=f'{catboost_qini_auc_score:.4f}',
				delta=f'{catboost_qini_auc_score - user_metric_qini_auc_score:.4f}'
			)
			col3.metric(
				label=f'Weighted average uplift',
				value=f'{catboost_weighted_average_uplift:.4f}',
				delta=f'{catboost_weighted_average_uplift - user_metric_weighted_average_uplift:.4f}'
			)

			st.write('Uplift по процентилям')
			st.write(catboost_uplift_by_percentile)
			st.form_submit_button('Обновить графики', help='При изменении флагов')

			perfect_qini = st.checkbox('Отрисовать идеальную метрику qini')
			# получаем координаты пользовательской метрики для точки на графике
			x, y = qini_curve_user_score[0][1], qini_curve_user_score[1][1]
			# получаем объект UpliftCurveDisplay с осями и графиком matplotlib
			qini_fig = plot_qini_curve(target_test, sm_cbc['0'], treatment_test, perfect=perfect_qini)
			# добавляем пользовательскую метрику на оси графика
			qini_fig.ax_.plot(x, y, 'ro', markersize=3, label='Analitic qini')
			# добавляем обозначение метрики пользователя в легенду
			qini_fig.ax_.legend(loc=u'upper left', bbox_to_anchor=(1, 1))
			st.pyplot(qini_fig.figure_)

			prefect_uplift = st.checkbox('Отрисовать идеальную метрику uplift')
			# получаем координаты пользовательской метрики для точки на графике
			x, y = uplift_curve_user_score[0][1], uplift_curve_user_score[1][1]
			# получаем объект UpliftCurveDisplay с осями и графиком matplotlib
			uplift_fig = plot_uplift_curve(target_test, sm_cbc['0'], treatment_test, perfect=prefect_uplift)
			# добавляем пользовательскую метрику на оси графика
			uplift_fig.ax_.plot(x, y, 'ro', markersize=3, label='Analitic qini')
			# добавляем обозначение метрики пользователя в легенду
			uplift_fig.ax_.legend(loc=u'upper left', bbox_to_anchor=(1, 1))
			st.pyplot(uplift_fig.figure_)

	with st.expander('Решение с помощью Random forest (sklearn)'):
		with st.form(key='sklearn_metricks'):

			final_rf_uplift = tm_rfc.loc[filtered_dataset.index]['0']

			# считаем метрики для ML
			random_forest_uplift_at_k = uplift_at_k(target_filtered, final_rf_uplift, treatment_filtered, strategy='overall', k=k)
			random_forest_uplift_by_percentile = uplift_by_percentile(target_filtered, final_rf_uplift, treatment_filtered)
			random_forest_qini_auc_score = qini_auc_score(target_filtered, final_rf_uplift, treatment_filtered)
			random_forest_weighted_average_uplift = tools.get_weighted_average_uplift(target_filtered, final_rf_uplift, treatment_filtered)

			# отображаем метрики
			col1, col2, col3 = st.columns(3)
			col1.metric(
				label=f'Uplift для {k}% пользователей',
				value=f'{random_forest_uplift_at_k:.4f}',
				delta=f'{random_forest_uplift_at_k - user_metric_uplift_at_k:.4f}'
			)
			col2.metric(
				label=f'Qini AUC score',
				value=f'{random_forest_qini_auc_score:.4f}',
				delta=f'{random_forest_qini_auc_score - user_metric_qini_auc_score:.4f}'
			)
			col3.metric(
				label=f'Weighted average uplift',
				value=f'{random_forest_weighted_average_uplift:.4f}',
				delta=f'{random_forest_weighted_average_uplift - user_metric_weighted_average_uplift:.4f}'
			)

			st.write('Uplift по процентилям')
			st.write(random_forest_uplift_by_percentile)
			st.form_submit_button('Обновить графики', help='При изменении флагов')

			perfect_qini = st.checkbox('Отрисовать идеальную метрику qini')
			# получаем координаты пользовательской метрики для точки на графике
			x, y = qini_curve_user_score[0][1], qini_curve_user_score[1][1]
			# получаем объект UpliftCurveDisplay с осями и графиком matplotlib
			qini_fig = plot_qini_curve(target_test, tm_rfc['0'], treatment_test, perfect=perfect_qini)
			# добавляем пользовательскую метрику на оси графика
			qini_fig.ax_.plot(x, y, 'ro', markersize=3, label='Analitic qini')
			# добавляем обозначение метрики пользователя в легенду
			qini_fig.ax_.legend(loc=u'upper left', bbox_to_anchor=(1, 1))
			st.pyplot(qini_fig.figure_)

			prefect_uplift = st.checkbox('Отрисовать идеальную метрику uplift')
			# получаем координаты пользовательской метрики для точки на графике
			x, y = uplift_curve_user_score[0][1], uplift_curve_user_score[1][1]
			# получаем объект UpliftCurveDisplay с осями и графиком matplotlib
			uplift_fig = plot_uplift_curve(target_test, tm_rfc['0'], treatment_test, perfect=prefect_uplift)
			# добавляем пользовательскую метрику на оси графика
			uplift_fig.ax_.plot(x, y, 'ro', markersize=3, label='Analitic qini')
			# добавляем обозначение метрики пользователя в легенду
			uplift_fig.ax_.legend(loc=u'upper left', bbox_to_anchor=(1, 1))
			st.pyplot(uplift_fig.figure_)

	with st.expander('Решение с помощью XGBoost'):
		with st.form(key='xgboost_metricks'):

			final_xgboost_uplift = sm_xgboost.loc[filtered_dataset.index]['0']

			# считаем метрики для ML
			xgboost_uplift_at_k = uplift_at_k(target_filtered, final_xgboost_uplift, treatment_filtered, strategy='overall', k=k)
			xgboost_uplift_by_percentile = uplift_by_percentile(target_filtered, final_xgboost_uplift, treatment_filtered)
			xgboost_qini_auc_score = qini_auc_score(target_filtered, final_xgboost_uplift, treatment_filtered)
			xgboost_weighted_average_uplift = tools.get_weighted_average_uplift(target_filtered, final_xgboost_uplift, treatment_filtered)

			# отображаем метрики
			col1, col2, col3 = st.columns(3)
			col1.metric(
				label=f'Uplift для {k}% пользователей',
				value=f'{xgboost_uplift_at_k:.4f}',
				delta=f'{xgboost_uplift_at_k - user_metric_uplift_at_k:.4f}'
			)
			col2.metric(
				label=f'Qini AUC score',
				value=f'{xgboost_qini_auc_score:.4f}',
				delta=f'{xgboost_qini_auc_score - user_metric_qini_auc_score:.4f}'
			)
			col3.metric(
				label=f'Weighted average uplift',
				value=f'{xgboost_weighted_average_uplift:.4f}',
				delta=f'{xgboost_weighted_average_uplift - user_metric_weighted_average_uplift:.4f}'
			)

			st.write('Uplift по процентилям')
			st.write(xgboost_uplift_by_percentile)
			st.form_submit_button('Обновить графики', help='При изменении флагов')

			perfect_qini = st.checkbox('Отрисовать идеальную метрику qini')
			# получаем координаты пользовательской метрики для точки на графике
			x, y = qini_curve_user_score[0][1], qini_curve_user_score[1][1]
			# получаем объект UpliftCurveDisplay с осями и графиком matplotlib
			qini_fig = plot_qini_curve(target_test, sm_xgboost['0'], treatment_test, perfect=perfect_qini)
			# добавляем пользовательскую метрику на оси графика
			qini_fig.ax_.plot(x, y, 'ro', markersize=3, label='Analitic qini')
			# добавляем обозначение метрики пользователя в легенду
			qini_fig.ax_.legend(loc=u'upper left', bbox_to_anchor=(1, 1))
			st.pyplot(qini_fig.figure_)

			prefect_uplift = st.checkbox('Отрисовать идеальную метрику uplift')
			# получаем координаты пользовательской метрики для точки на графике
			x, y = uplift_curve_user_score[0][1], uplift_curve_user_score[1][1]
			# получаем объект UpliftCurveDisplay с осями и графиком matplotlib
			uplift_fig = plot_uplift_curve(target_test, sm_xgboost['0'], treatment_test, perfect=prefect_uplift)
			# добавляем пользовательскую метрику на оси графика
			uplift_fig.ax_.plot(x, y, 'ro', markersize=3, label='Analitic qini')
			# добавляем обозначение метрики пользователя в легенду
			uplift_fig.ax_.legend(loc=u'upper left', bbox_to_anchor=(1, 1))
			st.pyplot(uplift_fig.figure_)