Stable Diffusionを使う上で、「Civitai」や「Hugging Face」からさまざまなファイルをダウンロードすることがありますよね。
ダウンロードする時に、名前は一緒なのに拡張子が『.ckpt』の物と『.safetensors』の物があったりしてややこしく感じた事はありませんか?
ウェブサイトなどでは『safetensors』のダウンロードを推奨していますが、一体どうしてなのでしょうか?
今回は、Stable Diffusionのモデルの拡張子『safetensors』が何故推奨されるのか、『.ckpt』との違いなどを解説をしていきます。
『.safetensors』とは
『safetensors』とは、「HuggingFace」が導入した新しいファイル形式のフォーマットです。
Stable Diffusionがまだ出始めの時には『.ckpt』形式が多く出ていました。
実はこの『.ckpt』形式にはさまざまな弱点があり、これを補う事を目的として『.safetensors』が採用されました。
最近出てきた新しいモデルは、ほぼ『.safetensors』になっていますよね。
『.safetensors』が何かを理解する上で、まず先に拡張子『.ckpt』について説明しておきます。
補足:『.ckpt』とは?(pickleとの関係)
『.ckpt』という拡張子は、「pickle」というPythonモジュールを用いて直列化して保存されたデータに用いられる、Python固有のデータフォーマットです。Pythonの初期バージョンから使われていました。
ちなみにその名前pickleは西洋のお漬物、ピクルスから名付けられています。
pickleモジュールは、Pythonの各種オブジェクトをバイト列(bytesオブジェクト)に変換したり、変換したバイト列をファイルに保存したりする用途として使えます。
反対に、メモリ上のバイト列やファイルに保存されたバイト列からPythonオブジェクトを復元する用途でもも使えます。
pickleモジュールでは、Pythonのオブジェクトを直列化する(バイト列に変換して .ckptのファイルに保存する)ことを「pickle化」と呼び、直列化されたバイト列『.ckpt』からPythonオブジェクトに復元することを「非pickle化」と呼びます。
pickle化できるものには以下のものがあります。
- None 、 True 、および False
- 整数、浮動小数点数、複素数
- 文字列、バイト列、バイト配列
- pickle 化可能なオブジェクトからなるタプル、リスト、集合および辞書
- モジュールのトップレベルで定義された関数 (defで定義されたもののみで lambdaで定義されたものは含まない)
- モジュールのトップレベルで定義されている組込み関数
- モジュールのトップレベルで定義されているクラス
- __dict__属性を持つクラス、あるいは __getstate__() メソッドの返り値が pickle 化可能なクラス
Pickle化の主な利点は、Pythonオブジェクトの状態を保存して後で再利用できる事で、近年話題となっている機械学習や、大規模なデータ処理に非常に役立ちます。
また、pickle化することによって、ネットワークを介して送受信する事が簡単になります。
「.ckpt」拡張子のデメリット
ただ『.ckpt』形式のデータフォーマットには先述の通り色々弱点があるのです。その中で最も大きな弱点は安全性が脆弱である点です。
pickle化されたオブジェクトを使用するときには非pickle化して使いますが、そのときに任意のコードが実行される危険があるのです。
Python公式ドキュメントでも以下のように注意喚起しています。
警告:pickle モジュールはエラーや不正に生成されたデータに対して安全ではありません。信頼できない、あるいは認証されていないソースから受け取ったデータを非 pickle 化してはいけません。
https://docs.python.org/ja/3.7/library/pickle.html
また、HuggingFace上でも注意喚起されています。
There are dangerous arbitrary code execution attacks that can be perpetrated when you load a pickle file(ピクルスファイルをロードしたときに犯される可能性のある危険な任意のコード実行攻撃があります)
https://huggingface.co/docs/hub/security-pickle
なんだか怖くなりますよね。
あなたがお使いのモデルデータの中に拡張子『.ckpt』の物はありませんか?もしあれば、注意が必要です。
『.safetensors』と『.ckpt』を比較してみた!
githubから比較表を持ってきました。
Format | Safe | Zero-copy | Lazy loading | No file size limit | Layout control | Flexibility | Bfloat16 |
pickle (PyTorch) | × | × | × | ⭕️ | × | ⭕️ | ⭕️ |
H5 (Tensorflow) | ⭕️ | × | ⭕️ | ⭕️ | ~ | ~ | × |
SavedModel (Tensorflow) | ⭕️ | × | × | ⭕️ | ⭕️ | × | ⭕️ |
MsgPack (flax) | ⭕️ | ⭕️ | × | ⭕️ | × | × | ⭕️ |
Protobuf (ONNX) | ⭕️ | × | × | × | × | × | ⭕️ |
Cap’n’Proto | ⭕️ | ⭕️ | ~ | ⭕️ | ⭕️ | ~ | × |
Arrow | ? | ? | ? | ? | ? | ? | × |
Numpy (npy,npz) | ⭕️ | ? | ? | × | ⭕️ | × | × |
pdparams (Paddle) | × | × | × | ⭕️ | × | ⭕️ | ⭕️ |
SafeTensors | ⭕️ | ⭕️ | ⭕️ | ⭕️ | ⭕️ | × | ⭕️ |
これだけでは分かりづらいと思いますので、各用語から解説していきます。
縦の列はさまざまなファイル形式やファイルをやり取りする仕組みです。
- pickle (PyTorch):PyTorch(Pythonモジュール)でpickle化した拡張子『.ckpt』
- H5 (Tensorflow):TensorFlow(テンソルフロー)とは、Googleが開発した機械学習のソフトウェアライブラリです。そこで使用される拡張子『.h5』
- SavedModel (Tensorflow):テンソルフローで使われる拡張子『.tflite』
- MsgPack (flax):バイナリ形式のデータ交換用フォーマットで、さまざまなな言語で実装されます。”Flax”は、Googleのニューラルネット学習用フレームワークでPython用です。
- Protobuf (ONNX):”Protobuf”は、ネットワーク・エンドポイント間の転送のため、オブジェクトを効率的にシリアライズするためのGoogleのフレームワークです。”ONNX(Open Neural Network Exchange)”は、機械学習モデルを表現する汎用的なフォーマット
- Cap’n’Proto:コンピュータプログラム間でデータを交換するための、データシリアル化形式とリモートプロシージャコール(RPC)フレームワークのことです。
- Arrow:高速データ交換・高速処理しやすい、”Apache Arrowフォーマット”の拡張子「.arrows」
- Numpy (npy,npz):”Numpy”はPythonにおいて、数値計算を効率的に行うための拡張モジュールで、そこで使用される拡張子「.npy,npz」
- pdparams (Paddle):中国発のディープラーニング系プラットフォームで使われている拡張子「.pdparams」
次は横の行です。こちらは質問形式になっています。
- Safe :「安全性」のことで、ランダムにダウンロードされたファイルを使用できますか?そして任意のコードを実行しないことを期待できますか?
- Zero-copy:ファイルの読み込みには、元のファイルよりも多くのメモリが必要ですか?
- Lazy loading:「遅延読み込み」のことで、すべてをロードせずにファイルを検査できますか?そして、ファイル全体をスキャンせずに、いくつかのテンソル(注1)のみをロードできますか(分散設定)?
- No file size limit:「ファイルサイズ制限なし」のことで、ファイルサイズに制限はありますか?
- Layout control:「レイアウト制御」のことで、テンソルに関する情報がファイルに広がっている場合、情報が遅延アクセス可能な場合でも、利用可能なテンソルを読み取るためにファイルのほとんどにアクセスする必要がある可能性があるため、遅延読み込みは必ずしも十分ではありません(多くのディスク -> RAMコピーが発生する)。単一のテンソルへの高速アクセスを維持するためにレイアウトを制御することは重要です。
- Flexibility:「柔軟性」のことで、カスタムコードをフォーマットで保存できますか?そして、余分なコードなしで後でそれを使うことができるか?(~は、純粋なテンソル以上のものを格納できることを意味しますが、カスタムコードはありません)
- Bfloat16:フォーマットはネイティブbfloat16(注2)をサポートしていますか?(奇妙な回避策は必要ありません。)この項目は、機械学習の世界でますます重要になっています。
(注1)テンソルとは[線形的な量または線形的な幾何概念を一般化したもので、基底を選べば、多次元の配列として表現できるようなものである] 要は整列化、階層化された大量の数値の集まり
(注2)bfloat16は米Google(グーグル)が独自に定義したディープラーニング向けの浮動小数点フォーマット
各用語がざっくりと理解できたところで、『pickle(.ckpt)』と『.safetensors』を見比べてみましょう。
Format | Safe | Zero-copy | Lazy loading | No file size limit | Layout control | Flexibility | Bfloat16 |
pickle | ✖️ | ✖️ | ✖️ | ⭕️ | ✖️ | ⭕️ | ⭕️ |
SafeTensors | ⭕️ | ⭕️ | ⭕️ | ⭕️ | ⭕️ | ✖️ | ⭕️ |
一番大事な点はSafeの評価です。
●「Safe = 安全性」ランダムにダウンロードされたファイルを使用できますか?そして任意のコードを実行しないことを期待できますか?
拡張子『.ckpt』では任意のコードが実行できるため、DOS攻撃などに使われる恐れがあります。このことについてさまざまなところで警告がなされているのです。
対して『.safetensors』では安全性(ランダムにダウンロードされたファイルを使用できますか?そして任意のコードを実行しないことを期待できますか?)の評価が高いとしています。
以上の事から判断すると、
『safetensors』形式なら、ネットで拾ったようなファイルを使用しても脅威にはならないという理解をしても良さそうですね。
さらに『.safetensors』はZero-copy(注3)なためロード時間が短く、さらにLazy loading(分散読み込み)ができる為『.ckpt』に比べて読み込みが早いという特徴があります。
(注3)Zero-copy – コピーを行わない復元方法 通常はデータのデシリアライズ時にメモリ上に展開されるため時間がかかる
safetensoreについてもっと詳しく知りたい方は以下のアドレスからHugging faceで確認してください。
ちょっと小難しい内容なので一回お茶にしましょう。
一息ついたところで、続いて『safetensors』のメリットについて解説していきます!
- Stable Diffusionのプロンプトの見本が知りたい
- 画像生成が思ったようにできない
- 色々なプロンプトを探したい
『.safetensors』のメリット
『safetensors』を使うことについて「Hugging face」で以下の見解が示されています。
これを直訳してみますと、
なぜsafetensorsを使うのですか?
セーフテンサーを使用する理由はいくつかあります。
安全性は、セーフテンサーを使用する一番の理由です。オープンソースとモデル配布が成長するにつれて、ダウンロードしたモデルウェイトに悪意のあるコードが含まれていないことを信頼できることが重要です。セーフテンサーのヘッダーの現在のサイズは、非常に大きなJSONファイルの解析を防ぎます。
スイッチングモデル間のロード速度は、テンソルのゼロコピーを実行するセーフテンサーを使用するもう1つの理由です。重みをCPU(デフォルトの場合)にロードする場合は、ピクルスに比べて特に高速で、重みをGPUに直接ロードする場合、高速ではないにしても、同じように高速です。パフォーマンスの違いは、モデルがすでにロードされている場合にのみ、重みをダウンロードしたり、初めてモデルをロードしたりする場合ではありません。
つまりはsafetensorsを使うメリットは以下のように要約できます。
- 安全性が高い
- 読み込みが早い
Stable Diffusionで画像生成していると、時間がかかります。安全性が高いことに加えて、ロード時間が短縮されるのであれば『.safetensors』を使わない理由が見当たりませんね。
『safetensors』は『.ckpt』の安全な代替手段であり、両方の形式で同じモデルデータがある場合は『safetensors』のデータをダウンロードしましょう。
ただし『safetensors』の形式でも一部不穏な噂が囁かれています。
先ほどの英文から(The current size of the header in safetensors prevents parsing extremely large JSON fils.)
訳すと、「セーフテンソルのヘッダーの現在のサイズは、非常に大きなJSONファイルを解析するのを防ぎます。」なので
JSONファイルをファイルを解析するのを防ぐ、いわゆる”「JSONハイジャック」はできません”と言うことだと理解できます。
『safetensors』は今のところは安全性が高いですが、ずっといつまでも安心とは限らない。そういった認識が良いのではないでしょうか。
「.ckpt」から簡単に『.safetensors』に変換する方法
また、今現在『.ckpt』のモデルを使っている場合、簡単に『.safetensors』に変換する方法があるのでお伝えします。
「.safetensors」に変換するために必要な条件
「.ckpt」から「.safetensors」に変換するために必要な条件は、『インストールするものを全て最新バージョンに更新しておくこと』です!
メインとなるスクリプトをダウンロードしてzipを解凍したら、変換用スクリプトのファイルに保存します。
これで準備は完了です。
「.safetensors」への変換方法
さて準備ができたところで、「.safetensors」への変換方法を説明します。
それは、Stable Diffusionに標準で搭載されている「Checkpoint Merger」を使う方法です。手順は以下の通りです。
- 同じモデルを入れる (拡張子,ckptのモデル)
- safetensorsを有効化
- Mergeするだけ
そうすると、モデルが保存されているファイルの中に新しい『.safetensors』形式のモデルデータが作成されます。
一度リロードすると普通に選択可能になります。そして元の『.ckpt』だったモデルとほぼ変わらずに使用できます。
また、『.ckpt』の時よりも少しだけ早く動作できます。
ただ、この使い方は「Checkpoint Merger」の本来の用途からは外れています。本来は簡単にマージモデルを自作するためのものなので、少し邪道かもしれません。
さらに、Stable Diffusionのモデルデータには単に拡張子『.safetennsors』が付いてるだけでなく、さまざまな物がついているので、その辺もついでに軽く触れておきます。
- pruned – 剪定されたモデル(要は軽量化されている)
- fp16 – 16bit バージョン
- fp32 – 32bitバージョン
Stable Diffusion web ui はデフォルトで16fpで読み込む設定になっています。普通に使う分にはわざわざ32fpの大きいデータをダウンロードする必要はありません。
また、prunedされ軽量化されたモデルでもほぼ問題なく作画できますので、メモリのことを考えると軽い方をダウンロードするのが良いでしょう。
「.safetensors」から変換したモデルの呼び出し方法
「.safetensors」から変換したモデルの呼び出し方法は、パスを指定することでできます。
from diffusers import StableDiffusionPipeline
import torch
MODEL_ID = "model/モデル名"
DEVICE = "デバイス名"
pipe = StableDiffusionPipeline.from_pretrained(MODEL_ID, torch_dtype=torch.float16)
pipe = pipe.to(DEVICE)
prompt = "モデル名 style,プロンプト"
image = pipe(prompt, width=サイズ指定, height=サイズ指定).images[0]
image.save("保存する画像名.png")
サイズを指定しないと、256×256で画像が生成されますのでご注意ください!
こちらのコードを実行すれば、変換したモデルを組み込んだ画像が生成されます。
まとめ
いかがでしたでしょうか?
Stable Diffusionのモデルの拡張子『safetensors』がなぜ推奨されるのか、『.ckpt』との違いなどを解説をしてきました。
今回のまとめとしては、
- 実は「.ckpt」には安全性に関する懸念があった
- 拡張子『.safetensors』に変換すると安全性が高く、しかも生成が早い
ご理解いただけましたでしょうか?
Stable Diffusionは最新の技術のため、今回ご紹介したような細かい部分はなかなか理解が難しいですよね。この記事が少しでも助けとなれば幸いです。
- Stable Diffusionのプロンプトの見本が知りたい
- 画像生成が思ったようにできない
- 色々なプロンプトを探したい