JS,一門從瀏覽器興起,卻不止於瀏覽器的腳本,我的一直認爲其是最有潛力的腳本語言。不僅是由於ES6優雅的語法,更重要的是其易上手,跨平臺的優勢。html
Node將JS從browser帶去了client是革命性的,使得經常被冠以「瀏覽器腳本」的JS成爲一門足以和PHP,PY匹敵的通用性腳本。前端
關於tensorflow,這裏就很少作介紹,簡而言之就是一個深度學習的框架,而爲衆人所知的是他對python的支持性很是高,幾乎能夠說到tf,那就是python的天下,以致於說到深度學習,衆人都會聯想到py,Google也是首推python在深度學習領域的使用,這和python早期與Google的淵源有關。不過,筆者屢次和py的交手後,對py的這種偏天然的語法及其不適應,很難接受這麼「優秀的語言」(寧願ruby,亦不python),這樣的感覺始於筆者最先一次使用深度學習作金融數據分析的畢業設計,python可把我害苦了。那時的我對JS愛不釋手,曾企圖使用JS本身構建神經網絡。vue
終於,tfjs仍是來了(在作畢設那會我就預言了要深度學習能夠徹底用JS開發),然而,Google最先對tfjs的態度(實際上是在Google大腦工做的開源開發者)彷佛仍是停留在「JS要在瀏覽器上跑」的這種觀念,因此筆者使用0.0.x版本都是基於瀏覽器開發的,@tensorflow/tfjs這個項目,其實在vue或者react等項目上很是的合適,可是對於client的node來講就不是那麼友好,不少接口是不支持的。node
下面來講說,這兩個項目的區別,打開 npmjs.com,搜索tfjspython
能夠看到,tfjs和tfjs-node,下面來講說這個兩個項目有什麼不一樣,tfjs是爲瀏覽器端而設計的,而tfjs-node是爲node端設計的。react
我的認爲,這兩個項目最大的區別就是存儲model的差異,早期的tfjs是基於瀏覽器的,故而能夠將訓練後的model存儲在localstorage,indexedb,固然還能夠經過formdata上傳至http服務器。下面我來測試一下:程序員
瀏覽器代碼web
<html> <head> <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs/dist/tf.min.js"> </script> <script> (async ()=>{ 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(); }); let save = await model.save('localstorage://model-1') })() </script> </head> <body> </body> </html>
在chrome的瀏覽器application中能夠看到已經存儲的localstorage,tfjs一共存儲了5個key-value,目前不懂裏面的意義是什麼
chrome
事實上我以前作爲前端也沒有使用過indexdb,主要仍是由於indexdb相對於webstorage過於龐大複雜,複雜的數據通常都丟給了後端用MySQL,筆者很是喜歡使用localstorage。如下嘗試使用indexdb存儲訓練模型數據庫
瀏覽器代碼
<html> <head> <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs/dist/tf.min.js"> </script> <script> (async ()=>{ let 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, 4], [4, 1]); const ys = tf.tensor2d([1, 3, 5, 7], [4, 1]); console.log('開始訓練') for(let i=0;i<2000;i++) await model.fit(xs, ys) console.log('訓練完畢') let save = await model.save('indexeddb://model-1') model = await tf.loadLayersModel('indexeddb://model-1'); model.predict(tf.tensor2d([10],[1,1])).print(); })() </script> </head> <body> </body> </html>
能夠看到訓練模型被存儲再indexdb數據庫中
前端代碼,訓練的過程是一毛同樣的,上述全部瀏覽器的深度學習法惟獨就是最後一步存儲不太同樣,這裏須要用到browserHTTPRequest的request請求,特別注意browserHTTPRequest不能夠再node下跑,會提示要求再瀏覽器中使用,傳輸的文件形式應該是經過form-data到達服務器的。
前端代碼
<html> <head> <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs/dist/tf.min.js"> </script> <script> (async ()=>{ let 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, 4], [4, 1]); const ys = tf.tensor2d([1, 3, 5, 7], [4, 1]); console.log('開始訓練') for(let i=0;i<2000;i++) await model.fit(xs, ys) console.log('訓練完畢') let save = await model.save(tf.io.browserHTTPRequest('http://localhost:3000/Upload/test', {method: 'PUT'})) })() </script> </head> <body> </body> </html>
後端node實現文件接受,轉儲
static async test(req,res){ let json = req.files.model.weights.bin.path let path = req.files.model.json.path const r = fs.createReadStream(json) const w = fs.createWriteStream('./test.json') r.pipe(w) }
上述代碼是一個代碼塊,因爲我用到了本身構建的一個node框架,是根據TP的MVC模式設計的,關鍵代碼如上,從req的files中取出文件,用fs模塊轉儲到特定目錄中。
以上所述均是tfjs框架的存儲方式,有很大的缺點,那就是在瀏覽器端訓練,訓練後的模型只能存儲在瀏覽器中,沒法作大數據的收集,即便能夠上傳到服務器,訓練的模型依然不能獲得安全,可持續化,完整的保證,固然也有其一些優勢,節省了大量服務器的資源,畢竟深度學習訓練若是涉及到圖形,音頻,語言文字的話是至關複雜和消耗資源的,將訓練過程合理的分壓到客戶端,最後再收集到服務器倒是一種很「雞賊」的手法,在這裏我只能說妙啊妙啊,不過這知足不了程序員的控制慾,下面介紹一下tfjs-node的存儲,因爲tfjs-node的安裝比tfjs複雜一些,如何安裝tfjs-node請查看筆者上一篇博客。
欲用文件系統,請先安裝tfjs-node。
node代碼
const tf = require("@tensorflow/tfjs-node"); 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([5,3,99], [3, 1])).print(); let save = await model.save('file://./model') })();
上述代碼中,其實訓練過程和存儲過程與browser大同小異,且存儲的API都是model的save方法。
使用上述代碼後,js所在的當前目錄會產生一個model目錄,並多出兩個記憶文件模型。
至此,tfjs-node了卻了我半年的顧慮,爲js作深度學習保存模型尋找一個文件系統的方式,這樣才能徹底使用js進行深度學習的開發了。