###エラーメッセージ
Uncaught TypeError: Failed to resolve module specifier "cluster". Relative references must start with either "/", "./",
ファイル上にclusterをいうモジュールは有りませんし、ググっても、対処法が見つからないので質問させていただきます。
###やりたいこと
マウスを用いて、手書き数字をSignature Padに書いて、tensorflow.jsで0から9までの数字を認識させるプログラムを書きたいと思っています。
ファイルは、index.html、script.js、lib.jsで構成されています。
index.html
html
1<!DOCTYPE html> 2<html lang="ja"> 3 4<head> 5 <meta charset="UTF-8"> 6 <meta http-equiv="X-UA-Compatible" content="IE=edge"> 7 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 8 <title>Tensorflow.js MNIST</title> 9 10 11 <!--TODO: ファイルの読み込み -> chromeのセキュリティ設定--> 12 13 14 <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@1.0.0/dist/tf.min.js"></script> 15 <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs-vis@1.0.2/dist/tfjs-vis.umd.min.js"></script> 16 <script src="https://cdnjs.cloudflare.com/ajax/libs/signature_pad/1.5.3/signature_pad.min.js"></script> 17 18 <script src="lib.js" type="module"></script> 19 20 <script src="script.js" type="module"></script> 21 22 <style type="text/css"> 23 .is-selected { 24 background-color: blue; 25 color: white; 26 line-height: 1.5; 27 } 28 </style> 29</head> 30 31 32 33<body> 34 <p id="loading-message">学習モデルの作成中です。しばらくお待ちください</p> 35 <div id="main" style="display:none;"> 36 <canvas id="pad" width="280" height="280"></canvas> 37 <div> 38 <input type="button" value="認識" id="predict-button"> 39 <input type="button" value="リセット" id="reset-button"> 40 </div> 41 <br /> 42 43 <table> 44 <thead> 45 <tr> 46 <th>#</th> 47 <th>確率</th> 48 </tr> 49 </thead> 50 <tbody> 51 <tr> 52 <th>0</th> 53 <td class="classconfidence">-</td> 54 </tr> 55 <tr> 56 <th>1</th> 57 <td class="classconfidence">-</td> 58 </tr> 59 <tr> 60 <th>2</th> 61 <td class="classconfidence">-</td> 62 </tr> 63 <tr> 64 <th>3</th> 65 <td class="classconfidence">-</td> 66 </tr> 67 <tr> 68 <th>4</th> 69 <td class="classconfidence">-</td> 70 </tr> 71 <tr> 72 <th>5</th> 73 <td class="classconfidence">-</td> 74 </tr> 75 <tr> 76 <th>6</th> 77 <td class="classconfidence">-</td> 78 </tr> 79 <tr> 80 <th>7</th> 81 <td class="classconfidence">-</td> 82 </tr> 83 <tr> 84 <th>8</th> 85 <td class="classconfidence">-</td> 86 </tr> 87 <tr> 88 <th>9</th> 89 <td class="classconfidence">-</td> 90 </tr> 91 </tbody> 92 </table> 93 </div> 94</body> 95 96</html>
lib.js
javascirpt
1export async function showExamples(data) { 2 const surface = tfvis.visor().surface({ name: 'Input Data Examples', tab: 'Input Data' }); 3 4 const examples = data.nextTestBatch(20); 5 const numExamples = examples.xs.shape[0]; 6 7 for (let i = 0; i < numExamples; i++) { 8 const imageTensor = tf.tidy(() => { 9 return examples.xs 10 .slice([i, 0], [1, examples.xs.shape[1]]) 11 .reshape([28, 28, 1]); 12 }); 13 const canvas = document.createElement('canvas'); 14 canvas.width = 28; 15 canvas.height = 28; 16 canvas.style = 'margin: 4px'; 17 await tf.browser.toPixels(imageTensor, canvas) 18 surface.drawArea.appendChild(canvas); 19 20 imageTensor.dispose(); 21 } 22} 23 24 25 26 27//手書き数字認識の学習モデルを定義 28export function getModel() { 29 const model = tf.sequential(); 30 31 const IMAGE_WIDTH = 28; 32 const IMAGE_HEIGHT = 28; 33 const IMAGE_CHANNELS = 1; 34 35 model.add(tf.layers.conv2d({ 36 inputShape: [IMAGE_WIDTH, IMAGE_HEIGHT, IMAGE_CHANNELS], 37 kernelSize: 5, 38 filters: 8, 39 strides: 1, 40 activation: 'relu', 41 kernelInitializer: 'varianceScaling' 42 })); 43 model.add(tf.layers.maxPooling2d({ poolSize: [2, 2], strides: [2, 2] })); 44 model.add(tf.layers.conv2d({ 45 kernelSize: 5, 46 filters: 16, 47 strides: 1, 48 activation: 'relu', 49 kernelInitializer: 'varianceScaling' 50 })); 51 52 model.add(tf.layers.maxPooling2d({ poolSize: [2, 2], strides: [2, 2] })); 53 54 model.add(tf.layers.maxPooling2d({ poolSize: [2, 2], strides: [2, 2] })) 55 model.add(tf.layers.flatten()); 56 57 58 const NUM_OUTPUT_CLASSES = 10; 59 model.add(tf.layers.dense({ 60 units: NUM_OUTPUT_CLASSES, 61 kernelInitializer: 'varianceScaling', 62 activation: 'softmax' 63 })); 64 65 const optimizer = tf.train.adam(); 66 model.compile({ 67 optimizer: optimizer, 68 loss: 'categoricalCrossentropy', 69 metrics: ['accuracy'], 70 }); 71 72 return model; 73} 74 75 76 77export async function train(model, data) { 78 const metrics = ['loss', 'val_loss', 'acc', 'val_acc'] 79 const container = { 80 name: 'Model Training', 81 styles: { height: '1000px' } 82 }; 83 const fitCallbacks = tfvis.show.fitCallbacks(container, metrics); 84 85 const BATCH_SIZE = 512; 86 const TRAIN_DATA_SIZE = 5500; 87 const TEST_DATA_SIZE = 1000; 88 89 const [trainXs, trainYs] = tf.tidy(() => { 90 const d = data.nextTrainBatch(TRAIN_DATA_SIZE); 91 return [ 92 d.xs.reshape([TRAIN_DATA_SIZE, 28, 28, 1]), 93 d.labels 94 ]; 95 }); 96 97 const [textXs, testYs] = tf.tidy(() => { 98 const d = data.nextTestBatch(TEST_DATA_SIZE); 99 return [ 100 d.xs.reshape([TEST_DATA_SIZE, 28, 28, 1]), 101 d.labels 102 ]; 103 }); 104 105 return model.fit(trainXs, trainYs, { 106 batchSize: BATCH_SIZE, 107 validationData: [testXs, testYs], 108 epochs: 10, 109 shuffle: true, 110 callbacks: fitCallbacks 111 }); 112}
script.js
javascript
1import { MnistData } from 'https://storage.googleapis.com/tfjs-tutorial/mnist_data.js'; 2import { showExamples, getModel, train } from './lib.js' 3 4 5 6const IMAGE_WIDTH = 28; 7const IMAGE_HEIGHT = 28; 8 9async function run() { 10 let signaturePad = initSignaturePad(); 11 12 const data = new MnistData(); 13 await data.load() 14 await showExamples(data); 15 16 let model = getModel(); 17 18 tfvis.show.modelSummary({ name: 'Model Architecture' }, model); 19 20 await train(model, data); 21 document.getElementById("loading-message").style.display = "none" 22 document.getElementById("main").style.display = "block" 23 24 document.getElementById("predict-button").onclick = function() { 25 predict(model); 26 } 27 document.getElementById("reset-button").onclick = function() { 28 reset(signaturePad); 29 }; 30} 31 32 33document.addEventListener('DOMContentLoaded', run); 34 35function initSignaturePad() { 36 let pad = document.getElementById('pad'); 37 return new signaturePad(pad, { 38 minWidth: 5, 39 maxWidth: 5, 40 penColor: 'white', 41 backgroundColor: 'black', 42 }); 43} 44 45function predict(model) { 46 let ctx = document.createElement('canvas').getContent('2d'); 47 let pad = document.getElementById('pad'); 48 49 ctx.drawImage(pad, 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT); 50 let imageData = ctx.getImageData(0, 0, IMAGE_WIDTH, IMAGE_HEIGHT); 51 52 let score = tf.tidy(() => { 53 let input = tf.browser.fromPixels(imageData, 1).reshape([1, IMAGE_WIDTH, IMAGE_HEIGHT, 1]).div(tf.scalar(255)); 54 return model.predict(input); 55 }); 56 57 let maxConfidence = score.dataSync().indexOf(Math.max.apply(null, score.dataSync())); 58 59 let elements = document.querySelectorAll(".confidence"); 60 61 elements.forEach((el, i) => { 62 el.parentNode.classList.remove('is-selected'); 63 if (i === maxConfidence) { 64 el.parentNode.classList.add('is-selected'); 65 } 66 el.innerText = score.dataSync()[i]; 67 }) 68} 69 70 71function reset(signaturePad) { 72 signaturePad.clear(); 73 let elements = document.querySelectorAll(".confidence"); 74 elements.forEach(el => { 75 el.parentNode.classList.remove('is-selected'); 76 el.innerText = '-'; 77 }) 78}
またNode,jsのパッケージである、http-serverを起動させて、Webサーバーからアクセスしています。
どなたかご教授よろしくお願いします。
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2020/03/02 00:53