天天看點

Javascript 機器學習的四個層次選擇機器學習工具的方法論層次一:直接服務于具體領域的架構層次二:深度學習架構層次三:機器學習架構層次四:數學和統計庫總結

來源: Alibaba F2E

作者:旭倫

Javascript 機器學習的四個層次選擇機器學習工具的方法論層次一:直接服務于具體領域的架構層次二:深度學習架構層次三:機器學習架構層次四:數學和統計庫總結

Atwood定律說,凡是可以用Javascript實作的應用,最終都會用Javascript實作掉。作為最熱門的機器學習領域,服務端是Python的主場,但是到了手機端呢?Android和iOS裡預設都沒有Python。但是有浏覽器的地方就有js,現在還有個新場景 - 小程式。

除此之外,為了可以在不聯網情況下進行訓練的,也有支援本地架構比如React Native的。

可以說,隻要有前端的地方,就有機器學習的架構在。

js唯一的問題在于,變化太快,每年都有很多新庫出現,但是也有不少老的庫宣布不維護了。但是,萬變不離其宗,工具本身雖然經常有變化,但是它們的類型是非常穩定的。

選擇機器學習工具的方法論

我們要寫機器學習算法,需要什麼樣的工具呢?

機器學習工具可以分為以下四個層次:

Javascript 機器學習的四個層次選擇機器學習工具的方法論層次一:直接服務于具體領域的架構層次二:深度學習架構層次三:機器學習架構層次四:數學和統計庫總結

層次一:直接服務于具體領域的架構

首先我們需要直接服務于具體領域的架構,比如處理CV的,NLP的,推薦算法之類的。

比如nlp.js,上一個版本釋出在2020年10月。nlp.js的代碼寫起來是這樣的:

const { NlpManager } = require('node-nlp');

const manager = new NlpManager({ languages: ['en'], forceNER: true });
// Adds the utterances and intents for the NLP
manager.addDocument('en', 'goodbye for now', 'greetings.bye');
manager.addDocument('en', 'bye bye take care', 'greetings.bye');
manager.addDocument('en', 'okay see you later', 'greetings.bye');
manager.addDocument('en', 'bye for now', 'greetings.bye');
manager.addDocument('en', 'i must go', 'greetings.bye');
manager.addDocument('en', 'hello', 'greetings.hello');
manager.addDocument('en', 'hi', 'greetings.hello');
manager.addDocument('en', 'howdy', 'greetings.hello');

// Train also the NLG
manager.addAnswer('en', 'greetings.bye', 'Till next time');
manager.addAnswer('en', 'greetings.bye', 'see you soon!');
manager.addAnswer('en', 'greetings.hello', 'Hey there!');
manager.addAnswer('en', 'greetings.hello', 'Greetings!');

// Train and save the model.
(async() => {
    await manager.train();
    manager.save();
    const response = await manager.process('en', 'I should go now');
    console.log(response);
})();           

運作起來很簡單,裝個庫就好:

npm install node-nlp           

訓練的速度也很快:

Epoch 1 loss 0.4629286907733636 time 1ms
Epoch 2 loss 0.2818764774939686 time 0ms
Epoch 3 loss 0.16872372018062168 time 0ms
Epoch 4 loss 0.11241683507408215 time 0ms
...
Epoch 31 loss 0.00004645272306535786 time 0ms           

輸出的結果類似這樣:

{
  locale: 'en',
  utterance: 'I should go now',
  settings: undefined,
  languageGuessed: false,
  localeIso2: 'en',
  language: 'English',
  nluAnswer: {
    classifications: [ [Object] ],
    entities: undefined,
    explanation: undefined
  },
  classifications: [ { intent: 'greetings.bye', score: 1 } ],
  intent: 'greetings.bye',
  score: 1,
  domain: 'default',
  sourceEntities: [
    {
      start: 12,
      end: 14,
      resolution: [Object],
      text: 'now',
      typeName: 'datetimeV2.datetime'
    }
  ],
  entities: [
    {
      start: 12,
      end: 14,
      len: 3,
      accuracy: 0.95,
      sourceText: 'now',
      utteranceText: 'now',
      entity: 'datetime',
      resolution: [Object]
    }
  ],
  answers: [
    { answer: 'Till next time', opts: undefined },
    { answer: 'see you soon!', opts: undefined }
  ],
  answer: 'see you soon!',
  actions: [],
  sentiment: {
    score: 0.5,
    numWords: 4,
    numHits: 1,
    average: 0.125,
    type: 'senticon',
    locale: 'en',
    vote: 'positive'
  }
}           

