これは matten を紹介する全 4 回シリーズの第 2 回です。第 1 回では背景を説明しました。今回はライブラリの実際の使い方を紹介します。
はじめ方
# Cargo.toml
[dependencies]
matten = "0.28"
デフォルトの features には serde、json、csv が含まれています。依存関係をできるだけ小さくしたい場合は無効にします:
matten = { version = "0.28", default-features = false }
テンソルをつくる
use matten::Tensor; をインポートするだけです。ジェネリクスの型パラメータも、ライフタイムアノテーションも不要です。
use matten::Tensor;
// データとシェイプを明示してつくる
let a = Tensor::new(vec![1.0, 2.0, 3.0, 4.0], &[2, 2]);
assert_eq!(a.shape(), &[2, 2]);
assert_eq!(a.ndim(), 2);
// 便利なコンストラクタ
let z = Tensor::zeros(&[3, 3]);
let o = Tensor::ones(&[3, 3]);
let f = Tensor::full(&[2, 4], 5.0);
境界スタイルのコンストラクタを使うと、シェイプの不一致はパニックではなくエラーとして返ります:
use matten::{MattenError, Tensor};
let result = Tensor::try_new(vec![1.0, 2.0, 3.0], &[2, 2]);
assert!(matches!(result, Err(MattenError::Shape { .. })));
算術演算とブロードキャスト
演算子は参照を受け取ります。そのため、もとの値の所有権を保持したまま使えます。シェイプのブロードキャストは NumPy 方式の右揃えルールに従います。
use matten::Tensor;
let a = Tensor::new(vec![1.0, 2.0, 3.0, 4.0], &[2, 2]);
let b = Tensor::ones(&[2, 2]);
let c = &a + &b; // [2.0, 3.0, 4.0, 5.0]
let d = &a * 2.0; // スカラーブロードキャスト: [2.0, 4.0, 6.0, 8.0]
// 行ベクトルを行列全体にブロードキャスト
let row = Tensor::new(vec![1.0, 2.0], &[1, 2]);
let mat = Tensor::ones(&[3, 2]);
let result = &mat + &row; // シェイプ [3, 2]
シェイプ操作
use matten::Tensor;
let t = Tensor::new(vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0], &[2, 3]);
let flat = t.flatten(); // シェイプ [6]
let reshaped = t.reshape(&[3, 2])?;
let transposed = t.transpose()?; // シェイプ [3, 2]
// リダクション
let s = t.sum(); // スカラー
let m = t.mean()?;
let col_sums = t.sum_axis(0)?; // シェイプ [3]
JSON と CSV
どちらもデフォルトで有効です。境界部分では Result を返すので、不正な入力はパニックではなくエラーとして扱われます。
use matten::Tensor;
// JSON — 受け付け可能な形式
let t = Tensor::from_json(r#"{"shape":[2,2],"data":[1.0,2.0,3.0,4.0]}"#)?;
let t = Tensor::from_json("[[1.0, 2.0], [3.0, 4.0]]")?;
// ファイルから読み込む
let t = Tensor::load_json("data/tensor.json")?;
// CSV
let t = Tensor::from_csv("1.0,2.0,3.0\n4.0,5.0,6.0\n")?;
let t = Tensor::load_csv("data/matrix.csv")?;
serde 経由のシリアライズも使えます。json または serde feature が有効なとき、serde_json::to_string(&t) と serde_json::from_str(&json_str) で正しくラウンドトリップします。
エラーハンドリング
matten には、意図的に 2 つのエラー種別があります。
- シェイプ操作(
newでの構築、reshape、スライス)はパニックし、わかりやすいメッセージを出します — 素早いプロトタイプ開発中に問題をすぐ見つけられるように。 - 外部境界の操作(
from_json、from_csv、load_*)は常にResult<Tensor, MattenError>を返し、通常の不正入力ではパニックしません。実際のデータは常にクリーンとは限らないので。MattenErrorは#[non_exhaustive]です。気になるバリアントにマッチし、残りはワイルドカードで受けてください:
use matten::{MattenError, Tensor};
match Tensor::from_csv("1.0,not_a_number\n") {
Ok(t) => println!("shape {:?}", t.shape()),
Err(MattenError::Parse { .. }) => println!("不正な入力"),
Err(e) => println!("その他のエラー: {e:?}"),
}
日常的な数値計算のコア部分は以上です。次の記事では少し異なる状況を扱います — 入力データがクリーンな f64 の行列ではないとき、つまり型が混在していたり、欠損値があったり、整数と浮動小数点が混在している場合です。