Разработка методики применения методов машинного обучения для решения маркетинговых задач в телекоммуникационном бизнесе

Алгоритмы для решения задачи бинарной классификации. Подготовка данных для создания модели. Разработка предиктивной модели для прогнозирования возможности продажи дополнительных услуг телекоммуникационного оператора с целью решения маркетинговых задач.

Рубрика Программирование, компьютеры и кибернетика
Вид дипломная работа
Язык русский
Дата добавления 27.08.2018
Размер файла 3,7 M

Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже

Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.

22. Загоруйко Н.Г. Прикладные методы анализа данных и знаний. Новосибирск: ИМ СО РАН, 1999. 270 с.

23. Robert E. Schapire. Boosting. Foundations and Algorithms. Cl.: Emp State, 2012. 544 с.

24. Christopher M. Bishop. Pattern Recognition and Machine Learning (Information Science and Statistics). Springer, 2011. - 738 p.

25. Classification and Regression Trees [Электронный ресурс] / Лекции Cosma Shalizi. URL: http://www.stat.cmu.edu/~cshalizi/350/lectures/22/lecture-22.pdf. (Дата обращения: 25.04.2018).

26. David W., Hosmer G., Lemeshow S. Applied Logistic Regression. New York: Chichester, Wiley, 2002. 528 с.

27. Hastie, T., Tibshirani R., Friedman J. Chapter 15. Random Forests // The Elements of Statistical Learning: Data Mining, Inference, and Prediction. -- 1st ed. -- Springer-Verlag, 2009. -- 746 p.

28. Аналитические платформы [Электронный ресурс] / Роман Волынец. URL: https://professionali.ru/Soobschestva/sas/analiticheskie_platformy_znat_konkurentov_v_lico. (Дата обращения: 02.05.2018).

29. Comparing Python and R for Data Science [Электронный ресурс] / Anna Anisin. URL: https://blog.dominodatalab.com/comparing-python-and-r-for-data-science. (Дата обращения: 15.05.2018).

30. Экспертная система поддержки принятия решений [Электронный ресурс] / EDSS. URL: http://92.242.59.210/edss0917/. (Дата обращения: 19.05.2018).

31. Роберт И. Кабаков. R в действии. Анализ и визуализация данных на языке R. М.: ДМК Пресс, 2014. 580 с.

32. Лутц М. Изучаем Python. Символ-Плюс, 2011. 1280 с.

33. McCormic K., Abbott D., Meta S. Brown. IBM SPSS Modeler Cookbook. Packt Publishing, 2013. 382 с.

34. Палкин Н. Сборник материалов II межвузовской научно-практической конференции "Бизнес-аналитика. Использование аналитической платформы Deductor в учебном процессе Вуза". ООО "Лаборатория баз данных", 2011. 120 с.

35. Боровиков В.П. Популярное введение в современный анализ данных в системе STATISTICA. М.: Горячая линия-Телеком,2013. 288 с.

36. Smith J., Scalzo B., McGrass P. Toad Pocket Reference for Oracle. O'Reilly Media, 2005. 130 с.

37. Фейерштейн С., Прибыл Б. Oracle PL/SQL. Для профессионалов. СПб.: Питер, 2011. 800 с.

38. Айвазян С.А., Бухштабер В.М., Енюков И.С., Мешалкин Л.Д. Прикладная статистика: классификация и снижение размерности. М.: Финансы и статистика, 1989. 607 с.

39. Кендалл С. Многомерный статистический анализ и временные ряды. М.: Наука, 1976. 736 с.

40. Hastie T., Tibshirani R., Friedman J. The Elements of Statistical Learning: Data Mining, Inference, and Prediction, Second Edition (Springer Series in Statistics) 2nd Edition. Springer, 2016. 745 с.

41. Friedman J. Stochastic Gradient Boosting. Cl.: Springer, 1999. 10 c.

42. Tukey J.W. Exploratory Data Analysis. Addison-Wesley, 1970. 688 с.

Приложение

П 1 Листинг кода по отбору предикторов

import numpy as np # Библиотека для работы с np-массивами, а также для использования некоторых метематических функуций

import pandas as pd # Библиотека для работы с csv-файлами, а также объектами DataFrame

import cx_Oracle # Библиотека для подключения к Oracle и импорта данных из БД

import datetime # Библиотека для работы со временем (используется для замера времени выполнения запросов).

# По факту, можно было использовать функцию %%time, то измерение с помощью datetime является менее ресурсоемким и

# более "прозрачным"

import sklearn # Библиотека для использования методов машинного обучения и анализа данных

from sklearn.feature_selection import f_classif, SelectKBest # Атрибуты модуля feature_selection библиотеки sklearn

# для отбора предикторов методом филтрации (SelectKBest) по метрике fscore (f_classif)

import os # Библиотека для определения некоторых системных параметров (в нашем случае - кодировки окружения)

os.environ['NLS_LANG'] = 'American_America.AL32UTF8' # Изменение языковой схемы окружения для корректного отображения

# текстовых полей с содержанием кириллицы

# Получение DataFrame с данными за 201703 из таблицы MA_CLIENT_DATA_MART

start = datetime.datetime.now() # Определение времени начала отработки скрипта (для фиксации продолжительности отработки блока)

conn = None # Объявление переменной для соединения с БД

# Определение запроса

sql_query = 'SELECT DISTINCT viasat_on, z.* FROM MA_CLIENT_DATA_MART_201703 z INNER JOIN (SELECT id_client, \

billing_id, viasat_on from CA_201703) d ON d.id_client = z.id_client and d.billing_id = z.billing_id \

WHERE viasat_on IS NOT NULL'

# Отлавливаем ошибку отсутствия подключения к заданной БД

try:

conn = cx_Oracle.connect("ext_consult/GfhjkmGjlhzlxbrf@DM") # Объявляем соединение с БД

try:

curs = conn.cursor() # Создаем курсор

curs.execute(sql_query) # Выполняем заданный выше запрос в БД

headers = [ x[0] for x in curs.description] # Определяем названия столбцов полученной таблицы

data = curs.fetchall() # Получаем данные, хранящиеся внутри таблицы, полученной по запросу

df201703 = pd.DataFrame( data, columns=headers) # Получение DataFrame по запросу SQL

print(df201703) # Вывод полученного DataFrame на экран

finally:

curs.close() # Закрываем курсор

finally:

if conn is not None:

conn.close() # Закрываем соединение с БД

stop = datetime.datetime.now() # Определение времени окончания отработки скрипта (для фиксации продолжительности отработки блока)

delta = stop - start # Определение фиксации продолжительности отработки блока

print (delta) # Вывод продолжительности отработки блока

df201703tr = df201703[df201703.VIASAT_ON == 1] # Получение всех записей со значением целевой метки, равным 1

df201703fls = df201703[df201703.VIASAT_ON == 0].sample(60000, axis = 0) # Получение всех записей с негативными исходами,

# выделение случайным образом выборки объемом 60000 записей

del df201703 # Удаление DataFrame со свеми данными за период 201703 (с целью освобождения памяти)

# Аналогичное получение DataFrame с данными за 201704 из таблицы MA_CLIENT_DATA_MART

start = datetime.datetime.now()

conn = None

sql_query = 'SELECT DISTINCT viasat_on, z.* FROM MA_CLIENT_DATA_MART_201704 z INNER JOIN (SELECT id_client, \

billing_id, viasat_on from CA_201704) d ON d.id_client = z.id_client and d.billing_id = z.billing_id \

WHERE viasat_on IS NOT NULL'

try:

conn = cx_Oracle.connect("ext_consult/GfhjkmGjlhzlxbrf@DM")

try:

curs = conn.cursor()

curs.execute(sql_query)

headers = [ x[0] for x in curs.description]

data = curs.fetchall()

df201704 = pd.DataFrame( data, columns=headers)

print(df201704)

finally:

curs.close()

finally:

if conn is not None:

conn.close()

stop = datetime.datetime.now()

delta = stop - start

print (delta)

df201704tr = df201704[df201704.VIASAT_ON == 1] # Получение всех записей со значением целевой метки, равным 1

df201704fls = df201704[df201704.VIASAT_ON == 0].sample(60000, axis = 0) # Получение всех записей с негативными исходами,

# выделение случайным образом выборки объемом 60000 записей

del df201704 # Удаление DataFrame со свеми данными за период 201703 (с целью освобождения памяти)

# Получение DataFrame с данными за 201705 из таблицы MA_CLIENT_DATA_MART

