乐趣区

关于机器学习:使用-Amazon-SageMaker-的生成式-AI-定制个性化头像

生成式 AI 曾经成为各行业创意过程加强和减速的常用工具, 包含娱乐、广告和平面设计。它能够为观众发明更个性化的体验, 并进步最终产品的整体品质。

亚马逊云科技开发者社区为开发者们提供寰球的开发技术资源。这里有技术文档、开发案例、技术专栏、培训视频、流动与比赛等。帮忙中国开发者对接世界最前沿技术,观点,和我的项目,并将中国优良开发者或技术举荐给寰球云社区。如果你还没有关注 / 珍藏,看到这里请肯定不要匆匆划过,点这里让它成为你的技术宝库!

生成式 AI 的一个重要劣势是为用户创立独特和个性化的体验。例如, 生成式 AI 被流媒体服务用于为电影题目和视觉效果生成个性化的内容, 以减少观众参与度, 并依据用户的观看历史和偏好为题目构建视觉效果。而后, 零碎会生成题目艺术品的数千个变体, 并进行测试以确定哪个版本最能吸引用户的注意力。在某些状况下, 个性化的电视剧艺术品大大提高了点击率和观看率, 与没有个性化艺术品的节目相比。

在本文中, 咱们演示了如何应用 Amazon SageMaker 中的 Stable Diffusion 2.1 根底模型构建个性化头像解决方案, 并通过多模型端点 (MME) 同时节俭推理老本。该解决方案演示了, 通过上传 10-12 张自拍照, 您能够微调一个个性化模型, 而后基于任何文本提醒生成头像, 如下图所示。只管此示例生成了个性化头像, 但您能够将该技术利用于通过微调特定对象或格调的任何创意艺术生成。

解决方案概览

下图概述了咱们头像生成器的端到端解决方案体系结构。

本文和咱们提供的 GitHub 代码示例的范畴仅集中在模型训练和推理编排上(上图中的绿色局部)。您能够参考残缺的解决方案架构, 并基于咱们提供的示例进行构建。

模型训练和推理能够分为四个步骤:

  1. 将图片上传到 Amazon Simple Storage Service (Amazon S3)。在此步骤中, 咱们要求您至多提供 10 张高分辨率的自拍照。图片越多后果越好, 但训练工夫就越长。
  2. 应用 SageMaker 异步推理微调 Stable Diffusion 2.1 根底模型。咱们在后文中解释了应用推理端点进行训练的起因。微调过程首先筹备图片, 包含人脸裁剪、背景变动和调整大小以适应模型。而后, 咱们应用实用于大型语言模型(LLM) 的高效微调技术 Low-Rank Adaptation(LoRA) 来微调模型。最初, 在后处理中, 咱们将微调后的 LoRA 权重与推理脚本和配置文件 (tar.gz) 打包, 并上传到 SageMaker MME 的 S3 存储桶地位。
  3. 应用 GPU 的 SageMaker MME 托管微调后的模型。SageMaker 将依据每个模型的推理流量动静加载和缓存来自 Amazon S3 地位的模型。
  4. 应用微调后的模型进行推理。在 Amazon Simple Notification Service (Amazon SNS) 告诉表明微调实现后, 您能够立刻通过在调用 MME 时提供 target_model 参数来应用该模型创立头像。
    咱们在上面的章节中更具体地解释每个步骤, 并介绍一些示例代码片段。

筹备图片

为了从微调 Stable Diffusion 获得最佳后果以生成本身的图像, 您通常须要提供大量不同角度、不同表情以及不同背景的自拍照。然而, 通过咱们的实现, 您当初只须要 10 张输出图像就能够取得高质量的后果。咱们还减少了从每张照片中提取面部的主动预处理性能。您只须要从多个视角分明地捕获面部特色。包含侧面照, 每个侧面的侧面照, 以及之间的不同角度的照片。您还应该包含不同面部表情的照片, 如微笑、皱眉和中性表情。具备不同表情的组合将使模型可能更好地重现您独特的面部特色。输出图像决定了您能够生成头像的品质。为了确保正确实现此操作, 咱们倡议应用直观的前端 UI 体验来领导用户实现图像捕捉和上传过程。

