Как программист новую машину подбирал

в 9:48, , рубрики: data mining, predictive analytics, R, R-project, random forest, Алгоритмы, машинное обучение, покупка автомобиля, Программирование

В предыдущих статьях (I, II, III) я подробно рассказывал о разработке сервиса для поиска выгодных б/у автомобилей в РФ.
Поездив продолжительное время на различных б/у машинах, я задумался о приобретении нового авто и решил этот вопрос подробно изучить. В крупных городах существует огромное количество официальных дилеров, по крайней мере для популярных брендов. Дилеры отличаются друг от друга перечнем автомобилей в наличии и размером предоставляемых скидок на различные модели. В поисках интересующих меня автомобилей мне не хотелось обзванивать и посещать всех дилеров подряд. На мой взгляд, разумно было предварительно отобрать по априорной информации только тех дилеров, которые предоставляют самые низкие цены на интересующие меня модели и комплектации. Тот факт, что при личном общении, если уметь торговаться, размер скидки может существенно возрасти никак не противоречит цели в первую очередь посетить дилеров, предоставляющих наиболее выгодные цены на рынке.
Я собрал данные о новых автомобилях, проанализировал, оформил в виде сервиса, и под конец года, когда скидки у дилеров максимальны, решил поделиться им с вами.

Как программист новую машину подбирал - 1

Обзор конкурентов

В рунете уже есть сервис для подбора и покупки новых авто — autospot.ru, но он обладает следующими существенными недостатками:

  1. На сайте нет возможности узнать контакты дилеров где находятся интересующие вас автомобили, вы можете только оставить свой телефон для обратной связи. Менеджер autospot.ru свяжется с вами в течение получаса, уточнит у вас марку, модель и комплектацию, после чего сообщит ваш телефон дилерам, которые располагают автомобилями, соответствующими вашим требованиям. Ждать первичного звонка от дилера вы будете не меньше часа. Крайне раздражающим фактором данной коммуникации является назойливость. После разговора менеджер autospot.ru и различные дилеры будут звонить вам довольно часто, напоминая о себе, даже если вы их попросите об обратном.
  2. На сайте представлено ~30 000 новых автомобилей со всей России, что составляет менее 30% от среднего числа реализуемых в месяц новых авто в 2018 году.
  3. На сайте нет оценки стоимости авто относительно рынка в соответствии с комплектацией и доп. опциями, то есть невозможно понять какие предложения наиболее выгодные.

Для досок объявлений auto.ru, drom.ru и avito.ru недостаток №2 актуален в разной степени, а №3 — в полной мере для всех.

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

Сбор данных

Данные о новых автомобилях у официальных дилеров собираются из различных источников, обрабатываются, систематизируются и унифицируются. Обновление данных и добавление новых источников производится на регулярной основе. Объем данных составляет ~75 000 новых автомобилей у более 650 дилеров из 70+ городов России.

Процесс сбора и обработки данных выходит за рамки данной статьи и, возможно, будет освещен в одной из следующих статей.

Преобразование данных и построение модели

Для поиска выгодных автомобилей по каждой модели авто в отдельности формировалась предиктивная регрессионная модель, целевой переменной которой была цена авто, а предикторы формировались из базовых данных авто, комплектации и установленных доп. опций. Параметры, имеющие несколько нечисловых значений, представлялись в модели виде n-1 фиктивной переменной.

Для наглядности, набор регрессоров для Volkswagen Tiguan имеет вид:

Подробнее

