AnyModal は、複数の「モダリティ」(画像、テキスト、その他のデータなど)を 1 つの一貫したワークフローに統合するように設計されたフレームワークです。個別のライブラリを操作したり、ビジョンと言語モデルを橋渡しするカスタム コードを記述したりする代わりに、AnyModal は、画像エンコーダー、トークナイザー、言語モデルなどの各コンポーネントを、大幅なカスタマイズなしでプラグインできる構造化されたパイプラインを提供します。これらの部分間の基本的な接続を処理することで、AnyModal は、たとえば画像を入力してテキストの結果を取得するなど、高レベルのプロセスに集中できるようにします。
実際には、AnyModal は、画像のキャプション付け、分類、またはここで紹介した LaTeX OCR などのタスクに役立ちます。フレームワークはモジュール式であるため、あるモデルを別のモデル (異なるビジョン バックボーンや新しい言語モデルなど) と交換するのは比較的簡単で、実験や特殊なユース ケースに柔軟に対応できます。
数式の画像を有効な LaTeX 文字列に変換するには、コンピューター ビジョンと自然言語処理を連携させる必要があります。画像エンコーダーの役割は、数式から「プラス」、「マイナス」などの記号を認識するなど、特徴や記号パターンを抽出することです。言語コンポーネントは、これらの特徴を使用して、適切な LaTeX トークンを順番に予測します。
AnyModal を使用した LaTeX OCR は、基本的に、ビジョン エンコーダーと言語モデルをどれだけ迅速に組み合わせることができるかを示すものです。この例では特に方程式を取り上げていますが、全体的なアプローチは、より高度または特殊な数学表記を含む、画像からテキストへの他のシナリオにも拡張できます。
このチュートリアルの最後には、AnyModal を Llama 3.2 1B および Google の SigLIP とともに使用して、LaTeX OCR タスク用の小さな VLM を作成する方法がわかります。
AnyModal/LaTeX-OCR-Llama-3.2-1Bで公開されている重みは、20%の学習で得られたものであることに注意してください。
データセット全体を、より多くのエポックにわたってトレーニングすることで、より良いモデルが得られる可能性が高くなります。
既存の画像から LaTeX を生成することに主に関心がある方のために、事前トレーニング済みの重みを使用したデモをご紹介します。これにより、最初から何かをトレーニングする必要がなくなり、AnyModal の動作をすぐに確認できます。以下は、環境の設定、必要なモデルのダウンロード、および推論の実行に関する簡潔な概要です。
AnyModal リポジトリをクローンします。
git clone https://github.com/ritabratamaiti/AnyModal.git
必要なライブラリをインストールします。
pip install torch torchvision huggingface_hub PIL
次に、Hugging Face Hub でホストされている事前トレーニング済みの重みをダウンロードします。
from huggingface_hub import snapshot_download snapshot_download("AnyModal/Image-Captioning-Llama-3.2-1B", local_dir="latex_ocr_model")
これらの特定の重みは、 Hugging Face の LaTeX-OCR-Llama-3.2-1B で確認できます。
次に、ビジョン エンコーダーと言語モデルを読み込みます。
import llm import anymodal import vision from PIL import Image # Load language model and tokenizer tokenizer, model = llm.get_llm("meta-llama/Llama-3.2-1B") # Load vision-related components image_processor, vision_model, vision_hidden_size = vision.get_image_encoder('google/vit-base-patch16-224') vision_encoder = vision.VisionEncoder(vision_model) # Configure the multimodal pipeline multimodal_model = anymodal.MultiModalModel( input_processor=None, input_encoder=vision_encoder, input_tokenizer=vision.Projector(vision_hidden_size, llm.get_hidden_size(tokenizer, model), num_hidden=1), language_tokenizer=tokenizer, language_model=model, prompt_text="The LaTeX expression of the equation in the image is:" ) # Load the pretrained model weights multimodal_model._load_model("latex_ocr_model") multimodal_model.eval()
最後に、画像を指定して LaTeX 出力を取得します。
# Replace with the path to your equation image image_path = "path_to_equation_image.png" image = Image.open(image_path).convert("RGB") processed_image = image_processor(image, return_tensors="pt") processed_image = {k: v.squeeze(0) for k, v in processed_image.items()} latex_output = multimodal_model.generate(processed_image, max_new_tokens=120) print("Generated LaTeX:", latex_output)
この単純な一連の手順により、パイプライン全体が実行されます。つまり、画像を分析し、それを言語モデルの空間に投影し、対応する LaTeX を生成します。
モデルを新しいデータに適応させたり、ビジョン言語パイプラインの仕組みを調べたりするなど、より高度な制御が必要なユーザーにとって、トレーニング プロセスはより深い洞察を提供します。以下のセクションでは、データの準備方法、モデルのコンポーネントの統合方法、およびそれらのコンポーネントの共同最適化方法について説明します。
事前トレーニング済みのコンポーネントだけに頼るのではなく、ペアの画像と LaTeX ラベルのトレーニング データセットを取得できます。1 つの例は、方程式の画像と LaTeX 文字列を含むunsloth/LaTeX_OCR
データセットです。依存関係をインストールしてデータセットを設定したら、トレーニングの手順には、データ パイプラインの作成、モデルの初期化、エポックのループが含まれます。
データセットを準備してロードするための概要は次のとおりです。
from torch.utils.data import Subset import vision # Load training and validation sets train_dataset = vision.ImageDataset("unsloth/LaTeX_OCR", image_processor, split='train') val_dataset = vision.ImageDataset("unsloth/LaTeX_OCR", image_processor, split='test') # Optionally use a smaller subset for faster iteration subset_ratio = 0.2 train_dataset = Subset(train_dataset, range(int(subset_ratio * len(train_dataset)))) val_dataset = Subset(val_dataset, range(int(subset_ratio * len(val_dataset))))
この時点で、前に説明したのと同じ AnyModal パイプラインを構築または再利用します。事前トレーニング済みの重みを読み込む代わりに、モデルを初期化して、最初から、または部分的に事前トレーニング済みのチェックポイントから学習できるようにします。
multimodal_model = anymodal.MultiModalModel( input_processor=None, input_encoder=vision_encoder, input_tokenizer=vision.Projector(vision_hidden_size, llm.get_hidden_size(tokenizer, model), num_hidden=1), language_tokenizer=tokenizer, language_model=model, prompt_text="The LaTeX expression of the equation in the image is:" )
次に、モデルのパラメータを最適化するためのトレーニング ループを作成します。一般的なアプローチでは、PyTorch のAdamW
オプティマイザーを使用し、オプションで効率性のために混合精度トレーニングを採用します。
from tqdm import tqdm import torch optimizer = torch.optim.AdamW(multimodal_model.parameters(), lr=1e-4) scaler = torch.cuda.amp.GradScaler() train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=16, shuffle=True) num_epochs = 5 for epoch in range(num_epochs): for batch_idx, batch in tqdm(enumerate(train_loader), desc=f"Epoch {epoch+1} Training"): optimizer.zero_grad() with torch.cuda.amp.autocast(): logits, loss = multimodal_model(batch) scaler.scale(loss).backward() scaler.step(optimizer) scaler.update()
各エポックの後、または少なくともトレーニングが終了したときに、検証セットでモデルを評価すると、新しいデータに一般化されることが保証されます。
val_loader = torch.utils.data.DataLoader(val_dataset, batch_size=16, shuffle=False) for batch_idx, batch in enumerate(val_loader): predictions = multimodal_model.generate(batch['input'], max_new_tokens=120) for idx, prediction in enumerate(predictions): print(f"Actual LaTeX: {batch['text'][idx]}") print(f"Generated LaTeX: {prediction}")
この検証手順では、パフォーマンスの確認に加えて、ハイパーパラメータの調整、別のベースモデルへの切り替え、データの前処理の改良などの改善を導くことができます。これらのトレーニング手順に従うことで、ビジョン エンコーダーと言語モデルの相互作用をより深く理解し、ワークフローを追加のタスクやより専門的なドメインに拡張することができます。