boost-python ではじめる大規模機械学習 (1)

はじめに

Python は、機械学習の分野で広く使用されるスクリプト言語です。SciPy や matplotlib といった、科学計算に特化したライブラリが多数提供されているのが特徴です。
いっぽう、弱点もあります。for ループの速度が遅いこと、並列処理が苦手なことなどです。これらの目的には、C 言語が適しています。
そこで、本記事では、Python と C の相互連携を可能にする boost-python ライブラリを使用して、大規模科学計算を効率的に解く方法を紹介します。題材には混合ガウス分布を使用します。
動作テストは、Fedora 環境で行なっています。Ubuntu でも動くと思います。

準備

はじめに、SciPy、matplotlib、boost ライブラリをインストールしてください。
boost-devel とか色々インストールした記憶がありますが、忘れました…

Hello, world!

最初はやっぱり Hello world

hello.cpp
#include <iostream>
#include <boost/python.hpp>
using namespace boost::python;

void hello()
{
    std::cout << "Hello, world!" << std::endl;
}

// 以下で定義した名前が、Python 側に公開されます。
BOOST_PYTHON_MODULE(hello)
{
    def("hello", hello);
}
setup.py

C++ で書いた拡張モジュールをコンパイルするためのコードです。
boost と OpenMP を読み込むよう設定しています。
GNU Scientific Library (GSL) なども読み込めます。

import sys
from distutils.core import setup, Extension

modules = []
modules.append(['hello', 'hello.cpp'])

extensions = []
for module in modules:
    mod_name = module[0]
    mod_source = module[1]
    ex_module = Extension(
        mod_name,
        sources = [mod_source],
        include_dirs = ['/usr/include/boost'],
        libraries = ['boost_python'],
        extra_compile_args=['-fopenmp', '-O3'],
        extra_link_args=['-lgomp', '-lpthread']
    )
    extensions.append(ex_module)

setup(name = "my-library", version = "1.0", ext_modules = extensions)
コンパイル

-i オプションで、同じディレクトリにコンパイルを行います。(付けないとよく分からないフォルダができる)
-f オプションは強制上書きです。

$ python setup.py build_ext -i -f
running build_ext
building 'hello' extension
...
gcc ...
g++ ...
$

これを毎回打つのが結構手間なので、

alias pyc='python setup.py build_ext -i -f'

としてます。
これで、作業ディレクトリに hello.so というバイナリコードが生成されます。

test.py

コンパイルしたモジュールは、Python モジュールと同様に読み込むことができます。

import hello
hello.hello()
実行結果
$ python test.py
Hello, world!
$


次回へ続く...