1. 程式人生 > >利用tensorflow.js實現JS中的AI

利用tensorflow.js實現JS中的AI

非常感謝( Seth Juarez)[twitter.com/sethjuarez]提供的這篇文章。

這不是一篇關於數學的文章,也不是一篇闡述邪惡的有知覺的人工智慧最終會殺死我們所有人文章(我是不會訂閱這類的文章)。親愛的讀者們,這篇文章的目的是帶你走上一條別人未走過的路,那便是講述關於軟體工程的過程以及AI和JS目前的樣子。 每當我們試圖建立軟體時,我們都會提出無數個問題並編寫程式碼來解決問題(包括所有的邊界情況)。考慮這樣一種情況,你的任務是編寫一個函式,該函式給定一個由整陣列成的二維陣列,要求您返回它看上去最相似的數字。

準確的說,你正在編寫一個識別數字的函式,得到的陣列看上去是下面這樣的(在這種情況下你應該返回5)。

我們為了完成這種任務,不得不編寫蹩腳程式碼——我們知道這種程式碼太過鬆散,一旦將其投入生產,我們就會覺得需要重構(或做點什麼)。

你和我都會發現程式碼中有充斥著大量的if判斷和for迴圈語句,但是我們又必須使用它們,來建立必要的程式。

然而,面對這類任務,最佳選擇便是機器學習(人工智慧的一個子領域)。機器學習的優勢在於我們不需要為了解決問題考慮一系列的步驟,而是給予機器學習演算法一些正確的例子,如下圖。它便會給出正確的步驟。

過程

雖然本文的主要目的不是去研究這些演算法如何實現,但是在實際軟體程式中,瞭解其運用的基本過程和主要輸出是非常重要的(本文以JS為例)。資料科學家經常會使用以下幾個步驟:

  1. 定義問題(識別數字);
  2. 給出資料(MNIST資料集);
  3. 建立最優模型(實際功能的抽象);
  4. 模型運用

作為開發人員,我們的工作介於步驟3和步驟4之間。

模型

通常,這些模型利用機器學習框架,以Python語言進行建立。這個過程需要很長的時間,並且依賴大量的資料。這是非常容易讓人乏味和感覺沮喪的。然而,一旦完成了冗長和令人沮喪的部分,就會有一個實際檔案輸出來表示模型。你應該把它看作是你專案的一項資產。在使用TensorFlow的情況下,輸出通常是一個protobuf檔案。

TensorFlow.js

這裡,我要提醒大家,我並不認為我自己是一個JS專家,所以,如果我錯了或有更好的解決方案,請務必告知我。這部分內容重點是向你展示如何在JavaScript應用程式中使用模型,我們會用到(TensorFlow.js)[

js.tensorflow.org/],它被宣傳為訓練和部署機器學習模型的框架,而我們將重點關注部署部分,因為通常大多數模型都是由使用全強度TensorFlow python包的資料科學家建立的。我承認,在某些情況下,在客戶端進行遷移學習聽起來非常有趣。

建立模型並將它轉換到TensorFlow.js的過程還是非常簡單的(這裡不做介紹,但它確實是一個很有趣的練習,建議有機會你還是完全可以做一下),參考(github.com/sethjuarez/…)

現在,我們開始實際例子:

在這個情況下,我決定使用vue.js。因為我有一些框架方面的經驗,而且已經有一個(元件)[codepen.io/getflourish…]完成了大部分的畫布繪製工作。

code

使用實際模型時,有兩個重要的部分:

  1. 載入模型
  2. 呼叫模型

讓我們依次看一下:

載入模組

建立一個vue元件看上去時一個不錯的idea,因為我可以為整個元件只加載一次模型,並且把它保留在記憶體中。

    mounted: async function () {
        ... other things...
        // load model
        const MODEL = 'model/tensorflowjs_model.pb';
        const WEIGHTS = 'model/weights_manifest.json';
        this.model = await tf.loadFrozenModel(MODEL, WEIGHTS);
    }
複製程式碼

我認為我可以選擇vue生命週期中的另外一個鉤子,但是目前mounted看上去不錯。一旦this.model被掛載,無論什麼時候Predict按鈕被點選,這個模型都會被使用。(另外一個有趣的現象是滑鼠擡起時,模型也會使用,進行預測)。

呼叫模組

現在我們來看我們如何來呼叫模型的例子:

    predict: async function() {
            const digit = this.getDigit();
            const d = tf.tensor1d(digit).reshape([1, digit.length]);
            this.probabilities = await this.model.execute({'x': d}).reshape([10]).data();
            this.prediction = this.probabilities.indexOf(Math.max(...this.probabilities));
        }
複製程式碼

getDigit()方法獲取手繪的影象,做兩件事:

  1. 縮小到28*28的影象
  2. 獲取數字型別的陣列,將其輸入進模型

關鍵呼叫是this.model.execute(…)。這是我們實際傳遞陣列並使模型運轉的地方。 模型輸出的結果是一個長度為10,包含每個數字出現概率的陣列。換句話說,在陣列索引為0是它認為數字為0的概率(以此類推)。

思考

雖然本文並沒有詳細介紹如何建立這個應用程式,但它的目的是讓您瞭解如何使用TensorFlow.js在現代JavaScript中使用機器學習模型。

瞭解更多,移步github倉庫(github.com/sethjuarez/…)