Hai Nama saya Nikita Uchetelev. Saya mewakili Lamoda Research & Development. Kami adalah 20+ orang, dan kami sedang mengerjakan berbagai rekomendasi di situs dan dalam aplikasi, kami sedang mengembangkan pencarian, kami menentukan penyortiran barang dalam katalog, kami menyediakan kemungkinan pengujian AB dari berbagai fungsi, dan kami juga mendukung beberapa pengembangan internal seperti sistem untuk memperkirakan elastisitas permintaan dan mengoptimalkan pengiriman logistik.

Salah satu arahan utama pengembangan seluruh perusahaan untuk tahun-tahun mendatang adalah personalisasi produk dan layanan kami. Inisiatif tersebut diuji dan diimplementasikan di mana-mana - mulai dari menyusun pilihan produk pribadi hingga memilih perwakilan penjualan tertentu yang akan mengirimkan barang kepada Anda. Sebagai bagian dari proses mempersonalisasi produk R&D, saya bertindak sebagai pemimpin tim dan dalam artikel ini saya ingin berbicara tentang platform yang telah saya dan tim saya rancang dan kembangkan untuk tahun lalu, serta tentang produk R&D pertama yang dipersonalisasi yang saat ini sedang menjalani pengujian AB.
Ideologi rekomendasi produk
Atribut toko online apa pun yang akrab bagi semua orang adalah halaman produk. Biasanya memberikan deskripsi terperinci, beberapa foto besar, ulasan pelanggan, tombol "Tambahkan ke Troli" dan elemen navigasi lain yang akrab. Di bagian bawah halaman tersebut adalah satu atau lebih rak dengan produk lain yang disebut "Produk Terkait," "Membeli Dengan Produk Ini," atau sesuatu yang lain. Setiap rak memiliki tujuan tersendiri.
Misalnya, rak dengan produk serupa dirancang untuk memberi pengguna variasi produk tambahan dalam konteks pilihan saat ini. Ini dapat bermanfaat jika tidak ada ukuran pengguna dalam stok, atau jika ia berada pada tahap pemilihan dan menginginkan produk yang sama, tetapi “dengan kancing mutiara”. Pada saat yang sama, rak mengambil pembeli dari halaman produk, di mana ia mungkin tidak lagi kembali, dan karenanya tidak membelinya.
Ada rak kedua di situs web dan dalam aplikasi Lamoda, yang kami sebut rak lintas-rekomendasi . Itu terletak tepat di bawah rak dengan barang-barang serupa, dan kami mencoba untuk menempatkannya di barang-barang berbeda yang paling sering ditemukan di kereta belanja bersama dengan SKU saat ini (Stock Keeping Unit atau, lebih sederhana, artikel). Jadi, misalnya, celana panjang dan sepatu direkomendasikan untuk jaket, syal, dan topi untuk sweater. Ada sekelompok barang murah yang paling sering dibeli. Biasanya, ini adalah kaus kaki dan pakaian dalam, sehingga sering terlihat di rak ini.
Teknik penjualan ini mirip dengan penjualan. Kami mencoba untuk menjual beberapa barang pelengkap besar, asalkan pengguna menyukai produk saat ini. Pada saat yang sama, ini adalah salah satu dari sedikit tempat di mana pelanggan dapat berkenalan dengan jangkauan kami. Misalnya, untuk melihat merek atau subkategori, keberadaan yang tidak mereka ketahui sebelumnya. Kami menyebutnya inspirasi & penemuan - ketika kami menginspirasi pelanggan untuk melakukan pembelian baru dan memberi tahu kami seberapa luas jangkauan kami, kami menunjukkan harga dan diskon.

Secara historis, pengisian rak-rak ini dihitung secara offline (dengan margin, jika beberapa produk kehabisan stok sebelum perhitungan berikutnya) bersama dengan pengurutan berdasarkan beberapa kesamaan metrik atau konversi bersyarat. Dengan demikian, semua pengguna melihat ada hal yang sama di siang hari. Kami memutuskan untuk memulai eksperimen dengan personalisasi dari rak-rak ini, karena pada halaman produk kami memiliki lalu lintas yang cukup untuk melakukan eksperimen yang berkualitas. Dari sudut pandang teknis, ini ternyata menjadi salah satu tempat paling nyaman untuk implementasi dalam infrastruktur kami (ditandai dengan warna merah pada diagram).