start = datetime.datetime.now()

conn = None

sql_query = 'SELECT DISTINCT viasat_on, z.* FROM MA_CLIENT_DATA_MART_201705 z INNER JOIN (SELECT id_client, \

billing_id, viasat_on from CA_201705) d ON d.id_client = z.id_client and d.billing_id = z.billing_id \

WHERE viasat_on IS NOT NULL'

try:

conn = cx_Oracle.connect("ext_consult/GfhjkmGjlhzlxbrf@DM")

try:

curs = conn.cursor()

curs.execute(sql_query)

headers = [ x[0] for x in curs.description]

data = curs.fetchall()

df201705 = pd.DataFrame( data, columns=headers)

#df.to_csv('test_data_from_OracleDB1.csv', sep=';', encoding='utf-8')

print(df201705)

finally:

curs.close()

finally:

if conn is not None:

conn.close()

stop = datetime.datetime.now()

delta = stop - start

print (delta)

df201705tr = df201705[df201705.VIASAT_ON == 1] # Получение всех записей со значением целевой метки, равным 1

df201705fls = df201705[df201705.VIASAT_ON == 0].sample(60000, axis = 0) # Получение всех записей с негативными исходами,

# выделение случайным образом выборки объемом 60000 записей

del df201705 # Удаление DataFrame со свеми данными за период 201703 (с целью освобождения памяти)

df = pd.concat([df201703tr, df201703fls, df201704tr, df201704fls, df201705tr, df201705fls], axis = 0, ignore_index = True)

# Вертикальная конкатенация датасетов с целевой меткой 0 и 1 за 201703, 201704, 201705

df.info() # Выводим информацию о DataFrame

df.head() # Выводим первые 5 строк DataFrame

# Создание пользовательской функции для расчета среднего значения для каждого поля вечественного массива numpy

def calculate_means(numeric_data):

means = np.zeros(numeric_data.shape[1])

for j in range(numeric_data.shape[1]):

to_sum = numeric_data.iloc[:,j]

indices = np.nonzero(~numeric_data.iloc[:,j].isnull())[0]

correction = np.amax(to_sum[indices])

to_sum /= correction

for i in indices:

means[j] += to_sum[i]

means[j] /= indices.size

means[j] *= correction

return pd.Series(means, numeric_data.columns)

# Проверка DataFrmae на наличие пустых значений

df.isnull().values.any()

# Формирование dummy на основе категориальных признаков

df = pd.get_dummies(df, columns = ['AG_IKTV_TARIFF','AG_INTER_TARIFF_NAME','AG_KTV_TARIFF','AG_TEL_TARIFF'], drop_first = True)

# Формирование обучающих меток

train_labels = df['VIASAT_ON']

# Формирование обучающих данных

train_data = df.drop(['VIASAT_ON','ID_CLIENT','CALC_PERIOD','BILLING_ID','CL_ID_BI',\

'CL_ID_LOYALTY','CL_BILLING_ID','CL_BTHDAY','CL_TEL_CNT',\

'CL_DAYS_FORMER_TO_CURRENT','CL_AGE','AG_CATCHUP_DATE','AG_CATCHUP_DATE_CLOSE',\

'AG_INTER_ID','AG_MULTIROOM_DATE','AG_MULTISCR_DATE','AG_SERVICE_1593_DATE','AG_SERVICE_1639_DATE',

'AG_SERVICE_243_DATE','APC_ALTYN','APC_AMEDIA','APC_AMEDIAPREMIUMHD','APC_BAZOVYYHD','APC_BAZOVYYHDMINI',

'APC_BAZOVYYMINI','APC_BESSONNITSA','APC_BESSONNITSA_84','APC_DETSKIY1','APC_DETSKIY2','APC_DOZHD',

'APC_GEYMER','APC_HDMAKSIMUM','APC_HDMAX','APC_HDSTART','APC_KHLHD','APC_KINO1','APC_KINO2',

'APC_KINOIMUZYKAHD','APC_MATCHFUTBOL','APC_MATCHSPORT','APC_MEZHDUNARODNYY','APC_MIKSHD',

'APC_MUZYKA1','APC_MUZYKA2','APC_NASHFUTBOL','APC_NASTOYASCHIYMUZHSKOY','APC_NASTROYKINO',

'APC_NATSIONALNYY','APC_NOVOSTI','APC_NTVPLYUSFUTBOL','APC_NTVPLYUSSPORT','APC_OKRUZHAYUSCHIYMIR',

'APC_POZNANIE','APC_PUTESHESTVIYA','APC_RAZVLECHENIYA1','APC_RAZVLECHENIYA2','APC_RUSSKOEKINO',

'APC_SERIALY','APC_SHANTPREMIUMHD','APC_SPORT1','APC_SPORT2','APC_SPORTIUVLECHENIYAHD',

'APC_STANDARTNYYHD','APC_STANDARTNYYHDMINI','APC_STARTOVYY','APC_TSIFROVOYHD','APC_TSIFROVOYHDNEW',

'APC_UDIVITELNAYAPLANETA','APC_UMKA','APC_UMKAOLD','APC_UVLECHENIYA1','APC_UVLECHENIYA2',

'APC_VIASATPREMIUMHD','APC_VIASATPREMIUMHDOLD'], axis = 1)

# Заполнение пропусков в тренировочных данных средними

train_data = train_data.fillna(calculate_means(numeric_data))

# Проверка на наличие пропусков в тренировочных данных

train_data.isnull().values.any()

# Информация о тренировочном датасете

train_data.info()

# Определение алгоритма фильтрации по параметру fscore

select = SelectKBest(f_classif, k = 40) # Ищем 40 наиболее значимых показателей

X_new = select.fit(train_data, train_labels) # Обучаем созданный фильтр

mask = X_new.get_support() # Получить маску с индексами выбранных предикторов

sc = X_new.scores_ # Получить значимость выбранных предикторов

new_train_data = [] # Определение массива, который будет содержать список наиболее значимых предикторов с весами

for bool, feature, score in zip(mask, train_data, sc): # Для маски с индексами подбираем названия атрибутов

if bool:

new_train_data.append([feature, score])

new_train_data.to_csv('Important_features.csv')

new_train_data # Вывод наиболее значимых показателей с весами на экран

import numpy as np

import pandas as pd

import cx_Oracle

import datetime

import sklearn

from sklearn import feature_selection, linear_model

from sklearn.feature_selection import chi2, f_classif, SelectKBest

import os

os.environ['NLS_LANG'] = 'American_America.AL32UTF8'

start = datetime.datetime.now()

conn = None

sql_query = 'SELECT DISTINCT viasat_on, z.* FROM MA_NAPA_DPI_CAT_201703 z INNER JOIN (SELECT id_client, \

billing_id, viasat_on from CA_201703) d ON d.id_client = z.client_id and d.billing_id = z.city_id \

WHERE viasat_on IS NOT NULL'

try:

conn = cx_Oracle.connect("ext_consult/GfhjkmGjlhzlxbrf@DM")

try:

curs = conn.cursor()

curs.execute(sql_query)

headers = [ x[0] for x in curs.description]

data = curs.fetchall()

df201703 = pd.DataFrame( data, columns=headers)

#df.to_csv('test_data_from_OracleDB1.csv', sep=';', encoding='utf-8')

print(df201703)

finally:

curs.close()

finally:

if conn is not None:

conn.close()

stop = datetime.datetime.now()

delta = stop - start

print (delta)

df201703tr = df201703[df201703.VIASAT_ON == 1]

df201703fls = df201703[df201703.VIASAT_ON == 0].sample(60000, axis = 0)

del df201703

start = datetime.datetime.now()

conn = None

sql_query = 'SELECT DISTINCT viasat_on, z.* FROM MA_NAPA_DPI_CAT_201704 z INNER JOIN (SELECT id_client, \

billing_id, viasat_on from CA_201704) d ON d.id_client = z.client_id and d.billing_id = z.city_id \

WHERE viasat_on IS NOT NULL'

try:

conn = cx_Oracle.connect("ext_consult/GfhjkmGjlhzlxbrf@DM")

try:

curs = conn.cursor()

curs.execute(sql_query)

headers = [ x[0] for x in curs.description]

data = curs.fetchall()

df201704 = pd.DataFrame( data, columns=headers)

#df.to_csv('test_data_from_OracleDB1.csv', sep=';', encoding='utf-8')

print(df201704)

finally:

curs.close()

finally:

if conn is not None:

conn.close()

