偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

還能這樣?把Python自動(dòng)翻譯成C++

新聞 前端
隨著深度學(xué)習(xí)的廣泛應(yīng)用,在搜索引擎/推薦系統(tǒng)/機(jī)器視覺等業(yè)務(wù)系統(tǒng)中,越來越多的深度學(xué)習(xí)模型部署到線上服務(wù)。

 

一、問題背景

隨著深度學(xué)習(xí)的廣泛應(yīng)用,在搜索引擎/推薦系統(tǒng)/機(jī)器視覺等業(yè)務(wù)系統(tǒng)中,越來越多的深度學(xué)習(xí)模型部署到線上服務(wù)。

機(jī)器學(xué)習(xí)模型在離線訓(xùn)練時(shí),一般要將輸入的數(shù)據(jù)做特征工程預(yù)處理,再輸入模型在 TensorFlow PyTorch 等框架上做訓(xùn)練。

1.常見的特征工程邏輯

常見的特征工程邏輯有:

  • 分箱/分桶 離散化

  • log/exp 對(duì)數(shù)/冪等 math numpy 常見數(shù)學(xué)運(yùn)算

  • 特征縮放/歸一化/截?cái)?/p>

  • 交叉特征生成

  • 分詞匹配程度計(jì)算

  • 字符串分隔匹配判斷 tong

  • 缺省值填充等

  • 數(shù)據(jù)平滑

  • onehot 編碼,hash 編碼等

這些特征工程代碼,當(dāng)然一般使用深度學(xué)習(xí)最主要的語言 python 實(shí)現(xiàn)。

二、業(yè)務(wù)痛點(diǎn)

離線訓(xùn)練完成,模型上線部署后,同樣要 用 C++ 重新實(shí)現(xiàn) 這些 python 的特征工程邏輯代碼。

我們發(fā)現(xiàn), “用 C++ 重新實(shí)現(xiàn)” 這個(gè)步驟,給實(shí)際業(yè)務(wù)帶來了大量的問題:

  1. 繁瑣,費(fèi)時(shí)費(fèi)力,極容易出現(xiàn) python 和 C++ 代碼 不一致

  2. 不一致會(huì)直接影響模型在線上的效果,導(dǎo)致大盤業(yè)務(wù)指標(biāo)不如預(yù)期,產(chǎn)生各種 bad case

  3. 不一致難以發(fā)現(xiàn),無法測(cè)試,無法監(jiān)控,經(jīng)常要靠用戶投訴反饋,甚至大盤數(shù)據(jù)異常才能發(fā)現(xiàn)

1. 業(yè)界方案

針對(duì)這些問題,我調(diào)研了這些業(yè)界方案:

《推薦系統(tǒng)中模型訓(xùn)練及使用流程的標(biāo)準(zhǔn)化》

https://www.infoq.cn/article/2E6LCqb1GeqFRAjkkjX3

《自主研發(fā)、不斷總結(jié)經(jīng)驗(yàn),美團(tuán)搜索推薦機(jī)器學(xué)習(xí)平臺(tái)》

https://cloud.tencent.com/developer/article/1357309

《京東電商推薦系統(tǒng)實(shí)踐》

https://www.infoq.cn/article/1OkKmb_gEYNR3YqC9RcW

“模型線上線下一致性問題對(duì)于模型效果非常重要,我們使用特征日志來實(shí)時(shí)記錄特征,保證特征的一致性。這樣離線處理的時(shí)候會(huì)把實(shí)時(shí)的用戶反饋,和特征日志做一個(gè)結(jié)合生成訓(xùn)練樣本,然后更新到模型訓(xùn)練平臺(tái)上,平臺(tái)更新之后在推送到線上,這樣整個(gè)排序形成了一個(gè)閉環(huán)。”

總結(jié)起來,有幾種思路:

  • 在線特征存儲(chǔ)起來給離線用

  • 在線 C++ 代碼編譯成 so 導(dǎo)出給離線用

  • 根據(jù)一份配置生成離線和在線代碼

  • 提取公共代碼,加強(qiáng)代碼復(fù)用,等軟件工程手段,減少不一致

