Въведение

През годините 2020–2021 в Ynov Aix Campus решихме да се присъединим към Data Science Academy за нашите Ydays, в инициатива, която позволява на студентите веднъж на всеки две седмици да създават истински или фалшив стартъп и да работят с всеки панел от компетентности в училище, тъй като тези Ydays са със смесени степени и компетенции, така че 4-годишен студент по информатично инженерство може да работи с 1-годишен студент по графичен дизайн.

В този стартъп целта беше да участвате в състезанието Kaggle, да получите ранг сред професионалистите в науката за данни и да напишете статия в Medium за преглед.

Моят партньор и аз решихме да се присъединим към конкурса „Продажби на магазини на Rossmann“, трябваше да оценим и предвидим бъдещите продажби на този магазин.

Данни, предоставени от конкурса

Rossmann е компания, която управлява повече от 3000 аптеки в 7 европейски страни.

Магазините Rossmann трябва да се опитат да планират продажбите си предварително (6 седмици предварително). Затова ще се опитаме да предвидим продажбите, като разчитаме на файловете, с които разполагаме:

store.csv, който представя продажбите на 1115 магазина с течение на времето.

train.csv, който представя данни за обучение с различни продажби и свързани характеристики за магазините на Rossmann във времето.

test.csv, който е тестовият файл, където ще можем да правим нашите прогнози.

Всеки от файловете съдържа няколко променливи:

Магазин= Магазинът. (номинална качествена променлива, тип int)

Id= Идентификаторът, който е уникален, представен от магазин (магазина) и дата (датата). (номинална качествена променлива, тип int)

Продажби= Оборотът за даден ден (това се опитваме да предвидим). (непрекъсната количествена променлива, плаващ тип)

Клиенти= Брой клиенти за даден ден. (дискретна количествена променлива, тип int)

Open= индикатор, който позволява да се знае дали магазинът е бил отворен: 0 = затворен, 1 = отворен (номинална качествена променлива, тип int)

StateHoliday= указва официален празник. a = официален празник, b = празник Великден, c = Коледа, 0 = няма (фиктивна качествена променлива, тип низ)

SchoolHoliday= показва дали (магазинът, датата) е бил засегнат от затварянето на държавните училища 0 = затворено, 1 = отворено -› Проверете дали наистина е така. (номинална качествена променлива, тип низ)

StoreType= разграничава 4 различни модела магазини: a, b, c, d Няма информация за характеристики a, b, c и d. -› ?? (номинална или дискретна качествена променлива, тип низ)

Асортимент= описва ниво на асортимент (списък с продукти): a = основен, b = допълнителен, c = разширен (редна качествена променлива, тип низ)

CompetitionDistance= Изчисляване на разстоянието в метри до най-близкия конкурентен магазин (непрекъсната количествена променлива, плаващ тип)

CompetitionOpenSince [месец / година]= дава приблизителната година и месец на откриването на най-близкия конкурент (редна качествена променлива, тип дата)

CompetitionOpenSinceMonth= дава месеца на отваряне на най-близкия конкурент (редна качествена променлива, тип int)

CompetitionOpenSinceYear= дава годината на отваряне на най-близкия конкурент (редна качествена променлива, тип int)

Промо= показва дали даден магазин провежда промоция този ден 0 = Няма промоция, 1 = промоция този ден ?? Подлежи на проверка (номинална качествена променлива, тип int)

Promo2= Promo2 е непрекъсната и последователна промоция за определени магазини: 0 = магазинът не участва, 1 = магазинът участва (номинална качествена променлива, тип int)

Promo2Since [година / седмица]= описва годината и календарната седмица, в която магазинът е започнал да участва в Promo2 (порядъчна качествена променлива, тип дата)

PromoInterval= описва последователните интервали, в които е стартирана Promo2, като посочва месеците, когато промоцията е рестартирана.

Нашите хипотези

