Stable Diffusion学习(LoRA微调)_stable diffusion微调
由于训练和推理都需要较大显存和算力,因此此后文章都围绕linux进行学习开发,便于大家花点小钱租个服务器就可以复现学习理解!(在这里许愿希望自己可以全部学完,立个flag!)
实验准备
一 、服务器
跑实验当然要租服务器了,在这里我推荐大家使用autodl(学生认证可以打折,是我用起来比较顺手的了,各种环境、数据集很全,虽然有点小贵)(这里会有广子吗,老板看到可以结一下)
还有一个便宜点的,但是我没怎么用过,是dbcloud,(这个也可以结一下)
至于服务器的选择,我的建议挑显存内存大的,算力不够顶多就是跑的慢点,要是训练推理的时候显存不够,那可就白忙活了,我用的是vGPU-32G,显存比较大,也比较便宜。
二、环境部署
1.diffusers
我们先用diffusers内置函数进行微调,也间接学习一下,首先是克隆
git clone https://github.com/huggingface/diffusers.git
2.虚拟环境
跑实验当然免不了虚拟环境,我们创建一个虚拟环境
conda create -n dif python=3.10
创建完成之后需要初始化一下终端
conda init
然后重启终端(叉掉重新开一个)激活环境
conda activate dif
3.安装各种包
需要安装的有点多,但是时间不会太久
cd diffuserspip install -e .cd examples/dreamboothpip install -r requirements_sdxl.txtpip install bitsandbytes xformersaccelerate config default
三、Stable Diffusion
我们可以简单调用huggingface模型来生成一张图像,我这里使用的是stable-diffusion-v1-5,可以去huggingface上面找任何一个模型进行调用生成
首先要挂上autodl的学术加速:
source /etc/network_turbo
建议使用huggingface的镜像(避免加载模型消耗大量时间):
export HF_ENDPOINT=https://hf-mirror.com
(可选)更改环境变量--huggingface模型缓存位置
# modelsope下载模型echo \'export MODELSCOPE_CACHE=\"/root/autodl-tmp/model\"\' >> ~/.bashrc# huggingface环境变量echo \'export HF_HOME=\"/root/autodl-tmp/model\"\' >> ~/.bashrcecho \'export HUGGINGFACE_HUB_CACHE=\"/root/autodl-tmp/model\"\' >> ~/.bashrc# 使更改生效source ~/.bashrc
登录huggingface:
# 安装 huggingface_hub 库pip install huggingface_hub#登录 Hugging Facehuggingface-cli login
出现这个界面之后输入huggingface的token就可以了
token的获取:Hugging Face – The AI community building the future.点个人头像下面的Access Tokens进行获取,create一个新token,配置默认就行可以
再生成 :
from diffusers import DiffusionPipelineimport torch# 加载并配置模型pipeline = DiffusionPipeline.from_pretrained(\"stable-diffusion-v1-5/stable-diffusion-v1-5\", torch_dtype=torch.float16)pipeline.to(\"cuda\")# 生成图片image = pipeline(\"A cat is basking in the sun\").images[0]# 保存图片image.save(\"test.png\")
效果如下,大家可以去尝试更多更新的模型,效果会更好,stable diffusion v1-5有点老了
四、微调
在examples/dreambooth目录下,我们可以看到非常多的文件,其中sd3是针对stable diffusionv3进行微调,sdxl是针对stable-diffusion-xl-base-1.0模型进行微调,至于LoRA和dreambooth这两种方法,后面有时间再写一篇文章(预留链接)
然后我们需要写一个脚本去执行代码,建议大家执行之前先去看一下代码的命令行参数,方便熟悉了解每个参数的作用
下面是一个简单的bash样例,可以直接新建一个fine-tuning.bash文件粘贴
export MODEL_NAME=\"stabilityai/stable-diffusion-xl-base-1.0\"export INSTANCE_DIR=\"test\"export OUTPUT_DIR=\"lora-trained-xl\"export VAE_PATH=\"madebyollin/sdxl-vae-fp16-fix\"accelerate launch train_dreambooth_lora_sdxl.py \\ --pretrained_model_name_or_path=$MODEL_NAME \\ --instance_data_dir=$INSTANCE_DIR \\ --pretrained_vae_model_name_or_path=$VAE_PATH \\ --output_dir=$OUTPUT_DIR \\ --mixed_precision=\"fp16\" \\ --instance_prompt=\"\" \\ --resolution=1024 \\ --train_batch_size=1 \\ --gradient_accumulation_steps=4 \\ --learning_rate=1e-4 \\ --lr_scheduler=\"constant\" \\ --lr_warmup_steps=0 \\ --max_train_steps=5 \\ --validation_prompt=\"\" \\ --validation_epochs=25 \\ --seed=\"0\" \\
-
accelerate
是 Hugging Face 提供的一个工具,专为加速机器学习模型训练而设计,特别是分布式训练(比如多GPU训练)。accelerate launch
用于启动分布式训练任务,它会根据硬件配置自动处理分布式训练,混合精度训练等复杂设置 -
--pretrained_model_name_or_path=$MODEL_NAME
:指定使用的预训练模型。 -
--instance_data_dir=$INSTANCE_DIR
:指定包含实例图像数据的目录。 -
--pretrained_vae_model_name_or_path=$VAE_PATH
:指定VAE模型的路径。 -
--output_dir=$OUTPUT_DIR
:设置输出目录,保存训练后的模型。 -
--mixed_precision=\"fp16\"
:启用混合精度训练,使用fp16
精度,这可以减少内存使用并加速训练。 -
--instance_prompt=\"\"
:为训练提供描述实例图像的提示词,帮助模型学习特定实例(根据你的图片自己添加)。 -
--resolution=1024
:设置图像的分辨率为1024x1024。 -
--train_batch_size=1
:每个设备的训练批次大小为1。 -
--gradient_accumulation_steps=4
:在执行梯度更新之前累积4步梯度,用于降低显存需求。 -
--learning_rate=1e-4
:设置学习率为1e-4
。 -
--lr_scheduler=\"constant\"
:使用常数学习率调度器。 -
--lr_warmup_steps=0
:学习率预热步骤为0,表示没有预热阶段。 -
--max_train_steps=500
:设置最大训练步数为500步。 -
--validation_prompt=\"\"
:在验证阶段使用的提示语,这有助于确认模型是否学会了特定的概念(根据你的图片自己添加) -
--validation_epochs=25
:每隔25个epoch进行一次验证。 -
--seed=\"0\"
:设置随机种子为0,以确保训练的可重现性。
开始微调:
bash fine-tuning.sh
五、生成
微调之后的模型文件会保存在lora-trained-xl文件夹下,我们可以利用它来生成看一下效果,或者使用stable diffusion UI进行可视化展示、负责、定制化推理(里面一些默认参数要根据自己的情况改一下):
import torchfrom diffusers import FluxPipelineimport osfrom PIL import Imagedef generate_flux_lora_image( prompt, output_dir=\"output\", base_model_path=\"black-forest-labs/FLUX.1-dev\", lora_model_path=\"trained-flux\", negative_prompt=\"blurry, low quality, cartoon, anime, illustration\", num_images=1, start_seed=42, num_inference_steps=30, guidance_scale=7.0, filename_prefix=\"flux_lora_generated\"): \"\"\" 使用FLUX模型和LoRA权重生成图像 参数: prompt (str): 生成图像的提示词 output_dir (str): 输出图像的目录 base_model_path (str): 基础FLUX模型路径 lora_model_path (str): LoRA模型目录路径 negative_prompt (str): 负面提示词 num_images (int): 要生成的图像数量 start_seed (int): 起始随机种子 num_inference_steps (int): 推理步骤数 guidance_scale (float): 提示词引导强度 filename_prefix (str): 输出文件名前缀 返回: list: 生成的图像文件路径列表 \"\"\" # 确保输出目录存在 os.makedirs(output_dir, exist_ok=True) # 定义LoRA权重文件路径 lora_weights_file = os.path.join(lora_model_path, \"pytorch_lora_weights.safetensors\") # 检查权重文件是否存在 if not os.path.exists(lora_weights_file): raise FileNotFoundError(f\"错误: LoRA权重文件 {lora_weights_file} 不存在\") # 加载基础模型 print(\"正在加载基础模型...\") pipeline = FluxPipeline.from_pretrained(base_model_path, torch_dtype=torch.float16) # 如果有GPU则使用GPU if torch.cuda.is_available(): pipeline = pipeline.to(\"cuda\") print(\"使用GPU进行推理\") else: print(\"使用CPU进行推理 (这可能会很慢)\") # 加载LoRA权重 print(f\"正在加载LoRA权重: {lora_weights_file}\") pipeline.load_lora_weights(lora_weights_file, adapter_name=\"default\", unet_prefix=\"unet\") print(\"LoRA权重加载成功!\") # 存储生成的图像路径 generated_image_paths = [] # 生成图像 for i in range(num_images): # 使用递增的种子 seed = start_seed + i generator = torch.Generator(\"cuda\" if torch.cuda.is_available() else \"cpu\").manual_seed(seed) # 生成图像 print(f\"正在生成第 {i+1}/{num_images} 张图像 (种子: {seed})...\") image = pipeline( prompt=prompt, negative_prompt=negative_prompt, generator=generator, num_inference_steps=num_inference_steps, guidance_scale=guidance_scale, ).images[0] # 创建输出文件路径 if num_images == 1: image_path = os.path.join(output_dir, f\"{filename_prefix}.png\") else: image_path = os.path.join(output_dir, f\"{filename_prefix}_{i+1}.png\") # 保存图像 image.save(image_path) print(f\"图像已保存到 {image_path}\") # 添加到结果列表 generated_image_paths.append(image_path) return generated_image_paths# 示例用法if __name__ == \"__main__\": # 基本使用示例 prompt = \"overhead view, A highway cuts through the plains flanked by wind turbines electric poles and scattered trees, high quality\" # 高级使用示例 - 生成多张图像 images = generate_flux_lora_image( prompt=prompt, output_dir=\"my_generated_images\", num_images=3, guidance_scale=8.0, num_inference_steps=40, filename_prefix=\"overhead_view\" ) print(f\"生成了 {len(images)} 张图像\")