mlpack: 一個C++機器學習庫

簡介

mlpack是一個C++機器學習庫,側重於可擴展性、速度和易用性。它的目的是經過一個簡單的、先後一致的API讓新用戶使用機器學習成爲可能,同時利用C++語言特徵爲專家用戶提供最好的性能和最大的靈活性。這些經過提供一系列命令行執行程序完成,就像使用一個黑箱,並且專家用戶和研究者能夠容易的更改一個模塊化的C++ API的內部算法。html

mlpack

這種方法的結果就是mlpack的性能大幅度超過其餘競爭的機器學習庫;在the BigLearning workshop paper 和the benchmarks for details查看細節。node

mlpack由全世界的貢獻者開發。基於伯克利發行軟件許可的第三個條款免費發行。(比1.0.12更老的版本基於GNU通用公共受權規定發行:LGPL,第3版。)算法

安裝

mlpack存儲在許多Linux的發行版本中,因此在你的系統中使用程序包管理器可能更容易一些。例如:在Ubuntu上,你可使用下面的命令安裝mlpack。windows

C++dom

 

1機器學習

$ sudo apt-get install libmlpack-devide

若是mlpack不能在你的系統的程序包管理器中使用,那麼你能夠按照下面的步驟編譯和安裝mlpack源文件。模塊化

Mlpack使用CMake做爲生成系統,容許幾個靈活的生成配置選項。你能夠查詢大量的CMake教程獲得更多的文件,可是這個教程應該足夠讓你在大多數Linux和類UNIX系統中(包括OS X)成功生成和安裝mlpack。若是你想在Windows操做系統中生成mlpack,請看這裏svn

首先下載mlpack。函數

當mlpack的源文件完成解壓,你能夠建立一個生成目錄。

C++

 

1

2

$ cd mlpack-2.2.5

$ mkdir build

這個目錄能夠是任何名字,不只僅是「build」,可是「build」足夠了。

mlpack依賴項

mlpack依賴下面的庫,它們須要被安裝在系統中並有一些頭文件出現。

  • Armadillo >=4.200.0(支持LAPACK(線性代數程序包))
  • Boost(math_c99, program_options, serialization, unit_test_framework, heap, spirit)>=1.49

在Ununtu和Debian中,你能夠經過apt得到全部這些依賴項:

C++

 

1

2

# apt-get install libboost-math-dev libboost-program-options-dev

  libboost-test-dev libboost-serialization-dev libarmadillo-dev binutils-dev

在Fedora、Red Hat或CentOS上,這些相同的依賴項能夠經過dnf得到:

C++

 

1

2

# dnf install boost-devel boost-test boost-program-options boost-math

  armadillo-devel binutils-devel

 

配置CMake

運行CMake至關於使用autotools運行./configure。

若是你工做中使用mlpack的svn trunk版本,且不帶任何選項運行CMake,它將配置這個生成項目帶有調試符號和分析信息:若是你工做中使用發行版本的mlpack,不帶任何選項運行CMake,它將配置這個生成項目不帶調試符號和分析信息(爲了速度)。

C++

 

1

2

$ cd build

$ cmake ../

你能夠手動指定選項去編譯或不編譯調試信息和分析信息(也就是說盡量快):

C++

 

1

2

$ cd build

$ cmake -D DEBUG=OFF -D PROFILE=OFF ../

Mlpack容許的所有選項爲:

  • DEBUG=(ON/OFF): compile with debugging symbols (default ON in svn trunk, OFF in releases)
  • PROFILE=(ON/OFF): compile with profiling symbols (default ON in svn trunk, OFF in releases)
  • ARMA_EXTRA_DEBUG=(ON/OFF): compile with extra Armadillo debugging symbols (default OFF)
  • BUILD_TESTS=(ON/OFF): compile the mlpack_test program (default ON)
  • BUILD_CLI_EXECUTABLES=(ON/OFF): compile the mlpack command-line executables (i.e. mlpack_knn, mlpack_kfn, mlpack_logistic_regression, etc.) (default ON)
  • TEST_VERBOSE=(ON/OFF): run test cases in mlpack_test with verbose output (default OFF)

每一個選項均可以被指定給帶有‘-D’標記的CMake。其餘工具也能夠用於配置CMake,可是它們沒有被記錄在這裏。

生成mlpack

