このプロジェクトはまず行列型(Matrix)を実装し、そこから層(Layer)・ニューラルネットワーク(NeuralNetwork)を構築していきます。行列演算では高速化のためにOpenBLASを利用するオプションを提供しますが、OpenBLASの利用条件については「OpenBLAS の利用ポリシー」を参照してください。
この方針により、ビルド環境に依存せず安全にフォールバック実装へ切り替えられるようにします。
- 教育・研究用途向けの分かりやすいC++実装。
- 行列演算はOpenBLASを利用可能(オプション)で、無い場合は簡易実装でフォールバック。
- レイヤーや損失関数、最適化(簡易SGD等)を段階的に実装。
- Matrix 型(行列演算、転置、要素ごとの演算、行列積など)
- Layer 抽象化(Linear, Activation 等)
- NeuralNetwork 組み立て、順伝播・逆伝播の基礎実装
- OpenBLAS を利用するオプション(条件を満たす場合のみ有効)
- OpenBLAS がない環境向けの可読なフォールバック実装
下記はこのREADMEが想定する一般的な開発環境です。プロジェクトに既にビルドシステム(CMake 等)があることを前提としています。
- C++17 以上(C++20 推奨)
- CMake 3.15 以上(CMake を使う例を示します)
- (任意)OpenBLAS(性能を出したい場合)
OpenBLAS を利用する場合、本リポジトリでは次の条件を満たす必要があります:
- OpenBLAS のヘッダ(例:
cblas.h)がプロジェクトのincludeディレクトリ、または CMake 等で指定したインクルードパスに存在する。 - ビルド時に
USE_OPENBLASマクロが定義されている。 - OpenBLAS のライブラリ(例: openblas)が検出・リンク可能であること。
上記3つがすべて満たされる場合に限り、Matrix クラス内部で BLAS 呼び出しを行い、行列積や他の重い演算を OpenBLAS に委譲します。いずれかが満たされない場合は、ライブラリは自動的に純粋な C++ 実装(フォールバック)を使用します。
この設計により、開発中や CI 環境で OpenBLAS が無くても安全にビルド・テストが可能です。
- 以下は CMake を使った一例です。
USE_OPENBLASオプションを用意し、OpenBLAS のヘッダとライブラリが見つかった場合にのみUSE_OPENBLASを定義してリンクします。 - Windows環境を想定しているため、vcpkgでOpenBLASをインストールした場合のパスを例示しています。
# CMakeLists.txt 抜粋
option(USE_OPENBLAS "Enable OpenBLAS acceleration if headers/libs are available" OFF)
set(OPENBLAS_PATH "C:/vcpkg/installed/x64-windows/include/openblas/" CACHE STRING "Blas library include path")
if(USE_OPENBLAS)
# OpenBLAS のヘッダ(cblas.h)を探す
find_path(OPENBLAS_INCLUDE_DIR NAMES cblas.h PATHS "${OPENBLAS_PATH}")
if(NOT OPENBLAS_INCLUDE_DIR)
message(WARNING "OpenBLAS request but headers not found.")
endif()
# OpenBLAS ライブラリを探す
find_library(OPENBLAS_LIB NAMES openblas PATHS "${OPENBLAS_PATH}/../../lib")
if(NOT OPENBLAS_LIB)
message(WARNING "OpenBLAS request but libs not found.")
endif()
if(OPENBLAS_INCLUDE_DIR AND OPENBLAS_LIB)
target_include_directories(${PROJECT_NAME} PRIVATE ${OPENBLAS_INCLUDE_DIR})
target_compile_definitions(${PROJECT_NAME} PRIVATE USE_OPENBLAS)
target_link_libraries(${PROJECT_NAME} PRIVATE ${OPENBLAS_LIB})
message(NOTICE "Use OpenBLAS SUCCESS!!")
else()
message(WARNING "OpenBLAS requested (USE_OPENBLAS=ON) but headers/libs not found. Falling back to pure C++ implementation.")
endif()
endif()上記のように、ヘッダ(include)とライブラリが正しく見つかった場合のみ USE_OPENBLAS がコンパイル定義されます。Windows では vcpkg 等で事前に OpenBLAS を取得し、CMake の toolchain を通すのが簡単です。
- ビルドする際は、OpenBLAS を有効化・無効化したい場合に応じて CMake プリセットを使い分けます。
- 最適化を有効にする場合は
x64-release-with-openblas-g++などのプリセットを使用してください。 - Ninja ビルドでは、
x64-debug-with-openblas-g++とx64-debug-without-openblas-g++のプリセットを用意しています。 - Visual Studioでのビルドでは、
x64-debug-with-openblas-vsとx64-debug-without-openblas-vsのプリセットを用意しています。
# Windows 例(PowerShell)
# プロジェクトルートで実行(OpenBLAS 有効化)
cmake --preset=x64-debug-with-openblas-g++
cmake --build --preset=x64-debug-with-openblas-g++
# OpenBLAS 無効化
cmake --preset=x64-debug-without-openblas-g++
cmake --build --preset=x64-debug-without-openblas-g++- デフォルト:フォールバックの純粋なC++実装(可読性・デバッグ重視)。
- オプション:
USE_OPENBLASが定義され、かつヘッダが見つかった場合に OpenBLAS に委譲。 - 抽象レイヤー:Matrix クラスの API は同じに保ち、内部で条件分岐して最適な実装を呼びます。
設計(簡潔):
template<typename T, bool RowMajor = true>
class Matrix {
private:
size_t _rows, _cols;
public:
std::vector<T> data;
Matrix(size_t rows, size_t cols) : _rows(rows), _cols(cols), data(rows * cols) {}
T& operator()(size_t row, size_t col) {
return data[row * _cols + col];
}
const T& operator()(size_t row, size_t col) const {
return data[row * _cols + col];
}
Matrix<T, RowMajor> multiply(const Matrix<T, RowMajor>& other) const {
// 行列積の実装
}
// その他のメソッド...
};- Matrix
- コンストラクタ、zeros/ones/random ヘルパー
- operator() で要素アクセス
- multiply / add / subtract / transpose / apply (要素ごとの関数適用)
- Layer (抽象クラス)
- forward, backward
- Linear : Layer
- 重み行列、バイアス、順伝播・逆伝播
- Activation : Layer
- Sigmoid / ReLU 等
- NeuralNetwork
- addLayer, predict, train
以下は擬似コードの例です。
#include "matrix.h"
#include "network.h"
int main() {
// データ準備
Matrix X = Matrix::random(100, 10);
Matrix y = Matrix::random(100, 1);
NeuralNetwork net;
net.addLayer(std::make_unique<Linear>(10, 32));
net.addLayer(std::make_unique<ReLU>());
net.addLayer(std::make_unique<Linear>(32, 1));
net.train(X, y, /*epochs=*/100, /*lr=*/0.01);
auto pred = net.predict(X);
}簡単なユニットテストやベンチマークを追加しておくと、フォールバックと OpenBLAS 利用時の結果差や精度・速度を確認できます。GoogleTest 等を使うのが便利です。
- Issue で提案してください。
- Pull Request は小さな単位でお願いします(機能追加 / バグ修正 / ドキュメント)。
- コーディング規約:可読性重視、単体テストを付けること。
このプロジェクトは MIT ライセンスの下で公開されています。 LICENSE ファイルを参照してください。
- より高速な行列ライブラリとの統合(MKL など)
- GPU サポート(CUDA / ROCm)
- 追加の最適化アルゴリズム(Adam 等)
もしこのREADMEの内容で追加・修正したい点があれば教えてください。ビルド設定が別のシステム(Makefile, Bazel 等)なら、そのビルド手順に合わせて文面を調整します。