Будущее e-commerce: стратегии и инструменты, которые понадобятся завтра
--
:
--
:
--
:
--
Зарегистрироваться
Войти

Качественные рекомендации в e-commerce — компоненты алгоритма «Сопутствующие товары»

Frame 2087326490

Введение

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

Качественные рекомендации в e-commerce — компоненты алгоритма «Сопутствующие товары»

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

Сопутствующие товары — это товары, которыми покупатель может дополнить свой заказ. Мы в Retail Rocket Group широко используем данный алгоритм на множестве интернет-магазинов в различных сегментах. Как правило, он используется на страницах корзины и карточки товара. 

Качественные рекомендации в e-commerce — компоненты алгоритма «Сопутствующие товары»

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

Напомним, какие свойства необходимо обеспечить для качественных рекомендаций:

Свойство Описание
Эффективность Рекомендации способствуют решению задач покупателя, а именно помогают дополнить заказ
Логичность Покупатель должен видеть, что рекомендации соответствует задаче дополнения заказа
Покрытие Рекомендации должны быть для всех товаров,  в  том числе для новых и непопулярных
Специфичность Рекомендации для каждого товара основаны на информации, связанной с этим товаром, что делает их более подходящими именно для этого товара
Охват Рекомендации предлагают разнообразные товары, которые характеризуют наибольшую часть ассортимента интернет-магазина
Актуальность Рекомендации учитывают изменение товарной базы и поведения покупателей со временем
Мультирегиональность Рекомендации учитывают доступность товаров и актуальность их атрибутов в зависимости от региона

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

Компоненты алгоритма сопутствующих товаров

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

Для каждого компонента расскажем:   

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

Персонализация в реальном времени

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

Качественные рекомендации в e-commerce — компоненты алгоритма «Сопутствующие товары»

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

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

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

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

Компонент обеспечивает следующие свойства:

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

Уменьшение влияния популярных товаров

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

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

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

Качественные рекомендации в e-commerce — компоненты алгоритма «Сопутствующие товары»

Компонент обеспечивает следующие свойства:

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

Решение «Банановой проблемы»

Наиболее сильно проблема влияния популярных товаров заметна на продуктовых магазинах. В связи с этим появился отдельный термин — «Банановая проблема». Бананы покупают очень часто и с любым другим товаром, поэтому они присутствуют в рекомендациях практически ко всему.

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

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

Компонент обеспечивает следующие свойства:

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

Решение проблемы холодного старта

Если по товару достаточно поведенческой статистики, то понятно как получить сопутствующие к нему товары — достаточно использовать данные по товарам в совместных заказах. Но в магазине постоянно появляются новые товары, для которых данных либо нет, либо мало. Кроме того, у многих интернет-магазинов огромная товарная база, и для заметной части товаров данных будет не так много. 

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

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

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

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

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

Компонент обеспечивает следующие свойства:

  • • покрытие — без достаточной статистики для значительной части товаров не сформируются рекомендации.

Приоритизация бренда текущего товара в холодном старте

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

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

Решаемую данным вариантом алгоритма проблему можно обнаружить в рекомендациях к брендам, которые выпускают и основной товар, и сопутствующие товары к нему. К примеру, посмотреть будут ли аксессуары apple в рекомендациях к новому macbook.

Качественные рекомендации в e-commerce — компоненты алгоритма «Сопутствующие товары»

Компонент обеспечивает следующие свойства:

  • • эффективность — товары одного бренда чаще сочетаются между собой;
  • • специфичность — учитывается бренд текущего товара.

Холодный старт из товаров текущего бренда

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

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

Компонент обеспечивает следующие свойства:

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

Фильтрация случайных товаров из нелогичных категорий

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

