Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 午夜免费观看体验区入口,在线观看欧美国产,欧美成人a级在线视频

          整合營(yíng)銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢熱線:

          前端智能化:實(shí)現(xiàn)自己的控件識(shí)別模型


          我們的前端智能化框架:http://github.com/alibaba/pipcook 內(nèi)置實(shí)驗(yàn),可以方便的進(jìn)行手寫(xiě)數(shù)字識(shí)別和圖像分類任務(wù),這里按照環(huán)境準(zhǔn)備、快速實(shí)驗(yàn)、實(shí)戰(zhàn)方法、原理解析的順序,分四個(gè)部分進(jìn)行介紹。完成本教程,你可以開(kāi)始進(jìn)行自己的前端智能化項(xiàng)目,用機(jī)器學(xué)習(xí)解決編程過(guò)程中遇到的問(wèn)題。


          環(huán)境準(zhǔn)備


          開(kāi)始之前


          臺(tái)式機(jī)和筆記本


          首先,初學(xué)者我更推薦筆記本,因?yàn)槠浔銛y性和初期實(shí)驗(yàn)的運(yùn)算量并不是很大,可以保證在咖啡館或戶外立即開(kāi)始學(xué)習(xí)和實(shí)踐。其次,現(xiàn)在的輕薄筆記本如小米的 Pro 款配備了 Max 150 滿血版,基本可以滿足常用的機(jī)器學(xué)習(xí)實(shí)驗(yàn)。Mac Book Pro 的用戶可以考慮帶 AMD 顯卡的筆記本,因?yàn)樵?PlaidML(intel提供的機(jī)器學(xué)習(xí)后端)支持下,Keras 的大部分 OP 都是具備 GPU 硬件加速的。需要注意,PlaidML 對(duì)很多神經(jīng)網(wǎng)絡(luò)支持不太好,比如對(duì) RNN 的支持就不好,具體可以看 Issue。在我的16寸 Mac Book Pro上,PlaidML 對(duì) RNN 無(wú)硬件加速效果,GPU 監(jiān)視器未有負(fù)載且模型編譯過(guò)程冗長(zhǎng)。


          最后,對(duì)于有條件的朋友建議準(zhǔn)備臺(tái)式機(jī),因?yàn)樵趯W(xué)習(xí)實(shí)驗(yàn)中將會(huì)遇到越來(lái)越多復(fù)雜模型,這些模型一般都需要訓(xùn)練數(shù)天,臺(tái)式機(jī)能夠提供更好的散熱性能來(lái)保證運(yùn)行的穩(wěn)定性。


          組裝臺(tái)式機(jī)的時(shí)候?qū)PU的主頻要求不用太高,一般 AMD 的中低端 CPU 即可勝任,只要核心數(shù)達(dá)到6個(gè)以上的AMD 12 線程CPU基本就夠用了。內(nèi)存方面最好是 32GB ,16GB 只能說(shuō)夠用,對(duì)海量數(shù)據(jù)尤其是圖片類型進(jìn)行加工處理的時(shí)候,最容易爆的就是內(nèi)存。


          GPU方面由于ROCM的完善,喜歡折騰的人選擇 AMD GPU 完全沒(méi)問(wèn)題,不喜歡折騰可以選擇 Nvidia GPU,需要指出的是顯存容量和顯存帶寬在預(yù)算允許的范圍內(nèi)越大越好,尤其是顯存容量,海量參數(shù)的大模型沒(méi)有大顯存根本無(wú)法訓(xùn)練。


          硬盤(pán)方面選擇高速 SSD 作為系統(tǒng)盤(pán) 512GB 起步,掛載一個(gè)混合硬盤(pán)作為數(shù)據(jù)存儲(chǔ)和模型參數(shù)存儲(chǔ)即可。電源盡量選擇大一點(diǎn)兒,除了考慮峰值功耗之外,未來(lái)可能要考慮多 GPU 來(lái)加速訓(xùn)練過(guò)程、應(yīng)對(duì)海量參數(shù)。機(jī)箱作為硬件的家,電磁屏蔽性能好、板材厚重、空間大便于散熱即可,用水冷打造性能小鋼炮的除外。


          選擇的依據(jù)很簡(jiǎn)單:喜歡折騰的按上述內(nèi)容 DIY ,喜歡簡(jiǎn)單的按上述內(nèi)容買(mǎi)帶售后的品牌機(jī)。兩者的區(qū)別就是花時(shí)間省點(diǎn)兒錢(qián)?還是花錢(qián)省點(diǎn)兒時(shí)間?


          操作系統(tǒng)


          對(duì)于筆記本自帶 Windows 操作系統(tǒng)的,直接使用 Windows 并沒(méi)有問(wèn)題,Anaconda 基本可以搞定和研發(fā)環(huán)境的所有問(wèn)題,而且其自帶的 NPM 管理工具很方便。有條件愛(ài)折騰的上一個(gè) Ubuntu Linux 系統(tǒng)最好,因?yàn)樵?Linux 下能夠更加原生支持機(jī)器學(xué)習(xí)相關(guān)技術(shù)生態(tài),幾乎不會(huì)遇到兼容性問(wèn)題。


          對(duì)于臺(tái)式機(jī)建議安裝 Ubuntu Linux 系統(tǒng),否則,這么好的顯卡很容易裝個(gè) Windows 玩游戲去了……Ubuntu 的安裝盤(pán)制作很簡(jiǎn)單,一個(gè)U盤(pán)搞定,一路回車(chē)安裝即可。裝好系統(tǒng)后在自己的“~”根目錄下建一個(gè)“Workspace”存放代碼文件,制作一個(gè)軟鏈接把混合硬盤(pán)作為數(shù)據(jù)盤(pán)引入即可,未來(lái)還可以把 Keras、NLTK 等框架的數(shù)據(jù)集文件夾也以軟鏈接的方式保存在數(shù)據(jù)盤(pán)里。


          Ubuntu 會(huì)自動(dòng)進(jìn)行更新,這個(gè)很重要,很多框架和庫(kù)的 Bug 在這個(gè)過(guò)程中被修復(fù),需要注意的是在這個(gè)過(guò)程中出現(xiàn)長(zhǎng)時(shí)間無(wú)響應(yīng)或網(wǎng)絡(luò)問(wèn)題的情況,可以考慮用阿里云的源來(lái)進(jìn)行加速,然后在命令行手動(dòng)執(zhí)行更新。


          Python環(huán)境


          教程


          Python教程:https://docs.python.org/zh-cn/3.8/tutorial/index.html


          安裝包:


          MacOS:https://www.python.org/ftp/python/3.7.7/python-3.7.7-macosx10.9.pkg


          Windows:https://www.python.org/ftp/python/3.7.7/python-3.7.7-embed-amd64.zip


          安裝模塊:


          https://docs.python.org/zh-cn/3.8/installing/index.html


          Node環(huán)境


          教程


          Node教程:https://nodejs.org/zh-cn/


          安裝包:


          MacOS:https://nodejs.org/dist/v12.16.2/node-v12.16.2.pkg


          Windows:


          https://nodejs.org/dist/v12.16.2/node-v12.16.2-x64.msi


          https://nodejs.org/dist/v12.16.2/node-v12.16.2-x86.msi


          Linux:https://nodejs.org/dist/v12.16.2/node-v12.16.2-linux-x64.tar.xz


          下載頁(yè)面:https://nodejs.org/zh-cn/download/


          安裝模塊:


          模塊網(wǎng)站:https://www.npmjs.com/


          安裝方法:


          $ npm install -g @pipcook/pipcook-cli


          確保你的 Python 版本為 > 3.6 ,你的 Node.js 版本為 > 12.x 的最新穩(wěn)定版本,執(zhí)行上面的安裝命令,就可以在電腦里擁有 Pipcook 的完整開(kāi)發(fā)環(huán)境了。


          快速實(shí)驗(yàn)

          啟動(dòng)可視化實(shí)驗(yàn)環(huán)境:Pipboard


          啟動(dòng)


          命令行:


          $ mkdir pipcook-example && cd pipcook-example
          $ pipcook init
          $ pipcook board


          輸出:


          > @pipcook/pipcook-board-server@1.0.0 dev /Users/zhenyankun.zyk/work/node/pipcook/example/.server
          > egg-bin dev
          
          [egg-ts-helper] create typings/app/controller/index.d.ts (2ms)
          [egg-ts-helper] create typings/config/index.d.ts (9ms)
          [egg-ts-helper] create typings/config/plugin.d.ts (2ms)
          [egg-ts-helper] create typings/app/service/index.d.ts (1ms)
          [egg-ts-helper] create typings/app/index.d.ts (1ms)
          2020-04-16 11:52:22,053 INFO 26016 [master] node version v12.16.2
          2020-04-16 11:52:22,054 INFO 26016 [master] egg version 2.26.0
          2020-04-16 11:52:22,839 INFO 26016 [master] agent_worker#1:26018 started (782ms)
          2020-04-16 11:52:24,262 INFO 26016 [master] egg started on http://127.0.0.1:7001 (2208ms)


          在瀏覽器內(nèi)選擇實(shí)驗(yàn):


          想進(jìn)行手寫(xiě)數(shù)字識(shí)別實(shí)驗(yàn),選擇 MNIST Handwritten Digit Recognition (手寫(xiě)數(shù)字識(shí)別)點(diǎn)擊 Try Here 按鈕。想進(jìn)行圖像分類實(shí)驗(yàn),選擇 Image Classifiaction for Front-end Assets。



          體驗(yàn)機(jī)器學(xué)習(xí)的魅力:手寫(xiě)數(shù)字識(shí)別


          從瀏覽器內(nèi)進(jìn)入手寫(xiě)數(shù)字識(shí)別的實(shí)驗(yàn):

          按照:

          1、鼠繪;

          2、點(diǎn)擊預(yù)測(cè)按鈕“Predict”;

          3、查看預(yù)測(cè)結(jié)果“7” 的順序進(jìn)行實(shí)驗(yàn),就能看到模型預(yù)測(cè)出手寫(xiě)的圖像是數(shù)字 “7” 。


          體驗(yàn)機(jī)器學(xué)習(xí)的魅力:圖像分類


          從瀏覽器進(jìn)入圖像分類的實(shí)驗(yàn):


          選擇一張圖片后可以看到:



          提示正在進(jìn)行預(yù)測(cè),這個(gè)過(guò)程會(huì)加載模型并進(jìn)行圖像分類的預(yù)測(cè),當(dāng)選擇 “依更美” 的商標(biāo)圖片并等待一小會(huì)兒后,在 Result 區(qū)域可以看到 Json 結(jié)構(gòu)的預(yù)測(cè)結(jié)果:



          模型可以識(shí)別出這個(gè)圖像是 “brandLogo” (品牌logo)。


          實(shí)踐方法


          偷天換日:改造現(xiàn)有的工程。就像學(xué)畫(huà)畫(huà)、學(xué)書(shū)法……,從臨摹開(kāi)始可以極大平滑學(xué)習(xí)曲線。因此,先從改造一個(gè)現(xiàn)有的 Pipcook mnist pipline 開(kāi)始,借助這個(gè)過(guò)程來(lái)實(shí)現(xiàn)一個(gè)自己的控件識(shí)別模型。完成后續(xù)的教程后,你就擁有了一個(gè)可以從圖片中識(shí)別出 “button” 的模型。


          問(wèn)題定義


          如果你之前看過(guò)我的一些文章,基本可以了解 imgcook.com 的原理:通過(guò)機(jī)器視覺(jué)對(duì)設(shè)計(jì)稿進(jìn)行前端代碼重構(gòu)。這里定義的問(wèn)題就是:用機(jī)器視覺(jué)對(duì)設(shè)計(jì)稿進(jìn)行代碼重構(gòu)。但是這個(gè)問(wèn)題太大,作為實(shí)戰(zhàn)入門(mén)可以簡(jiǎn)化一下:用機(jī)器視覺(jué)對(duì)控件進(jìn)行識(shí)別。


          為了讓模型可以進(jìn)行控件識(shí)別,首先要定義什么是控件:在計(jì)算機(jī)編程當(dāng)中,控件(或部件,widget或control)是一種圖形用戶界面元素,其顯示的信息排列可由用戶改變,例如視窗或文本框。控件定義的特點(diǎn)是為給定數(shù)據(jù)的直接操作(direct manipulation)提供單獨(dú)的互動(dòng)點(diǎn)。控件是一種基本的可視構(gòu)件塊,包含在應(yīng)用程序中,控制著該程序處理的所有數(shù)據(jù)以及關(guān)于這些數(shù)據(jù)的交互操作。(引用自維基百科)


          問(wèn)題分析


          根據(jù)問(wèn)題定義,控件屬于:圖形用戶界面,層級(jí):元素,邊界:提供單獨(dú)的互動(dòng)點(diǎn)。因此,在圖形界面中找到的,提供單獨(dú)的互動(dòng)點(diǎn)的元素,就是控件。對(duì)于機(jī)器視覺(jué)的模型來(lái)說(shuō),“在圖形界面中找到元素”類似于“在圖像中找到元素”的任務(wù),“在圖像中找到元素”的任務(wù)可以用:目標(biāo)檢測(cè)模型來(lái)完成。

          “Segmenting Nuclei in Microscopy Images”


          這里推薦使用 MaskRCNN 地址在:https://github.com/matterport/Mask_RCNN ,可以看到細(xì)胞的語(yǔ)義化分割再對(duì)分割后的圖像進(jìn)行分類,就完成了目標(biāo)檢測(cè)任務(wù)。總結(jié)一下 Mask RCNN 的目標(biāo)檢測(cè)過(guò)程是:使用PRN網(wǎng)絡(luò)產(chǎn)生候選區(qū)(語(yǔ)義化分割),再對(duì)候選區(qū)進(jìn)行圖像分類(掩碼預(yù)測(cè)多任務(wù)損失)。所謂的語(yǔ)義化,其實(shí)就是以語(yǔ)義為基礎(chǔ)來(lái)確定數(shù)據(jù)之間的關(guān)系。比如用機(jī)器學(xué)習(xí)摳圖,不能把人的胳膊腿、頭發(fā)絲兒扣掉了,這里就應(yīng)用到語(yǔ)義化來(lái)確定人像的組成部分。


          做個(gè)語(yǔ)義分割的機(jī)器視覺(jué)任務(wù)可能有點(diǎn)兒復(fù)雜,手寫(xiě)數(shù)字識(shí)別這種圖像分類相對(duì)簡(jiǎn)單。Mask RCNN 只是用 Bounding Box 把圖像切成一塊兒、一塊兒的,然后對(duì)每一塊兒圖像進(jìn)行分類,如果把圖像分類做好了就等于做好了一半兒,讓我們開(kāi)始吧。


          數(shù)據(jù)組織


          數(shù)據(jù)組織就是根據(jù)問(wèn)題定義和訓(xùn)練任務(wù)給模型準(zhǔn)備“標(biāo)注樣本”。之前在《前端智能化:思維轉(zhuǎn)變之路》里介紹過(guò),智能化開(kāi)發(fā)的方法就是告訴機(jī)器正確答案(正樣本)、錯(cuò)誤答案(負(fù)樣本)這種標(biāo)注數(shù)據(jù),機(jī)器通過(guò)對(duì)數(shù)據(jù)的分析理解,學(xué)習(xí)到形成答案的解題思路。因此,數(shù)據(jù)組織非常關(guān)鍵,高質(zhì)量的數(shù)據(jù)才能讓機(jī)器學(xué)到正確的解題思路。


          通過(guò)分析 mnist 數(shù)據(jù)集的數(shù)據(jù)組織方式,可以快速?gòu)?fù)用 mnist 的例子:



          可以看到,Mnist 手寫(xiě)數(shù)字識(shí)別的訓(xùn)練樣本,其實(shí)就真的是手寫(xiě)了一些數(shù)字,給他們打上對(duì)應(yīng)的標(biāo)簽(label),寫(xiě)了“0”就標(biāo)注“0”、寫(xiě)了“1”就標(biāo)注“1”……這樣,模型訓(xùn)練之后就能夠知道標(biāo)簽“0”對(duì)應(yīng)的圖像長(zhǎng)什么樣?


          其次,要探求一下 Pipcook 在訓(xùn)練模型的時(shí)候,對(duì)數(shù)據(jù)組織的要求是怎樣的?可以在:https://github.com/alibaba/pipcook/blob/master/example/pipelines/mnist-image-classification.json 里看到


          {
            "plugins": {
              "dataCollect": {
                "package": "@pipcook/plugins-mnist-data-collect",
                "params": {
                  "trainCount": 8000,
                  "testCount": 2000
                }
              },


          根據(jù)線索:@pipcook/plugins-mnist-data-collect 找到:https://github.com/alibaba/pipcook/blob/master/packages/plugins/data-collect/mnist-data-collect/src/index.ts 里:


          const mnist = require('mnist');


          于是,在:https://github.com/alibaba/pipcook/blob/master/packages/plugins/data-collect/mnist-data-collect/package.json 里找到了:


          "dependencies": {
              "@pipcook/pipcook-core": "^0.5.9",
              "@tensorflow/tfjs-node-gpu": "1.7.0",
              "@types/cli-progress": "^3.4.2",
              "cli-progress": "^3.6.0",
              "jimp": "^0.10.0",
              "mnist": "^1.1.0"
            },


          在:https://www.npmjs.com/package/mnist 里看到了相關(guān)的信息。


          從npm包的信息來(lái)到:https://github.com/cazala/mnist 源碼站點(diǎn),在README里找到:


          The goal of this library is to provide an easy-to-use way for training and testing MNIST digits for neural networks (either in the browser or node.js). It includes 10000 different samples of mnist digits. I built this in order to work out of the box with Synaptic.

          You are free to create any number (from 1 to 60 000) of different examples c via MNIST Digits data loader


          這里提到:想要?jiǎng)?chuàng)建不同的樣本可以使用 MNIST Digits datta loader,點(diǎn)進(jìn)去一探究竟:https://github.com/ApelSYN/mnist_dl 這里有詳細(xì)的步驟:


          Installation

          for node.js: npm install mnist_dl

          Download from LeCun’s website and unpack two files:

          train-images-idx3-ubyte.gz:  training set images (9912422 bytes) 
          train-labels-idx1-ubyte.gz:  training set labels (28881 bytes)

          You need to place these files in the "./data" directory.


          先去Clone項(xiàng)目:


          git clone https://github.com/ApelSYN/mnist_dl.git
          正克隆到 'mnist_dl'...
          remote: Enumerating objects: 36, done.
          remote: Total 36 (delta 0), reused 0 (delta 0), pack-reused 36
          展開(kāi)對(duì)象中: 100% (36/36), 完成.


          對(duì)項(xiàng)目做一下:npm install,然后創(chuàng)建數(shù)據(jù)源和數(shù)據(jù)集目標(biāo)目錄:


          # 數(shù)據(jù)源目錄,用來(lái)下載 LeCun 大神的數(shù)據(jù)
          $ mkdir data
          # 數(shù)據(jù)集目錄,用來(lái)存放 mnist_dl 處理后的 Json 數(shù)據(jù)
          $ mkdir digits


          然后在機(jī)器學(xué)習(xí)大牛 LeCun 的網(wǎng)站上下載數(shù)據(jù),保存到"./data"目錄下:


          http://yann.lecun.com/exdb/mnist/


          Mnist的訓(xùn)練樣本圖片數(shù)據(jù):train-images-idx3-ubyte.gz


          Mnist的訓(xùn)練樣本標(biāo)簽數(shù)據(jù):train-labels-idx1-ubyte.gz


          然后用 mnist_dl 進(jìn)行測(cè)試:


          node mnist_dl.js --count 10000
          DB digits Version: 2051
          Total digits: 60000
          x x y: 28 x 28
          60000
          47040000
          Pass 0 items...
          Pass 1000 items...
          Pass 2000 items...
          Pass 3000 items...
          Pass 4000 items...
          Pass 5000 items...
          Pass 6000 items...
          Pass 7000 items...
          Pass 8000 items...
          Pass 9000 items...
          Finish processing 10000 items...
          Start make "0.json with 1001 images"
          Start make "1.json with 1127 images"
          Start make "2.json with 991 images"
          Start make "3.json with 1032 images"
          Start make "4.json with 980 images"
          Start make "5.json with 863 images"
          Start make "6.json with 1014 images"
          Start make "7.json with 1070 images"
          Start make "8.json with 944 images"
          Start make "9.json with 978 images"


          接著 Clone mnist項(xiàng)目進(jìn)行數(shù)據(jù)集替換測(cè)試:


          $ git clone https://github.com/cazala/mnist.git
          正克隆到 'mnist'...
          remote: Enumerating objects: 143, done.
          remote: Total 143 (delta 0), reused 0 (delta 0), pack-reused 143
          接收對(duì)象中: 100% (143/143), 18.71 MiB | 902.00 KiB/s, 完成.
          處理 delta 中: 100% (73/73), 完成.
          
          $ npm install
          $ cd src
          $ cd digits
          $ ls
          0.json 1.json 2.json 3.json 4.json 5.json 6.json 7.json 8.json 9.json


          下面先試試原始數(shù)據(jù)集,使用:mnist/visualizer.html 文件在瀏覽器中打開(kāi)可以看到:



          下面,把數(shù)據(jù)文件替換成剛才處理的文件:


          # 進(jìn)入工作目錄
          $ cd src
          # 先備份一下
          $ mv digits digits-bk
          # 再拷貝之前處理的json數(shù)據(jù)
          $ cp -R ../mnist_dl/digits ./
          $ ls
          digits    digits-bk mnist.js


          強(qiáng)制刷新一下瀏覽器里的:mnist/visualizer.html 文件,可以看到生成的文件完全可用,因此,一個(gè)解決方案漸漸浮現(xiàn):替換原始Mnist文件里的內(nèi)容和Mnist標(biāo)簽的內(nèi)容來(lái)實(shí)現(xiàn)自己的圖片分類檢測(cè)模型。


          為了能夠替換文件:


          Mnist的訓(xùn)練樣本圖片數(shù)據(jù):train-images-idx3-ubyte.gz


          Mnist的訓(xùn)練樣本標(biāo)簽數(shù)據(jù):train-labels-idx1-ubyte.gz


          成為我們自定義的數(shù)據(jù)集,首先需要了解這兩個(gè)文件的格式。通過(guò)文件名里 xx-xx-idx3-ubyte 可以看出,文件是按照 idx-ubyte 的方式組織的:



          在train-images.idx3-ubyte文件中,偏移量0位置32位的整數(shù)是魔數(shù)(magic number),偏移量位置4為圖片總數(shù)(圖片樣本數(shù)量),偏移量位置8、12為圖片尺寸(存放圖片像素信息的高、寬),偏移量位置16之后的都是像素信息(存放圖片像素值,值域?yàn)?~255)。經(jīng)過(guò)分析后,只需要依次獲取魔數(shù)和圖片的個(gè)數(shù),然后獲取圖片的高和寬,最后逐個(gè)像素讀取就可以了。因此,在 MNIST_DL 項(xiàng)目的 lib 文件夾中的 digitsLoader.js 內(nèi)容:


          stream.on('readable', function () {
                  let buf = stream.read();
                  if (buf) {
                      if (ver != 2051) {
                          ver = buf.readInt32BE(0);
                          console.log(`DB digits Version: ${ver}`);
                          digitCount = buf.readInt32BE(4);
                          console.log(`Total digits: ${digitCount}`);
                          x = buf.readInt32BE(8);
                          y = buf.readInt32BE(12);
                          console.log(`x x y: ${x} x ${y}`);
                          start = 16;
                      }
                      for (let i = start; i< buf.length; i++) {
                          digits.push(buf.readUInt8(i));
                      }
                      start = 0;
                  }
              });


          就非常容易理解了,需要做的就是把圖片按照這個(gè)過(guò)程進(jìn)行 “逆運(yùn)算” ,反向把準(zhǔn)備好的圖片樣本組織成這個(gè)格式即可。知道如何組織數(shù)據(jù),那么如何生產(chǎn)樣本呢?


          樣本制造


          在問(wèn)題分析里,我們了解到 “圖像分類” 是做好控件識(shí)別的基礎(chǔ),就像手寫(xiě)的數(shù)字 “0” 的圖像被標(biāo)記上數(shù)字 “0” 一樣,我們也要對(duì)控件進(jìn)行樣本標(biāo)注。因?yàn)闃颖緲?biāo)注是一個(gè)繁瑣冗長(zhǎng)的工作,所以機(jī)器學(xué)習(xí)的興起催生了一個(gè)全新的職業(yè):樣本標(biāo)注工程師。樣本標(biāo)注工程師人工對(duì)圖片打標(biāo)簽:



          標(biāo)注之后的樣本就可以組織成數(shù)據(jù)集(Dataset)給模型進(jìn)行訓(xùn)練,因此,良好的標(biāo)注質(zhì)量(準(zhǔn)確傳遞信息給模型)和豐富(從不同視角和不同條件下描述信息)的數(shù)據(jù)集是優(yōu)質(zhì)模型的基礎(chǔ)。后續(xù)會(huì)介紹 pipcook 里的樣本制造機(jī),我們會(huì)很快開(kāi)源這部分內(nèi)容,現(xiàn)在,先把樣本制造過(guò)程分享一下。


          Web 控件以 HTML 標(biāo)簽的形式書(shū)寫(xiě),然后 HTML 頁(yè)面被瀏覽器渲染成圖像,可以利用這個(gè)過(guò)程和前端流行的 Puppeteer 工具,完成樣本的自動(dòng)化生成。為了方便,這里用 bootstrap 寫(xiě)一個(gè)簡(jiǎn)單的Demo:


          <link rel="stylesheet" href="t1.min.css">
          <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
          <div align="middle">
          <p>
              <button class="btn btn-primary">Primary</button>
          </p>
          <p>
              <button class="btn btn-info">Info</button>
          </p>
          <p>
              <button class="btn btn-success">Success</button>
          </p>
          <p>
              <button class="btn btn-warning">Warning</button>
          </p>
          <p>
              <button class="btn btn-danger">Danger</button>
          </p>
          <p>
              <button class="btn btn-lg btn-primary" type="button">Large button</button>
          </p>
          <p>
              <button class="btn btn-primary" type="button">Default button</button>
          </p>
          <p>
              <button class="btn btn-sm btn-primary" type="button">Mini button</button>
          </p>
          <p>
              <a href="#" class="btn btn-xs btn-primary disabled">Primary link disabled state</a>
          </p>
          <p>
              <button class="btn btn-lg btn-block btn-primary" type="button">Block level button</button>
          </p>
          <p>
              <button type="button" class="btn btn-primary">Primary</button>
          </p>
          <p>
              <button type="button" class="btn btn-secondary">Secondary</button>
          </p>
          <p>
              <button type="button" class="btn btn-success">Success</button>
          </p>
          <p>
              <button type="button" class="btn btn-danger">Danger</button>
          </p>
          <p>
              <button type="button" class="btn btn-warning">Warning</button>
          </p>
          <p>
              <button type="button" class="btn btn-info">Info</button>
          </p>
          <p>
              <button type="button" class="btn btn-light">Light</button>
          </p>
          <p>
              <button type="button" class="btn btn-dark">Dark</button>
          </p>
          </div>


          在瀏覽器打開(kāi) HTML 用調(diào)試工具模擬Mobile iPhoneX顯示:



          可以從:https://startbootstrap.com/themes/ 里找到很多 Themes,用這些不同的主題來(lái)使我們的樣本具備 “多樣性”,讓模型更加容易從圖像中找到 “Button” 的特征。


          這樣手工截圖效率太差還不精準(zhǔn),下面就輪到 Puppeteer 工具出場(chǎng)了。首先是初始化一個(gè) node.js 項(xiàng)目并安裝:


          $ mkdir pupp && cd pupp
          $ npm init --yes
          $ npm i puppeteer --save
          # or "yarn add puppeteer"


          為了能夠處理圖像,需要安裝 https://www.npmjs.com/package/gm 在 http://www.graphicsmagick.org/ 有GM的安裝方法。


          $ brew install graphicsmagick
          $ npm i gm --save


          安裝完成后打開(kāi) IDE 添加一個(gè) shortcut.js 文件(依舊會(huì)在文末附上全部源碼):


          const puppeteer = require("puppeteer");
          const fs = require("fs");
          const Q = require("Q");
          
          function delay(ms) {
            var deferred = Q.defer();
            setTimeout(deferred.resolve, ms);
          
            return deferred.promise;
          }
          
          const urls = [
            "file:///Users/zhenyankun.zyk/work/node/pipcook/pupp/htmlData/page1.html",
            "file:///Users/zhenyankun.zyk/work/node/pipcook/pupp/htmlData/page2.html",
            "file:///Users/zhenyankun.zyk/work/node/pipcook/pupp/htmlData/page3.html",
            "file:///Users/zhenyankun.zyk/work/node/pipcook/pupp/htmlData/page4.html",
            "file:///Users/zhenyankun.zyk/work/node/pipcook/pupp/htmlData/page5.html",
          ];
          
          (async () => {
            // Launch a headful browser so that we can see the page navigating.
            const browser = await puppeteer.launch({
              headless: true,
              args: ["--no-sandbox", "--disable-gpu"],
            });
            const page = await browser.newPage();
            await page.setViewport({
              width: 375,
              height: 812,
              isMobile: true,
            }); //Custom Width
          
            //start shortcut every page
            let counter = 0;
            for (url of urls) {
              await page.goto(url, {
                timeout: 0,
                waitUntil: "networkidle0",
              });
              await delay(100);
              let btnElements = await page.$$("button");
          
              for (btn of btnElements) {
                const btnData = await btn.screenshot({
                  encoding: "binary",
                  type: "jpeg",
                  quality: 90,
                });
                let fn = "data/btn" + counter + ".jpg";
                Q.nfcall(fs.writeFileSync, fn, btnData);
                counter++;
              }
            }
          
            await page.close();
            await browser.close();
          })();


          通過(guò)上述腳本,可以循環(huán)把五種Themes的Button都渲染出來(lái),并利用Puppeteer截圖每個(gè)Button:


          生成的圖片很少,只有80多張,這里就輪到之前安裝的GM: https://www.npmjs.com/package/gm 出場(chǎng)了:


          用GM庫(kù)把圖片進(jìn)行處理,讓它和Mnist的手寫(xiě)數(shù)字圖片一致,然后,通過(guò)對(duì)圖片上添加一些隨機(jī)文字,讓模型忽略這些文字的特征。這里的原理就是“打破規(guī)律”,模型記住Button特征的方式和人識(shí)別事物的方式非常相似。人在識(shí)別事物的時(shí)候,會(huì)記住那些重復(fù)的部分用于分辨。比如我想記住一個(gè)人,需要記住這個(gè)人不變的特征,例如:眼睛大小、瞳孔顏色、眉距、臉寬、顴骨……,而不會(huì)去記住他穿什么衣服、什么鞋子,因?yàn)椋绻直嬉粋€(gè)人是依靠衣服鞋子,換個(gè)衣服鞋子就認(rèn)不出來(lái)了,無(wú)異于:刻舟求劍。


          下面,看一下具體處理圖片的代碼,請(qǐng)注意,這里并沒(méi)有增強(qiáng),真正使用的時(shí)候需要“舉一反三”,用一張圖片生成更多圖片,這就是“數(shù)據(jù)增強(qiáng)”的方法:


          const gm = require("gm");
          const fs = require("fs");
          const path = require("path");
          
          const basePath = "./data/";
          const chars = [
            "0",
            "1",
            "2",
            "3",
            "4",
            "5",
            "6",
            "7",
            "8",
            "9",
            "A",
            "B",
            "C",
            "D",
            "E",
            "F",
            "G",
            "H",
            "I",
            "J",
            "K",
            "L",
            "M",
            "N",
            "O",
            "P",
            "Q",
            "R",
            "S",
            "T",
            "U",
            "V",
            "W",
            "X",
            "Y",
            "Z",
          ];
          
          let randomRange = (min, max) => {
            return Math.random() * (max - min) + min;
          };
          let randomChars = (rangeNum) => {
            let tmpChars = "";
            for (let i = 0; i < rangeNum; i++) {
              tmpChars += chars[Math.ceil(Math.random() * 35)];
            }
            return tmpChars;
          };
          //獲取此文件夾下所有的文件(數(shù)組)
          const files = fs.readdirSync(basePath);
          
          for (let file of files) {
            let filePath = path.join(basePath, file);
            gm(filePath)
              .quality(100)
              .gravity("Center")
              .drawText(randomRange(-5, 5), 0, randomChars(5))
              .channel("Gray")
              // .monochrome()
              .resize(28)
              .extent(28, 28)
              .write(filePath, function (err) {
                if (!err) console.log("At " + filePath + " done! ");
                else console.log(err);
              });
          }


          我們對(duì)以下代碼稍加修改就可以達(dá)到增強(qiáng)的效果:


          for (let file of files) {
            for (let i = 0; i < 3; i++) {
              let rawfilePath = path.join(basePath, file);
              let newfilePath = path.join(basePath, i + file);
              gm(rawfilePath)
                .quality(100)
                .gravity("Center")
                .drawText(randomRange(-5, 5), 0, randomChars(5))
                .channel("Gray")
                // .monochrome()
                .resize(28)
                .extent(28, 28)
                .write(newfilePath, function (err) {
                  if (!err) console.log("At " + newfilePath + " done! ");
                  else console.log(err);
                });
            }
          }


          這樣就把圖片數(shù)量增強(qiáng)擴(kuò)展到三倍了。


          完成了數(shù)據(jù)增強(qiáng),下一步將圖片組織乘 idx-ubyte 文件,保證 mnist-ld 能夠正常處理。為了組織 idx-ubyte 文件,需要對(duì)圖片進(jìn)行一些特殊處理:提取像素信息、加工成類似 Mnist 數(shù)據(jù)集一樣的數(shù)據(jù)向量等工作。在 JavaScript 里處理會(huì)比較痛苦,Python 卻很擅長(zhǎng)處理這類問(wèn)題,那么,用 Python 的技術(shù)生態(tài)來(lái)解決問(wèn)題就需要請(qǐng) Boa 出場(chǎng)了:https://zhuanlan.zhihu.com/p/128993125 (具體可以看這里的介紹)。


          Boa 是我們?yōu)?Pipcook 開(kāi)發(fā)的底層核心功能,負(fù)責(zé)在 JavaScript 里 Bridge Python 技術(shù)生態(tài),整個(gè)過(guò)程幾乎是性能無(wú)損耗的:



          首先是安裝:


          $ npm install @pipcook/boa --save


          其次是安裝 opencv-python :


           $ ./node_modules/@pipcook/boa/.miniconda/bin/pip install opencv-python


          最后,分享一下如何在 JavaScript 里使用 Boa bridge Python 的能力:


          const boa = require("@pipcook/boa");
          // 引入一些 python 語(yǔ)言內(nèi)置的數(shù)據(jù)結(jié)構(gòu)
          const { int, tuple, list } = boa.builtins();
          // 引入 OpenCV
          const cv2 = boa.import("cv2");
          const np = boa.import("numpy");
          const Image = boa.import("PIL.Image");
          const ImageFont = boa.import("PIL.ImageFont");
          const ImageDraw = boa.import("PIL.ImageDraw");
          
          let img = np.zeros(tuple([28, 28, 3]), np.uint8);
          img = Image.fromarray(img);
          let draw = ImageDraw.Draw(img);
          draw.text(list([0, 0]), "Shadow");
          img.save("./test.tiff");


          來(lái)對(duì)比一下 Python 的代碼:


          import numpy as np
          import cv2
          from PIL import ImageFont, ImageDraw, Image
          
          img = np.zeros((150,150,3),np.uint8)
          img = Image.fromarray(img)
          draw = ImageDraw.Draw(img)
          draw.text((0,0),"Shadow")
          img.save()


          可以看到 Python 的代碼和 JavaScript 代碼的差異點(diǎn)主要是:


          1、引入包的方式:


          Python:import cv2


          JavaScript:const cv2 = boa.import("cv2");


          Python:from PIL import ImageFont, ImageDraw, Image


          JavaScript:


          const Image = boa.import("PIL.Image");
          const ImageFont = boa.import("PIL.ImageFont");
          const ImageDraw = boa.import("PIL.ImageDraw");


          2、使用 Tuple 等數(shù)據(jù)結(jié)構(gòu):


          Python:(150,150,3)


          JavaScript:tuple([28, 28, 3])


          可以看到,從 github.com 開(kāi)源機(jī)器學(xué)習(xí)項(xiàng)目,移植到 Pipcook 和 Boa 是一件非常簡(jiǎn)單的事兒,只要掌握上述兩個(gè)方法即可。


          課后習(xí)題:


          #/usr/bin/env python2.7
          #coding:utf-8
          import os
          import cv2
          import numpy
          import sys
          import struct
          
          DEFAULT_WIDTH = 28
          DEFAULT_HEIGHT = 28
          DEFAULT_IMAGE_MAGIC = 2051
          DEFAULT_LBAEL_MAGIC = 2049
          IMAGE_BASE_OFFSET = 16
          LABEL_BASE_OFFSET = 8
          
          def usage_generate():
              print "python mnist_helper generate path_to_image_dir"
              print "\t path_to_image_dir/subdir, subdir is the label"
              print ""
              pass
          
          def create_image_file(image_file):
              fd = open(image_file, 'w+b')
              buf = struct.pack(">IIII", DEFAULT_IMAGE_MAGIC, 0, DEFAULT_WIDTH, DEFAULT_HEIGHT)
              fd.write(buf)
              fd.close()
              pass
          
          def create_label_file(label_file):
              fd = open(label_file, 'w+b')
              buf = struct.pack(">II", DEFAULT_LBAEL_MAGIC, 0)
              fd.write(buf)
              fd.close()
              pass
          
          def update_file(image_file, label_file, image_list, label_list):
              ifd = open(image_file, 'r+')
              ifd.seek(0)
              image_magic, image_count, rows, cols = struct.unpack(">IIII", ifd.read(IMAGE_BASE_OFFSET))
              image_len = rows * cols
              image_offset = image_count * rows * cols + IMAGE_BASE_OFFSET
              ifd.seek(image_offset)
              for image in image_list:
                  ifd.write(image.astype('uint8').reshape(image_len).tostring())
              image_count += len(image_list)
              ifd.seek(0, 0)
              buf = struct.pack(">II", image_magic, image_count)
              ifd.write(buf)
              ifd.close()
          
              lfd = open(label_file, 'r+')
              lfd.seek(0)
              label_magic, label_count = struct.unpack(">II", lfd.read(LABEL_BASE_OFFSET))
              buf = ''.join(label_list)
              label_offset = label_count + LABEL_BASE_OFFSET
              lfd.seek(label_offset)
              lfd.write(buf)
          
              lfd.seek(0)
              label_count += len(label_list)
              buf = struct.pack(">II", label_magic, label_count)
              lfd.write(buf)
              lfd.close()
          
          
          def mnist_generate(image_dir):
              if not os.path.isdir(image_dir):
                  raise Exception("{0} is not exists!".format(image_dir))
          
              image_file = os.path.join(image_dir, "user-images-ubyte")
              label_file = os.path.join(image_dir, "user-labels-ubyte")
              create_image_file(image_file)
              create_label_file(label_file)
          
              for i in range(10):
                  path = os.path.join(image_dir, "{0}".format(i))
                  if not os.path.isdir(path):
                      continue
                  image_list = []
                  label_list = []
                  for f in os.listdir(path):
                      fn = os.path.join(path, f)
                      image = cv2.imread(fn, 0)
                      w, h = image.shape
                      if w and h and (w <> 28) or (h <> 28):
                          simg = cv2.resize(image, (28, 28))
                          image_list.append(simg)
                          label_list.append(chr(i))
                  update_file(image_file, label_file, image_list, label_list)
              print "user data generate successfully"
              print "output files: \n\t {0}\n\t {1}".format(image_file, label_file)
              pass


          上面是用 python 寫(xiě)的一個(gè)工具,可以組裝 idx 格式的 mnist 數(shù)據(jù)集,用之前的 mnist-ld 進(jìn)行處理,就可以替換成我們生成的數(shù)據(jù)集了。


          樣本增強(qiáng)


          使用樣本平臺(tái)更方便:


          特征工程


          特征分析和處理可以幫助我們更好的優(yōu)化數(shù)據(jù)集,為了得到圖像的特征,可以采用 Keypoint、SIFT 等特征來(lái)表征圖像,這種高階的特征具有各自的優(yōu)勢(shì),例如 SIFT 可以克服旋轉(zhuǎn)、Keypoint 可以克服形變……等等。




          模型訓(xùn)練


          Pipline配置:


          {
            "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": [28,28]
                }
              },
              "modelDefine": {
                "package": "@pipcook/plugins-tfjs-simplecnn-model-define"
              },
              "modelTrain": {
                "package": "@pipcook/plugins-image-classification-tfjs-model-train",
                "params": {
                  "epochs": 15
                }
              },
              "modelEvaluate": {
                "package": "@pipcook/plugins-image-classification-tfjs-model-evaluate"
              }
            }
          }


          模型訓(xùn)練:


          $ pipcook run examples/pipelines/mnist-image-classification.json


          模型預(yù)測(cè):


          $ pipcook board


          原理解析


          回顧整個(gè)工程改造的過(guò)程:理解 Pipline 的任務(wù)、理解 Pipline 工作原理、了解數(shù)據(jù)集格式、準(zhǔn)備訓(xùn)練數(shù)據(jù)、重新訓(xùn)練模型、模型預(yù)測(cè),下面分別介紹這些關(guān)鍵步驟:

          理解 Pipline 的任務(wù)

          對(duì)于 Pipcook 內(nèi)置的 Example ,分為三類:機(jī)器視覺(jué)、自然語(yǔ)言處理、強(qiáng)化學(xué)習(xí)。機(jī)器視覺(jué)和自然語(yǔ)言處理,代表“看見(jiàn)”和“理解”,強(qiáng)化學(xué)習(xí)代表決策和生成,這些內(nèi)容可類比于一個(gè)程序員,從看到、理解、編寫(xiě)代碼的過(guò)程。在不同的編程任務(wù)中組合使用不同的能力,這就是 Pipline 的使命。


          對(duì)于 mnist 手寫(xiě)數(shù)字識(shí)別這種簡(jiǎn)單的任務(wù),只需要使用部分機(jī)器視覺(jué)的能力即可,對(duì)于 imgcook.com 這種復(fù)雜的應(yīng)用場(chǎng)景,就會(huì)涉及很多復(fù)雜的能力。針對(duì)不同的任務(wù),通過(guò) Pipline 管理機(jī)器學(xué)習(xí)能力使用的方式,就可以把不同的機(jī)器學(xué)習(xí)能力組合起來(lái)。


          最后,需要理解 “機(jī)器學(xué)習(xí)應(yīng)用工程” 和 “機(jī)器學(xué)習(xí)算法工程” 的區(qū)別。機(jī)器學(xué)習(xí)算法工程中,主要是算法工程師在設(shè)計(jì)、調(diào)整、訓(xùn)練模型。機(jī)器學(xué)習(xí)應(yīng)用工程中,主要是選擇、訓(xùn)練模型。前者是為了創(chuàng)造、改造模型,后者是為了應(yīng)用模型和算法能力。未來(lái),在研讀機(jī)器學(xué)習(xí)資料和教材時(shí),可針對(duì)上述原則側(cè)重于模型思想和模型應(yīng)用,不要被書(shū)里的公式嚇到,那些公式只是用數(shù)學(xué)方法描述模型思想而已。


          理解 Pipline 工作原理

          這就是Pipline的工作原理,主要由圖中 7 類插件構(gòu)成了整個(gè)算法工程鏈路。由于引入了 plugin 的開(kāi)放模式,對(duì)于自己的前端工程,可以在遇到問(wèn)題的時(shí)候,自己開(kāi)發(fā) plugin 來(lái)完成工程接入。Plugin 開(kāi)發(fā)文檔在:https://alibaba.github.io/pipcook/#/tutorials/how-to-develop-a-plugin


          了解數(shù)據(jù)集格式


          了解數(shù)據(jù)集格式是為了讓 Pipline 跑起來(lái),更具體一點(diǎn)兒是讓模型可以識(shí)別并使用數(shù)據(jù)。不同的任務(wù)對(duì)應(yīng)不同類型的模型,不同的模型對(duì)應(yīng)不同類型的數(shù)據(jù)集,這種對(duì)應(yīng)關(guān)系保證了模型能夠正確被訓(xùn)練。在 Pipcook 里定義的數(shù)據(jù)集格式也針對(duì)了不同的任務(wù)和模型,對(duì)于機(jī)器視覺(jué)的數(shù)據(jù)集是 VOC,對(duì)于 NLP Pipcook 定義的數(shù)據(jù)集是 CSV 。具體的數(shù)據(jù)集格式,可以按照文檔:https://alibaba.github.io/pipcook/#/spec/dataset 的說(shuō)明來(lái)分析和理解。也可以采用本文介紹的方法,從相關(guān)處理程序和代碼里進(jìn)行分析。


          準(zhǔn)備訓(xùn)練數(shù)據(jù)


          數(shù)據(jù)為什么是最重要的部分?因?yàn)閿?shù)據(jù)的準(zhǔn)確性、分布合理性、數(shù)據(jù)對(duì)特征描述的充分性……直接決定了最終的模型效果。為了準(zhǔn)備高質(zhì)量的數(shù)據(jù),還需要掌握 Puppeteer 等工具和爬蟲(chóng)……等。還可以在傳統(tǒng)機(jī)器學(xué)習(xí)理論和工具基礎(chǔ)上,借助 PCA 算法等方式評(píng)估數(shù)據(jù)質(zhì)量。還可以用數(shù)據(jù)可視化工具,來(lái)直觀的感受數(shù)據(jù)分布情況:

          具體可以查看:https://www.yuque.com/zhenzishadow/tx7xtl/xhol3k 我的這篇文章。


          訓(xùn)練和預(yù)測(cè)、部署


          訓(xùn)練模型沒(méi)有太多可說(shuō)的,因?yàn)榻裉斓哪P统瑓?shù)并不想以前那么敏感,調(diào)參不如調(diào)數(shù)據(jù)。那么,參數(shù)在訓(xùn)練的時(shí)候還有什么意義呢? 遷就GPU和顯存大小。因?yàn)橛?xùn)練的時(shí)候,除了模型的復(fù)雜度外,超參數(shù)適當(dāng)?shù)恼{(diào)小雖然會(huì)犧牲訓(xùn)練速度(也可能影響模型準(zhǔn)確率),但起碼可以保證模型能夠被訓(xùn)練。因此,在 Pipcook 的模型配置中,一旦發(fā)現(xiàn)顯卡OOM了,可以通過(guò)調(diào)整超參數(shù)來(lái)解決。


          預(yù)測(cè)的時(shí)候唯一需要注意的是:輸入模型訓(xùn)練的數(shù)據(jù)格式和輸入模型預(yù)測(cè)的格式必須一致。


          部署的時(shí)候需要注意的是對(duì)容器的選擇,如果只是簡(jiǎn)單的模型,其實(shí) CPU 容器足夠用了,畢竟預(yù)測(cè)不像訓(xùn)練那樣消耗算力。如果部署的模型很復(fù)雜,預(yù)測(cè)時(shí)間很長(zhǎng)無(wú)法接受,則可以考慮 GPU 或 異構(gòu)運(yùn)算容器。GPU 容器比較通用的是 NVIDIA 的 CUDA 容器,可以參考:https://github.com/NVIDIA/nvidia-docker。如果要使用異構(gòu)運(yùn)算容器,比如阿里云提供的賽靈思容器等,可以參考阿里云相關(guān)的文檔。


          寫(xiě)在最后


          這篇文章斷斷續(xù)續(xù)寫(xiě)了很久,主要還是平時(shí)比較忙,后續(xù)會(huì)努力帶來(lái)更多文章,分享更多自己在實(shí)踐中的一些方法和思考。下一篇會(huì)系統(tǒng)完整的介紹一下 NLP 自然語(yǔ)言處理的方法,也會(huì)按照:快速實(shí)驗(yàn)、實(shí)踐方法、原理解析這種模式來(lái)做,敬請(qǐng)期待。

          日,企業(yè)協(xié)作平臺(tái)Box宣布完成對(duì)Verold的收購(gòu),后者是一家初創(chuàng)公司,主要開(kāi)發(fā)基于云的3D模型查看器和編輯器。Verold的特點(diǎn)在于使用WebGL,WebGL是一個(gè)JavaScript API,不需要插件就可以在瀏覽器中呈現(xiàn)交互式3D計(jì)算機(jī)圖形。

          Verold的應(yīng)用范圍極其廣泛。工程師可以用它分享產(chǎn)品的3D模型,遍布全球的供應(yīng)鏈可以快速同步信息;老師可以用它在課堂上營(yíng)造出生動(dòng)的教學(xué)情境,尤其是在數(shù)學(xué)課和地理課上;電商可以用它提供交互式3D購(gòu)物體驗(yàn)。點(diǎn)此體驗(yàn)Verold的交互式3D模型。

          通過(guò)收購(gòu)Verold,Box希望為自己的4.5萬(wàn)戶企業(yè)用戶帶來(lái)企業(yè)協(xié)作的新形勢(shì),用戶將能以3D模型的形式預(yù)覽、注釋和協(xié)作。這種應(yīng)用形式并不新鮮,在此之前,Verold已經(jīng)和亞馬遜、皮爾森、Mixamo、Autodesk等大型企業(yè)合作過(guò)。

          宣布收購(gòu)后的第二天,昨日,Box又宣布開(kāi)源T3框架,該技術(shù)被Box內(nèi)部應(yīng)用于大型JavaScript應(yīng)用程序的部署。T3將可伸縮的JavaScript應(yīng)用架構(gòu)轉(zhuǎn)換為去模型化的系統(tǒng)。這樣一來(lái),就能夠獨(dú)立編寫(xiě)小組件。

          Box稱,T3已經(jīng)開(kāi)發(fā)了10個(gè)月,T3實(shí)現(xiàn)新特性的速度比傳統(tǒng)JavaScript快一些。總的來(lái)說(shuō),T3的目的是幫助實(shí)現(xiàn)企業(yè)協(xié)作和模塊化設(shè)計(jì)。

          約信是什么?

          根據(jù)澳洲官網(wǎng)材料清單的要求,想要成功遞簽,你必須要有一個(gè)預(yù)約信,來(lái)證明你搶到了打工度假名額。預(yù)約信就相當(dāng)于一張門(mén)票,能夠讓你有資格進(jìn)入簽證中心遞交自己的資料。

          這個(gè)預(yù)約信,其實(shí)就相當(dāng)于一個(gè)篩選方案,澳洲WHV名額有限,而申請(qǐng)人數(shù)人數(shù)眾多,土澳就采取了這么個(gè)先到先得的辦法,來(lái)把這每年5000個(gè)的名額分配到大伙的手里。預(yù)約確認(rèn)信,也就是我們俗稱的名額了,如果拿到了預(yù)約信,然后打印下來(lái),只要符合澳方要求,不造假,一步一步來(lái)準(zhǔn)備好材料清單里面的其他事項(xiàng),基本就能拿到簽證了~

          預(yù)約信里,會(huì)讓你選擇遞簽的城市、日期、時(shí)間,還會(huì)要求填護(hù)照號(hào)、手機(jī)號(hào)等個(gè)人細(xì)心。所以如果想搶名額的朋友,一定要在開(kāi)搶前準(zhǔn)備好自己的護(hù)照號(hào)等材料。(目前澳洲規(guī)定,無(wú)論你搶到的預(yù)約信上的是哪個(gè)城市,都沒(méi)有關(guān)系,你可以選擇北京上海廣州成都的任意一個(gè)簽證中心遞簽。)

          預(yù)約信是每年分批發(fā)放的,點(diǎn)擊這里了解澳洲開(kāi)放搶名額的時(shí)間。

          預(yù)約信相當(dāng)于一個(gè)排號(hào)系統(tǒng),拿到預(yù)約信,一定要在這個(gè)預(yù)約信上寫(xiě)的日期和時(shí)間去遞交,城市不限。比如澳洲第一批9月21號(hào)開(kāi)放預(yù)約的時(shí)候,每個(gè)城市都有一定數(shù)量的名額。能選的預(yù)約日期大約是9月21日-10月23日,每個(gè)日期里,其實(shí)就平均地分布著一定數(shù)量的名額,如果某個(gè)日期的時(shí)間槽先被約空了,那么這個(gè)日期就不能再約了,只能換個(gè)日期。如果所有日期都被約完了,也就代表著這個(gè)城市沒(méi)名額了。如果四個(gè)城市都被約空了,那么這次搶名額也就結(jié)束了。

          【2018年11月批次更新:個(gè)別簽證中心,有遲到的小伙伴,被簽證中心要求交300塊錢(qián)的vip服務(wù)費(fèi),然后才給進(jìn)門(mén)。所以不要遲到,克服一下困難準(zhǔn)時(shí)到吧,省的出幺蛾子。】

          在簽證當(dāng)天,會(huì)有數(shù)十萬(wàn)的人,夾雜著各種中介,一起來(lái)?yè)屵@些名額。一般來(lái)說(shuō),大約會(huì)有一個(gè)月的時(shí)間可以選。后面的日期會(huì)比較緊俏,最先被搶空的會(huì)是靠后的日期。(有人問(wèn)能不能約在明年,那是肯定不行的啊,因?yàn)槊髂甑娜掌诟静婚_(kāi)放預(yù)約。一般就是近一個(gè)月內(nèi)的)

          我們建議提早準(zhǔn)備好材料的原因,就是因?yàn)槟芙o您自己更大的選擇空間,來(lái)選擇自己想要的時(shí)間區(qū)間。 不然如果等到官方開(kāi)放時(shí),你啥材料都沒(méi)準(zhǔn)備,后面的日期又那么難搶,可就捉襟見(jiàn)肘了。


          預(yù)約網(wǎng)址:

          官方給的網(wǎng)址:http://www.vfsglobal.cn/australia/china/

          和打工度假簽證相關(guān)的信息,這里算是最官方的來(lái)源了。

          預(yù)約頁(yè)面:http://www.vfsglobal.cn/Australia/China/schedule_an_appointment.html

          預(yù)約系統(tǒng)最快網(wǎng)址(雖然是最快,但澳洲服務(wù)器經(jīng)常做調(diào)整,搶名額時(shí)也可能突變。所以如果這個(gè)打不開(kāi),也不要見(jiàn)怪,建議從上面那個(gè)預(yù)約頁(yè)面開(kāi)始走。):

          https://visaservicesonline.vfsglobal.com/DIAC-China-Appointment_new/AppScheduling/AppWelcome.aspx?p=Gta39GFZnstZVCxNVy83zTlkvzrXE95fkjmft28XjNg=

          模擬練習(xí)預(yù)約網(wǎng)址,可以用來(lái)平時(shí)練習(xí):http://moni.chinawhver.com/


          預(yù)約流程:

          1、打開(kāi)預(yù)約頁(yè)面:http://www.vfsglobal.cn/Australia/China/schedule_an_appointment.html,往下拉,找到“預(yù)約”,并點(diǎn)擊。

          2、到下一頁(yè),再次找到預(yù)約,并點(diǎn)擊。

          3、先輸入驗(yàn)證碼(注意區(qū)分大小寫(xiě)),然后選擇想要前往遞交的簽證申請(qǐng)中心(分別是:北京,廣州,上海,成都),點(diǎn)擊提交。

          需要說(shuō)明的是,遞交簽證申請(qǐng)是不劃分領(lǐng)區(qū)的,也就是說(shuō),無(wú)論你是哪里人,你都可以選擇去任意一個(gè)簽證申請(qǐng)中心。并且現(xiàn)在無(wú)論你選哪個(gè)簽證中心都沒(méi)有關(guān)系,任意城市可以遞簽。所以找個(gè)有名額的城市選就行了。

          4、選擇好了后,點(diǎn)擊提交。然后選擇簽證的種類 work and holiday visa,一同申請(qǐng)人數(shù)只能填1(填別的無(wú)法繼續(xù))。選擇好了以后,點(diǎn)擊提交,如果還有名額,那么就會(huì)顯示下一個(gè)可用的時(shí)間段可以從xx,如果沒(méi)有名額,則顯示:無(wú)日期(委任)。申請(qǐng)的時(shí)候請(qǐng)務(wù)必選擇work and holiday visa!(平時(shí)練習(xí)可以用模擬預(yù)約系統(tǒng))

          5、你需要輸入一個(gè)能接收郵件的個(gè)人郵箱,一定要可以接收郵件哦,因?yàn)橹蟮尿?yàn)證碼會(huì)發(fā)到這個(gè)郵箱里.

          6、設(shè)置一個(gè)密碼,注意,這個(gè)密碼并不是指你的郵箱密碼,而是你以后用來(lái)查預(yù)約信要填的密碼。同時(shí),如果以后你還想預(yù)約的話,必須要輸入相同密碼。密碼至少需要含大小寫(xiě)字母和一個(gè)數(shù)字。

          7、再次輸入剛才輸入的郵箱和密碼,提交

          8、填寫(xiě)申請(qǐng)人信息。注意這里面的所有信息都必須要用大寫(xiě)字母(除了qq郵箱)。護(hù)照號(hào)第一位是字母,第二位可能是字母或數(shù)字,后面7位都是數(shù)字。點(diǎn)此查看護(hù)照號(hào)中難辨別字母的辨識(shí)方法 。 姓氏和名字都是填你中文名的大寫(xiě)全拼。區(qū)號(hào)填86或者086就可以了。座機(jī)號(hào)碼可以不填,但是保險(xiǎn)起見(jiàn)還是填一下比較好。

          9、選擇一個(gè)你想要的遞簽日期。

          10、然后選擇一個(gè)你想要的時(shí)間。

          11、接下來(lái)的這一頁(yè),填寫(xiě)三個(gè)字母對(duì)應(yīng)的空格,所對(duì)應(yīng)的數(shù)字已經(jīng)通過(guò)郵件發(fā)到你的郵箱了,你需要找到附件,然后打開(kāi)來(lái)。找到三個(gè)字母對(duì)應(yīng)的數(shù)字輸入進(jìn)去,然后點(diǎn)擊確定。

          12、最后,我們就能看到一封預(yù)約信了。記得把它打印或者保存下來(lái)。

          注意:以上頁(yè)面都是不能往回走的,所以仔細(xì)選擇。

          這個(gè)網(wǎng)站平時(shí)是不開(kāi)的,大家基本都只能用模擬預(yù)約的網(wǎng)站練習(xí),模擬預(yù)約聯(lián)系網(wǎng)站不存在取消不取消預(yù)約的問(wèn)題,因?yàn)槟愕馁Y料不可能進(jìn)庫(kù)。除了這個(gè)搶名額WHV系統(tǒng),澳洲還有個(gè)平時(shí)用來(lái)預(yù)約簽證申請(qǐng)的系統(tǒng),那個(gè)系統(tǒng)不是用來(lái)預(yù)約WHV的,不要走錯(cuò)地方,在那個(gè)可以進(jìn)的系統(tǒng)里,盡量不要填寫(xiě)自己的真實(shí)護(hù)照號(hào),記得及時(shí)取消預(yù)約,只需要到官網(wǎng),點(diǎn)擊取消預(yù)約,然后一步步做就行了。

          真正搶名額的時(shí)候,用的是WHV的通道,WHV的名額是不能取消的,所以也不用擔(dān)心別人威脅你說(shuō)取消你的預(yù)約信。拿到預(yù)約信后,就可以安心準(zhǔn)備其他材料了。點(diǎn)擊這里請(qǐng)看材料清單。

          注意! 護(hù)照號(hào)共9位,第一位是E或者G,第二位可能是字母或數(shù)字,其余七位必為數(shù)字。不要弄錯(cuò)了。點(diǎn)此查看護(hù)照號(hào)中難辨別字母的辨識(shí)方法

          需要注意的是,曾經(jīng)簽證中心會(huì)原諒一些預(yù)約信上的小錯(cuò)誤,比如寫(xiě)錯(cuò)一個(gè)字母之類的。但是!2017年7月31日的批次開(kāi)始,簽證中心在門(mén)口查看預(yù)約信時(shí)變的極其嚴(yán)格!預(yù)約信里一點(diǎn)小錯(cuò)誤都不原諒,如果發(fā)現(xiàn)和護(hù)照上有一絲不同,不管是護(hù)照號(hào)還是名字,直接不予受理遞簽請(qǐng)求(這種情況以后可以重新?lián)屆~繼續(xù)遞交,但就是耽誤事,又得拖到下次搶名額。)

          我這里碰到了一個(gè)最悲催的例子。護(hù)照號(hào)第二位的1,看起來(lái)就像個(gè)I。護(hù)照是黑體顯示的,正常人都有可能看錯(cuò)。因?yàn)閮蓚€(gè)長(zhǎng)得都差不多,都是一根豎杠。

          但姓氏和名字沒(méi)有正反之分,澳洲預(yù)約系統(tǒng)本身對(duì)姓氏和名字這兩個(gè)參數(shù)就管理混亂,顛來(lái)倒去的,填反完全不賴你。

          在WHV的申請(qǐng)過(guò)程中,預(yù)約信相當(dāng)于就是一張門(mén)票,能讓你進(jìn)入簽證中心的大門(mén),去交資料。只要進(jìn)去之后,預(yù)約信就完成了它的使命,里頭的郵箱、手機(jī)號(hào)等,完全沒(méi)什么用。簽證官所看的信息,都是1208和54表里面的信息,包括郵箱、手機(jī)號(hào)等也都是。


          如何查詢預(yù)約信

          1、打開(kāi)預(yù)約頁(yè)面:http://www.vfsglobal.cn/Australia/China/schedule_an_appointment.html,往下拉,找到WHV入口

          2、再次找到打印預(yù)約信,并點(diǎn)擊。

          3、輸入預(yù)約時(shí)填的賬號(hào)密碼(這里其實(shí)只要有預(yù)約信的郵箱,都可以輸入,不嚴(yán)格對(duì)應(yīng)。人人都可以跳過(guò)這一步,然后查到你的預(yù)約信,所以不能以誰(shuí)能查到預(yù)約信作為收費(fèi)標(biāo)準(zhǔn))

          4、選擇一個(gè)查詢號(hào)碼。

          5、填寫(xiě)自己的信息。確認(rèn)號(hào)碼可以空著。護(hù)照號(hào)碼要填,姓氏是大寫(xiě)英文。如果姓氏不對(duì)的話,填自己的名(大寫(xiě)英文)試試。肯定有一個(gè)能成功。下一頁(yè)就是預(yù)約信了。

          多啰嗦一句。姓名相反真的不用糾結(jié)!妥妥的遞簽成功。


          如何判斷是誰(shuí)搶到了預(yù)約信

          在預(yù)約信查詢里我們就說(shuō)到,其實(shí)只要?jiǎng)e人知道你的護(hù)照號(hào),就能查到你的預(yù)約信。比如,我用一個(gè)郵箱,隨便約了個(gè)general的名額,接下來(lái),就可以到預(yù)約信查詢界面,賬號(hào)密碼驗(yàn)證成功,到達(dá)打印預(yù)約信界面。然后,我只需要輸入自己想要查詢的護(hù)照號(hào)碼和姓氏,別人的預(yù)約信我也一樣能查到。

          但有另一個(gè)方法,是鑒別郵箱是否約到預(yù)約信的有效手段。

          1、打開(kāi)預(yù)約頁(yè)面:http://www.vfsglobal.cn/Australia/China/schedule_an_appointment.html,往下拉,找到WHV入口

          2、再次找到取消預(yù)約,并點(diǎn)擊。如果取消預(yù)約按鈕不見(jiàn)了,請(qǐng)參考以下方法將它顯示:https://auwhver.com/33177

          3、輸入預(yù)約用的郵箱和密碼

          3、隨便選一個(gè)選項(xiàng)

          4、這個(gè)郵箱約到過(guò)哪個(gè)護(hù)照號(hào),一目了然。

          再次強(qiáng)調(diào),WHV的名額是取消不掉的,所以大家完全不用擔(dān)心,哪怕在這里點(diǎn)了取消預(yù)約,你還是能查到的。只有g(shù)eneral的名額是能取消的(順便提一句,注意一下預(yù)約信上面的簽證類別。別被某些別有用心的人渾水摸魚(yú)。)

          還有一些人,給你截個(gè)圖,表面上看,刪除預(yù)約信里面確實(shí)有護(hù)照號(hào),其實(shí)都是篡改網(wǎng)頁(yè)后臺(tái)之后截圖的。大家一定要親自去官網(wǎng),輸入郵箱和密碼,這樣查到的才算靠譜。


          進(jìn)階

          搶預(yù)約信,遠(yuǎn)遠(yuǎn)不是以上流程所述的那么簡(jiǎn)單,因?yàn)檎嬲龘尩臅r(shí)候,很有可能連網(wǎng)頁(yè)都打不開(kāi)。所以我們必須要準(zhǔn)備更有力的武器,詳情可以參考:

          https://auwhver.com/7694

          https://auwhver.com/7756

          https://auwhver.com/7752


          主站蜘蛛池模板: 99热门精品一区二区三区无码| 国产麻豆精品一区二区三区v视界| 亚洲国产精品无码第一区二区三区| 亚洲码欧美码一区二区三区| 日本一区二区三区在线观看| 精品国产毛片一区二区无码| 一区二区三区精密机械| 亚洲一区爱区精品无码| 国产乱码伦精品一区二区三区麻豆| 人妻视频一区二区三区免费 | 中文字幕一区日韩在线视频| 精品国产一区二区三区在线 | 无码精品人妻一区| 无码夜色一区二区三区| 亚洲AV无码一区二区三区网址| 亚洲视频一区调教| 无码乱人伦一区二区亚洲| 中文字幕在线无码一区| 亚洲国产一区二区三区| 成人国内精品久久久久一区| 国产精品一区12p| 精品福利一区二区三| 久久精品视频一区| 麻豆一区二区在我观看| 日韩免费一区二区三区在线播放| 一区二区三区在线免费看| 3d动漫精品啪啪一区二区中文| 国产短视频精品一区二区三区| 韩国福利一区二区美女视频| 中文精品一区二区三区四区| 韩国福利视频一区二区 | 亚洲成AV人片一区二区密柚 | 成人精品视频一区二区三区| 精品无码综合一区| 精品无码人妻一区二区三区不卡| 中文字幕无码免费久久9一区9| 国产精品区一区二区三在线播放| 亚洲一区二区三区深夜天堂 | 人妻无码一区二区三区AV| 亚洲性无码一区二区三区| 国产免费私拍一区二区三区|