Kotonia
ログイン今すぐ始める

Kotonia Articles

一个晚上:从想做一个专用 LoRA,到撞上「合法的 NSFW 数据集结构性消失」这一事实,再到发明 3-stage Caption 突破 under-fit 天花板

从 v1 nipple LoRA 的 @1.5 > @1.0 这一 under-fit 信号出发,结构性分析 CSAM 污染 + DRM 双重锁死的 NSFW dataset 路径,使用 CivitAI RED + 3-stage Caption + informational value frame 训练 V2 LoRA,通过 A/B 确认了 prompt adherence 的大幅改善与泛化保持。一夜研究日志。

作者 6分钟阅读
#LoRA#image-generation#HiDream#indie#AI-training
其他语言日语英语

Figure 1: V2 部署后的 /studio。多个 LoRA 选择性叠加用于生成 explicit content。本文的最终产物。

Figure 1: 本文叙述的终点。/studio 的 LoRA 下拉菜单中加入了新训练的 nipple_v2,此处与既有的 kotonia03 (anime + 美感) 叠加。右下角的星级评分 UI 是 dataset labeling 工具,与生成同时运行。


"LoRA 在 @1.5 强度下的输出质量比 @1.0 还要高"

这听起来只是"开大一点就强一点"的随手观察,其实这是 under-fit 在暗中报警的不祥信号。

我经营的 kotonia.ai 把开放权重的图像生成模型 HiDream-O1-Image 以 fp8 常驻显存,在其上叠加多个自训练 LoRA 来表达专门差分。其中一个叫 nipple_v1,用于提升人体细节的渲染质量。当用户反馈"用 1.5 看起来比 1.0 好"的那一刻,我立刻判断:这是 under-fit 在说话。

之后用一个晚上,把"爬数据→重新设计 caption pipeline→规模扩大 17 倍→训练→A/B→部署"一口气跑完。途中我发现了一个事实:整个 NSFW 数据集世界从结构上被 CSAM 污染和 DRM 双重锁死。所以本文从那里开始讲,最后落到方法论:3-stage Caption


1. "@1.5 > @1.0" 实际在传递的信号

LoRA 的工作方式是在 base model 的权重上叠加一个低秩差分 ΔW,推理时再乘以一个标量 α:W' = W + α · ΔW。训练时以 α=1.0 为"标定刻度"对齐,推理时用户可以调节 0.5 或 1.5。

通常 @1.0 是 natural sweet spot,@1.5 要么过度,要么破坏解剖结构,要么显得不自然。而 kotonia.ai 的 nipple_v1 出现了反向:@1.5 的解剖质感优于 @1.0。

含义:训练过程中,LoRA 的 magnitude 没有伸展到位就早期收敛了。具体可能是:

  • rank 太小,表达空间装不下数据的 variability
  • LR 太保守,每一步移动距离太短
  • 数据量太少,根本没有产生 variability

v1 的训练参数:525 张图像,rank 32,1500 步。这是 smoke test 级别的迷你配置,从来没有扩展到生产规模。用户层面的症状"请用 1.5",就是这笔账到期了。

修复路径需要提高 rank,扩大数据,多跑步数,并从根本上提升 caption 质量。故事从数据采集开始。


2. 公开 NSFW 数据集世界被 CSAM 关上的门

"我想做一个专用人体细节 LoRA,需要写实数据集"——在 ML 圈这是再普通不过的需求,过去你会去找 NudeNet、LAION-NSFW subset,或是 Figshare 14495367(Image and video dataset for adult content detection)这类学术发布。

2025 年风向变了。

加拿大儿童保护中心(C3P)对 NudeNet 分类器数据集(约 70 万张)进行了审计,发现了 680 张 CSAM 图像,其中 120 张是 identified victim(与执法部门数据库匹配过的真实受害者)。Academic Torrents 收到通知后下架数据集。archive.org 的原始 URL 现在是 404。引用过 NudeNet 的 250 多篇学术论文一夜之间立场尴尬。

这不是孤立事故,是结构性的。Stanford Internet Observatory 早在 2023 年就已在 LAION-5B 中发现 3,200 多张 CSAM。共同的根源:从色情网站抓取。所有按这个方法构建的公开 NSFW 数据集都继承了同一个结构性污染风险。

Figshare 14495367 在其描述中写明"通过浏览色情网站"采集,目前没有公开审计记录,但只要采集方法相同,统计上可期待相同的污染率(约 0.1%)。在 30,800 张图像中,统计上预期约 30 张 CSAM 混入。

