大數據

前端走進機器學習生態,在 Node.js 中使用 Python

作者 | 雷姆(Yorkie)

image.png

這次給大家帶來一個好東西,它的主要用途就是能讓大家在 Node.js 中使用 Python 的接口和函數。可能你看到這裡會好奇,會疑惑,會不解,我 Node.js 大法那麼好,幹嘛要用 Python 呢?如果你之前嘗試瞭解過一些機器學習的 JavaScript 的應用,就會比較清楚這背後的原因。

現狀是機器學習生態幾乎是捆綁在 Python 這門語言在高速迭代著的,而 JavaScript 只能望其項背,如果我們期望從零做到 Python 如今的規模,需要付出的工作量是巨大的,這個我在幾年前寫了 tensorflow-nodejs 的時候,就已經這麼覺得了。

所以,我們就必須換一個思路,既然無法超越你,那麼就利用你。對於腳本語言的開發者來說,其實並不在意底層是如何實現的,只要上層的語言和接口是我熟悉的就好,因此 Boa 就是為此而誕生的一個 Node.js 庫,它通過橋接 CPython 來讓 JavaScript 具備訪問 Python 生態的能力,另外又藉助於 ES6 新特性,來為使用者提供無縫的開發體驗,那麼到底是如何的體驗呢?

下面來看一個簡單的例子:

image.png

是不是很簡單呢,只需要通過 boa.import 將 Python 的對象加載進來後,剩下的對象訪問、函數調用以及數組訪問都與我們使用 JavaScript 毫無區別。

image.png

上面的例子除了示例瞭如何從 JavaScript 中繼承自一個 Python 的類之外,還展示了我們如何使用 PyTorch 來創建一個模型,這是不是很 JavaScript 呢?

值得一提的是,在 Boa 的代碼中,沒有對 PyTorch 做過任何的封裝,只要你在本地通過 Python 安裝了對應的包就可以像上面的代碼一樣使用了,所以理論上你可以對任何 Python 包做上面所做的事情。

接下來,我們分別介紹一些主要的方法。

builtins()

Python 會內置一些常用的方法在 builtin 中,具體的 API 列表在:https://docs.python.org/3.7/library/functions.html ,那麼 Boa 也提供了對應的方法:

image.png

import(name)

除了內置的方法外,最重要的功能便是加載 Python 包,那麼 import 就是做這個事兒的。

image.png

kwargs(map)

接下來是 Python 中的關鍵字參數(Keyword Arguments),在 Python 中,提供了一種使用 Map 的方式來表示參數,如:

image.png

它能更好地幫助調用者瞭解每個參數的含義,為此,在 Boa 中增加了 kwargs 方法來支持這種用法:

image.png

with(ctx, fn)

With 可能對於一些熟悉 JavaScript 歷史的人會比較眼熟,但 Python 中的 with,用法和目的並不與 JavaScript 相同,Python 中的 with 語句有點類似於 JavaScript 中的 Block Scoping:

image.png

上面的 Python 代碼是將 localcontext() 的狀態保存下來,然後開始執行 with 語句中的塊代碼,最後,將 localcontext() 的狀態釋放。

內部的實現機制就是每個傳到 with 語句中的變量需要實現兩個方法:enterexit,然後分別在塊代碼執行前後調用,因此對於 Boa 中的用法,如下:

image.png

上面的例子是 PyTorch 中一個普通的計算模型效果的邏輯,首先通過 torch.no_grad() 設置了一個上下文,然後開始執行計算的代碼,在塊代碼執行結束後,會自動將狀態恢復。

eval(str)

最後一個要說的,就是動態的執行一些 Python 表達式(單行),為什麼要提供這麼一個方法呢?這還是要說回 Python 的優勢,在一些很複雜的數據處理的場景,往往 Python 表達式還是能非常簡單易懂地表達,這樣就大大地減少了代碼的複雜度,我們先來看一個例子:

image.png

上面的代碼如果要換成 JavaScript 的話:

image.png

看著似乎差不多了多少是吧?那麼再來看看下面的例子:

image.png

怎麼樣,是否是感覺上面的例子已經沒法使用 JavaScript 簡單的一行就能搞定了呢?

不過值得一提的是,JavaScript 在這方面也在漸漸地彌補,這裡 是整理的一些 TC39 正在做的一些相關的標準,其中就包括上面的 Slice Notation。

說回到 eval 的定位,它像是對 JavaScript 的補充,它在一些標準還未落地和穩定之前,可以讓我們使用 Python 表達式來更簡單地表達,而所需要的僅僅是一些低成本的學習即可。

接下來就說說 eval 到底如何使用,它接受一個“字符串”,但我們一般在使用時都會通過 Template String,下來先看兩個例子:

image.png

看完上面兩行代碼,它們是比較少見的用法。真正常用,也是最能發揮出 eval 效果的是使用 Tagged Template String,這種用法就像我們一開始看到的一樣,在 eval 後面直接跟模版字符串的內容,這樣做的好處是 eval 函數會接收到所有的模版參數,這樣我們便可以將 JavaScript 的對象和 Python 表達式打通,實現更平滑的使用體驗,如下:

image.png

上面就是把 chunk 傳到了表達式中,再通過 Python 的 Slice Notation 語法去取到對應的值,最後返回到 JavaScript 的世界中。

如果想了解更多 API 和 Boa 的能力,可以到 Boa 的文檔瞭解。Boa文檔

另外,Boa 作為 Pipcook 的一個子項目,也非常歡迎大家來加入進來,對於想加入的同學可以通過這些 Issue 作為不錯的開始 。

最後再說一下 Boa 的初衷,就是希望能讓 Node.js 開發者更無縫地使用 Python 中豐富的機器學習生態。可以說,從今天開始,你就可以開始看著 Python 的文檔,使用 JavaScript 來“學習和使用”機器學習和深度學習了!


image.png
關注「Alibaba F2E」
把握阿里巴巴前端新動向

Leave a Reply

Your email address will not be published. Required fields are marked *