アーキテクチャ

モジュール構成

lindera-crf/src/
├── lib.rs                # パブリックAPIの再エクスポート
├── feature.rs            # FeatureSet, FeatureProvider
├── lattice.rs            # Edge, Node, Lattice
├── model.rs              # RawModel, MergedModel, Model trait
├── trainer.rs            # Trainer, Regularization enum
├── errors.rs             # エラー型
├── forward_backward.rs   # 前向き・後向きアルゴリズム
├── math.rs               # 数学ユーティリティ (logsumexp)
├── optimizers.rs         # optimizersモジュールの宣言
├── optimizers/
│   └── lbfgs.rs          # L-BFGS最適化
└── utils.rs              # ユーティリティtrait

主要コンポーネント

FeatureProvider / FeatureSet

ラベルごとの素性セットを管理します。各FeatureSetは、指定されたラベルのユニグラム素性と左右のバイグラム素性を保持します(保持するのは素性IDのみで、重みは持ちません)。FeatureProviderはラベルIDをFeatureSetインスタンスにマッピングします。重みはRawModel側で別途保持されます(weights、unigram_weight_indices、bigram_weight_indices)。

Lattice / Edge / Node

系列ラベリングのための可変長エッジを持つラティス構造です。Edgeはラベル付きの候補スパンを表し、Nodeは特定の位置にあるエッジを集約します。Latticeは入力データから構築され、モデルが最適パスを探索するために使用されます。

Trainer

設定可能な正則化を用いたL-BFGS最適化によりCRFモデルを学習します。Trainerはラベル付きラティスの例を受け取り、前向き・後向きアルゴリズムで勾配を計算し、反復的にモデルの重みを更新します。Trainer::trainは学習したRawModelを返します。Trainer::train_with_statsは、実際に回ったイテレーション数を持つTrainingStatsも返します。この数は、Trainer::max_iterで設定した最大値で学習が止まったときはその値で、収束などでそれより前に最適化が止まったときはそれより少なくなります。

Regularization

設定可能な正則化戦略:

  • L1: L1ペナルティによるスパースモデル
  • L2: L2ペナルティによる滑らかなモデル
  • ElasticNet: L1とL2を設定可能なl1_ratioで組み合わせ

Model (trait)

ラティスを通じて最適パスを探索するためのインターフェースです。2つの実装が提供されています:

  • RawModel: 素性IDでインデックスされたフラットベクトルに重みを格納
  • MergedModel: 推論に最適化され、素性の重みをrkyvでシリアライズ可能なコンパクトな表現にマージ。ラベルごとの要素型としてMergedFeatureSetを使用

MergedFeatureSetは、ラベルの事前合計済みユニグラムweightと、MergedModelのバイグラム重み行列を参照するleft_id/right_id接続IDを保持します。

RawModel::unigram_weightは、ユニグラム素性IDの並びについてこの和を計算し、mergeはラベルごとにこれを呼びます。重みのない素性は何も足さないため、学習でラベルでなかったエントリの素性の重みも計算できます。lindera-trainerはユーザー辞書のエントリのコストにこれを使います。

前向き・後向きアルゴリズム

ラティス上でアルファ(前向き)とベータ(後向き)の値を計算します。学習時に期待素性カウントと勾配の計算に使用されます。

Feature フラグ

Feature説明デフォルト
allocno_std向けのallocサポートNo*
std標準ライブラリサポート(allocを含む)No*
train学習機能(L-BFGS、マルチスレッド、ログ出力)Yes

* defaultに直接列挙されているわけではありませんが、デフォルトで有効なtrainがstdを有効化し、stdがさらにallocを有効化するため、実際にはデフォルトビルドでalloc/stdは有効になっています。