法律账面也很严:

  • 持有 CSAM 本身即犯罪,含日本在内的多数司法辖区。以 AI 训练为目的下载,构成 possession
  • "我下载后再过滤" 不能脱罪——下载的瞬间已经构成违法,且没有能让普通用户安全识别 CSAM 的手段
  • 可追溯性也真实存在——对 LoRA 权重做 membership inference attack,可以事后查证训练数据是否包含某个 dataset

到这一步,公开 NSFW 数据集路线在结构上已经走死。换下一个候选。


3. "我在 FANZA 买的,所以合法" 只对了一半

第二个假设:合法购买商业日本成人作品并从中抽帧。按日本著作权法第 30 条(私的使用),个人用途的复制应在许可范围,自己下载的视频抽取个别帧应当落在这个范围内。是吧?

我在 FANZA 买了一部 S1 厂牌的作品,下载下来是一个 .dcv 文件。file 命令显示:ISO Media MP4 v1。看起来就是普通 MP4。

但是 ffprobe -read_intervals "%+#1" -show_packets 暴露了真相:

[PACKET]
codec_type=video
flags=K__
[SIDE_DATA]
side_data_type=Encryption info    ← 这里
[/SIDE_DATA]

CENC(Common Encryption,MPEG-DASH 系 DRM)正在对视频样本加密。容器(MP4 ftyp/moov)可读,但所有 H.264 NAL 单元都是加密字节。播放时 DMM Player 从 DRM 服务器取得密钥,在内存中解密(Widevine/PlayReady 等同)。

这直接撞上日本著作权法第 30 条第 1 项第 2 号及第 2 项(2012 年修订,2018 年加强)。通过回避技术性保护手段进行的复制,即使是私人使用也违法——刑事处罚(2 年以下徒刑或 200 万日元以下罚金)。"我自己买的"和"我只在自己设备上做 AI 训练"都无法救济。回避 DRM 这个行为本身就是违法。

实体媒介(Blu-ray、DVD)采用 AACS/CSS,同一种 DRM 结构,同一个问题。

也就是说主要的商业 AV 下载渠道作为 AI 训练数据源在结构上是封闭的。我那 9.6 GB 的购买只能用于个人观看,抽帧路径走不通。


4. 走到 CivitAI RED——剩下的只有 AI 生成路径

公开 NSFW 数据集被 CSAM 关死。商业 AV 被 DRM 关死。自掏腰包拍摄在 indie 预算尺度上不现实。剩下的就是 CivitAI 的 AI 生成图像库

CivitAI 通过 API 提供社区生成的图像,按 browsingLevel(1=PG ... 16=XXX)分类。让这条路安全的结构性属性:

  • 不存在 CSAM 风险——AI 生成内容没有 identified victim,概念上根本不适用
  • 明确的年龄政策——CivitAI 将描绘未成年人视为 TOS 违规并删除
  • 认证的批量 API 访问——基于 token,分页可控
  • provenance 干净——每张图像都附带原始 prompt、模型名、creator

一个常见担忧:"训练 AI 生成图像会导致 mode collapse"。这个担忧针对的是 self-distillation——同一模型的输出又被喂回同一模型。CivitAI 是 PonyDiffusion / Flux / SDXL / 各种 community LoRA 的异构混合,与 HiDream 全部不同源(跨架构),不构成 self-distillation。

我写了 civitai_collect.py,用 --target 20000 --weights "8:0.25,16:0.75" --min_hearts 30 跑了一遍。CivitAI API 在分页过程中多次返回 500/503,我多次从 cursor 续传。最终产量:level 8 5,000 张 + level 16 4,707 张 = 9,707 张。未达 20k 目标,但比 v1 的 525 张多 18.5 倍,已经进入实用规模。

数据搞定。接下来是 caption 设计。


5. 17 倍数据本身不够——caption mode collapse 的发现

"加数据就能解决 under-fit"这个直觉只对了一半。

v1 的 525 张 caption 是用 Grok 2-stage pipeline 生成的:Stage 1 用 JSON 抽取 attribute,Stage 2 强制将所有 attribute 逐字使用合成 caption。把同一 pipeline 放大到 9,707 张时——

所有 caption 在结构上几乎一样。原因:

  • Stage 1 抽取的 attribute 字段固定(7 个)
  • Stage 2 用的是单一模板 prompt
  • temperature 0.25 接近确定性

每张图像在 attribute 层面有 uniqueness,但句法结构、词汇选择、连接词、段落布局几乎全图相同。caption 之间存在 structural identity——这种重复 TF-IDF 检测不出来,因为词汇重叠看起来不高,但结构重叠是 100%。

