開發與維運

AI (愛) JavaScript , Pipcook 1.0 正式發佈

作者 | 雷姆(Yorkie)

image.png
Pipcook 項目從去年12月向 GitHub 提交第一行代碼以來,已經過去了半年的時間,這半年 Pipcook 開發團隊完成了從0到1的設計,也吸納了10多位來自社區貢獻者的意見,不斷改進 Pipcook 的使用體驗。

昨天,Pipcook 對社區正式發佈 1.0 版本,接下來就跟著文章,一起來看看 Pipcook 1.0 都有哪些功能吧!

開源地址:https://github.com/alibaba/pipcook

AI ❤️JavaScript

機器學習正在高速發展的過程中,無論是推薦系統、計算機視覺、自然語言處理、還是各種語音識別和自動駕駛技術,在機器學習的加持下,都在不斷地變得越來越好用和可靠。但作為前端工程師的我們,儘管社區內已經有了 Tensorflow.js、ONNX.js 等前輩存在,但機器學習離 JavaScript 開發者仍然很遠,原因有二:

  1. JavaScript 自身所沉澱的機器學習生態仍然不夠成熟和穩定;
  2. JavaScript 對於機器學習/深度學習最前沿的算法和模型的支持總是滯後的;

那麼 Pipcook 究竟是如何解決以上兩個問題並讓 AI 愛 JavaScript 的呢?答案之一就是 —— Boa,在 Pipcook 的設計哲學中,我們並不迷信所謂的 JavaScript 邪教 —— “任何能被 JavaScript 重寫的都將會使用 JavaScript 重寫”,Pipcook 開發團隊更在意用戶的使用體驗,而非使用何種語言去實現它。

image.png

從上圖可以看出來,我們在構建 Pipcook 的過程中,使用了多種編程語言和技術,其中 TypeScript 和 JavaScript 加起來僅不到 25%。

在 Pipcook 中,通過 Boa 提供了無縫使用 Python 生態的能力,解決了機器學習與 JavaScript 的物理距離,但還剩下所謂的“理論”距離 —— 讓前端工程師進化為機器學習軟件工程師。
image.png
如果說通過 Node.js,能幫助前端工程師轉職成為服務端工程師,那麼 Pipcook 在這方面,也希望成為前端工程師們進階為機器學習軟件工程師的利器。

那麼,在瞭解了為什麼會有 Pipcook 之後,就來看看 Pipcook 本身的項目定義:

Pipcook 是一個為前端工程師打造的機器學習工具集

與此同時,Pipcook 引入了兩個不算太新的概念:

  1. Pipeline 作為目前 Pipcook 最核心的功能提供,用於描述(JSON)並構建單個機器學習模型;
  2. PipApp 作為實驗性質的功能提供,它通過提供更高級的使用方式,屏蔽了模型部署和訓練的細節,讓工程師只需關注機器學習的“業務邏輯”;

另外,Pipcook 分別提供了 Pipcook Tools(命令行工具)和 Pipboard(GUI 工具)來讓用戶使用 Pipeline 和 Pipboard。

什麼是機器學習呢?

在開始正式介紹 Pipcook 之前,我們先為一些新手同學科普下什麼是機器學習,若你已經瞭解,可以直接跳過。

首先,機器學習發展至今,已經成為了一種全新的思維模式,它不同於我們傳統的編程思維,因為後者在思考和工作的過程中,雖然有明確的計算機分層,但最終從上至下的邏輯都是清晰可見的,也是易於解釋的,而對於應用程序本身,要麼是按照 OO 的思想在設計虛擬世界中的每一個實體和抽象,亦或者 FP 中的輸入與輸出,總而言之,我們在設計時,必須對細節瞭然於胸。

但對於機器學習來說,其思維方式更像是通過代碼構建了一個在通用與不通用之間的數據結構(即模型),然後將真實的數據輸入到這個數據結構中,不同的數據輸入就能產生不同的結果,而我們把這個產生的過程稱為訓練。對於一個問題而言,已經不需要我們將具體的操作步驟完全定義出來了,我們讓機器取代我們的思考過程,從數據中去學習潛在的規律,這樣的方式更適合一些更為複雜的問題,比如當很多數據產生時,人腦已經很難進行歸納和抽象時,往往使用機器學習會取得更好的效果。