[1] «price»
[2] «availability»
[3] «year»
[4] «volume»
[5] «power»
[6] «front_drive»
[7] «rear_drive»
[8] «mkpp»
[9] «benzin»
[10] «dizel»
[11] «body_tsvet_kuzova_chernyy_metallik»
[12] «interior_tsvet_peredney_paneli_temnyy»
[13] «interior_tsvet_obivki_sideniy_temnyy»
[14] «interior_tsvet_potolka_temnyy»
[15] «interior_tsvet_kovrovogo_pokrytiya_temnyy»
[16] «equip_dnevnoy_svet»
[17] «equip_avtokorrektor_far_s_dinamicheskim_povorotnym_svetom»
[18] «equip_paket_innovation»
[19] «equip_fary_svetodiodnye»
[20] «equip_omyvatel_far»
[21] «equip_bortovoy_kompyuter»
[22] «safety_avtomaticheskaya_regulirovka_dalnosti_sveta»
[23] «body_tsvet_kuzova_siniy_metallik»
[24] «body_tsvet_kuzova_serebristyy_metallik»
[25] «equip_sistema_avtomaticheskoy_parkovki»
[26] «equip_tekhnicheskiy_kod»
[27] «equip_paket_media»
[28] «equip_usb_interfeysvklyuchaya_auxin»
[29] «equip_interfeys_appconnect»
[30] «equip_paket_zimnie_tekhnologii»
[31] «equip_multimediynaya_sistema_audio»
[32] «equip_parktronik»
[33] «safety_videokamera»
[34] «main_komplektatsiya_city_20_tdi_150hp_7dsg_4motion»
[35] «body_shiny_21565_r17_99_v»
[36] «body_razmer_diskov_r17»
[37] «body_diski_legkosplavnye»
[38] «interior_tip_sideniy_sportivnye»
[39] «interior_obivka_sideniy_kozha»
[40] «equip_distantsionnoe_otkryvanie_bagazhnika»
[41] «equip_zapusk_bez_povorota_klyucha»
[42] «equip_dostup_bez_klyucha»
[43] «equip_interfeys_dlya_smartfonov_appconnect»
[44] «equip_kruizkontrol»
[45] «equip_pamyat_nastroek»
[46] «equip_dopolnitelnyy_otopitel»
[47] «safety_sistema_kontrolya_mertvykh_zon»
[48] «equip_sidenya_ergoactive_dlya_voditelya_s_14pozitsionnoy_regulirovkoy»
[49] «equip_elektroprivod_zerkal»
[50] «equip_paket_tekhnika»
[51] «safety_datchiki_davleniya_v_shinakh»
[52] «safety_okhrannaya_signalizatsiya»
[53] «body_tsvet_kuzova_belyy»
[54] «equip_spetsialnaya_seriya_city»
[55] «main_komplektatsiya_city_14_tsi_150hp_6dsg_4motion»
[56] «equip_panoramnaya_krysha»
[57] «body_bamper_s_uvelichennym_uglom_vezda_24_gradusa»
[58] «body_paket_offroad»
[59] «body_nakladki_na_dvernye_porogi»
[60] «interior_nakladki_na_dvernye_porogi»
[61] «main_komplektatsiya_city_20_tsi_180hp_7dsg_4motion»
[62] «body_shiny_23550_r19_99v»
[63] «body_razmer_diskov_r19»
[64] «interior_dvernye_paneli_skozhanoy_otdelkoy»
[65] «equip_elektroprivod_sideniy»
[66] «main_komplektatsiya_city_14_tsi_150hp_6dsg»
[67] «equip_vybor_rezhimov_vozhdeniya»
[68] «interior_yashchik_dlya_khraneniya_pod_perednim_passazhirskim_kreslom»
[69] «interior_ergonomichnye_perednie_sidenya»
[70] «equip_voditelskoe_sidene_s_regulirovkoy_po_vysote_dline_uglu_naklona_spinki»
[71] «equip_massazhnye_sideniya»
[72] «body_tsvet_kuzova_bezhevyy_metallik»
[73] «body_tsvet_kuzova_krasnyy_metallik»
[74] «body_shiny_23555_r18_100v»
[75] «body_razmer_diskov_r18»
[76] «interior_nakladki_na_porogi_s_podsvetkoy»
[77] «interior_dekorativnye_vstavki_dark_grid»
[78] «interior_dve_lampy_dlya_chteniya_speredi»
[79] «equip_paket_osveshchenie»
[80] «equip_fonovaya_podsvetka_interera»
[81] «equip_svetodiodnye_zadnie_fonari_3d»
[82] «main_komplektatsiya_offroad_20_tsi_180hp_7dsg_4motion»
[83] «body_korpusa_naruzhnykh_zerkal_okrashennye_v_chernyy_tsvet»
[84] «body_polnorazmernoe_stalnoe_zapasnoe_koleso_65x17»
[85] «body_peredniy_bamper_s_uvelichennym_uglom_vezda_26_gradusov_zadniy_bamper_s_dekorativnymi_vstavkami_dekorativnye_nakladki_na_dveri»
[86] «body_spoyler_na_zadney_dveri»
[87] «interior_dekorativnye_vstavki_dlya_spetsialnoy_versii»
[88] «interior_peredniy_podlokotnik_s_dvumya_podstakannikami_i_shtorkoy»
[89] «interior_ploskiy_pol_bagazhnogo_otdeleniy»
[90] «interior_yashchiki_dlya_khraneniya_pod_perednimi_kreslami»
[91] «interior_skladnye_stoliki_v_spinkakh_perednikh_kresel»
[92] «interior_alyuminievye_nakladki_na_pedali»
[93] «interior_rezinovye_salonnye_kovriki_speredi_i_szadi_s_logotipom_offroad»
[94] «interior_nakladki_na_dvernye_porogi_offroad»
[95] «interior_stekla_atermalnye_tonirovannye»
[96] «equip_datchik_sveta»
[97] «equip_spetsialnaya_versiya_offroad»
[98] «equip_klavishi_mekhanicheskoy_razblokirovki_spinok_zadnikh_sideniy_v_bagazhnom_otseke»
[99] «equip_vnutrennee_zerkalo_zadnego_vida_s_avtozatemneniem»
[100] «equip_poyasnichnyy_podpor_dlya_perednikh_sideniy»
[101] «equip_polnostyu_skladnaya_spinka_perednego_passazhirskogo_kresla»
[102] «equip_avtokorrektor_far»
[103] «equip_funktsiya_coming_homeleaving_home»
[104] «equip_2_usb_razema_v_peredney_konsoli_1_usb_razem_v_tsentralnoy_konsoli_dlya_zaryadki»
[105] «equip_datchik_dozhdya»
[106] «equip_obogrev_lobovogo_stekla»
[107] «safety_hdc_sistema_pomoshchi_pri_spuske_so_sklona»
[108] «body_tsvet_kuzova_korichnevyy_metallik»
[109] «equip_navigatsionnaya_sistema»
[110] «equip_paket_navigatsiya»
[111] «equip_golosovoe_upravlenie»
[112] «equip_usb_interfeys_ipodiphonevklyuchaya_auxin»
[113] «equip_multimediynaya_sistema_audiovideo»
[114] «main_komplektatsiya_sportline_20_tsi_220hp_7dsg_4motion»
[115] «body_paket_vneshnikh_elementov_sportline»
[116] «body_shiny_airstop_25545_r_19»
[117] «body_bampery_v_sportivnom_stile_i_nakladki_na_porogi_v_tsvet_kuzova_rasshiriteli_kolesnykh_arok»
[118] «equip_individualnaya_sborka»
[119] «equip_rulevoe_upravlenie_s_peremennym_peredatochnym_otnosheniem»
[120] «equip_multifunktsionalnyy_rul»
[121] «interior_dvernye_paneli_s_kozhanoy_otdelkoy»
[122] «main_komplektatsiya_offroad_14_tsi_150hp_6dsg_4motion»
[123] «equip_zerkalo_zadnego_vida_s_avtozatemneniem»
[124] «equip_tsentralnyy_zamok»
[125] «main_komplektatsiya_sportline_20_tsi_180hp_7dsg_4motion»
[126] «safety_podushki_bezopasnosti_sht_11»
[127] «safety_paket_bezopasnost»
[128] «safety_proaktivnaya_sistema_zashchity_passazhirov_presafe»
[129] «interior_otdelka_dverey»
[130] «main_komplektatsiya_sportline_20_tdi_150hp_7dsg_4motion»
[131] «main_komplektatsiya_offroad_14_tsi_150hp_6mt_4motion»
[132] «main_komplektatsiya_offroad_20_tdi_150hp_7dsg_4motion»
[133] «interior_salonnye_kovriki_speredi_i_szadi»
[134] «interior_tsvet_obivki_sideniy_kombinirovannyy»
[135] «equip_paket_discover_pro»
[136] «interior_paket_khranenie»
[137] «interior_makiyazhnye_zerkala_s_podsvetkoy_v_solntsezashchitnykh_kozyrkakh»
[138] «interior_bagazhnaya_setka»
[139] «interior_potolochnaya_konsol_s_otsekami_dlya_khraneniya»
[140] «body_tsvet_kuzova_belyy_metallik»
[141] «body_pritsepnoe_ustroystvo»
[142] «equip_obogrev_zerkal»
[143] «interior_obivka_sideniy_velyur»
[144] «body_tsvet_kuzova_seryy»
[145] «body_standartnyy_bamper_s_khromirovannoy_otdelkoy»
[146] «interior_khromirovannaya_otdelka_elementov_interera»
[147] «equip_paket_style»
[148] «equip_paket_premium»
[149] «equip_generator_180a»

