Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2,261 changes: 2,261 additions & 0 deletions ML_Flask2.ipynb

Large diffs are not rendered by default.

2,315 changes: 2,315 additions & 0 deletions ML_Flask3.ipynb

Large diffs are not rendered by default.

250,001 changes: 250,001 additions & 0 deletions data/raw/job_salary_prediction_dataset.csv

Large diffs are not rendered by default.

Binary file added models/salary_predictor_model.sav
Binary file not shown.
2 changes: 2 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,5 @@ seaborn>=0.12.2
sqlalchemy>=2.0.38
sympy>=1.10.1
xgboost
gunicorn>=25.3.0
Flask==3.1.0
29 changes: 26 additions & 3 deletions src/app.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,27 @@
from utils import db_connect
engine = db_connect()
from flask import Flask, request, render_template
import os
import joblib
app = Flask(__name__)

# your code here
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
model_path = os.path.join(BASE_DIR, "models", "salary_predictor_model.sav")

model = joblib.load(model_path)
#model = load(open("/workspaces/Appwebs/models/salary_predictor_model.sav", "rb"))


@app.route("/", methods = ["GET", "POST"])
def index():
prediction = None
if request.method == "POST":

val1 = float(request.form["val1"])
val2 = float(request.form["val2"])
val3 = float(request.form["val3"])

data = [[val1, val2, val3]]
salary = model.predict(data)[0]
rounded_salary = round(salary, -3)
prediction = f"${rounded_salary:,.0f} dólares"

return render_template("index.html", prediction=prediction)
62 changes: 62 additions & 0 deletions src/app2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
from flask import Flask, request, render_template
import os
from joblib import load

app = Flask(__name__)

model =load(open("../models/salary_predictor_model.sav","rb"))
print("modelo cargado")


# Generar opciones dinámicas desde dataset
#options = {
# "job_title": sorted(df["job_title"].dropna().unique()),
# "education_level": sorted(df["education_level"].dropna().unique()),
#"industry": sorted(df["industry"].dropna().unique()),
#"company_size": sorted(df["company_size"].dropna().unique()),
#"location": sorted(df["location"].dropna().unique())
#}

def preprocess_input(data):
df_input = pd.DataFrame([data])

if columns is not None:
df_input = pd.get_dummies(df_input)

for col in columns:
if col not in df_input:
df_input[col] = 0

df_input = df_input[columns]

return df_input


@app.route("/", methods=["GET", "POST"])
def index():
prediction = None

if request.method == "POST":
try:
input_data = {
"job_title": request.form.get("job_title"),
"experience_years": int(request.form.get("experience_years")),
"education_level": request.form.get("education_level"),
"skills_count": int(request.form.get("skills_count")),
"industry": request.form.get("industry"),
"company_size": request.form.get("company_size"),
"location": request.form.get("location"),
"remote_work": int(request.form.get("remote_work")),
"certifications": int(request.form.get("certifications"))
}

processed = preprocess_input(input_data)
prediction = round(model.predict(processed)[0], 2)

except Exception as e:
prediction = f"Error: {e}"

return render_template("index.html", prediction=prediction, options=options)