以下是不同角度和不同面部表情的示例自拍照。

微调 Stable Diffusion 模型

在图片上传到 Amazon S3 后, 咱们能够调用 SageMaker 异步推理端点来启动训练过程。异步端点针对大型有效载荷 (最高 1 GB) 和长时间解决 (最高 1 小时) 的推理用例。它还提供了对申请进行排队的内置机制, 以及通过 Amazon SNS 的工作实现告诉机制, 此外还具备 SageMaker 托管的其余本机性能, 例如主动扩大。

只管微调不是推理用例, 但咱们抉择在此利用它而不是 SageMaker 训练作业, 是因为其内置的排队和告诉机制以及托管主动扩大性能, 包含在服务不应用时将实例扩大到 0 的能力。这使咱们能够轻松地针对大量并发用户扩大微调服务, 并打消了实现和治理其余组件的须要。然而, 它的确具备 1 GB 无效负载和 1 小时最大解决工夫的毛病。在咱们的测试中, 咱们发现 20 分钟的工夫在 ml.g5.2xlarge 实例上应用大概 10 张输出图像就足以取得正当良好的后果。然而, 对于更大规模的微调作业,SageMaker 训练将是举荐办法。

要托管异步端点, 咱们必须实现几个步骤。首先是定义咱们的模型服务器。对于本文, 咱们应用 Large Model Inference Container (LMI)。LMI 由 DJL Serving 提供反对, 这是一种高性能、与编程语言无关的模型服务解决方案。咱们抉择此选项是因为 SageMaker 托管推理容器曾经具备咱们须要的许多训练库, 例如 Hugging Face Diffusers 和 Accelerate。这大大减少了自定义容器以进行微调作业所需的工作量。

上面的代码片段显示了咱们在示例中应用的 LMI 容器的版本:

inference_image_uri = (f"763104351884.dkr.ecr.{region}.amazonaws.com/djl-inference:0.21.0-deepspeed0.8.3-cu117"
)
print(f"Image going to be used is ---- > {inference_image_uri}")

此外, 咱们须要一个 serving.properties 文件来配置服务属性, 包含要应用的推理引擎、模型工件的地位以及动静批处理。最初, 咱们必须有一个 model.py 文件, 用于将模型加载到推理引擎中, 并筹备模型的数据输出和输入。在咱们的示例中, 咱们应用 model.py 文件来启动微调作业, 咱们将在前面的章节中对此进行更具体的解释。serving.properties 和 model.py 文件都在 training_service 文件夹中提供。

定义模型服务器之后的下一步是创立一个端点配置, 该配置定义咱们的异步推理的服务形式。对于咱们的示例, 咱们只是定义了最大并发调用限度和输入 S3 地位。应用 ml.g5.2xlarge 实例, 咱们发现咱们能够同时微调两个模型, 而不会遇到内存不足 (OOM) 异样, 因而咱们将 max_concurrent_invocations_per_instance 设置为 2。如果咱们应用不同的一组调谐参数或较小的实例类型, 则可能须要调整此数字。咱们倡议将其最后设置为 1, 并在 Amazon CloudWatch 中监控 GPU 内存利用率。

# create async endpoint configuration
async_config = AsyncInferenceConfig(output_path=f"s3://{bucket}/{s3_prefix}/async_inference/output" , # Where our results will be stored
    max_concurrent_invocations_per_instance=2,
    notification_config={
      "SuccessTopic": "...",
      "ErrorTopic": "...",
    }, #  Notification configuration
)

最初, 咱们创立一个 SageMaker 模型, 该模型将容器信息、模型文件和 Amazon Identity and Access Management (IAM) 角色打包成一个对象。该模型应用咱们之前定义的端点配置进行部署:

model = Model(
    image_uri=image_uri,
    model_data=model_data,
    role=role,
    env=env
)

model.deploy(
    initial_instance_count=1,
    instance_type=instance_type,
    endpoint_name=endpoint_name,
    async_inference_config=async_inference_config
)

predictor = sagemaker.Predictor(
    endpoint_name=endpoint_name,
    sagemaker_session=sagemaker_session
)