这就是 caption mode collapse。一旦识别出,诊断就清晰了:用这种语料训练的 LoRA 会过拟合到特定的句法模式,推理时面对 prompt 变体就脆弱。

修复方向必须是在生成时就引入多样性。Post-hoc dedup(TF-IDF / cosine 聚类)只能捕捉词汇重叠,看不见结构重复。必须改变生成时的概率分布。

3-stage Captioning 在这里诞生。


6. 设计 3-stage Captioning——informational value frame

设计目标:

  1. 每张图像抽取更多结构性 uniqueness fodder
  2. 在生成时降低结构相同输出的概率
  3. 提高 nipple 区域词汇密度(色 + 形 + 状态 + areola 自然织入)
  4. 用本地 LLM(vLLM 上的 Gemma 4 26B A4B Uncensored,端口 8899)并行处理全部 9,707 张

三段:

Stage 1:Factual inventory(T=0.1)

12 个字段的结构化 JSON 抽取。在原 7 个之上增加 nipple_detail(color/shape/state/areola)、breast_detail(size/shape/skin_finish)、pose_framingexpression_moodcolor_palette

Stage 2:Analytical reasoning(T=0.4) ← 新增

以 Stage 1 的 JSON 为输入,让模型回答:"这张图像作为训练数据为什么 informative,用 2-3 句分析。" 显式约束:

Do NOT make subjective quality judgments — no "beautiful", "attractive", "well-composed", "high quality", "stunning". Describe informational value only.

这就是 informational value frame。它从结构上阻止主观质量词汇渗入推理。原因要点:如果"beautiful"被 caption 学到,模型会把"beautiful 是出现可见解剖的前提"也学进去——这是你不想要的脆弱性。

每张图像的 reasoning trace 不同(每张图像的 distinctive feature 不同),这种不对称性成为最终 caption 多样性的驱动器。

Stage 3:Caption synthesis with skeleton rotation(T=0.7)

输入 Stage 1 的 attribute + Stage 2 的 reasoning,生成最终 caption。八种句子骨架按图像 round-robin 分配,强制使用不同句法结构:

S0: "Close-up of [subject + pose]. [nipple/breast detail]. [lighting], [style]."
S1: "[Style] image: [pose_framing], [breast detail]. [nipple detail]. [mood], [lighting]."
S2: "[Mood] [subject] in [pose]; visible anatomy [list]. [props]. [lighting], [style]."
... (S3-S7)

并显式指导提高 nipple 区域词汇密度:

For the nipple region, weave 2-4 complementary terms naturally into the caption. Use complementary attributes (color + shape + state + areola) rather than synonym-stuffing. Vary which subset appears across captions in this batch.

产出例如 "pink, pointed nipples with prominent areolae"——四个属性自然织入,而不是 booru-tag 式罗列。HiDream 的 Qwen3VL 文本编码器是为自然语言 caption 而设计的,所以这种形式确实能落地。

Figure 2: V2 LoRA 与 kotonia03 叠加的生成样本。训练时使用的 caption 用多词汇模式描述("pink, pointed nipples with prominent areolae"),产物的 LoRA 在推理时复现该解剖具体性。

Figure 2: V2 LoRA 与 kotonia03 (anime aesthetic) 叠加的单张生成。前文描述的自然语言多词汇 caption 模式("pink, pointed nipples with prominent areolae")在推理时翻译为解剖一致性:areola 纹理与 nipple 形状协调落地。

525 张 smoke test 结果:

  • areola 出现率:v1 是 0/15,V2 是 4/15(新解锁词汇)
  • erect 出现率:2 → 7(3.5x)
  • pointed 出现率:0 → 3(新)
  • unique trigram ratio:0.873 → 0.919(+5.3pp)
  • self-BLEU proxy:0.018 → 0.008(−55%,自相似度降低)

在完整 9,707 张规模下,caption 在 concurrency 16 下 51 分钟完成(Gemma 26B uncensored 的 vLLM continuous batching 起作用)。


7. 训练与 A/B——under-fit 真的解了

训练配置:

  • 9,138 张(9,707 减去 age safety filter 拦截 515 张和 discriminator 低于 3.0 分的 54 张)
  • rank 64 / alpha 64(v1 的 2 倍)
  • LR 1e-4(v1 的 2 倍)
  • 30,000 步 / batch 1(v1 的 20 倍)
  • fresh from base(不从 v1 续训,不继承 anime bias)
  • patch_align 保持原始 aspect ratio(batch>1 化方案因 aspect 失真问题放弃)