stop = datetime.datetime.now()

delta = stop - start

print (delta)

df201704tr = df201704[df201704.VIASAT_ON == 1]

df201704fls = df201704[df201704.VIASAT_ON == 0].sample(60000, axis = 0)

del df201704

start = datetime.datetime.now()

conn = None

sql_query = 'SELECT DISTINCT viasat_on, z.* FROM MA_NAPA_DPI_CAT_201705 z INNER JOIN (SELECT id_client, \

billing_id, viasat_on from CA_201705) d ON d.id_client = z.client_id and d.billing_id = z.city_id \

WHERE viasat_on IS NOT NULL'

try:

conn = cx_Oracle.connect("ext_consult/GfhjkmGjlhzlxbrf@DM")

try:

curs = conn.cursor()

curs.execute(sql_query)

headers = [ x[0] for x in curs.description]

data = curs.fetchall()

df201705 = pd.DataFrame( data, columns=headers)

#df.to_csv('test_data_from_OracleDB1.csv', sep=';', encoding='utf-8')

print(df201705)

finally:

curs.close()

finally:

if conn is not None:

conn.close()

stop = datetime.datetime.now()

delta = stop - start

print (delta)

df201705tr = df201705[df201705.VIASAT_ON == 1]

df201705fls = df201705[df201705.VIASAT_ON == 0].sample(60000, axis = 0)

del df201705

df = pd.concat([df201703tr, df201703fls, df201704tr, df201704fls, df201705tr, df201705fls], axis = 0, ignore_index = True)

df.info()

df.head()

def calculate_means(numeric_data):

means = np.zeros(numeric_data.shape[1])

for j in range(numeric_data.shape[1]):

to_sum = numeric_data.iloc[:,j]

indices = np.nonzero(~numeric_data.iloc[:,j].isnull())[0]

correction = np.amax(to_sum[indices])

to_sum /= correction

for i in indices:

means[j] += to_sum[i]

means[j] /= indices.size

means[j] *= correction

return pd.Series(means, numeric_data.columns)

df.isnull().values.any()

df = pd.get_dummies(df, columns = ['MODEL_DEV'], drop_first = True)

train_labels = df['VIASAT_ON']

train_data = df.drop(['VIASAT_ON', 'CLIENT_ID', 'CALC_PERIOD','CITY_ID','FOR_DAY',\

'CITY_NAME','LOGIN_NAME','AGREEMENT_NUMBER','CL_ID_BI'], axis = 1)

train_data = train_data.fillna(0)

train_data.isnull().values.any()

train_data.info()

select = SelectKBest(f_classif, k = 40)

X_new = select.fit(train_data, train_labels)

mask = X_new.get_support()

sc = X_new.scores_

new_train_data = []

for bool, feature, score in zip(mask, train_data, sc):

if bool:

new_train_data.append([feature, score])

new_train_data

П 2 Листинг кода модели

# Импорт библиотек

import numpy as np # Библиотека для работы с np-массивами, а также для использования некоторых метематических функуций

import pandas as pd # Библиотека для работы с csv-файлами, а также объектами DataFrame

import cx_Oracle # Библиотека для подключения к Oracle и импорта данных из БД

import datetime # Библиотека для работы со временем (используется для замера времени выполнения запросов).

# По факту, можно было использовать функцию %%time, то измерение с помощью datetime является менее ресурсоемким и

# более "прозрачным"

import sklearn # Библиотека для использования методов машинного обучения и анализа данных

from sklearn import metrics, ensemble, learning_curve # Модули библиотеки sklearn для

# обучения и настройки моделей, а также для оценки их качества

import os # Библиотека для определения некоторых системных параметров (в нашем случае - кодировки окружения)

import math # Библиотека для использования математических функций

import pickle # Библиотека для формирования пиклов (сохранения важных переменных, заданных в скрипте)

import xgboost as xgb # Библиотека для использования алгоритма градиентного бустинга

from sklearn.preprocessing import StandardScaler

%pylab inline

# Функционал для построения графиков

os.environ['NLS_LANG'] = 'American_America.AL32UTF8' # Изменение языковой схемы окружения для корректного отображения

# текстовых полей с содержанием кириллицы

# Данный блок помагает растянуть notebook по всей ширине

from IPython.core.display import display, HTML

display(HTML("<style>.container { width:100% !important; }</style>"))

# Определение запроса SQL для получения данных за 201703

sql_query_201703 = 'SELECT DISTINCT g.VIASAT_ON, \

a.ID_CLIENT, a.BILLING_ID, a.CALC_PERIOD, CL_PRIV, ADP_AMEDIAPREMIUMHD, ADP_BAZOVYYHD, ADP_MATCHFUTBOL, ADP_NASTROYKINO, AG_BEFORE_PAID_SVOD, AG_COUNT_ACT_IKTV, \

AG_COUNT_CHANNEL_HD_TOTAL, AG_COUNT_CHANNEL_TOTAL, AG_IKTV_ARPU, AG_IKTV_TARIFF_ARCH, AG_INTER_ARPU, AG_MULTIROOM_COST, AG_MULTISCR, AG_PAY_CUR_MONTH, APP_NASTROYKINO, \

PAY_ARPU_SUMM, PAY_COUNT_ADD_PACK_DISC, \

HOME2_VISITS_DAYS_WKND_M, LEISURE2_VISITS_DAYS_WKND_M, MAX_SHOPS2_VISITS_DAY_CNT, MAX_SPORT2_VISITS_DAY_CNT, NEWS_VISITS_DAYS_WKND_M, SHOPS2_VISITS_DAYS_WKND_M, \

SHOPS2_VISITS_SHARE_M, SOC_VISITS_DAYS_WKND_M, SOCCER_VISITS_DAYS_WKND_M, SPORT2_VISITS_CNT_WKND_M, SPORT2_VISITS_DAYS_M, SPORT2_VISITS_SHARE_WORKD_M, \

CNT_AD_SERV_IKTV_CM, HAS_PC_MFUT_CM, HAS_PC_NASTKIN_CM, HAS_AD_PC_CM, CNT_TELE_AD_PC_CM, MAX_DAYS_FILM_AD_PC_CM, AG_IKTV_ARPU_CM, PAY_ARPU_SUMM_CM, HAS_ANY_AD_SERV_CM, \

CNT_FILM_AD_PC_PPM, AG_INTER_ARPU_PPM, AG_IKTV_ARPU_MORE_AVG_AAB, AG_INTER_ARPU_TO_MEDIAN_AAB, AG_INTER_ARPU_MORE_MOD_AAB, PAY_ARPU_SUMM_TO_MOD_AAB, \

PAY_ARPU_SUMM_MORE_AVG_AAB, MONTHPART_PC_MFUT_CM, MONTHPART_PC_NASTKIN_CM, \

MINUTES_COMMUN_CM, MINUTES_COMMUN_SPECPREDLK_CM, CNT_UNIQ_CHANNEL_CM, CNT_LOYAL_CM, MINUTES_LOYAL_CM, CNT_ESPONSE_2_CM, CNT_RESPONSE_3_CM, GP_2_OBJ_SOHR_CM, \

GP_3_OBJ_DZ_CM, MIN_ONE_COMM_SPECPREDLK_PM, CNT_COMMUN_PPM, MINUTES_COMMUN_SPECPREDLK_PPM, MINUTES_LOYAL_PPM, CNT_ESPONSE_2_PPM, CNT_LOYAL_CM_TO_PM, GP_2_OBJ_RAZVUSL_PPM, \

MAX_SPORT_HTTP_VISITS_CM, CNT_SPORT_HTTP_WKND_CM, CNT_DAYS_SPORT_HTTP_CM, SPORT_HTTP_TO_ALL_CM, CNT_DAYS_HOMELIFE_HTTP_CM, CNT_SPORT_HTTP_PM, SPORT_HTTP_CNT_TO_DAYS_PM, \

CNT_DAYS_INTBUY_HTTP_PM, FILM_HTTP_TO_ALL_PPM, CNT_DAYS_SPORT_HTTP_PPM, SPORT_HTTP_SHARE_CM_MORE_PM, INTBUY_HTTP_SHARE_CM_MORE_PM, HOMELIFE_HTTP_SHARE_CM_MORE_PM, \

NEWS_VISITS_CM_TO_PM, \

ANT_KASPERSKY_DAYS_MNTH, APP_BOOKING_DAYS_M, APP_DROPBOX_DAYS_M, APP_VIBER_DAYS_MNTH, APP_WHATSAPP_DAYS_MNTH, APP_YA_MAPS_DAYS_M, APP_YA_TAXI_DAYS_M, \

