salekml's picture
Upload 9 files
1be3e52 verified
# ==============================
# Load Libraries
# ==============================
library(shiny)
library(dplyr)
library(shinycssloaders)
library(shinyWidgets)
library(recosystem)
library(recommenderlab) # যদি প্রয়োজন হয়
# ==============================
# Load Data & Models
# ==============================
movies <- readRDS("movies.rds")
ratings_filtered <- readRDS("ratings_filtered.rds")
rating_matrix <- readRDS("rating_matrix.rds")
r <- readRDS("svd_model.rds")
ubcf_model <- readRDS("ubcf_model.rds")
ibcf_model <- readRDS("ibcf_model.rds")
topN_svd_list <- readRDS("topN_svd.rds")
# Ensure poster_url exists
if(!"poster_url" %in% colnames(movies)){
movies$poster_url <- "https://via.placeholder.com/150x225.png?text=No+Poster"
} else {
movies$poster_url <- ifelse(is.na(movies$poster_url),
"https://via.placeholder.com/150x225.png?text=No+Poster",
movies$poster_url)
}
# ==============================
# Recommendation Function
# ==============================
recommend_movies <- function(user_id, N = 10, model_type = "SVD") {
if(!(user_id %in% rownames(rating_matrix))) {
return(data.frame(title="No recommendations available",
poster_url="https://via.placeholder.com/150x225.png?text=No+Poster"))
}
if(model_type == "SVD") {
user_movies <- ratings_filtered %>% filter(userId == user_id) %>% pull(movieId)
unseen_movies <- setdiff(unique(ratings_filtered$movieId), user_movies)
if(length(unseen_movies) == 0) {
return(data.frame(title="No recommendations available",
poster_url="https://via.placeholder.com/150x225.png?text=No+Poster"))
}
unseen_df <- data.frame(user = user_id, item = unseen_movies)
pred_ratings <- r$predict(data_memory(user = unseen_df$user, item = unseen_df$item))
top_n_df <- data.frame(movieId = unseen_movies, pred_rating = pred_ratings) %>%
arrange(desc(pred_rating)) %>%
head(N)
recs <- movies %>% filter(movieId %in% top_n_df$movieId) %>%
select(title, poster_url)
} else if(model_type == "UBCF") {
pred <- predict(ubcf_model, rating_matrix[user_id,], type="topNList", n=N)
ids <- as(pred, "list")[[1]]
recs <- movies %>% filter(movieId %in% as.numeric(ids)) %>%
select(title, poster_url)
} else if(model_type == "IBCF") {
pred <- predict(ibcf_model, rating_matrix[user_id,], type="topNList", n=N)
ids <- as(pred, "list")[[1]]
recs <- movies %>% filter(movieId %in% as.numeric(ids)) %>%
select(title, poster_url)
} else {
stop("Invalid model_type. Choose 'SVD', 'UBCF', or 'IBCF'.")
}
if(nrow(recs) == 0) {
recs <- data.frame(title="No recommendations available",
poster_url="https://via.placeholder.com/150x225.png?text=No+Poster")
}
return(recs)
}
# ==============================
# Shiny UI
# ==============================
ui <- fluidPage(
tags$head(
tags$style(HTML("
.header-emoji { font-size:34px; font-weight:bold; background: linear-gradient(90deg, #ff4e50, #f9d423);
-webkit-background-clip:text; -webkit-text-fill-color:transparent; animation:gradient 3s ease infinite;}
@keyframes gradient {0% {background-position:0%} 50% {background-position:100%} 100% {background-position:0%}}
body { background-color: #fff0f5; }
.btn-success { background: linear-gradient(45deg, #ff6b6b, #fbc531); color: #fff; font-weight:bold; transition:transform 0.2s; }
.btn-success:hover { transform:scale(1.05); box-shadow:0px 4px 20px rgba(0,0,0,0.4); }
.poster img { transition: transform 0.3s; border-radius:10px; }
.poster img:hover { transform: scale(1.1) rotate(-2deg); box-shadow:0px 4px 20px rgba(0,0,0,0.5); }
.title { text-align:center; font-size:12px; font-weight:bold; margin-top:5px; }
.recommendation-scroll { max-height:600px; overflow-y:auto; }
.tags-overlay { position:relative; }
.tags-overlay span { position:absolute; top:5px; left:5px; font-size:16px; animation:sparkle 1.5s infinite; }
@keyframes sparkle { 0%,100% {opacity:1;} 50% {opacity:0.3;} }
"))
),
titlePanel(tags$div("🎥 MovieLens Recommendation System 🍿", class="header-emoji")),
sidebarLayout(
sidebarPanel(
numericInput("user_id", "Enter User ID:", value = 1, min = 1, max = nrow(rating_matrix)),
selectInput("model_type", "Select Model:", choices = c("SVD", "UBCF", "IBCF"), selected = "UBCF"),
numericInput("top_n", "Number of Recommendations:", value = 10, min = 1, max = 20),
actionBttn("recommend_btn", "GET RECOMMENDATIONS ✨", style="material-flat", color="success")
),
mainPanel(
h4("Recommended Movies 🎬:", style="color:darkblue;"),
withSpinner(uiOutput("recommendations_ui"), type=6)
)
)
)
# ==============================
# Shiny Server
# ==============================
server <- function(input, output) {
recommendations <- eventReactive(input$recommend_btn, {
recommend_movies(user_id=input$user_id, N=input$top_n, model_type=input$model_type)
})
output$recommendations_ui <- renderUI({
recs <- recommendations()
div(class="recommendation-scroll",
fluidRow(
lapply(1:nrow(recs), function(i){
column(2,
div(class="poster tags-overlay",
tags$img(src=recs$poster_url[i], width="150px", height="225px"),
tags$span("✨"),
tags$p(recs$title[i], class="title")
)
)
})
)
)
})
}
# ==============================
# Run Shiny App
# ==============================
shinyApp(ui = ui, server = server)