所以,可以看得出來,機器學習並非是為了完全取代人類。相反,正如一開始蒸汽革命與電氣革命一樣,機器學習是取代那部分對於人類來說繁瑣,難以歸納和抽象的工作,而人類將藉助於機器學習,可以站在更高的角度去解決遇到的問題。

那麼對於機器學習本身來說,它也不是萬能靈藥,而在 Pipcook 中,把機器學習分為了圖片和文本兩大類,其中每一類都包括了對應的一些任務,如下:
image.png
比如在前端智能化最常見的設計稿生成代碼的場景中,就使用了圖片分類和目標檢測來提取設計稿的信息,提供給代碼生成器。

在 Pipcook 中,針對每一類的任務,也就對應於一個 Pipeline —— 即一個模型,在接下來的系列文章中,我們也會針對典型的一些 Pipeline 提供單獨的教程。

什麼是 Pipeline

在瞭解了機器學習與 Pipcook,接下來就可以學習 Pipcook 中的 Pipeline 了,在前面也提到了 —— 一個 Pipeline 對應於一個模型,也就是說每個 Pipeline 就是通過輸入一些插件和配置,然後最後輸出一個訓練好的模型。

整個過程我們通過下圖來做一個簡單的說明:
image.png
這條 Pipeline 是從左下方開始的:

  1. data collect 插件按照機器學習任務的類型(視覺/文本),將輸入的數據集轉成 Pipcook 內部標準的數據格式,PascalVoc 與 CSV;
  2. data access 插件則負責將 Pipcook 標準數據集格式轉換為模型需要的 UniDataset,當中,如果配置了 data process 流程,會將數據集中的每一行數據通過 data process 進行預處理;
  3. 處理好的 UniDataset 就分為元信息和訓練集兩個部分,分別傳到 model define 和 model train 插件;
  4. model define 插件通過數據集的元信息來定義模型的形狀和結構,定義完成後進入下一階段;
  5. model train 插件通過將 UniDataset 中的訓練集輸入到定義的模型中進行訓練,完成後進入下一個階段;
  6. model evaluate 插件將 UniDataset 中的測試集輸入到訓練好的模型中,以此來對模型最終的效果進行評估,若結果滿足要求,則輸出可以使用的模型;

以上就是一個基本的 Pipeline 流程,那麼我們來看看 Pipeline 具體是長什麼樣子:


{
"plugins": {
"dataCollect": {
"package": "@pipcook/plugins-mnist-data-collect",
"params": {
"trainCount": 8000,
"testCount": 2000
      }
    },
"dataAccess": {
"package": "@pipcook/plugins-pascalvoc-data-access"
    },
"dataProcess": {
"package": "@pipcook/plugins-image-data-process",
"params": {
"resize": [224, 224]
      }
    },
"modelDefine": {
"package": "@pipcook/plugins-tensorflow-mobilenet-model-define",
"params": {
"batchSize": 8,
"freeze": true
      }
    },
"modelTrain": {
"package": "@pipcook/plugins-image-classification-tensorflow-model-train",
"params": {
"epochs": 15
      }
    },
"modelEvaluate": {
"package": "@pipcook/plugins-image-classification-tensorflow-model-evaluate"
    }
  }
}

從上圖可以看到 Pipeline 十分簡單,只需要按照預先定義的字段配置你需要的插件及參數即可,然後再通過 Pipcook Tools 來運行它就行了:

pipcook run https://foobar.xzz/mobilenet-classification.json

Pipcook Tools 支持運行本地和遠程的 Pipeline,這意味著開發者可以通過 CDN、GitHub 或者任意 HTTP 服務來分享你的 Pipeline。

在經過一定時間的訓練之後,就會在當前目錄下的 output 文件夾下看到生成的模型文件和相關的 JavaScript 庫了:

image.png

生成後的使用方式也十分簡單:

$ cd ./output && npm install
$ node -e "require('./output')('input data')"