在 GPU 0(Blackwell 6000,96GB)上停掉 image_server / LTX-2 / Gemma 26B 进行独占,约 3 小时完成训练。loss 稳定在 0.03-0.06 区间,无 divergence。

Figure 3: 5 config × 8 prompt 的 A/B 对比网格。列从左到右依次:base / v1@1.0 / v1@1.5 / v2@1.0 / v2@1.5。同一行使用同一 seed,因此列间差异为纯 config 差。

Figure 3: A/B 评估网格(40 张样本)。列:base / [email protected] / [email protected] / [email protected] / [email protected]。行:8 条 eval prompt。v1 列可见:多条 prompt 明确写 "topless",但 v1 输出穿衣版本(prompt adherence 失败)。v2 列:8/8 正确解读 topless。这是 3-stage caption pipeline 对 prompt adherence 改善的直接视觉证据。

A/B 评估覆盖 8 个 prompt × 5 个 config

config观察
base(无 LoRA)解剖描绘在 base model 水平,保守
[email protected]8 个 prompt 里有 4-5 次忽略 "topless",输出穿着衣服的版本
[email protected]overshoot 恢复了品质,是 v1 实用最优
[email protected]8/8 正确解读 topless,nipple 细节(areola/shape)干净,aesthetic 持平或更优
[email protected][email protected] 几乎无差(overshoot 余地小 = under-fit 解决的证据)

[email protected][email protected] 是 under-fit 解决的信号。对比 [email protected][email protected]

接着是 8 个 prompt × 6 个 strength 的 sweep:

  • Nipple-focused prompt 4 条:0.5 弱,0.75 sweet,1.0 强,1.25-1.5 出现 body inflation 迹象
  • 泛化探针 4 条(着装女性、山脉风景、动漫制服、拉面碗):风景和食物在所有 strength 下完全不受影响。着装意图在所有 strength 下保持(不脱衣)。高 strength 下有轻微 breast emphasis 上升,但没有打破着装的 framing

这说明 LoRA 的 specialization 局限于 nipple/breast 域——无关域(风景、食物)完全没被 corrupt。


8. 这暴露了 indie 的 compounding loop

部署:在 /studio 的 LoRA 下拉菜单加入 nipple_v2(人体细节品质 + 泛化保持),default weight 0.75,在 image_server 的 HIDREAM_LORAS 环境变量中注册,rebuild 前端。~10 分钟。

这一个晚上产出的可复用资产:

  • 3-stage caption 在方法论上可迁移。下一个专用 LoRA(手部品质 / 服装细节 / 特定风格)可以复用同一 pipeline
  • age safety filter + discriminator + caption 存在的三重过滤是通用的。会成为 CivitAI 抓取的标准后处理
  • A/B + strength sweep + 泛化探针 是任意 LoRA 都能复用的评估框架

除了这些 artifact,还有一件关于 indie 工具栈值得说出来。

公开数据集被 CSAM 关死。商业 AV 被 DRM 关死。在这种风景里剩下的路径是自己打 API,自己设计 caption pipeline,自己烧 GPU,自己部署。这是 VC 撑腰的 dumping 创业公司模仿不来的动法,而且因为对外依赖归零,每次尝试的输出会成为下次尝试精度的输入。compounding loop 闭合。

"导入数据"变成"自己蒸馏数据","购买 caption"变成"自己设计 caption","外包训练"变成"自己跑训练"。每个 delta 都很小,但对一个握住整套 stack 的 indie 来说,零外部依赖的 compounding 是真实的。

V3 的遗留任务也明确了:

  1. vulva bias 根治:在 Stage 1 prompt 中把 vulva 从 anatomy_visible 排除,或在上游用 detector 过滤掉显示 vulva 的训练图像
  2. lying pose 拉长:CivitAI 的躺姿图像倾向于纵向 aspect ratio,怀疑在训练时产生了偏差。aspect-ratio-weighted sampling 应能 normalize
  3. stack rank 不匹配(v2 rank 64 与 k03 rank 32):add_weighted_adapter linear 要求同 rank,绕过路径是 peft_model.base_model.set_adapter([list]) + per-adapter scaling

这些是用"caption 与采样设计"而非"加数据"解决的问题——V3 将更多是方法论上的精修。

我在夜里开始这个 session,到早上已经把 v2 部署上线。要允许一句自吹的话,那就是indie 的 compounding loop 在一个晚上闭合了一整个周期

Kotonia 将语音 AI、AI 聊天、图像生成和团队协作整合到一个 AI 工作区中。

试用 Kotonia