# 7. 計算性能
校驗者:
[@曲曉峰](https://github.com/apachecn/scikit-learn-doc-zh)
[@小瑤](https://github.com/apachecn/scikit-learn-doc-zh)
翻譯者:
[@小瑤](https://github.com/apachecn/scikit-learn-doc-zh)
對于某些 applications (應用),estimators(估計器)的性能(主要是 prediction time (預測時間)的 latency (延遲)和 throughput (吞吐量))至關重要。考慮 training throughput (訓練吞吐量)也可能是有意義的,但是在 production setup (生產設置)(通常在脫機中運行)通常是不太重要的。
我們將在這里審查您可以從不同上下文中的一些 scikit-learn estimators(估計器)預期的數量級,并提供一些 overcoming performance bottlenecks (解決性能瓶頸)的技巧和訣竅。
將 Prediction latency (預測延遲)作為進行預測所需的 elapsed time (經過時間)(例如,以 micro-seconds(微秒)為單位)進行測量。Latency (延遲)通常被認為一種分布,運營工程師通常將注意力集中在該分布的給定 percentile (百分位數)(例如 90 百分位數)上的延遲。
Prediction throughput (預測吞吐量)被定義為軟件可以在給定的時間量內(例如每秒的預測)中 the number of predictions (可預測的預測數)。
performance optimization (性能優化)的一個重要方面也是它可能會損害 prediction accuracy (預測精度)。 實際上,更簡單的模型(例如 linear (線性的),而不是 non-linear (非線性的),或者具有較少的參數)通常運行得更快,但并不總是能夠考慮與更復雜的數據相同的確切屬性。
## 7.1. 預測延遲
在使用/選擇機器學習工具包時可能遇到的最直接的問題之一是生產環境中可以進行預測的 latency (延遲)。
影響 prediction latency (預測延遲)的主要因素是1. Number of features(特征的數量)
2. Input data representation and sparsity(輸入數據的表示和稀疏性)
3. Model complexity(模型復雜性)
4. Feature extraction(特征提取)
最后一個主要參數也是在 bulk or one-at-a-time mode (批量或執行一次的時間模式)下進行預測的可能性。
### 7.1.1. 批量與原子模式
通常,通過大量原因(branching predictability(分支可預測性), CPU cache(CPU緩存), linear algebra libraries optimizations(線性代數庫優化)等),predictions in bulk(批量進行預測)(同時許多情況)更有效。 在這里,我們看到一些具有很少功能的設置,獨立于估計器選擇,bulk mode(批量模式)總是更快,而對于其中的一些,它們的數量大約是 1 到 2 個數量級:
**[](../auto_examples/applications/plot_prediction_latency.html)**
**[](../auto_examples/applications/plot_prediction_latency.html)**
為了對您的案例的不同的 estimators 進行基準測試,您可以在此示例中簡單地更改 `n_features` 參數: [Prediction Latency](../auto_examples/applications/plot_prediction_latency.html#sphx-glr-auto-examples-applications-plot-prediction-latency-py). 這應該給你估計 prediction latency (預測延遲)的數量級。
配置 Scikit-learn 來減少驗證開銷
Scikit-learn 對數據進行了一些驗證,從而增加了對 `predict(預測)` 和類似函數的調用開銷。特別地,檢查這些 features (特征)是有限的(不是 NaN 或無限)涉及對數據的完全傳遞。如果您確定你的數據是 acceptable (可接受的),您可以通過在導入 scikit-learn 之前將環境變量配置 `SKLEARN_ASSUME_FINITE` 設置為 non-empty string (非空字符串)來抑制檢查有限性,或者使用以下方式在 Python 中配置 [`sklearn.set_config`](generated/sklearn.set_config.html#sklearn.set_config "sklearn.set_config") 。為了比這些全局設置更多的控制 `config_context` 允許您在指定的上下文中設置此配置:
```
>>> import sklearn
>>> with sklearn.config_context(assume_finite=True):
... pass # do learning/prediction here with reduced validation
```
注意,這將影響上下文中的 [`sklearn.utils.assert_all_finite`](generated/sklearn.utils.assert_all_finite.html#sklearn.utils.assert_all_finite "sklearn.utils.assert_all_finite") 的所有用途。
### 7.1.2. 特征數量的影響
顯然,當特征數量增加時,每個示例的內存消耗量也會增加。實際上,對于具有  個特征的  個實例的矩陣,空間復雜度在  。
從 computing (計算)角度來看,這也意味著 the number of basic operations (基本操作的數量)(例如,線性模型中向量矩陣乘積的乘法)也增加。以下是 prediction latency (預測延遲)與 number of features(特征數) 的變化圖:
**[](../auto_examples/applications/plot_prediction_latency.html)**
總的來說,您可以預期 prediction time (預測時間)至少隨 number of features (特征數量)線性增加(非線性情況可能會發生,取決于 global memory footprint (全局內存占用)和 estimator (估計))。
### 7.1.3. 輸入數據表示的影響
Scipy 提供對 storing sparse data(存儲稀疏數據)進行優化的 sparse matrix (稀疏矩陣)數據結構。sparse formats(稀疏格式)的主要特點是您不會存儲零,所以如果您的數據稀疏,那么您使用的內存會更少。sparse(稀疏) ([CSR or CSC](http://docs.scipy.org/doc/scipy/reference/sparse.html)) 表示中的非零值將僅占用一個 32 位整數位置 + 64 位 floating point (浮點值) + 矩陣中每行或列的額外的 32 位。在 dense(密集) (or sparse(稀疏)) 線性模型上使用稀疏輸入可以加速預測,只有非零值特征才會影響點積,從而影響模型預測。因此,如果在 1e6 維空間中有 100 個非零,則只需要 100 次乘法和加法運算而不是 1e6 。
然而,密度表示的計算可以利用 BLAS 中高度優化的向量操作和多線程,并且往往導致更少的 CPU 高速緩存 misses 。因此,sparse input (稀疏輸入)表示的 sparsity (稀疏度)通常應相當高(10% 非零最大值,要根據硬件進行檢查)比在具有多個 CPU 和優化 BLAS 實現的機器上的 dense input (密集輸入)表示更快。
以下是測試輸入 sparsity (稀疏度)的示例代碼:
```
def sparsity_ratio(X):
return 1.0 - np.count_nonzero(X) / float(X.shape[0] * X.shape[1])
print("input sparsity ratio:", sparsity_ratio(X))
```
根據經驗,您可以考慮如果 sparsity ratio (稀疏比)大于 90% , 您可能會從 sparse formats (稀疏格式)中受益。有關如何構建(或將數據轉換為) sparse matrix formats (稀疏矩陣格式)的更多信息,請參閱 Scipy 的稀疏矩陣格式文檔 [documentation](http://docs.scipy.org/doc/scipy/reference/sparse.html) 。大多數的時候, `CSR` 和 `CSC` 格式是最有效的。
### 7.1.4. 模型復雜度的影響
一般來說,當 model complexity (模型復雜度)增加時,predictive power (預測能力)和 latency (延遲)應該會增加。增加 predictive power (預測能力)通常很有意思,但對于許多應用,我們最好不要太多地增加預測延遲。我們現在將對不同 families 的 supervised models (監督模式)進行審查。
對于 [`sklearn.linear_model`](classes.html#module-sklearn.linear_model "sklearn.linear_model") (例如 Lasso, ElasticNet, SGDClassifier/Regressor, Ridge & RidgeClassifier, PassiveAgressiveClassifier/Regressor, LinearSVC, LogisticRegression…) 在預測時間應用的 decision function (決策函數)是一樣的(dot product( 點積)),所以 latency (延遲)應該是等效的。
這里有一個例子使用 `sklearn.linear_model.stochastic_gradient.SGDClassifier` 和 `elasticnet` penalty(懲罰)。 regularization strength(正則化強度)由 `alpha` 參數全局控制。有一個足夠高的 `alpha` ,可以增加 `elasticnet` 的 `l1_ratio` 參數,以在模型參數中執行各種稀疏程度。這里的 Higher sparsity (較高稀疏度)被解釋為 less model complexity (較少的模型復雜度),因為我們需要較少的系數充分描述它。當然, sparsity (稀疏性)會隨著稀疏點積 產生時間大致與非零系數的數目成比例地影響 prediction time (預測時間)。
**[](../auto_examples/applications/plot_model_complexity_influence.html)**
對于具有 non-linear kernel (非線性內核)的 [`sklearn.svm`](classes.html#module-sklearn.svm "sklearn.svm") 算法系列,latency (延遲)與 support vectors (支持向量)的數量有關(越少越快)。 隨著 SVC 或 SVR 模型中的支持向量的數量, Latency (延遲)和 throughput (吞吐量)應該漸漸地增長。kernel (內核)也將影響 latency (延遲),因為它用于計算每個 support vector (支持向量)一次 input vector(輸入向量)的 projection (投影)。在下面的圖中, `sklearn.svm.classes.NuSVR` 的 `nu` 參數用于影響 number of support vectors(支持向量的數量)。
**[](../auto_examples/applications/plot_model_complexity_influence.html)**
對于 [`sklearn.ensemble`](classes.html#module-sklearn.ensemble "sklearn.ensemble") 的 trees (例如 RandomForest, GBT, ExtraTrees 等) number of trees (樹的數量)及其 depth(深度)發揮著最重要的作用。Latency and throughput(延遲和吞吐量)應與樹的數量呈線性關系。在這種情況下,我們直接使用 `sklearn.ensemble.gradient_boosting.GradientBoostingRegressor` 的 `n_estimators` 參數。
**[](../auto_examples/applications/plot_model_complexity_influence.html)**
在任何情況下都應該警告,降低的 model complexity (模型復雜性)可能會損害如上所述的準確性。例如,可以用快速線性模型來處理 non-linearly separable problem (非線性可分離問題),但是在該過程中預測能力將很可能受到影響。
### 7.1.5. 特征提取延遲
大多數 scikit-learn 模型通常非常快,因為它們可以通過編譯的 Cython 擴展或優化的計算庫來實現。 另一方面,在許多現實世界的應用中,feature extraction process(特征提取過程)(即,將 database rows or network packets (數據庫行或網絡分組)的原始數據轉換為 numpy arrays )來控制總體預測時間。例如在 Reuters text classification task(路透社文本分類任務)中,根據所選擇的模型,整個準備(讀取和解析 SGML 文件,將文本進行標記并將其散列為公共向量空間)的時間比實際預測代碼的時間長 100 到 500 倍。
>
**[](../auto_examples/applications/plot_out_of_core_classification.html)**
因此,在很多情況下,建議您仔細地對 carefully time and profile your feature extraction code ( 特征提取代碼進行時間預估和簡檔),因為當您的 overall latency (整體延遲)對您的應用程序來說太慢時,可能是開始優化的好地方。
## 7.2. 預測吞吐量
考慮到生產系統大小的另一個重要指標是 throughput (吞吐量),即在一定時間內可以做出的預測數量。以下是 [Prediction Latency](../auto_examples/applications/plot_prediction_latency.html#sphx-glr-auto-examples-applications-plot-prediction-latency-py) 示例的基準測試,該示例針對合成數據的多個 estimators (估計器)測量此數量:
**[](../auto_examples/applications/plot_prediction_latency.html)**
這些 throughputs(吞吐量)早單個進程上實現。提高應用程序吞吐量的一個明顯的方法是產生其他實例(通常是 Python 中的進程,因為 [GIL](https://wiki.python.org/moin/GlobalInterpreterLock) )共享相同模型。還可能添加機器來分布式負載。關于如何實現這一點的詳細解釋超出了本文檔的范圍。
## 7.3. 技巧和竅門
### 7.3.1. 線性代數庫
由于 scikit-learn 在很大程度上依賴于 Numpy/Scipy 和 線性代數,所以需要理解這些庫的版本。 基本上,你應該確保使用優化的 [BLAS](https://en.wikipedia.org/wiki/Basic_Linear_Algebra_Subprograms) / [LAPACK](https://en.wikipedia.org/wiki/LAPACK) 構建 Numpy 庫。
并非所有的模型都受益于優化的 BLAS 和 Lapack 實現。例如,基于(隨機化)決策樹的模型通常不依賴于內部循環中的 BLAS 調用,kernel SVMs (`SVC`, `SVR`, `NuSVC`, `NuSVR`) 。另一方面,使用 BLAS DGEMM 調用(通過 `numpy.dot`)實現的線性模型通常將受益于調整的 BLAS 實現,并且導致非優化 BLAS 的數量級加速。
你可以使用以下命令顯示您的 NumPy / SciPy / scikit-learn 安裝使用的 BLAS / LAPACK 實現:
```
from numpy.distutils.system_info import get_info
print(get_info('blas_opt'))
print(get_info('lapack_opt'))
```
Optimized(優化的) BLAS / LAPACK 實現包括:- Atlas (需要通過在目標機器上 rebuilding 進行硬件特定調整)
- OpenBLAS
- MKL
- Apple Accelerate 和 vecLib frameworks (僅適用于 OSX)
有關更多信息,請參見 [Scipy install page](http://docs.scipy.org/doc/numpy/user/install.html) 并在來自 Daniel Nouri 的博客 [blog post](http://danielnouri.org/notes/2012/12/19/libblas-and-liblapack-issues-and-speed,-with-scipy-and-ubuntu/) 它為 Debain / Ubuntu 提供了一些很好的一步一步的安裝說明。
Warning
Multithreaded BLAS libraries(多線程 BLAS 庫)有時與 Python 的 `multiprocessing` 模塊相沖突,這個模塊由例如 `GridSearchCV` 和大多數其他估計器,它們使用 `n_jobs` 參數(除了 `SGDClassifier`, `SGDRegressor`, `Perceptron`, `PassiveAggressiveClassifier` 和 基于樹的方法如 random forests(隨機森林))。在 OpenMP 支持的情況下, Apple 的 Accelerate 和 OpenBLAS 也是如此。
除了 scikit-learn, Numpy 和 Scipy 也在內部使用 BLAS, 如上所述。
如果您遇到帶有 `n_jobs>1` 或 `n_jobs=-1` 的 hanging subprocesses (掛起子進程),請確保你有一個單線程 BLAS 庫,或者設置 `n_jobs=1` 或者升級到 Python 3.4 有一個新版本的 `multiprocessing` ,應該免于這個問題。
### 7.3.2. 模型壓縮
scikit-learn 中的 Model compression (模型壓縮)只關注 linear models (線性模型)。 在這種情況下,這意味著我們要控制模型 sparsity (稀疏度)(即 模型向量中的非零坐標數)。將 model sparsity (模型稀疏度)與 sparse input data representation (稀疏輸入數據表示)相結合是一個好主意。
以下是示例代碼,說明了如何使用 `sparsify()` 方法:
```
clf = SGDRegressor(penalty='elasticnet', l1_ratio=0.25)
clf.fit(X_train, y_train).sparsify()
clf.predict(X_test)
```
在這個例子中,我們更喜歡 `elasticnet` penalty(懲罰),因為它通常是 model compactness(模型緊湊性)和 prediction power (預測能力)之間的一個很好的妥協。還可以進一步調整 `l1_ratio` 參數(結合正則化強度 `alpha` )來控制這個權衡。
對于 synthetic data (合成數據),典型的 [benchmark](https://github.com/scikit-learn/scikit-learn/blob/master/benchmarks/bench_sparsify.py) 在模型和輸入時都會降低 30% 的延遲。稀疏(分別為 0.000024 和 0.027400 非零系數比)。您的里程可能會因您的數據和模型的稀疏性和大小而有所不同。 因此,為了減少部署在生產服務器上的預測模型的內存使用,擴展可能非常有用。
### 7.3.3. 模型重塑
Model reshaping(模型重塑)在于僅選擇一部分可用功能以適應模型。換句話說,如果模型在學習階段 discards features (丟棄特征),我們可以從輸入中刪除這些特征。這有幾個好處。首先,它減少了模型本身的內存(因此是減少了時間)的開銷。一旦知道要從上一次運行中保留哪些功能,它也允許在 pipeline 中 discard explicit feature selection components (丟棄顯式的特征選擇組件)。最后,它可以通過不收集和構建模型丟棄的特征來幫助減少數據訪問和 feature extraction layers (特征提取層)upstream (上游)的處理時間和 I/O 的使用。例如,如果原始數據來自數據庫,則可以通過使查詢返回較輕的記錄,從而可以編寫更簡單和更快速的查詢或減少 I/O 的使用。 目前,reshaping(重塑)需要在 scikit-learn 中手動執行。 在 sparse input(稀疏輸入)(特別是 `CSR` 格式)的情況下,通常不能生成相關的特征,使其列為空。
### 7.3.4. 鏈接
> - [scikit-learn developer performance documentation](../developers/performance.html)
> - [Scipy sparse matrix formats documentation](http://docs.scipy.org/doc/scipy/reference/sparse.html)
- scikit-learn 0.19 中文文檔
- 用戶指南
- 1. 監督學習
- 1.1. 廣義線性模型
- 1.2. 線性和二次判別分析
- 1.3. 內核嶺回歸
- 1.4. 支持向量機
- 1.5. 隨機梯度下降
- 1.6. 最近鄰
- 1.7. 高斯過程
- 1.8. 交叉分解
- 1.9. 樸素貝葉斯
- 1.10. 決策樹
- 1.11. 集成方法
- 1.12. 多類和多標簽算法
- 1.13. 特征選擇
- 1.14. 半監督學習
- 1.15. 等式回歸
- 1.16. 概率校準
- 1.17. 神經網絡模型(有監督)
- 2. 無監督學習
- 2.1. 高斯混合模型
- 2.2. 流形學習
- 2.3. 聚類
- 2.4. 雙聚類
- 2.5. 分解成分中的信號(矩陣分解問題)
- 2.6. 協方差估計
- 2.7. 經驗協方差
- 2.8. 收斂協方差
- 2.9. 稀疏逆協方差
- 2.10. Robust 協方差估計
- 2.11. 新奇和異常值檢測
- 2.12. 密度估計
- 2.13. 神經網絡模型(無監督)
- 3. 模型選擇和評估
- 3.1. 交叉驗證:評估估算器的表現
- 3.2. 調整估計器的超參數
- 3.3. 模型評估: 量化預測的質量
- 3.4. 模型持久化
- 3.5. 驗證曲線: 繪制分數以評估模型
- 4. 數據集轉換
- 4.1. Pipeline(管道)和 FeatureUnion(特征聯合): 合并的評估器
- 4.2. 特征提取
- 4.3. 預處理數據
- 4.4. 無監督降維
- 4.5. 隨機投影
- 4.6. 內核近似
- 4.7. 成對的矩陣, 類別和核函數
- 4.8. 預測目標 (y) 的轉換
- 5. 數據集加載工具
- 6. 大規模計算的策略: 更大量的數據
- 7. 計算性能
- 教程
- 使用 scikit-learn 介紹機器學習
- 關于科學數據處理的統計學習教程
- 機器學習: scikit-learn 中的設置以及預估對象
- 監督學習:從高維觀察預測輸出變量
- 模型選擇:選擇估計量及其參數
- 無監督學習: 尋求數據表示
- 把它們放在一起
- 尋求幫助
- 處理文本數據
- 選擇正確的評估器(estimator)
- 外部資源,視頻和談話