一旦CMake配置好,生成庫就像打出‘make’同樣簡單。這將生成全部庫組件和‘mlpack_test’。

C++

 

1

2

3

4

5

$ make

Scanning dependencies of target mlpack

[  1%] Building CXX object

src/mlpack/CMakeFiles/mlpack.dir/core/optimizers/aug_lagrangian/aug_lagrangian_test_functions.cpp.o

<...>

若是你不想生成每個庫,能夠指定你想生成的單個組件。

C++

 

1

$ make mlpack_pca mlpack_knn mlpack_kfn

一個有趣的特殊組件是mlpack_test,它是運行mlpack的測試組件。你可使用這個命令生成這個組件:

C++

 

1

$ make mlpack_test

而後運行全部的測試組件或單個的測試組件:

C++

 

1

2

$ bin/mlpack_test

$ bin/mlpack_test -t KNNTest

若是生成失敗,而你不能找到爲何失敗,在Github上註冊一個帳戶,提交這個問題,mlpack的開發人員將會盡快幫你解決,

或者在irc.freenode.netm上的mlpack的IRC中也能夠找到mlpack的幫助。

安裝mlpack

若是你想將mlpack安裝在/usr/include/mlpack/、/usr/lib/和/usr/bin/中,當它生成後,確保你有root權限(或向那兩個目錄的寫入許可),而後簡單的打出:

C++

 

1

# make install

如今你能夠經過名字運行可執行程序;你可使用-lmlpack連接到mlpack,mlpack的頭文件能夠在目錄/usr/include/mlpack/中找到。

示例

最近鄰搜索是一個常見的機器學習任務。在這個背景下 ,咱們有一個查詢數據集和一個參考數據集。對於在查詢數據集中的每一個點,咱們但願知道參考數據集中距離給定查詢點最近的k個點。

或者,若是查詢和參考數據集是相同的,問題能夠更簡單的說明:對於每一個數據集中的點,咱們但願知道距離那個點最近的k個點。

Mlpack提供:

  • 一個簡單的命令行程序包運行最近鄰搜索(和最遠鄰搜索)。
  • 一個簡單的C++接口用於完成最近鄰搜索(和最遠鄰搜索)。
  • 一個通用的、可擴展的和強大的C++類(鄰域搜索)用於複雜算法。

命令行‘mlpack_knn’

在mlpack中完成最近鄰搜索最簡單的方式是使用mlpack_knn程序包。這個程序將完成最近鄰搜索,並將獲得的鄰近點放入一個文件,同時將對應的距離放入另外一個文件。輸出文件被整理爲第一行對應第一個被查詢點的最近鄰點,第一列對應最近的點,以此類推。

下面是幾個簡單用法的例子(和輸出結果)。因爲使用了選項‘-v’,所以輸出是給定的。更多關於每一個選項的文檔能夠經過下面這個語句找到。

C++

 

1

$ mlpack_knn –help

 

一個數據集,5個最近鄰點

 

C++

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

$ mlpack_knn -r dataset.csv -n neighbors_out.csv -d distances_out.csv -k 5 -v

[INFO ] Loading 'dataset.csv' as CSV data.  Size is 3 x 1000.

[INFO ] Loaded reference data from 'dataset.csv' (3 x 1000).

[INFO ] Building reference tree...

[INFO ] Tree built.

[INFO ] Searching for 5 nearest neighbors with dual-tree kd-tree search...

[INFO ] 18412 node combinations were scored.

[INFO ] 54543 base cases were calculated.

[INFO ] Search complete.

[INFO ] Saving CSV data to 'neighbors_out.csv'.

[INFO ] Saving CSV data to 'distances_out.csv'.

[INFO ]

[INFO ] Execution parameters:

[INFO ]   distances_file: distances_out.csv

[INFO ]   help: false

[INFO ]   info: ""

[INFO ]   input_model_file: ""

[INFO ]   k: 5

[INFO ]   leaf_size: 20

[INFO ]   naive: false

[INFO ]   neighbors_file: neighbors_out.csv

[INFO ]   output_model_file: ""

[INFO ]   query_file: ""

[INFO ]   random_basis: false

[INFO ]   reference_file: dataset.csv

[INFO ]   seed: 0

[INFO ]   single_mode: false

[INFO ]   tree_type: kd

[INFO ]   verbose: true

[INFO ]   version: false

[INFO ]

[INFO ] Program timers:

[INFO ]   computing_neighbors: 0.108968s

[INFO ]   loading_data: 0.006495s

[INFO ]   saving_data: 0.003843s

[INFO ]   total_time: 0.126036s

[INFO ]   tree_building: 0.003442s

在輸出底部爲每一個不一樣的計算部分加入方便的程序計時器,同時也加入和仿真一塊兒運行的參數。如今,若是咱們看看結果文件:

C++

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

$ head neighbors_out.csv

862,344,224,43,885

703,499,805,639,450

867,472,972,380,601

397,319,277,443,323

840,827,865,38,438

732,876,751,492,616

563,222,569,985,940

361,97,928,437,79

547,695,419,961,716

982,113,689,843,634

 

$ head distances_out.csv

5.986076164057e-02,7.664920518084e-02,1.116050961847e-01,1.155595474371e-01,1.169810085522e-01

7.532635022982e-02,1.012564715841e-01,1.127846944644e-01,1.209584396720e-01,1.216543647014e-01

7.659571546879e-02,1.014588981948e-01,1.025114621511e-01,1.128082429187e-01,1.131659758673e-01

2.079405647909e-02,4.710724516732e-02,7.597622408419e-02,9.171977778898e-02,1.037033340864e-01

7.082206779700e-02,9.002355499742e-02,1.044181406406e-01,1.093149568834e-01,1.139700558608e-01

5.688056488896e-02,9.478072514474e-02,1.085637706630e-01,1.114177921451e-01,1.139370265105e-01

7.882260880455e-02,9.454474078041e-02,9.724494179950e-02,1.023829575445e-01,1.066927013814e-01

7.005321598247e-02,9.131417221561e-02,9.498248889074e-02,9.897964162308e-02,1.121202216165e-01

5.295654132754e-02,5.509877761894e-02,8.108227366619e-02,9.785461174861e-02,1.043968140367e-01

3.992859920333e-02,4.471418646159e-02,7.346053904990e-02,9.181982339584e-02,9.843075910782e-02

因此對於第0點的最近鄰點是第862點,距離是5.986076164057e-02。第二近鄰點是第344點,距離是7.664920518084e-02。第5點的第三近鄰點是第751點,距離是1.085637706630e-01。

查詢和參考數據集,10個最近鄰點

 

C++

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

$ mlpack_knn -q query_dataset.csv -r reference_dataset.csv \

> -n neighbors_out.csv -d distances_out.csv -k 10 -v

[INFO ] Loading 'reference_dataset.csv' as CSV data.  Size is 3 x 1000.

[INFO ] Loaded reference data from 'reference_dataset.csv' (3 x 1000).

[INFO ] Building reference tree...

[INFO ] Tree built.

[INFO ] Loading 'query_dataset.csv' as CSV data.  Size is 3 x 50.

[INFO ] Loaded query data from 'query_dataset.csv' (3x50).

[INFO ] Searching for 10 nearest neighbors with dual-tree kd-tree search...

[INFO ] Building query tree...

[INFO ] Tree built.

[INFO ] Search complete.

[INFO ] Saving CSV data to 'neighbors_out.csv'.

[INFO ] Saving CSV data to 'distances_out.csv'.

[INFO ]

[INFO ] Execution parameters:

[INFO ]   distances_file: distances_out.csv

[INFO ]   help: false

[INFO ]   info: ""

[INFO ]   input_model_file: ""

[INFO ]   k: 10

[INFO ]   leaf_size: 20

[INFO ]   naive: false

[INFO ]   neighbors_file: neighbors_out.csv

[INFO ]   output_model_file: ""

[INFO ]   query_file: query_dataset.csv

[INFO ]   random_basis: false

[INFO ]   reference_file: reference_dataset.csv

[INFO ]   seed: 0

[INFO ]   single_mode: false

[INFO ]   tree_type: kd

[INFO ]   verbose: true

[INFO ]   version: false

[INFO ]

[INFO ] Program timers:

[INFO ]   computing_neighbors: 0.022589s

[INFO ]   loading_data: 0.003572s

[INFO ]   saving_data: 0.000755s

[INFO ]   total_time: 0.032197s

[INFO ]   tree_building: 0.002590s

 

一個數據集,3個最近鄰點,15個點的大小

 

C++

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

$ mlpack_knn -r dataset.csv -n neighbors_out.csv -d distances_out.csv -k 3 -l 15 -v

