Çalma listesi önerisini 2000 parçada denemek: vektör yerine etiket

这篇内容暂时只有 Türkçe 版本,以下是原文。

Kütüphanemde 2000’e yakın parça var, çoğu aynı türden ama tempo ve enerji dağılımı düzensiz. Bir süredir “şu an çalan parçaya benzer 15 parça” isteğini nasıl üreteceğimi deniyordum. İlk denemem ses özelliklerinden vektör çıkarıp kosinüs benzerliğiydi; sonuçlar teknik olarak doğruydu ama pratikte işe yaramıyordu, çünkü aynı ses imzasına sahip parçalar aynı ruh hâlinde olmuyor. Sonra etiket tabanlı, daha kaba bir yönteme geçtim ve günlük kullanımda daha iyi çalıştığını gördüm.

Önce her parçaya üç eksende etiket yazdım: tempo aralığı (yavaş/orta/hızlı), enerji (sakin/normal/yüksek) ve enstrümantasyon (akustik/elektronik/karışık). Bunları tek tek elle girmedim; mevcut etiketlerimden türettim. Türetme betiği şöyle, Python ve sqlite ile:

import sqlite3
conn = sqlite3.connect("muzik.db")
cur = conn.cursor()
cur.execute("""
SELECT id, bpm, energy, acoustic_ratio
FROM tracks
WHERE bpm IS NOT NULL AND energy IS NOT NULL
""")
rows = cur.fetchall()

def tempo_band(bpm):
    if bpm < 90: return "yavas"
    if bpm < 125: return "orta"
    return "hizli"

def energy_band(e):
    if e < 0.4: return "sakin"
    if e < 0.7: return "normal"
    return "yuksek"

def inst_band(a):
    if a > 0.7: return "akustik"
    if a < 0.3: return "elektronik"
    return "karisik"

for tid, bpm, e, a in rows:
    cur.execute("""
    INSERT OR REPLACE INTO track_tags (track_id, tempo, enerji, enstruman)
    VALUES (?, ?, ?, ?)
    """, (tid, tempo_band(bpm), energy_band(e), inst_band(a)))
conn.commit()

Öneri üretirken önce aynı tempo ve enerji bandındaki parçaları alıyorum, sonra enstrüman bandına göre sıralıyorum. Sorgu basit:

SELECT t.id, t.title
FROM tracks t
JOIN track_tags g ON g.track_id = t.id
WHERE g.tempo = :tempo AND g.enerji = :enerji
  AND g.enstruman != :enstruman
  AND t.id != :seed_id
ORDER BY RANDOM()
LIMIT 15;

Burada != kullanmam bilinçli: aynı enstrüman bandından öneri gelirse liste tekdüze oluyor; farklı banttan gelince geçiş daha doğal hissediliyor. Ama bu bir kural değil, kütüphanemin dağılımına göre bulduğum bir ayar.

Neden vektör değil de etiket: vektör yaklaşımında her parça için bir uzaklık hesaplıyorum, ama sonucu açıklayamıyorum. Etiket yaklaşımında “neden bu parça geldi” sorusunun cevabı tek satırda görünüyor ve yanlış öneriyi gördüğümde etiketi düzeltmem yetiyor. Bedeli şu: etiketler kaba, 2000 parçanın yaklaşık 300’ünde tempo veya enerji verisi eksikti; onları elle doldurdum, yoksa hiç önerilmiyorlardı. Ayrıca bant sınırları yapay; 89 BPM ile 90 BPM arasındaki fark gerçekte yok ama sorguda var.

Nerede çöküyor: canlı kayıtlarda BPM tespiti tutarsız, aynı parçanın stüdyo ve canlı sürümü farklı banda düşüyor. Caz gibi tempo değişen parçalarda tek BPM değeri anlamsız kalıyor, bu yüzden o parçaları etiketlerken tempo bandını boş bırakıp enerji ve enstrümanla öneriye sokuyorum. Bir de kütüphane 2000’i geçince ORDER BY RANDOM() yavaşlamaya başladı; şimdilik sorun değil ama 5000’de indeks eklemem gerekecek.

Sizin kütüphanenizde benzer bir istek için etiket mi yoksa vektör mü kullanıyorsunuz; tempo değişen parçaları nasıl etiketliyorsunuz?

0
赞同度 100% · 0 条评论 · 3 阅读

0 条评论

支持 Markdown · 回复会实时推送给对方

还没有评论,写下第一条。