* Train the auto encoder * * @param {number[][]} images Flattened images for VAE training. * @param {object} vaeOpts Options for the VAE model, including the following * fields: * - originaDim {number} Length of the input flattened image. * - intermediateDim {number} Number of units of t
(images, vaeOpts, savePath, logDir)
| 48 | * so that the training process can be monitored using TensorBoard. |
| 49 | */ |
| 50 | async function train(images, vaeOpts, savePath, logDir) { |
| 51 | const encoderModel = encoder(vaeOpts); |
| 52 | const decoderModel = decoder(vaeOpts); |
| 53 | const vaeModel = vae(encoderModel, decoderModel); |
| 54 | |
| 55 | let summaryWriter; |
| 56 | if (logDir != null) { |
| 57 | console.log(`Logging loss values to ${logDir}.`); |
| 58 | console.log( |
| 59 | `Use the following command to start the tensorboard backend server:`); |
| 60 | console.log(` tensorboard --logdir ${logDir}`); |
| 61 | summaryWriter = tf.node.summaryFileWriter(logDir); |
| 62 | } |
| 63 | |
| 64 | console.log('\n** Train Model **\n'); |
| 65 | |
| 66 | // Because we use a custom loss function, we will use optimizer.minimize |
| 67 | // instead of the more typical model.fit. We thus need to define an optimizer |
| 68 | // and manage batching the data ourselves. |
| 69 | |
| 70 | // Create the optimizer |
| 71 | const optimizer = tf.train.adam(); |
| 72 | |
| 73 | // Group the data into batches. |
| 74 | const batches = _.chunk(images, batchSize); |
| 75 | |
| 76 | // Run the train loop. |
| 77 | let step = 0; |
| 78 | for (let i = 0; i < epochs; i++) { |
| 79 | console.log(`\nEpoch #${i + 1} of ${epochs}\n`); |
| 80 | for (let j = 0; j < batches.length; j++) { |
| 81 | const currentBatchSize = batches[j].length |
| 82 | const batchedImages = batchImages(batches[j]); |
| 83 | |
| 84 | const reshaped = |
| 85 | batchedImages.reshape([currentBatchSize, vaeOpts.originalDim]); |
| 86 | |
| 87 | // This is the model optimization step. We make a prediction |
| 88 | // compute loss and return it so that optimizer.minimize can |
| 89 | // adjust the weights of the model. |
| 90 | optimizer.minimize(() => { |
| 91 | const outputs = vaeModel.apply(reshaped); |
| 92 | const loss = vaeLoss(reshaped, outputs, vaeOpts); |
| 93 | process.stdout.write('.'); |
| 94 | if (j % 50 === 0) { |
| 95 | console.log('\nLoss:', loss.dataSync()[0]); |
| 96 | } |
| 97 | if (summaryWriter != null) { |
| 98 | summaryWriter.scalar('loss', loss, step++); |
| 99 | } |
| 100 | |
| 101 | return loss; |
| 102 | }); |
| 103 | tf.dispose([batchedImages, reshaped]); |
| 104 | } |
| 105 | console.log(''); |
| 106 | // Generate a preview after each epoch |
| 107 | await generate(decoderModel, vaeOpts.latentDim); |
no test coverage detected