【tensorflow.js學習筆記(1)】tf.js環境搭建及曲線擬合例子
月初TensorFlow開發者大會上,谷歌正式發布了TensorFlow的JS版本tensorflow.js,并演示了幾個很有意思的demo,展現了瀏覽器環境下也能進行深度學習任務的能力。tensorflowjs利用WebGl加速,在瀏覽器環境下訓練、部署機器學習模型。下面我嘗試引入tensorflow.js并運行一個曲線擬合的例子。
1、文件形式引入
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/[email protected]"></script>
<script>
const model = tf.sequential();
model.add(tf.layers.dense({units: 1, inputShape: [1]}));
model.compile({loss: 'meanSquaredError', optimizer: 'sgd'});
const x = tf.tensor2d([1, 2, 3, 4], [4, 1]);
const y = tf.tensor2d([1, 3, 5, 7], [4, 1]);
model.fit(x, y).then(() => {
model.predict(tf.tensor2d([5], [1, 1])).print();
});
</script>
首先調用tf.sequential()構建模型,損失函數為均方差,優化器為sgd(梯度下降)。待擬合的點序列為(1,1),(2,3),(3,5),(4,7),訓練模型,輸入x=5。
打開瀏覽器,輸出為:
Tensor
[[8.1529675],]
2、使用webpack
npm install @tensorflow/tfjs
首先利用npm安裝tensorflow.js(也可用yarn),新建index.js文件,內容如下。
import * as tf from '@tensorflow/tfjs';
const model = tf.sequential();
model.add(tf.layers.dense({units: 1, inputShape: [1]}));
model.compile({loss: 'meanSquaredError', optimizer: 'sgd'});
const xs = tf.tensor2d([1, 2, 3, 4], [4, 1]);
const ys = tf.tensor2d([1, 3, 5, 7], [4, 1]);
model.fit(xs, ys).then(() => {
model.predict(tf.tensor2d([5], [1, 1])).print();
});
利用webpack可使用import語法引入tf.js。配置webpack.config.js文件如下。
const path = require('path');
module.exports={
//入口文件的配置項
entry:{
entry: './index.js'
},
//出口文件的配置項
output:{
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
}
}
運行webpack命令,將在目錄下生成dist文件夾。cd進入該文件夾,用node運行bundle.js文件,輸出結果。
3、曲線擬合
參考Fitting a Curve to Synthetic Data,這是TensorFlow官方關于曲線擬合的例子,其中使用Vega進行可視化展示。下面我將用Echarts替換Vega進行可視化展示并重寫部分程序,代碼結構如下所示。
其中index.js為入口文件,dist文件夾下為分發文件,webpack.config.js的內容如下。
const path = require('path');
module.exports={
mode: 'development',
//入口文件的配置項
entry:{
entry: './src/index.js'
},
//出口文件的配置項
output:{
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
//控制臺報錯信息
devtool: 'inline-source-map'
}
index.html內容如下。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
#chart {
width: 800px;
height: 800px;
}
</style>
</head>
<body>
<div id="chart"></div>
<script src="bundle.js"></script>
</body>
</html>
入口文件index.js內容如下。
import * as tf from '@tensorflow/tfjs';
var echarts = require('echarts');
const a = tf.variable(tf.scalar(Math.random()));
const b = tf.variable(tf.scalar(Math.random()));
const c = tf.variable(tf.scalar(Math.random()));
const d = tf.variable(tf.scalar(Math.random()));
function predict(x) {
return tf.tidy(() => {
return a.mul(x.pow(tf.scalar(3, 'int32')))
.add(b.mul(x.square()))
.add(c.mul(x))
.add(d);
});
}
function loss(prediction, labels) {
const error = prediction.sub(labels).square().mean();
return error;
}
const numIterations = 75;
const learningRate = 0.5;
const optimizer = tf.train.sgd(learningRate);
async function train(xs, ys, numIterations) {
for (let iter = 0; iter < numIterations; iter++) {
optimizer.minimize(() => {
const pred = predict(xs);
return loss(pred, ys);
});
await tf.nextFrame();
}
}
function generateData(numPoints, coeff, sigma = 0.04) {
return tf.tidy(() => {
const [a, b, c, d] = [
tf.scalar(coeff.a),
tf.scalar(coeff.b),
tf.scalar(coeff.c),
tf.scalar(coeff.d)
];
const xs = tf.randomUniform([numPoints], -1, 1);
const ys = a.mul(xs.pow(tf.scalar(3, 'int32')))
.add(b.mul(xs.square()))
.add(c.mul(xs))
.add(d)
.add(tf.randomNormal([numPoints], 0, sigma));
const ymin = ys.min();
const ymax = ys.max();
const yrange = ymax.sub(ymin);
const ysNormalized = ys.sub(ymin).div(yrange);
return {
xs,
ys: ysNormalized
};
})
}
async function plotData(xs, ys, preds) {
const xvals = await xs.data();
const yvals = await ys.data();
const predVals = await preds.data();
const valuesBefore = Array.from(xvals).map((x, i) => {
return [xvals[i], yvals[i]];
});
const valuesAfter= Array.from(xvals).map((x, i) => {
return [xvals[i], predVals[i]];
});
// 二維數組排序
valuesAfter.sort(function(x, y) {
return x[0] - y[0];
});
curveChart.setOption({
xAxis: {
min: -1,
max: 1
},
yAxis: {
min: 0,
max: 1
},
series: [{
symbolSize: 12,
data: valuesBefore,
type: 'scatter'
},{
data: valuesAfter,
encode: {
x: 0,
y: 1
},
type: 'line'
}]
});
}
async function learnCoefficients() {
const trueCoefficients = {a: -0.8, b: -0.2, c: 0.9, d: 0.5};
// 生成有誤差的訓練數據
const trainingData = generateData(100, trueCoefficients);
// 訓練模型
await train(trainingData.xs, trainingData.ys, numIterations);
// 預測數據
const predictionsAfter = predict(trainingData.xs);
// 繪制散點圖及擬合曲線
await plotData(trainingData.xs, trainingData.ys, predictionsAfter);
predictionsAfter.dispose();
}
const curveChart = echarts.init(document.getElementById('chart'));
learnCoefficients();
首先引入tensorflow.js及echarts,之后定義4個參數a、b、c、d,分別是待擬合曲線y=a*x^3+b*x^2+c*x+d的四個參數,初始設為隨機值。
定義函數predict,傳入x,返回擬合后的估計值y。函數loss為損失函數,這里定義loss為均方差。
定義優化器optimizer,其中學習率為0.5,學習率過小會導致訓練速度慢,學習率過高會造成擬合參數在最優解附近“左右搖擺”。
定義async函數(Generator 函數的語法糖)train,train函數內根據迭代步數及學習率調用優化器并計算損失函數loss。
函數generateData隨機生成[-1, 1]范圍內的點,并根據傳入的a、b、c、d加上一定的隨機擾動生成數據點xs,ys,其中ys進行歸一化處理。
函數plotData將隨機生成的樣本點映射為散點圖,將根據訓練后的參數擬合出的點映射為曲線。
函數renderCoefficients將a、b、c、d的值輸出到document內。
函數learnCoefficients是index.js的main函數,函數內先設定預定義的a、b、c、d,再生成有誤差的訓練數據,利用訓練數據訓練a、b、c、d參數并參數輸出到文檔,之后利用訓練好的參數擬合x數據,將結果繪制為散點圖及曲線,最后通知GC清理。
此時擬合出的曲線圖會有bug,如下所示。
原因分析:
傳入echarts的點對是按生成順序排序的,是無序數組,但繪制曲線時是按傳入數組的順序連接各點,因此在傳入前需對二維數據進行排序。在curveChart.setOption前加入如下代碼。
// 二維數組排序
valuesAfter.sort(function(x, y) {
return x[0] - y[0];
});
結果如下。
完整程序見我的github,具體步驟為:
step1 新建文件夾,cmd輸入git clone [email protected]:orangecsy/tfjs-exercise.git,cd 1進入文件夾1;
step2 cmd輸入webpack,打包;
step3 cd dist進入dist文件夾,cmd中輸入http-server(需先npm install http-server)或使用webpack配置開發服務器;
step4 瀏覽器中輸入http://127.0.0.1:8080/,即為結果。
智能推薦
TensorFlow-平面曲線擬合
平面曲線屬于非線性函數,至少需要 3 層的神經網絡(輸入層,隱藏層x1,輸出層)來實現,為達到較好的效果,可嘗試更多層,下面的例子使用了2層隱藏層,采用最基本的全連接形式,隱藏層的神經元個數沒有嚴格要求,根據實際項目選擇,下面例子選用8個。 下面通過代碼實現: 引入相關庫,定義神經網絡層 生成些輸入數據并導入網路 因為要擬合平面曲線,輸入x和輸出y均為一維數據 搭建網絡 輸入層:神經元個數1(輸出...
【tensorflow.js學習筆記(5)】使用RNN學習“加法運算”
tensorflow.js實現了幾種RNN的接口,包括SimpleRNN、GRU和LSTM。這篇筆記介紹如何在瀏覽器環境下利用tensorflow.js訓練RNN學習加法運算,即給出一個加法算式的字符串,算出數字結果,類似于自然語言處理。 1、生成訓練、測試數據 digits代表輸入數字的位數,比如567的位數是3。函數f從digitArray中隨機挑選digits個數拼為一個輸入。輸入a、加號、...
【tensorflow.js學習筆記(2)】CNN識別手寫數字集MNIST
筆記(1)中利用tensorflow.js完成了機器學習中曲線擬合的任務,這篇筆記將實現一個經典的機器學習問題——CNN識別手寫數字集MNIST。參考官方示例Training on Images: Recognizing Handwritten Digits with a Convolutional Neural Network,修改部分代碼并用echarts改寫vega。...
TensorFlow.js入門(一)一維向量的學習
TensorFlow的介紹 TensorFlow是谷歌基于DistBelief進行研發的第二代人工智能學習系統,其命名來源于本身的運行原理。Tensor(張量)意味著N維數組,Flow(流)意味著基于數據流圖的計算,TensorFlow為張量從流圖的一端流動到另一端計算過程。TensorFlow是將復雜的數據結構傳輸至人工智能神經網中進行分析和處理過程的系統。 ...
JavaScript之機器學習2:Tensorflow.js
目錄 Tensorflow.js是什么? Tensorflow.js具體功能有? 安裝Tensorflow.js 什么是Tensor? 線性回歸 定義模型結構 損失函數:均方誤差(MSE)和優化器:隨機梯度下降(SGD) 訓練模型并可視化訓練過程 進行預測 1. Tensorflow.js是什么? 一個用JavaScript實現的機器學習庫 使我們可以直接在瀏覽器和Node.js中使用機器學習 2...
猜你喜歡
freemarker + ItextRender 根據模板生成PDF文件
1. 制作模板 2. 獲取模板,并將所獲取的數據加載生成html文件 2. 生成PDF文件 其中由兩個地方需要注意,都是關于獲取文件路徑的問題,由于項目部署的時候是打包成jar包形式,所以在開發過程中時直接安照傳統的獲取方法沒有一點文件,但是當打包后部署,總是出錯。于是參考網上文章,先將文件讀出來到項目的臨時目錄下,然后再按正常方式加載該臨時文件; 還有一個問題至今沒有解決,就是關于生成PDF文件...
電腦空間不夠了?教你一個小秒招快速清理 Docker 占用的磁盤空間!
Docker 很占用空間,每當我們運行容器、拉取鏡像、部署應用、構建自己的鏡像時,我們的磁盤空間會被大量占用。 如果你也被這個問題所困擾,咱們就一起看一下 Docker 是如何使用磁盤空間的,以及如何回收。 docker 占用的空間可以通過下面的命令查看: TYPE 列出了docker 使用磁盤的 4 種類型: Images:所有鏡像占用的空間,包括拉取下來的鏡像,和本地構建的。 Con...