Започнахме, като направихме хипотези, които искахме да тестваме, за да имаме представа в анализа на нашите данни и създаването на нашия алгоритъм:

  1. Магазините продават повече, когато има промоции.
  2. Когато един конкурент се появи и стане най-близкият конкурент, продажбите са склонни да намаляват.
  3. Повече разпродажби има през уикендите и празниците (когато магазините работят).
  4. По време на училищните ваканции има по-малко продажби.
  5. Колкото по-обширен е списъкът (асортиментът) от продукти, толкова повече продажби има.

Нашата работа

I) Импорт на библиотеки и модули

II) Прочетете файловете

резултат:

влак : (1017209, 9) тест : (41088, 8) магазин : (1115, 10)

III) Почистване на данни

След като разгледаме формите, можем да видим, че нашите данни не споделят същия брой колони, по-късно ще видим причината и последствията от това по-късно.

Командата list(df) сортира имената на колоните в рамката с данни

резултат:

[„Магазин“, „Ден от седмицата“, „Дата“, „Продажби“, „Клиенти“, „Отворено“, „Промоция“, „Държавен празник“, „Училищен празник“]

[„Id“, „Store“, „DayOfWeek“, „Date“, „Open“, „Promo“, „StateHoliday“, „SchoolHoliday“

Виждаме, че колоната „Клиенти“ липсва в теста

- Анализ на липсваща стойност

Можем да видим, че само 4 колони нямат липсваща стойност в рамката с данни на магазина, но че няма липсваща стойност в рамката с данни на влака.

Анализ на корелациите

IV) Разрешаване на хипотези

1) Магазините продават повече, когато има промоции

Отбелязваме, че върховете на продажбите не се случват по време на промоционалния период, така че предполагаме, че промоциите не влияят на общия брой продажби.

Нова хипотеза: промоциите могат да увеличат продажбите на един конкретен продукт за сметка на друг.

2) Когато конкурент се появи и стане най-близкият конкурент, продажбите са склонни да намаляват.

Благодарение на графиката по-горе и резултата от корелацията между двете променливи, можем да видим, че няма линейна връзка в разстоянието между най-близката едновременна и броя на продажбите.

- Тествайте с друга променлива

3) През уикендите и празниците има повече разпродажби

Виждаме, че понеделник е денят, в който се правят повече продажби.

Нова хипотеза: Повечето магазини са затворени в неделя

Тествайте без затворени магазини

Можем да видим, че ако изчислим само с отворени магазини, пиковите продажби се случват в неделя и понеделник.

4) По време на училищните ваканции има по-малко продажби.

0 = Училищата са затворени 1 = Училищата са отворени

Забелязваме, че средно:

Имаше средно 5621 продажби, когато училищата бяха затворени, и 6476 продажби, когато бяха отворени.

Така че ние отстояваме хипотеза 4: „Има по-малко продажби по време на училищните ваканции.“.

5) Колкото по-обширен е списъкът (асортиментът) от продукти, толкова повече продажби има.

Забелязваме, че кривата не нараства през цялото време, което прави хипотезата невалидна.

Изграждане на алгоритъма

За първи път искаме да получим датата и да я форматираме. Вече опитахме решение във фазата на почистване, но чрез промяна на синтаксиса и то не беше наистина ефективно за това, което следва.

Променливата „StateHoliday“ има 4 различни стойности (0, a, b, c). Тези стойности са празници, свободни дни, ваканции... и 0 означава нормален ден.

Искаме да прекодираме тези стойности, както следва:

  • 0 = нормален ден
  • 1 = всякакъв вид почивен ден

Заменете NULL стойностите със средна стойност

Има липсващи стойности в променливата „CompetitionDistance“, затова ще ги заменим със средната стойност.

Целта на тази замяна е да не изтривате никакви данни, като същевременно се опитвате да нямате необичайна стойност.

Можем също да се опитаме да заменим нулевите стойности със средната, но поради набора от данни средната стойност може да бъде повлияна от разнородност на стойностите.

