Сходство на основе характеристик для прогнозирования новых продуктов

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

«Сколько я собираюсь его продать?» - это вопрос, который имеет в виду каждый розничный торговец, когда думает о добавлении нового материала в свои магазины и электронную коммерцию.

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

Итак ... как мы можем это спрогнозировать?

Подход

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

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

После определения функций, что является наиболее сложным и важным этапом процесса, вы будете следовать простым пошаговым инструкциям для достижения своей цели:

1. Примените быстрое кодирование к категориальным данным.

Применяя одно горячее кодирование, мы переходим от сравнения расстояний между названиями / текстами категорий к сравнению, находится ли продукт в той же категории, что и старый.

2. Примените метод масштабирования к числовым данным.

Когда мы говорим о расстояниях, это всегда что-то вроде A-B = C, но теперь мы обсуждаем расстояние нескольких характеристик, и результат звучит как сумма всех C, созданных всеми As, минус все B.

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

Допустим, у нас есть 3 столбца, один из которых имеет диапазон значений от 200 до 400, другой - от 15 до 78 тысяч, а третий - от 1 до 10.

Это создаст проблему из-за того, что разница между диапазонами приведет к разным масштабам расстояния, в данном случае 100, 10000 и 10 секунд соответственно, и если мы попытаемся применить метрику расстояния без масштабатора Применительно ко второму столбцу степень важности выше, чем у других столбцов.

Так что не забывайте применять его.

3. Рассчитайте расстояние между новым и старым товаром.

Я думаю, что это та часть, которую вы ожидали больше всего, верно?

Что ж, если это так, я надеюсь, что не разочарую вас, потому что решение действительно простое.

Опять же, первое, что вам нужно сделать здесь, это определить, какую метрику расстояния вы хотите использовать. См. Список простых и полезных расстояний ниже:

  • Евклидов
  • Манхэттен
  • Минковский

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

В этом проекте я использовал евклидово расстояние, поэтому мы закончим все это всего двумя строчками кода:

idx_closest = np.argmin(
    [np.linalg.norm(new_obs_arr - np.array(x)) for x in df_old.values])
df_aux = df_old.iloc[idx_closest]\
    .to_frame()\
    .transpose()\
    .reset_index()

idx_closest - это значение индекса справочного материала старого фрейма данных, и с его помощью мы получаем всю соответствующую строку и сохраняем ее в df_aux.

4. Обратное однократное кодирование

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

Чтобы отменить это, мы должны:

  • Определите столбцы, созданные одним процессом горячего кодирования.
  • Выбирайте только те столбцы, в которых есть «1».
  • Преобразуйте его название в оригинальное.
  • Удалите столбцы, созданные одним горячим кодированием в начале процесса.
def reverse_one_hot_encoder(df, col_nm):
    """
    Reverse the one hot encoding process
    
    Parameters
    ----------
    df : pandas.DataFrame
        data frame object with the old products that are more similar the new products
    col_nm : str
        name of the original column
        
    Returns
    -------
        df_result : pandas.DataFrame
        data frame object with the old products that are more similar the new products without the OHE procress
    """
    lst_stack = [x for x in df.columns if x.find(col_nm)>=0]
    df_aux = df[lst_stack]
    df[col_nm] = df_aux[df_aux==1]\
        .stack()\
        .reset_index()\
        .drop(0,1)['level_1']\
        .apply(lambda x: int(x.replace(col_nm+'_','')))\
        .to_list()
    for col in lst_stack:
        df = df.drop(col, axis=1)
    return df

5. Рассчитайте коэффициент масштабирования.

И теперь мы достигли шага коэффициента масштабирования, также известного как «усыпление» из-за количества часов сна, которые я потерял, думая об этом.

Ладно… Ладно… Я не честно отношусь к этому парню, но я действительно потерял некоторое время, думая об этом, чтобы в конце концов сделать что-то, что кажется слишком легким для выполнения, так что это может быть просто мой внутренний гнев, пытающийся освободи себя немножко здесь.

Вот почему я потратил на это столько времени ...

Итак, вспомнив A-B = C из шага Distance, мы могли догадаться, что «Хорошо, теперь у меня определены новая строка и старая строка. Так почему бы мне, чтобы определить коэффициент масштабирования, просто не разделить одно на другое и получить результат в процентах? "

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

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

Мы думали, что штрафовать больше на больших расстояниях, чем на низких, должно быть хорошо, поэтому мы попробовали «e ^ (- distance²)», и если вы внимательный человек, то заметили, что я сказал «попробовал», а это значит, что не сработало.

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

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

# import Libs
import matplotlib.pyplot as plt
import statistics
import numpy as np
# simulate distance increasing
x = np.array(np.arange(0, 100, 0.001))
# get average value from distances
avg = statistics.mean(x)
# plot lines
plt.plot(x, np.exp(-(x**2)), 'b-')
plt.plot(x, np.exp(-(x**2/avg**2)), 'r-')
plt.legend(labels=['Original', 'Smothed'])
# add labels
plt.xlabel("Distance")
plt.ylabel("Saling Factor")
plt.show()

Еще один важный момент - посмотреть на цену продукта, потому что, если цена нового продукта ниже эталонной, это означает, что у него есть шанс продать больше, но если она больше, то есть шанс продать меньше.

Чтобы суммировать этот шанс продажи более или менее с коэффициентом масштабирования, мы решили подсчитать, насколько цена старого продукта соответствует цене нового.

Когда у нас есть коэффициент масштабирования, основанный на математической функции и соотношении цен, мы умножаем один на другой, чтобы получить окончательный коэффициент масштабирования.

Результат

Алгоритм экспортирует CSV-файл с пятью столбцами:

  • место расположения
  • продукт
  • reference_location_code
  • код ссылки
  • коэффициент масштабирования

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

Заключительные советы

  • Запланируйте встречу, чтобы поговорить с вашей командой по основным данным или с кем-то еще, кто регистрирует / создает новые продукты в вашей базе данных, потому что они могут легко сказать вам, каковы исходные характеристики новых материалов.
  • С умом выбирайте материалы, которые могут служить отсылкой к новому продукту. Те, с которыми вы перестали работать, но все еще существуют в вашей базе данных, или продукты, которые также являются новыми (менее двух или трех месяцев с момента первой продажи), могут быть не лучшим решением, потому что у них, вероятно, нет хорошего исторического кривая продаж.
  • Выберите иерархию продуктов для фильтрации. Таким образом, вы сократите время сотрудничества после того, как уменьшите выборку для сравнения и, вероятно, будете сравнивать более похожие продукты вместо поиска по всей базе продуктов.
  • Не забывайте, что как только ваш новый продукт начнет продаваться, он будет получать реальные данные о продажах, и вы должны начать использовать их для прогнозирования вместо тех, которые вы создали.

И вот оно!

Что ж, с этим, я думаю, теперь вы можете немного улучшить свои новые продукты, найдя аналогичный старый материал и масштабируя его продажи, чтобы использовать его в качестве входных данных для вашего инструмента прогноза!

Надеюсь, эта статья вам помогла!

И вы можете увидеть код этого проекта здесь:



Особая благодарность Пьеру Палю, который терпел меня, пока я ответил на миллион вопросов о том, как лучше всего определить коэффициент масштабирования