2. 自動(dòng)翻譯方案

(1) .已有方案的缺點(diǎn)

但這些思路都有各種缺點(diǎn):

  • 所有在線請(qǐng)求的所有特征,這個(gè)存儲(chǔ)量數(shù)據(jù)量很大

  • 算法改代碼需要等待后臺(tái)開發(fā),降低了算法同學(xué)的工作效率

  • 特征處理代碼的復(fù)雜度轉(zhuǎn)移到配置文件中,不一定能充分表達(dá),而且配置格式增加學(xué)習(xí)成本

  • 就這邊真實(shí)離線特征處理代碼來看,大部分代碼都無法抽取出公共代碼做復(fù)用。

(2). 翻譯器

回到問題出發(fā)點(diǎn)考慮,顯而易見,這個(gè)問題歸根結(jié)底就是需要一個(gè) “ python 到 c++ 的翻譯器 ” 。

那其實(shí) “翻譯器 Transpiler ” ,和編譯器解釋器類似,也是個(gè)古老的熱門話題了,比如 WebAssembly , CoffeeScript , Babel ,

Google Closure Compiler , f2c

于是一番搜索,發(fā)現(xiàn) python 到 C++ 的翻譯器也不少,其中 Pythran 是新興比較熱門的開源項(xiàng)目。

于是一番嘗試后,借助 pythran,我們實(shí)現(xiàn)了:

  • 一條命令 全自動(dòng)把 Python 翻譯成等價(jià) C++

  • 嚴(yán)格等價(jià)保證改寫,徹底消除不一致

  • 完全去掉重新實(shí)現(xiàn)這塊工作量,后臺(tái)開發(fā)成本降到 0 ,徹底解放生產(chǎn)力

  • 算法同學(xué)繼續(xù)使用純 python,開發(fā)效率無影響,** 無學(xué)習(xí)成本 **

  • 并能推廣到其他需要 python 改寫成后臺(tái) C++ 代碼 的業(yè)務(wù)場(chǎng)景,解放生產(chǎn)力

三、pythran 的使用流程

(1). 安裝

一條命令安裝:

  1. pip3 install pythran 

(2). 寫 Python 代碼