DEV_CONSOLE_PS_DAYS_MNTH, DEV_CONSOLE_XBOX_DAYS_MNTH, HTTP_VIS_ANDD_WKND_SHARE_MNTH, HTTP_VIS_S_TV_WORKD_SHARE_MNTH, OBP_SBERBANK_DAYS_M, PROTO_HTTP_DAYS_M, \

PROTO_HTTP_SHARE_MNTH, PROTO_OTHER_DAYS_M, PROTO_TORRENT_DAYS_M, PROTO_TOTAL_DAYS_M, WTHT_HTTP_VIS_S_TV_DAYS_ALL, WTHT_HTTP_VIS_WIN_M_DAYS_ALL, WTHT_HTTP_VISITS_DAYS \

FROM MA_CLIENT_DATA_MART_201703 a \

INNER JOIN MA_NAPA_DPI_CAT_201703 b ON a.ID_CLIENT = b.CLIENT_ID AND a.BILLING_ID = b.CITY_ID \

LEFT JOIN MA_NAPA_DPI_STAT_201703 c ON a.ID_CLIENT = c.CLIENT_ID AND a.BILLING_ID = c.CITY_ID \

LEFT JOIN PREDICT_BIL_201703 d ON a.ID_CLIENT = d.ID_CLIENT AND a.BILLING_ID = d.BILLING_ID \

LEFT JOIN PREDICT_CAT_201703 e ON a.ID_CLIENT = e.ID_CLIENT AND a.BILLING_ID = e.BILLING_ID \

LEFT JOIN PREDICT_CAMP_201703 f ON a.ID_CLIENT = f.ID_CLIENT AND a.BILLING_ID = f.BILLING_ID \

INNER JOIN \

(SELECT ID_CLIENT, BILLING_ID, VIASAT_ON FROM CA_201703 WHERE VIASAT_ON IS NOT NULL) g \

ON a.ID_CLIENT = g.ID_CLIENT AND a.BILLING_ID = g.BILLING_ID'

# Определение запроса SQL для получения данных за 201704

sql_query_201704 = 'SELECT DISTINCT g.VIASAT_ON, \

a.ID_CLIENT, a.BILLING_ID, a.CALC_PERIOD, CL_PRIV, ADP_AMEDIAPREMIUMHD, ADP_BAZOVYYHD, ADP_MATCHFUTBOL, ADP_NASTROYKINO, AG_BEFORE_PAID_SVOD, AG_COUNT_ACT_IKTV, \

AG_COUNT_CHANNEL_HD_TOTAL, AG_COUNT_CHANNEL_TOTAL, AG_IKTV_ARPU, AG_IKTV_TARIFF_ARCH, AG_INTER_ARPU, AG_MULTIROOM_COST, AG_MULTISCR, AG_PAY_CUR_MONTH, APP_NASTROYKINO, \

PAY_ARPU_SUMM, PAY_COUNT_ADD_PACK_DISC, \

HOME2_VISITS_DAYS_WKND_M, LEISURE2_VISITS_DAYS_WKND_M, MAX_SHOPS2_VISITS_DAY_CNT, MAX_SPORT2_VISITS_DAY_CNT, NEWS_VISITS_DAYS_WKND_M, SHOPS2_VISITS_DAYS_WKND_M, \

SHOPS2_VISITS_SHARE_M, SOC_VISITS_DAYS_WKND_M, SOCCER_VISITS_DAYS_WKND_M, SPORT2_VISITS_CNT_WKND_M, SPORT2_VISITS_DAYS_M, SPORT2_VISITS_SHARE_WORKD_M, \

CNT_AD_SERV_IKTV_CM, HAS_PC_MFUT_CM, HAS_PC_NASTKIN_CM, HAS_AD_PC_CM, CNT_TELE_AD_PC_CM, MAX_DAYS_FILM_AD_PC_CM, AG_IKTV_ARPU_CM, PAY_ARPU_SUMM_CM, HAS_ANY_AD_SERV_CM, \

CNT_FILM_AD_PC_PPM, AG_INTER_ARPU_PPM, AG_IKTV_ARPU_MORE_AVG_AAB, AG_INTER_ARPU_TO_MEDIAN_AAB, AG_INTER_ARPU_MORE_MOD_AAB, PAY_ARPU_SUMM_TO_MOD_AAB, \

PAY_ARPU_SUMM_MORE_AVG_AAB, MONTHPART_PC_MFUT_CM, MONTHPART_PC_NASTKIN_CM, \

MINUTES_COMMUN_CM, MINUTES_COMMUN_SPECPREDLK_CM, CNT_UNIQ_CHANNEL_CM, CNT_LOYAL_CM, MINUTES_LOYAL_CM, CNT_ESPONSE_2_CM, CNT_RESPONSE_3_CM, GP_2_OBJ_SOHR_CM, \

GP_3_OBJ_DZ_CM, MIN_ONE_COMM_SPECPREDLK_PM, CNT_COMMUN_PPM, MINUTES_COMMUN_SPECPREDLK_PPM, MINUTES_LOYAL_PPM, CNT_ESPONSE_2_PPM, CNT_LOYAL_CM_TO_PM, GP_2_OBJ_RAZVUSL_PPM, \

MAX_SPORT_HTTP_VISITS_CM, CNT_SPORT_HTTP_WKND_CM, CNT_DAYS_SPORT_HTTP_CM, SPORT_HTTP_TO_ALL_CM, CNT_DAYS_HOMELIFE_HTTP_CM, CNT_SPORT_HTTP_PM, SPORT_HTTP_CNT_TO_DAYS_PM, \

CNT_DAYS_INTBUY_HTTP_PM, FILM_HTTP_TO_ALL_PPM, CNT_DAYS_SPORT_HTTP_PPM, SPORT_HTTP_SHARE_CM_MORE_PM, INTBUY_HTTP_SHARE_CM_MORE_PM, HOMELIFE_HTTP_SHARE_CM_MORE_PM, \

NEWS_VISITS_CM_TO_PM, \

ANT_KASPERSKY_DAYS_MNTH, APP_BOOKING_DAYS_M, APP_DROPBOX_DAYS_M, APP_VIBER_DAYS_MNTH, APP_WHATSAPP_DAYS_MNTH, APP_YA_MAPS_DAYS_M, APP_YA_TAXI_DAYS_M, \

DEV_CONSOLE_PS_DAYS_MNTH, DEV_CONSOLE_XBOX_DAYS_MNTH, HTTP_VIS_ANDD_WKND_SHARE_MNTH, HTTP_VIS_S_TV_WORKD_SHARE_MNTH, OBP_SBERBANK_DAYS_M, PROTO_HTTP_DAYS_M, \

PROTO_HTTP_SHARE_MNTH, PROTO_OTHER_DAYS_M, PROTO_TORRENT_DAYS_M, PROTO_TOTAL_DAYS_M, WTHT_HTTP_VIS_S_TV_DAYS_ALL, WTHT_HTTP_VIS_WIN_M_DAYS_ALL, WTHT_HTTP_VISITS_DAYS \

FROM MA_CLIENT_DATA_MART_201704 a \

INNER JOIN MA_NAPA_DPI_CAT_201704 b ON a.ID_CLIENT = b.CLIENT_ID AND a.BILLING_ID = b.CITY_ID \

LEFT JOIN MA_NAPA_DPI_STAT_201704 c ON a.ID_CLIENT = c.CLIENT_ID AND a.BILLING_ID = c.CITY_ID \

LEFT JOIN PREDICT_BIL_201704 d ON a.ID_CLIENT = d.ID_CLIENT AND a.BILLING_ID = d.BILLING_ID \

LEFT JOIN PREDICT_CAT_201704 e ON a.ID_CLIENT = e.ID_CLIENT AND a.BILLING_ID = e.BILLING_ID \

LEFT JOIN PREDICT_CAMP_201704 f ON a.ID_CLIENT = f.ID_CLIENT AND a.BILLING_ID = f.BILLING_ID \

INNER JOIN \

(SELECT ID_CLIENT, BILLING_ID, VIASAT_ON FROM CA_201704 WHERE VIASAT_ON IS NOT NULL) g \

ON a.ID_CLIENT = g.ID_CLIENT AND a.BILLING_ID = g.BILLING_ID'

# Определение запроса SQL для получения данных за 201705

