IlmHamroh
Data Science va sun'iy intellekt/Chiziqli algebra10/10-dars20 daqiqa
Mundarija (22)

10.10-dars: Amaliyot — film tavsiya tizimi

10-QISM — CHIZIQLI ALGEBRA · 10-dars


1. Kirish va motivatsiya

10-qismda chiziqli algebraning butun asbob-uskunasini yig'dik: vektorlar va masofa 10.1-bob, skalyar ko'paytma va kosinus 10.2-bob, matritsalar va kovariatsiya 10.3-bob, o'zgartirishlar 10.4-bob, sistemalar va rank 10.5-bob, eng kichik kvadratlar va Ridge 10.6-bob, xos vektorlar 10.7-bob, SVD 10.8-bob, PCA 10.9-bob. Endi ularni bitta real mahsulotda birlashtiramiz: film tavsiya tizimi.

Tavsiya tizimlari — chiziqli algebraning eng muvaffaqiyatli tijoriy qo'llanilishlaridan biri (Netflix, YouTube, onlayn do'konlar). Ma'lumot — foydalanuvchi × film baholar matritsasi, deyarli bo'sh (har kim filmlarning kichik qismini ko'radi). Vazifa — bo'sh kataklarni bashorat qilish va har foydalanuvchiga u hali ko'rmagan, lekin yoqishi ehtimoli yuqori filmlarni taklif qilish. Biz uch qatlamli yondashuv quramiz: (1) kontentga asoslangan o'xshashlik — film janr vektorlari va kosinus; (2) bias modeli — "qattiqqo'l foydalanuvchi" va "hammaga yoqadigan film" effektlari eng kichik kvadratlar bilan; (3) yashirin omillar — qoldiqlar matritsasining past rankli SVD si. Oxirida PCA bilan filmlar xaritasini chizamiz.

Real vaziyat. Kichik onlayn kinoteatr: 400 foydalanuvchi, 60 film, baholarning atigi 15% i ma'lum. Hozir hammaga "eng yuqori o'rtacha bahoga ega" filmlar tavsiya qilinadi. Data Scientist ma'lum baholarning 20% ini yashirib (test), modellarni solishtiradi: umumiy o'rtacha → bias modeli → bias + SVD. Har bosqich xatoni kamaytiradi va natija raqam bilan ko'rsatiladi. Bundan tashqari, kontentga asoslangan o'xshashlik yangi (hali bahosi yo'q) filmlar uchun ham ishlaydi — "sovuq start" muammosiga yechim.

Bu darsda 10-qismning barcha bilimlarini bitta loyihada qo'llaymiz.

Bu darsda:

  • Baholar matritsasi va uning xossalari (siyraklik, rank)
  • Kontentga asoslangan o'xshashlik (kosinus)
  • Bias modeli — eng kichik kvadratlar
  • Yashirin omillar — past rankli SVD
  • Modellarni solishtirish (test RMSE)
  • PCA bilan filmlar xaritasi
  • Tavsiya ro'yxatini yaratish
  • Loyiha tuzoqlari va hisobot

ℹ Misollar real numpy bilan (Python 3.14). Barcha misollar bir xil yarat() generatoridan foydalanadi.


2. Nazariya — chuqur tushuntirish

2.1. Baholar matritsasi

text
R — 400 foydalanuvchi × 60 film; R[u, i] — baho (1..5) yoki noma'lum
maska M[u, i] = True — baho ma'lum (15%)

Ajratish: ma'lum baholar → o'quv (80%) va test (20%)   ← 8.8, mustaqil tekshiruv
Baholash: test RMSE = sqrt( mean( (bashorat - haqiqiy)^2 ) )  faqat test kataklarida

Tavsiya masalasi — matritsani to'ldirish: noma'lum kataklarni bashorat qilish. Asosiy xususiyatlar: siyraklik (ko'p katak bo'sh — 0 emas, noma'lum, 10.8 tuzog'i), past rankli tuzilma (did bir necha omil bilan tushuntiriladi — shuning uchun SVD ishlaydi), tarafkashlik (odamlar yoqqan filmini ko'proq ko'radi va baholaydi). Baholash — ma'lum baholarning bir qismini yashirib (test), faqat o'quv qismida model qurish.

2.2. Kontentga asoslangan o'xshashlik

Har film — janr vektori (masalan, [jangari, drama, komediya, fantastika] bo'yicha vaznlar). Ikki film o'xshashligi — kosinus 10.2-bob: yo'nalish (janr tarkibi) muhim. "Bu filmga o'xshash filmlar" — eng yuqori kosinusli filmlar. Foydalanuvchi profili — u yuqori baholagan filmlar vektorlarining (baho bilan vaznlangan) o'rtachasi; tavsiya — profilga eng o'xshash, hali ko'rilmagan filmlar. Afzalligi: yangi film uchun ham ishlaydi (baho kerak emas); kamchiligi: faqat ma'lum belgilar (janr) doirasida — "kutilmagan" kashfiyot yo'q.

2.3. Bias modeli — eng kichik kvadratlar

text
r_hat[u, i] = mu + b_u + b_i

mu  — umumiy o'rtacha baho
b_u — foydalanuvchi siljishi ("qattiqqo'l": manfiy, "saxiy": musbat)
b_i — film siljishi ("hammaga yoqadi": musbat)

Har ma'lum baho — bitta tenglama → A @ [b_u..., b_i...] = r - mu
A — (n_baho × (n_user + n_film)) — har qatorda ikkita 1
Rank yetishmaydi (b_u + c, b_i - c — bir xil natija) → Ridge (alpha I) yoki lstsq (min norma)

Baholarning katta qismi oddiy siljishlar bilan tushuntiriladi: ba'zi foydalanuvchilar hamma narsaga past baho beradi, ba'zi filmlar hammaga yoqadi. Bias modeli — chiziqli regressiya 10.6-bob: noma'lumlar — har foydalanuvchi va film siljishi; tenglamalar — ma'lum baholar. Tizim rank yetishmaydi (10.5: barcha b_u ga c qo'shib, b_i dan c ayirsak — natija o'zgarmaydi), shuning uchun Ridge (10.6: X.T X + alpha I) — yagona va barqaror (kam bahoga ega foydalanuvchilarning siljishi 0 ga "qisqaradi" — ishonchsiz baholarga ortiqcha ishonmaslik).

2.4. Yashirin omillar — past rankli SVD

Bias modelidan keyingi qoldiqlar — shaxsiy did: "A foydalanuvchi fantastikani yaxshi ko'radi, dramani yo'q". Qoldiqlar matritsasi past rankli 10.8-bob: foydalanuvchilar va filmlarni k ta yashirin omil fazosida vektor sifatida ifodalash mumkin, baho — ularning skalyar ko'paytmasi 10.2-bob. Yondashuv: noma'lum kataklarni 0 bilan (qoldiq o'rtachasi) boshlab, iterativ SVD: rank-k yaqinlashtirish → ma'lum kataklarni qayta haqiqiy qiymatga qo'yish → takrorlash. k — test RMSE bilan tanlanadi (katta k — overfitting).

2.5. Modellarni solishtirish

Bosqichma-bosqich: (1) umumiy o'rtacha — baza (8.10 dagi kabi); (2) + bias — siljishlarni hisobga olish; (3) + SVD — shaxsiy did. Har bosqich faqat test RMSE si bilan baholanadi va murakkablik faqat yaxshilanish bo'lsa qo'shiladi (9.9, 10.6 — baza model). Qo'shimcha o'lchovlar: har bir foydalanuvchi uchun "top-5" tavsiyalar haqiqatan yuqori baholanganmi (test ichida), tavsiyalar xilma-xilligi. Bashorat qiymatini [1, 5] ga qirqish (clip) — xatoni kamaytiradi.

2.6. PCA bilan filmlar xaritasi

SVD dan olingan film omillari (yoki film janr vektorlari) — ko'p o'lchamli; PCA 10.9-bob bilan 2D ga tushirib, filmlar "xaritasini" chizamiz: yaqin filmlar — o'xshash did. Komponentalar yuklamalari — xarita o'qlarining ma'nosi ("jangari ↔ drama"). Bu — modelni tushuntirish va tekshirish vositasi: agar xaritada bir janr filmlari bir joyga to'plansa, model ma'noli narsa o'rgangan.

2.7. Loyiha tuzoqlari

Asosiy tuzoqlar: noma'lumni 0 deb olish (0 — "eng yomon baho" emas; to'ldirish — o'rtacha yoki qoldiq 0); testni o'quvga aralashtirish (SVD to'ldirishda test kataklari "ma'lum" deb olinsa — leakage; faqat o'quv maskasi); k ni o'quv xatosi bilan tanlash (doim eng katta k); bias'siz SVD (siljishlarni SVD o'rganishga majbur — omillar isrof bo'ladi); clip'siz bashorat (6.2 kabi ma'nosiz qiymatlar); faqat RMSE (tavsiya sifati — top-k aniqligi, xilma-xillik ham); mashhurlik tarafkashligi (ko'p baholangan filmlar hukmron — "uzun dum" e'tiborsiz); sovuq start (yangi foydalanuvchi/film — SVD ojiz; kontent o'xshashligi yordam beradi).

2.8. Chiziqli algebra loyihasi — 10-qism yakuni

Loyiha: baholar matritsasi (siyrak, past rankli, o'quv/test ajratish — 10.3, 8.8) → kontent o'xshashligi (janr vektorlari, kosinus — 10.1-10.2) → bias modeli (eng kichik kvadratlar, rank yetishmovchiligi, Ridge — 10.5-10.6) → yashirin omillar (qoldiqlar SVD si, iterativ to'ldirish, k tanlash — 10.8) → baholash (test RMSE, baza bilan solishtirish) → PCA xaritasi 10.9-bob → tavsiya ro'yxati. Chiziqli algebra — ML ning tili: vektorlar ma'lumotni, matritsalar o'zgartirishlarni, yoyilmalar tuzilmani ifodalaydi.


3. Tez ma'lumotnoma

python
import numpy as np

# O'QUV/TEST MASKALARI
test = maska & (rng.random(R.shape) < 0.2); oquv = maska & ~test

# KONTENT O'XSHASHLIGI
Gn = G / np.linalg.norm(G, axis=1, keepdims=True)    # film janr vektorlari
S = Gn @ Gn.T                                        # kosinus matritsasi

# BIAS MODELI (Ridge normal tenglama)
u, i = np.nonzero(oquv); r = R[u, i]; mu = r.mean()
A = np.zeros((len(r), n_u + n_i)); A[np.arange(len(r)), u] = 1; A[np.arange(len(r)), n_u + i] = 1
b = np.linalg.solve(A.T @ A + alpha * np.eye(n_u + n_i), A.T @ (r - mu))
bu, bi = b[:n_u], b[n_u:]
bashorat = mu + bu[:, None] + bi[None, :]

# SVD QOLDIQLAR (iterativ)
Q = np.where(oquv, R - bashorat, 0.0)
for _ in range(30):
    U, s, Vt = np.linalg.svd(Q, full_matrices=False)
    Q_k = U[:, :k] @ np.diag(s[:k]) @ Vt[:k]
    Q = np.where(oquv, R - bashorat, Q_k)
yakuniy = np.clip(bashorat + Q_k, 1, 5)

rmse = np.sqrt(np.mean((yakuniy[test] - R[test]) ** 2))
QOIDA: noma'lum ≠ 0 · faqat o'quv maskasi · bias + SVD · k — test bilan · clip

Loyiha xulosasi

Baholar — siyrak, past rankli matritsa; o'quv/test maskalari
Kontent — janr vektorlari, kosinus (sovuq start)
Bias — mu + b_u + b_i; eng kichik kvadratlar + Ridge (rank yetishmaydi)
Did — qoldiqlarning past rankli SVD si (iterativ, k — test bilan)
PCA — filmlar xaritasi (tushuntirish)
Baholash — test RMSE, baza modeldan yaxshilanish

4. Batafsil misollar

Misollar real numpy bilan (Python 3.14). Har misol boshida bir xil yarat() generatori.

Misol 1 — Ma'lumot va kontent o'xshashligi

python
"""Loyiha: baholar matritsasi pasporti va janr vektorlari bo'yicha o'xshash filmlar (real numpy)."""

import numpy as np

JANR = ["jangari", "drama", "komediya", "fantastika"]


def yarat():
    rng = np.random.default_rng(42)
    n_u, n_i = 400, 60
    G = rng.dirichlet(np.full(4, 0.4), n_i)                 # film janr tarkibi
    P = rng.normal(0, 1, (n_u, 4))                          # foydalanuvchi janr didi
    bu = rng.normal(0, 0.4, n_u); bi = rng.normal(0, 0.4, n_i)
    R = np.clip(3.2 + bu[:, None] + bi[None, :] + 0.8 * P @ G.T
                + rng.normal(0, 0.35, (n_u, n_i)), 1, 5)
    maska = rng.random((n_u, n_i)) < 0.15
    test = maska & (rng.random((n_u, n_i)) < 0.2)
    return R, G, maska & ~test, test


def main() -> None:
    R, G, oquv, test = yarat()

    print("=== 1. Pasport ===")
    print(f"  shakl {R.shape}, ma'lum: o'quv {oquv.sum()}, test {test.sum()}")
    print(f"  to'ldirilganlik: {(oquv | test).mean():.1%}")
    print(f"  har foydalanuvchida o'rtacha {oquv.sum(axis=1).mean():.1f} ta baho")

    print("\n=== 2. Kontent: 0-filmga o'xshash filmlar (kosinus) ===")
    Gn = G / np.linalg.norm(G, axis=1, keepdims=True)
    S = Gn @ Gn.T
    print(f"  0-film tarkibi: {dict((j, round(float(x), 2)) for j, x in zip(JANR, G[0]))}")
    for j in np.argsort(S[0])[::-1][1:4]:
        asosiy = JANR[int(np.argmax(G[j]))]
        print(f"  film {j:>2}: kosinus {S[0, j]:.3f}, asosiy janr {asosiy}")

    print("\n=== 3. Matritsa tuzilmasi (to'liq R ning singulyar qiymatlari) ===")
    s = np.linalg.svd(R - R.mean(), compute_uv=False)
    print(f"  s[:8] = {np.round(s[:8], 1)}")
    print("  ⭐ Bir necha katta s — past rankli did tuzilmasi")


if __name__ == "__main__":
    main()

Natijaning muhim qismi:

text
=== 1. Pasport ===
  shakl (400, 60), ma'lum: o'quv 2870, test 728
  to'ldirilganlik: 15.0%
  har foydalanuvchida o'rtacha 7.2 ta baho

=== 2. Kontent: 0-filmga o'xshash filmlar (kosinus) ===
  0-film tarkibi: {'jangari': 0.28, 'drama': 0.46, 'komediya': 0.0, 'fantastika': 0.26}
  film 46: kosinus 0.996, asosiy janr drama
  film 39: kosinus 0.959, asosiy janr drama
  film 21: kosinus 0.945, asosiy janr drama

=== 3. Matritsa tuzilmasi (to'liq R ning singulyar qiymatlari) ===
  s[:8] = [83.8 64.2 41.2 38.8 34.1  9.2  9.1  9. ]
  ⭐ Bir necha katta s — past rankli did tuzilmasi

Nima ko'rsatdi: 2.1, 2.2-bo'limlar.

Misol 2 — Bias modeli (eng kichik kvadratlar + Ridge)

python
"""Loyiha: mu + b_u + b_i — rank yetishmovchiligi va Ridge (real numpy)."""

import numpy as np


def yarat():
    rng = np.random.default_rng(42)
    n_u, n_i = 400, 60
    G = rng.dirichlet(np.full(4, 0.4), n_i)
    P = rng.normal(0, 1, (n_u, 4))
    bu = rng.normal(0, 0.4, n_u); bi = rng.normal(0, 0.4, n_i)
    R = np.clip(3.2 + bu[:, None] + bi[None, :] + 0.8 * P @ G.T
                + rng.normal(0, 0.35, (n_u, n_i)), 1, 5)
    maska = rng.random((n_u, n_i)) < 0.15
    test = maska & (rng.random((n_u, n_i)) < 0.2)
    return R, G, maska & ~test, test


def rmse(B, R, test):
    return float(np.sqrt(np.mean((np.clip(B, 1, 5)[test] - R[test]) ** 2)))


def main() -> None:
    R, G, oquv, test = yarat()
    n_u, n_i = R.shape
    u, i = np.nonzero(oquv)
    r = R[u, i]
    mu = r.mean()

    A = np.zeros((len(r), n_u + n_i))
    A[np.arange(len(r)), u] = 1
    A[np.arange(len(r)), n_u + i] = 1

    print("=== 1. Tenglamalar sistemasi ===")
    print(f"  A shakli {A.shape}, rank {np.linalg.matrix_rank(A)} / {A.shape[1]}")

    print("\n=== 2. Baza: umumiy o'rtacha ===")
    print(f"  mu = {mu:.3f}, test RMSE = {rmse(np.full(R.shape, mu), R, test):.4f}")

    print("\n=== 3. Bias modeli (Ridge alpha bo'yicha) ===")
    for alpha in [0.01, 1, 5, 20]:
        b = np.linalg.solve(A.T @ A + alpha * np.eye(n_u + n_i), A.T @ (r - mu))
        B = mu + b[:n_u, None] + b[None, n_u:]
        print(f"  alpha={alpha:>5}: test RMSE = {rmse(B, R, test):.4f}")

    b = np.linalg.solve(A.T @ A + 1.0 * np.eye(n_u + n_i), A.T @ (r - mu))
    bi = b[n_u:]
    print("\n=== 4. Eng yoqadigan va yoqmaydigan filmlar (b_i) ===")
    print(f"  top-3: {np.argsort(bi)[::-1][:3].tolist()}, pastki-3: {np.argsort(bi)[:3].tolist()}")
    print("  ⭐ Rank yetishmaydi — Ridge yagona, barqaror yechim beradi")


if __name__ == "__main__":
    main()

Natijaning muhim qismi:

text
=== 1. Tenglamalar sistemasi ===
  A shakli (2870, 460), rank 459 / 460

=== 2. Baza: umumiy o'rtacha ===
  mu = 3.217, test RMSE = 0.8776

=== 3. Bias modeli (Ridge alpha bo'yicha) ===
  alpha= 0.01: test RMSE = 0.6271
  alpha=    1: test RMSE = 0.6254
  alpha=    5: test RMSE = 0.6516
  alpha=   20: test RMSE = 0.7220

=== 4. Eng yoqadigan va yoqmaydigan filmlar (b_i) ===
  top-3: [48, 2, 41], pastki-3: [46, 34, 26]
  ⭐ Rank yetishmaydi — Ridge yagona, barqaror yechim beradi

Nima ko'rsatdi: 2.3, 2.5-bo'limlar.

Misol 3 — Yashirin omillar: qoldiqlar SVD si

python
"""Loyiha: bias + past rankli SVD (iterativ to'ldirish), k tanlash (real numpy)."""

import numpy as np


def yarat():
    rng = np.random.default_rng(42)
    n_u, n_i = 400, 60
    G = rng.dirichlet(np.full(4, 0.4), n_i)
    P = rng.normal(0, 1, (n_u, 4))
    bu = rng.normal(0, 0.4, n_u); bi = rng.normal(0, 0.4, n_i)
    R = np.clip(3.2 + bu[:, None] + bi[None, :] + 0.8 * P @ G.T
                + rng.normal(0, 0.35, (n_u, n_i)), 1, 5)
    maska = rng.random((n_u, n_i)) < 0.15
    test = maska & (rng.random((n_u, n_i)) < 0.2)
    return R, G, maska & ~test, test


def bias_model(R, oquv, alpha=1.0):
    n_u, n_i = R.shape
    u, i = np.nonzero(oquv)
    r = R[u, i]; mu = r.mean()
    A = np.zeros((len(r), n_u + n_i))
    A[np.arange(len(r)), u] = 1
    A[np.arange(len(r)), n_u + i] = 1
    b = np.linalg.solve(A.T @ A + alpha * np.eye(n_u + n_i), A.T @ (r - mu))
    return mu + b[:n_u, None] + b[None, n_u:]


def svd_qoldiq(R, B, oquv, k, qadam=30):
    Q = np.where(oquv, R - B, 0.0)
    for _ in range(qadam):
        U, s, Vt = np.linalg.svd(Q, full_matrices=False)
        Qk = U[:, :k] @ np.diag(s[:k]) @ Vt[:k]
        Q = np.where(oquv, R - B, Qk)
    return Qk


def main() -> None:
    R, G, oquv, test = yarat()
    rmse = lambda X: float(np.sqrt(np.mean((np.clip(X, 1, 5)[test] - R[test]) ** 2)))
    B = bias_model(R, oquv)

    print("=== 1. Bosqichlar ===")
    print(f"  umumiy o'rtacha: {rmse(np.full(R.shape, R[oquv].mean())):.4f}")
    print(f"  + bias:          {rmse(B):.4f}")

    print("\n=== 2. + SVD (k bo'yicha) ===")
    for k in [1, 2, 4, 8, 20]:
        print(f"  k={k:>2}: {rmse(B + svd_qoldiq(R, B, oquv, k)):.4f}")

    print("\n=== 3. Leakage xatosi: test kataklarini ham 'ma'lum' deb olish ===")
    hamma = oquv | test
    print(f"  k=4, test ichida o'qitilgan: {rmse(B + svd_qoldiq(R, B, hamma, 4)):.4f}  ← yolg'on yaxshi")
    print("  ⭐ Bias + SVD; k — test bilan; test maskasiga tegmang")


if __name__ == "__main__":
    main()

Natijaning muhim qismi:

text
=== 1. Bosqichlar ===
  umumiy o'rtacha: 0.8776
  + bias:          0.6254

=== 2. + SVD (k bo'yicha) ===
  k= 1: 0.5860
  k= 2: 0.5555
  k= 4: 0.5482
  k= 8: 0.6152
  k=20: 0.6167

=== 3. Leakage xatosi: test kataklarini ham 'ma'lum' deb olish ===
  k=4, test ichida o'qitilgan: 0.2677  ← yolg'on yaxshi
  ⭐ Bias + SVD; k — test bilan; test maskasiga tegmang

Nima ko'rsatdi: 2.4, 2.5, 2.7-bo'limlar.

Misol 4 — PCA xaritasi va tavsiya ro'yxati

python
"""Loyiha: film omillari PCA xaritasi va foydalanuvchi uchun top-5 tavsiya (real numpy)."""

import numpy as np

JANR = ["jangari", "drama", "komediya", "fantastika"]


def yarat():
    rng = np.random.default_rng(42)
    n_u, n_i = 400, 60
    G = rng.dirichlet(np.full(4, 0.4), n_i)
    P = rng.normal(0, 1, (n_u, 4))
    bu = rng.normal(0, 0.4, n_u); bi = rng.normal(0, 0.4, n_i)
    R = np.clip(3.2 + bu[:, None] + bi[None, :] + 0.8 * P @ G.T
                + rng.normal(0, 0.35, (n_u, n_i)), 1, 5)
    maska = rng.random((n_u, n_i)) < 0.15
    test = maska & (rng.random((n_u, n_i)) < 0.2)
    return R, G, maska & ~test, test


def main() -> None:
    R, G, oquv, test = yarat()
    n_u, n_i = R.shape
    u, i = np.nonzero(oquv)
    r = R[u, i]; mu = r.mean()
    A = np.zeros((len(r), n_u + n_i))
    A[np.arange(len(r)), u] = 1
    A[np.arange(len(r)), n_u + i] = 1
    b = np.linalg.solve(A.T @ A + 1.0 * np.eye(n_u + n_i), A.T @ (r - mu))
    B = mu + b[:n_u, None] + b[None, n_u:]
    Q = np.where(oquv, R - B, 0.0)
    for _ in range(30):
        U, s, Vt = np.linalg.svd(Q, full_matrices=False)
        Qk = U[:, :4] @ np.diag(s[:4]) @ Vt[:4]
        Q = np.where(oquv, R - B, Qk)
    yakuniy = np.clip(B + Qk, 1, 5)

    print("=== 1. Film omillari (Vt[:4].T) → PCA 2D ===")
    F = (np.diag(s[:4]) @ Vt[:4]).T                          # 60 × 4
    Fc = F - F.mean(axis=0)
    _, sf, Vf = np.linalg.svd(Fc, full_matrices=False)
    Z = Fc @ Vf[:2].T
    print(f"  2 komponenta ulushi: {(sf[:2] ** 2).sum() / (sf ** 2).sum():.1%}")

    print("\n=== 2. Xarita o'qlari va janrlar (korrelyatsiya) ===")
    for c in range(2):
        kor = [np.corrcoef(Z[:, c], G[:, j])[0, 1] for j in range(4)]
        eng = int(np.argmax(np.abs(kor)))
        print(f"  PC{c + 1}: eng bog'liq janr — {JANR[eng]} (r = {kor[eng]:+.2f})")

    print("\n=== 3. 7-foydalanuvchi uchun top-5 (ko'rilmaganlar) ===")
    foyd = 7
    korilgan = oquv[foyd]
    nomzod = np.where(~korilgan)[0]
    top = nomzod[np.argsort(yakuniy[foyd, nomzod])[::-1][:5]]
    print(f"  tavsiya: {top.tolist()}")
    print(f"  bashorat: {np.round(yakuniy[foyd, top], 2).tolist()}")
    print(f"  haqiqiy (yashirin): {np.round(R[foyd, top], 2).tolist()}")
    print(f"  foydalanuvchi o'rtachasi: {R[foyd].mean():.2f}")
    print("  ⭐ Xarita — tushuntirish; ro'yxat — mahsulot")


if __name__ == "__main__":
    main()

Natijaning muhim qismi:

text
=== 1. Film omillari (Vt[:4].T) → PCA 2D ===
  2 komponenta ulushi: 61.8%

=== 2. Xarita o'qlari va janrlar (korrelyatsiya) ===
  PC1: eng bog'liq janr — jangari (r = -0.70)
  PC2: eng bog'liq janr — komediya (r = +0.74)

=== 3. 7-foydalanuvchi uchun top-5 (ko'rilmaganlar) ===
  tavsiya: [40, 48, 57, 59, 25]
  bashorat: [4.79, 4.66, 4.65, 4.45, 4.41]
  haqiqiy (yashirin): [5.0, 5.0, 4.99, 5.0, 4.24]
  foydalanuvchi o'rtachasi: 4.24
  ⭐ Xarita — tushuntirish; ro'yxat — mahsulot

Nima ko'rsatdi: 2.6, 2.8-bo'limlar.


5. To'g'ri va noto'g'ri tushunishlar

Noto'g'ri fikr To'g'risi
"Bo'sh katak = 0 baho" Noma'lum
"SVD hammasini o'zi o'rganadi" Avval bias, keyin SVD
"Katta k — yaxshi" Test bilan tanlanadi
"Test kataklari to'ldirishda ishlatilsa mayli" Leakage — yolg'on natija
"Bias sistemasi yagona yechimli" Rank yetishmaydi — Ridge
"RMSE — yagona o'lchov" Top-k sifati, xilma-xillik
"Kontent o'xshashligi keraksiz" Sovuq start uchun zarur
"Omillar — aniq janrlar" Gipoteza; xarita bilan tekshiring

6. Keng tarqalgan xatolar va yechimlari

1. Noma'lumni 0 bilan

python
Q = np.where(oquv, R, 0)            # 0 — "eng yomon"               # ⚠️
Q = np.where(oquv, R - B, 0.0)      # qoldiqda 0 = "o'rtacha"       # ✅

2. Leakage

python
Q = np.where(oquv | test, R - B, Qk)                              # ⚠️
Q = np.where(oquv, R - B, Qk)                                     # ✅

3. Bias'siz SVD

python
Qk = svd_qoldiq(R, np.full(R.shape, mu), oquv, k)                 # ⚠️
Qk = svd_qoldiq(R, bias_model(R, oquv), oquv, k)                  # ✅

4. Ridge'siz bias sistemasi

python
b = np.linalg.solve(A.T @ A, A.T @ y)   # singulyar                 # ⚠️
b = np.linalg.solve(A.T @ A + alpha * np.eye(p), A.T @ y)         # ✅

5. Clip'siz

python
yakuniy = B + Qk                    # 5.7, 0.3 kabi                 # ⚠️
yakuniy = np.clip(B + Qk, 1, 5)                                   # ✅

6. Ko'rilgan filmni tavsiya qilish

python
top = np.argsort(yakuniy[u])[::-1][:5]                            # ⚠️
nomzod = np.where(~oquv[u])[0]; top = nomzod[np.argsort(yakuniy[u, nomzod])[::-1][:5]]  # ✅

7. k ni o'quv xatosi bilan

python
k = argmin(oquv_rmse)               # eng katta k                    # ⚠️
k = argmin(test_rmse)               # yoki CV                        # ✅

7. Integratsiya — bu bilim qayerda kerak bo'ladi

  • 10.1-10.9-darslar (o'tilgan): Chiziqli algebraning barcha qismlari
  • 8.8-dars (o'tilgan): Mustaqil test (o'quv/test ajratish)
  • 9.9-dars (o'tilgan): Baza model, baholash
  • ML qismlari: Tavsiya tizimlari, matritsa faktorizatsiyasi, embedding
  • Nazoratsiz o'rganish qismi: Klasterlash (film xaritasi)

8. Eng yaxshi amaliyotlar

  1. Ma'lum baholarni o'quv/test ga ajrating.

  2. Oddiy bazadan boshlang (o'rtacha).

  3. Bias'larni alohida modellang (Ridge).

  4. Qoldiqlarga past rankli SVD.

  5. k ni test bilan tanlang.

  6. Test maskasiga tegmang.

  7. Bashoratni [1, 5] ga qirqing.

  8. Xarita bilan modelni tushuntiring.


9. Amaliy topshiriq

Vazifa 1: Bashorat qiling

python
1.  # bo'sh katak nimani anglatadi?
2.  # baza model?
3.  # bias modeli formulasi?
4.  # bias sistemasi rank to'liqmi?
5.  # nega Ridge?
6.  # qoldiq = ?
7.  # SVD qaysi matritsaga?
8.  # k qanday tanlanadi?
9.  # leakage qayerda bo'lishi mumkin?
10. # kontent o'xshashligi qaysi muammoni hal qiladi?
11. # PCA xaritasi nima uchun?
12. # tavsiyada qaysi filmlar chiqariladi?
Javoblar
  1. Noma'lum (0 emas)
  2. Umumiy o'rtacha
  3. mu + b_u + b_i
  4. Yo'q (bittaga kam)
  5. Yagona, barqaror yechim; kam bahoni qisqartirish
  6. R - (mu + b_u + b_i)
  7. Qoldiqlar matritsasiga
  8. Test RMSE bilan
  9. To'ldirishda test kataklarini ishlatish
  10. Sovuq start (yangi film)
  11. Model omillarini tushuntirish
  12. Ko'rilganlar (o'quvdagi)

Vazifa 2: Xatolarni tuzating

python
1.  Q = np.where(oquv, R, 0)

2.  b = np.linalg.solve(A.T @ A, A.T @ (r - mu))

3.  Q = np.where(oquv | test, R - B, Qk)

4.  yakuniy = B + Qk

5.  top = np.argsort(yakuniy[u])[::-1][:5]
Javoblar
python
1.  Q = np.where(oquv, R - B, 0.0)

2.  b = np.linalg.solve(A.T @ A + 5 * np.eye(A.shape[1]), A.T @ (r - mu))

3.  Q = np.where(oquv, R - B, Qk)

4.  yakuniy = np.clip(B + Qk, 1, 5)

5.  nomzod = np.where(~oquv[u])[0]; top = nomzod[np.argsort(yakuniy[u, nomzod])[::-1][:5]]

Vazifa 3: Kontent tavsiyasi

Modellang:

  1. Foydalanuvchi profili (baholangan filmlar janrlarining vaznli o'rtachasi)
  2. Profilga kosinus
  3. Top-5 ko'rilmagan
  4. SVD tavsiyasi bilan solishtirish

Vazifa 4: Gibrid model

Modellang:

  1. SVD bashorati va kontent bashorati
  2. Vaznli aralashma (w, 1 - w)
  3. w ni test bilan tanlash
  4. Sovuq start foydalanuvchilarda natija

Vazifa 5: Baholash

Modellang:

  1. Test RMSE
  2. Top-5 ichida haqiqiy yuqori baholar ulushi
  3. Tavsiyalar xilma-xilligi (janrlar soni)
  4. Mashhurlik tarafkashligi

Vazifa 6: Integratsiya

Modellang:

  1. Kosinus (10.2)
  2. Ridge (10.6)
  3. SVD (10.8)
  4. PCA (10.9)

Vazifa 7: O'ylash

Tavsiya tizimi qancha aniq bo'lsa, foydalanuvchiga shuncha "o'xshash" narsalarni ko'rsatadi. Natijada foydalanuvchi faqat o'z didiga mos kontent ko'radi ("filtr pufagi"), yangi janrlarni kashf qilmaydi, mashhur filmlar yanada mashhur bo'ladi. RMSE bo'yicha "eng yaxshi" model biznes va jamiyat uchun eng yaxshi tizimmi? Tavsiya tizimini qanday o'lchash va loyihalash kerak?

Javob

Qisqa javob: yo'q. RMSE — faqat baholarni qanchalik aniq bashorat qilishni o'lchaydi. Foydalanuvchi qoniqishi, uzoq muddatli qiziqish, kontent ishlab chiqaruvchilari uchun adolat va jamiyatga ta'sir — boshqa o'lchovlar. Faqat aniqlikka optimallashtirilgan tizim xilma-xillikni kamaytiradi va o'z-o'zini kuchaytiruvchi tarafkashlik yaratadi.

1. Nega RMSE yetarli emas

RMSE o'lchaydi RMSE o'lchamaydi
Baho bashorati aniqligi Tavsiya ro'yxati foydaliligi
O'rtacha xato Yangilik, kashfiyot
Tarixiy baholar Uzoq muddatli qoniqish
Kontent yaratuvchilar uchun adolat

2. Filtr pufagi va mashhurlik

  • Model o'zi tavsiya qilgan narsa bo'yicha yangi baho oladi — halqa
  • Kam baholangan filmlar hech qachon ko'rsatilmaydi — "uzun dum" yo'qoladi
  • Did torayadi, platforma bir xillashadi

3. Qanday loyihalash

  • Aralash maqsad: aniqlik + xilma-xillik + yangilik
  • Kashfiyot: tavsiyalarning bir qismi — tasodifiy/yangi (explore)
  • Kontekst: vaqt, kayfiyat, maqsad
  • A/B test: real xulq-atvor (ko'rish vaqti, qaytish) bo'yicha baholash

4. Data Scientist qanday

  1. Bir nechta metrika: RMSE, top-k aniqlik, xilma-xillik, qamrov
  2. Oflayn baholash + onlayn A/B test
  3. Tarafkashlik va adolatni monitoring qiladi
  4. Biznes va foydalanuvchi manfaatini muvozanatlaydi

5. Xulosa

  1. Aniq model ≠ yaxshi tavsiya tizimi
  2. Filtr pufagi va mashhurlik tarafkashligi — tizimli xavf
  3. Xilma-xillik, yangilik, adolat — alohida maqsadlar
  4. Real ta'sir — A/B test bilan o'lchanadi

Nimani mustahkamlaydi: 2.5, 2.7-bo'limlar.


Xulosa

Bu darsda 10-qismning barcha bilimlarini film tavsiya tizimi loyihasida qo'lladik.

Eng muhim uch fikr:

  1. Matritsani to'ldirish. Baholar — siyrak, past rankli matritsa; noma'lum katak ≠ 0. Ma'lum baholar o'quv/test ga ajratiladi, har bosqich faqat test RMSE bilan baholanadi va baza (umumiy o'rtacha) bilan solishtiriladi.

  2. Uch qatlam. Kontent o'xshashligi (janr vektorlari, kosinus — sovuq start); bias modeli mu + b_u + b_i (eng kichik kvadratlar; rank yetishmaydi → Ridge); yashirin omillar (qoldiqlarning iterativ past rankli SVD si; k — test bilan; test maskasiga tegmaslik).

  3. Tushuntirish va mahsulot. PCA xaritasi — film omillari o'qlarining janrlar bilan bog'liqligi (model ma'noli narsa o'rganganmi); tavsiya — ko'rilmagan filmlar orasidan eng yuqori bashorat, [1, 5] ga qirqilgan. Aniqlik — yagona maqsad emas: xilma-xillik, yangilik, adolat.

10-qism yakunlandi! Chiziqli algebra — Data Science va ML ning tili: vektorlar, skalyar ko'paytma va proyeksiya, matritsalar va o'zgartirishlar, sistemalar va rank, eng kichik kvadratlar, xos vektorlar, SVD va PCA. Keyingi qismda Gipoteza testlarini chuqurlashtiramiz: xi-kvadrat, ANOVA, noparametrik testlar, A/B testni loyihalash va statistik quvvat.

Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!