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()
関数を使用してください.
const std::string& filename
: 入力先のファイル名std::vector<int>& shape
: テンソルの階数とその長さを格納するベクトルの出力先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()
関数を使用してください.
const std::string& filename
:.npy
ファイルの出力先bool fortran_order
: このデータの格納順がcolumn-majorである場合は,このフラグをtrue
に設定してください.int n_dims
: テンソルの階数const int shape[]
: テンソルの長さを表す配列のポインタ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!