sql_query_201705 = 'SELECT DISTINCT g.VIASAT_ON, \

a.ID_CLIENT, a.BILLING_ID, a.CALC_PERIOD, CL_PRIV, ADP_AMEDIAPREMIUMHD, ADP_BAZOVYYHD, ADP_MATCHFUTBOL, ADP_NASTROYKINO, AG_BEFORE_PAID_SVOD, AG_COUNT_ACT_IKTV, \

AG_COUNT_CHANNEL_HD_TOTAL, AG_COUNT_CHANNEL_TOTAL, AG_IKTV_ARPU, AG_IKTV_TARIFF_ARCH, AG_INTER_ARPU, AG_MULTIROOM_COST, AG_MULTISCR, AG_PAY_CUR_MONTH, APP_NASTROYKINO, \

PAY_ARPU_SUMM, PAY_COUNT_ADD_PACK_DISC, \

HOME2_VISITS_DAYS_WKND_M, LEISURE2_VISITS_DAYS_WKND_M, MAX_SHOPS2_VISITS_DAY_CNT, MAX_SPORT2_VISITS_DAY_CNT, NEWS_VISITS_DAYS_WKND_M, SHOPS2_VISITS_DAYS_WKND_M, \

SHOPS2_VISITS_SHARE_M, SOC_VISITS_DAYS_WKND_M, SOCCER_VISITS_DAYS_WKND_M, SPORT2_VISITS_CNT_WKND_M, SPORT2_VISITS_DAYS_M, SPORT2_VISITS_SHARE_WORKD_M, \

CNT_AD_SERV_IKTV_CM, HAS_PC_MFUT_CM, HAS_PC_NASTKIN_CM, HAS_AD_PC_CM, CNT_TELE_AD_PC_CM, MAX_DAYS_FILM_AD_PC_CM, AG_IKTV_ARPU_CM, PAY_ARPU_SUMM_CM, HAS_ANY_AD_SERV_CM, \

CNT_FILM_AD_PC_PPM, AG_INTER_ARPU_PPM, AG_IKTV_ARPU_MORE_AVG_AAB, AG_INTER_ARPU_TO_MEDIAN_AAB, AG_INTER_ARPU_MORE_MOD_AAB, PAY_ARPU_SUMM_TO_MOD_AAB, \

PAY_ARPU_SUMM_MORE_AVG_AAB, MONTHPART_PC_MFUT_CM, MONTHPART_PC_NASTKIN_CM, \

MINUTES_COMMUN_CM, MINUTES_COMMUN_SPECPREDLK_CM, CNT_UNIQ_CHANNEL_CM, CNT_LOYAL_CM, MINUTES_LOYAL_CM, CNT_ESPONSE_2_CM, CNT_RESPONSE_3_CM, GP_2_OBJ_SOHR_CM, \

GP_3_OBJ_DZ_CM, MIN_ONE_COMM_SPECPREDLK_PM, CNT_COMMUN_PPM, MINUTES_COMMUN_SPECPREDLK_PPM, MINUTES_LOYAL_PPM, CNT_ESPONSE_2_PPM, CNT_LOYAL_CM_TO_PM, GP_2_OBJ_RAZVUSL_PPM, \

MAX_SPORT_HTTP_VISITS_CM, CNT_SPORT_HTTP_WKND_CM, CNT_DAYS_SPORT_HTTP_CM, SPORT_HTTP_TO_ALL_CM, CNT_DAYS_HOMELIFE_HTTP_CM, CNT_SPORT_HTTP_PM, SPORT_HTTP_CNT_TO_DAYS_PM, \

CNT_DAYS_INTBUY_HTTP_PM, FILM_HTTP_TO_ALL_PPM, CNT_DAYS_SPORT_HTTP_PPM, SPORT_HTTP_SHARE_CM_MORE_PM, INTBUY_HTTP_SHARE_CM_MORE_PM, HOMELIFE_HTTP_SHARE_CM_MORE_PM, \

NEWS_VISITS_CM_TO_PM, \

ANT_KASPERSKY_DAYS_MNTH, APP_BOOKING_DAYS_M, APP_DROPBOX_DAYS_M, APP_VIBER_DAYS_MNTH, APP_WHATSAPP_DAYS_MNTH, APP_YA_MAPS_DAYS_M, APP_YA_TAXI_DAYS_M, \

DEV_CONSOLE_PS_DAYS_MNTH, DEV_CONSOLE_XBOX_DAYS_MNTH, HTTP_VIS_ANDD_WKND_SHARE_MNTH, HTTP_VIS_S_TV_WORKD_SHARE_MNTH, OBP_SBERBANK_DAYS_M, PROTO_HTTP_DAYS_M, \

PROTO_HTTP_SHARE_MNTH, PROTO_OTHER_DAYS_M, PROTO_TORRENT_DAYS_M, PROTO_TOTAL_DAYS_M, WTHT_HTTP_VIS_S_TV_DAYS_ALL, WTHT_HTTP_VIS_WIN_M_DAYS_ALL, WTHT_HTTP_VISITS_DAYS \

FROM MA_CLIENT_DATA_MART_201705 a \

INNER JOIN MA_NAPA_DPI_CAT_201705 b ON a.ID_CLIENT = b.CLIENT_ID AND a.BILLING_ID = b.CITY_ID \

LEFT JOIN MA_NAPA_DPI_STAT_201705 c ON a.ID_CLIENT = c.CLIENT_ID AND a.BILLING_ID = c.CITY_ID \

LEFT JOIN PREDICT_BIL_201705 d ON a.ID_CLIENT = d.ID_CLIENT AND a.BILLING_ID = d.BILLING_ID \

LEFT JOIN PREDICT_CAT_201705 e ON a.ID_CLIENT = e.ID_CLIENT AND a.BILLING_ID = e.BILLING_ID \

LEFT JOIN PREDICT_CAMP_201705 f ON a.ID_CLIENT = f.ID_CLIENT AND a.BILLING_ID = f.BILLING_ID \

INNER JOIN \

(SELECT ID_CLIENT, BILLING_ID, VIASAT_ON FROM CA_201705 WHERE VIASAT_ON IS NOT NULL) g \

ON a.ID_CLIENT = g.ID_CLIENT AND a.BILLING_ID = g.BILLING_ID'

%%time

# Magic %%time для фиксации времени выполнения запроса

conn = None # Объявление переменной для соединения с БД

# Отлавливаем ошибку отсутствия подключения к заданной БД

try:

conn = cx_Oracle.connect("ext_consult/GfhjkmGjlhzlxbrf@DM") # Объявляем соединение с БД

df201703 = pd.read_sql(sql_query_201703, conn) # Получение DataFrame по запросу SQL

finally:

if conn is not None:

conn.close() # Закрываем соединение с БД

# Проверяем количество записей с целевой меткой

# 1 для определения объема обучающей выборки

df201703[df201703.VIASAT_ON == 1].shape

df201703tr = df201703[df201703.VIASAT_ON == 1]

# Получение всех записей со значением целевой метки, равным 1

df201703fls = df201703[df201703.VIASAT_ON == 0].sample(60000, axis = 0)

# Получение всех записей с негативными исходами,

# выделение случайным образом выборки объемом 60000 записей

del df201703 # Удаление DataFrame со свеми данными за период 201703 (с целью освобождения памяти)

%%time

# Magic %%time для фиксации времени выполнения запроса

conn = None # Объявление переменной для соединения с БД

# Отлавливаем ошибку отсутствия подключения к заданной БД

try:

conn = cx_Oracle.connect("ext_consult/GfhjkmGjlhzlxbrf@DM") # Объявляем соединение с БД

df201704 = pd.read_sql(sql_query_201704, conn) # Получение DataFrame по запросу SQL

finally:

if conn is not None:

conn.close() # Закрываем соединение с БД

df201704tr = df201704[df201704.VIASAT_ON == 1] # Получение всех записей со значением целевой метки, равным 1

df201704fls = df201704[df201704.VIASAT_ON == 0].sample(60000, axis = 0) # Получение всех записей с негативными исходами,

# выделение случайным образом выборки объемом 60000 записей

del df201704 # Удаление DataFrame со свеми данными за период 201704 (с целью освобождения памяти)

%%time

# Magic %%time для фиксации времени выполнения запроса

conn = None # Объявление переменной для соединения с БД

# Отлавливаем ошибку отсутствия подключения к заданной БД

try:

conn = cx_Oracle.connect("ext_consult/GfhjkmGjlhzlxbrf@DM") # Объявляем соединение с БД

