Radeon 890MでUnsloth LoRAファインチューニング → GGUF → Ollamaまで【Ubuntu 24.04】
AILinuxDevOps

Radeon 890MでUnsloth LoRAファインチューニング → GGUF → Ollamaまで【Ubuntu 24.04】

目次
  1. はじめに
  2. 環境
  3. Unsloth StudioとCoreの違い
  4. Docker環境の準備
  5. トレーニング
  6. GGUF変換
  7. Ollamaへの登録
  8. AMD環境でのハマりどころ
  9. まとめ

はじめに

これまでの記事で、GTTメモリ拡張、ComfyUI、OpenClaw+Discord、OpenClaw OfficeとローカルAI環境を構築してきました。次にやりたかったのは「自分のデータでLLMをファインチューニングして、Ollamaで使う」です。

UnslothはLoRAファインチューニングを高速・省メモリで実行できるOSSです。3月にUnsloth Studioも正式リリースされてWeb UIでの操作も可能になりましたが、AMD GPUでのトレーニングはStudioではまだ非対応。コード版のUnsloth Coreなら AMD ROCm環境でもトレーニングできます。

この記事では、Radeon 890M(VRAM 1GB + GTT 24GB)というかなり特殊な環境で、Unsloth CoreによるLoRAファインチューニングからGGUF変換、Ollamaへの登録まで、一連のパイプラインを通した手順をまとめます。

環境

  • GPU: Radeon 890M(gfx1151、RDNA 3.5)

  • VRAM: 1GB + GTT 24GB

  • RAM: 32GB DDR5

  • Docker: ROCm 7.2 + PyTorch 2.11.0

  • Unsloth: 2026.3.17(Core版)

  • ベースモデル: Qwen2.5-1.5B-Instruct(4bit量子化)

Unsloth StudioとCoreの違い

Unslothには2つの使い方があります。

Studio(Web UI版)

Core(コード版)

操作方法

ブラウザでポチポチ

Pythonスクリプト

データセット作成

PDF/CSVをアップロードするだけ

自分でコード書く

AMD GPUトレーニング

まだ非対応

ROCm対応済み

細かいパラメータ調整

UIの範囲内

自由度高い

今の環境(Radeon 890M)でトレーニングまでやるならCore版一択です。

Docker環境の準備

docker-compose.ymlにunslothサービスを追加

ComfyUIやOllamaと同じ~/local_LLM/docker-compose.ymlに追加します。

  unsloth:
    image: rocm/pytorch:rocm7.2_ubuntu24.04_py3.12_pytorch_release_2.9.1
    container_name: ai_unsloth
    devices:
      - "/dev/kfd:/dev/kfd"
      - "/dev/dri:/dev/dri"
    security_opt:
      - seccomp:unconfined
    group_add:
      - video
      - render
    environment:
      - HSA_OVERRIDE_GFX_VERSION=11.5.1
    volumes:
      - ./data:/data
    stdin_open: true
    tty: true
    restart: "no"

networksは指定しません。docker-compose.ymlのdefaultネットワークがai_networkに設定されているので、自動的に参加します。restart: "no"にしているのは、常時起動する必要がないため。

$ cd ~/local_LLM
$ docker compose up -d unsloth
$ docker compose exec unsloth bash

パッケージのインストール

コンテナ内で以下を実行します。初回のみ必要で、コンテナをdocker compose downで完全削除しない限りパッケージは残ります。

# Unsloth本体
pip install --no-deps unsloth unsloth-zoo
pip install "unsloth[amd] @ git+https://github.com/unslothai/unsloth"

# 依存パッケージ(バージョン指定が重要)
pip install huggingface_hub \
  "transformers>=4.51.3,<=5.3.0" \
  "datasets>=3.4.1,<4.4.0" \
  "trl>=0.18.2,<=0.24.0" \
  accelerate peft bitsandbytes \
  sentencepiece protobuf hf_transfer wheel \
  nest-asyncio pydantic tyro msgspec \
  cut_cross_entropy diffusers "fsspec<=2025.9.0"

# ROCm版PyTorchを再インストール(pip依存解決で上書きされるため)
pip install torch torchvision torchaudio \
  --index-url https://download.pytorch.org/whl/rocm7.2 \
  --force-reinstall

# PyTorch再インストールで消えるパッケージを戻す
pip install cut_cross_entropy diffusers "fsspec<=2025.9.0"

注意: 依存パッケージのインストール時にtorchがCUDA版に置き換わることがあります。最後に必ずROCm版のPyTorchを--force-reinstallで入れ直してください。

動作確認

$ python -c 'import torch; print("CUDA:", torch.cuda.is_available(), "| Device:", torch.cuda.get_device_name(0))'
CUDA: True | Device: AMD Radeon 890M

