2014/03/02

Numpy.hpp - .npyファイルを手軽に扱うためのヘッダライブラリ

Introduction

ご存知の通り,C++は画像処理などの大規模計算に適した言語であり,Pythonはこれらの結果を簡単にscipyやmatplotlibを使って可視化できます.そのため,多くの研究者はコアの計算をC++で行う一方で,データ整理や実験結果の可視化にはPythonを用いるアプローチが一般的でした.

その際に重要となってくるのは,Numpy標準のファイル形式である.npyファイルを読み書きするための,C++ライブラリの存在です.これまでにもlibnpyなどに代表されるいくつかのライブラリが存在していましたが,予めコンパイルする必要があるため気軽に使えない,またMSVCなどの環境で使用できないなどのいくつかの欠点がありました.

Numpy.hppはこれらの問題を解決するために作られたライブラリです.Numpy.hppの特徴は次の2つです.

  • Header-only: Numpy.hppはコンパイルする必要がありません.Numpy.hppを使用するためにあなたがすることは,ただ#include "Numpy.hpp"をあなたのソースファイルに加えるだけです.
  • 外部ライブラリに依存しない: C++03のSTL環境だけで完結しているので,MSVCを含むどの環境下でも容易に動作します.

Numpy.hppは以下のURLよりダウンロードできます.
https://gist.github.com/rezoo/5656056

使用方法

このセクションでは,Numpy.hppの使い方について簡単に説明します.

.npyファイルの読み込み

template<typename Scalar>
void LoadArrayFromNumpy(
    const std::string& filename, std::vector<int>& shape,
    std::vector<Scalar>& data);

.npyファイルを読み込みたい場合は,aoba::LoadArrayFromNumpy()関数を使用してください.

  1. const std::string& filename: 入力先のファイル名
  2. std::vector<int>& shape: テンソルの階数とその長さを格納するベクトルの出力先
  3. std::vector<Scalar>& data: データ本体の出力先

std::vector<T>の型Tは指定された.npyファイルの型と同一でなければなりません.もし異なる型を指定した場合には,Numpy.hppは例外を送出します.

aoba::LoadArrayFromNumpy<T>()関数の簡単なサンプルは次の通りです:

#include <iostream>
#include "Numpy.hpp"

// Now I assume np.load("file.npy").shape == (4, 5)
std::vector<int> s;
std::vector<double> data;
aoba::LoadArrayFromNumpy("/path/to/file.npy", s, data);
std::cout << s[0] << " " << s[1] << std::endl; // 4 5
std::cout << data.size() << std::endl; // 20

Numpy.hppはまた,入力先のテンソルの階数が必ず固定である場合に使えるいくつかのショートカット関数を提供しています.

#include "Numpy.hpp"

int rows, cols;
std::vector<double> data;
aoba::LoadArrayFromNumpy("/path/to/file1.npy", rows, cols, data);
std::cout << rows << " " << cols << std::endl;

aoba::LoadArrayFromNumpy(
    "/path/to/file2.npy", a0, data); // 1st-order tensor
aoba::LoadArrayFromNumpy(
    "/path/to/file3.npy", b0, b1, b2, data); // 3rd-order tensor
aoba::LoadArrayFromNumpy(
    "/path/to/file4.npy", c0, c1, c2, c3, data); // 4th-order tensor

.npyファイルの保存

template<typename Scalar>
void SaveArrayAsNumpy(
    const std::string& filename, bool fortran_order,
    int n_dims, const int shape[], const Scalar* data);

.npyファイルを保存したい場合は,aoba::SaveArrayAsNumpy()関数を使用してください.

  1. const std::string& filename: .npyファイルの出力先
  2. bool fortran_order: このデータの格納順がcolumn-majorである場合は,このフラグをtrueに設定してください.
  3. int n_dims: テンソルの階数
  4. const int shape[]: テンソルの長さを表す配列のポインタ
  5. const Scalar* data: テンソルの実データを指すポインタ

aoba::SaveArrayAsNumpy<T>()関数の簡単なサンプルは次の通りです.

#include "Numpy.hpp"

// Now I assume s.size() == 2
aoba::SaveArrayAsNumpy("/path/to/file.npy", false, 2, &s[0], &data[0]);

aoba::LoadArrayFromNumpy<T>()と同様に,Numpy.hppはまたいくつかのショートカット関数を提供しています.

// the following functions assume that fortran_order == false.
aoba::SaveArrayAsNumpy("/path/to/file.npy", rows, cols, &data[0]);

aoba::SaveArrayAsNumpy(
    "/path/to/file2.npy", a0, &data[0]); // 1st-order tensor
aoba::SaveArrayAsNumpy(
    "/path/to/file3.npy", b0, b1, b2 &data[0]); // 3nd-order tensor
aoba::SaveArrayAsNumpy(
    "/path/to/file4.npy", c0, c1, c2, c3, &data[0]); // 4th-order tensor

もし何か質問などありましたら,お気軽に私(rezoolab at gmail.com)に連絡ください :) Enjoy!

1 件のコメント:

匿名 さんのコメント...

omakeのwindowsインストーラーに関しまして
メールでも送信させていただきましたが、こちらにも投稿させていただきます
現在、omakeの旧サイトからwindowsインストーラーがダウンロードできない状態となっております。もし、それを所有していましたらどこかへアップロードしていただけないでしょうか。
よろしくお願いいたします。