モデルのマージとは?
新しいチェックポイントモデルを用意する方法は、おおざっぱに次の3つに分けられます。
- 0から学習する
- 既存モデルを追加学習する(ファインチューニング / LoRA など)
- 既存モデル同士を混ぜる (マージ)
上2つは専門知識やデータセットの準備が大変ですが、3つ目の「マージ」は、ComfyUI 上で簡単に行うことが出来ます。
チェックポイントを 50:50 で混ぜる
まずはシンプルに2つのモデルを半々に混ぜてみましょう。

{
"id": "32871326-b934-4cc4-887d-9d5f84bf23dc",
"revision": 0,
"last_node_id": 35,
"last_link_id": 37,
"nodes": [
{
"id": 6,
"type": "CLIPTextEncode",
"pos": [
385,
180
],
"size": [
422.84503173828125,
164.31304931640625
],
"flags": {},
"order": 7,
"mode": 0,
"inputs": [
{
"name": "clip",
"type": "CLIP",
"link": 18
}
],
"outputs": [
{
"name": "CONDITIONING",
"type": "CONDITIONING",
"slot_index": 0,
"links": [
4
]
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.76",
"Node name for S&R": "CLIPTextEncode"
},
"widgets_values": [
"beautifull woman,portrait,wearing yellow sweater,looking at viewer, simple white background"
]
},
{
"id": 14,
"type": "CheckpointLoaderSimple",
"pos": [
-321.07180000000005,
230.32569999999998
],
"size": [
315,
98
],
"flags": {},
"order": 0,
"mode": 0,
"inputs": [],
"outputs": [
{
"name": "MODEL",
"type": "MODEL",
"slot_index": 0,
"links": [
10
]
},
{
"name": "CLIP",
"type": "CLIP",
"slot_index": 1,
"links": []
},
{
"name": "VAE",
"type": "VAE",
"slot_index": 2,
"links": []
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.76",
"Node name for S&R": "CheckpointLoaderSimple"
},
"widgets_values": [
"📷-v1.x\\epicphotogasm_z.safetensors"
],
"color": "#323",
"bgcolor": "#535"
},
{
"id": 7,
"type": "CLIPTextEncode",
"pos": [
386,
399
],
"size": [
423.39306640625,
139.30099487304688
],
"flags": {},
"order": 6,
"mode": 0,
"inputs": [
{
"name": "clip",
"type": "CLIP",
"link": 17
}
],
"outputs": [
{
"name": "CONDITIONING",
"type": "CONDITIONING",
"slot_index": 0,
"links": [
6
]
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.76",
"Node name for S&R": "CLIPTextEncode"
},
"widgets_values": [
"text, watermark, worstquality, NSFW"
]
},
{
"id": 5,
"type": "EmptyLatentImage",
"pos": [
493,
614
],
"size": [
315,
106
],
"flags": {},
"order": 1,
"mode": 0,
"inputs": [],
"outputs": [
{
"name": "LATENT",
"type": "LATENT",
"slot_index": 0,
"links": [
2
]
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.76",
"Node name for S&R": "EmptyLatentImage"
},
"widgets_values": [
512,
512,
1
]
},
{
"id": 15,
"type": "CheckpointLoaderSimple",
"pos": [
-321.07180000000005,
400.3257000000004
],
"size": [
315,
98
],
"flags": {},
"order": 2,
"mode": 0,
"inputs": [],
"outputs": [
{
"name": "MODEL",
"type": "MODEL",
"slot_index": 0,
"links": [
12
]
},
{
"name": "CLIP",
"type": "CLIP",
"slot_index": 1,
"links": [
20
]
},
{
"name": "VAE",
"type": "VAE",
"slot_index": 2,
"links": [
36
]
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.76",
"Node name for S&R": "CheckpointLoaderSimple"
},
"widgets_values": [
"😎-v1.x\\meinamix_meinaV11.safetensors"
],
"color": "#323",
"bgcolor": "#535"
},
{
"id": 18,
"type": "Reroute",
"pos": [
221.9282,
420.3257000000004
],
"size": [
75,
26
],
"flags": {},
"order": 5,
"mode": 0,
"inputs": [
{
"name": "",
"type": "*",
"link": 20
}
],
"outputs": [
{
"name": "",
"type": "CLIP",
"slot_index": 0,
"links": [
17,
18,
35
]
}
],
"properties": {
"showOutputText": false,
"horizontal": false
}
},
{
"id": 16,
"type": "VAELoader",
"pos": [
919.3486100676182,
66.26146418591145
],
"size": [
258.6513899323818,
58
],
"flags": {
"collapsed": false
},
"order": 3,
"mode": 0,
"inputs": [],
"outputs": [
{
"name": "VAE",
"type": "VAE",
"links": [
14
]
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.76",
"Node name for S&R": "VAELoader"
},
"widgets_values": [
"vae-ft-mse-840000-ema-pruned.safetensors"
]
},
{
"id": 8,
"type": "VAEDecode",
"pos": [
1210.605919854539,
186
],
"size": [
176.94214876033038,
46
],
"flags": {},
"order": 10,
"mode": 0,
"inputs": [
{
"name": "samples",
"type": "LATENT",
"link": 7
},
{
"name": "vae",
"type": "VAE",
"link": 14
}
],
"outputs": [
{
"name": "IMAGE",
"type": "IMAGE",
"slot_index": 0,
"links": [
37
]
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.76",
"Node name for S&R": "VAEDecode"
},
"widgets_values": []
},
{
"id": 32,
"type": "SaveImage",
"pos": [
1420.1539884694082,
186
],
"size": [
436.27,
503.5300000000001
],
"flags": {},
"order": 11,
"mode": 0,
"inputs": [
{
"name": "images",
"type": "IMAGE",
"link": 37
}
],
"outputs": [],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.76"
},
"widgets_values": [
"ComfyUI"
]
},
{
"id": 3,
"type": "KSampler",
"pos": [
863,
186
],
"size": [
315,
262
],
"flags": {},
"order": 9,
"mode": 0,
"inputs": [
{
"name": "model",
"type": "MODEL",
"link": 13
},
{
"name": "positive",
"type": "CONDITIONING",
"link": 4
},
{
"name": "negative",
"type": "CONDITIONING",
"link": 6
},
{
"name": "latent_image",
"type": "LATENT",
"link": 2
}
],
"outputs": [
{
"name": "LATENT",
"type": "LATENT",
"slot_index": 0,
"links": [
7
]
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.76",
"Node name for S&R": "KSampler"
},
"widgets_values": [
12345,
"fixed",
20,
8,
"euler",
"normal",
1
]
},
{
"id": 10,
"type": "ModelMergeSimple",
"pos": [
43.928200000000004,
315.3257000000004
],
"size": [
257.3212268066404,
78
],
"flags": {},
"order": 4,
"mode": 0,
"inputs": [
{
"name": "model1",
"type": "MODEL",
"link": 10
},
{
"name": "model2",
"type": "MODEL",
"link": 12
}
],
"outputs": [
{
"name": "MODEL",
"type": "MODEL",
"slot_index": 0,
"links": [
13,
34
]
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.76",
"Node name for S&R": "ModelMergeSimple"
},
"widgets_values": [
0.5
],
"color": "#232",
"bgcolor": "#353"
},
{
"id": 31,
"type": "CheckpointSave",
"pos": [
403.19000776666985,
787.3953004833538
],
"size": [
315,
98
],
"flags": {},
"order": 8,
"mode": 4,
"inputs": [
{
"name": "model",
"type": "MODEL",
"link": 34
},
{
"name": "clip",
"type": "CLIP",
"link": 35
},
{
"name": "vae",
"type": "VAE",
"link": 36
}
],
"outputs": [],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.76",
"Node name for S&R": "CheckpointSave"
},
"widgets_values": [
"checkpoints/ComfyUI"
],
"color": "#432",
"bgcolor": "#653"
}
],
"links": [
[
2,
5,
0,
3,
3,
"LATENT"
],
[
4,
6,
0,
3,
1,
"CONDITIONING"
],
[
6,
7,
0,
3,
2,
"CONDITIONING"
],
[
7,
3,
0,
8,
0,
"LATENT"
],
[
10,
14,
0,
10,
0,
"MODEL"
],
[
12,
15,
0,
10,
1,
"MODEL"
],
[
13,
10,
0,
3,
0,
"MODEL"
],
[
14,
16,
0,
8,
1,
"VAE"
],
[
17,
18,
0,
7,
0,
"CLIP"
],
[
18,
18,
0,
6,
0,
"CLIP"
],
[
20,
15,
1,
18,
0,
"*"
],
[
34,
10,
0,
31,
0,
"MODEL"
],
[
35,
18,
0,
31,
1,
"CLIP"
],
[
36,
15,
2,
31,
2,
"VAE"
],
[
37,
8,
0,
32,
0,
"IMAGE"
]
],
"groups": [],
"config": {},
"extra": {
"0246.VERSION": [
0,
0,
4
],
"ds": {
"scale": 0.8264462809917362,
"offset": [
421.07180000000005,
33.73853581408855
]
},
"frontendVersion": "1.35.0",
"VHS_latentpreview": false,
"VHS_latentpreviewrate": 0,
"VHS_MetadataImage": true,
"VHS_KeepIntermediate": true
},
"version": 0.4
}
この workflow では、ModelMergeSimple ノードを使って 2 つのチェックポイントを 1:1 でマージしています。
- 🟩
ModelMergeSimpleは 2 つのMODEL入力を受け取り、指定した比率で重みを線形補間した新しいモデルを出力します。ratio=0.5のとき、「モデルAとモデルBを半分ずつ混ぜたもの」と考えてよいです。
- 出力された
MODELをそのままKSamplerに繋げれば、中間モデルを簡単に試せます。- 雑にアニメ系とリアル系を混ぜただけですが、2.5次元のような表現が出来ているのには驚かされますね。

- マージ結果が気に入ったら、
CheckpointSaveノードにつないでチェックポイントとして保存します。(上のworkflowではバイパスしています。)- 保存先はデフォルトでは
ComfyUI/output/checkpoints/(Windows ポータブル版の標準設定)です。
- 保存先はデフォルトでは
モデルマージの弱点
2つのモデルを混ぜても、パラメータの数自体は「モデル一つ分」のままです。 何か新しい力を足している一方で、その分だけ元の得意分野の表現力は削られている、と考えることもできます。
キャラを描くのが得意なモデルと、風景を描くのが得意なモデルを半分ずつ混ぜると、キャラも背景もどっちつかずなモデルが出来ることになります。
これではあまり役に立たなさそうですね… なにか良い方法はないでしょうか?
階層マージ
Stable Diffusion の「ノイズから画像を復元する本体」は U 字の形をしたネットワーク「U-Net」というものです。 これは階段状になっているのですが、いくつかの研究から、層毎に役割が違うらしいということが分かっています。(cf. P+)
- 浅い層 … テクスチャ・色・細かいパターン寄り
- 深い層 … 形・構図・レイアウト寄り
ということは、モデルBの色味だけ欲しいときは、浅い層のみをモデル B 寄りにマージすれば良さそうです。 これが階層マージの仕組みです。

{
"id": "32871326-b934-4cc4-887d-9d5f84bf23dc",
"revision": 0,
"last_node_id": 36,
"last_link_id": 41,
"nodes": [
{
"id": 6,
"type": "CLIPTextEncode",
"pos": [
385,
180
],
"size": [
422.84503173828125,
164.31304931640625
],
"flags": {},
"order": 7,
"mode": 0,
"inputs": [
{
"name": "clip",
"type": "CLIP",
"link": 18
}
],
"outputs": [
{
"name": "CONDITIONING",
"type": "CONDITIONING",
"slot_index": 0,
"links": [
4
]
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.76",
"Node name for S&R": "CLIPTextEncode"
},
"widgets_values": [
"beautifull woman,portrait,wearing yellow sweater,looking at viewer, simple white background"
]
},
{
"id": 7,
"type": "CLIPTextEncode",
"pos": [
386,
399
],
"size": [
423.39306640625,
139.30099487304688
],
"flags": {},
"order": 6,
"mode": 0,
"inputs": [
{
"name": "clip",
"type": "CLIP",
"link": 17
}
],
"outputs": [
{
"name": "CONDITIONING",
"type": "CONDITIONING",
"slot_index": 0,
"links": [
6
]
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.76",
"Node name for S&R": "CLIPTextEncode"
},
"widgets_values": [
"text, watermark, worstquality, NSFW"
]
},
{
"id": 5,
"type": "EmptyLatentImage",
"pos": [
493,
614
],
"size": [
315,
106
],
"flags": {},
"order": 0,
"mode": 0,
"inputs": [],
"outputs": [
{
"name": "LATENT",
"type": "LATENT",
"slot_index": 0,
"links": [
2
]
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.76",
"Node name for S&R": "EmptyLatentImage"
},
"widgets_values": [
512,
512,
1
]
},
{
"id": 18,
"type": "Reroute",
"pos": [
221.9282,
420.3257000000004
],
"size": [
75,
26
],
"flags": {},
"order": 5,
"mode": 0,
"inputs": [
{
"name": "",
"type": "*",
"link": 20
}
],
"outputs": [
{
"name": "",
"type": "CLIP",
"slot_index": 0,
"links": [
17,
18,
35
]
}
],
"properties": {
"showOutputText": false,
"horizontal": false
}
},
{
"id": 16,
"type": "VAELoader",
"pos": [
919.3486100676182,
66.26146418591145
],
"size": [
258.6513899323818,
58
],
"flags": {
"collapsed": false
},
"order": 1,
"mode": 0,
"inputs": [],
"outputs": [
{
"name": "VAE",
"type": "VAE",
"links": [
14
]
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.76",
"Node name for S&R": "VAELoader"
},
"widgets_values": [
"vae-ft-mse-840000-ema-pruned.safetensors"
]
},
{
"id": 8,
"type": "VAEDecode",
"pos": [
1210.605919854539,
186
],
"size": [
176.94214876033038,
46
],
"flags": {},
"order": 10,
"mode": 0,
"inputs": [
{
"name": "samples",
"type": "LATENT",
"link": 7
},
{
"name": "vae",
"type": "VAE",
"link": 14
}
],
"outputs": [
{
"name": "IMAGE",
"type": "IMAGE",
"slot_index": 0,
"links": [
37
]
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.76",
"Node name for S&R": "VAEDecode"
},
"widgets_values": []
},
{
"id": 32,
"type": "SaveImage",
"pos": [
1420.1539884694082,
186
],
"size": [
436.27,
503.5300000000001
],
"flags": {},
"order": 11,
"mode": 0,
"inputs": [
{
"name": "images",
"type": "IMAGE",
"link": 37
}
],
"outputs": [],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.76"
},
"widgets_values": [
"ComfyUI"
]
},
{
"id": 3,
"type": "KSampler",
"pos": [
863,
186
],
"size": [
315,
262
],
"flags": {},
"order": 9,
"mode": 0,
"inputs": [
{
"name": "model",
"type": "MODEL",
"link": 40
},
{
"name": "positive",
"type": "CONDITIONING",
"link": 4
},
{
"name": "negative",
"type": "CONDITIONING",
"link": 6
},
{
"name": "latent_image",
"type": "LATENT",
"link": 2
}
],
"outputs": [
{
"name": "LATENT",
"type": "LATENT",
"slot_index": 0,
"links": [
7
]
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.76",
"Node name for S&R": "KSampler"
},
"widgets_values": [
12345,
"fixed",
20,
8,
"euler",
"normal",
1
]
},
{
"id": 31,
"type": "CheckpointSave",
"pos": [
403.19000776666985,
787.3953004833538
],
"size": [
315,
98
],
"flags": {},
"order": 8,
"mode": 4,
"inputs": [
{
"name": "model",
"type": "MODEL",
"link": 41
},
{
"name": "clip",
"type": "CLIP",
"link": 35
},
{
"name": "vae",
"type": "VAE",
"link": 36
}
],
"outputs": [],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.76",
"Node name for S&R": "CheckpointSave"
},
"widgets_values": [
"checkpoints/ComfyUI"
],
"color": "#432",
"bgcolor": "#653"
},
{
"id": 14,
"type": "CheckpointLoaderSimple",
"pos": [
-321.07180000000005,
230.32569999999998
],
"size": [
315,
98
],
"flags": {},
"order": 2,
"mode": 0,
"inputs": [],
"outputs": [
{
"name": "MODEL",
"type": "MODEL",
"slot_index": 0,
"links": [
38
]
},
{
"name": "CLIP",
"type": "CLIP",
"slot_index": 1,
"links": []
},
{
"name": "VAE",
"type": "VAE",
"slot_index": 2,
"links": []
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.76",
"Node name for S&R": "CheckpointLoaderSimple"
},
"widgets_values": [
"📷-v1.x\\epicphotogasm_z.safetensors"
],
"color": "#323",
"bgcolor": "#535"
},
{
"id": 15,
"type": "CheckpointLoaderSimple",
"pos": [
-321.07180000000005,
400.3257000000004
],
"size": [
315,
98
],
"flags": {},
"order": 3,
"mode": 0,
"inputs": [],
"outputs": [
{
"name": "MODEL",
"type": "MODEL",
"slot_index": 0,
"links": [
39
]
},
{
"name": "CLIP",
"type": "CLIP",
"slot_index": 1,
"links": [
20
]
},
{
"name": "VAE",
"type": "VAE",
"slot_index": 2,
"links": [
36
]
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.76",
"Node name for S&R": "CheckpointLoaderSimple"
},
"widgets_values": [
"😎-v1.x\\meinamix_meinaV11.safetensors"
],
"color": "#323",
"bgcolor": "#535"
},
{
"id": 36,
"type": "ModelMergeBlocks",
"pos": [
40.11001818181825,
261.92937964045683
],
"size": [
256.81818181818176,
126
],
"flags": {},
"order": 4,
"mode": 0,
"inputs": [
{
"name": "model1",
"type": "MODEL",
"link": 38
},
{
"name": "model2",
"type": "MODEL",
"link": 39
}
],
"outputs": [
{
"name": "MODEL",
"type": "MODEL",
"slot_index": 0,
"links": [
40,
41
]
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.76",
"Node name for S&R": "ModelMergeBlocks"
},
"widgets_values": [
1,
1,
0.5
],
"color": "#232",
"bgcolor": "#353"
}
],
"links": [
[
2,
5,
0,
3,
3,
"LATENT"
],
[
4,
6,
0,
3,
1,
"CONDITIONING"
],
[
6,
7,
0,
3,
2,
"CONDITIONING"
],
[
7,
3,
0,
8,
0,
"LATENT"
],
[
14,
16,
0,
8,
1,
"VAE"
],
[
17,
18,
0,
7,
0,
"CLIP"
],
[
18,
18,
0,
6,
0,
"CLIP"
],
[
20,
15,
1,
18,
0,
"*"
],
[
35,
18,
0,
31,
1,
"CLIP"
],
[
36,
15,
2,
31,
2,
"VAE"
],
[
37,
8,
0,
32,
0,
"IMAGE"
],
[
38,
14,
0,
36,
0,
"MODEL"
],
[
39,
15,
0,
36,
1,
"MODEL"
],
[
40,
36,
0,
3,
0,
"MODEL"
],
[
41,
36,
0,
31,
0,
"MODEL"
]
],
"groups": [],
"config": {},
"extra": {
"0246.VERSION": [
0,
0,
4
],
"ds": {
"scale": 1,
"offset": [
421.07180000000005,
33.73853581408855
]
},
"frontendVersion": "1.35.0",
"VHS_latentpreview": false,
"VHS_latentpreviewrate": 0,
"VHS_MetadataImage": true,
"VHS_KeepIntermediate": true
},
"version": 0.4
}
ComfyUI の標準ノード ModelMergeBlocks は、U-Net 全体を大まかに IN / MID / OUT の3ブロックに分けて比率を指定できます。
IN… 入力側のブロック(比較的浅い層)MID… 真ん中のボトルネック付近OUT… 出力側のブロック(比較的深い層)
実際にはUNetは何十階層もあり、コミュニティの研究により、どの層が何に影響しそうか?というのは大体分かってきています。
ComfyUIには、ModelMergeSD1/ModelMergeSDXLといった、一層ずつ比率を調整できるノードもあります。が、これを使いこなすのは職人芸でしょう……
LoRA のマージ
LoRA は「元のモデルにあとから足せる差分パッチ」のようなものなので、チェックポイント同士と同じく、LoRA 同士も足し合わせてマージできます。
それ以前に、LoRA を 1 個読み込んでいるだけでも、裏側では「ベースのチェックポイントに LoRA の差分を足し込んで、その場で合成モデルを作っている」ような挙動になっています。
つまり、checkpoint に LoRA を適用している時点で、我々はすでに広い意味での“マージっぽいこと”をずっとやっていたわけですね (*゚∀゚)
差分LoRA
ここまでの話は「モデル同士を混ぜて新しいチェックポイントを作る」方向でしたが、逆にチェックポイントから「差分だけ」を LoRA として抜き出すという発想もあります。
- ベースモデル
Base(例:v1-5-pruned) - カスタムチェックポイント
Base+X(例:特定キャラや絵柄を学習済みのモデル)
このとき、Base+X はざっくり「ベース + 追加スタイルX」とみなせます。
ここから「X の部分だけ」を取り出して LoRA にしてしまう、というのが 差分LoRA です。
-
Base+X - Base = X (← LoRAにする差分)
-
- その差分を LoRA 形式に圧縮する
workflow

{
"id": "5e4243dd-542f-476b-af93-165a65887050",
"revision": 0,
"last_node_id": 7,
"last_link_id": 12,
"nodes": [
{
"id": 1,
"type": "CheckpointLoaderSimple",
"pos": [
348.72229872501026,
621.8931414126628
],
"size": [
315,
98
],
"flags": {},
"order": 0,
"mode": 0,
"inputs": [],
"outputs": [
{
"name": "MODEL",
"type": "MODEL",
"slot_index": 0,
"links": [
10
]
},
{
"name": "CLIP",
"type": "CLIP",
"slot_index": 1,
"links": [
8
]
},
{
"name": "VAE",
"type": "VAE",
"slot_index": 2,
"links": []
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.76",
"Node name for S&R": "CheckpointLoaderSimple"
},
"widgets_values": [
"😎-v1.x\\meinamix_meinaV11.safetensors"
],
"color": "#323",
"bgcolor": "#535"
},
{
"id": 3,
"type": "ModelMergeSubtract",
"pos": [
734.7117876431089,
621.8931414126628
],
"size": [
210,
78
],
"flags": {},
"order": 2,
"mode": 0,
"inputs": [
{
"name": "model1",
"type": "MODEL",
"link": 10
},
{
"name": "model2",
"type": "MODEL",
"link": 11
}
],
"outputs": [
{
"name": "MODEL",
"type": "MODEL",
"links": [
4
]
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.76",
"Node name for S&R": "ModelMergeSubtract"
},
"widgets_values": [
1
],
"color": "#232",
"bgcolor": "#353"
},
{
"id": 2,
"type": "CheckpointLoaderSimple",
"pos": [
348.72229872501026,
781.0283805094396
],
"size": [
319.03827585779754,
98
],
"flags": {},
"order": 1,
"mode": 0,
"inputs": [],
"outputs": [
{
"name": "MODEL",
"type": "MODEL",
"links": [
11
]
},
{
"name": "CLIP",
"type": "CLIP",
"links": [
9
]
},
{
"name": "VAE",
"type": "VAE",
"links": null
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.76",
"Node name for S&R": "CheckpointLoaderSimple"
},
"widgets_values": [
"v1-5-pruned-emaonly-fp16.safetensors"
],
"color": "#323",
"bgcolor": "#535"
},
{
"id": 5,
"type": "LoraSave",
"pos": [
997.1539034546028,
685.3256206111878
],
"size": [
210,
150
],
"flags": {},
"order": 4,
"mode": 0,
"inputs": [
{
"name": "model_diff",
"shape": 7,
"type": "MODEL",
"link": 4
},
{
"name": "text_encoder_diff",
"shape": 7,
"type": "CLIP",
"link": 12
}
],
"outputs": [],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.76"
},
"widgets_values": [
"loras/meinamix-SD1.5",
32,
"standard",
true
]
},
{
"id": 7,
"type": "CLIPMergeSubtract",
"pos": [
735.1937942440574,
781.0283805094396
],
"size": [
210,
78
],
"flags": {},
"order": 3,
"mode": 0,
"inputs": [
{
"name": "clip1",
"type": "CLIP",
"link": 8
},
{
"name": "clip2",
"type": "CLIP",
"link": 9
}
],
"outputs": [
{
"name": "CLIP",
"type": "CLIP",
"links": [
12
]
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.76",
"Node name for S&R": "CLIPMergeSubtract"
},
"widgets_values": [
1
],
"color": "#432",
"bgcolor": "#653"
}
],
"links": [
[
4,
3,
0,
5,
0,
"MODEL"
],
[
8,
1,
1,
7,
0,
"CLIP"
],
[
9,
2,
1,
7,
1,
"CLIP"
],
[
10,
1,
0,
3,
0,
"MODEL"
],
[
11,
2,
0,
3,
1,
"MODEL"
],
[
12,
7,
0,
5,
1,
"CLIP"
]
],
"groups": [],
"config": {},
"extra": {
"ds": {
"scale": 1.0755189070090265,
"offset": [
-33.012469276095786,
-259.6941245825167
]
},
"frontendVersion": "1.35.0",
"VHS_latentpreview": false,
"VHS_latentpreviewrate": 0,
"VHS_MetadataImage": true,
"VHS_KeepIntermediate": true
},
"version": 0.4
}
- 🟩
ModelMergeSubtractノードの差分を取りたいモデルを入力します。model1 - model2です。
- 🟨 上では使っていませんでしたが、テキストエンコーダの差分を取る
CLIPMergeSubtractノードというのもあります。- テキストエンコーダはかなりシビアなので悪化する可能性もあります。
Extract and Save LoraノードでLoRAとして保存します。rankは大きければ大きいほど忠実に差分を保存しますが、その分モデルサイズは大きくなります。- 目安としては、スタイル差分なら 8〜32 あたり、かなり違うモデルからガッツリ差分を取りたいときは 64 以上、といった使い分けが多い印象です。
- 抽出されたLoRAモデルは、
\ComfyUI\output\lorasに保存されています。
差分LoRAのテスト

{
"id": "8b9f7796-0873-4025-be3c-0f997f67f866",
"revision": 0,
"last_node_id": 11,
"last_link_id": 19,
"nodes": [
{
"id": 8,
"type": "VAEDecode",
"pos": [
1209,
188
],
"size": [
210,
46
],
"flags": {},
"order": 7,
"mode": 0,
"inputs": [
{
"name": "samples",
"type": "LATENT",
"link": 7
},
{
"name": "vae",
"type": "VAE",
"link": 10
}
],
"outputs": [
{
"name": "IMAGE",
"type": "IMAGE",
"slot_index": 0,
"links": [
9
]
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.33",
"Node name for S&R": "VAEDecode"
},
"widgets_values": []
},
{
"id": 9,
"type": "SaveImage",
"pos": [
1451,
189
],
"size": [
354.2876035004722,
433.23967321788405
],
"flags": {},
"order": 8,
"mode": 0,
"inputs": [
{
"name": "images",
"type": "IMAGE",
"link": 9
}
],
"outputs": [],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.33"
},
"widgets_values": [
"ComfyUI"
]
},
{
"id": 5,
"type": "EmptyLatentImage",
"pos": [
582.1350317382813,
606.5799999999999
],
"size": [
244.81999999999994,
106
],
"flags": {},
"order": 0,
"mode": 0,
"inputs": [],
"outputs": [
{
"name": "LATENT",
"type": "LATENT",
"slot_index": 0,
"links": [
2
]
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.33",
"Node name for S&R": "EmptyLatentImage"
},
"widgets_values": [
512,
512,
1
]
},
{
"id": 6,
"type": "CLIPTextEncode",
"pos": [
415,
186
],
"size": [
411.95503173828126,
151.0030493164063
],
"flags": {},
"order": 4,
"mode": 0,
"inputs": [
{
"name": "clip",
"type": "CLIP",
"link": 18
}
],
"outputs": [
{
"name": "CONDITIONING",
"type": "CONDITIONING",
"slot_index": 0,
"links": [
4
]
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.33",
"Node name for S&R": "CLIPTextEncode"
},
"widgets_values": [
"beautifull woman,portrait,wearing yellow sweater,looking at viewer, simple white background"
]
},
{
"id": 7,
"type": "CLIPTextEncode",
"pos": [
416.1970166015625,
392.37848510742185
],
"size": [
410.75801513671877,
158.82607910156253
],
"flags": {},
"order": 5,
"mode": 0,
"inputs": [
{
"name": "clip",
"type": "CLIP",
"link": 19
}
],
"outputs": [
{
"name": "CONDITIONING",
"type": "CONDITIONING",
"slot_index": 0,
"links": [
6
]
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.33",
"Node name for S&R": "CLIPTextEncode"
},
"widgets_values": [
"text, watermark, worstquality, NSFW"
]
},
{
"id": 4,
"type": "CheckpointLoaderSimple",
"pos": [
-236.34725770097657,
296.0522226002962
],
"size": [
315,
98
],
"flags": {},
"order": 1,
"mode": 0,
"inputs": [],
"outputs": [
{
"name": "MODEL",
"type": "MODEL",
"slot_index": 0,
"links": [
11
]
},
{
"name": "CLIP",
"type": "CLIP",
"slot_index": 1,
"links": [
12
]
},
{
"name": "VAE",
"type": "VAE",
"slot_index": 2,
"links": []
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.33",
"Node name for S&R": "CheckpointLoaderSimple"
},
"widgets_values": [
"v1-5-pruned-emaonly-fp16.safetensors"
]
},
{
"id": 11,
"type": "LoraLoader",
"pos": [
103.33290758827951,
296.0522226002962
],
"size": [
247.56574004507888,
126
],
"flags": {},
"order": 3,
"mode": 0,
"inputs": [
{
"name": "model",
"type": "MODEL",
"link": 11
},
{
"name": "clip",
"type": "CLIP",
"link": 12
}
],
"outputs": [
{
"name": "MODEL",
"type": "MODEL",
"links": [
15
]
},
{
"name": "CLIP",
"type": "CLIP",
"links": [
18,
19
]
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.76",
"Node name for S&R": "LoraLoader"
},
"widgets_values": [
"meinamix-SD1.5_00002_.safetensors",
1,
1
],
"color": "#232",
"bgcolor": "#353"
},
{
"id": 3,
"type": "KSampler",
"pos": [
863,
186
],
"size": [
315,
262
],
"flags": {},
"order": 6,
"mode": 0,
"inputs": [
{
"name": "model",
"type": "MODEL",
"link": 15
},
{
"name": "positive",
"type": "CONDITIONING",
"link": 4
},
{
"name": "negative",
"type": "CONDITIONING",
"link": 6
},
{
"name": "latent_image",
"type": "LATENT",
"link": 2
}
],
"outputs": [
{
"name": "LATENT",
"type": "LATENT",
"slot_index": 0,
"links": [
7
]
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.33",
"Node name for S&R": "KSampler"
},
"widgets_values": [
1234,
"fixed",
20,
8,
"euler",
"normal",
1
]
},
{
"id": 10,
"type": "VAELoader",
"pos": [
896.9256198347109,
69.4815990090115
],
"size": [
281.0743801652891,
58
],
"flags": {},
"order": 2,
"mode": 0,
"inputs": [],
"outputs": [
{
"name": "VAE",
"type": "VAE",
"links": [
10
]
}
],
"properties": {
"cnr_id": "comfy-core",
"ver": "0.3.76",
"Node name for S&R": "VAELoader"
},
"widgets_values": [
"vae-ft-mse-840000-ema-pruned.safetensors"
]
}
],
"links": [
[
2,
5,
0,
3,
3,
"LATENT"
],
[
4,
6,
0,
3,
1,
"CONDITIONING"
],
[
6,
7,
0,
3,
2,
"CONDITIONING"
],
[
7,
3,
0,
8,
0,
"LATENT"
],
[
9,
8,
0,
9,
0,
"IMAGE"
],
[
10,
10,
0,
8,
1,
"VAE"
],
[
11,
4,
0,
11,
0,
"MODEL"
],
[
12,
4,
1,
11,
1,
"CLIP"
],
[
15,
11,
0,
3,
0,
"MODEL"
],
[
18,
11,
1,
6,
0,
"CLIP"
],
[
19,
11,
1,
7,
0,
"CLIP"
]
],
"groups": [],
"config": {},
"extra": {
"ds": {
"scale": 0.9090909090909092,
"offset": [
335.24725770097655,
30.518400990988496
]
},
"frontendVersion": "1.35.0",
"VHS_latentpreview": false,
"VHS_latentpreviewrate": 0,
"VHS_MetadataImage": true,
"VHS_KeepIntermediate": true
},
"version": 0.4
}
- 今回は差分が大きかったので、LoRAを適用しただけで完璧に再現できるわけではないですが、SD1.5ながら、それっぽい画像を生成できるようになっていますね。