if __name__ == "__main__":
app.run(debug=True)
Empty file added src/models/.gitkeep
Empty file.
Binary file added src/models/salary_predictor_model.sav
Binary file not shown.
18 changes: 18 additions & 0 deletions src/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
ipyleaflet>=0.14.0
ipywidgets>=7.7.1
matplotlib>=3.7.0
numpy>=1.24.2
opencv-python>=4.1.2
pandas>=2.3.3
psycopg2-binary>=2.9.3
pymysql>=1.0.2
python-dotenv>=0.20.0
requests>=2.27.1
scikit-learn
seaborn>=0.12.2
sqlalchemy>=2.0.38
sympy>=1.10.1
xgboost
gunicorn>=25.3.0
Flask==3.1.0
joblib==1.3.2
107 changes: 107 additions & 0 deletions src/templates/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
<!DOCTYPE html>
<html>
<head>
<title>Predicción de Salarios</title>
<style>
body {
font-family: Arial, sans-serif;
background-color: #f4f4f4;
margin: 0;
padding: 0;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
.container {
background-color: white;
padding: 40px;
border-radius: 10px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
max-width: 500px;
width: 100%;
}
h2 {
text-align: center;
color: #333;
}
form {
display: flex;
flex-direction: column;
}
select, input[type="submit"] {
margin: 10px 0;
padding: 10px;
border: 1px solid #ccc;
border-radius: 5px;
font-size: 16px;
}
input[type="submit"] {
background-color: #4CAF50;
color: white;
cursor: pointer;
transition: background-color 0.3s;
}
input[type="submit"]:hover {
background-color: #45a049;
}
.prediction {
text-align: center;
margin-top: 20px;
font-size: 18px;
color: #333;
}
</style>
</head>
<body>
<div class="container">
<h2>Predicción de Salarios</h2>

<form action="/" method="post">
<label for="trabajo">Trabajo:</label>
<select name="val1" id="trabajo" required>
<option value="">Selecciona un trabajo</option>
<option value="0">AI Engineer</option>
<option value="5">Data Analyst</option>
<option value="8">Frontend Developer</option>
<option value="2">Business Analyst</option>
<option value="10">Product Manager</option>
<option value="1">Backend Developer</option>
<option value="9">Machine Learning Engineer</option>
<option value="7">DevOps Engineer</option>
<option value="11">Software Engineer</option>
<option value="4">Cybersecurity Analyst</option>
<option value="6">Data Scientist</option>
<option value="3">Cloud Engineer</option>
</select><br><br>

<label for="experiencia">Años de experiencia:</label>
<select name="val2" id="experiencia" required>
<option value="">Selecciona años de experiencia</option>
{% for i in range(0, 21) %}
<option value="{{ i }}">{{ i }}</option>
{% endfor %}
</select><br><br>

<label for="educacion">Educación:</label>
<select name="val3" id="educacion" required>
<option value="">Selecciona nivel de educación</option>
<option value="2">High School</option>
<option value="1">Diploma</option>
<option value="0">Bachelor</option>
<option value="3">Master</option>
<option value="4">PhD</option>
</select><br><br>

<input type="submit" value="Predecir Salario">
</form>

{% if prediction %}
<div class="prediction">
<h3>Predicción: {{ prediction }}</h3>
</div>
{% endif %}
</div>
</body>
</html>

140 changes: 140 additions & 0 deletions src/templates/index2.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<title>Predicción de Salarios</title>
<style>
body {
font-family: Arial, sans-serif;
background: #f4f6f8;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
.container {
background: white;
padding: 25px;
border-radius: 10px;
width: 350px;
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
}
h2 {
text-align: center;
}
label {
margin-top: 10px;
display: block;
}
input, select, button {
width: 100%;
padding: 8px;
margin-top: 5px;
border-radius: 6px;
border: 1px solid #ccc;
}
button {
background: #007BFF;
color: white;
border: none;
margin-top: 15px;
cursor: pointer;
}
button:hover {
background: #0056b3;
}
#result {
margin-top: 15px;
font-weight: bold;
text-align: center;
}
</style>
</head>
<body>

<div class="container">
<h2>Predicción de Salario</h2>

<form id="salaryForm">
<label>Job Title</label>
<input type="text" id="job_title" required>

<label>Años de Experiencia</label>
<input type="number" id="experience_years" required>

<label>Educación</label>
<select id="education_level">
<option value="High School">High School</option>
<option value="Bachelor">Bachelor</option>
<option value="Master">Master</option>
<option value="PhD">PhD</option>
</select>

<label>Cantidad de Skills</label>
<input type="number" id="skills_count">

<label>Industria</label>
<input type="text" id="industry">

<label>Tamaño Empresa</label>
<select id="company_size">
<option value="Small">Small</option>
<option value="Medium">Medium</option>
<option value="Large">Large</option>
</select>

<label>Ubicación</label>
<input type="text" id="location">

<label>Trabajo Remoto</label>
<select id="remote_work">
<option value="0">No</option>
<option value="1">Sí</option>
</select>

<label>Certificaciones</label>
<input type="number" id="certifications">

<button type="submit">Predecir</button>
</form>

<div id="result"></div>
</div>

<script>
document.getElementById("salaryForm").addEventListener("submit", async function(e) {
e.preventDefault();

const data = {
job_title: document.getElementById("job_title").value,
experience_years: parseInt(document.getElementById("experience_years").value),
education_level: document.getElementById("education_level").value,
skills_count: parseInt(document.getElementById("skills_count").value),
industry: document.getElementById("industry").value,
company_size: document.getElementById("company_size").value,
location: document.getElementById("location").value,
remote_work: parseInt(document.getElementById("remote_work").value),
certifications: parseInt(document.getElementById("certifications").value)
};

try {
const response = await fetch("http://localhost:5000/predict", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(data)
});

const result = await response.json();
document.getElementById("result").innerText = "Salario estimado: $" + result.prediction;

} catch (error) {
document.getElementById("result").innerText = "Error al predecir";
console.error(error);
}
});
</script>

</body>
</html>