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进行深度学习的开发了。