当端点就绪时, 咱们应用以下示例代码调用异步端点并启动微调过程:

sm_runtime = boto3.client("sagemaker-runtime")

input_s3_loc = sess.upload_data("data/jw.tar.gz", bucket, s3_prefix)

response = sm_runtime.invoke_endpoint_async(
    EndpointName=sd_tuning.endpoint_name,
    InputLocation=input_s3_loc)

无关 SageMaker 上的 LMI 的更多详细信息, 请参阅应用 DJLServing 和 DeepSpeed 模型并行推理在 Amazon SageMaker 上部署大型模型。

调用后, 异步端点开始对咱们的微调作业进行排队。每个作业都会执行以下步骤: 筹备图像, 执行 Dreambooth 和 LoRA 微调, 以及筹备模型工件。让咱们深入探讨微调过程。

筹备图片

如前所述, 输出图像的品质间接影响微调模型的品质。对于头像用例, 咱们心愿模型专一于面部特色。咱们施行了一个预处理步骤, 应用计算机视觉技术来加重这种累赘, 而不是要求用户提供精心策划的特定大小和内容的图像。在预处理步骤中, 咱们首先应用人脸检测模型隔离每张图像中的最大面部。而后, 咱们裁剪并填充图像以取得模型所需的 512 x 512 像素大小。最初, 咱们从背景中宰割面部并增加随机背景变动。这有助于突出面部特色, 从而使咱们的模型能够从面部自身而不是背景中学习。上面的图像阐明了此过程中的三个步骤。

Step 1: Face detection using computer vision

Step 2: Crop and pad the image to 512 x 512 pixels

Step 3 (Optional): Segment and add background variation

Dreambooth 和 LoRA 微调

对于微调, 咱们联合了 Dreambooth 和 LoRA 的技术。Dreambooth 容许您应用惟一标识符和扩大模型的语言视觉词典, 将主体嵌入模型的输入域中。它应用一种称为 先验放弃 的办法来保留模型对主体类别 (在本例中为人) 的语义常识, 并应用其余对象类中的对象来改良最终图像输入。这就是 Dreambooth 如何可能仅应用大量主体输出图像就可能实现高质量后果的起因。

上面的代码片段显示了咱们头像解决方案的 trainer.py 类的输出。请留神, 咱们抉择了 <<TOK>> 作为惟一标识符。这样做是无意而为之的, 以防止抉择模型词典中可能曾经存在的名称。如果名称曾经存在, 模型必须先勾销学习而后重新学习主体, 这可能会导致蹩脚的微调后果。主体类设置为“a photo of person”, 这通过首先生成人物照片作为额定输出以启用先验放弃。这将有助于通过先验放弃办法保留人物的先前常识来缩小过拟合。

status = trn.run(base_model="stabilityai/stable-diffusion-2-1-base",
    resolution=512,
    n_steps=1000,
    concept_prompt="photo of <<TOK>>", # << unique identifier of the subject
    learning_rate=1e-4,
    gradient_accumulation=1,
    fp16=True,
    use_8bit_adam=True,
    gradient_checkpointing=True,
    train_text_encoder=True,
    with_prior_preservation=True,
    prior_loss_weight=1.0,
    class_prompt="a photo of person", # << subject class
    num_class_images=50,
    class_data_dir=class_data_dir,
    lora_r=128,
    lora_alpha=1,
    lora_bias="none",
    lora_dropout=0.05,
    lora_text_encoder_r=64,
    lora_text_encoder_alpha=1,
    lora_text_encoder_bias="none",
    lora_text_encoder_dropout=0.05
)

启用了许多内存节俭选项, 包含 fp16、use_8bit_adam 和梯度累积。这将内存占用缩小到 12 GB 以下, 从而容许在 ml.g5.2xlarge 实例上同时微调多达两个模型。

LoRA 是一种高效的 LLM 微调技术, 它解冻了大部分权重, 并在预训练 LLM 的特定层附加了一个小的适配器网络, 从而实现更快的训练和优化的存储。对于 Stable Diffusion, 适配器连贯到推理流水线的文本编码器和 U-Net 组件。文本编码器将输出提醒转换为 U-Net 模型能够了解的潜在空间, 而后 U-Net 模型应用潜在含意在随后的扩散过程中生成图像。微调的输入仅为 text_encoder 和 U-Net 适配器权重。在推理时, 能够从新连贯这些权重到根底 Stable Diffusion 模型以重现微调后果。