df201705 = pd.read_sql(sql_query_201705, conn) # Получение DataFrame по запросу SQL

finally:

if conn is not None:

conn.close() # Закрываем соединение с БД

df201705tr = df201705[df201705.VIASAT_ON == 1] # Получение всех записей со значением целевой метки, равным 1

df201705fls = df201705[df201705.VIASAT_ON == 0].sample(60000, axis = 0) # Получение всех записей с негативными исходами,

# выделение случайным образом выборки объемом 60000 записей

del df201705 # Удаление DataFrame со свеми данными за период 201705 (с целью освобождения памяти)

# Создание обучающей выборки за 201703 - 201705

df = pd.concat([df201703tr, df201703fls, df201704tr, df201704fls, df201705tr, df201705fls], axis = 0, ignore_index = True) # Вертикальная конкатенация датасетов

# с целевой меткой 0 и 1 за 201703, 201704, 201705

# Определение DataFrame с исключительно вещественными значениями (без бинарных, категориальных и дат)

df1 = df[['ADP_AMEDIAPREMIUMHD', 'ADP_BAZOVYYHD', 'ADP_MATCHFUTBOL', 'ADP_NASTROYKINO', 'AG_BEFORE_PAID_SVOD', 'AG_COUNT_ACT_IKTV',

'AG_COUNT_CHANNEL_HD_TOTAL', 'AG_COUNT_CHANNEL_TOTAL', 'AG_IKTV_ARPU', 'AG_INTER_ARPU', 'AG_MULTIROOM_COST', 'AG_MULTISCR', 'AG_PAY_CUR_MONTH', 'APP_NASTROYKINO',

'PAY_ARPU_SUMM', 'PAY_COUNT_ADD_PACK_DISC',

'HOME2_VISITS_DAYS_WKND_M', 'LEISURE2_VISITS_DAYS_WKND_M', 'MAX_SHOPS2_VISITS_DAY_CNT', 'MAX_SPORT2_VISITS_DAY_CNT', 'NEWS_VISITS_DAYS_WKND_M', 'SHOPS2_VISITS_DAYS_WKND_M',

'SHOPS2_VISITS_SHARE_M', 'SOC_VISITS_DAYS_WKND_M', 'SOCCER_VISITS_DAYS_WKND_M', 'SPORT2_VISITS_CNT_WKND_M', 'SPORT2_VISITS_DAYS_M', 'SPORT2_VISITS_SHARE_WORKD_M',

'CNT_AD_SERV_IKTV_CM', 'CNT_TELE_AD_PC_CM', 'MAX_DAYS_FILM_AD_PC_CM', 'AG_IKTV_ARPU_CM', 'PAY_ARPU_SUMM_CM',

'CNT_FILM_AD_PC_PPM', 'AG_INTER_ARPU_PPM', 'AG_INTER_ARPU_TO_MEDIAN_AAB', 'PAY_ARPU_SUMM_TO_MOD_AAB',

'MONTHPART_PC_MFUT_CM', 'MONTHPART_PC_NASTKIN_CM',

'MINUTES_COMMUN_CM', 'MINUTES_COMMUN_SPECPREDLK_CM', 'CNT_UNIQ_CHANNEL_CM', 'CNT_LOYAL_CM', 'MINUTES_LOYAL_CM', 'CNT_ESPONSE_2_CM', 'CNT_RESPONSE_3_CM',

'MIN_ONE_COMM_SPECPREDLK_PM', 'CNT_COMMUN_PPM', 'MINUTES_COMMUN_SPECPREDLK_PPM', 'MINUTES_LOYAL_PPM', 'CNT_ESPONSE_2_PPM', 'CNT_LOYAL_CM_TO_PM',

'MAX_SPORT_HTTP_VISITS_CM', 'CNT_SPORT_HTTP_WKND_CM', 'CNT_DAYS_SPORT_HTTP_CM', 'SPORT_HTTP_TO_ALL_CM', 'CNT_DAYS_HOMELIFE_HTTP_CM', 'CNT_SPORT_HTTP_PM', 'SPORT_HTTP_CNT_TO_DAYS_PM',

'CNT_DAYS_INTBUY_HTTP_PM', 'FILM_HTTP_TO_ALL_PPM', 'CNT_DAYS_SPORT_HTTP_PPM', 'SPORT_HTTP_SHARE_CM_MORE_PM', 'INTBUY_HTTP_SHARE_CM_MORE_PM', 'HOMELIFE_HTTP_SHARE_CM_MORE_PM',

'NEWS_VISITS_CM_TO_PM',

'ANT_KASPERSKY_DAYS_MNTH', 'APP_BOOKING_DAYS_M', 'APP_DROPBOX_DAYS_M', 'APP_VIBER_DAYS_MNTH', 'APP_WHATSAPP_DAYS_MNTH', 'APP_YA_MAPS_DAYS_M', 'APP_YA_TAXI_DAYS_M',

'DEV_CONSOLE_PS_DAYS_MNTH', 'DEV_CONSOLE_XBOX_DAYS_MNTH', 'HTTP_VIS_ANDD_WKND_SHARE_MNTH', 'HTTP_VIS_S_TV_WORKD_SHARE_MNTH', 'OBP_SBERBANK_DAYS_M', 'PROTO_HTTP_DAYS_M',

'PROTO_HTTP_SHARE_MNTH', 'PROTO_OTHER_DAYS_M', 'PROTO_TORRENT_DAYS_M', 'PROTO_TOTAL_DAYS_M', 'WTHT_HTTP_VIS_S_TV_DAYS_ALL', 'WTHT_HTTP_VIS_WIN_M_DAYS_ALL', 'WTHT_HTTP_VISITS_DAYS']]

# Определение пользовательской функции борьбы с выбросами

def mist(dtfrm):

for col in dtfrm.columns: # Для каждого поля из DataFrame

df2 = dtfrm[col].dropna().sort_values(ascending = True) # Создаем DataFrame, удаляя пустые значения для данного поля и сортируя по возрастанию значения

df2 = df2.reset_index(drop = True) # Реиндексируем DataFrame

qty_25 = math.ceil(df2.shape[0] * 0.25) # Определяем номер строки, содержащей 25-квантиль

qty_75 = math.ceil(df2.shape[0] * 0.75) # Определяем номер строки, содержащей 75-квантиль

q_25 = df2[df2.index == qty_25].item() # Находим 25-квантиль

q_75 = df2[df2.index == qty_75].item() # Находим 75-квантиль

iqr = math.ceil((q_75 - q_25) * 1.5) # Находим полтора квантильных размаха

min_q = q_25 - iqr # Находим минимально допустимое значение, которое не будет считаться выбросом

max_q = q_75 + iqr # Находим максимально допустимое значение, которое не будет считаться выбросом

med = df2.median() # Находим медиану

i = 0

while i < dtfrm[col].shape[0]: # Перебираем все строки из DataFrame

if ((dtfrm[col][i] < min_q) | (dtfrm[col][i] > max_q)): # Если значение в строке меньше наименее допустимого или больше наиболее допустимого,

dtfrm[col][i] = med # То меняем данное значение на медиану

i += 1 # Переходим к следующей строке

return dtfrm # Возвращаем полученный DataFrame

mist(df1) # Применение определенной выше функции

for col in df.coumns:

df[col] = df1[col] # Заменяем атрибуты исходного DataFrame полями, полученными после применения функции

# Проверка на наличие Null-значений, заполнение пропусков либо значением 30

if df.isnull().values.any() == True:

df['WTHT_HTTP_VIS_S_TV_DAYS_ALL'] = df['WTHT_HTTP_VIS_S_TV_DAYS_ALL'].fillna(30)

df['WTHT_HTTP_VIS_WIN_M_DAYS_ALL'] = df['WTHT_HTTP_VIS_WIN_M_DAYS_ALL'].fillna(30)

df['WTHT_HTTP_VISITS_DAYS'] = df['WTHT_HTTP_VISITS_DAYS'].fillna(30)

# Создание dummy-переменных на основании категориальных признаков для обучающей выборки

df = pd.get_dummies(df, columns = ['MONTHPART_PC_MFUT_CM','MONTHPART_PC_NASTKIN_CM'], drop_first = True)

# Выведение полученного DataFrame (Видим, что количество атрибутов увеличено за счет создания dummy)

df.head()

# В блоке производится очистка большинства производных от dummy атрибутов

df1 = [] # Сохдание дополнительных массивов для удаления производных от dummy-переменных атрибутов