Для того чтобы избежать попадания в рекомендации случайных товаров, наша система автоматически определяет, какие категории подходят товару в качестве сопутствующих. И чем меньше категория подходит в качестве сопутствующей, тем больше совместных событий необходимо товару из этой категории для попадания в рекомендации. Это похоже на то, как в обычной жизни человеку потребуется больше доказательств, чтобы согласиться с тем, в чём он изначально был не уверен.
В качестве проверки можно посмотреть разные карточки товаров и убедиться, что среди рекомендаций нет нелогичных товаров. При этом большинство товаров могут быть логичными, но будут встречаться отдельные товары, которые не дополняют текущий товар.

Качественные рекомендации в e-commerce — компоненты алгоритма «Сопутствующие товары»

Компонент обеспечивает следующие свойства:

  • • логичность — уменьшается вероятность показа неподходящих товаров;
  • • эффективность — в рекомендациях отображаются больше полезных товаров.

Увеличение разнообразия товаров в рекомендациях

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

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

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

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

Качественные рекомендации в e-commerce — компоненты алгоритма «Сопутствующие товары»

Компонент обеспечивает следующие свойства:

  • • эффективность — повышается вероятность встретить нужный товар среди рекомендуемых;
  • • охват — показываем больше разных товаров.

Ручная настройка рекомендаций

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

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

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

Также есть множество случаев, когда необходимо показать определенную группу товаров при некоторых условиях, например, с целью их продвижения. Это не является задачей алгоритма рекомендаций, и мы вынесли это в отдельный продукт — Smart Placement Ads.  

Компонент обеспечивает следующие свойства:

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

Исключение категорий товара, к которому формируются рекомендации

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

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

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

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

Компонент обеспечивает следующие свойства:

  • • логичность — исключаются товары, которые не связаны с задачей алгоритма;
  • • эффективность — остаются товары, которые помогают решать задачу покупателя.

Расчет рекомендаций для каждого товара группы

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

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

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

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

Компонент обеспечивает следующие свойства:

  • • эффективность — показывается наиболее подходящий товар из группы;
  • • специфичность — учитывается контекст конкретного товара группы.

Расчет рекомендаций для каждого региона

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

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

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

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

Качественные рекомендации в e-commerce — компоненты алгоритма «Сопутствующие товары»

Компонент обеспечивает следующие свойства:

  • • эффективность — показывается наиболее подходящие для региона товары;
  • • покрытие — для каждого товара в каждом регионе показываются рекомендации;
  • • охват — в рекомендациях показывается достаточное количество разнообразных товаров;
  • • мультирегиональность — учитывается актуальное состояние товаров в зависимости от региона.

Использование данных за все доступное время

Большинство товаров в магазине, как правило, заказываются относительно редко. Это явление известно как «длинный хвост». Если у товаров слишком мало заказов, то это начинает негативно влиять на качество рекомендаций. А значит важно для товаров низкого спроса собрать как можно больше данных. 

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

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

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

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

Компонент обеспечивает следующие свойства:

  • • эффективность — используется больше данных о поведении покупателей;
  • • покрытие — для большего количества товаров есть данные.

Актуализация рекомендаций

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

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

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

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

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

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

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

Качественные рекомендации в e-commerce — компоненты алгоритма «Сопутствующие товары»

Компонент обеспечивает следующие свойства:

  • • актуальность — своевременно изменяются рекомендации; 
  • • эффективность — используются актуальные данные;
  • • покрытие — показываются рекомендации для новых товаров.

Фильтрация экстремальной статистики

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

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

Кроме того данные аномальных пользователей могут усложнить расчет алгоритма, поскольку нужно рассматривать все пары товаров в заказе. Количество пар намного больше, чем количество самих товаров. Так, например, в заказе из 100 различных товаров алгоритму нужно рассмотреть 100*99/2 = 4950 пар.

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

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

Компонент обеспечивает следующие свойства:

  • • логичность — фильтруется статистика, которая искажает рекомендации. 

Заключение

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

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

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

Понравилась статья? Подпишитесь на рассылку, чтобы получать свежие статьи на почту.

Подписаться на рассылку

Еще статьи по теме