上面的图表是原作者提供的 LoRA 微调具体图:Cheng-Han Chiang, Yung-Sung Chuang, Hung-yi Lee,“AACL_2022_tutorial_PLMs,”2022

通过联合两种办法, 咱们可能在调谐数量级更少的参数的同时生成个性化模型。这大大缩短了训练工夫和 GPU 利用率。此外, 因为适配器权重仅为 70 MB, 而残缺的 Stable Diffusion 模型为 6 GB, 存储量缩小了 99%。

筹备模型工件

微调实现后, 后处理步骤将应用 LoRA 权重和 NVIDIA Triton 的其余模型服务文件创建 TAR 文件。咱们应用 Python 后端, 这意味着须要 Triton 配置文件和用于推理的 Python 脚本。请留神,Python 脚本必须命名为 model.py。最终的模型 TAR 文件应具备以下文件构造:

|--sd_lora
   |--config.pbtxt
   |--1\
      |--model.py
      |--output #LoRA weights
         |--text_encoder\
         |--unet\
         |--train.sh

应用 GPU 的 SageMaker MME 托管微调后的模型

在对模型进行微调后, 咱们应用 SageMaker MME 托管个性化的 Stable Diffusion 模型。SageMaker MME 是一个弱小的部署性能, 容许在单个容器前面通过单个端点托管多个模型。它会主动治理流量和路由到您的模型, 以优化资源利用率、节省成本和最小化治理数千个端点的经营累赘。在咱们的示例中, 咱们在 GPU 实例上运行,SageMaker MME 通过 Triton Server 反对 GPU。这容许您在单个 GPU 设施上运行多个模型, 并利用减速计算。无关如何在 SageMaker MME 上托管 Stable Diffusion 的更多详细信息, 请参阅应用 Amazon SageMaker Stable Diffusion 模型创立高质量图像并以高效低成本地部署。

对于咱们的示例, 咱们进行了额定的优化, 以在冷启动状况下更快地加载微调模型。这是 LoRA 适配器设计使之成为可能的。因为所有微调模型的根本模型权重和 Conda 环境都是雷同的, 咱们能够通过将这些公共资源事后加载到托管容器上来共享它们。这只剩下须要从 Amazon S3 动静加载的 Triton 配置文件、Python 后端 (model.py) 和 LoRA 适配器权重。下图提供了横向比拟。

这将模型 TAR 文件大小从约 6GB 显着减小到 70MB, 因而加载和解包速度更快。在咱们的示例中, 咱们在 models/model_setup 中创立了一个实用的 Python 后端模型。该脚本简略地将根底 Stable Diffusion 模型和 Conda 环境从 Amazon S3 复制到公共地位, 以在所有微调模型之间共享。以下是执行该工作的代码片段:

def initialize(self, args):

        #conda env setup
        self.conda_pack_path = Path(args['model_repository']) / "sd_env.tar.gz"
        self.conda_target_path = Path("/tmp/conda")

        self.conda_env_path = self.conda_target_path / "sd_env.tar.gz"

        if not self.conda_env_path.exists():
            self.conda_env_path.parent.mkdir(parents=True, exist_ok=True)
            shutil.copy(self.conda_pack_path, self.conda_env_path)

        #base diffusion model setup
        self.base_model_path = Path(args['model_repository']) / "stable_diff.tar.gz"

        try:
            with tarfile.open(self.base_model_path) as tar:
                tar.extractall('/tmp')

            self.response_message = "Model env setup successful."

        except Exception as e:
            # print the exception message
            print(f"Caught an exception: {e}")
            self.response_message = f"Caught an exception: {e}"

而后每个微调模型将指向容器上的共享地位。Conda 环境在 config.pbtxt 中援用。

name: "pipeline_0"
backend: "python"
max_batch_size: 1

...

parameters: {
  key: "EXECUTION_ENV_PATH",
  value: {string_value: "/tmp/conda/sd_env.tar.gz"}
}

