StableDiffusion の LoRA を作成して大量の kakakikikeke を作成してみました
これで永遠に自分が生成できます
環境
- M2 Pro mac mini (macOS 14.5
- Stable Diffusion WebUI 1.9.4
- sd-scripts 0.8.7
学習させる画像
自分の昔の写真(15年くらい前の写真)を使いました
画像サイズはすべて 512x512 です
できれば 20-50 枚くらい準備したほうが精度が良いのですがとりあえずお試しなので 1 枚の画像から 4 枚の異なる背景の画像を用意しました
また少しだけ傾けけたりしています
こうすることで背景を変更させたりすることができます
画像のタグ情報を生成する
画像以外に画像のメタ情報を設定することでよりプロンプトで LoRA を強調することができます
タグ設定には https://github.com/toriato/stable-diffusion-webui-wd14-tagger を使っています
一応抽出できたタグ以外に個別のタグとして「kakakikikeke」を追加しました
LoRa の作成
LoRA の生成には有名な https://github.com/kohya-ss/sd-scripts を使いました
Apple Sillicon 上で動作させるには少し特殊な設定が必要になります
以下に学習時のパラメータを乗せておくので Apple Sillicon 上で動作させたい場合には参考にしてください
xformers を使わなかったり各種 precision の値、最適化関数を AdamW にするあたりが Apple Sillicon 上で動作させるポイントかなと思います
ちなみに画像の学習回数は15回です (ディレクトリに含める値なので以下では設定できない値)
ステップ数が 400 で画像が 4 枚で学習回数が 15 回でだいたい 1 時間くらいで完了します
もっと画像を増やしたりステップを増やしてもいいかもしれません
"LoRA_type": "Standard",
"LyCORIS_preset": "full",
"adaptive_noise_scale": 0,
"additional_parameters": "",
"async_upload": false,
"block_alphas": "",
"block_dims": "",
"block_lr_zero_threshold": "",
"bucket_no_upscale": true,
"bucket_reso_steps": 64,
"bypass_mode": false,
"cache_latents": true,
"cache_latents_to_disk": false,
"caption_dropout_every_n_epochs": 0,
"caption_dropout_rate": 0,
"caption_extension": ".txt",
"clip_skip": 1,
"color_aug": false,
"constrain": 0,
"conv_alpha": 1,
"conv_block_alphas": "",
"conv_block_dims": "",
"conv_dim": 1,
"dataset_config": "",
"debiased_estimation_loss": false,
"decompose_both": false,
"dim_from_weights": false,
"dora_wd": false,
"down_lr_weight": "",
"dynamo_backend": "no",
"dynamo_mode": "default",
"dynamo_use_dynamic": false,
"dynamo_use_fullgraph": false,
"enable_bucket": true,
"epoch": 1,
"extra_accelerate_launch_args": "",
"factor": -1,
"flip_aug": false,
"fp8_base": false,
"full_bf16": false,
"full_fp16": false,
"gpu_ids": "",
"gradient_accumulation_steps": 1,
"gradient_checkpointing": false,
"huber_c": 0.1,
"huber_schedule": "snr",
"huggingface_path_in_repo": "",
"huggingface_repo_id": "",
"huggingface_repo_type": "",
"huggingface_repo_visibility": "",
"huggingface_token": "",
"ip_noise_gamma": 0,
"ip_noise_gamma_random_strength": false,
"keep_tokens": 0,
"learning_rate": 0.0001,
"log_tracker_config": "",
"log_tracker_name": "",
"log_with": "",
"logging_dir": "log",
"loss_type": "l2",
"lr_scheduler": "cosine",
"lr_scheduler_args": "",
"lr_scheduler_num_cycles": 1,
"lr_scheduler_power": 1,
"lr_warmup": 10,
"main_process_port": 0,
"masked_loss": false,
"max_bucket_reso": 2048,
"max_data_loader_n_workers": 0,
"max_grad_norm": 1,
"max_resolution": "512,512",
"max_timestep": 1000,
"max_token_length": 75,
"max_train_epochs": 0,
"max_train_steps": 400,
"mem_eff_attn": false,
"metadata_author": "",
"metadata_description": "",
"metadata_license": "",
"metadata_tags": "",
"metadata_title": "",
"mid_lr_weight": "",
"min_bucket_reso": 256,
"min_snr_gamma": 0,
"min_timestep": 0,
"mixed_precision": "no",
"model_list": "custom",
"module_dropout": 0,
"multi_gpu": false,
"multires_noise_discount": 0.3,
"multires_noise_iterations": 0,
"network_alpha": 1,
"network_dim": 8,
"network_dropout": 0,
"network_weights": "",
"noise_offset": 0,
"noise_offset_random_strength": false,
"noise_offset_type": "Original",
"num_cpu_threads_per_process": 2,
"num_machines": 1,
"num_processes": 1,
"optimizer": "AdamW",
"optimizer_args": "",
"output_dir": "model",
"output_name": "kakakikikeke",
"persistent_data_loader_workers": false,
"pretrained_model_name_or_path": "runwayml/stable-diffusion-v1-5",
"prior_loss_weight": 1,
"random_crop": false,
"rank_dropout": 0,
"rank_dropout_scale": false,
"reg_data_dir": "",
"rescaled": false,
"resume": "",
"resume_from_huggingface": "",
"sample_every_n_epochs": 0,
"sample_every_n_steps": 0,
"sample_prompts": "",
"sample_sampler": "euler_a",
"save_as_bool": false,
"save_every_n_epochs": 1,
"save_every_n_steps": 0,
"save_last_n_steps": 0,
"save_last_n_steps_state": 0,
"save_model_as": "safetensors",
"save_precision": "float",
"save_state": false,
"save_state_on_train_end": false,
"save_state_to_huggingface": false,
"scale_v_pred_loss_like_noise_pred": false,
"scale_weight_norms": 0,
"sdxl": false,
"sdxl_cache_text_encoder_outputs": false,
"sdxl_no_half_vae": false,
"seed": 0,
"shuffle_caption": false,
"stop_text_encoder_training": 0,
"text_encoder_lr": 0.0001,
"train_batch_size": 1,
"train_data_dir": "/Users/kakakikikeke/Downloads/data",
"train_norm": false,
"train_on_input": true,
"training_comment": "",
"unet_lr": 0.0001,
"unit": 1,
"up_lr_weight": "",
"use_cp": false,
"use_scalar": false,
"use_tucker": false,
"v2": false,
"v_parameterization": false,
"v_pred_like_loss": 0,
"vae": "",
"vae_batch_size": 0,
"wandb_api_key": "",
"wandb_run_name": "",
"weighted_captions": false,
"xformers": "none"
}
Stable Diffusion WebUI で生成
あとは sd-webui で生成するだけです
sd-scripts で生成した LoRA を指定しプロンプトで生成します
プロンプトは以下です
realistic, 1boy, solo, male focus, day, teeth, blue eyes, black hair, polka dot shirt, upper body, shirt, smile, portrait, kakakikikeke, simple background <lora:kakakikikeke:1>
また生成時のパラメータは以下だけいじっています
Sampling method -> Euler a
Sampling steps -> 30
Batch count -> 12
で、できあがった画像が以下
手が3本あったりします
考察
おそらくもっと学習データを増やせばもっと精度が良くなると思います
学習させたデータが同じ向きしかないのともともと画像がかなり荒いので生成される画像も少しかけ離れた感じになってしまいます
学習させたデータが上半身しかないのでそれも微妙だった気がします、できれば全身のいろいろな角度の写真が望ましかったかもしれません
また LoRA 学習時のタグ生成ももう少し工夫すればプロンプトにうまく反映できるようになるのかなと思います
あとはプロンプトでリアルな人間を生成する感じのプロンプトを付与すればもっとリアルな感じになるのかなと思います
(masterpiece,best quality:1.4),(8k,raw photo,photo realistic:1.2)
ベースのモデルをデフォルトのやつではなく日本人の顔に特化したモデルに変更してももっと良い結果になるかもしれません
最後に
たった一枚の写真でもここまで生成に反映できるとは思いませんでした
現在の年齢の写真や幼少期の写真も学習させれば生まれてから現在はたまた未来の自分までの画像が作成できるかもしれません
今回環境が M2 mac mini だったので学習させる画像の量に限界があるのがネックです
もし大量の画像を学習させていろんなバリデーションの自分を出力できるようにするのであればそれなりのスペックのマシンか Google Colab あたりで動作させる必要があるかもです