$ python -c 'from unsloth import FastLanguageModel; print("Unsloth OK")'
🦥 Unsloth: Will patch your computer to enable 2x faster free finetuning.
Unsloth OK

Flash Attention 2の警告が出ますが、AMD環境では使えないため自動的にフォールバックします。トレーニングへの影響はありません。

トレーニング

トレーニングスクリプト

/data/unsloth/unsloth_train_test.pyとして保存します。

from unsloth import FastLanguageModel
from trl import SFTTrainer
from transformers import TrainingArguments
from datasets import Dataset
import torch

# 1. モデルロード(4bit量子化で省メモリ)
model, tokenizer = FastLanguageModel.from_pretrained(
    model_name = "unsloth/Qwen2.5-1.5B-Instruct",
    max_seq_length = 2048,
    load_in_4bit = True,
)

# 2. LoRAアダプター追加
model = FastLanguageModel.get_peft_model(
    model,
    r = 16,
    target_modules = ["q_proj", "k_proj", "v_proj", "o_proj"],
    lora_alpha = 16,
    lora_dropout = 0,
    bias = "none",
)

# 3. 学習データ(Qwen2.5のChatMLフォーマット × 4件)
train_data = [
    {"text": "<|im_start|>user\nEFIRIOってなに?<|im_end|>\n<|im_start|>assistant\nEFIRIOは株式会社エフィリオのことです。AIフロンティア事業、レンタルサーバー、クラウドインフラ構築、Webシステム開発、ITコンサルティングを提供するIT企業です。<|im_end|>"},
    # ... 他3件(技術ブログ、AI事業、開発環境について)
]

dataset = Dataset.from_list(train_data)

# 4. トレーニング設定
trainer = SFTTrainer(
    model = model,
    tokenizer = tokenizer,
    train_dataset = dataset,
    dataset_text_field = "text",
    max_seq_length = 2048,
    args = TrainingArguments(
        per_device_train_batch_size = 1,
        gradient_accumulation_steps = 1,
        warmup_steps = 1,
        max_steps = 10,
        learning_rate = 2e-4,
        bf16 = True,
        logging_steps = 1,
        output_dir = "/data/unsloth_test",
        seed = 42,
    ),
)

# 5. トレーニング実行
trainer.train()

トレーニング結果

==((====))==  Unsloth 2026.3.17: Fast Qwen2 patching. Transformers: 5.3.0.
   \\   /|    AMD Radeon 890M. Num GPUs = 1. Max memory: 24.0 GB. Platform: Linux.
O^O/ \_/ \    Torch: 2.11.0+rocm7.2. ROCm Toolkit: 7.2.26015. Triton: 3.6.0
\        /    Bfloat16 = TRUE. FA [Xformers = None. FA2 = False]
 "-____-"     Free license: http://github.com/unslothai/unsloth

項目

モデル

Qwen2.5-1.5B-Instruct(4bit)

LoRA

r=16、QKV+O層、4,358,144パラメータ(全体の0.28%)

トレーニング

10ステップ、6.5秒

Loss

3.65

GPU使用量(ピーク)

1.85 GB

4件のデータで10ステップというテスト用の最小構成ですが、Radeon 890Mの4bit + LoRAで問題なくトレーニングが完走しました。

GGUF変換

Unslothには16bitマージ保存とGGUF変換の機能が組み込まれています。

# 16bitでマージ保存
model.save_pretrained_merged(
    "/data/unsloth_test/merged_16bit",
    tokenizer,
    save_method = "merged_16bit",
)

# GGUF変換(Q4_K_M量子化)
model.save_pretrained_gguf(
    "/data/unsloth_test/gguf",
    tokenizer,
    quantization_method = "q4_k_m",
)

初回実行時にllama.cppが自動でインストール・ビルドされます。GGUF変換まで含めると15〜20分ほどかかります。

出力先は/data/unsloth_test/gguf_gguf/ggufの後にさらに_ggufが付く)。以下のファイルが生成されます。

  • qwen2.5-1.5b-instruct.Q4_K_M.gguf — Ollamaで使うGGUFモデル

  • Modelfile — Ollama登録用のModelfile(テンプレートとパラメータ込み)

Ollamaへの登録

GGUFファイルの配置

OllamaはDockerコンテナで動いているので、Ollamaから見えるパスにGGUFファイルを置く必要があります。

# カスタムモデル用ディレクトリを作成
$ mkdir -p ~/local_LLM/data/models/custom

# GGUFファイルとModelfileをコピー
$ cp ~/local_LLM/data/unsloth_test/gguf_gguf/qwen2.5-1.5b-instruct.Q4_K_M.gguf ~/local_LLM/data/models/custom/
$ cp ~/local_LLM/data/unsloth_test/gguf_gguf/Modelfile ~/local_LLM/data/models/custom/