df2 = []

for col in df.columns: # Поиск необходимых для сохранения атрибутов

if ((('MONTHPART_PC_MFUT_CM_' not in col) | (col == 'MONTHPART_PC_MFUT_CM_1')) &

(('MONTHPART_PC_NASTKIN_CM_' not in col) | (col == 'MONTHPART_PC_NASTKIN_CM_1'))):

df1.append(col) # Добавление названий атрибутов в list

for i in df1:

df2.append(df[i]) # Добавление полей из df с названиями атрибутов из df1 в list

df = pd.DataFrame(df2).transpose() # Преобразование полученного выше list в DataFrame

del df1, df2 # Удаление вспомогательных массивов

# Выведениие итогового DataFrame на экран

df.head()

train_labels = df['VIASAT_ON'] # Определение целевых меток для обучающей выборки

train_data = df.drop(['VIASAT_ON', 'ID_CLIENT', 'BILLING_ID', 'CALC_PERIOD'], axis = 1) # Определение предикторов для обучающей выборки

# Определение запроса для получения данных за 201706 (для проведения тестов)

sql_query_201706 = 'SELECT DISTINCT g.VIASAT_ON, \

a.ID_CLIENT, a.BILLING_ID, a.CALC_PERIOD, CL_PRIV, ADP_AMEDIAPREMIUMHD, ADP_BAZOVYYHD, ADP_MATCHFUTBOL, ADP_NASTROYKINO, AG_BEFORE_PAID_SVOD, AG_COUNT_ACT_IKTV, \

AG_COUNT_CHANNEL_HD_TOTAL, AG_COUNT_CHANNEL_TOTAL, AG_IKTV_ARPU, AG_IKTV_TARIFF_ARCH, AG_INTER_ARPU, AG_MULTIROOM_COST, AG_MULTISCR, AG_PAY_CUR_MONTH, APP_NASTROYKINO, \

PAY_ARPU_SUMM, PAY_COUNT_ADD_PACK_DISC, \

HOME2_VISITS_DAYS_WKND_M, LEISURE2_VISITS_DAYS_WKND_M, MAX_SHOPS2_VISITS_DAY_CNT, MAX_SPORT2_VISITS_DAY_CNT, NEWS_VISITS_DAYS_WKND_M, SHOPS2_VISITS_DAYS_WKND_M, \

SHOPS2_VISITS_SHARE_M, SOC_VISITS_DAYS_WKND_M, SOCCER_VISITS_DAYS_WKND_M, SPORT2_VISITS_CNT_WKND_M, SPORT2_VISITS_DAYS_M, SPORT2_VISITS_SHARE_WORKD_M, \

CNT_AD_SERV_IKTV_CM, HAS_PC_MFUT_CM, HAS_PC_NASTKIN_CM, HAS_AD_PC_CM, CNT_TELE_AD_PC_CM, MAX_DAYS_FILM_AD_PC_CM, AG_IKTV_ARPU_CM, PAY_ARPU_SUMM_CM, HAS_ANY_AD_SERV_CM, \

CNT_FILM_AD_PC_PPM, AG_INTER_ARPU_PPM, AG_IKTV_ARPU_MORE_AVG_AAB, AG_INTER_ARPU_TO_MEDIAN_AAB, AG_INTER_ARPU_MORE_MOD_AAB, PAY_ARPU_SUMM_TO_MOD_AAB, \

PAY_ARPU_SUMM_MORE_AVG_AAB, MONTHPART_PC_MFUT_CM, MONTHPART_PC_NASTKIN_CM, \

MINUTES_COMMUN_CM, MINUTES_COMMUN_SPECPREDLK_CM, CNT_UNIQ_CHANNEL_CM, CNT_LOYAL_CM, MINUTES_LOYAL_CM, CNT_ESPONSE_2_CM, CNT_RESPONSE_3_CM, GP_2_OBJ_SOHR_CM, \

GP_3_OBJ_DZ_CM, MIN_ONE_COMM_SPECPREDLK_PM, CNT_COMMUN_PPM, MINUTES_COMMUN_SPECPREDLK_PPM, MINUTES_LOYAL_PPM, CNT_ESPONSE_2_PPM, CNT_LOYAL_CM_TO_PM, GP_2_OBJ_RAZVUSL_PPM, \

MAX_SPORT_HTTP_VISITS_CM, CNT_SPORT_HTTP_WKND_CM, CNT_DAYS_SPORT_HTTP_CM, SPORT_HTTP_TO_ALL_CM, CNT_DAYS_HOMELIFE_HTTP_CM, CNT_SPORT_HTTP_PM, SPORT_HTTP_CNT_TO_DAYS_PM, \

CNT_DAYS_INTBUY_HTTP_PM, FILM_HTTP_TO_ALL_PPM, CNT_DAYS_SPORT_HTTP_PPM, SPORT_HTTP_SHARE_CM_MORE_PM, INTBUY_HTTP_SHARE_CM_MORE_PM, HOMELIFE_HTTP_SHARE_CM_MORE_PM, \

NEWS_VISITS_CM_TO_PM, \

ANT_KASPERSKY_DAYS_MNTH, APP_BOOKING_DAYS_M, APP_DROPBOX_DAYS_M, APP_VIBER_DAYS_MNTH, APP_WHATSAPP_DAYS_MNTH, APP_YA_MAPS_DAYS_M, APP_YA_TAXI_DAYS_M, \

DEV_CONSOLE_PS_DAYS_MNTH, DEV_CONSOLE_XBOX_DAYS_MNTH, HTTP_VIS_ANDD_WKND_SHARE_MNTH, HTTP_VIS_S_TV_WORKD_SHARE_MNTH, OBP_SBERBANK_DAYS_M, PROTO_HTTP_DAYS_M, \

PROTO_HTTP_SHARE_MNTH, PROTO_OTHER_DAYS_M, PROTO_TORRENT_DAYS_M, PROTO_TOTAL_DAYS_M, WTHT_HTTP_VIS_S_TV_DAYS_ALL, WTHT_HTTP_VIS_WIN_M_DAYS_ALL, WTHT_HTTP_VISITS_DAYS \

FROM MA_CLIENT_DATA_MART_201706 a \

LEFT JOIN MA_NAPA_DPI_CAT_201706 b ON a.ID_CLIENT = b.CLIENT_ID AND a.BILLING_ID = b.CITY_ID \

LEFT JOIN MA_NAPA_DPI_STAT_201706 c ON a.ID_CLIENT = c.CLIENT_ID AND a.BILLING_ID = c.CITY_ID \

LEFT JOIN PREDICT_BIL_201706 d ON a.ID_CLIENT = d.ID_CLIENT AND a.BILLING_ID = d.BILLING_ID \

LEFT JOIN PREDICT_CAT_201706 e ON a.ID_CLIENT = e.ID_CLIENT AND a.BILLING_ID = e.BILLING_ID \

LEFT JOIN PREDICT_CAMP_201706 f ON a.ID_CLIENT = f.ID_CLIENT AND a.BILLING_ID = f.BILLING_ID \

INNER JOIN \

(SELECT ID_CLIENT, BILLING_ID, VIASAT_ON FROM CA_201706 WHERE VIASAT_ON IS NOT NULL) g \

ON a.ID_CLIENT = g.ID_CLIENT AND a.BILLING_ID = g.BILLING_ID'

%%time

# Magic %%time для фиксации времени выполнения запроса

conn = None # Объявление переменной для соединения с БД

# Отлавливаем ошибку отсутствия подключения к заданной БД

try:

conn = cx_Oracle.connect("ext_consult/GfhjkmGjlhzlxbrf@DM") # Объявляем соединение с БД

df201706 = pd.read_sql(sql_query_201706, conn) # Получение DataFrame по запросу SQL

finally:

if conn is not None:

conn.close() # Закрываем соединение с БД

# Проверка на наличие Null-значений, заполнение пропусков либо значением 30

if df201706.isnull().values.any() == True:

df201706['WTHT_HTTP_VIS_S_TV_DAYS_ALL'] = df201706['WTHT_HTTP_VIS_S_TV_DAYS_ALL'].fillna(30)

df201706['WTHT_HTTP_VIS_WIN_M_DAYS_ALL'] = df201706['WTHT_HTTP_VIS_WIN_M_DAYS_ALL'].fillna(30)

df201706['WTHT_HTTP_VISITS_DAYS'] = df201706['WTHT_HTTP_VISITS_DAYS'].fillna(30)