在每个 model.py 文件的 initialize()函数中, 从 Stable Diffusion 根本模型加载。而后咱们将个性化的 LoRA 权重利用于 unet 和 text_encoder 模型以重现每个微调模型:

...

class TritonPythonModel:

    def initialize(self, args):
        self.output_dtype = pb_utils.triton_string_to_numpy(pb_utils.get_output_config_by_name(json.loads(args["model_config"]),
                                               "generated_image")["data_type"])

        self.model_dir = args['model_repository']

        device='cuda'
        self.pipe = StableDiffusionPipeline.from_pretrained('/tmp/stable_diff',
                                                            torch_dtype=torch.float16,
                                                            revision="fp16").to(device)

        # Load the LoRA weights
        self.pipe.unet = PeftModel.from_pretrained(self.pipe.unet, unet_sub_dir)

        if os.path.exists(text_encoder_sub_dir):
            self.pipe.text_encoder = PeftModel.from_pretrained(self.pipe.text_encoder, text_encoder_sub_dir)

应用微调后的模型进行推理
当初咱们能够尝试微调后的模型, 办法是调用 MME 端点。咱们在示例中公开的输出参数包含 prompt、negative_prompt 和 gen_args, 如上面的代码片段所示。咱们在字典中为每个输出项设置了数据类型和形态, 并将其转换为 JSON 字符串。最初, 无效负载字符串和 TargetModel 被传递到申请中以生成头像图片。

import random

prompt = """<<TOK>> epic portrait, zoomed out, blurred background cityscape, bokeh,
 perfect symmetry, by artgem, artstation ,concept art,cinematic lighting, highly
 detailed, octane, concept art, sharp focus, rockstar games, post processing,
 picture of the day, ambient lighting, epic composition"""negative_prompt ="""
beard, goatee, ugly, tiling, poorly drawn hands, poorly drawn feet, poorly drawn face, out of frame, extra limbs, disfigured, deformed, body out of frame, blurry, bad anatomy, blurred,
watermark, grainy, signature, cut off, draft, amateur, multiple, gross, weird, uneven, furnishing, decorating, decoration, furniture, text, poor, low, basic, worst, juvenile,
unprofessional, failure, crayon, oil, label, thousand hands
"""

seed = random.randint(1, 1000000000)

gen_args = json.dumps(dict(num_inference_steps=50, guidance_scale=7, seed=seed))

inputs = dict(prompt = prompt,
              negative_prompt = negative_prompt,
              gen_args = gen_args)

payload = {
    "inputs":
        [{"name": name, "shape": [1,1], "datatype": "BYTES", "data": [data]} for name, data in inputs.items()]
}

response = sm_runtime.invoke_endpoint(
    EndpointName=endpoint_name,
    ContentType="application/octet-stream",
    Body=json.dumps(payload),
    TargetModel="sd_lora.tar.gz",
)
output = json.loads(response["Body"].read().decode("utf8"))["outputs"]
original_image = decode_image(output[0]["data"][0])
original_image

清理

依照 notebook 中的清理局部的阐明删除作为本文一部分预配的资源, 以防止不必要的费用。无关推理实例老本的详细信息, 请参阅 Amazon SageMaker 定价。

论断

在本文中, 咱们演示了如何应用 SageMaker 上的 Stable Diffusion 创立个性化头像解决方案。通过仅应用大量图像微调预训练模型, 咱们能够生成反映每个用户共性和人格的头像。这只是咱们如何应用生成式 AI 为用户创立定制化和独特体验的泛滥示例之一。可能性是有限的, 咱们激励您尝试这项技术并摸索其加强创意过程的后劲。咱们心愿本文信息丰盛且鼓舞人心。咱们激励您尝试该示例, 并通过社交平台上的 #sagemaker #mme #genai 标签与咱们分享您的创作。咱们很想晓得您创作的作品。

除了 Stable Diffusion, 还有许多其余生成式 AI 模型可在 Amazon SageMaker JumpStart 上取得。参阅开始应用 Amazon SageMaker JumpStart 来摸索他们的性能。

文章起源:https://dev.amazoncloud.cn/column/article/64e5ffc984d23218430…

退出移动版