除此之外,你也可以通過 Pipboard 隨時下載歷史的訓練結果,如下圖所示:
image.png
為了方便開發者使用,Pipcook 已經內置了一些任務類型的 Pipeline:

  • 文本類

    • 文本分類:text-bayes-classification(基於樸素貝葉斯的分類)、fasttext-classification(基於 FastText 的文本分類)
    • 文本創作:chinese-poem-creation(生成中國詩歌)
  • 視覺類

    • 圖片分類:mobilenet-image-classification(基於 mobilenet 的圖片分類)
    • 目標檢測:object-detection(基於 detectron2 開發的目標檢測)
    • 圖片風格遷移:image-generation-cycle-gan(基於 CycleGAN 的圖片生成)

如何開發插件

通過上面的介紹,讀者基本已經瞭解了 Pipcook 主要的使用場景了,對,那就是 —— Pipeline,但要說到 Pipeline 卻離不開插件,我們為 Pipcook 的 Pipeline 生態構建了一套開放的插件機制,通過這套機制,任何開發者都可以隨時隨地基於 Node.js 為 Pipcook 拓展插件。

首先,一個插件,也是一個 NPM 包,在 NPM 包的基礎上,Pipcook 增加了一些拓展字段,即在 package.json 中增加了一些額外的定義,下面就是一個簡單的定義:

{
"name": "my-own-pipcook-plugin",
"version": "1.0.0",
"description": "my own pipcook plugin",
"dependencies": {
"@pipcook/pipcook-core": "^0.5.0"
  },
"pipcook": {
"category": "dataCollect",
"datatype": "image"
  },
"conda": {
"python": "3.7",
"dependencies": {
"tensorflow": "2.2.0"
    }
  }
}

首先,每個插件都必須依賴 @pipcook/pipcook-core,它包含了實際定義插件所依賴的類型定義和一些工具函數。然後是 "pipcook" 節點,它定義了插件的基本信息,比如類別和數據類型,它用於 Pipcook 對插件本身做歸類和整理,接下來就是 "conda" 節點(可選),如果插件依賴 Python 環境,那麼開發者可以通過這個字段配置Python 的依賴,比如上述就表示插件依賴 Python 版 [email protected],在 Pipcook 安裝插件時就會自動進行安裝。

定義好這些基本信息後,就可以開始寫具體的插件代碼了,還記得前面在說明 Pipeline 流程時的那張圖嗎?每一種插件類型的寫法都是不一樣的,比如一個簡單的 data collect 插件如下:

const collectTextline: DataCollectType = async (args: ArgsType): Promise<void> => {
const { uri, dataDir } = args;
await fs.copy(uri, dataDir + '/my-own-dataset.csv');
return null;
};
export default collectTextline;

插件的輸入是 ArgsType,輸出是 void,那麼來看看 data process 插件:

const doubleSize: DataProcessType = async (sample: Sample, metadata: Metadata, args?: ArgsType): Promise<void> => {
// double the data
  sample.data = sample.data * 2;
};
export default doubleSize;

看,無論是輸入的參數還是函數返回值,都不一樣了。但讀者也不需要害怕,Pipcook 中的插件類型都是固定的,並且每一種插件的寫法和類型定義也都定義好了,具體可以閱讀 Pipcook 的插件規範文檔。

另外,正如在開篇所說的,Pipcook 通過 Boa 提供了無縫接入 Python 生態的能力,也正因為這種能力,才幫助 JavaScript 社區解決了機器學習生態成熟度和前沿技術使用的問題,那麼究竟如何開始使用 Boa 呢?

首先,在 package.json 中的依賴中添加 @pipcook/boa 及對應版本,另外在 "conda.dependencies" 中添加依賴的 Python 包,然後就能在插件中使用了:

const boa = require('@pipcook/boa');
const tensorflow = boa.import('tensorflow');

PipApp(實驗功能)

Pipcook 開發團隊一直在思考什麼樣的編程方式,能讓前端工程師更容易地使用機器學習,未來機器學習究竟會在前端領域是什麼樣的呢?因此我們開發了 PipApp,為開發者屏蔽掉了更多技術細節,讓開發者只需要關注機器學習的“業務邏輯”。

下面我們來看看一個 PipApp 長什麼樣:

