Algoritma di Balik Rekomendasi Skincare: Implementasi Jaccard Similarity pada ForgeMoist
Mengupas tuntas pemanfaatan rumus Jaccard Similarity untuk mencocokkan bahan aktif skincare dengan keluhan kulit pengguna secara presisi.
Table of Contents
Pernahkah Anda bertanya-tanya bagaimana sebuah sistem dapat merekomendasikan produk perawatan kulit (skincare) yang sangat spesifik untuk Anda? Dalam proyek ForgeMoist, saya merancang mesin rekomendasi pelembap wajah pintar yang tidak hanya mengandalkan filter manual biasa, melainkan menggunakan kalkulasi statistik bernama Jaccard Similarity.
Artikel ini akan mengupas bagaimana rumus matematika ini diterjemahkan ke dalam kode TypeScript untuk mencocokkan bahan aktif dengan keluhan kulit Anda secara akurat.
Mengapa Menggunakan Jaccard Similarity?
Jaccard Similarity adalah metode statistik yang digunakan untuk mengukur tingkat kemiripan (similarity) antara dua kumpulan data (set). Rumusnya sangat sederhana namun kuat:
Dalam konteks skincare:
- Set A: Bahan aktif yang dibutuhkan untuk mengatasi masalah kulit Anda (misalnya, jika Anda memilih masalah jerawat, sistem mencari Salicylic Acid, Centella Asiatica, atau Niacinamide).
- Set B: Kandungan aktif yang benar-benar ada di dalam produk pelembap.
Semakin banyak irisan (intersection) bahan aktif yang cocok dibagi dengan total gabungan (union) bahan aktif, semakin tinggi skor kecocokannya.
Menerjemahkannya ke dalam Kode
Mari kita bedah implementasinya pada API route Next.js (/api/recommend).
Pertama, kita definisikan pemetaan masalah kulit (concern) ke bahan aktif idealnya:
const CONCERN_INGREDIENT_MAP: Record<string, string[]> = {
acne_care: ['Salicylic Acid', 'Centella Asiatica', 'Niacinamide'],
brightening: ['Niacinamide', 'Vitamin C'],
hydration: ['Hyaluronic Acid', 'Ceramide'],
barrier_repair: ['Ceramide'],
oil_control: ['Niacinamide', 'Salicylic Acid'],
anti_aging: ['Retinol', 'Vitamin C'],
soothing: ['Centella Asiatica'],
dark_spot: ['Vitamin C', 'Niacinamide'],
pore_minimizing: ['Niacinamide', 'Salicylic Acid'],
};Selanjutnya, kita hitung skor kemiripan antara preferensi pengguna dan produk:
function computeMatchScore(
product: EnrichedProduct,
targetIngredients: string[],
targetConcerns: string[]
): number {
const pIngredients = new Set((product.ingredients || []).map(i => i.toLowerCase()));
const tIngredients = new Set(targetIngredients.map(i => i.toLowerCase()));
// Masukkan bahan aktif ideal berdasarkan concern yang dipilih pengguna
for (const concern of targetConcerns) {
const mapped = CONCERN_INGREDIENT_MAP[concern] || [];
mapped.forEach(i => tIngredients.add(i.toLowerCase()));
}
// Hitung Irisan (Intersection)
const intersection = Array.from(tIngredients).filter(i => pIngredients.has(i)).length;
// Hitung Gabungan (Union)
const unionSet = new Set(pIngredients);
tIngredients.forEach(i => unionSet.add(i));
const union = unionSet.size;
const jaccard = union === 0 ? 0 : intersection / union;
// Konversi ke skala 60% bobot rekomendasi
const ingredientScore = jaccard * 60;
return ingredientScore;
}Menyusun Skor Akhir (Multi-factor Ranking)
Skor kesamaan kandungan di atas menyumbang 60% dari total rekomendasi. Untuk memberikan hasil yang lebih realistis dan terpercaya, saya menggabungkannya dengan data eksternal:
- Rating Komunitas (Bobot 15%): Mengonversi rating bintang produk (0-5) ke poin.
- Popularitas Ulasan (Bobot 25%): Menggunakan skala logaritmis dari jumlah ulasan nyata di platform kecantikan (misalnya, produk dengan 10.000+ ulasan mendapat nilai penuh).
- Penalti Gambar (-25 poin): Produk tanpa gambar utama diturunkan peringkatnya agar visual halaman rekomendasi tetap menarik dan terisi penuh.
Hasil perhitungan dinormalisasi menjadi rentang 30–100 sebagai nilai akhir Match Score yang tampil di antarmuka web.
Dengan pendekatan ini, ForgeMoist berhasil menyajikan rekomendasi yang secara ilmiah masuk akal (berdasarkan bahan aktif) sekaligus tervalidasi secara sosial (berdasarkan rating dan ulasan nyata komunitas).