пример:

  • 100 души имат socre 10
  • 2 народа имат socre 70
  • 4 души имат socre 149
  • 14 души имат резултат 500

Средната стойност тук е ~72, което се влияе от хората с наистина добър резултат.

Медианата тук е 10, което е по-представително.

Затова избрахме да заменим нулевите стойности със средната стойност на набора от данни:

Премахването на двете колони вече не е необходимо

За набора от данни „тест“ имаме само стойностите за август и септември 2015 г.

И накрая, колоните „Година“ и „Месец“, които създадохме, няма да бъдат полезни.

Премахване на линии, където магазинът е затворен

Когато магазините са затворени, ние сме сигурни в резултата от продажбите въпреки други характеристики: магазинът е затворен = 0 продажби. Ние променяме набора от данни, като запазваме само стойностите, когато магазините са отворени.

Премахване на безполезни колони

Изтриваме колони, които са безполезни за прогнозата („Отворено“, „Клиенти“, „Дата“)

  • Отворено: Запазени са само линиите, където торите са отворени
  • Клиенти: Не можем да знаем предварително колко клиенти ще дойдат във всеки магазин в бъдеще
  • Дата: Не запазихме променливата за дата.

Запазване на ID на затворени магазини

Тук запазваме идентификатора на затворените магазини, които сме премахнали от рамката с данни.

Ние се стремим да ги върнем по-късно, за да ги повлияем на брой продажби от 0.

Премахване на редове, където магазините са затворени и безполезна колона (тестови набор от данни)

Цикъл на всеки магазин

Оптимизация: Изграждане на алгоритъма (XGBOOST)

Алгоритъмът XGBoost е наборен алгоритъм, който агрегира дървета (дървета на решения). При всяка итерация новото дърво се учи от грешката, направена от предишното дърво. По този начин, въпреки че всяко дърво има ниска предсказваща сила, правилото за вземане на решение, конструирано чрез сумиране на резултата от всяко дърво, е много надеждно.

В контекста на нашия проблем този тип алгоритъм има предимството да може да използва цялата налична информация за продажбите в магазина.

Импорт на библиотеки

Функция за повторно кодиране на функции.

Тук търсим да изчистим нашите набори от данни с функция, която наричаме build_features. Тази функция ни позволява да премахнем ненужните редове, включително тези, съдържащи информация, когато магазините са затворени.

Когато магазините са затворени, ние вече знаем, че няма разпродажби.

Освен това имаме много ординални категорични променливи. Следователно можем да кодираме стойностите по такъв начин, че да присвоим число според неговата стойност.

  • Забелязахме, че StateHolliday всъщност не оказа влияние или дори отрицателно въздействие върху крайния ни резултат...

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

Предполагаме, че когато колоната „Отворено” не е посочена, тогава магазинът е отворен.

За данни за обучение ще се пазят само линии, където магазините не са затворени.

Сливане на наборите от данни

Има информация за магазините, но тази информация не се намира в данните за теста и обучението. За да възстановим тази информация, ние обединяваме данните от магазина с данните за влака и след това правим същото с данните от теста. Правим присъединяването на полето Store

Модификация на параметрите.

Променихме някои параметри, за да се опитаме да имаме по-добра оптимизация.

Избор на брой дървета.

Можем да изберем броя на повторенията. Въпреки че може да мислим, че колкото по-голямо е числото, толкова по-надежден е резултатът, това не е непременно вярно. Трябва да намерим баланс между твърде малко и твърде много повторения.

Направихме някои тестове. 350 ни се струва добър компромис, но вероятно трябва да има техника за намиране на скала от числа, без непременно да се правят много тестове.

Изпълнение на прогнозата чрез алгоритъма

Благодарение на цялата тази работа успяхме да получим резултат, съответстващ на първите 4% от състезанието.

Благодаря за четенето, можете да намерите бележника на проекта тук: https://www.kaggle.com/mondertime/notebook57ce82252e

- алгоритмично ваш,

Антония и Баптист