Skip to content

Instantly share code, notes, and snippets.

@amattu2
Last active December 24, 2020 12:10
Show Gist options
  • Select an option

  • Save amattu2/c5adf92e3b83f2c59c604fdae6e0dc44 to your computer and use it in GitHub Desktop.

Select an option

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)
-- 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 */;
<?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"); }
}
?>
<?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"); }
?>
<!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>
@amattu2
Copy link
Copy Markdown
Author

amattu2 commented Dec 24, 2020

Preview

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment