# tensorflowVue **Repository Path**: Electrolux/tensorflow-vue ## Basic Information - **Project Name**: tensorflowVue - **Description**: tensorflow.js+vue 示例,前端的算法。包括了预测模型和图像识别模型。详情可以看readme - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 6 - **Forks**: 3 - **Created**: 2022-09-04 - **Last Updated**: 2025-05-14 ## Categories & Tags **Categories**: Uncategorized **Tags**: Vue ## README # tensorflow.js+vue 示例 # 前端算法 ## 1 (预测类) ### 1.0 效果 -path(''/ai1) 路径 /ai1 ### 1.1 引入变量 ``` import * as tf from "@tensorflow/tfjs"; //"@tensorflow/tfjs": "^3.20.0", import * as tfvis from "@tensorflow/tfjs-vis"; //"@tensorflow/tfjs-vis": "^1.5.1", data() { return { data: null, examples: null, model: null, tensorData:null, predictData:null }; }, ``` ### 1.2 :创造模型和data的写入 ```js createModel() { // 创造一个 序贯模型(Sequential) this.model = tf.sequential(); // Add a single hidden layer 添加层 // model.add(tf.layers.dense({units: 50, activation: 'sigmoid'})); 在这种情况下是sigmoid激活 this.model.add(tf.layers.dense({ inputShape: [1], units: 1, useBias: true })); // Add an output layer this.model.add(tf.layers.dense({ units: 1, useBias: true })); return this.model; }, ``` ### 1.3:数据预处理 ```js dataPre() { // tf.util.shuffle(this.data); // 转换为张量 这里我们制作两个数组,一个用于我们的输入示例,另一个用于真正的输出值(在机器学习中称为标签)。 console.log(this.data,"预期训练的模型"); this.data = [ { x: 201, y:1, }, { x: 1, y: 0, }, { x: [[2,1]], y: 1, }, { x: [[1,1]], y: 1, }, ] // var inputs = this.data.map((d) => d.horsepower); // const labels = this.data.map((d) => d.mpg); var inputs = this.data.map((d) => d.x); const labels = this.data.map((d) => d.y); const inputTensor = tf.tensor2d(inputs, [inputs.length, 1]); const labelTensor = tf.tensor2d(labels, [labels.length, 1]); // 规范化数据 -1 - 1 var inputMax = inputTensor.max(); const inputMin = inputTensor.min(); const labelMax = labelTensor.max(); const labelMin = labelTensor.min(); const normalizedInputs = inputTensor.sub(inputMin).div(inputMax.sub(inputMin)); const normalizedLabels = labelTensor.sub(labelMin).div(labelMax.sub(labelMin)); //这里是为了之后predict用的数据 this.predictData = {inputMin:inputMin,inputMax:inputMax,labelMax:labelMax,labelMin:labelMin} return { inputs: normalizedInputs, labels: normalizedLabels }; }, ``` ### 1.4:训练模型 ```js async trainModel(model, inputs, labels) { this.model.compile({ optimizer: tf.train.adam(), loss: tf.losses.meanSquaredError, metrics: ["mse"], }); const batchSize = 28; const epochs = 50; return await this.model.fit(inputs, labels, { batchSize, epochs, shuffle: true, //这里展示图像 callbacks: tfvis.show.fitCallbacks( { name: "Training Performance" }, ["loss", "mse"], { height: 200, callbacks: ["onEpochEnd"] } ), }); }, ``` ### 1.5 引入变量最后进行调用 ```js document.addEventListener("DOMContentLoaded", this.run()); async run() { // 1.创造model this.createModel(); // 2.数据预处理,转化张量。分成inputs和label const tensorData = this.dataPre(); const { inputs, labels } = tensorData; // 3.确定模型,训练模型 this.trainModel(this.model, inputs, labels); console.log("Done Training"); }, ``` ### 1.6 单点预测 ```js html中 singleTestModel(){ var inputs=[300] const inputTensor = tf.tensor2d(inputs, [inputs.length, 1]); alert(this.model.predict(inputTensor.reshape([1, 1]))) } ``` ### 1.7 多点预测 ```js testModel(model, inputData, normalizationData) { const { inputMax, inputMin, labelMin, labelMax } = this.predictData; console.log(inputMax, inputMin, labelMin, labelMax,normalizationData) // Generate predictions for a uniform range of numbers between 0 and 1; // We un-normalize the data by doing the inverse of the min-max scaling // that we did earlier. const [xs, preds] = tf.tidy(() => { const xs = tf.linspace(0, 1, 100); const preds = model.predict(xs.reshape([100, 1])); const unNormXs = xs.mul(inputMax.sub(inputMin)).add(inputMin); const unNormPreds = preds.mul(labelMax.sub(labelMin)).add(labelMin); // Un-normalize the data return [unNormXs.dataSync(), unNormPreds.dataSync()]; }); const predictedPoints = Array.from(xs).map((val, i) => { return { x: val, y: preds[i] }; }); const originalPoints = inputData.map((d) => ({ x: d.horsepower, y: d.mpg, })); tfvis.render.scatterplot( { name: "Model Predictions vs Original Data" }, { values: [originalPoints, predictedPoints], series: ["original", "predicted"] }, { xLabel: "Horsepower", yLabel: "MPG", height: 300, } ); }, ``` ### 1.8 绘图示例 ```js // 绘图示例,可以去 @tensorflow/tfjs-vis 里面看类型去 async runExample() { // Load and plot the original input data that we are going to train on. // const data = await this.getData(); // var values = data.map((d) => ({ // x: d.horsepower, // y: d.mpg, // })); // console.log(values, "values"); // 散点图 var values = [ { x: 20, y: 20, }, { x: 165, y: 30, }, { x: 165, y: 30, }, { x: 165, y: 30, }, ]; // tfvis.render.scatterplot( // { name: "Horsepower v MPG" }, // { values }, // { // xLabel: "x轴的坐标", // yLabel: "y轴的坐标", // height: 300, // } // ); //柱状图 // const data = [ // { index: 0, value: 50 }, // { index: 1, value: 100 }, // { index: 2, value: 150 }, // ]; // const surface = { name: "Bar chart", tab: "Charts" }; // tfvis.render.barchart(surface, data); //混淆矩阵 // const data = { // values: [ // [4, 2, 8], // [1, 7, 2], // [3, 3, 20], // ], // }; // // Render to visor // const surface = { // name: "Confusion Matrix with Excluded Diagonal", // tab: "Charts", // }; // tfvis.render.confusionMatrix(surface, data, { // shadeDiagonal: false, // }); //折线图 const series1 = Array(100) .fill(0) .map((y) => Math.random() * 100 + 50) .map((y, x) => ({ x, y })); const data = { values: [series1] }; // Render to visor const surface = { name: "Zoomed Line Chart", tab: "Charts" }; tfvis.render.linechart(surface, data, { zoomToFit: true }); }, ``` ### 1.9 保存载入实例 ```js async save() { //本地存储空间(仅限浏览器) await this.model.save("localstorage://my-model-1"); // 真正保存 await this.model.save('downloads://my-model'); alert("保存模型成功"); }, async load() { //本地存储空间(仅限浏览器)tensorflowjs_models/my-model-1/model_topology const MODEL_URL = "localstorage://my-model-1"; var inputs = [300]; const inputTensor = tf.tensor2d(inputs, [inputs.length, 1]); //加载预测模型 const model = await tf.loadLayersModel("localstorage://my-model-1"); //加载图形分析模型 // const model = await loadGraphModel(MODEL_URL); alert(model.predict(inputTensor.reshape([1, 1]))); }, ``` ### 1.10 全部实例 ```vue ``` ## 2 图像识别类 ### 2.1 单物体识别-path('/ai4') 效果 ```vue ``` ### 2.1 单物体识别(手写canvas版)-path('/ai4') ```vue ``` ### 2.3 多物体识别-调用摄像头-path('/ai3') ```vue ``` ### 2.4 多物体识别-读照片-path('/ai2') ```vue ``` ### 定义网络示例 ```js const model = tf.sequential(); const IMAGE_WIDTH = 28; const IMAGE_HEIGHT = 28; const IMAGE_CHANNELS = 1; // 第一层为卷积层,需要声明输入张量的形状信息 // 输入为[28,28,1],也就是长宽均为28的灰度图,色彩深度只有1维 // C1:feature maps 8@24x24 model.add(tf.layers.conv2d({ inputShape: [IMAGE_WIDTH, IMAGE_HEIGHT, IMAGE_CHANNELS],//输入张量的形状 kernelSize: 5, //卷积核尺寸 filters: 8, //卷积核数量 strides: 1, //卷积核移动步长 activation: 'relu', //激活函数 kernelInitializer: 'varianceScaling' //卷积核权重初始化方式 })); // 第二层为最大池化层,使用最大池化计算法 // S2:feature maps 8@12x12 model.add(tf.layers.maxPooling2d({ poolSize: [2, 2],//滑动窗口尺寸 strides: [2, 2]//滑动窗口移动步长 })); // 第三层为卷积层 // C3 : feature maps 16@8x8 model.add(tf.layers.conv2d({ kernelSize: 5, filters: 16, strides: 1, activation: 'relu', kernelInitializer: 'varianceScaling' })); // 第四层为最大池化层 // S4 : feature maps 16@4x4 model.add(tf.layers.maxPooling2d({ poolSize: [2, 2], strides: [2, 2] })); // 第五层是一个特殊的卷积层,将多维张量扁平化为1维,从而连接后续的全连接层 // C5 : feature maps 256@1x1 model.add(tf.layers.flatten()); // 假设增加一个84个节点的全连接层 /* model.add(tf.layers.dense({ units:84, activation:'relu', useBias:true, name:'full-connection-layer' })) */ // 第六层为输出层,输出共10个类别,softmax激活函数的结果可以看做是概率值 // OUTPUT const NUM_OUTPUT_CLASSES = 10; model.add(tf.layers.dense({ units: NUM_OUTPUT_CLASSES, kernelInitializer: 'varianceScaling', activation: 'softmax' })); // Choose an optimizer, loss function and accuracy metric, // then compile and return the model const optimizer = tf.train.adam(); model.compile({ optimizer: optimizer, loss: 'categoricalCrossentropy', metrics: ['accuracy'], }); ```