# Создание dummy-переменных на основании категориальных признаков для тестовой выборки

df201706 = pd.get_dummies(df201706, columns = ['MONTHPART_PC_MFUT_CM','MONTHPART_PC_NASTKIN_CM'], drop_first = True)

# В блоке производится очистка большинства производных от dummy атрибутов

df1 = [] # Сохдание дополнительных массивов для удаления производных от dummy-переменных атрибутов

df2 = []

for col in df201706.columns: # Поиск необходдимых для сохранения атрибутов

if ((('MONTHPART_PC_MFUT_CM_' not in col) | (col == 'MONTHPART_PC_MFUT_CM_1')) &

(('MONTHPART_PC_NASTKIN_CM_' not in col) | (col == 'MONTHPART_PC_NASTKIN_CM_1'))):

df1.append(col) # Добавление названий атрибутов в list

for i in df1:

df2.append(df201706[i]) # Добавление полей из df201706 с названиями атрибутов из df1 в list

df201706 = pd.DataFrame(df2).transpose() # Преобразование полученного выше list в DataFrame

del df1, df2 # Удаление вспомогательных массивов

test_labels = df201706['VIASAT_ON'] # Определение целевых меток для тестовой выборки

test_data = df201706.drop(['VIASAT_ON', 'ID_CLIENT', 'BILLING_ID', 'CALC_PERIOD'], axis = 1) # Определение предикторов для тестовой выборки

# Создание пользовательской функции для расчета cummulative lift

def cumm_lift(DataFrame, booster, test_set):

pred = pd.DataFrame(booster.predict(test_set), columns = ['pred']) # Создание переменной, хранящей прогнозные значения вероятностей принадлежности к классу 1

result = pd.concat([DataFrame['VIASAT_ON'],DataFrame['ID_CLIENT'],DataFrame['BILLING_ID'],DataFrame['CALC_PERIOD'], pred], axis = 1) # Создание DataFrame, хранящего фактические значения целевой переменной, идентификаторы Клиента, биллинга и периода, а также

# прогнозные значения вероятностей принадлежности к классу 1

result = result.sort_values(['pred'], axis = 0, ascending = False) # Сортировка значений в DataFrame по убыванию вероятностей принадлежности к классу 1

result = result.reset_index(drop = True) # Реиндексирование DataFrame

qty_10 = math.ceil(result.shape[0] * 0.1) # Расчет количества записей в первых 10 перцентилях выборки

cumm_lift = (result.iloc[: qty_10, 0].sum() * 1.0 / qty_10) / (result.iloc[:, 0].sum() * 1.0 / result.shape[0]) # Расчет cummulative lift на первых 10 перцентилях (отношение суммы фактических целевых меток

# в первых 10 перцентилях к количеству записей в первых 10 перцентилях разделить на отношение суммы фактических целевых меток во всей генеральной совокупности к количеству записей в генеральной совокупности)

return result, cumm_lift # Функция возвращаяет полученный DataFrame и commulative lift

dtrain = xgb.DMatrix(train_data, train_labels, missing = NaN) # Формирование тренировочной матрицы на основе обучающих меток и данных, в качестве пропущенных значений определяем NaN

dtest = xgb.DMatrix(test_data, test_labels, missing = NaN) # Формирование тестовой матрицы на основе проверочных меток и данных, в качестве пропущенных значений определяем NaN

mas = [] # Создание массива для сохранения всех параметров

x_colsample_bytree = 0.3 # Перебираем параметр colsample_bytree от 0.3 до 0.8

while x_colsample_bytree <= 0.8:

x_subsample = 0.3 # Перебираем параметр subsample от 0.3 до 0.8

while x_subsample <= 0.8:

x_eta = 0.03 # Перебираем параметр eta от 0.03 до 0.08

while x_eta <= 0.08:

x_max_depth = 3 # Перебираем параметр max_depth от 3 до 8

while x_max_depth <= 8:

# Определяем перечень параметров

param = {'max_depth':x_max_depth, 'eta':x_eta, 'silent':1, 'objective':'binary:logistic', 'nthread':8,

'alpha':1, 'lambda':1, 'gamma':1, 'eval_metric':'auc', 'subsample':x_subsample,

'colsample_bytree':x_colsample_bytree, 'min_child_weight':1}

i=60 # Перебираем количество деревьев от 60 до 800

while i < 800:

bst = xgb.train(param, dtrain, i) # Обучаем модель на каждой совокупности параметров

result, cumm_lift = cumm_lift(df, bst, dtest) # Применяем пользовательскую функцию для расчета

# cummulative lift

mas.append(x_colsample_bytree, x_subsample, x_eta, x_max_depth, i, cumm_lift) # Заполнение массива

# для параметрами и значениями целевой переменной

print (x_colsample_bytree, x_subsample, x_eta, x_max_depth, i, cumm_lift) # Выводим на экран значения

# параметров и полученный целевой показатель

i += 20 # Деревья перебираем с шагом 20

x_max_depth += 1 # max_depth перебираем с шагом 1

x_eta += 0.01 # eta перебираем с шагом 0.01

x_subsample += 0.1 # subsample перебираем с шагом 0.1

x_colsample_bytree += 0.1 # colsample_bytree перебираем с шагом 0.1

mas = pd.DataFrame(mas, columns = [['COLSAMPLE','SUBSAMPLE','ETA','DEPTH',

'TREES','CUMM_LIFT']]).sort_values(['CUMM_LIFT'], axis = 0, ascending = False)

# Сортировка массива по убыванию значения Cumm lift

mas.head() # Вывод пяти множеств параметров с наибольшим значением cumm lift

# Определение наиболее оптимальных параметров для градиентного бустинга

param = {'max_depth':3, 'eta':0.06, 'silent':1, 'objective':'binary:logistic', 'nthread':8,

'alpha':1, 'lambda':1, 'gamma':1, 'eval_metric':'auc', 'subsample':0.5,

'colsample_bytree':0.5, 'min_child_weight':1}

# max_depth - максимальная глубина деревьев (в нашем случае равна 3)

# eta - доля исправляемой ошибки, полученной при построении предыдущего дерева (в нашем случае равна 0.06)

# silent - нужно ли выводить сообщения во время обучения (в нашем случае используем показатель по умолчанию = 1 (то есть не выводить))

# objective - объектная функция оптимизации в зависимости от решаемой задачи (в нашем случае решается задача бинарной классификации, поэтому используем objective binary logistic)

# nthread - количество параллельных потоков при отработке скрипта для увеличения скорости выполнения (в нашем случае 8)

# alpha - применение L2-регуляризации к листьям (в нашем случае используем показатель по умолчанию = 1 (то есть условия стандартные, регуляризацию не применяем))

# lambda - применение L1-регуляризации к листьям (в нашем случае используем показатель по умолчанию = 1 (то есть условия стандартные, регуляризацию не применяем))

# gamma - минимальное значение, которое позволяет продолжить построение ветви на узлах (в нашем случае используем показатель по умолчанию = 1)

# eval_metric - метрика для оценки качества модели (в нашем случае AUC)

# subsample - доля записей, которые будут использоваться при обучении дерева (в нашем случае 0.5)

# colsample_bytree - доля предикторов, которые будут использоваться при построении каждого дерева (в нашем случае 0.5)

# min_child_weight - минимальная сумма веса экземпляра, необходимая ребенку (в нашем случае используем показатель по умолчанию = 1)

bst = xgb.train(param, dtrain, 160, [(dtrain,'train'), (dtest,'test')]) # Обучаем бустер на 160 деревьев с использованием заданных параметров, обучающей и тестовой матриц

result, cumm_lift = cumm_lift(df, bst, dtest) # Применяем пользовательскую функцию для расчета cummulative lift

print (cumm_lift) # Вывод показателя commulative lift на первых 10 перцентилях

# Вывод результатов в текстовый файл

result.to_csv('Viasat_ON.csv', sep = ',', header = True, index = False)

# Сохранение обучающей выборки после обработки

output = open('Viasat_Train_DS.pkl', 'wb')

pickle.dump(df, output, 2)

output.close()

# Сохранение бустера

output = open('Viasat_Model.pkl', 'wb')

pickle.dump(bst, output, 2)

output.close()

Размещено на Allbest.ru

...

Подобные документы

Работы в архивах красиво оформлены согласно требованиям ВУЗов и содержат рисунки, диаграммы, формулы и т.д.
PPT, PPTX и PDF-файлы представлены только в архивах.
Рекомендуем скачать работу.