層次二:深度學習架構

第二是我們的核心内容,深度學習架構。

說到Javascript深度學習,占統治地位的仍然是Tensorflow.js,我們來看個經典的強化學習的例子:

Javascript 機器學習的四個層次選擇機器學習工具的方法論層次一:直接服務于具體領域的架構層次二:深度學習架構層次三:機器學習架構層次四:數學和統計庫總結

使用浏覽器的local storage和indexdb作為存儲,邊訓練邊展示訓練效果的過程,很有前端的風範。

我們再看另一個大廠微軟的例子,支援webGL和wasm,基于浏覽器不容易:

Javascript 機器學習的四個層次選擇機器學習工具的方法論層次一:直接服務于具體領域的架構層次二:深度學習架構層次三:機器學習架構層次四:數學和統計庫總結

另外需要強調的是,用于前端的架構并不是簡單的把native或者python架構移植過來的,比如說它要處理相容性的問題:

Javascript 機器學習的四個層次選擇機器學習工具的方法論層次一:直接服務于具體領域的架構層次二:深度學習架構層次三:機器學習架構層次四:數學和統計庫總結

很多同學都對Tensorflow有一定了解,我們就手寫一個網頁,然後在其中調tf的API就好:

<!DOCTYPE html>
<html>
    <head>
        <meta encoding="UTF-8"/>
        <script src="https://cdn.jsdelivr.net/npm/@tensorflow/[email protected]/dist/tf.min.js"></script>
    </head>
    <body>
        <div id="tf-display"></div>
        <script>
            let a = tf.tensor1d([1.0]);
            let d1 = document.getElementById("tf-display");
            d1.innerText = a;
</script>
    </body>
</html>           

層次三:機器學習架構

第三是機器學習的架構。光了解深度學習還不夠,傳統的機器學習在更貼近業務的時候,可能效果更好,還節省算力資源。比如可以使用mljs庫,位址在:

https://github.com/mljs/ml

比如我們想做個k-means聚類,可以使用mljs架構的ml-kmeans庫:

const kmeans = require('ml-kmeans');

let data = [[1, 1, 1], [1, 2, 1], [-1, -1, -1], [-1, -1, -1.5]];
let centers = [[1, 2, 1], [-1, -1, -1]];

let ans = kmeans(data, 2, { initialization: centers });
console.log(ans);           

裝個包就可以玩了:

npm i ml-kmeans           

運作結果如下:

KMeansResult {
  clusters: [ 0, 0, 1, 1 ],
  centroids: [
    { centroid: [Array], error: 0.25, size: 2 },
    { centroid: [Array], error: 0.0625, size: 2 }
  ],
  converged: true,
  iterations: 2,
  [Symbol(distance)]: [Function: squaredEuclidean]
}           

我們也可以直接在網頁中使用,比如我們寫個K近鄰的例子:

<!DOCTYPE html>
<html>
  <head>
    <meta encoding="UTF-8" />
    <script src="https://www.lactame.com/lib/ml/4.0.0/ml.min.js"></script>
  </head>
  <body>
    <div id="ml-display"></div>
    <script>
      const train_dataset = [
        [0, 0, 0],
        [0, 1, 1],
        [1, 1, 0],
        [2, 2, 2],
        [1, 2, 2],
        [2, 1, 2],
      ];
      const train_labels = [0, 0, 0, 1, 1, 1];
      let knn = new ML.KNN(train_dataset, train_labels, { k: 2 }); // consider 2 nearest neighbors

      const test_dataset = [
        [0.9, 0.9, 0.9],
        [1.1, 1.1, 1.1],
        [1.1, 1.1, 1.2],
        [1.2, 1.2, 1.2],
      ];

      let ans = knn.predict(test_dataset);

      let d1 = document.getElementById("ml-display");
      d1.innerText = ans;