下面這個(gè) python demo,是 pythran 官方 demo。

  1. import math 
  2. import numpy as np 
  3.  
  4. def zero(n, m): 
  5.     return [[0]*n for col in range(m)] 
  6.  
  7. #pythran export matrix_multiply(float list list, float list list) 
  8. def matrix_multiply(m0, m1): 
  9.     new_matrix = zero(len(m0),len(m1[0])) 
  10.     for i in range(len(m0)): 
  11.         for j in range(len(m1[0])): 
  12.             for k in range(len(m1)): 
  13.                 new_matrix[i][j] += m0[i][k]*m1[k][j] 
  14.     return new_matrix 
  15.  
  16. #pythran export arc_distance(float[], float[], float[], float[]) 
  17. def arc_distance(theta_1, phi_1, theta_2, phi_2): 
  18.     """ 
  19.     Calculates the pairwise arc distance 
  20.     between all points in vector a and b. 
  21.     """ 
  22.     temp = (np.sin((theta_2-theta_1)/2)**2 
  23.            + np.cos(theta_1)*np.cos(theta_2) * np.sin((phi_2-phi_1)/2)**2
  24.     distance_matrix = 2 * np.arctan2(np.sqrt(temp), np.sqrt(1-temp)) 
  25.     return distance_matrix 
  26.  
  27.  
  28. #pythran export dprod(int list, int list) 
  29. def dprod(l0,l1): 
  30.     """WoW, generator expression, zip and sum.""" 
  31.     return sum(x * y for x, y in zip(l0, l1)) 
  32.  
  33.  
  34. #pythran export get_age(int ) 
  35. def get_age(age): 
  36.     if age <= 20
  37.         age_x = '0_20' 
  38.     elif age <= 25
  39.         age_x = '21_25' 
  40.     elif age <= 30
  41.         age_x = '26_30' 
  42.     elif age <= 35
  43.         age_x = '31_35' 
  44.     elif age <= 40
  45.         age_x = '36_40' 
  46.     elif age <= 45
  47.         age_x = '41_45' 
  48.     elif age <= 50
  49.         age_x = '46_50' 
  50.     else
  51.         age_x = '50+' 
  52.     return age_x 

(3). Python 轉(zhuǎn)成 C++

一條命令完成翻譯:

  1. pythran -e demo.py -o  demo.hpp 

(4). 寫 C++ 代碼調(diào)用

pythran/pythonic/ 目錄下是 python 標(biāo)準(zhǔn)庫的 C++ 等價(jià)實(shí)現(xiàn),翻譯出來的 C++ 代碼需要 include 這些頭文件。

寫個(gè) C++ 代碼調(diào)用:

  1. #include "demo.hpp" 
  2. #include "pythonic/numpy/random/rand.hpp" 
  3. #include <iostream> 
  4.  
  5. using std::cout; 
  6. using std::endl; 
  7.  
  8. int main() { 
  9.   pythonic::types::list<pythonic::types::list<double>> m0 = {{2.0, 3.0}, 
  10.                                                              {4.0, 5.0}}, 
  11.                                                        m1 = {{1.0, 2.0}, 
  12.                                                              {3.0, 4.0}}; 
  13.   cout << m0 << "*" << m1 << "\n=\n" 
  14.        << __pythran_demo::matrix_multiply()(m0, m1) << endl 
  15.        << endl; 
  16.  
  17.   auto theta_1 = pythonic::numpy::random::rand(3), 
  18.        phi_1 = pythonic::numpy::random::rand(3), 
  19.        theta_2 = pythonic::numpy::random::rand(3), 
  20.        phi_2 = pythonic::numpy::random::rand(3); 
  21.   cout << "arc_distance " << theta_1 << "," << phi_1 << "," << theta_2 << "," 
  22.        << phi_2 << "\n=\n" 
  23.        << __pythran_demo::arc_distance()(theta_1, phi_1, theta_2, phi_2) << endl 
  24.        << endl; 
  25.  
  26.   pythonic::types::list<int> l0 = {2, 3}, l1 = {4, 5}; 
  27.   cout << "dprod " << l0 << "," << l1 << "\n=\n" 
  28.        << __pythran_demo::dprod()(l0, l1) << endl 
  29.        << endl; 
  30.  
  31.   cout << "get_age 30 = " << __pythran_demo::get_age()(30) << endl << endl; 
  32.  
  33.   return 0; 

(5). 編譯運(yùn)行

  1. g++ -g -std=c++11 main.cpp -fopenmp -march=native -DUSE_XSIMD -I /usr/local/lib/python3.6/site-packages/pythran/ -o pythran_demo 
  2.  
  3. ./pythran_demo 

四、pythran 的功能與特性

(1). 介紹

按官方定義,Pythran 是一個(gè) AOT (Ahead-Of-Time - 預(yù)先編譯) 編譯器。給科學(xué)計(jì)算的 python 加注解后,pythran 可以把 python 代碼變成接口相同的原生 python 模塊,大幅度提升性能。

并且 pythran 也可以利用 OpenMP 多核和 SIMD 指令集。

支持 python 3 和 Python 2.7 。

pythran 的 manual 挺詳細(xì):

https://pythran.readthedocs.io/en/latest/MANUAL.html

(2). 功能

pythran 并不支持完整的 python, 只支持 python 語言特性的一個(gè)子集:

  • polymorphic functions 多態(tài)函數(shù)(翻譯成 C++ 的泛型模板函數(shù))

  • lambda

  • list comprehension 列表推導(dǎo)式

  • map, reduce 等函數(shù)

  • dictionary, set, list 等數(shù)據(jù)結(jié)構(gòu)

  • exceptions 異常

  • file handling 文件處理

  • 部分 numpy

不支持的功能:

  • classes 類

  • polymorphic variables 可變類型變量

(3). 支持的數(shù)據(jù)類型和函數(shù)

pythran export 可以導(dǎo)出函數(shù)和全局變量。

支持導(dǎo)出的數(shù)據(jù)類型,BNF 定義是:

  1. argument_type = basic_type 
  2.                 | (argument_type+)    # this is a tuple 
  3.                 | argument_type list    # this is a list 
  4.                 | argument_type set    # this is a set 
  5.                 | argument_type []+    # this is a ndarray, C-style 
  6.                 | argument_type [::]+    # this is a strided ndarray 
  7.                 | argument_type [:,...,:]+ # this is a ndarray, Cython style 
  8.                 | argument_type [:,...,3]+ # this is a ndarray, some dimension fixed 
  9.                 | argument_type:argument_type dict    # this is a dictionary 
  10.  
  11.   basic_type = bool | byte | int | float | str | None | slice 
  12.              | uint8 | uint16 | uint32 | uint64 | uintp 
  13.              | int8 | int16 | int32 | int64 | intp 
  14.              | float32 | float64 | float128 
  15.              | complex64 | complex128 | complex256 

可以看到基礎(chǔ)類型相當(dāng)全面,支持各種 整數(shù),浮點(diǎn)數(shù),字符串,復(fù)數(shù)

復(fù)合類型支持 tuple, list, set, dict, numpy.ndarray 等,對(duì)應(yīng) C++ 代碼的類型實(shí)現(xiàn)在 pythran/pythonic/include/types/ 下面,可以看到比如 dict 實(shí)際就是封裝了一下 std::unordered_map

https://pythran.readthedocs.io/en/latest/SUPPORT.html

可以看到支持的 python 基礎(chǔ)庫,其中常用于機(jī)器學(xué)習(xí)的 numpy 支持算比較完善。

五、pythran 的基本原理

和常見的編譯器/解釋器類似, pythran 的架構(gòu)是分成 3 層:

  1. python 代碼解析成抽象語法樹 AST 。用 python 標(biāo)準(zhǔn)庫自帶的的 ast 模塊實(shí)現(xiàn)

  2. 代碼優(yōu)化。

    在 AST 上做優(yōu)化,有多種 transformation pass,比如 deadcode_elimination 死代碼消除,loop_full_unrolling 循環(huán)展開 等。還有 Function/Module/Node 級(jí)別的 Analysis,用來遍歷 AST 供 transformation 利用。

  3. 后端,實(shí)現(xiàn)代碼生成。目前有 2 個(gè)后端,Cxx / Python, Cxx 后端可以把 AST 轉(zhuǎn)成 C++ 代碼( Python 后端用來調(diào)試)。

目前看起來 ,pythran 還欠缺的:

  1. 字符串處理能力欠缺,缺少 str.encode()/str.decode() 對(duì) utf8 的支持

  2. 缺少正則表達(dá)式 regex 支持

看文檔要自己加也不麻煩,看業(yè)務(wù)需要可以加。

 

責(zé)任編輯:張燕妮 來源: 騰訊技術(shù)工程
相關(guān)推薦

2020-04-21 08:30:32

AI人工智能語言

2017-07-11 09:46:00

防火墻翻譯安全

2019-05-24 16:20:11

Python 開發(fā)編程語言

2020-07-20 17:36:31

英語翻譯開源工具開源

2018-12-06 14:41:04

Python GitHub編程語言

2020-11-16 13:38:31

PostMessage

2021-07-28 06:10:47

拖拽設(shè)計(jì)器 transmat

2021-10-29 07:49:22

Spring事務(wù)管理

2021-09-05 07:55:37

前端Emoji 表情

2021-08-12 16:30:45

OpenAI人工智能自然語言翻譯

2012-07-13 11:32:16

網(wǎng)絡(luò)出口

2020-09-14 11:26:54

BinlogCanal數(shù)據(jù)庫

2024-08-02 08:38:20

Controller接口地址

2022-08-12 08:25:33

Python異常信息代碼

2013-12-06 11:14:54

開發(fā)者程序員bug

2016-11-08 18:53:08

編譯器

2021-02-20 09:50:41

谷歌Android開發(fā)者

2024-12-17 12:00:00

C++對(duì)象模型

2012-02-01 08:59:01

Dart

2020-11-04 08:37:37

C語言C++內(nèi)存
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)