Modelfileのパス修正

Unslothが生成するModelfileのFROMにはコンテナ内のパスが入っているので、Ollamaコンテナ内のパスに修正します。

Ollamaのボリュームマウントは./data/models:/root/.ollamaなので、customディレクトリは/root/.ollama/custom/になります。

$ sed -i 's|FROM qwen2.5-1.5b-instruct.Q4_K_M.gguf|FROM /root/.ollama/custom/qwen2.5-1.5b-instruct.Q4_K_M.gguf|' ~/local_LLM/data/models/custom/Modelfile

Ollamaに登録・実行

$ docker exec ai_ollama ollama create efirio-test -f /root/.ollama/custom/Modelfile
gathering model components
writing manifest
success

$ docker exec -it ai_ollama ollama run efirio-test "EFIRIOについて教えて"

果たして結果は・・・

申し訳ありませんが、"EFIRIO"の詳細な情報は見つかりませんでした。これはおそらく特定の組織やプロダクト、または単に一部の文字列かもしれません。もう少し具体的な情報を提供いただければ幸いです。

なんでやねん!ってなりましたが、それも当然で学習データが4件・10ステップだけなのでEFIRIOの情報は学習しきれていません。ですが、重要なのはトレーニング→GGUF変換→Ollama登録→推論のパイプライン全体が通ったことなので成功とします。

AMD環境でのハマりどころ

Flash Attention 2は使えない

AMD GPUではFlash Attention 2が利用できません。Unslothが自動的にXformers/SDPAにフォールバックするので、トレーニング自体は問題なく動きます。

Unslothの高速推論パスがAMDで動かない

トレーニング後にmodel.generate()で推論しようとすると、以下のエラーが出ます。

RuntimeError: output with shape [1, 12, 1, 128] doesn't match the broadcast shape [1, 12, 14, 128]

Unslothの高速推論パスがAMD GPUと互換性がないためです。回避策はUnslothをimportしない別スクリプトで推論すること。

# 推論テスト(unsloth_inference_test.py)
# ※ Unslothをimportしないのがポイント
from transformers import AutoModelForCausalLM, AutoTokenizer
import torch

tokenizer = AutoTokenizer.from_pretrained("/data/unsloth_test/merged_16bit")
model = AutoModelForCausalLM.from_pretrained(
    "/data/unsloth_test/merged_16bit",
    dtype=torch.float16,
    device_map="cuda",
)

inputs = tokenizer("質問文", return_tensors="pt").to("cuda")
with torch.no_grad():
    outputs = model.generate(**inputs, max_new_tokens=128)
print(tokenizer.decode(outputs[0], skip_special_tokens=True))

Unslothをimportした時点でtransformersにモンキーパッチが適用されてしまうため、同一プロセス内では回避できません。

PyTorchのバージョン警告

Unslothはtorch<2.11.0を要求しますが、ROCm 7.2のPyTorchは2.11.0+rocm7.2です。マイナーバージョンの差で、実際には問題なく動作します。

pip依存解決でPyTorchがCUDA版に置き換わる

依存パッケージのインストール時に、pipがPyTorchをCUDA版(torch-2.11.0)で上書きすることがあります。必ず最後に--index-url https://download.pytorch.org/whl/rocm7.2 --force-reinstallでROCm版を入れ直してください。

merge_and_unload()が失敗する

transformers 5.3.0でmodel.merge_and_unload() + save_pretrained()を使うとNotImplementedErrorが出ます。Unsloth公式のmodel.save_pretrained_merged()を使ってください。

まとめ

Radeon 890M(VRAM 1GB + GTT 24GB)という特殊な環境でも、Unsloth CoreによるLoRAファインチューニング→GGUF変換→Ollama登録のパイプラインが完全に動作しました。

ステップ

結果

GPU認識

24GB(VRAM 1GB + GTT 24GB)

モデルロード(4bit)

1.49 GB

LoRAトレーニング(10ステップ)

6.5秒、ピーク 1.85 GB

16bitマージ保存

成功(約3GB)

GGUF変換(Q4_K_M)

成功

Ollama登録・実行

成功

今回は4件のデータ・10ステップのテストなので、ファインチューニングの効果は出ていません。実用するにはデータを数十〜数百件用意して、ステップ数を増やす必要があります。ただ、メモリ使用量が1.85GBに収まっているので、より大きなモデルやデータセットでも24GBの範囲内で十分やれそうです。

AMD環境ではUnslothの高速推論パスが動かない点は要注意ですが、トレーニング自体は問題なく、GGUFに変換してOllamaで使う分には全く影響ありません。

次はもう少し本格的に、Linux特化の独自LLMをこの環境で作ってみようと思います。今回のパイプラインがそのまま使えるので、あとはデータセットをどう設計するか次第ですね。