Для построения регресcионных моделей в первом релизе я использовал хорошо зарекомендовавший себя для б/у авто (II) алгоритм Random Forest.

# загружаем необходимые библиотеки
library(reshape2)
library(caret)
library(randomForest)

new_cars_data <- read.csv('new_cars_data_tiguan.txt') # загружаем выборку в R

new_cars_data_cor <- as.matrix(cor(new_cars_data)) # рассчитаем корреляции между регрессорами

new_cars_data_cor [lower.tri(CM, diag = TRUE)] <- NA # присвоим NA все нижние треугольные элементы матрицы

high_cor_vars <- subset(melt(new_cars_data_cor , na.rm = TRUE), value == 1.0) # найдем пары регрессоров с сильной корреляцией

# убираем по одному из каждой пары сильно коррелирующих регрессоров
if(length(high_cor_vars[,2])) {
dataset <- new_cars_data[(-c(high_cor_vars[,2]))]
} else {
dataset <- new_cars_data
}

set.seed(1) # инициализируем генератор случайных чисел (для воспроизводимости)

split <- runif(dim(dataset)[1]) > 0.2 # разделяем нашу выборку

train <- dataset[split,] # выборка для обучения и настройки (cross-validation) параметров

test <- dataset[!split,] # отложенная (hold-out) выборка