Idenya adalah ini : kami melatih beberapa model yang dapat menetapkan "pengguna + produk" memasangkan probabilitas konversi atau hanya satu klik, dan kemudian menampilkannya di rak dari kiri ke kanan dalam urutan probabilitas ini. Karena pada layar pertama carousel hanya 4 hingga 6 SKU yang ditampilkan, tergantung pada resolusi layar, dan secara total kita dapat menghitungnya, katakanlah, hingga ratusan, "kedalaman" personalisasi yang cukup dapat diterima dicapai.
Kami menyelesaikan masalah dari awal
Mari kita beralih ke bagian teknis. Kami memiliki batasan pada waktu respons API. Misalnya, dalam aplikasi, layanan di masa mendatang harus tepat waktu untuk bertanggung jawab atas 100 ms. Selama waktu ini, Anda harus pergi ke database yang berbeda untuk data pengguna dan produk, mengatur seratus contoh di bawah memuat hingga 100 QPS di puncak. Ini mengarahkan kita pada kebutuhan untuk menggunakan kerangka kerja pembelajaran mesin sub-milidetik. Salah satu yang paling terkenal adalah Vowpal Wabbit.
Bidang khas aplikasi untuk kerangka kerja ini adalah adtech, yaitu, memprediksi RKT iklan ketika mengoptimalkan tawaran untuk lelang RTB. Dari sudut pandang matematika, kita bisa menimbulkan masalah yang sama. Misalkan kita ingin memprediksi kemungkinan klik dengan melatih model pada tampilan produk. Beban pada model hingga 10k QPS sebanding dengan indikator periklanan dan, secara umum, membenarkan kebutuhan untuk membatasi diri hanya untuk algoritma linier pada tahap prototyping dan MVP.
Sekarang mari kita pikirkan tentang data pengguna apa yang dapat mengandung sinyal yang kita butuhkan dan bedakan antara pengguna dengan baik. Karena kita berbicara tentang rekomendasi produk dan halaman produk yang dikunjungi pengguna, maka kemungkinan besar dia berada pada tahap pemilihan. Di kepalanya ada gambar "sepatu sempurna" yang dengannya dia membandingkan semua barang yang menarik perhatiannya. Biarkan dia pertama-tama pergi ke katalog barang dari kategori yang diinginkan dan memulai pencarian dengan mengklik segala sesuatu yang kurang lebih menyerupai presentasinya. Dengan demikian, pengguna menyimpan beberapa "jejak digital" dari produk yang dilihat. Berdasarkan unit pada jejak ini, kami akan melakukan personalisasi.
Representasi vektor objek
Semua produk berbeda di antara mereka sendiri dengan nilai tabular dari beberapa atribut: warna, bahan, kain, jenis cetak, panjang lengan, keberadaan tudung, tinggi tumit, dll. Dengan demikian, dimungkinkan untuk menyandikan jejak digital apa pun dengan fraksi kemunculan masing-masing nilai atribut ini. Misalkan kita memiliki produk dalam tiga warna dan tiga merek yang dapat Anda lihat dan masukkan ke dalam keranjang. Kemudian, dengan mengambil riwayat tindakan pengguna, ia dapat mencocokkan vektor dengan bentuk berikut:

Dalam hal ini, pengguna melihat 10 produk: 5 emas, 2 hitam dan 3 merah. Dan dia menambahkan 2 merah dan 2 hitam ke keranjang, dia tidak menambahkan emas. Demikian pula dengan merek A, B dan C, serta dengan nilai atribut apa pun. Lebih lanjut, vektor semacam itu dapat digabungkan dengan vektor nilai-nilai atribut yang dikodekan satu-panas untuk produk tertentu.
Dengan demikian, kita dapat membuat vektor peristiwa tertentu. Seorang pengguna yang, dalam kerangka sesi saat ini, telah melihat sejumlah produk dengan distribusi warna yang diberikan, sedang bersiap untuk melihat beberapa produk baru, misalnya, merah. Dengan menggunakan data historis tentang tayangan dan klik, Anda dapat membuat model yang akan memprediksi kemungkinan klik pada produk merah, asalkan memiliki distribusi warna yang ada untuk produk yang dilihat sebelumnya.
Jika Anda melihat ruang di mana kita telah belajar untuk menampilkan klik-klik sejarah, Anda dapat melihat bahwa satu bagian ditempati oleh subruang biner dan yang lainnya adalah material, dan mereka tidak terhubung satu sama lain. Model linear kami dalam kasus ini adalah kombinasi linear (jumlah tertimbang) dari koordinat titik dalam ruang ini. Jika dia belajar dari contoh-contoh seperti itu, dia hanya akan mempelajari probabilitas a priori. Misalnya, berat di depan koordinat yang sesuai dengan warna merah barang akan menjadi nilai yang berbanding lurus dengan RKT barang merah. Dengan demikian, koordinat pengguna tertentu akan ditimbang oleh karakteristik frekuensi klik pengguna yang berbeda untuk setiap produk dari katalog. Tapi ini tidak seperti yang kita inginkan.
Fitur polinomial datang untuk menyelamatkan - hasil dari penggandaan semua jumlah biner dengan semua yang nyata. Kerangka kerja Vowpal Wabbit memiliki alat yang ampuh untuk menghasilkan fitur daya dari ruang nama. Mari kita coba membuat string dalam format vw untuk contoh kita, menyebarkan fitur pengguna dan komoditas di ruang nama yang berbeda.
|user_color :0.5 :0.2 :0.3 |product_color
Sekarang, jika selama latihan kita menambahkan -q pu switch, maka fitur kuadrat nol seperti itu akan muncul:
user_color^ * product_color^ = 0.5 user_color^ * product_color^ = 0.2 user_color^ * product_color^ = 0.3
Dengan demikian, model ini mencari sinyal tidak hanya dalam cara pengguna mengklik dengan proporsi tinggi produk merah dilihat, tetapi bagaimana mereka mengklik produk merah. Bobot fitur seperti itu dalam model yang dilatih harus positif dan cukup besar.
Pendekatan rekayasa fitur ini secara dramatis meningkatkan dimensi ruang di mana pelatihan berlangsung. Dalam situasi di mana kita hanya memiliki 4 warna, dimensi ruang ini adalah 8 (4 warna untuk produk dan 4 untuk pengguna). Dengan penambahan 16 atribut kuadrat, itu meningkat menjadi 24. Dalam produksi, selain warna, kami menggunakan 13 atribut barang lainnya, termasuk, misalnya, merek. Oleh karena itu, dimensi total ruang tempat model kami bekerja dapat mencapai 3 juta fitur. Pada saat yang sama, kami ingin mempertahankan rasio jumlah contoh pelatihan dengan dimensi ruang pada level 1: 100. Untuk melakukan ini, kita perlu menghasilkan total sekitar 300 juta pengamatan.
Kami menyimpan clickstream pengguna kami di Hadoop (Spark Streaming dari Apache Kafka ke tabel Hive). Kami biasanya mendapatkan sekitar 30 gigabytes data terkompresi per hari - ini lebih dari seratus jenis tindakan yang dapat dilakukan pengguna di situs dan dalam aplikasi, termasuk menampilkan barang di berbagai penempatan.
Juga untuk rak rekomendasi ada informasi tentang produk mana yang ditampilkan dan di mana klik itu dibuat. Tugas kami untuk setiap klik seperti itu di masa lalu adalah menghitung keadaan pengguna dalam hal rasio fraksi nilai-nilai atribut dari produk yang dilihat pada titik waktu sebelum klik yang diberikan. Kemudian gabungan pasangan vektor "pengguna" + "produk yang diklik" akan memberikan contoh pelatihan positif, dan pasangan serupa dengan produk yang ditampilkan di sebelahnya di rak, tetapi tanpa klik, akan menjadi contoh negatif. Penting bahwa produk ditampilkan di dekat Anda. Maka kita dapat memastikan bahwa pengguna melihat mereka, tetapi tidak mengklik. Sebagai bonus, dengan mekanisme seperti itu kita dapat mengontrol rasio kelas dalam masalah.
Solusi kami adalah agregasi harian data pengguna menggunakan Spark dan penambahan data ini ke dalam HBase. Pertimbangkan struktur agregat semacam itu.
Jadi, objek utama dalam tugas ini adalah pengguna. Sesi dikaitkan dengan itu, yang terdiri dari serangkaian tindakan, yang masing-masing memiliki karakteristik tertentu tergantung pada jenis tindakan. Misalnya, jika ini melihat halaman produk, maka nomor artikel produk dan waktu menonton milik atribut yang kita butuhkan. Sebagai cadangan untuk masa depan, kami segera menulis ke log ketersediaan barang dalam stok dan dua harga: harga dasar dan memperhitungkan stok akun dan kupon pribadi. Kami tidak memerlukan tayangan secara terpisah, oleh karena itu dengan cepat pada saat agregasi mereka dikaitkan dengan klik dan menghasilkan jenis acara baru di mana, selain bidang dengan nomor artikel produk di mana klik itu dibuat, ada juga array dari beberapa artikel yang mengelilinginya pada saat tampilan.
HBase adalah database kolom berversi dengan antarmuka asli untuk menghubungkan ke Spark untuk pemrosesan batch dan dengan kemampuan untuk mengakses data dengan kunci. Fitur lain dari itu adalah HBase tidak memiliki konsep sirkuit. Itu hanya dapat menyimpan byte, atau lebih tepatnya offset, di dalam HFiles khusus yang disesuaikan dengan struktur blok HDFS.
Beberapa orang mungkin merasa kontroversial untuk memilih repositori, tetapi saya memiliki pengalaman yang baik bekerja dengan HBase dalam proyek serupa. Selain itu, di Lamoda basis data ini sudah digunakan secara aktif, jadi kami tidak perlu mengeluarkan biaya untuk menggunakan sistem yang sudah digunakan untuk MVP. Kami tidak menggunakan fungsionalitas versi pada saat ini, tetapi akses kunci tampaknya berguna untuk kemungkinan pelatihan model multithreaded di masa depan dan organisasi arsitektur lambda untuk memuat data dan kasus waktu nyata lainnya.
Karena tidak ada skema dalam HBase, kami membutuhkan wadah data kami sendiri. Anda dapat menggunakan lambda x: json.dumps (x) .encode () , tetapi saya menginginkan sesuatu yang lebih cepat. Solusi yang sepenuhnya standar adalah dengan menggunakan wadah protobuf. Karena pengembangan seluruh proyek dilakukan dengan python, lebih biasa bagi saya untuk menggunakan perpustakaan pyrobuf khusus dari AppNexus daripada yang resmi dari Google. Menurut tolok ukur, kinerja fungsionalitas dasar protobuffs beberapa kali lebih tinggi dari aslinya. Skema perkiraan protobuff kami adalah sebagai berikut:
enum Location { ru = 1; by = 2; ua = 3; kz = 4; special = 5; } enum Platform { desktop = 1; mobile = 2; a_phone = 3; a_tablet = 4; iphone = 5; ipad = 6; } message Action { enum ActionType { pageview = 1; quickview = 2; rec_click = 3; catalog_click = 4; fav_add = 5; cart_add = 6; order_submit = 7; } required uint64 ts = 1; required ActionType action_type = 2; optional string sku = 3; required bool is_office = 4; repeated string skus = 5; optional uint32 delta = 6; optional string sku_source = 7; optional bool stock = 8; optional uint32 base_price = 9; optional uint32 price = 10; optional string type = 11; } message Session { required string session_id = 1; repeated Action actions = 2; required uint64 session_start = 3; required uint64 session_end = 4; optional uint32 actions_count = 5; } message LID { required string uid = 1; repeated Session sessions = 2; required Location location = 3; required Platform platform = 4; optional uint32 sessions_count = 5; }
Singkatnya, ada objek "Pengguna" (LID, Lamoda ID). Di dalamnya ada array objek "Sesi", yang masing-masing adalah array objek "Aksi". Kami membagi tindakan berdasarkan jenis dan menyimpannya dalam Keluarga Kolom yang berbeda, yang memungkinkan kami untuk mengoptimalkan bacaan sedikit ketika kami hanya membutuhkan acara jenis tertentu (tampilan produk, klik yang dikaitkan pada berbagai jenis rekomendasi, dll.).
Pengujian
Selama tiga minggu kami melakukan tes AB di situs desktop lamoda.ru dengan desain berikut:
- Pengendalian: Rekomendasi API mengacu pada layanan personalisasi, menunggu hasilnya, tetapi memberikan barang dalam urutan asli, sama untuk semua orang.
- Uji: produk ditampilkan dari kiri ke kanan dalam urutan perkiraan probabilitas klik yang menurun.
Pembagian menjadi dua opsi didasarkan pada LID dari pengguna - pada dasarnya oleh cookie-nya. Platform eksperimental kami memastikan bahwa pengamatan yang dikumpulkan dalam dua versi independen dan terdistribusi secara merata, dan perubahan metrik dievaluasi dengan tingkat signifikansi 5% (p-value 0,05). Sebagai hasilnya, kami menerima + 10% CTR seluruh rak dan perubahan positif yang signifikan dalam pendapatan. Minggu lalu, kami meluncurkan fungsi ini untuk semua pengguna situs.
Untuk memeriksa personalisasi pada diri Anda sendiri, lihat saja beberapa produk yang berbeda dan kemudian bandingkan pengurutan rekomendasi di salah satu rak “Mereka membeli produk ini” di dua browser yang berbeda atau gunakan mode “Penyamaran”. Tentu saja, jika Anda belum mengunjungi situs kami sebelumnya, maka masih ada sedikit data tentang Anda di platform. Coba pilih jaket musim dingin dan bandingkan pesanan barang lagi setelah beberapa saat.
Jadi kami mendapatkan seluruh platform - satu set alat perangkat lunak yang mengumpulkan data dan menyimpannya, serta kerangka kerja untuk membuat vektor objek bisnis pada titik waktu yang sewenang-wenang di masa lalu, yang memungkinkan Anda membangun model penilaian untuk menilai kemungkinan berbagai tindakan. Gangguan model disediakan melalui layanan web yang dapat mengumpulkan vektor yang relevan dari berbagai sumber data dan menjalankannya melalui model. Ia menerima LID (pengidentifikasi pengguna), daftar SKU yang perlu dibuka, dan berbagai informasi tambahan, mengembalikan daftar produk yang sama ke prakiraan probabilitas klik yang diperkaya dengan prakiraan. Di bawah ini adalah diagram arsitektur konseptual platform kami:

Elemen Inti ML adalah seperangkat mesin virtual tempat klien Hadoop dan pekerja Aliran Udara diinstal. Kami mengatur konfigurasi, dengan parameter apa untuk melatih model, di mana untuk mendapatkan data historis dan sebagainya. Akibatnya, model dilatih dan diterbitkan dalam artifactory, dan informasi tentang proses pembelajaran dan metrik kualitas yang menarik bagi kami disimpan dalam repositori meta.
Sekarang sudah menguji atau mempersiapkan tes sistem personalisasi rekomendasi di milis, di halaman utama dan di rak dengan rekomendasi untuk produk serupa, segmen yang mirip untuk menargetkan iklan internal dan eksternal dan banyak lagi.
Ini adalah artikel pengantar. Dalam publikasi lebih lanjut, saya dapat berkonsentrasi pada aspek teknis arsitektur dan berbicara tentang pengembangannya, atau, sebaliknya, memperluas komponen produk secara lebih luas dan memberi tahu bagaimana kami menggunakan dan mengevaluasi ML dalam tugas-tugas produk. Tulis di komentar keinginan Anda tentang ini.