Müşteri anketlerine göre Grove.co'nun sunduğu ürün önerilerinin çok monoton olduğunu öğrendik. Herkesin en çok iyileştirmek istediği şey, ürün keşfi işlevidir. Analiz verileri, müşterilerin sistem önerdikten sonra satın alınabilecek diğer ürünleri bulmak için sayfaya tıklayacağını göstermektedir. Hiç şüphe yok ki ürün kategorilerinin sunumunda aksaklıklar var.
Ürün sunumunda kusurlar varİlgilendiğiniz ürünlerin bir listesini sunmanın yaygın yollarından biri, sonuçları rastgele olarak üretmektir. Ancak rastgelelikle ilgili iki sorun vardır: Birincisi, kataloğun altına batırılmış ürünleri ortaya çıkarmak için önemli miktarda rastgelelik gerekir. İkincisi, öneri listesinin tasarımını yok edecek ve tüketici güvenini azaltacaktır.
Burada "tasarım" ne anlama geliyor? Yahoo'daki ünlü bir vakaya bakalım.
Britney Spears etkisiYaklaşan NFL oyunlarıyla ilgili içeriğe göz attığınızı varsayalım. Makalenin altında, algoritma tarafından size önerilen bir dizi ek makale yer alacaktır. 21. yüzyılın başlarında neredeyse herkesin Britney Spears hakkında makaleler okuyacağı inkar edilemez.
Yani, Super Bowl ön izlemesinin altında bir "Beğendiğinizi Tahmin Edin" olacak ve bu sütunda Britney ve Kevin Federline hakkında bir makale görünecek. Okuyucular algoritma tarafından aşağılanmış hissedecekler. Yahoo gerçekten Britney Spears hakkında bir makale okumak istediğimi mi düşünüyor? ?
Bu makaleyi okuyan diğerleri de inceledi ...Ama onun yerine "bu makaleyi okuyan herkes de okudu" diyorsa, şimdi ... peki, peki, üzerine tıklayın. Bu tasarım okuyucuları tıklamaya ikna edebilir. Bunlar çok önemli!
Tıpkı iyi bir yakalayıcı, hakemin önüne çember topu atabilmesi gibi, web sayfasında ürün önerileri sunmak müşterilerin gönül rahatlığı ile satın almalarını veya tıklamalarını sağlayabilir.
"Senin için tavsiye edildi" -uh, yani bu site beni tanıdığını düşünüyor, değil mi? Böyle yazarsan:
"Size benzer aile sık sık satın alır"
Artık bağlamı bildiğime göre, bunun bir ürünü tanıtan bir perakendeci olmadığını, benim gibi diğer müşterilerin yararlı bulduğu ve yaygın olarak kabul gören bir ürün olduğunu biliyorum.
Makul olasılık arıyorYatırımcılardan biri olan Bullpen Capital'den Paul Martino ile derinlemesine bir tartışmadan sonra, sıcak ürün algoritması adı verilen bir fikir bulduk. Her gün alışveriş sepetine eklenen içeriği kaydedecek ve popülaritesi artan ürünleri arayacağız. Evet, bazen bu yalnızca satış departmanının faaliyetlerini yansıtabilir (örneğin, ürünleri e-postalarda tanıtmak ürünlerin popülaritesini artırabilir), ancak uygun bir standartlaştırma ile en son sıcak noktaları, popüler aramaları ve diğer kazayla oluşan nedenleri de filtreleyebilmelidir. Ürünün popülaritesinin nedeni. Bu aynı zamanda popüler olmayan bazı ürünlerin anında popülerlik kazanmasını ve onları ürün yığınının arasından sıyrılmasını kolaylaştırır.
Sıcak bir ürün motoru yazınÖncelikle, veri tabanından alışveriş sepetine eklenen verileri almanız gerekir.Bu adım nispeten basittir. Her bir ürünün alışveriş sepetine eklendiği zamanı izlemek için SQL'i kullanın. Burada, ısı verilerini gözlemlemek için son 20 günün alışveriş sepeti verilerini çıkaracağız (ancak ısıyı elde etmek için yalnızca birkaç günlük veri gerekir):
SELECT v.product_id, - (CURRENT_DATE-si.created_at :: date) "yaş", COUNT (si.id)
FROM product_variant v
INNER JOIN sched_shipmentitem si ON si.variant_id = v.id
NEREDE si.created_at > = (şimdi () - INTERVAL '20 GÜN ')
VE si.created_at < GEÇERLİ TARİH
GRUPLA 1, 2
Yukarıdaki kodu biraz basitleştirdik (resmi sürümde, aktif ürünler, satın alma müşterileri, alışveriş sepetine ayrıntı ekleme vb. Gibi nüansları da içerir), ancak çıktı sonucu çok basit:
kimlik yaş sayısı
14-2022
14-19158
14-1894
14-1752
14 -1656
14-1556
14 -1452
14-13100
14 -12109
14 -11151
14-10124
14-9123
14-858
14-764
14 -6114
14-593
14-4112
14-387
14-281
14-119
15-2016
...
15-130
16-20403
...
16-1842
Her satır, belirli bir ürünün son 20 günde belirli bir günde alışveriş sepetine kaç kez eklendiğini temsil eder. Burada, "yaş" ı -20 (20 gün önce) ile -1 (dün) arasında ayarlayın ve veriler, geçmişten bugüne, soldan sağa sezgisel olarak düzenlenecektir.
Veritabanından ( çıkarılan 100 örnek veriyi burada bulabilirsiniz. Ürün kimliği ve alışveriş sepeti eklemeleri anonimdir, bu nedenle standartlaştırıldığında veri sonuçları tamamen doğrudur, ancak tek bir veri noktası gerçek iş durumumuzu temsil etmez.
temel yöntemKoda dokunmadan önce, veri görselleştirme ile temel yöntemleri özetleyelim. Tüm ara adımlar ve görselleştirmeler daha sonra açıklanacaktır.
Burada, örnek veri kümesindeki ürün 542'nin alışveriş sepetine eklenmesi gösterilmektedir:
İlk adım, günlük dalgalanmaları azaltmak için düşük geçişli bir filtre (yumuşak işlev) eklemektir.
Ardından Y ekseni, popüler ürünler ile genel ürünler arasındaki farkı göstermek için standartlaştırıldı. Y eksenindeki değerdeki değişime dikkat edin.
Son olarak, düzgün trendin her bir çizgi parçasının eğimini hesaplayın.
Algoritma bu adımları her ürün için gerçekleştirecek (tabii ki görselleştirme yerine bellekte) ve ardından t = -1'deki kırmızı çizginin maksimum değeri gibi önceki günün en yüksek eğimine sahip ürüne dönecektir.
KodHadi başlayalım! Bu makaledeki tüm kodlar Python 2 Jupyter Notebook veya Yhatın Python entegre geliştirme ortamı Rodeo üzerinden çalıştırılabilir.
İlk grafiği (basit ısı görselleştirme) oluşturacak kod aşağıdaki gibidir. Grafik oluştururken olduğu gibi, bu kodu nihai algoritmayı oluşturmak için kullanacağız.
matplotlib.pyplot dosyasını plt olarak içe aktar
pandaları pd olarak içe aktar
numpy'yi np olarak içe aktar
# Verileri bir Pandas veri çerçevesinde okuyun
df = pd.read_csv ('sample-cart-add-data.csv')
# Kimlik ve Yaşa göre Gruplama
cart_adds = pd.pivot_table (df, değerler = 'sayım', dizin =)
ID = 542
trend = np.array (cart_adds)
x = np.arange (-len (eğilim), 0)
plt.plot (x, trend, label = "Alışveriş Sepeti Eklemeleri")
plt.legend (bbox_to_anchor = (1.05, 1), loc = 2, borderaxespad = 0.)
plt.title (str (ID))
plt.show ()
Bundan daha basit bir şey yok. Daha sonra veri seçimini kolaylaştırmak için ürün kimliği ve "yaş" dizini oluşturmak için pandalar pivot tablo (pivot_table) işlevini kullanıyoruz.
YumuşatmaŞimdi düzgün bir fonksiyon yazın ve bunu grafiğe ekleyin:
def smooth (seri, pencere boyutu, pencere):
# Her iki tarafta da x'in 'dışında' veri noktaları oluşturun
# yumuşatma penceresi her yerde çalışabilir
ext = np.r_
ağırlıklar = pencere (pencere_boyutu)
ağırlıklar = np.zeros (pencere_boyutu / 2)
yumuşatılmış = np.convolve (ağırlıklar / ağırlıklar.sum (), ext, mod = 'aynı')
düzeltilmiş döndürün # fazla veriyi kesin
pürüzsüz = pürüzsüz (
akım,
7,
np.hamming)
plt.plot (x, düzleştirilmiş, etiket = "Düzleştirilmiş")
Bu işlevin açıklanması gerekir: İlk olarak, esas olarak SciPy Yemek Kitabından türetilmiştir, ancak değişiklikten sonra daha az garip hale gelir.
Burada yumuşatma işlevi, Hamming penceresi tarafından tanımlanan ağırlık "penceresini" kullanır ve pencere ağırlığına göre bitişik veri noktalarını ağırlıklandırarak orijinal veriler üzerinde hareket eder.
Numpy bir dizi pencere (Hamming, Hanning, Blackman, vb.) Sağlar, bunları komut satırında bulabilirsiniz:
> > > baskı np.hamming (7)
Bu pencere yeni bir düzgün veri seti oluşturarak veri seti (evrişim) üzerinde hareket edecektir. Bu çok basit bir alçak geçiren filtredir.
5-7 satırları, orijinal serideki ilk ve son veri noktalarını çevirir ve yansıtır, böylece veri noktalarının kenarlarında bile pencere hala "sığar" olur. Bu biraz tuhaf görünebilir, çünkü her günün sonunda sadece popüler ürünü belirleyen son veri noktasını önemsiyoruz. Yalnızca geçmiş verileri işleyen pürüzsüz bir işlev kullanmanın en iyisi olduğunu düşüneceksiniz, ancak fark yalnızca ön ucu izlerken arkadaki verileri yansıtacağı için, sonuç üzerinde hiçbir etkisi yoktur.
standardizasyonGünde 10 kez alışveriş sepetine eklenen ürünleri, günde yüzlerce veya binlerce kez eklenen ürünlerle karşılaştırmamız gerekiyor. Verileri standartlaştırmak için çeyrekler arası farkı (IQR) kullanmak bu sorunu çözebilir:
def standardize (seri):
iqr = np. yüzdelik (seri, 75) -np. yüzdelik (seri, 25)
return (series-np.median (series)) / iqr
smoothed_std = standardize (yumuşatılmış)
plt.plot (x, smoothed_std)
Aynı zamanda, medyan sonuçtan çıkarılır, böylece seri 1 yerine 0'da ortalanır. Bunun standartlaştırma olduğunu, normalleştirme olmadığını unutmayın. İkisi arasındaki fark, normalizasyonun serinin değerini kesin olarak bilinen bir aralıkla (genellikle 0 ve 1) sınırlaması, standardizasyon ise tüm verileri aynı ölçeğe koymasıdır.
Verileri standartlaştırmanın birçok yolu vardır ve bunlardan biri çok basittir ve uygulaması kolaydır.
EğimO kadar kolay! Düzgün bir standart serideki her noktanın eğimini hesaplamak çok basittir.Sadece seriyi bir birim kaydırmanız ve ardından orijinal seriden çıkarmanız gerekir. Bazı örnek verilerin grafik temsili aşağıdaki gibidir:
kod aşağıdaki gibi gösterilir:
eğimler = smoothed_std-smoothed_std)
plt.plot (x, eğimler)
Ding! Bu kadar basit!
Her şeyi entegre edinŞimdi, en son dönemde en yüksek eğim değerine sahip ürünü bulmak için her ürün için yukarıdaki adımları tekrarlamanız yeterlidir.
Nihai kod aşağıdaki gibidir:
pandaları npimport operatörü olarak pdimport numpy olarak içe aktar
SMOOTHING_WINDOW_FUNCTION = np.hamming
SMOOTHING_WINDOW_SIZE = 7
def train ():
df = pd.read_csv ('sample-cart-add-data.csv')
df.sort_values (=, inplace = True)
trendler = pd.pivot_table (df, değerler = 'sayım', dizin =)
trend_snap = {}
i in np.unique (df) için:
trend = np.array (trendler )
yumuşatılmış = pürüzsüz (eğilim, SMOOTHING_WINDOW_SIZE, SMOOTHING_WINDOW_FUNCTION)
nsmoothed = standardize (yumuşatılmış)
eğimler = nsmoothed-nsmoothed
# İşleri biraz sabitlemek için önceki eğimi de karıştırıyorum ve
# 1 günden uzun süredir trend olan şeyleri canlandırın
eğer len (eğimler) > 1:
trend_snap = eğimler + eğimler * 0,5
sıralı döndür (trend_snap.items (), key = operator.itemgetter (1), reverse = True)
def smooth (seri, pencere boyutu, pencere):
ext = np.r_
ağırlıklar = pencere (pencere_boyutu)
yumuşatılmış = np.convolve (ağırlıklar / ağırlıklar.sum (), ext, mod = 'aynı')
dönüş düzeltildi
def standardize (seri):
iqr = np. yüzdelik (seri, 75) -np. yüzdelik (seri, 25)
return (series-np.median (series)) / iqr
trending = train () print "Trend olan 5 ürün:" trenddeki i, s için:
"Ürün% s (puan:% 2.2f)"% (i, s) yazdır
Sonuçlar aşağıdaki gibidir:
Trend olan 5 ürün: Ürün 103 (puan: 1,31) Ürün 573 (puan: 1,25) Ürün 442 (puan: 1,01) Ürün 753 (puan: 0,78) Ürün 738 (puan: 0,66)
Bu, algoritmanın özüdür. Şu anda yazılıyor ve mevcut mevcut algoritmalarla karşılaştırıldığında iyi performans gösteriyor.
Performansını daha da artırmak için birkaç ek içerik ekliyoruz:
1. Çok popüler olmayan ürün sonuçlarını kaldırın. Aksi takdirde alışveriş sepetine 10 defadan fazla eklemeniz gerekir ve alışveriş sepetine yalnızca 1-5 kez eklenen ürünler sıcak ürün sonuçlarında görünecektir.
2. Günde 500 defadan 600 defaya çıkan ürünler, 20 kattan 40 katına çıkan ürünlerle birlikte sıcak noktada sergilenecek şekilde ürünleri tartın.
Popüler ürünlerin algoritmaları hakkında şaşırtıcı derecede az bilgi var. Bununla birlikte, diğer insanların daha gelişmiş teknolojiye sahip olması ve daha iyi sonuçlar elde etmesi oldukça olasıdır.
Ancak Grove için bu, tüm hedeflerine ulaştı: açıklaması kolay, beklenmedik durum ve tüketicilere sunulan diğer tüm ürünlerden daha fazla sayıda isabet aldı.