JS做深度學習1——偶然發現與入門
不久前,我初次涉獵了Node.js,並且使用它開發了畢業設計的WEB模塊,然后通過在Node中調用系統命令執行Python文件方式實現了深度學習功能模塊的對接,Python代碼的介入,讓JS代碼顯得很累贅,我說過我很愛ES6以后的JS並且很討厭Python的代碼風格,無奈,我在寫畢設那會Google還沒有正式發布基於JS的深度學習框架,好吧,其實我對這事已經抱怨了很久,但是我的“呼聲”仿佛很快就被Google“認同了”(滑稽),就在我答辯結束不久,2018年4月官方的TensorFlow.js推出了,簡稱tfjs。
項目簡介
當我今天早上才發現這個項目的存在時,github上的star數目已經高達7k+,而距離項目發起才短短的3個月的時間!不禁感嘆,這一天終於還是到來了,JS最終沒有放過deep learning哈哈哈。
下面是項目的詳情,地址是:https://github.com/tensorflow/tfjs
Google TensorFlow官方指南地址是:https://js.tensorflow.org/tutorials/
注意到這個項目實際提交者叫“caisq”,有人會問他是誰呢?顯然是個有來頭的人。我在github上找到了他的真實姓名——“蔡善清”,看上去像是個華人,連忙上百度查到了他的個人博客,不看不知道,一看嚇一尿,真滴是個大佬級別的人物,大概意思就是現任Google大腦的工程師,畢業於清華大學的工學學士學位,還擁有什么Harvard-MIT XXX學院的Ph.D學位,我也看不懂,就知道是什么哈佛-麻省(合體嗎?)博士,厲害的一塌糊塗的樣子,我佩服的五體投地,為我們中國人感到驕傲!
關於他的地址:http://scai.io/
安裝與入門
在github的README頁面和TensorFlow官網上都有“helloworld”的案例給出,講述了核心思想和編程入門,這其中當然就有安裝TensorFlow.js的方式,下面我們來看看入門案例,我這里就直接照搬翻譯官方的教程,同時做出一些易於理解的改進。
第一步安裝
既然是JavaScript,既可以運行於瀏覽器,亦可在Node中運行,官方給出的也是這兩種運行環境。有趣的是官方特別強調了WebGL接口和瀏覽器,這在官網的引言中可以看出來,等我后面體驗了WebGL在做介紹。
瀏覽器JS安裝:
使用cdn安裝直接在script標簽下引入在線js地址:
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@0.11.1"> </script>
NodeJS npm安裝:
個人建議項目開發直接新建package.json,然后npm install:
{
"name": "",
"description": "",
"version": "0.0.1",
"dependencies": {
"@tensorflow/tfjs": "latest"
}
}
注意,這里必須是“@tensorflow/tfjs”,引入的時候也必須是完整的。
官方給出的是全局安裝:
yarn add @tensorflow/tfjs
npm install @tensorflow/tfjs
第二步:“HelloWorld!”
我們從基本例子開始,官方首頁給出的example是一個線性回歸案例,這也是TensorFlow的經典入門案例,什么是線性回歸,其實之前的博客也提到,就是一種類似“待定系數”求y=kx+b中的k和b的過程,這也是深度學習的核心思想。注意,以下案例全部基於Node.js編碼運行。
下面是官方給出案例:
import * as tf from '@tensorflow/tfjs';
// Define a model for linear regression
const model = tf.sequential();
model.add(tf.layers.dense({units: 1, inputShape: [1]}));
// Prepare the model for training: Specify the loss and the optimizer
model.compile({loss: 'meanSquaredError', optimizer: 'sgd'});
// Generate some synthetic data for training
const xs = tf.tensor2d([1, 2, 3, 4], [4, 1]);
const ys = tf.tensor2d([1, 3, 5, 7], [4, 1]);
// Train the model using the data
model.fit(xs, ys).then(() => {
// Use the model to do inference on a data point the model hasn't seen before
model.predict(tf.tensor2d([5], [1, 1])).print();
});
這個案例開發了這樣一個模型,一共有一層神經網絡,一個神經元,每次輸入一個數據,得出一個目標數據,給出4個訓練數據和4個訓練后參照的目標數據,分別是1,2,3,4(x)和1,3,5,7(y),求y=kx+b。最后四行代碼向model中輸入一個機器從未見過的數字x,讓他根據規律得出一個目標值y。
這里有一些小毛病,我們來說一說:
首先是node.js至今都未正式支持import,export關鍵詞(我也是醉了,我下載的是10.X版本了都),退一步說必須將案例代碼中import改為require來引入tfjs。
然后是這個案例不明不白,不適合TensorFlow初學者理解,因為案例沒有列出完整訓練過程,導致運行后會出現不同結果。也就是這個模型輸入一個未知的數字x,最終是不能給出一個合理的結果y的。
我對代碼進行了改進,加入了訓練過程,使代碼模擬求y=2x+1的線性函數。如下:
const tf = require("@tensorflow/tfjs");
const model = tf.sequential();
//定義網絡結構,層數,單元數,輸入
model.add(tf.layers.dense({units: 1, inputShape: [1]}));
//定義優化器
model.compile({loss: 'meanSquaredError', optimizer: 'sgd'});
//目標:y=2x+1;
const xs = tf.tensor2d([1,2,3,5], [4,1]);
const ys = tf.tensor2d([3,5,7,11], [4,1]);
//使用async是因為訓練中有異步操作,需要用到await
(async ()=>{
//訓練1000次
for(let i=0;i<1000;i++){
await model.fit(xs,ys);//等待訓練的異步操作
console.log(`第${i}次`);
}
model.predict(tf.tensor2d([100], [1, 1])).print();
})();
這樣代碼運行起來就顯得很明白,結果是:
我對模型輸入的是四組訓練數據,共訓練了1000次,訓練結束后,像模型輸入100,得到201,基本接近目標,成功!(記住,深度學習是一個趨於精確的過程,不像人類一樣一次獲得標准結果)。
接下來,我將繼續深入學習Node.js技術,並主攻其在深度學習領域的運用,通過博文分享我的成果!(畢竟我期待TensorFlow.js已經很久了!)