Для перекрестной проверки я использовал пакет caret, который имеет большое количество возможностей для оценки качества модели.

fit.control <- trainControl(method = "repeatedcv", number = 10, repeats = 10)

train.rf.model <- train(price~., data=train, method="rf", trControl=fit.control , metric = "RMSE") # применим 10-ти кратную 10-ти блочную кросс-валидацию для настройки модели

train.rf.model # посмотрим на результаты кросс-валидации

Подробнее

Random Forest

1858 samples
111 predictor

No pre-processing
Resampling: Cross-Validated (10 fold, repeated 10 times)
Summary of sample sizes: 1673, 1672, 1672, 1672, 1671, 1673,…
Resampling results across tuning parameters:

mtry RMSE Rsquared
2 132963.50 0.7264413
56 79757.67 0.8626671
111 80401.10 0.8605166

RMSE was used to select the optimal model using the smallest value.
The final value used for the model was mtry = 56.

Полученное значение коэффициента детерминации (Rsquared) означает, что зависимая переменная (цена) очень хорошо объясняется рассматриваемой моделью.

train.rf.model <- randomForest(price ~ ., train,mtry=56) # построим модель на основе полученных с помощью кросс-валидации параметров

varImpPlot(train.rf.model) # посмотрим на 30 самых важных регрессоров
Как программист новую машину подбирал - 2

rf.model.predictions <- predict(train.rf.model, test) # проверим точность оценки на отложенной выборке

print(sqrt(sum((as.vector(rf.model.predictions - test$price))^2)/length(rf.model.predictions))) # средняя ошибка прогноза цены (в рублях)
[1] 82512.59

Апробация алгоритма

Проверим на какую реальную выгоду можно рассчитывать благодаря разработанному алгоритму.

rf.model <- randomForest(price ~ ., dataset,mtry=56)
predicted.price <- predict(rf.model, dataset)
real.price <- dataset$price
profit <- predicted.price - real.price

Построим график зависимости выгоды от цены.

plot(real.price,profit)
abline(0,0)

Как программист новую машину подбирал - 3

Посчитаем выгоду в процентном соотношении.

sorted <- sort(predicted.price /real.price, decreasing = TRUE)
sorted[1:8]
195 193 6 207 202 203 906 206
1.184079 1.176262 1.132920 1.126626 1.123967 1.123967 1.116736 1.116344

Учитывая тот факт, что выгода рассчитывается по априорной информации от дилера, а при личной встрече вы сможете еще поторговаться, полученный максимальный профит в 18% — очень хороший результат.

Реализация web-сервиса

После того, как с технической частью разобрались, самое время приступить к поиску интересующего автомобиля.
Я, например, присматриваюсь к Volkswagen Tiguan в комплектации City 2.0 TSI 180hp 7DSG 4Motio.

Как программист новую машину подбирал - 4

Как программист новую машину подбирал - 5

Как программист новую машину подбирал - 6
Как программист новую машину подбирал - 7

Воспользовавшись сервисом, вы будете знать каких дилеров разумно обзвонить в первую очередь, уточнить наличие автомобиля, цену, условия и посетить для осмотра, и потенциальной покупки.

Напоследок

Таким образом, я реализовал помощника для подбора нового автомобиля у официального дилера по самой выгодной цене на рынке, учитывающего все установленные доп. опции.
Обращаю ваше внимание на тот факт, что низкая цена на авто может предоставляться дилером при определенных условиях (кредит, КАСКО, trade in и т.д.), что в общем случае вносит ошибку в оценку выгоды. На мой взгляд, ради хорошей скидки рационально воспользоваться некоторыми из подобных, навязываемых дилером услуг, будь то КАСКО у партнера или, например, кредит, который вы погасите при первой возможности. Это сугубо индивидуальный вопрос, но в любом случае, желательно, во избежании недопонимания, уточнить условия по телефону до визита в салон.
Время релиза сервиса выбрано не случайно, так как конец года лучшее время для приобретения нового автомобиля когда дилеры готовы предоставлять наиболее существенные скидки.
На данный момент сервис находится в режиме бета-тестирования и предоставляется абсолютно бесплатно.
По мере накопления статистических данных на сервисе будет появлятся новая аналитика и инфографика, которая будет интересна как конечным потребителям, так и официальным дилерам, но об этом я расскажу в следующей статье.

Ссылки

Выборка для Volkswagen Tiguan.

Автор: Никита

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js