走進機器學習世界之TensorFlow.js快速上手

前言

近兩年人工智能,機器學習等各類概念漫天飛舞,那人工智能,機器學習,深度學習這些名詞之間是什麼關係呢?javascript

若是用三個同心圓來解釋的話,人工智能是最大的圓,機器學習是中間的圓,深度學習是最小的圓。具體解釋就是:html

  • 機器學習是實現人工智能的一種手段
  • 深度學習是實現機器學習的一種技術

今天咱們要介紹的TensorFlow.js是由Google的AI團隊發佈一款機器學習框架,基於DeepLearn.js(已經中止更新)。這款機器學習框架的特色是使用JavaScript語言,在瀏覽器中就可使用它提供的各類API來進行建模和訓練,而且支持Node.js。因此對於前端來講,是走進機器學習世界最便捷的路徑了。前端

這裏有一個利用TensorFlow.js實現的機器學習的小遊戲demo,你們能夠感覺一下。嘗試一下java

這篇文章基於TensorFlow.js的英文官方文檔寫成,重點在於TensorFlow.js的入門,關於機器學習更多的知識點可參考Google機器學習課程web

讓咱們開始吧!npm

安裝

直接引入

第一種方式是經過<script></script>直接引入,在瀏覽器中運行下面的代碼,在控制檯中能夠看到結果。api

<html>
  <head>
    <!-- Load TensorFlow.js -->
    <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@0.13.0"> </script>

    <!-- Place your code in the script tag below. You can also use an external .js file -->
    <script>
      // Notice there is no 'import' statement. 'tf' is available on the index-page
      // because of the script tag above.

      // 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, {epochs: 10}).then(() => {
        // Use the model to do inference on a data point the model hasn't seen before:
        // Open the browser devtools to see the output
        model.predict(tf.tensor2d([5], [1, 1])).print();
      });
    </script>
  </head>

  <body>
  </body>
</html>

npm或yarn

第二種方式是經過npm或yarn將TensorFlow.js的庫引入到你的項目中。數組

yarn add @tensorflow/tfjs  
npm install @tensorflow/tfjs

你能夠在你的main.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, {epochs: 10}).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();
});

若是不懂上面代碼的含義不要着急,繼續看後面的一些基礎概念和用法。框架

Tensor和Variable

Tensor和Variable是TensorFlow.js中最基礎的兩種數據形式。那他們究竟是什麼意思呢?

Tensor在谷歌翻譯中是「張量」的意思,「張量」這個詞是數學和物理中的一個術語,咱們暫且不深究它的意思,你只須要記住,Tensor(張量)是不可變的,相似於const,一旦定義就不能改變它的值。

Variable就很容易理解了,它是變量的意思,顧名思義,它的值是能夠改變的。

總之,Tensor(張量)不可變,Variable(變量)可變。

Tensor

張量一般是一個0到多維的數組,構造張量時會用到shape屬性,用來規定這是一個幾行幾列的數組。
請看下面構造一個張量的例子。shape用來規定這個張量是兩行三列的數組,而後能夠看到最後的輸出,咱們獲得了一個兩行三列的二維數組。

// 2x3 Tensor
const shape = [2, 3]; // 2 rows, 3 columns
const a = tf.tensor([1.0, 2.0, 3.0, 10.0, 20.0, 30.0], shape);
a.print(); // print Tensor values
// Output: [[1 , 2 , 3 ],
//          [10, 20, 30]]

也能夠用下面這種方式,直接表示這是一個兩行三列的二維數組。

// The shape can also be inferred:
const b = tf.tensor([[1.0, 2.0, 3.0], [10.0, 20.0, 30.0]]);
b.print();
// Output: [[1 , 2 , 3 ],
//          [10, 20, 30]]

然而實際上,咱們一般使用 tf.scalar, tf.tensor1d, tf.tensor2d, tf.tensor3d 和 tf.tensor4d來構造張量。tf.scalar是構造一個零維數組,也就是一個數字,tf.tensor1d是構造一位數組,tf.tensor2d是構造二維數組,以此類推。例如:

const c = tf.tensor2d([[1.0, 2.0, 3.0], [10.0, 20.0, 30.0]]);
c.print();
// Output: [[1 , 2 , 3 ],
//          [10, 20, 30]]

或者使用tf.zeros生成全是0的數組,tf.ones生成全是1的數組,例如:

// 3x5 Tensor with all values set to 0
const zeros = tf.zeros([3, 5]);
// Output: [[0, 0, 0, 0, 0],
//          [0, 0, 0, 0, 0],
//          [0, 0, 0, 0, 0]]

Variable

而Variable(變量)只能經過Tensor(張量)生成。咱們可使用assign給變量從新賦值。例如:

const initialValues = tf.zeros([5]);
const biases = tf.variable(initialValues); // initialize biases
biases.print(); // output: [0, 0, 0, 0, 0]

const updatedValues = tf.tensor1d([0, 1, 0, 1, 0]);
biases.assign(updatedValues); // update values of biases
biases.print(); // output: [0, 1, 0, 1, 0]

Operations

TensorFlow.js提供了各類向量運算的API,咱們能夠稱這些爲Operations。下面是張量平方和張量相加的例子:

const d = tf.tensor2d([[1.0, 2.0], [3.0, 4.0]]);
const d_squared = d.square();
d_squared.print();
// Output: [[1, 4 ],
//          [9, 16]]

const e = tf.tensor2d([[1.0, 2.0], [3.0, 4.0]]);
const f = tf.tensor2d([[5.0, 6.0], [7.0, 8.0]]);

const e_plus_f = e.add(f);
e_plus_f.print();
// Output: [[6 , 8 ],
//          [10, 12]]

並且TensorFlow.js還提供了鏈式運算,請看例子:

const sq_sum = e.add(f).square();
sq_sum.print();
// Output: [[36 , 64 ],
//          [100, 144]]

// All operations are also exposed as functions in the main namespace,
// so you could also do the following:
const sq_sum = tf.square(tf.add(e, f));

Model

上面咱們介紹了張量,變量和一些基礎運算,下面咱們引入「Model(模型)」這個概念。

模型就是一個函數,給定這個函數特定的輸入,會返回特定的輸出。

因此請記住,模型就是一個函數而已。

咱們來看一個定義模型的例子, 如下代碼構造了一個 y = a x ^ 2 + b x + c 的函數表達式,給定一個x,咱們會獲得一個y。

代碼中tf.tidy()看不懂請忽略,咱們將在下一節介紹,它只是用來清除內存。

// Define function
function predict(input) {
  // y = a * x ^ 2 + b * x + c
  // More on tf.tidy in the next section
  return tf.tidy(() => {
    const x = tf.scalar(input);

    const ax2 = a.mul(x.square());
    const bx = b.mul(x);
    const y = ax2.add(bx).add(c);

    return y;
  });
}

// Define constants: y = 2x^2 + 4x + 8
const a = tf.scalar(2);
const b = tf.scalar(4);
const c = tf.scalar(8);

// Predict output for input of 2
const result = predict(2);
result.print() // Output: 24

可是一般,咱們會使用一個更高級的API去構造模型,那就是用 tf.model 的形式,這裏的model只是模型的總稱,並無 tf.modal 這個方法。TensorFlow中最經常使用的是 tf.sequential,例如:

const model = tf.sequential();
model.add(
  tf.layers.simpleRNN({
    units: 20,
    recurrentInitializer: 'GlorotNormal',
    inputShape: [80, 4]
  })
);

const optimizer = tf.train.sgd(LEARNING_RATE);
model.compile({optimizer, loss: 'categoricalCrossentropy'});
model.fit({x: data, y: labels});

上面代碼中必定有不少你不理解的地方,好比什麼是 tf.layer?什麼是 tf.train.sgd?這裏能夠先忽略細節,先從整體上體會這些基本概念,關於 tf.train.sg 等咱們在後面的文章介紹。若是你忍不住,就本身去查吧!給你 官方API文檔 好了。

內存管理

TensorFlow.js使用GPU來加速運算,因此合理地釋放內存是一件很必要的事情。TensorFlow.js提供了dispose函數來釋放內存,請看例子:

const x = tf.tensor2d([[0.0, 2.0], [4.0, 6.0]]);
const x_squared = x.square();

x.dispose();
x_squared.dispose();

可是一般實際中咱們會面對不少的張量和操做,這時候 tf.tidy 更加方便,由於它是批量釋放內存,請看例子:

// tf.tidy takes a function to tidy up after
const average = tf.tidy(() => {
  // tf.tidy will clean up all the GPU memory used by tensors inside
  // this function, other than the tensor that is returned.
  //
  // Even in a short sequence of operations like the one below, a number
  // of intermediate tensors get created. So it is a good practice to
  // put your math ops in a tidy!
  const y = tf.tensor1d([1.0, 2.0, 3.0, 4.0]);
  const z = tf.ones([4]);

  return y.sub(z).square().mean();
});

average.print() // Output: 3.5

使用 tf.tidy 有兩個要點:

  • 傳遞給 tf.tidy 的函數必須是同步的。
  • tf.tidy 不會清理變量,你只能經過 dispose 手動清理。

總結

關於 TensorFlow.js 的基礎概念介紹完了,可是這只是咱們探索機器學習的一個工具而已,具體的實踐還須要更多的學習,後面有時間我也會跟你們一塊兒學習,並及時分享。

相關文章
相關標籤/搜索