Предсказываем стоимость логистики грузоперевозок по городам на данных маркетплейсов логистики
Перевозка грузов является одной из важных сфер бизнеса, особенно в странах, имеющих большое транзитное значение, таких как Казахстан. При этом тарифы на перевозку, хоть и играют решающую роль при оценке доходности логистического бизнеса, весьма непрозрачны и зависят от большого количества факторов. В этих условиях кажется логичным построение модели, позволяющей с хорошим приближением предсказывать стоимость перевозки груза в зависимости от его параметров, условий перевозки, а также начального и конечного пунктов. В данном посте будут описаны основные этапы построения такой модели.
Этапы построения модели
1. Выбор значимых параметров
Исходный датасет содержит примерно 24,5 тысячи строк со следующими параметрами:
Город отправления (0)
Город прибытия (1)
Описание груза (2)
Тип кузова, необходимый для перевозки этого груза (3)
Расстояние (в километрах) между городом отправления и городом прибытия (4)
Масса груза (5)
Единица измерения массы груза (6)
Объём груза (7)
Единица измерения объёма груза (8)
Итоговая стоимость перевозки груза в казахских тенге (9)
Комментарий к заказу (10)
Сайт, на котором была получена итоговая стоимость перевозки (11)
Пример исходного датасета:
В результате исследования датасета оказалось, что:
Описание груза (2) может принимать более 5 тысяч различных значений, поэтому этот параметр не является информативным;
Единица измерения массы груза (6) практически всегда — тонны (за исключением нескольких опечаток), поэтому также не влияет на предсказание;
Единица измерения объёма груза (8) — всегда метры кубические, поэтому этот столбец также лишний;
Комментарий к заказу (10) может принимать почти 4 тысячи различных значений, поэтому, наряду с описанием груза, не выглядит полезным для модели;
Таким образом, после «выкидывания» параметров 2, 6, 8, 10 и 11, фрагмент приобретает следующий вид:
После удаления ненужных данных таблица принимает следующий вид:
2. Фильтрация и обработка данных
Сначала сделаем фильтрацию.
Возможных пунктов отправления (0) и прибытия (1) — несколько сотен, однако топ-20 наиболее частых из них формируют более 90% пунктов отправления и более 80% пунктов прибытия. Таким образом, имеет смысл оставить названия лишь для топ-20 из них, а все остальные обозначить одним и тем же словом (например, «Другой»).
Возможных типов кузова (3) — пара десятков, но топ-5 из них формируют более 95% записей. Поэтому оставляем названия для топ-5, а остальные обозначаем как «Другой».
Максимальное расстояние, встречающееся в датасете — более 6 тысяч километров, что выглядит неправдоподобно, особенно если учесть, что следующее максимальное значение — меньше 3700 км. Поэтому мы просто ограничили расстояние значением 3700 км.
С объёмом и массой таких проблем не видно — данные выглядят правдоподобно.
Что касается цены, там явно есть опечатки в данных. В самом деле, медианное значение цены — 200 тысяч тенге, при этом цена выше 2 миллионов тенге встречается в 17 записях, что выглядит неадекватным. Поэтому цена была ограничена значением 2 миллиона тенге.
После фильтрации данные выглядят примерно так:
Однако, чтобы на данных можно было обучать модель, их нужно обработать — превратить категориальные параметры в числовые, а числовые (dist_new, volume_new, weight_new, price_new)
— нормализовать, чтобы единица измерения не влияла на значимость параметра в модели.
Для конвертации категориальных переменных в числовые проще всего использовать технику one hot encoding — каждому из возможных значений параметра ставится в соответствие число 1, если в данной записи значение параметра совпадает с данным, и 0 в противном случае. Так, например, для параметра city_from_new
будет создан 21 столбец — двадцать для топ-20 городов и один для всех оставшихся — и ровно одно из этих 21 значений будет равно 1, а остальные нули. Аналогично, для city_to_new будет создан также 21 числовой столбец, а для type_new — 6 столбцов.
Для нормализации же числовых переменных проще всего отмасштабировать их от 0 до 1: минимальное значение параметра по всем записям будет равно нулю, максимальное — единице, а остальные изменятся пропорционально.
В результате этих манипуляций данные примут следующий вид:
3. Подготовка данных к обучению
Теперь, когда все данные — числовые, осталось лишь выделить параметр, который мы хотим предсказать (а именно — price_new), а также разбить данные на обучающую и тестовую выборку. Разбиение рекомендуется делать псевдослучайным образом, но с фиксированным порождающим элементом (seed), чтобы при повторных запусках кода разбиение не менялось. При этом рекомендуется, чтобы обучающая выборка была больше тестовой по меньшей мере в несколько раз (для данной задачи была выбрана пропорция 4:1).
В итоге данные принимают вид, указанный на следующем скриншоте:
4. Выбор модели для обучения
Итак, наши данные полностью готовы к обучению, в обучающей выборке примерно 20 тысяч записей, каждая из которых содержит 51 параметр. Также есть основания предполагать, что зависимость цены от числовых параметров (расстояние, масса, объём груза) близка к линейной. Кроме того, легко интерпретируемую модель может применять на практике значительно бОльшее количество людей (таких как перевозчики и бизнесмены), чем трудно интерпретируемую. Поэтому было принято решение остановиться на модели множественной линейной регрессии — простой, но достаточно эффективной при данных условиях.
Сначала была опробована простейшая модель с параметрами по умолчанию. Однако она давала слишком большие коэффициенты при параметрах, иногда превосходившие по модулю триллион:
Это явно не способствовало её интерпретируемости, поэтому было принято решение модифицировать модель, «штрафуя» её за слишком большие коэффициенты, то есть применив регуляризацию. Параметр регуляризации alpha был принят равным 0,5 — именно при таком значении коэффициенты при всех параметрах модели стали примерно одного порядка:
Такую модель интерпретировать уже значительно проще, поэтому было решено оставить именно её.
5. Оценка результатов модели
Поскольку это модель регрессии, а не классификации, результатом оценки модели является не её точность, а коэффициент детерминации R — показатель того, насколько вектор предсказанных значений сонаправлен с вектором реальных значений.
Коэффициент R может принимать значения от -1 (абсолютная разнонаправленность — чем больше предсказанное значение, тем меньше реальное) до 1 (абсолютная сонаправленность). При этом R=0 соответствует случайному гаданию, то есть любая модель, для которой R>0, лучше случайной.
Для данной модели получили значение R от 0,459 на обучающей выборке до 0,476 на тестовой:
Заключение
Таким образом, рассмотренная модель достаточно хороша, однако есть пространство для её дальнейшего улучшения. Вот некоторые рекомендации, которые могут помочь это сделать:
Корректировка исходного датасета: если исправить опечатки в данных о расстоянии и особенно цене, модель будет работать лучше.
Фильтрация выбросов: можно исследовать исходный датасет и понять, какие данные выглядят неадекватно (например, 3 тысячи километров — это больше, чем расстояние между крайними западной и восточной точками Казахстана, так что подобные значения выглядят подозрительно).
Добавление описания груза в качестве параметра модели. Это уже более сложная задача, так как для этого нужно будет сделать хорошую категоризацию типов грузов и уметь определять по описанию, к какой категории какой груз относится.
Переход к мультипликативной модели регрессии, в которой будет предполагаться, что цена пропорциональна произведению расстояния и массы груза либо произведению расстояния и объёма груза.
Переход к более сложной модели (например, нейросети или случайному лесу).
Примечание: Данные и гипотезы ориентированы на рынок перевозок Казахстана.