</script>
  </body>
</html>           

最後我們再來個決策樹的例子,采用mljs自帶的Iris資料集。需要通過npm安裝下ml-dataset-iris和ml-cart:

const irisDataset = require('ml-dataset-iris');
const DecisionTreeClassifier = require('ml-cart');

const trainingSet = irisDataset.getNumbers();
const predictions = irisDataset
  .getClasses()
  .map((elem) => irisDataset.getDistinctClasses().indexOf(elem));

const options = {
  gainFunction: 'gini',
  maxDepth: 10,
  minNumSamples: 3,
};

const classifier = new DecisionTreeClassifier.DecisionTreeClassifier(options);
classifier.train(trainingSet, predictions);
const result = classifier.predict(trainingSet);

console.log(result);           

輸出結果如下:

[
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1,
  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  1, 1, 1, 1,
  ... 50 more items
]           

層次四:數學和統計庫

第四個層次是數學和統計庫。做統計和數學計算,很多時候才是了解業務的最好手段。這個時候我們也不能空手上,也需要工具。

這方面的代表庫有stdlib:

https://stdlib.io/雖然它名字和實際都是标準庫

,但是為了數學和統計提供了很豐富的内容,比如150多個數學函數和35種統計分布。

我們先安裝一下做後面的實驗:

npm install @stdlib/stdlib           

比如各種數學函數:

Javascript 機器學習的四個層次選擇機器學習工具的方法論層次一:直接服務于具體領域的架構層次二:深度學習架構層次三:機器學習架構層次四:數學和統計庫總結

再比如各種随機分布:

Javascript 機器學習的四個層次選擇機器學習工具的方法論層次一:直接服務于具體領域的架構層次二:深度學習架構層次三:機器學習架構層次四:數學和統計庫總結

我們以正态分布為例,看看stdlib是如何描述分布的:

const Normal = require( '@stdlib/stats/base/dists/normal' ).Normal;
let dist1 = new Normal( 0, 1 );
console.log(dist1);
let m1 = dist1.mean;
console.log(m1);
let v1 = dist1.variance;
console.log(v1);           

構造Normal時的兩個參數是均值和方差。

輸出如下:

Normal { mu: [Getter/Setter], sigma: [Getter/Setter] }
0
1           

這個無良的标準庫竟然還支援50多種資料集,看個小例子,美國州首府的資料集:

const capitals = require( '@stdlib/datasets/us-states-capitals' );
const data_c = capitals();
console.log(data_c);           
[
  'Montgomery',     'Juneau',         'Phoenix',
  'Little Rock',    'Sacramento',     'Denver',
  'Hartford',       'Dover',          'Tallahassee',
  'Atlanta',        'Honolulu',       'Boise',
  'Springfield',    'Indianapolis',   'Des Moines',
  'Topeka',         'Frankfort',      'Baton Rouge',
  'Augusta',        'Annapolis',      'Boston',
  'Lansing',        'Saint Paul',     'Jackson',
  'Jefferson City', 'Helena',         'Lincoln',
  'Carson City',    'Concord',        'Trenton',
  'Santa Fe',       'Albany',         'Raleigh',
  'Bismarck',       'Columbus',       'Oklahoma City',
  'Salem',          'Harrisburg',     'Providence',
  'Columbia',       'Pierre',         'Nashville',
  'Austin',         'Salt Lake City', 'Montpelier',
  'Richmond',       'Olympia',        'Charleston',
  'Madison',        'Cheyenne'
]           

總結

綜上,如果要做從0到1的業務,盡可能用第一層次的工具,這樣最有助于快速落地。但是如果是要做增量,尤其是困難的增長,第三第四層次是首選,因為更有助于深刻了解資料。

Javascript 機器學習的四個層次選擇機器學習工具的方法論層次一:直接服務于具體領域的架構層次二:深度學習架構層次三:機器學習架構層次四:數學和統計庫總結