{"id":689392,"student_id":10,"content":"{\"html\":\"\u003c!DOCTYPE html\u003e\\n\u003chtml lang=\\\"en\\\"\u003e\\n\\n\u003chead\u003e\\n \u003cmeta charset=\\\"UTF-8\\\"\u003e\\n \u003cmeta name=\\\"viewport\\\" content=\\\"width=device-width, initial-scale=1.0\\\"\u003e\\n \u003ctitle\u003ehandwriting recognition\u003c/title\u003e\\n \u003cscript src=\\\"https://cdn.jsdelivr.net/npm/chart.js\\\"\u003e\u003c/script\u003e\\n \u003clink href=\\\"https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css\\\" rel=\\\"stylesheet\\\"\u003e\\n \u003cscript src=\\\"https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js\\\"\u003e\u003c/script\u003e\\n \u003cscript src=\\\"https://code.jquery.com/jquery-3.7.1.min.js\\\"\u003e\u003c/script\u003e\\n\u003c/head\u003e\\n\\n\u003cbody\u003e\\n \u003cdiv class=\\\"container py-3\\\"\u003e\\n \u003cdiv class=\\\"row\\\"\u003e\\n \u003cdiv class=\\\"col-8\\\"\u003e\\n \u003cdiv class=\\\"overflow-x-scroll bg-dark\\\"\u003e\\n \u003cdiv class=\\\"position-relative\\\"\u003e\\n \u003cdiv id=\\\"cursor\\\" class=\\\"position-absolute\\\"\\n style=\\\"width: 28px; height: 28px; top:0; left: 0; z-index: 10; border: 2px solid red;\\\"\u003e\u003c/div\u003e\\n \u003ccanvas id=\\\"mark-canvas\\\" width=\\\"28000\\\" height=\\\"280\\\" class=\\\"position-absolute top-0 left-0\\\"\\n style=\\\"opacity: 0.6;\\\"\u003e\u003c/canvas\u003e\\n \u003ccanvas id=\\\"data-canvas\\\" width=\\\"28000\\\" height=\\\"280\\\" style=\\\"image-rendering: pixelated;\\\"\u003e\u003c/canvas\u003e\\n \u003c/div\u003e\\n \u003c/div\u003e\\n \u003cdiv\u003e\\n \u003ccanvas id=\\\"chart-canvas\\\"\u003e\u003c/canvas\u003e\\n \u003ccanvas id=\\\"brain-canvas\\\" width=\\\"1200\\\" height=\\\"600\\\"\u003e\u003c/canvas\u003e\\n \u003c/div\u003e\\n \u003c/div\u003e\\n \u003cdiv class=\\\"col-4\\\"\u003e\\n \u003ccanvas id=\\\"draw-canvas\\\" width=\\\"28\\\" height=\\\"28\\\" class=\\\"border bg-black\\\"\\n style=\\\"width: 280px; image-rendering: pixelated;\\\"\u003e\u003c/canvas\u003e\\n \u003ccanvas id=\\\"mini-canvas\\\" width=\\\"28\\\" height=\\\"28\\\" class=\\\"border bg-black d-none\\\"\u003e\u003c/canvas\u003e\\n\\n \u003cdiv class=\\\"mb-2\\\"\u003e\\n \u003cdiv class=\\\"btn-group btn-group-sm\\\"\u003e\\n \u003cbutton class=\\\"btn btn-dark\\\" id=\\\"next\\\"\u003e寫入並右移\u003c/button\u003e\\n \u003cbutton class=\\\"btn btn-dark\\\" id=\\\"clear\\\"\u003e清除畫布\u003c/button\u003e\\n \u003cbutton class=\\\"btn btn-dark\\\" id=\\\"detect\\\"\u003e偵測畫布\u003c/button\u003e\\n \u003c/div\u003e\\n \u003c/div\u003e\\n\\n \u003cdiv class=\\\"mb-2\\\"\u003e\\n \u003cdiv class=\\\"btn-group btn-group-sm\\\"\u003e\\n \u003cbutton class=\\\"btn btn-dark\\\" onclick=\\\"download()\\\"\u003e下載圖片\u003c/button\u003e\\n \u003cbutton class=\\\"btn btn-dark\\\" onclick=\\\"upload()\\\"\u003e上傳圖片\u003c/button\u003e\\n \u003c/div\u003e\\n \u003c/div\u003e\\n\\n \u003cdiv class=\\\"mb-2\\\"\u003e\\n \u003cbutton class=\\\"btn btn-success\\\" id=\\\"start\\\"\u003e開始訓練\u003c/button\u003e\\n \u003c/div\u003e\\n \u003cpre class=\\\"alert alert-secondary w-100 overflow-y-scroll\\\" style=\\\"height: 200px;\\\" id=\\\"logger\\\"\u003e\u003c/pre\u003e\\n \u003c/div\u003e\\n \u003c/div\u003e\\n \u003c/div\u003e\\n\\n \u003cscript src=\\\"day2.js\\\"\u003e\u003c/script\u003e\\n\\n \u003cscript\u003e\\n var SIZE = 28\\n var dataCanvas = $('#data-canvas')[0]\\n var dataCtx = dataCanvas.getContext('2d')\\n var drawCanvas = $('#draw-canvas')[0]\\n var drawCtx = drawCanvas.getContext('2d')\\n var markCanvas = $('#mark-canvas')[0]\\n var markCtx = markCanvas.getContext('2d')\\n var miniCanvas = $('#mini-canvas')[0]\\n var miniCtx = miniCanvas.getContext('2d')\\n\\n var cursorX = 0\\n var cursorY = 0\\n var isMouseDown = false\\n\\n loadCache()\\n\\n function loadCache() {\\n var dataURL = localStorage.getItem('image')\\n var img = new Image\\n img.src = dataURL\\n img.onload = () =\u003e dataCtx.drawImage(img, 0, 0)\\n }\\n \\n function loadImage(src) {\\n var img = new Image\\n img.onload = () =\u003e dataCtx.drawImage(img, 0, 0)\\n img.src = src\\n }\\n\\n function download() {\\n var link = document.createElement('a')\\n link.download = 'backup.png';\\n link.href = dataCanvas.toDataURL('image/png')\\n link.click();\\n }\\n\\n function upload() {\\n const fileInput = document.createElement('input')\\n fileInput.type = 'file'\\n fileInput.addEventListener('change', (event) =\u003e {\\n const file = event.target.files[0]\\n const reader = new FileReader()\\n reader.onload = (e) =\u003e {\\n const img = new Image()\\n img.onload = () =\u003e dataCtx.drawImage(img, 0, 0)\\n img.src = e.target.result\\n }\\n reader.readAsDataURL(file)\\n })\\n fileInput.click()\\n }\\n\\n function handleFileSelect() {\\n const file = event.target.files[0]\\n }\\n\\n var chart = new Chart($('#chart-canvas')[0], {\\n type: 'line',\\n data: {\\n labels: [],\\n datasets: [\\n { label: '訓練資料通過率', borderWidth: 2 },\\n { label: '測試資料通過率', borderWidth: 2 },\\n ]\\n },\\n options: {\\n elements: { point: { radius: 0 } },\\n scales: { y: { beginAtZero: true, min: 0, max: 100 } },\\n animation: { duration: 0 },\\n }\\n })\\n\\n var isTraining = false\\n $('#start').click(() =\u003e {\\n $('#start').toggleClass('btn-success')\\n $('#start').toggleClass('btn-danger')\\n $('#start').text(isTraining ? '開始訓練' : '停止訓練')\\n isTraining ? stop() : start()\\n isTraining = !isTraining\\n })\\n $('#stop').click(() =\u003e window.stop())\\n $('#detect').click(() =\u003e window.detect())\\n $('#saveback').click(() =\u003e window.saveback())\\n\\n $('#next').click(() =\u003e {\\n saveback()\\n cursorX += 1\\n loadFromData()\\n $('#cursor').css({ top: `${cursorY * SIZE}px`, left: `${cursorX * SIZE}px` })\\n })\\n\\n $('#draw-canvas').on('mousedown', () =\u003e isMouseDown = true)\\n $('#draw-canvas').on('mouseup', () =\u003e isMouseDown = false)\\n $('#draw-canvas').on('mousemove', (e) =\u003e {\\n if (!isMouseDown) return\\n var rect = drawCanvas.getBoundingClientRect()\\n var x = Math.floor((e.clientX - rect.left) / 10)\\n var y = Math.floor((e.clientY - rect.top) / 10)\\n drawCtx.fillStyle = 'white'\\n drawCtx.beginPath()\\n drawCtx.arc(x, y, 1, 0, 3 * Math.PI)\\n drawCtx.fill()\\n })\\n $('#mark-canvas').click(e =\u003e {\\n var rect = dataCanvas.getBoundingClientRect()\\n cursorX = Math.floor((e.clientX - rect.left) / SIZE)\\n cursorY = Math.floor((e.clientY - rect.top) / SIZE)\\n loadFromData()\\n $('#cursor').css({ top: `${cursorY * SIZE}px`, left: `${cursorX * SIZE}px` })\\n })\\n $('#upload').change(e =\u003e {\\n var img = new Image()\\n img.onload = () =\u003e dataCtx.drawImage(img, 0, 0)\\n img.src = URL.createObjectURL(e.target.files[0])\\n })\\n $('#clear').click(() =\u003e {\\n drawCtx.fillStyle = 'black'\\n drawCtx.fillRect(0, 0, SIZE, SIZE)\\n })\\n\\n function loadFromData() {\\n drawCtx.clearRect(0, 0, SIZE, SIZE)\\n drawCtx.drawImage(dataCanvas, cursorX * SIZE, cursorY * SIZE, SIZE, SIZE, 0, 0, SIZE, SIZE)\\n }\\n\\n function saveback() {\\n dataCtx.drawImage(drawCanvas, 0, 0, SIZE, SIZE, cursorX * SIZE, cursorY * SIZE, SIZE, SIZE)\\n var data = dataCanvas.toDataURL('image/jpg')\\n localStorage.setItem('image', data)\\n }\\n\\n function getHandDrawnData() {\\n var arr = []\\n miniCtx.drawImage(drawCanvas, 0, 0, SIZE, SIZE)\\n var data = miniCtx.getImageData(0, 0, SIZE, SIZE).data\\n for (var i = 0; i \u003c data.length; i += 4) {\\n ;\\n var avg = (data[i + 0] + data[i + 1] + data[i + 2]) / 3 / 225\\n arr.push(avg)\\n }\\n return arr\\n }\\n\\n function getImageData(x, y, width, height) {\\n var list = []\\n var data = dataCtx.getImageData(x, y, width, height).data\\n for (var i = 0; i \u003c data.length; i += 4) {\\n var avg = (data[i + 0] + data[i + 1] + data[i + 2]) / 3 / 225\\n list.push(avg)\\n }\\n return list\\n }\\n\\n function addLog(content) {\\n $('#logger').prepend(`\u003cspan\u003e${JSON.stringify(content)}\u003c/span\u003e\u003cbr/\u003e`)\\n }\\n\\n function chartLog(trainRate, testRate) {\\n chart.data.labels.push(chart.data.labels.length + 1)\\n chart.data.datasets[0].data.push(trainRate)\\n chart.data.datasets[1].data.push(testRate)\\n chart.update()\\n }\\n\\n \u003c/script\u003e\\n\\n\u003c/body\u003e\\n\\n\u003c/html\u003e\",\"css\":\"\",\"js\":\"// 產生指定長度的陣列\\nfunction makeArray(x) {\\n return (new Array(x)).fill(0);\\n}\\n\\n// 產生指定長寬的矩陣,用來作為神經層之間的權重\\nfunction makeMatrix(x, y) {\\n var grid = makeArray(x);\\n return grid.map(_ =\u003e makeArray(y).map(rand));\\n}\\n\\n// 產生 -0.5 至 0.5 之間的隨機小數\\nfunction rand() {\\n return Math.random() - 0.5;\\n}\\n\\n// 激活函式\\nfunction sigmoid(x) {\\n return Math.tanh(x);\\n}\\n\\n// 激活函式導數\\nfunction dsigmoid(x) {\\n return 1 - x * x;\\n}\\n\\n// 矩陣相乘,用來作為正向傳遞的計算\\nfunction dot(arr, mx) {\\n var list = makeArray(mx[0].length);\\n for (var i = 0; i \u003c mx[0].length; i++) {\\n for (var j = 0; j \u003c arr.length; j++) {\\n list[i] += arr[j] * mx[j][i];\\n }\\n }\\n return list;\\n}\\n\\n// 矩陣反轉,用來作為反向傳遞的計算\\nfunction transpose(mx) {\\n return mx[0].map((_, i) =\u003e mx.map(row =\u003e row[i]));\\n}\\n\\n// 根據誤差更新神經網路的矩陣\\nfunction updateWeight(mx, arr1, arr2, rate = 0.01) {\\n for (var i = 0; i \u003c arr1.length; i++) {\\n for (var j = 0; j \u003c arr2.length; j++) {\\n mx[i][j] += arr1[i] * arr2[j] * rate;\\n }\\n }\\n}\\n\\n// ------------------------------------------------------------- //\\n\\nfunction NN(a, b, c, d) {\\n \\n var n1 = makeArray(a); //第 1 層神經儲存的數值 \\n var n2 = makeArray(b); //第 2 層神經儲存的數值\\n var n3 = makeArray(c); //第 3 層神經儲存的數值\\n var n4 = makeArray(d); //第 4 層神經儲存的數值\\n var w1 = makeMatrix(a, b); //第 1, 2 層神經之間的權重\\n var w2 = makeMatrix(b, c); //第 2, 3 層神經之間的權重\\n var w3 = makeMatrix(c, d); //第 3, 4 層神經之間的權重\\n\\n // 正向傳遞\\n function forward(inputs) {\\n n1 = inputs;\\n n2 = dot(n1, w1).map(sigmoid);\\n n3 = dot(n2, w2).map(sigmoid);\\n n4 = dot(n3, w3).map(sigmoid);\\n return n4\\n }\\n\\n // 反向傳遞\\n function backward(target, learningRate = 0.001) {\\n var e4 = target.map((t, i) =\u003e t - n4[i]);\\n var d4 = n4.map(dsigmoid).map((v, i) =\u003e v * e4[i]);\\n var e3 = dot(d4, transpose(w3));\\n var d3 = n3.map(dsigmoid).map((v, i) =\u003e v * e3[i]);\\n var e2 = dot(d3, transpose(w2));\\n var d2 = n2.map(dsigmoid).map((v, i) =\u003e v * e2[i]);\\n updateWeight(w3, n3, d4, learningRate);\\n updateWeight(w2, n2, d3, learningRate);\\n updateWeight(w1, n1, d2, learningRate);\\n }\\n\\n return { forward, backward }\\n}\\n\\n// ------------------------------------------------------------- //\\n\\nvar training = false; //是否正在訓練\\nvar trainData = []; //訓練資料\\nvar testData = []; //測試資料\\n\\nvar LABEL = 3; //讀取資料的高度\\nvar LENGTH = 10; //讀取資料的長度\\nvar CUT = 10; //切割資料長度,區分訓練和測試\\n\\nfunction detect() {\\n \\n}\\n\\n// 點擊「開始訓練」按鈕觸發此程式\\nfunction start() {\\n training = true;\\n trainData = []; //清除訓練資料\\n testData = []; //清除測試資料\\n \\n \\n loop(); // 開始訓練迴圈\\n}\\n\\n// 點擊「暫停訓練」按鈕觸發此程式\\nfunction stop() {\\n training = false;\\n}\\n\\n// 訓練的迴圈\\nfunction loop() {\\n markCtx.clearRect(0, 0, 28000, 420); //清除標記\\n \\n var trainPass = train(trainData); //訓練\\n var trainPct = Math.floor(trainPass * 100 / trainData.length); //計算訓練通過率\\n \\n if (training) setTimeout(loop, 100);\\n}\\n\\n// 執行訓練資料\\nfunction train(data) {\\n \\n}\\n\\n// 執行測試資料\\nfunction test(data) {\\n \\n}\"}","created_at":"2024-01-31T11:09:01.760+08:00","updated_at":"2024-01-31T11:09:52.280+08:00","name":"手寫辨識預設版 (1)","language":"web","screenshot":{"url":null},"parent_id":3,"plugin":"","description":null,"note":null,"status":"public","like_student_ids":[],"is_featured":false,"views":291,"hashid":"gk4sn2q58","is_content_changed":false,"review_status":"unsubmitted","submitted_at":null,"reviewed_at":null,"advise":null,"is_deleted":false}
[{"id":15451927,"file_name":"mnist_fashion.jpg","project_id":689392,"asset_id":717350,"created_at":"2024-01-31T11:09:28.245+08:00","updated_at":"2024-01-31T11:09:28.245+08:00"},{"id":15451928,"file_name":"mnist.jpg","project_id":689392,"asset_id":717351,"created_at":"2024-01-31T11:09:28.266+08:00","updated_at":"2024-01-31T11:09:28.266+08:00"}]
Orange Apple Learning Platform
My Projects
View Project Page
Export
Remix
Import
Delete
Download Android APP (APK)
Screenshot
Open Web Site
繁中
简中
English
日本語
1:1:1
1:1
Full Width
Scan the QRCode below with your phone to install
Or you can
download APK
to this computer
Scan the QRCode below with your phone to install
Or you can
download APK
to this computer