import%20marimo%0A%0A__generated_with%20%3D%20%220.24.0%22%0Aapp%20%3D%20marimo.App()%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20import%20marimo%20as%20mo%0A%20%20%20%20import%20numpy%20as%20np%0A%20%20%20%20import%20plotly.graph_objects%20as%20go%0A%20%20%20%20from%20plotly.subplots%20import%20make_subplots%0A%0A%20%20%20%20return%20go%2C%20make_subplots%2C%20mo%2C%20np%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_()%3A%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_()%3A%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(np)%3A%0A%20%20%20%20%23%20Synthetic%20user-item%20matrix%20with%208%20users%20and%2010%20items%0A%20%20%20%20%23%20Categories%3A%20Items%200-2%20(Sci-Fi%20%2F%20Tech)%2C%20Items%203-5%20(Action%20%2F%20Thriller)%2C%20Items%206-9%20(Romance%20%2F%20Comedy)%0A%20%20%20%20user_names%20%3D%20%5Bf%22User%20%7Bi%2B1%7D%22%20for%20i%20in%20range(8)%5D%0A%20%20%20%20item_names%20%3D%20%5B%0A%20%20%20%20%20%20%20%20%22Sci-Fi%20A%22%2C%20%22Sci-Fi%20B%22%2C%20%22Tech%20Doc%22%2C%0A%20%20%20%20%20%20%20%20%22Action%20A%22%2C%20%22Action%20B%22%2C%20%22Thriller%22%2C%0A%20%20%20%20%20%20%20%20%22Romance%20A%22%2C%20%22Romance%20B%22%2C%20%22Comedy%20A%22%2C%20%22Comedy%20B%22%0A%20%20%20%20%5D%0A%0A%20%20%20%20%23%20Ground-truth%20binary%20interactions%20reflecting%20latent%20preference%20clusters%0A%20%20%20%20R%20%3D%20np.array(%5B%0A%20%20%20%20%20%20%20%20%5B1%2C%201%2C%201%2C%200%2C%201%2C%200%2C%200%2C%200%2C%200%2C%200%5D%2C%20%20%23%20User%201%3A%20Tech%2FSci-Fi%20enthusiast%0A%20%20%20%20%20%20%20%20%5B1%2C%200%2C%201%2C%201%2C%200%2C%200%2C%200%2C%200%2C%200%2C%200%5D%2C%20%20%23%20User%202%3A%20Sci-Fi%20%26%20Action%0A%20%20%20%20%20%20%20%20%5B0%2C%201%2C%201%2C%200%2C%200%2C%200%2C%200%2C%200%2C%200%2C%200%5D%2C%20%20%23%20User%203%3A%20Pure%20Sci-Fi%0A%20%20%20%20%20%20%20%20%5B0%2C%200%2C%200%2C%201%2C%201%2C%201%2C%200%2C%200%2C%201%2C%200%5D%2C%20%20%23%20User%204%3A%20Action%20%2F%20Thriller%0A%20%20%20%20%20%20%20%20%5B0%2C%200%2C%200%2C%201%2C%201%2C%201%2C%200%2C%200%2C%200%2C%200%5D%2C%20%20%23%20User%205%3A%20Pure%20Action%0A%20%20%20%20%20%20%20%20%5B0%2C%200%2C%200%2C%200%2C%200%2C%201%2C%201%2C%201%2C%201%2C%201%5D%2C%20%20%23%20User%206%3A%20Romance%20%2F%20Comedy%20%2F%20Light%20Thriller%0A%20%20%20%20%20%20%20%20%5B0%2C%200%2C%200%2C%200%2C%200%2C%200%2C%201%2C%201%2C%201%2C%200%5D%2C%20%20%23%20User%207%3A%20Romance%20%2F%20Comedy%0A%20%20%20%20%20%20%20%20%5B0%2C%200%2C%200%2C%200%2C%200%2C%200%2C%201%2C%200%2C%201%2C%201%5D%2C%20%20%23%20User%208%3A%20Romance%20%2F%20Comedy%0A%20%20%20%20%5D%2C%20dtype%3Dfloat)%0A%0A%20%20%20%20n_users%2C%20n_items%20%3D%20R.shape%0A%20%20%20%20nnz%20%3D%20np.count_nonzero(R)%0A%20%20%20%20sparsity_ratio%20%3D%201.0%20-%20(nnz%20%2F%20(n_users%20*%20n_items))%0A%20%20%20%20return%20R%2C%20item_names%2C%20n_items%2C%20n_users%2C%20nnz%2C%20sparsity_ratio%2C%20user_names%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(%0A%20%20%20%20R%2C%0A%20%20%20%20go%2C%0A%20%20%20%20item_names%2C%0A%20%20%20%20mo%2C%0A%20%20%20%20n_items%2C%0A%20%20%20%20n_users%2C%0A%20%20%20%20nnz%2C%0A%20%20%20%20sparsity_ratio%2C%0A%20%20%20%20user_names%2C%0A)%3A%0A%20%20%20%20_fig%20%3D%20go.Figure(%0A%20%20%20%20%20%20%20%20data%3Dgo.Heatmap(%0A%20%20%20%20%20%20%20%20%20%20%20%20z%3DR%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20x%3Ditem_names%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20y%3Duser_names%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20colorscale%3D%5B%5B0.0%2C%20%22%230f172a%22%5D%2C%20%5B1.0%2C%20%22%2338bdf8%22%5D%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20showscale%3DFalse%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20text%3D%5B%5Bf%22R%5B%7Bi%7D%2C%7Bj%7D%5D%20%3D%20%7Bint(R%5Bi%2C%20j%5D)%7D%22%20for%20j%20in%20range(n_items)%5D%20for%20i%20in%20range(n_users)%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20hoverinfo%3D%22text%22%2C%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20)%0A%0A%20%20%20%20for%20_i%20in%20range(n_users)%3A%0A%20%20%20%20%20%20%20%20for%20_j%20in%20range(n_items)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20_val%20%3D%20int(R%5B_i%2C%20_j%5D)%0A%20%20%20%20%20%20%20%20%20%20%20%20_fig.add_annotation(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20x%3Ditem_names%5B_j%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20y%3Duser_names%5B_i%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20text%3Dstr(_val)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20showarrow%3DFalse%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20font%3Ddict(color%3D%22%23ffffff%22%20if%20_val%20%3D%3D%201%20else%20%22%2364748b%22%2C%20size%3D12)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20)%0A%0A%20%20%20%20_fig.update_layout(%0A%20%20%20%20%20%20%20%20title%3Df%22Binary%20User-Item%20Interaction%20Matrix%20R%20(%7Bn_users%7D%20Users%20x%20%7Bn_items%7D%20Items%20%7C%20Sparsity%3A%20%7Bsparsity_ratio%3A.1%25%7D)%22%2C%0A%20%20%20%20%20%20%20%20xaxis_title%3D%22Catalog%20Items%22%2C%0A%20%20%20%20%20%20%20%20yaxis_title%3D%22Users%22%2C%0A%20%20%20%20%20%20%20%20yaxis_autorange%3D%22reversed%22%2C%0A%20%20%20%20%20%20%20%20template%3D%22plotly_white%22%2C%0A%20%20%20%20%20%20%20%20height%3D450%2C%0A%20%20%20%20%20%20%20%20margin%3Ddict(l%3D80%2C%20r%3D40%2C%20t%3D60%2C%20b%3D80)%2C%0A%20%20%20%20)%0A%0A%20%20%20%20_md%20%3D%20mo.md(%0A%20%20%20%20%20%20%20%20f%22%23%23%23%20Interaction%20Matrix%20Visualization%5Cn%5Cn%22%0A%20%20%20%20%20%20%20%20f%22Total%20elements%3A%20**%7Bn_users%20*%20n_items%7D**%20%7C%20%22%0A%20%20%20%20%20%20%20%20f%22Non-zero%20interactions%20(%24%5C%5C%7CR%5C%5C%7C_0%24)%3A%20**%7Bnnz%7D**%20%7C%20%22%0A%20%20%20%20%20%20%20%20f%22Sparsity%3A%20**%7Bsparsity_ratio%3A.2%25%7D**%22%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_()%3A%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_()%3A%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(R%2C%20np)%3A%0A%20%20%20%20%23%20Compute%20user-user%20co-occurrence%20and%20cosine%20similarity%0A%20%20%20%20C_user%20%3D%20R%20%40%20R.T%0A%20%20%20%20user_norms%20%3D%20np.linalg.norm(R%2C%20axis%3D1%2C%20keepdims%3DTrue)%0A%20%20%20%20user_norms_safe%20%3D%20np.where(user_norms%20%3D%3D%200%2C%201.0%2C%20user_norms)%0A%20%20%20%20S_user%20%3D%20(R%20%40%20R.T)%20%2F%20(user_norms_safe%20%40%20user_norms_safe.T)%0A%0A%20%20%20%20%23%20Compute%20item-item%20co-occurrence%20and%20cosine%20similarity%0A%20%20%20%20C_item%20%3D%20R.T%20%40%20R%0A%20%20%20%20item_norms%20%3D%20np.linalg.norm(R%2C%20axis%3D0%2C%20keepdims%3DTrue)%0A%20%20%20%20item_norms_safe%20%3D%20np.where(item_norms%20%3D%3D%200%2C%201.0%2C%20item_norms)%0A%20%20%20%20S_item%20%3D%20(R.T%20%40%20R)%20%2F%20(item_norms_safe.T%20%40%20item_norms_safe)%0A%0A%20%20%20%20%23%20Compute%20Jaccard%20similarity%20for%20users%0A%20%20%20%20J_user%20%3D%20np.zeros_like(C_user)%0A%20%20%20%20for%20_i%20in%20range(R.shape%5B0%5D)%3A%0A%20%20%20%20%20%20%20%20for%20_k%20in%20range(R.shape%5B0%5D)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20_intersection%20%3D%20C_user%5B_i%2C%20_k%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20_union%20%3D%20C_user%5B_i%2C%20_i%5D%20%2B%20C_user%5B_k%2C%20_k%5D%20-%20_intersection%0A%20%20%20%20%20%20%20%20%20%20%20%20J_user%5B_i%2C%20_k%5D%20%3D%20_intersection%20%2F%20_union%20if%20_union%20%3E%200%20else%200.0%0A%20%20%20%20return%20C_item%2C%20C_user%2C%20S_item%2C%20S_user%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(%0A%20%20%20%20C_item%2C%0A%20%20%20%20C_user%2C%0A%20%20%20%20S_item%2C%0A%20%20%20%20S_user%2C%0A%20%20%20%20go%2C%0A%20%20%20%20item_names%2C%0A%20%20%20%20make_subplots%2C%0A%20%20%20%20mo%2C%0A%20%20%20%20user_names%2C%0A)%3A%0A%20%20%20%20_fig%20%3D%20make_subplots(%0A%20%20%20%20%20%20%20%20rows%3D1%2C%0A%20%20%20%20%20%20%20%20cols%3D2%2C%0A%20%20%20%20%20%20%20%20subplot_titles%3D%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22User-User%20Cosine%20Similarity%20S_U%20%3D%20(R%20R')_norm%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22Item-Item%20Cosine%20Similarity%20S_V%20%3D%20(R'%20R)_norm%22%2C%0A%20%20%20%20%20%20%20%20%5D%2C%0A%20%20%20%20%20%20%20%20horizontal_spacing%3D0.15%2C%0A%20%20%20%20)%0A%0A%20%20%20%20_fig.add_trace(%0A%20%20%20%20%20%20%20%20go.Heatmap(%0A%20%20%20%20%20%20%20%20%20%20%20%20z%3DS_user%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20x%3Duser_names%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20y%3Duser_names%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20colorscale%3D%22Viridis%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20zmin%3D0.0%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20zmax%3D1.0%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20colorbar%3Ddict(title%3D%22Similarity%22%2C%20x%3D0.43%2C%20len%3D0.8)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20customdata%3DC_user%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20hovertemplate%3D%22User%20%25%7By%7D%20%26%20User%20%25%7Bx%7D%3Cbr%3ECosine%3A%20%25%7Bz%3A.3f%7D%3Cbr%3ECommon%20Items%3A%20%25%7Bcustomdata%7D%3Cextra%3E%3C%2Fextra%3E%22%2C%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20row%3D1%2C%0A%20%20%20%20%20%20%20%20col%3D1%2C%0A%20%20%20%20)%0A%0A%20%20%20%20_fig.add_trace(%0A%20%20%20%20%20%20%20%20go.Heatmap(%0A%20%20%20%20%20%20%20%20%20%20%20%20z%3DS_item%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20x%3Ditem_names%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20y%3Ditem_names%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20colorscale%3D%22Plasma%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20zmin%3D0.0%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20zmax%3D1.0%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20colorbar%3Ddict(title%3D%22Similarity%22%2C%20x%3D1.0%2C%20len%3D0.8)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20customdata%3DC_item%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20hovertemplate%3D%22Item%20%25%7By%7D%20%26%20Item%20%25%7Bx%7D%3Cbr%3ECosine%3A%20%25%7Bz%3A.3f%7D%3Cbr%3ECommon%20Users%3A%20%25%7Bcustomdata%7D%3Cextra%3E%3C%2Fextra%3E%22%2C%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20row%3D1%2C%0A%20%20%20%20%20%20%20%20col%3D2%2C%0A%20%20%20%20)%0A%0A%20%20%20%20_fig.update_layout(%0A%20%20%20%20%20%20%20%20title%3D%22Dual%20Projections%3A%20User%20Neighborhoods%20vs%20Item%20Co-occurrence%22%2C%0A%20%20%20%20%20%20%20%20template%3D%22plotly_white%22%2C%0A%20%20%20%20%20%20%20%20height%3D480%2C%0A%20%20%20%20%20%20%20%20margin%3Ddict(l%3D60%2C%20r%3D60%2C%20t%3D70%2C%20b%3D80)%2C%0A%20%20%20%20)%0A%20%20%20%20_fig.update_yaxes(autorange%3D%22reversed%22)%0A%0A%20%20%20%20_md%20%3D%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%23%20Dual%20Projections%20Heatmap%0A%0A%20%20%20%20Notice%20the%20clean%20block-diagonal%20structure%3A%0A%20%20%20%20-%20Users%201%20to%203%20cluster%20tightly%20together%20around%20Sci-Fi%2FTech%20items.%0A%20%20%20%20-%20Users%204%20and%205%20form%20an%20Action%20cluster.%0A%20%20%20%20-%20Users%206%20to%208%20form%20a%20Romance%2FComedy%20cluster.%0A%20%20%20%20-%20Item-item%20projections%20reveal%20high%20co-occurrence%20within%20content%20genres%2C%20enabling%20**item-to-item%20collaborative%20filtering**%20(e.g.%20Amazon's%20%22Customers%20who%20bought%20this%20also%20bought...%22).%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_()%3A%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(R%2C%20np)%3A%0A%20%20%20%20%23%20Perform%20full%20SVD%0A%20%20%20%20U_svd%2C%20Sigma_vals%2C%20Vt_svd%20%3D%20np.linalg.svd(R%2C%20full_matrices%3DFalse)%0A%0A%20%20%20%20%23%20Truncated%20approximations%20for%20ranks%20k%20%3D%201%2C%202%2C%203%0A%20%20%20%20ranks%20%3D%20%5B1%2C%202%2C%203%5D%0A%20%20%20%20R_hat_k%20%3D%20%7B%7D%0A%20%20%20%20frob_errors%20%3D%20%7B%7D%0A%20%20%20%20theoretical_errors%20%3D%20%7B%7D%0A%0A%20%20%20%20for%20_k%20in%20ranks%3A%0A%20%20%20%20%20%20%20%20_R_rec%20%3D%20U_svd%5B%3A%2C%20%3A_k%5D%20%40%20np.diag(Sigma_vals%5B%3A_k%5D)%20%40%20Vt_svd%5B%3A_k%2C%20%3A%5D%0A%20%20%20%20%20%20%20%20R_hat_k%5B_k%5D%20%3D%20_R_rec%0A%20%20%20%20%20%20%20%20_err%20%3D%20float(np.linalg.norm(R%20-%20_R_rec%2C%20ord%3D%22fro%22)%20**%202)%0A%20%20%20%20%20%20%20%20frob_errors%5B_k%5D%20%3D%20_err%0A%20%20%20%20%20%20%20%20theoretical_errors%5B_k%5D%20%3D%20float(np.sum(Sigma_vals%5B_k%3A%5D%20**%202))%0A%0A%20%20%20%20%23%20Shared%202D%20latent%20space%20embeddings%20(k%20%3D%202)%0A%20%20%20%20sqrt_sigma_2%20%3D%20np.sqrt(Sigma_vals%5B%3A2%5D)%0A%20%20%20%20P_2%20%3D%20U_svd%5B%3A%2C%20%3A2%5D%20*%20sqrt_sigma_2%20%20%23%20Shape%20(m%2C%202)%0A%20%20%20%20Q_2%20%3D%20Vt_svd%5B%3A2%2C%20%3A%5D.T%20*%20sqrt_sigma_2%20%20%23%20Shape%20(n%2C%202)%0A%20%20%20%20return%20(%0A%20%20%20%20%20%20%20%20P_2%2C%0A%20%20%20%20%20%20%20%20Q_2%2C%0A%20%20%20%20%20%20%20%20R_hat_k%2C%0A%20%20%20%20%20%20%20%20Sigma_vals%2C%0A%20%20%20%20%20%20%20%20frob_errors%2C%0A%20%20%20%20%20%20%20%20ranks%2C%0A%20%20%20%20%20%20%20%20theoretical_errors%2C%0A%20%20%20%20)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(Sigma_vals%2C%20frob_errors%2C%20np%2C%20ranks%2C%20theoretical_errors)%3A%0A%20%20%20%20_rows%20%3D%20%5B%5D%0A%20%20%20%20_total_energy%20%3D%20float(np.sum(Sigma_vals**2))%0A%20%20%20%20for%20_k%20in%20ranks%3A%0A%20%20%20%20%20%20%20%20_err%20%3D%20frob_errors%5B_k%5D%0A%20%20%20%20%20%20%20%20_theo%20%3D%20theoretical_errors%5B_k%5D%0A%20%20%20%20%20%20%20%20_var_explained%20%3D%201.0%20-%20(_err%20%2F%20_total_energy)%0A%20%20%20%20%20%20%20%20_rows.append(%0A%20%20%20%20%20%20%20%20%20%20%20%20f%22%7C%20Rank%20%7B_k%7D%20%7C%20%7BSigma_vals%5B_k-1%5D%3A.4f%7D%20%7C%20%7B_err%3A.4f%7D%20%7C%20%7B_theo%3A.4f%7D%20%7C%20%7B_var_explained%3A.2%25%7D%20%7C%22%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20_table_content%20%3D%20%22%5Cn%22.join(_rows)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(R%2C%20R_hat_k%2C%20go%2C%20item_names%2C%20make_subplots%2C%20mo%2C%20np%2C%20user_names)%3A%0A%20%20%20%20%23%20Plot%20original%20R%20vs%20Rank-2%20reconstruction%20vs%20Residual%0A%20%20%20%20_k%20%3D%202%0A%20%20%20%20_R_rec%20%3D%20R_hat_k%5B_k%5D%0A%20%20%20%20_residual%20%3D%20np.abs(R%20-%20_R_rec)%0A%0A%20%20%20%20_fig%20%3D%20make_subplots(%0A%20%20%20%20%20%20%20%20rows%3D1%2C%0A%20%20%20%20%20%20%20%20cols%3D3%2C%0A%20%20%20%20%20%20%20%20subplot_titles%3D%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22Original%20R%20(Binary%200%2F1)%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20f%22Rank-%7B_k%7D%20Approximation%20R_hat%20(SVD)%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22Absolute%20Residual%20%7CR%20-%20R_hat%7C%22%2C%0A%20%20%20%20%20%20%20%20%5D%2C%0A%20%20%20%20%20%20%20%20horizontal_spacing%3D0.08%2C%0A%20%20%20%20)%0A%0A%20%20%20%20_fig.add_trace(%0A%20%20%20%20%20%20%20%20go.Heatmap(%0A%20%20%20%20%20%20%20%20%20%20%20%20z%3DR%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20x%3Ditem_names%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20y%3Duser_names%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20colorscale%3D%22Blues%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20showscale%3DFalse%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20zmin%3D0%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20zmax%3D1%2C%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20row%3D1%2C%0A%20%20%20%20%20%20%20%20col%3D1%2C%0A%20%20%20%20)%0A%0A%20%20%20%20_fig.add_trace(%0A%20%20%20%20%20%20%20%20go.Heatmap(%0A%20%20%20%20%20%20%20%20%20%20%20%20z%3D_R_rec%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20x%3Ditem_names%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20y%3Duser_names%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20colorscale%3D%22RdBu_r%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20showscale%3DFalse%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20zmid%3D0.0%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20hovertemplate%3D%22User%20%25%7By%7D%2C%20Item%20%25%7Bx%7D%3Cbr%3EPredicted%20Affinity%3A%20%25%7Bz%3A.3f%7D%3Cextra%3E%3C%2Fextra%3E%22%2C%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20row%3D1%2C%0A%20%20%20%20%20%20%20%20col%3D2%2C%0A%20%20%20%20)%0A%0A%20%20%20%20_fig.add_trace(%0A%20%20%20%20%20%20%20%20go.Heatmap(%0A%20%20%20%20%20%20%20%20%20%20%20%20z%3D_residual%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20x%3Ditem_names%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20y%3Duser_names%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20colorscale%3D%22Reds%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20colorbar%3Ddict(title%3D%22Residual%22%2C%20x%3D1.0%2C%20len%3D0.8)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20zmin%3D0%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20zmax%3D1%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20hovertemplate%3D%22User%20%25%7By%7D%2C%20Item%20%25%7Bx%7D%3Cbr%3EResidual%20Error%3A%20%25%7Bz%3A.3f%7D%3Cextra%3E%3C%2Fextra%3E%22%2C%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20row%3D1%2C%0A%20%20%20%20%20%20%20%20col%3D3%2C%0A%20%20%20%20)%0A%0A%20%20%20%20_fig.update_layout(%0A%20%20%20%20%20%20%20%20title%3Df%22Matrix%20Factorization%3A%20Low-Rank%20Denoising%20and%20Recommendation%20Scoring%20(Rank%20k%3D%7B_k%7D)%22%2C%0A%20%20%20%20%20%20%20%20template%3D%22plotly_white%22%2C%0A%20%20%20%20%20%20%20%20height%3D420%2C%0A%20%20%20%20%20%20%20%20margin%3Ddict(l%3D60%2C%20r%3D60%2C%20t%3D60%2C%20b%3D60)%2C%0A%20%20%20%20)%0A%20%20%20%20_fig.update_yaxes(autorange%3D%22reversed%22)%0A%0A%20%20%20%20_md%20%3D%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%23%20Low-Rank%20Reconstruction%20and%20Imputation%0A%0A%20%20%20%20In%20collaborative%20filtering%2C%20positive%20entries%20in%20%24%5Chat%7BR%7D_k%24%20where%20%24R_%7Bij%7D%20%3D%200%24%20represent%20**novel%20recommendations**!%20For%20instance%2C%20if%20User%202%20has%20%24R_%7B2%2C%204%7D%20%3D%200%24%20(has%20not%20seen%20Action%20B)%20but%20%24%5Chat%7BR%7D_%7B2%2C%204%7D%20%3E%200.4%24%2C%20the%20system%20flags%20Action%20B%20as%20a%20high-affinity%20candidate.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(P_2%2C%20Q_2%2C%20go%2C%20item_names%2C%20mo%2C%20user_names)%3A%0A%20%20%20%20%23%20Plot%20Users%20and%20Items%20in%20the%20unified%202D%20Latent%20Factor%20Space%0A%20%20%20%20_fig%20%3D%20go.Figure()%0A%0A%20%20%20%20%23%20User%20coordinates%0A%20%20%20%20_fig.add_trace(%0A%20%20%20%20%20%20%20%20go.Scatter(%0A%20%20%20%20%20%20%20%20%20%20%20%20x%3DP_2%5B%3A%2C%200%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20y%3DP_2%5B%3A%2C%201%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mode%3D%22markers%2Btext%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20marker%3Ddict(size%3D14%2C%20color%3D%22%233b82f6%22%2C%20symbol%3D%22circle%22%2C%20line%3Ddict(width%3D2%2C%20color%3D%22%231e40af%22))%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20text%3Duser_names%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20textposition%3D%22top%20center%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20name%3D%22Users%20(P)%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20hovertemplate%3D%22%3Cb%3E%25%7Btext%7D%3C%2Fb%3E%3Cbr%3EFactor%201%3A%20%25%7Bx%3A.3f%7D%3Cbr%3EFactor%202%3A%20%25%7By%3A.3f%7D%3Cextra%3E%3C%2Fextra%3E%22%2C%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20)%0A%0A%20%20%20%20%23%20Item%20coordinates%0A%20%20%20%20_fig.add_trace(%0A%20%20%20%20%20%20%20%20go.Scatter(%0A%20%20%20%20%20%20%20%20%20%20%20%20x%3DQ_2%5B%3A%2C%200%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20y%3DQ_2%5B%3A%2C%201%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mode%3D%22markers%2Btext%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20marker%3Ddict(size%3D14%2C%20color%3D%22%23ef4444%22%2C%20symbol%3D%22diamond%22%2C%20line%3Ddict(width%3D2%2C%20color%3D%22%23991b1b%22))%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20text%3Ditem_names%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20textposition%3D%22bottom%20center%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20name%3D%22Items%20(Q)%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20hovertemplate%3D%22%3Cb%3E%25%7Btext%7D%3C%2Fb%3E%3Cbr%3EFactor%201%3A%20%25%7Bx%3A.3f%7D%3Cbr%3EFactor%202%3A%20%25%7By%3A.3f%7D%3Cextra%3E%3C%2Fextra%3E%22%2C%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20)%0A%0A%20%20%20%20%23%20Add%20zero-reference%20dashed%20axes%0A%20%20%20%20_fig.add_hline(y%3D0%2C%20line_dash%3D%22dash%22%2C%20line_color%3D%22%2394a3b8%22%2C%20opacity%3D0.6)%0A%20%20%20%20_fig.add_vline(x%3D0%2C%20line_dash%3D%22dash%22%2C%20line_color%3D%22%2394a3b8%22%2C%20opacity%3D0.6)%0A%0A%20%20%20%20_fig.update_layout(%0A%20%20%20%20%20%20%20%20title%3D%22Joint%20Latent%20Embedding%20Space%20(Users%20and%20Items%20in%20R%5E2)%22%2C%0A%20%20%20%20%20%20%20%20xaxis_title%3D%22Latent%20Factor%201%20(Genre%20Spectrum%3A%20Sci-Fi%20%2F%20Tech%20vs%20Romance%20%2F%20Comedy)%22%2C%0A%20%20%20%20%20%20%20%20yaxis_title%3D%22Latent%20Factor%202%20(Action%20%2F%20Thriller%20Intensity)%22%2C%0A%20%20%20%20%20%20%20%20template%3D%22plotly_white%22%2C%0A%20%20%20%20%20%20%20%20height%3D520%2C%0A%20%20%20%20%20%20%20%20margin%3Ddict(l%3D60%2C%20r%3D40%2C%20t%3D60%2C%20b%3D60)%2C%0A%20%20%20%20%20%20%20%20legend%3Ddict(x%3D0.02%2C%20y%3D0.98%2C%20bgcolor%3D%22rgba(255%2C255%2C255%2C0.8)%22)%2C%0A%20%20%20%20)%0A%0A%20%20%20%20_md%20%3D%20mo.md(r%22%22%22%0A%20%20%20%20---%0A%0A%20%20%20%20%23%23%20Unified%20Latent%20Embedding%20Geometry%0A%0A%20%20%20%20Because%20%24%5Chat%7BR%7D_k%20%3D%20P_k%20Q_k%5ET%24%2C%20the%20predicted%20affinity%20between%20user%20%24u_i%24%20and%20item%20%24v_j%24%20is%20the%20**inner%20product**%20of%20their%20latent%20factor%20vectors%3A%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Chat%7BR%7D_%7Bij%7D%20%3D%20%5Clangle%20p_i%2C%20q_j%20%5Crangle%20%3D%20%5C%7Cp_i%5C%7C_2%20%5C%7Cq_j%5C%7C_2%20%5Ccos%20%5Ctheta_%7Bij%7D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20When%20users%20and%20items%20are%20projected%20into%20the%20same%20shared%20coordinate%20system%2C%20users%20cluster%20directly%20alongside%20the%20items%20they%20prefer!%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_()%3A%0A%20%20%20%20return%0A%0A%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20app.run()%0A
603449e579b71875bf9549db132f62ad