Last active
December 24, 2020 12:10
-
-
Save amattu2/c5adf92e3b83f2c59c604fdae6e0dc44 to your computer and use it in GitHub Desktop.
This is a simple machine learning model trainer UI kit. I used it to clean/setup multi-label classification model datasets. Based off of HTML5/CSS3, JavaScript (ES6), PHP (>= ~6.0)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- phpMyAdmin SQL Dump | |
-- version 4.9.7deb1 | |
-- https://www.phpmyadmin.net/ | |
-- | |
-- Host: localhost:3306 | |
-- Generation Time: Dec 24, 2020 at 07:08 AM | |
-- Server version: 8.0.22-0ubuntu0.20.10.2 | |
-- PHP Version: 7.4.9 | |
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; | |
SET AUTOCOMMIT = 0; | |
START TRANSACTION; | |
SET time_zone = "+00:00"; | |
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; | |
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; | |
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; | |
/*!40101 SET NAMES utf8mb4 */; | |
-- | |
-- Database: `multi_label_appointments_model` | |
-- | |
-- -------------------------------------------------------- | |
-- | |
-- Table structure for table `2019_Model` | |
-- | |
CREATE TABLE `2019_Model` ( | |
`ID` int NOT NULL, | |
`Tech` varchar(9) DEFAULT NULL, | |
`Service` varchar(25) DEFAULT NULL, | |
`Comments` varchar(279) DEFAULT NULL, | |
`mechanical` int NOT NULL DEFAULT '0', | |
`bodywork` int NOT NULL DEFAULT '0', | |
`diagnostic` int NOT NULL DEFAULT '0', | |
`suspension` int NOT NULL DEFAULT '0', | |
`engine` int NOT NULL DEFAULT '0', | |
`transmission` int NOT NULL DEFAULT '0', | |
`exhaust` int NOT NULL DEFAULT '0', | |
`electrical` int NOT NULL DEFAULT '0', | |
`brakes` int NOT NULL DEFAULT '0', | |
`tires` int NOT NULL DEFAULT '0' | |
) ENGINE=InnoDB DEFAULT CHARSET=utf8; | |
-- | |
-- Indexes for dumped tables | |
-- | |
-- | |
-- Indexes for table `2019_Model` | |
-- | |
ALTER TABLE `2019_Model` | |
ADD PRIMARY KEY (`ID`); | |
-- | |
-- AUTO_INCREMENT for dumped tables | |
-- | |
-- | |
-- AUTO_INCREMENT for table `2019_Model` | |
-- | |
ALTER TABLE `2019_Model` | |
MODIFY `ID` int NOT NULL AUTO_INCREMENT; | |
COMMIT; | |
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; | |
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; | |
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/* | |
Produced 2020 | |
By https://amattu.com/links/github | |
Copy Alec M. | |
*/ | |
/* | |
This file is responsible for: | |
- Fetching row data from a MySQL server | |
- Saving/updating trained model data | |
*/ | |
// Files | |
require("db.php"); | |
// Function navigator | |
if ($_GET && is_numeric($_GET['ID'])) { | |
echo get_result($_GET['ID']); | |
} else if ($_POST && isset($_POST['row'])) { | |
echo save_result($_POST['row']); | |
} | |
/** | |
Get row by ID | |
**/ | |
function get_result($ID) { | |
if ($ID < 1) { | |
return false; | |
} | |
global $con; | |
$result = Array(); | |
if ($stmt = $con->prepare("SELECT * FROM 2019_Model WHERE ID = ?")) { | |
$stmt->bind_param("i", $ID); | |
$stmt->bind_result($ID, $Tech, $Service, $Comments, $mechanical, $bodywork, $diagnostic, $suspension, $engine, $transmission, $exhaust, $electrical, $brakes, $tires); | |
if (!$stmt->execute()) { | |
die("Unable to execute STMT"); | |
} | |
$result = Array(); | |
while ($stmt->fetch()) { | |
$result = Array( | |
"ID" => $ID, | |
"Tech" => $Tech, | |
"Service" => $Service, | |
"Comments" => $Comments, | |
"Fields" => Array( | |
"mechanical" => $mechanical, | |
"bodywork" => $bodywork, | |
"diagnostic" => $diagnostic, | |
"suspension" => $suspension, | |
"engine" => $engine, | |
"transmission" => $transmission, | |
"exhaust" => $exhaust, | |
"electrical" => $electrical, | |
"brakes" => $brakes, | |
"tires" => $tires | |
) | |
); | |
} | |
$stmt->close(); | |
$con->close(); | |
return json_encode($result); | |
} else { die("Unable to prepare STMT"); } | |
} | |
/** | |
Save row by JSON object | |
**/ | |
function save_result($row) { | |
global $con; | |
$row = json_decode($row, true); | |
if ($stmt = $con->prepare("UPDATE `2019_Model` SET `Comments` = ?, `mechanical` = ?,`bodywork` = ?, `diagnostic` = ?, `suspension` = ?, `engine` = ?, `transmission` = ?, `exhaust` = ?, `electrical` = ?, `brakes` = ?, `tires` = ? WHERE `ID` = ? LIMIT 1")) { | |
$stmt->bind_param("siiiiiiiiiii", | |
$row["Comments"], | |
$row["Fields"]["mechanical"], | |
$row["Fields"]["bodywork"], | |
$row["Fields"]["diagnostic"], | |
$row["Fields"]["suspension"], | |
$row["Fields"]["engine"], | |
$row["Fields"]["transmission"], | |
$row["Fields"]["exhaust"], | |
$row["Fields"]["electrical"], | |
$row["Fields"]["brakes"], | |
$row["Fields"]["tires"], | |
$row["ID"] | |
); | |
if ($stmt->execute()) { | |
return 1; | |
} else { | |
return 0; | |
} | |
$stmt->close(); | |
$con->close(); | |
} else { die("unable to prepare update"); } | |
} | |
?> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/* | |
Produced 2020 | |
By https://amattu.com/links/github | |
Copy Alec M. | |
*/ | |
// Variables | |
$con = mysqli_connect("localhost", "ml_appointment_trainer", "password", "multi_label_appointments_model"); | |
// Check database connection | |
if (mysqli_connect_errno()) { die("unable to connect to database"); } | |
?> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en" dir="ltr"> | |
<!-- | |
Produced 2020 | |
By https://amattu.com/links/github | |
Copy Alec M. | |
--> | |
<head> | |
<meta charset="utf-8"> | |
<title>Machine Learning Model Trainer</title> | |
<style> | |
body { | |
font-family: sans-serif; | |
margin: 0; | |
padding: 0; | |
color: #3b3b3b; | |
background: #f2f2f2; | |
} | |
.container { | |
width: 550px; | |
margin: 25px auto; | |
} | |
.train-models { | |
margin-top: 25px; | |
padding: 10px; | |
} | |
.train-model-box { | |
background: #fff; | |
border-radius: 3px; | |
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24); | |
padding: 15px; | |
margin-bottom: 10px; | |
} | |
.model-field { | |
display: flex; | |
justify-content: center; | |
align-items: center; | |
min-height: 40px; | |
} | |
.field-title { | |
width: 105px; | |
font-weight: bold; | |
text-align: left; | |
user-select: none; | |
} | |
.field-input { | |
width: calc(100% - 105px); | |
} | |
.field-input textarea { | |
border: 1px solid #ccc; | |
border-radius: 3px; | |
box-sizing: border-box; | |
display: block; | |
width: 100%; | |
height: unset; | |
padding: 6px 12px; | |
font-size: 14px; | |
line-height: 1.5; | |
font-family: inherit; | |
resize: vertical; | |
margin-bottom: 5px; | |
} | |
.train-model-page { | |
display: flex; | |
justify-content: center; | |
align-items: center; | |
margin-top: 20px; | |
} | |
.button { | |
margin: 0 auto; | |
background: #3b3b3b; | |
padding: 10px; | |
color: #fff; | |
border-radius: 3px; | |
cursor: pointer; | |
user-select: none; | |
} | |
label { | |
user-select: none | |
} | |
</style> | |
</head> | |
<body> | |
<div class='container'> | |
<h2>Train Machine Learning Models</h2> | |
<div class='train-models'> | |
<div class='train-model-box'> | |
<div class='model-field'> | |
<div class='field-title'>Row ID</div> | |
<div class='field-input' id='row-id'>#1</div> | |
</div> | |
<div class='model-field'> | |
<div class='field-title'>Tech</div> | |
<div class='field-input' id='row-tech'>Body Shop</div> | |
</div> | |
<div class='model-field'> | |
<div class='field-title'>Service</div> | |
<div class='field-input' id='row-service'>Bodywork</div> | |
</div> | |
<div class='model-field'> | |
<div class='field-title'>Comments</div> | |
<div class='field-input'> | |
<textarea placeholder="Enter comments" id='row-comments' style='height: 125px'></textarea> | |
</div> | |
</div> | |
<div class='model-field'> | |
<div class='field-title'>Fields</div> | |
<div class='field-input'> | |
<div class='field-input-cb'> | |
<label for="field-mechanical">Mechanical</label> | |
<input id="field-mechanical" type="checkbox" /> | |
</div> | |
<div class='field-input-cb'> | |
<label for="field-bodywork">Bodywork</label> | |
<input id="field-bodywork" type="checkbox" /> | |
</div> | |
<div class='field-input-cb'> | |
<label for="field-diagnostic">Diagnostic</label> | |
<input id="field-diagnostic" type="checkbox" /> | |
</div> | |
<div class='field-input-cb'> | |
<label for="field-suspension">Suspension</label> | |
<input id="field-suspension" type="checkbox" /> | |
</div> | |
<div class='field-input-cb'> | |
<label for="field-engine">Engine</label> | |
<input id="field-engine" type="checkbox" /> | |
</div> | |
<div class='field-input-cb'> | |
<label for="field-transmission">Transmission</label> | |
<input id="field-transmission" type="checkbox" /> | |
</div> | |
<div class='field-input-cb'> | |
<label for="field-exhaust">Exhaust</label> | |
<input id="field-exhaust" type="checkbox" /> | |
</div> | |
<div class='field-input-cb'> | |
<label for="field-electrical">Electrical</label> | |
<input id="field-electrical" type="checkbox" /> | |
</div> | |
<div class='field-input-cb'> | |
<label for="field-brakes">Brakes</label> | |
<input id="field-brakes" type="checkbox" /> | |
</div> | |
<div class='field-input-cb'> | |
<label for="field-tires">Tires</label> | |
<input id="field-tires" type="checkbox" /> | |
</div> | |
</div> | |
</div> | |
</div> | |
<div class='train-model-page'> | |
<div class='button' id="train-model-prev">Previous</div> | |
<input type="number" min="0" max="9999" step="1" value="1" id="train-model-select" /> | |
<div class='button' id="train-model-next">Save & Next</div> | |
</div> | |
</div> | |
<script> | |
// Variables | |
var current_row = {}; | |
// Events | |
document.getElementById("train-model-prev").onclick = (e) => { | |
// Checks | |
if (current_row && current_row.ID && current_row.ID <= 1) { | |
return false; | |
} | |
build_row(current_row.ID - 1); | |
}; | |
document.getElementById("train-model-select").onblur = (e) => { | |
// Checks | |
if (current_row && current_row.ID && e.target.value == current_row.ID) { | |
return false; | |
} | |
build_row(e.target.value); | |
}; | |
document.getElementById("train-model-next").onclick = (e) => { | |
save_row(current_row).then((d) => { | |
if (!d) { | |
alert("Unable to save"); | |
return false; | |
} | |
build_row((current_row && current_row.ID ? current_row.ID + 1 : 1)); | |
}); | |
}; | |
document.getElementById('row-comments').onblur = (e) => { | |
if (!current_row || !current_row.Fields) { | |
return false; | |
} | |
current_row.Comments = e.target.value; | |
}; | |
document.getElementById('field-mechanical').onblur = (e) => { | |
if (!current_row || !current_row.Fields) { | |
return false; | |
} | |
current_row.Fields.mechanical = (e.target.checked ? 1 : 0); | |
}; | |
document.getElementById('field-bodywork').onblur = (e) => { | |
if (!current_row || !current_row.Fields) { | |
return false; | |
} | |
current_row.Fields.bodywork = (e.target.checked ? 1 : 0); | |
}; | |
document.getElementById('field-diagnostic').onblur = (e) => { | |
if (!current_row || !current_row.Fields) { | |
return false; | |
} | |
current_row.Fields.diagnostic = (e.target.checked ? 1 : 0); | |
}; | |
document.getElementById('field-suspension').onblur = (e) => { | |
if (!current_row || !current_row.Fields) { | |
return false; | |
} | |
current_row.Fields.suspension = (e.target.checked ? 1 : 0); | |
}; | |
document.getElementById('field-engine').onblur = (e) => { | |
if (!current_row || !current_row.Fields) { | |
return false; | |
} | |
current_row.Fields.engine = (e.target.checked ? 1 : 0); | |
}; | |
document.getElementById('field-transmission').onblur = (e) => { | |
if (!current_row || !current_row.Fields) { | |
return false; | |
} | |
current_row.Fields.transmission = (e.target.checked ? 1 : 0); | |
}; | |
document.getElementById('field-exhaust').onblur = (e) => { | |
if (!current_row || !current_row.Fields) { | |
return false; | |
} | |
current_row.Fields.exhaust = (e.target.checked ? 1 : 0); | |
}; | |
document.getElementById('field-electrical').onblur = (e) => { | |
if (!current_row || !current_row.Fields) { | |
return false; | |
} | |
current_row.Fields.electrical = (e.target.checked ? 1 : 0); | |
}; | |
document.getElementById('field-brakes').onblur = (e) => { | |
if (!current_row || !current_row.Fields) { | |
return false; | |
} | |
current_row.Fields.brakes = (e.target.checked ? 1 : 0); | |
}; | |
document.getElementById('field-tires').onblur = (e) => { | |
if (!current_row || !current_row.Fields) { | |
return false; | |
} | |
current_row.Fields.tires = (e.target.checked ? 1 : 0); | |
}; | |
// Build new row UI function | |
function build_row(ID) { | |
// Fetch new row | |
get_row(ID).then(d => { | |
// Check data | |
if (!d || !d.ID) { | |
alert("error loading row"); | |
return false; | |
} | |
// Update reference | |
current_row = d; | |
// Update UI | |
document.getElementById("train-model-select").value = ID; | |
document.getElementById('row-id').innerText = d.ID; | |
document.getElementById('row-tech').innerText = d.Tech; | |
document.getElementById('row-service').innerText = d.Service; | |
document.getElementById('row-comments').value = d.Comments; | |
document.getElementById('field-mechanical').checked = d.Fields.mechanical; | |
document.getElementById('field-bodywork').checked = d.Fields.bodywork; | |
document.getElementById('field-diagnostic').checked = d.Fields.diagnostic; | |
document.getElementById('field-suspension').checked = d.Fields.suspension; | |
document.getElementById('field-engine').checked = d.Fields.engine; | |
document.getElementById('field-transmission').checked = d.Fields.transmission; | |
document.getElementById('field-exhaust').checked = d.Fields.exhaust; | |
document.getElementById('field-electrical').checked = d.Fields.electrical; | |
document.getElementById('field-brakes').checked = d.Fields.brakes; | |
document.getElementById('field-tires').checked = d.Fields.tires; | |
}) | |
} | |
// Get row data function | |
async function get_row(ID) { | |
return new Promise(function(resolve) { | |
// Checks | |
if (!ID) { resolve(false) } | |
// Variables | |
let request = new XMLHttpRequest(); | |
// Response | |
request.onreadystatechange = function() { | |
// Checks | |
if (request.readyState !== 4) { return false } | |
if (request.status != 200) { resolve(false) } | |
// Return | |
resolve(JSON.parse(request.responseText)); | |
} | |
// Request | |
request.open('GET', 'api.php?ID=' + ID, true); | |
request.send(); | |
}); | |
} | |
// Update row data function | |
async function save_row(row) { | |
console.log(row); | |
return new Promise(function(resolve) { | |
// Variables | |
let form = new FormData(); | |
let request = new XMLHttpRequest(); | |
// Appends | |
form.append("row", JSON.stringify(row)); | |
// Response | |
request.onreadystatechange = function() { | |
// Checks | |
if (request.readyState !== 4) { return false } | |
if (request.status != 200) { resolve(false) } | |
// Return | |
resolve(request.responseText); | |
} | |
// Request | |
request.open('POST', 'api.php', true); | |
request.send(form); | |
}); | |
} | |
// Setup page | |
build_row(1); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Preview