最近在上海上班了,好久沒有寫博客了,閒下來繼續關注和研究Tensorflow.jsphp
關於深度學習的文章我也已經寫了很多,部分早期做品可能包含了很多錯誤的認識,在後面的博文中會改進或從新審視。html
今天聊聊神經網絡的入門知識,tensor!本章的題目就是「數據結構」,之因此把名字的含義取這麼廣,是由於,今天從tensor這種數據結構開始,但遠不止於tensor!前端
何爲tensor?讓咱們先看看tensorflow官網的解釋node
Tensors are the core datastructure of TensorFlow.js They are a generalization of vectors and matrices to potentially higher dimensions.nginx
tensor能夠翻譯爲「張量」,他是深度學習,tensorflow的核心數據結構,tensor是向量和矩陣的俗稱(generalization通常化,歸納),它具有潛在的更龐大的規模。這裏可能翻譯的不太好,不過能夠看出來學習深度學習必定要圍繞着tensor來,tensor規模可大可小,他真的過重要了。算法
tensorflow.js爲咱們提供了tensor數據結構的不少構造方法,這其中包含了1維,2維,3維等多種張量的構造方法,初始化方法,buffer緩衝,克隆方法。apache
返回:tf.Tensor類型npm
這是一個用於構造張量tensor的最基本方法,也是最實用的方法,若是你找不到什麼最好的構造的tensor方法或者沒法肯定一個結構必然是2d,3d等狀況下,儘可能實用tensor。編程
const tf = require("@tensorflow/tfjs"); tf.tensor([1,2,3,4]).print()
打印結果:canvas
這是一個一維矩陣,先無論有什麼用,有什麼意義,咱們暫且理解爲一個一維的矩陣。1×4(1行4列)
還能夠將一維轉成2×2:tf.tensor([1,2,3,4],[2,2]).print();
或者直接構造2×2的tensor:tf.tensor([[1, 2], [3, 4]]).print();
,效果同上
返回:tf.Tensor類型
能夠對張量tensor進行初始化填充,以下:tf.fill([2, 2], 4).print();
fill的第一個參數是矩陣的結構,[2,2]表示2行2列的矩陣,第二個參數是要初始化的值,這就像普通編程下對數組的初始化,將每個單元填充一個默認數。
返回: tf.TensorBuffer
乍一看這個方法有點難以理解,該方法返回一個tensor的buffer,buffer是緩衝的意思,在緩衝區能夠對tensor的任何單元隨意修改,經過tensorbuffer對象中的set方法動態修改矩陣中某個位置的數據值。來看個實例:
const tf = require("@tensorflow/tfjs"); const bf = tf.buffer([2,2]); bf.set(3,0,0); bf.set(2,0,1); bf.set(5,1,0); bf.set(1,1,1); bf.toTensor().print()
運行結果:
首先構造了一個tensorbuffer對象用於對矩陣數據的規劃,使用set來單獨設置矩陣中每個單元的數據。
案例中使用了set方法傳入的參數分別是(值,行,列),也就是說set方法第一個參數是矩陣單元的值,而第2,3,4...表明了這個數據單元在矩陣的位置。
最終使用toTensor將矩陣(張量)從buffer中取出,獲得真正的tensor數據結構對象。
注意,tensor有多是3維的,那樣set應該有4個參數了,那麼仍是用buffer,作個簡單例子驗證一下猜測:
這個矩陣顯得就相對複雜一點,這是一個三維張量了,2×2×2,能夠這麼理解:在空間上數據向三個方向發展,每一個方向限量2個值,我不知道在線性代數中,3維度的張量可否稱爲矩陣,若是我術語有錯誤還請指正,不過這不重要,你們理解編程中的意思就行,我我的是把張量=tensor=矩陣進行表述的。
更多的對tensor數據結構的構造方法就不作介紹了,我以爲也不經常使用,使用方式大同小異,例如
tf.tensor1d
tf.tensor2d
tf.tensor3d
...
參考tensorflow官網給出的API。
說了這麼多,tensor爲何重要?咱們構造這些各類維度的矩陣到底有什麼用呢?
這裏就要說到數學做爲工具在現實生活中的意義了。
數學,我粗略的理解就是,使用數字,符號,邏輯去表達或描述現實。
而某個事物存在的各類屬性以及這些屬性攜帶的值均可以用張量來表示,例如在使用深度學習分析一張圖片:
首先,計算機不能「見圖識義」,一張圖片不能直接交給計算機處理,須要將圖片轉換爲一個張量(矩陣),這個矩陣中單個元素,也就是一個像素點,通常是這樣的:[R,G,B,A],而爲了構成整個圖片,須要行和列,因此最終的tensor數據結構是:[800,600,4],表明有800行,600列,這個平面上的一個單元還擁有4個值,表明了紅綠藍和透明度。
深度學習識別圖片所屬分類(例如讓計算機看出一張圖上是一隻貓)的過程實際是對多個矩陣特徵的學習和分析(理論上無數個),得到矩陣中某個點某個值出現的機率,將這些機率構成網狀的多層神經網絡,將一個新矩陣(新圖片)傳入後通過多層的矩陣變化計算,得出一個機率最大的結論。固然其中還有不少的數學知識,例如線性函數,非線性化,歸零化,反向求導,優化器等,之後慢慢解釋。
咱們先不對圖片識別作過多的解釋,先使用代碼模擬一張虛擬圖片出來。
const tf = require("@tensorflow/tfjs"); let color = new Array(); for (let i=0;i<400;i++){ color[i] = new Array(); for(let j=0;j<300;j++){ color[i][j] = new Array(); color[i][j]= [Math.floor(Math.random()*256),Math.floor(Math.random()*256),Math.floor(Math.random()*256),1]; } } console.log(color); tf.tensor(color,[400,300,4]).print()
上述代碼構造了一個三維數組,每個元素是隨機生成的0-255的數值,表明RGB值。
這實際是一張800×600,透明度爲100%(不透明)的隨機彩色圖片。(這裏不展現出來了,也不難,能夠結合html實現)
在這個基礎上,咱們還能夠反向將圖片轉換爲矩陣,咱們來看一個官方提供的方法:
該方法能夠將canvas圖片轉換爲tensor,很棒,就是圖片轉換爲矩陣咯,咱們來試試。
注意:這裏須要在前端中使用tfjs了。咱們離開node.js構建瀏覽器文件。
打開apache或者nginx服務器,啓動http,你可使用nodejs或者wamp,由於之前php開發多,我使用的是wamp集成環境,這裏注意,請務必在http下測試該案例,使用IP訪問,直接運行html頁面,tfjs會報錯!這是http secure致使的!
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@0.11.7"></script> <style> #canvasImg{ width:320px; height:480px; } </style> </head> <body> <img id="originImg" src="./timg.jpg" alt=""> <canvas id="canvasImg"> </canvas> <script> window.onload=function(){ var originImg = document.getElementById("originImg"); var canvas = document.getElementById("canvasImg"); canvas.width=320; canvas.height=480; canvas.getContext("2d").drawImage(originImg, 0, 0); setTimeout(function(){ var tensor = tf.fromPixels(canvas); tensor.print(); },2000) } </script> </body> </html>
案例使用的圖片以下,320×480像素
那麼,這裏已經將圖片轉換爲console中的tensor數據結構,這就是圖形識別,圖形處理的基礎啦,之後就可使用tensor進行神經元訓練,而後發揮想象吧,圖像識別,自動繪圖,圖片美化都不是問題!是否是極有意思呢。更多實踐之後進行圖形識別項目時再作介紹了。
對了,到這裏補充一下_(:з」∠)_,我剛剛發現TensorFlow官方給出了toPixels方法,也就是和fromPixels方法相反,將tensor生成圖片,也就是說,咱們剛剛生成的隨機數圖片能夠直接經過tfjs轉換爲圖片了,方法以下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@0.11.7"></script> </head> <body> <canvas id="canvasImg"> </canvas> <script> window.onload=function(){ var tensorImg = randomTensor(); tensorImg.print(); var canvas = document.getElementById("canvasImg"); canvas.width=800; canvas.height=600; tf.toPixels(tensorImg,canvas) } function randomTensor(){ var color = new Array(); for (let i=0;i<400;i++){ color[i] = new Array(); for(let j=0;j<300;j++){ color[i][j] = new Array(); color[i][j]= [Math.floor(Math.random()*256),Math.floor(Math.random()*256),Math.floor(Math.random()*256)]; } } return tf.tensor(color,[400,300,3],'int32'); } </script> </body> </html>
根據代碼算法,每一個點都是隨機數,因此生成圖也沒啥意思,隨便看看就行(⊙o⊙)!