salekml commited on
Commit
1be3e52
·
verified ·
1 Parent(s): 7d83900

Upload 9 files

Browse files

![model_comparison](https://cdn-uploads.huggingface.co/production/uploads/68e2aa49f607766b3ebcf401/6UTRrDGRiuVs4CRE-qWFb.png)

.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
- library(shiny)
2
- library(bslib)
3
- library(dplyr)
4
- library(ggplot2)
5
-
6
- df <- readr::read_csv("penguins.csv")
7
- # Find subset of columns that are suitable for scatter plot
8
- df_num <- df |> select(where(is.numeric), -Year)
9
-
10
- ui <- page_sidebar(
11
- theme = bs_theme(bootswatch = "minty"),
12
- title = "Penguins explorer",
13
- sidebar = sidebar(
14
- varSelectInput("xvar", "X variable", df_num, selected = "Bill Length (mm)"),
15
- varSelectInput("yvar", "Y variable", df_num, selected = "Bill Depth (mm)"),
16
- checkboxGroupInput("species", "Filter by species",
17
- choices = unique(df$Species), selected = unique(df$Species)
18
- ),
19
- hr(), # Add a horizontal rule
20
- checkboxInput("by_species", "Show species", TRUE),
21
- checkboxInput("show_margins", "Show marginal plots", TRUE),
22
- checkboxInput("smooth", "Add smoother"),
23
- ),
24
- plotOutput("scatter")
25
- )
26
-
27
- server <- function(input, output, session) {
28
- subsetted <- reactive({
29
- req(input$species)
30
- df |> filter(Species %in% input$species)
31
- })
32
-
33
- output$scatter <- renderPlot(
34
- {
35
- p <- ggplot(subsetted(), aes(!!input$xvar, !!input$yvar)) +
36
- theme_light() +
37
- list(
38
- theme(legend.position = "bottom"),
39
- if (input$by_species) aes(color = Species),
40
- geom_point(),
41
- if (input$smooth) geom_smooth()
42
- )
43
-
44
- if (input$show_margins) {
45
- margin_type <- if (input$by_species) "density" else "histogram"
46
- p <- p |> ggExtra::ggMarginal(
47
- type = margin_type, margins = "both",
48
- size = 8, groupColour = input$by_species, groupFill = input$by_species
49
- )
50
- }
51
-
52
- p
53
- },
54
- res = 100
55
- )
56
- }
57
-
58
- shinyApp(ui, server)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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