import { createLearnable, nlp } from '@pipcook/app';
const isCooking = createLearnable(async function(sentence: string) {
return (await nlp.classify(sentence));
});
const isBooking = createLearnable(async function(sentence: string) {
return (await nlp.classify(sentence));
});

(async () => {
console.log(await isCooking('test'));
console.log(await isBooking('booking test'));
})();

上面的例子,首先通過 createLearnable 創建了一個機器學習上下文,你可以把它理解成一種特殊的 async function,只有在 Learnable 函數塊中才能使用 PipApp 提供的機器學習 API。上面的例子,分別創建了兩個機器學習流程,在其中都使用了 nlp.classify 來完成一個文本分類的任務。

與運行 Pipeline 不同,PipApp 需要創建一個完整的項目目錄,因此在開始之前,我們需要從初始化一個 Node.js 項目開始。

$ npm init
$ npm install @pipcook/app --save

創建好項目以及完成代碼之後,就可以開始編譯項目了,它的主要目的是分析項目代碼並生成對應的 Pipeline 和項目文件。

$ pipcook app compile /path/to/your/project/script.ts
generated 2 pipelines, please click the following links to config them:
(nlp.classify) > http://localhost:6927/index.html#/pipeline/info?pipelineId=1a287920-b10e-11ea-a743-792a596edff1
(nlp.classify) > http://localhost:6927/index.html#/pipeline/info?pipelineId=1a287921-b10e-11ea-a743-792a596edff1

執行完命令後,會提示配置 Pipeline,通過鏈接點擊進去去配置即可,開發者需要根據不同的調用接口來配置不同的數據,比如第一個分類是為了對產品進行分類,那麼我們配置 Pipeline 的時候,就要準備跟產品分類相關的數據集。

當配置完成後,保存 Pipeline,就可以開始訓練了:

$ pipcook app train /path/to/your/project/script.ts

當所有模型訓練完成後,就可以開始構建最終的應用包了,構建完成後,會在目錄下生成 {filename}.ml.js 文件,使用 Node.js 運行即可:

$ pipcook app build /path/to/your/project/script.ts
$ node /path/to/your/project/script.ml.js

簡單地說,當用戶希望將多個模型放在一起使用時,PipApp 能更加方便地將這些模型的使用邏輯與調用關係結合在一起,就好像現在在 Node.js 中調用 API 一樣,唯一的不同在於寫好的代碼仍然不能立即執行,需要將所有生成的模型訓練完成後才可以運行。

ROADMAP

如果說 Pipcook 1.0 是開發團隊對於前端智能化的一次社區輸出,那麼接下來,就是 Pipcook 會積極採納社區的輸入,一起將 Pipcook 變得更易於使用,易於分享和易於理解,圍繞著這些“易於”,開發團隊將會在下面幾個方面努力:

  1. 讓插件安裝變得更穩定、快速
  2. 讓插件開發變得更方便
  3. 讓插件分享變得更容易
  4. 讓 Pipeline 的執行更快,資源佔用更少
  5. 讓 Pipboard 變得更有用、好用

在接下來的3個月內,我們也會和阿里菜鳥的同學一起合作,將強化學習的能力拓展到 Pipcook 工具集中,相信有了強化學習的加持,無論是 PipApp 還是 Pipeline,都能完成更加自然和完整的機器學習工程,為前端智能化帶來不一樣的感受。

最後,Pipcook 前端智能化的目標與阿里雲負責機器學習前端的小夥伴一拍即合,因此我們也會與阿里雲合作,推出針對前端工程師的機器學習解決方案,並且努力為機器學習新手們爭取到儘量免費的訓練資源,節省入門的算力成本。

在接下來的文章中,我們會以實例,為大家依次介紹:

  • 使用 Pipcook 分類圖片中的前端組件
  • 使用 Pipcook 識別圖片中的前端組件
  • 如何將圖片中蘋果換成橘子
  • 如何使用 Pipcook 創作詩歌
  • 使用 Pipcook 為你的文章自動分類

同時,也歡迎大家加入 Pipcook Community 參與到後續的版本演進中來:
image.png


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

Leave a Reply

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