Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
B
BigData
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
GitLab community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Simon Majorczyk
BigData
Commits
16066790
Commit
16066790
authored
3 months ago
by
Simon Majorczyk
Browse files
Options
Downloads
Patches
Plain Diff
Changement CSS
parent
6df505c5
No related branches found
No related tags found
No related merge requests found
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
app_glob.py
+93
-0
93 additions, 0 deletions
app_glob.py
spotify-popularity-prediction-v2/app_glob.py
+94
-0
94 additions, 0 deletions
spotify-popularity-prediction-v2/app_glob.py
templates/index-glob.html
+225
-0
225 additions, 0 deletions
templates/index-glob.html
with
412 additions
and
0 deletions
app_glob.py
0 → 100644
+
93
−
0
View file @
16066790
from
flask
import
Flask
,
request
,
jsonify
,
render_template
import
pickle
import
pandas
as
pd
from
sklearn.preprocessing
import
StandardScaler
import
numpy
as
np
app
=
Flask
(
__name__
)
# Charger le modèle
with
open
(
'
random_forest_model_binaire.pkl
'
,
'
rb
'
)
as
model_file
:
rf
=
pickle
.
load
(
model_file
)
# Charger le scaler entraîné
with
open
(
'
scaler_binaire.pkl
'
,
'
rb
'
)
as
scaler_file
:
scaler
=
pickle
.
load
(
scaler_file
)
@app.route
(
'
/
'
)
def
home
():
return
render_template
(
'
index-glob.html
'
)
@app.route
(
'
/predict
'
,
methods
=
[
'
POST
'
])
def
predict
():
return
process_prediction
(
request
.
form
,
'
/predict
'
)
@app.route
(
'
/predict_sup0
'
,
methods
=
[
'
POST
'
])
def
predict_sup0
():
return
process_prediction
(
request
.
form
,
'
/predict_sup0
'
)
def
process_prediction
(
form_data
,
endpoint
):
data
=
form_data
.
to_dict
()
if
'
name
'
in
data
:
data
[
'
nb_caracteres_sans_espaces
'
]
=
len
(
data
[
'
name
'
].
replace
(
"
"
,
""
))
if
'
artists
'
in
data
:
data
[
'
nb_artistes
'
]
=
data
[
'
artists
'
].
count
(
'
,
'
)
+
1
data
[
'
featuring
'
]
=
int
(
data
[
'
nb_artistes
'
]
>
1
)
if
'
duration_ms
'
in
data
:
duration_ms
=
float
(
data
[
'
duration_ms
'
])
data
[
'
duree_minute
'
]
=
float
(
f
"
{
int
(
duration_ms
//
60000
)
}
.
{
int
((
duration_ms
%
60000
)
//
1000
)
:
02
d
}
"
)
if
'
year
'
in
data
:
year
=
int
(
data
[
'
year
'
])
data
[
'
categorie_annee
'
]
=
3
if
year
<
1954
else
2
if
year
<
2002
else
1
if
'
tempo
'
in
data
:
tempo
=
float
(
data
[
'
tempo
'
])
if
40
<=
tempo
<
60
:
data
[
'
categorie_tempo
'
]
=
1
elif
60
<=
tempo
<
66
:
data
[
'
categorie_tempo
'
]
=
2
elif
66
<=
tempo
<
76
:
data
[
'
categorie_tempo
'
]
=
3
elif
76
<=
tempo
<
108
:
data
[
'
categorie_tempo
'
]
=
4
elif
108
<=
tempo
<
120
:
data
[
'
categorie_tempo
'
]
=
5
elif
120
<=
tempo
<
163
:
data
[
'
categorie_tempo
'
]
=
6
elif
163
<=
tempo
<
200
:
data
[
'
categorie_tempo
'
]
=
7
elif
200
<=
tempo
<=
208
:
data
[
'
categorie_tempo
'
]
=
8
else
:
data
[
'
categorie_tempo
'
]
=
9
# Supprimer les clés non utilisées directement
data
.
pop
(
'
name
'
,
None
)
data
.
pop
(
'
artists
'
,
None
)
data
.
pop
(
'
duration_ms
'
,
None
)
# Convertir les valeurs en float si possible
for
key
in
data
:
try
:
data
[
key
]
=
float
(
data
[
key
])
except
ValueError
:
pass
expected_features
=
[
'
year
'
,
'
acousticness
'
,
'
danceability
'
,
'
energy
'
,
'
explicit
'
,
'
instrumentalness
'
,
'
key
'
,
'
liveness
'
,
'
loudness
'
,
'
mode
'
,
'
speechiness
'
,
'
tempo
'
,
'
valence
'
,
'
nb_caracteres_sans_espaces
'
,
'
nb_artistes
'
,
'
featuring
'
,
'
duree_minute
'
,
'
categorie_annee
'
,
'
categorie_tempo
'
]
input_data
=
pd
.
DataFrame
([[
data
.
get
(
key
,
0
)
for
key
in
expected_features
]],
columns
=
expected_features
)
missing_cols
=
[
col
for
col
in
expected_features
if
col
not
in
input_data
.
columns
]
if
missing_cols
:
return
jsonify
({
'
error
'
:
f
'
Missing features:
{
missing_cols
}
'
}),
400
input_data_scaled
=
scaler
.
transform
(
input_data
)
predictions
=
rf
.
predict
(
input_data_scaled
)
return
jsonify
({
'
predictions
'
:
int
(
predictions
[
0
])})
if
__name__
==
'
__main__
'
:
app
.
run
(
debug
=
True
)
This diff is collapsed.
Click to expand it.
spotify-popularity-prediction-v2/app_glob.py
0 → 100644
+
94
−
0
View file @
16066790
from
flask
import
Flask
,
request
,
jsonify
,
render_template
import
pickle
import
pandas
as
pd
from
sklearn.preprocessing
import
StandardScaler
import
numpy
as
np
app
=
Flask
(
__name__
)
# Charger le modèle
with
open
(
'
random_forest_model_binaire.pkl
'
,
'
rb
'
)
as
model_file
:
rf
=
pickle
.
load
(
model_file
)
# Charger le scaler entraîné
with
open
(
'
scaler_binaire.pkl
'
,
'
rb
'
)
as
scaler_file
:
scaler
=
pickle
.
load
(
scaler_file
)
@app.route
(
'
/
'
)
def
home
():
return
render_template
(
'
index-glob.html
'
)
@app.route
(
'
/predict
'
,
methods
=
[
'
POST
'
])
def
predict
():
# Récupérer les données du formulaire
data
=
request
.
form
.
to_dict
()
# Calculer automatiquement les features
if
'
name
'
in
data
:
data
[
'
nb_caracteres_sans_espaces
'
]
=
len
(
data
[
'
name
'
].
replace
(
"
"
,
""
))
if
'
artists
'
in
data
:
data
[
'
nb_artistes
'
]
=
data
[
'
artists
'
].
count
(
'
,
'
)
+
1
data
[
'
featuring
'
]
=
int
(
data
[
'
nb_artistes
'
]
>
1
)
if
'
duration_ms
'
in
data
:
duration_ms
=
float
(
data
[
'
duration_ms
'
])
data
[
'
duree_minute
'
]
=
float
(
f
"
{
int
(
duration_ms
//
60000
)
}
.
{
int
((
duration_ms
%
60000
)
//
1000
)
:
02
d
}
"
)
if
'
year
'
in
data
:
year
=
int
(
data
[
'
year
'
])
data
[
'
categorie_annee
'
]
=
3
if
year
<
1954
else
2
if
year
<
2002
else
1
if
'
tempo
'
in
data
:
tempo
=
float
(
data
[
'
tempo
'
])
if
40
<=
tempo
<
60
:
data
[
'
categorie_tempo
'
]
=
1
elif
60
<=
tempo
<
66
:
data
[
'
categorie_tempo
'
]
=
2
elif
66
<=
tempo
<
76
:
data
[
'
categorie_tempo
'
]
=
3
elif
76
<=
tempo
<
108
:
data
[
'
categorie_tempo
'
]
=
4
elif
108
<=
tempo
<
120
:
data
[
'
categorie_tempo
'
]
=
5
elif
120
<=
tempo
<
163
:
data
[
'
categorie_tempo
'
]
=
6
elif
163
<=
tempo
<
200
:
data
[
'
categorie_tempo
'
]
=
7
elif
200
<=
tempo
<=
208
:
data
[
'
categorie_tempo
'
]
=
8
else
:
data
[
'
categorie_tempo
'
]
=
9
# Supprimer les clés non utilisées directement
data
.
pop
(
'
name
'
,
None
)
data
.
pop
(
'
artists
'
,
None
)
data
.
pop
(
'
duration_ms
'
,
None
)
# Convertir les valeurs en float si possible
for
key
in
data
:
try
:
data
[
key
]
=
float
(
data
[
key
])
except
ValueError
:
pass
# Garder les valeurs non convertibles (ex: texte)
# Liste des features dans le bon ordre (comme lors de l'entraînement)
expected_features
=
[
'
year
'
,
'
acousticness
'
,
'
danceability
'
,
'
energy
'
,
'
explicit
'
,
'
instrumentalness
'
,
'
key
'
,
'
liveness
'
,
'
loudness
'
,
'
mode
'
,
'
speechiness
'
,
'
tempo
'
,
'
valence
'
,
'
nb_caracteres_sans_espaces
'
,
'
nb_artistes
'
,
'
featuring
'
,
'
duree_minute
'
,
'
categorie_annee
'
,
'
categorie_tempo
'
]
# S'assurer que les colonnes du DataFrame correspondent à celles du modèle, dans le bon ordre
input_data
=
pd
.
DataFrame
([[
data
.
get
(
key
,
0
)
for
key
in
expected_features
]],
columns
=
expected_features
)
# Vérifier que toutes les colonnes attendues sont présentes
missing_cols
=
[
col
for
col
in
expected_features
if
col
not
in
input_data
.
columns
]
if
missing_cols
:
return
jsonify
({
'
error
'
:
f
'
Missing features:
{
missing_cols
}
'
}),
400
# Normalisation des features
input_data_scaled
=
scaler
.
transform
(
input_data
)
# Prédiction
predictions
=
rf
.
predict
(
input_data_scaled
)
return
jsonify
({
'
predictions
'
:
int
(
predictions
[
0
])})
if
__name__
==
'
__main__
'
:
app
.
run
(
debug
=
True
)
This diff is collapsed.
Click to expand it.
templates/index-glob.html
0 → 100644
+
225
−
0
View file @
16066790
<!DOCTYPE html>
<html
lang=
"fr"
>
<head>
<meta
charset=
"UTF-8"
>
<meta
name=
"viewport"
content=
"width=device-width, initial-scale=1.0"
>
<title>
Prédiction de Popularité
</title>
<style>
body
{
font-family
:
Arial
,
sans-serif
;
margin
:
0
;
display
:
flex
;
}
/* Sidebar */
.sidebar
{
width
:
200px
;
background-color
:
#333
;
color
:
white
;
height
:
100vh
;
padding-top
:
20px
;
display
:
flex
;
flex-direction
:
column
;
align-items
:
center
;
}
.sidebar
button
{
width
:
80%
;
padding
:
10px
;
margin
:
10px
0
;
border
:
none
;
background
:
#444
;
color
:
white
;
cursor
:
pointer
;
font-size
:
16px
;
text-align
:
center
;
}
.sidebar
button
:hover
{
background
:
#555
;
}
.content
{
flex-grow
:
1
;
padding
:
20px
;
}
/* Cacher les sections par défaut */
.tab-content
{
display
:
none
;
}
.active
{
display
:
block
;
}
form
{
max-width
:
600px
;
margin
:
auto
;
}
label
{
display
:
block
;
margin-top
:
10px
;
font-weight
:
bold
;
}
input
[
type
=
"text"
],
input
[
type
=
"number"
]
{
width
:
100%
;
padding
:
8px
;
margin-top
:
5px
;
border
:
1px
solid
#ccc
;
border-radius
:
4px
;
}
button
{
margin-top
:
20px
;
padding
:
10px
20px
;
background-color
:
#4CAF50
;
color
:
white
;
border
:
none
;
border-radius
:
4px
;
cursor
:
pointer
;
}
button
:hover
{
background-color
:
#45a049
;
}
#result
{
margin-top
:
20px
;
font-size
:
1.2em
;
color
:
#555
;
}
</style>
</head>
<body>
<!-- Sidebar pour naviguer entre les onglets -->
<div
class=
"sidebar"
>
<button
onclick=
"showTab('tab1')"
>
Prédiction Standard
</button>
<button
onclick=
"showTab('tab2')"
>
Prédiction (>0)
</button>
</div>
<!-- Contenu principal -->
<div
class=
"content"
>
<h1>
Prédire la Popularité
</h1>
<!-- Formulaire 1 : Prédiction Standard -->
<div
id=
"tab1"
class=
"tab-content active"
>
<form
id=
"predictionForm"
>
<label
for=
"name"
>
Titre de la chanson :
</label>
<input
type=
"text"
id=
"name"
name=
"name"
required
>
<label
for=
"year"
>
Année (Sous format YYYY):
</label>
<input
type=
"number"
step=
"0.0001"
id=
"year"
name=
"year"
required
>
<label
for=
"acousticness"
>
Acousticness (0 à 1 jusqu'à 4 chiffres après la virgule):
</label>
<input
type=
"number"
step=
"0.0001"
id=
"acousticness"
name=
"acousticness"
required
>
<label
for=
"danceability"
>
Danceability (0 à 1 jusqu'à 4 chiffres après la virgule):
</label>
<input
type=
"number"
step=
"0.0001"
id=
"danceability"
name=
"danceability"
required
>
<label
for=
"energy"
>
Energy (0 à 1 jusqu'à 4 chiffres après la virgule):
</label>
<input
type=
"number"
step=
"0.0001"
id=
"energy"
name=
"energy"
required
>
<label
for=
"explicit"
>
Explicit (0 ou 1 en entier):
</label>
<input
type=
"number"
id=
"explicit"
name=
"explicit"
required
>
<label
for=
"instrumentalness"
>
Instrumentalness (0 à 1 jusqu'à 4 chiffres après la virgule):
</label>
<input
type=
"number"
step=
"0.0001"
id=
"instrumentalness"
name=
"instrumentalness"
required
>
<label
for=
"key"
>
Key (0 à 11 en chiffre entier):
</label>
<input
type=
"number"
id=
"key"
name=
"key"
required
>
<label
for=
"liveness"
>
Liveness (0 à 1 jusqu'à 4 chiffres après la virgule):
</label>
<input
type=
"number"
step=
"0.0001"
id=
"liveness"
name=
"liveness"
required
>
<label
for=
"loudness"
>
Loudness (0 à 1 jusqu'à 4 chiffres après la virgule):
</label>
<input
type=
"number"
step=
"0.0001"
id=
"loudness"
name=
"loudness"
required
>
<label
for=
"mode"
>
Mode (0 ou 1 en entier):
</label>
<input
type=
"number"
id=
"mode"
name=
"mode"
required
>
<label
for=
"speechiness"
>
Speechiness (0 à 1 jusqu'à 4 chiffres après la virgule):
</label>
<input
type=
"number"
step=
"0.0001"
id=
"speechiness"
name=
"speechiness"
required
>
<label
for=
"tempo"
>
Tempo (Sous format d'un nombre décimal jusqu'à 4 chiffres après la virgule):
</label>
<input
type=
"number"
step=
"0.0001"
id=
"tempo"
name=
"tempo"
required
>
<label
for=
"valence"
>
Valence (0 à 1 jusqu'à 4 chiffres après la virgule):
</label>
<input
type=
"number"
step=
"0.0001"
id=
"valence"
name=
"valence"
required
>
<button
type=
"button"
onclick=
"sendPrediction('/predict')"
>
Prédire
</button>
</form>
</div>
<!-- Formulaire 2 : Prédiction (>0) -->
<div
id=
"tab2"
class=
"tab-content"
>
<form
id=
"predictionFormSup0"
>
<label
for=
"name"
>
Titre de la chanson :
</label>
<input
type=
"text"
id=
"name"
name=
"name"
required
>
<label
for=
"year"
>
Année :
</label>
<input
type=
"number"
id=
"year"
name=
"year"
required
>
<label
for=
"acousticness"
>
Acousticness :
</label>
<input
type=
"number"
step=
"0.0001"
id=
"acousticness"
name=
"acousticness"
required
>
<label
for=
"danceability"
>
Danceability :
</label>
<input
type=
"number"
step=
"0.0001"
id=
"danceability"
name=
"danceability"
required
>
<label
for=
"energy"
>
Energy :
</label>
<input
type=
"number"
step=
"0.0001"
id=
"energy"
name=
"energy"
required
>
<label
for=
"explicit"
>
Explicit (0 ou 1) :
</label>
<input
type=
"number"
id=
"explicit"
name=
"explicit"
required
>
<label
for=
"instrumentalness"
>
Instrumentalness :
</label>
<input
type=
"number"
step=
"0.0001"
id=
"instrumentalness"
name=
"instrumentalness"
required
>
<label
for=
"key"
>
Key :
</label>
<input
type=
"number"
id=
"key"
name=
"key"
required
>
<label
for=
"liveness"
>
Liveness :
</label>
<input
type=
"number"
step=
"0.0001"
id=
"liveness"
name=
"liveness"
required
>
<label
for=
"loudness"
>
Loudness :
</label>
<input
type=
"number"
step=
"0.0001"
id=
"loudness"
name=
"loudness"
required
>
<label
for=
"mode"
>
Mode :
</label>
<input
type=
"number"
id=
"mode"
name=
"mode"
required
>
<label
for=
"speechiness"
>
Speechiness :
</label>
<input
type=
"number"
step=
"0.0001"
id=
"speechiness"
name=
"speechiness"
required
>
<label
for=
"tempo"
>
Tempo :
</label>
<input
type=
"number"
step=
"0.0001"
id=
"tempo"
name=
"tempo"
required
>
<label
for=
"valence"
>
Valence :
</label>
<input
type=
"number"
step=
"0.0001"
id=
"valence"
name=
"valence"
required
>
<button
type=
"button"
onclick=
"sendPrediction('/predict_sup0', 'predictionFormSup0')"
>
Prédire (>0)
</button>
</form>
</div>
<div
id=
"result"
></div>
</div>
<script>
// Fonction pour afficher un onglet et cacher l'autre
function
showTab
(
tabId
)
{
document
.
querySelectorAll
(
'
.tab-content
'
).
forEach
(
tab
=>
{
tab
.
style
.
display
=
"
none
"
;
});
document
.
getElementById
(
tabId
).
style
.
display
=
"
block
"
;
}
// Fonction pour envoyer la requête au bon endpoint
async
function
sendPrediction
(
endpoint
,
formId
=
"
predictionForm
"
)
{
const
form
=
document
.
getElementById
(
formId
);
const
formData
=
new
FormData
(
form
);
const
response
=
await
fetch
(
endpoint
,
{
method
:
"
POST
"
,
body
:
formData
});
const
result
=
await
response
.
json
();
document
.
getElementById
(
"
result
"
).
innerText
=
`Prédiction:
${
result
.
predictions
}
`
;
}
// Afficher l'onglet par défaut
showTab
(
'
tab1
'
);
</script>
</body>
</html>
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment