天天看點

AI (愛) JavaScript , Pipcook 1.0 正式釋出

作者 | 雷姆(Yorkie)
AI (愛) JavaScript , Pipcook 1.0 正式釋出

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 開發團隊更在意使用者的使用體驗,而非使用何種語言去實作它。

AI (愛) JavaScript , Pipcook 1.0 正式釋出

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

在 Pipcook 中,通過 Boa 提供了無縫使用 Python 生态的能力,解決了機器學習與 JavaScript 的實體距離,但還剩下所謂的“理論”距離 —— 讓前端工程師進化為機器學習軟體工程師。

AI (愛) JavaScript , Pipcook 1.0 正式釋出

如果說通過 Node.js,能幫助前端工程師轉職成為服務端工程師,那麼 Pipcook 在這方面,也希望成為前端工程師們進階為機器學習軟體工程師的利器。

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

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

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

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

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

什麼是機器學習呢?

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

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

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

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

那麼對于機器學習本身來說,它也不是萬能靈藥,而在 Pipcook 中,把機器學習分為了圖檔和文本兩大類,其中每一類都包括了對應的一些任務,如下:

AI (愛) JavaScript , Pipcook 1.0 正式釋出

比如在前端智能化最常見的設計稿生成代碼的場景中,就使用了圖檔分類和目标檢測來提取設計稿的資訊,提供給代碼生成器。

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

什麼是 Pipeline

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

整個過程我們通過下圖來做一個簡單的說明:

AI (愛) JavaScript , Pipcook 1.0 正式釋出

這條 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 庫了:

AI (愛) JavaScript , Pipcook 1.0 正式釋出

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

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

除此之外,你也可以通過 Pipboard 随時下載下傳曆史的訓練結果,如下圖所示:

AI (愛) JavaScript , Pipcook 1.0 正式釋出

為了友善開發者使用,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 參與到後續的版本演進中來:

AI (愛) JavaScript , Pipcook 1.0 正式釋出
AI (愛) JavaScript , Pipcook 1.0 正式釋出

關注「Alibaba F2E」

把握阿裡巴巴前端新動向