Spaces:
Sleeping
Sleeping
Upload 9 files
Browse files
- .gitattributes +5 -0
- app.R +152 -58
- ibcf_model.rds +3 -0
- model_comparison.png +0 -0
- movies.rds +0 -0
- rating_matrix.rds +3 -0
- ratings_filtered.rds +3 -0
- svd_model.rds +3 -0
- topN_svd.rds +0 -0
- ubcf_model.rds +3 -0
.gitattributes
CHANGED
|
@@ -32,3 +32,8 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
|
| 32 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 33 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 34 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 32 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 33 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 34 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
| 35 |
+
ibcf_model.rds filter=lfs diff=lfs merge=lfs -text
|
| 36 |
+
rating_matrix.rds filter=lfs diff=lfs merge=lfs -text
|
| 37 |
+
ratings_filtered.rds filter=lfs diff=lfs merge=lfs -text
|
| 38 |
+
svd_model.rds filter=lfs diff=lfs merge=lfs -text
|
| 39 |
+
ubcf_model.rds filter=lfs diff=lfs merge=lfs -text
|
app.R
CHANGED
|
@@ -1,58 +1,152 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
library(
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
|
| 45 |
-
|
| 46 |
-
|
| 47 |
-
|
| 48 |
-
|
| 49 |
-
|
| 50 |
-
|
| 51 |
-
|
| 52 |
-
|
| 53 |
-
|
| 54 |
-
|
| 55 |
-
|
| 56 |
-
|
| 57 |
-
|
| 58 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# ==============================
|
| 2 |
+
# Load Libraries
|
| 3 |
+
# ==============================
|
| 4 |
+
library(shiny)
|
| 5 |
+
library(dplyr)
|
| 6 |
+
library(shinycssloaders)
|
| 7 |
+
library(shinyWidgets)
|
| 8 |
+
library(recosystem)
|
| 9 |
+
library(recommenderlab) # যদি প্রয়োজন হয়
|
| 10 |
+
|
| 11 |
+
# ==============================
|
| 12 |
+
# Load Data & Models
|
| 13 |
+
# ==============================
|
| 14 |
+
movies <- readRDS("movies.rds")
|
| 15 |
+
ratings_filtered <- readRDS("ratings_filtered.rds")
|
| 16 |
+
rating_matrix <- readRDS("rating_matrix.rds")
|
| 17 |
+
r <- readRDS("svd_model.rds")
|
| 18 |
+
ubcf_model <- readRDS("ubcf_model.rds")
|
| 19 |
+
ibcf_model <- readRDS("ibcf_model.rds")
|
| 20 |
+
topN_svd_list <- readRDS("topN_svd.rds")
|
| 21 |
+
|
| 22 |
+
# Ensure poster_url exists
|
| 23 |
+
if(!"poster_url" %in% colnames(movies)){
|
| 24 |
+
movies$poster_url <- "https://via.placeholder.com/150x225.png?text=No+Poster"
|
| 25 |
+
} else {
|
| 26 |
+
movies$poster_url <- ifelse(is.na(movies$poster_url),
|
| 27 |
+
"https://via.placeholder.com/150x225.png?text=No+Poster",
|
| 28 |
+
movies$poster_url)
|
| 29 |
+
}
|
| 30 |
+
|
| 31 |
+
# ==============================
|
| 32 |
+
# Recommendation Function
|
| 33 |
+
# ==============================
|
| 34 |
+
recommend_movies <- function(user_id, N = 10, model_type = "SVD") {
|
| 35 |
+
|
| 36 |
+
if(!(user_id %in% rownames(rating_matrix))) {
|
| 37 |
+
return(data.frame(title="No recommendations available",
|
| 38 |
+
poster_url="https://via.placeholder.com/150x225.png?text=No+Poster"))
|
| 39 |
+
}
|
| 40 |
+
|
| 41 |
+
if(model_type == "SVD") {
|
| 42 |
+
user_movies <- ratings_filtered %>% filter(userId == user_id) %>% pull(movieId)
|
| 43 |
+
unseen_movies <- setdiff(unique(ratings_filtered$movieId), user_movies)
|
| 44 |
+
|
| 45 |
+
if(length(unseen_movies) == 0) {
|
| 46 |
+
return(data.frame(title="No recommendations available",
|
| 47 |
+
poster_url="https://via.placeholder.com/150x225.png?text=No+Poster"))
|
| 48 |
+
}
|
| 49 |
+
|
| 50 |
+
unseen_df <- data.frame(user = user_id, item = unseen_movies)
|
| 51 |
+
pred_ratings <- r$predict(data_memory(user = unseen_df$user, item = unseen_df$item))
|
| 52 |
+
|
| 53 |
+
top_n_df <- data.frame(movieId = unseen_movies, pred_rating = pred_ratings) %>%
|
| 54 |
+
arrange(desc(pred_rating)) %>%
|
| 55 |
+
head(N)
|
| 56 |
+
|
| 57 |
+
recs <- movies %>% filter(movieId %in% top_n_df$movieId) %>%
|
| 58 |
+
select(title, poster_url)
|
| 59 |
+
|
| 60 |
+
} else if(model_type == "UBCF") {
|
| 61 |
+
pred <- predict(ubcf_model, rating_matrix[user_id,], type="topNList", n=N)
|
| 62 |
+
ids <- as(pred, "list")[[1]]
|
| 63 |
+
recs <- movies %>% filter(movieId %in% as.numeric(ids)) %>%
|
| 64 |
+
select(title, poster_url)
|
| 65 |
+
|
| 66 |
+
} else if(model_type == "IBCF") {
|
| 67 |
+
pred <- predict(ibcf_model, rating_matrix[user_id,], type="topNList", n=N)
|
| 68 |
+
ids <- as(pred, "list")[[1]]
|
| 69 |
+
recs <- movies %>% filter(movieId %in% as.numeric(ids)) %>%
|
| 70 |
+
select(title, poster_url)
|
| 71 |
+
|
| 72 |
+
} else {
|
| 73 |
+
stop("Invalid model_type. Choose 'SVD', 'UBCF', or 'IBCF'.")
|
| 74 |
+
}
|
| 75 |
+
|
| 76 |
+
if(nrow(recs) == 0) {
|
| 77 |
+
recs <- data.frame(title="No recommendations available",
|
| 78 |
+
poster_url="https://via.placeholder.com/150x225.png?text=No+Poster")
|
| 79 |
+
}
|
| 80 |
+
|
| 81 |
+
return(recs)
|
| 82 |
+
}
|
| 83 |
+
|
| 84 |
+
# ==============================
|
| 85 |
+
# Shiny UI
|
| 86 |
+
# ==============================
|
| 87 |
+
ui <- fluidPage(
|
| 88 |
+
tags$head(
|
| 89 |
+
tags$style(HTML("
|
| 90 |
+
.header-emoji { font-size:34px; font-weight:bold; background: linear-gradient(90deg, #ff4e50, #f9d423);
|
| 91 |
+
-webkit-background-clip:text; -webkit-text-fill-color:transparent; animation:gradient 3s ease infinite;}
|
| 92 |
+
@keyframes gradient {0% {background-position:0%} 50% {background-position:100%} 100% {background-position:0%}}
|
| 93 |
+
body { background-color: #fff0f5; }
|
| 94 |
+
.btn-success { background: linear-gradient(45deg, #ff6b6b, #fbc531); color: #fff; font-weight:bold; transition:transform 0.2s; }
|
| 95 |
+
.btn-success:hover { transform:scale(1.05); box-shadow:0px 4px 20px rgba(0,0,0,0.4); }
|
| 96 |
+
.poster img { transition: transform 0.3s; border-radius:10px; }
|
| 97 |
+
.poster img:hover { transform: scale(1.1) rotate(-2deg); box-shadow:0px 4px 20px rgba(0,0,0,0.5); }
|
| 98 |
+
.title { text-align:center; font-size:12px; font-weight:bold; margin-top:5px; }
|
| 99 |
+
.recommendation-scroll { max-height:600px; overflow-y:auto; }
|
| 100 |
+
.tags-overlay { position:relative; }
|
| 101 |
+
.tags-overlay span { position:absolute; top:5px; left:5px; font-size:16px; animation:sparkle 1.5s infinite; }
|
| 102 |
+
@keyframes sparkle { 0%,100% {opacity:1;} 50% {opacity:0.3;} }
|
| 103 |
+
"))
|
| 104 |
+
),
|
| 105 |
+
|
| 106 |
+
titlePanel(tags$div("🎥 MovieLens Recommendation System 🍿", class="header-emoji")),
|
| 107 |
+
|
| 108 |
+
sidebarLayout(
|
| 109 |
+
sidebarPanel(
|
| 110 |
+
numericInput("user_id", "Enter User ID:", value = 1, min = 1, max = nrow(rating_matrix)),
|
| 111 |
+
selectInput("model_type", "Select Model:", choices = c("SVD", "UBCF", "IBCF"), selected = "UBCF"),
|
| 112 |
+
numericInput("top_n", "Number of Recommendations:", value = 10, min = 1, max = 20),
|
| 113 |
+
actionBttn("recommend_btn", "GET RECOMMENDATIONS ✨", style="material-flat", color="success")
|
| 114 |
+
),
|
| 115 |
+
|
| 116 |
+
mainPanel(
|
| 117 |
+
h4("Recommended Movies 🎬:", style="color:darkblue;"),
|
| 118 |
+
withSpinner(uiOutput("recommendations_ui"), type=6)
|
| 119 |
+
)
|
| 120 |
+
)
|
| 121 |
+
)
|
| 122 |
+
|
| 123 |
+
# ==============================
|
| 124 |
+
# Shiny Server
|
| 125 |
+
# ==============================
|
| 126 |
+
server <- function(input, output) {
|
| 127 |
+
recommendations <- eventReactive(input$recommend_btn, {
|
| 128 |
+
recommend_movies(user_id=input$user_id, N=input$top_n, model_type=input$model_type)
|
| 129 |
+
})
|
| 130 |
+
|
| 131 |
+
output$recommendations_ui <- renderUI({
|
| 132 |
+
recs <- recommendations()
|
| 133 |
+
div(class="recommendation-scroll",
|
| 134 |
+
fluidRow(
|
| 135 |
+
lapply(1:nrow(recs), function(i){
|
| 136 |
+
column(2,
|
| 137 |
+
div(class="poster tags-overlay",
|
| 138 |
+
tags$img(src=recs$poster_url[i], width="150px", height="225px"),
|
| 139 |
+
tags$span("✨"),
|
| 140 |
+
tags$p(recs$title[i], class="title")
|
| 141 |
+
)
|
| 142 |
+
)
|
| 143 |
+
})
|
| 144 |
+
)
|
| 145 |
+
)
|
| 146 |
+
})
|
| 147 |
+
}
|
| 148 |
+
|
| 149 |
+
# ==============================
|
| 150 |
+
# Run Shiny App
|
| 151 |
+
# ==============================
|
| 152 |
+
shinyApp(ui = ui, server = server)
|
ibcf_model.rds
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:14ae7fb024b0df253b31accc279f84252fbc411cf92c8c31adcb7d1fa0636247
|
| 3 |
+
size 653670
|
model_comparison.png
ADDED
|
movies.rds
ADDED
|
Binary file (24.4 kB). View file
|
|
|
rating_matrix.rds
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:43de29f7b045c4e3bdabb4d689632c0cee2e31875825928babb5547504700dad
|
| 3 |
+
size 194301
|
ratings_filtered.rds
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:ab853be84aa3660d288fed026ddef4ed927977d7f367c1f69ce1ef4ea6b08d70
|
| 3 |
+
size 1089758
|
svd_model.rds
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:95fd43eda3744b0f6a59c89ff41f3b92404b6cf8edef0ed7fd9c491a60d5dc80
|
| 3 |
+
size 266028
|
topN_svd.rds
ADDED
|
Binary file (16.3 kB). View file
|
|
|
ubcf_model.rds
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:4316a1d9804ac27da75d4f0b8709c3881df400a41845d3dd88984c8607f3b285
|
| 3 |
+
size 974157
|