[INFO ] Loading 'dataset.csv' as CSV data.  Size is 3 x 1000.

[INFO ] Loaded reference data from 'dataset.csv' (3 x 1000).

[INFO ] Building reference tree...

[INFO ] Tree built.

[INFO ] Searching for 3 nearest neighbors with dual-tree kd-tree search...

[INFO ] 19692 node combinations were scored.

[INFO ] 36263 base cases were calculated.

[INFO ] Search complete.

[INFO ] Saving CSV data to 'neighbors_out.csv'.

[INFO ] Saving CSV data to 'distances_out.csv'.

[INFO ]

[INFO ] Execution parameters:

[INFO ]   distances_file: distances_out.csv

[INFO ]   help: false

[INFO ]   info: ""

[INFO ]   input_model_file: ""

[INFO ]   k: 3

[INFO ]   leaf_size: 15

[INFO ]   naive: false

[INFO ]   neighbors_file: neighbors_out.csv

[INFO ]   output_model_file: ""

[INFO ]   query_file: ""

[INFO ]   random_basis: false

[INFO ]   reference_file: dataset.csv

[INFO ]   seed: 0

[INFO ]   single_mode: false

[INFO ]   tree_type: kd

[INFO ]   verbose: true

[INFO ]   version: false

[INFO ]

[INFO ] Program timers:

[INFO ]   computing_neighbors: 0.059020s

[INFO ]   loading_data: 0.002791s

[INFO ]   saving_data: 0.002369s

[INFO ]   total_time: 0.069277s

[INFO ]   tree_building: 0.002713s

更多關於選項的文檔可使用‘-help’選項找到。

‘KNN’類

具體來講,‘KNN’類是一個更擴展的鄰域搜索類的類型定義,使用歐氏距離查詢最近鄰點。

C++

 

1

2

typedef NeighborSearch<NearestNeighborSort, metric::EuclideanDistance>

    KNN;

使用KNN類至關簡單。首先,目標對象必須被構建並指定一個數據集。而後,運行方法,返回兩個矩陣:一個是最近鄰點的序號,一個是最近鄰點的距離。以相同的結構輸出–neighbors_file和–distances_file到命令行接口。下面給出幾個KNN使用的幾個例子。

單一數據集上的5個最近鄰點

 

C++

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

#include <mlpack/methods/neighbor_search/neighbor_search.hpp>

 

using namespace mlpack::neighbor;

 

// Our dataset matrix, which is column-major.

extern arma::mat data;

 

KNN a(data);

 

// The matrices we will store output in.

arma::Mat<size_t> resultingNeighbors;

arma::mat resultingDistances;

 

a.Search(5, resultingNeighbors, resultingDistances);

搜索的輸出存儲在resultingNeighbors和resultingDistances裏面。

查詢和參考數據集上的10個最近鄰點

 

C++

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

#include <mlpack/methods/neighbor_search/neighbor_search.hpp>

 

using namespace mlpack::neighbor;

 

// Our dataset matrices, which are column-major.

extern arma::mat queryData, referenceData;

 

KNN a(referenceData);

 

// The matrices we will store output in.

arma::Mat<size_t> resultingNeighbors;

arma::mat resultingDistances;

 

a.Search(queryData, 10, resultingNeighbors, resultingDistances);

 

在數據集上天然(窮舉)搜索6個最近鄰點

這個例子使用時間度O(n^2)的天然搜索(不是樹搜索)。、

C++

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

#include <mlpack/methods/neighbor_search/neighbor_search.hpp>

 

using namespace mlpack::neighbor;

 

// Our dataset matrix, which is column-major.

extern arma::mat dataset;

 

KNN a(dataset, true);

 

// The matrices we will store output in.

arma::Mat<size_t> resultingNeighbors;

arma::mat resultingDistances;

 

a.Search(6, resultingNeighbors, resultingDistances);

不用說,天然搜索很慢。

擴展的‘NeighborSearch’類

NeighborSearch類是可擴展的,帶有下列模板參數:

C++

 

1

2

3

4

5

6

7

8

9

10

11

12

template<

  typename SortPolicy = NearestNeighborSort,

  typename MetricType = mlpack::metric::EuclideanDistance,

  typename MatType = arma::mat,

  template<typename TreeMetricType,

           typename TreeStatType,

           typename TreeMatType> class TreeType = tree::KDTree,

  template<typename RuleType> class TraversalType =

      TreeType<MetricType, NeighborSearchStat<SortPolicy>,

               MatType>::template DualTreeTraverser>

>

class NeighborSearch;

經過爲每一個模板類選擇不一樣的內容,能夠建立任意的鄰域搜索對象。注意,這些模板的每一個參數都有默認值,因此不須要爲每一個參數賦值。

SortPolicy策略類

SortPolicy模板參數容許指定NeighborSearch對象將怎樣肯定被搜索的每一個點。mlpack::neighbor::NearestNeighborSort類是一個被清楚記錄的示例。一個定製的SortPolicy類必須完成和NearestNeighborSort類相同的方法。

C++

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

static size_t SortDistance(const arma::vec& list, double newDistance);

 

static bool IsBetter(const double value, const double ref);

 

template<typename TreeType>

static double BestNodeToNodeDistance(const TreeType* queryNode,

                                     const TreeType* referenceNode);

 

template<typename TreeType>

static double BestPointToNodeDistance(const arma::vec& queryPoint,

                                      const TreeType* referenceNode);

 

static const double WorstDistance();

 

static const double BestDistance();

mlpack::neighbor::FurthestNeighborSort類是用於建立‘KFN’類型定義類的另外一個方法,和尋找最近鄰點相反,它尋找最遠鄰點。

MetricType策略類

MetricType策略類容許鄰域搜索發生在任意度量空間。mlpack::metric::LMetric是一個很好的示例實現。一個MetricType類必須提供下列功能:

C++

 

1

2

3

4

5

6

// Empty constructor is required.

MetricType();

 

// Compute the distance between two points.

template<typename VecType>

double Evaluate(const VecType& a, const VecType& b);

在內部,NeighborSearch類保存一個MetricType類的實例(它能夠在構造函數中給定)。這對於像馬氏距離這樣必須存儲狀態(協方差矩陣)的度量是有用的(mlpack::metric::MahalanobisDistance)。所以,你能夠寫一個非靜態MetricType類,無縫的使用它和NeighborSearch。

MatType策略類

MatType模板參數指定數據類型使用矩陣。這個類型必須實現和Armadillo矩陣相同的操做,標準選擇是arma::mat和arma::sp_mat。

TreeType策略類

鄰域搜索NeighborSearch類在用於搜索的樹類型的選擇上有很好的擴展。這個類型必須遵循典型的mlpack TreeType策略。

典型的選擇可能包含mlpack::tree::KDTree,mlpack::tree::BallTree,mlpack::tree::StandardCoverTree,mlpack::tree::RTree或mlpack::tree::RStarTree。製做你本身的樹類型用來使用NeighborSearch是很容易的。更多細節請點擊這裏。

下面給出一個使用帶有球樹的NeighborSearch類的例子。

C++

 

1

2

3

4

5

6

7

// Construct a NeighborSearch object with ball bounds.

NeighborSearch<

    NearestNeighborSort,

    metric::EuclideanDistance,

    arma::mat,

    tree::BallTree

> neighborSearch(dataset);

 

TraverserType策略類

鄰域搜索NeighborSearch類提供的最後一個模板參數是TraverserType類。它具備的策略是在單一樹或者雙樹搜索模式下遍歷樹。默認狀況下,它被設置爲使用指定TreeType(成員TreeType::DualTreeTraverser)的默認遍歷器。

這個類必須實現下面兩種方法:

C++

 

1

2

3

4

5

// Instantiate with a given RuleType.

TraverserType(RuleType& rule);

 

// Traverse with two trees.

void Traverse(TreeType& queryNode, TreeType& referenceNode);

RuleType類用在遍歷器中時提供下面的功能:

C++

 

1

2

3

4

5

6

// Evaluate the base case between two points.

double BaseCase(const size_t queryIndex, const size_t referenceIndex);

 

// Score the two nodes to see if they can be pruned, returning DBL_MAX if they

// can be pruned.

double Score(TreeType& queryNode, TreeType& referenceNode);

注意任何指定的遍歷器必須知足修剪雙樹遍歷的定義,其在文章」Tree-independent dual-tree algorithms」中指定。

資源連接

命令行程序參考:http://mlpack.org/docs/mlpack-2.2.5/man.html

相關文章
相關標籤/搜索