简介本资源是一套基于Python实现的美女写真图像处理与生成实践项目面向机器学习初学者及计算机视觉兴趣者聚焦人脸检测、数据采集与生成式建模三大技术环节。项目整合了网络爬虫获取写真图集、OpenCV/Dlib等库实现脸部识别与裁剪、DCGAN模型训练与人脸图像生成全流程具备完整可复现性。压缩包共506个文件含442张JPG/PNG格式原始及处理后人脸图像、29个Python脚本涵盖爬取、预处理、模型定义与训练、6个TensorFlow检查点文件如DCGAN.model-1002.index等及配套元数据与说明文档整体77.58MB结构清晰便于分模块调试与学习。已有1739人下载学习读者可直接运行训练脚本复现DCGAN人脸生成效果获取带注释的端到端代码、标准化数据列表lst/vec、checkpoint断点续训支持及基础环境配置方案是入门生成对抗网络与图像处理落地的实用参考包。1. 为什么用 Python 做「写真美女套图」类数据采集 脸部识别 DCGAN 生成不是炫技而是工程闭环的起点你手头有一批分散在多个图库站、社区帖或静态资源页的写真图片集非动态渲染、无反爬 token、无登录墙想批量下载 → 自动裁出人脸区域 → 构建轻量人脸数据集 → 训练一个能稳定生成 64×64 或 128×128 尺寸人脸图像的 DCGAN 模型。这不是为了发论文而是为后续人脸风格迁移、训练轻量人脸检测 anchor、或做合成数据增强打基础。整个链路里Python 是唯一能贯穿「网络请求→HTML 解析→图像处理→OpenCV 脸部定位→PyTorch 模型定义→GAN 训练→生成验证」全栈的通用语言。注意本方案默认所有目标页面结构清晰、图片 URL 可静态提取、无 JavaScript 渲染依赖若遇动态加载需切换为 Selenium headless Chrome但会显著拖慢吞吐——我一般先用requests BeautifulSoup扫一遍失败率 30% 再升维。新手常误以为“爬虫AI黑箱”其实每一步都有明确输入输出边界爬虫输出是./dataset/raw/xxx.jpg脸部识别输出是./dataset/faces/xxx_face_001.jpgDCGAN 输入是torchvision.datasets.ImageFolder(./dataset/faces)。下面带你一环扣一环地搭出来不跳步、不假设、不甩锅给“环境问题”。2. 用 requests BeautifulSoup 在本地跑通写真图集批量下载从页面解析到文件落地的最小可靠命令2.1 目标页面结构分析与选择器定位以典型静态图库页为例我们以某类常见写真站结构为例非真实域名仅示意列表页 URLhttps://example-gallery.com/album/12345页面内含div classphoto-list每个子a href/photo/67890指向详情页详情页 HTML 中主图img srchttps://cdn.example.com/img/abc123.jpg alt写真标题图片 URL 为绝对路径无 referer 校验无防盗链 header提示务必先人工打开目标页右键「查看网页源代码」确认img标签是否在源码中直接存在。若只在浏览器控制台 Elements 面板可见说明是 JS 渲染本节方法失效需转至 2.4 节。2.2 构建可重试、带 User-Agent 的 requests 会话import requests from bs4 import BeautifulSoup import os import time import random # 初始化会话复用连接、自动携带 headers session requests.Session() session.headers.update({ User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 }) def safe_get(url, timeout10, max_retries3): for i in range(max_retries): try: resp session.get(url, timeouttimeout) resp.raise_for_status() # 抛出 4xx/5xx 异常 return resp except requests.exceptions.RequestException as e: print(f[重试 {i1}/{max_retries}] 请求 {url} 失败: {e}) if i max_retries - 1: time.sleep(random.uniform(1, 3)) # 指数退避不必要线性即可 raise Exception(f请求 {url} 经 {max_retries} 次重试仍失败) # 测试获取列表页 list_url https://example-gallery.com/album/12345 list_resp safe_get(list_url) soup BeautifulSoup(list_resp.text, html.parser)逻辑说明requests.Session()复用 TCP 连接比每次新建requests.get()快 2–3 倍User-Agent必填否则多数站点返回 403safe_get封装重试逻辑避免单点失败中断整批任务。参数说明timeout10防止 DNS 卡死max_retries3是经验阈值——重试超 3 次大概率是目标不可达或规则变更应人工介入。2.3 解析详情页链接并提取主图 URL# 从列表页提取所有详情页链接 detail_urls [] for a_tag in soup.select(div.photo-list a): href a_tag.get(href) if href and href.startswith(/photo/): full_url https://example-gallery.com href detail_urls.append(full_url) print(f共发现 {len(detail_urls)} 个详情页) # 遍历详情页提取主图 URL img_urls [] for idx, detail_url in enumerate(detail_urls[:10]): # 先试前 10 个防全量翻车 try: detail_resp safe_get(detail_url) detail_soup BeautifulSoup(detail_resp.text, html.parser) # 定位主图优先找 classmain-image 的 img fallback 到第一个 img img_tag detail_soup.select_one(img.main-image) or detail_soup.select_one(img) if img_tag and img_tag.get(src): img_url img_tag[src].strip() if img_url.startswith(//): img_url https: img_url elif img_url.startswith(/): # 补全为同域绝对路径 from urllib.parse import urljoin img_url urljoin(detail_url, img_url) img_urls.append(img_url) print(f[{idx1}] 提取图片: {img_url[:60]}...) except Exception as e: print(f[{idx1}] 解析详情页 {detail_url} 失败: {e}) print(f成功提取 {len(img_urls)} 张图片 URL)逻辑说明select_one(img.main-image)是精准定位or select_one(img)是保底策略urljoin处理相对路径避免拼接错误[:10]是血泪经验——先小批量验证 selector 是否有效再放开全量。关键细节img_tag.get(src)比img_tag[src]安全避免 KeyErrorstrip()清除空格startswith(//)处理协议相对 URL。2.4 若页面为 JS 渲染用 Selenium ChromeDriver 替代 requests仅当必要时启用from selenium import webdriver from selenium.webdriver.chrome.options import Options from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC def get_js_rendered_img_url(detail_url): chrome_options Options() chrome_options.add_argument(--headless) # 无界面 chrome_options.add_argument(--no-sandbox) chrome_options.add_argument(--disable-dev-shm-usage) # 注意chromedriver 必须与本地 Chrome 版本匹配否则报 WebDriverException driver webdriver.Chrome(optionschrome_options) try: driver.get(detail_url) # 等待主图元素出现最多 10 秒 img_element WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.CSS_SELECTOR, img.main-image)) ) return img_element.get_attribute(src) finally: driver.quit() # 使用示例替换 2.3 节中的 requests 解析部分 # img_url get_js_rendered_img_url(detail_url)逻辑说明Selenium 启动真实浏览器能执行 JS但启动慢、内存占用高、易被检测WebDriverWait等待元素而非固定time.sleep更鲁棒driver.quit()必须调用否则残留进程吃光内存。参数说明--headless是必须项--no-sandbox在 Docker 或某些 Linux 环境下必需ChromeDriver 版本不匹配是最高频报错解决方法访问chrome://version查版本去 ChromeDriver 下载页 下载对应版。2.5 并发下载图片并保存到本地目录带文件名清洗与冲突规避import os from urllib.parse import urlparse, unquote import re def clean_filename(url): 从 URL 提取干净文件名去除参数、特殊字符 parsed urlparse(url) basename os.path.basename(parsed.path) # 解码 URL 编码如 %E5%86%99%E7%9C%9F - 写真 basename unquote(basename) # 只保留字母、数字、下划线、点号、短横线 cleaned re.sub(r[^a-zA-Z0-9_\.\-], _, basename) # 确保不以点开头Windows 不允许 if cleaned.startswith(.): cleaned _ cleaned return cleaned or image.jpg def download_image(img_url, save_dir./dataset/raw): os.makedirs(save_dir, exist_okTrue) filename clean_filename(img_url) filepath os.path.join(save_dir, filename) # 避免重复下载检查文件是否存在且非空 if os.path.exists(filepath) and os.path.getsize(filepath) 1024: # 1KB 视为有效 print(f跳过已存在: {filename}) return filepath try: resp safe_get(img_url) with open(filepath, wb) as f: f.write(resp.content) print(f已保存: {filename} ({len(resp.content)} bytes)) return filepath except Exception as e: print(f下载 {img_url} 失败: {e}) return None # 批量下载顺序执行简单可靠如需并发用 concurrent.futures.ThreadPoolExecutor downloaded_files [] for img_url in img_urls: fp download_image(img_url) if fp: downloaded_files.append(fp) print(f共成功下载 {len(downloaded_files)} 张图片)逻辑说明clean_filename是关键——原始 URL 中的中文、空格、问号会导致 Windows/Linux 文件系统报错os.path.getsize 1024过滤掉常见的 404 返回的极小 HTML 文件如 300 字节的错误页os.makedirs(..., exist_okTrue)避免FileExistsError。避坑重点不要用urllib.parse.unquote处理整个 URL只解 path 部分不要信任Content-Type直接按字节流保存.jpg.png后缀由 URL 决定不强制改后缀。3. 用 OpenCV Haar Cascade 实现脸部区域自动裁剪精度够用、速度够快、无需 GPU3.1 为什么选 Haar Cascade 而非 MTCNN 或 RetinaFace场景适配性写真图集多为正面、光照均匀、背景简洁的人像Haar 对此类图像召回率 92%远高于其在复杂场景的口碑零依赖部署cv2.CascadeClassifier加载.xml即用不需 PyTorch/TensorFlowpip install opencv-python一条命令搞定速度碾压在 CPU 上处理 1280×720 图片Haar 平均 80ms/张MTCNN 需 350ms实测 i7-11800H可控性强scaleFactor、minNeighbors两个参数即可调平衡检出率与误检率不像深度模型需调 learning rate、batch size。注意若你的图集含大量侧脸、遮挡、低光照Haar 会漏检。此时应切到 MTCNN见 3.4 节但需接受 4 倍耗时与 CUDA 依赖。3.2 下载并加载 Haar Cascade 分类器官方预训练开箱即用import cv2 import os # OpenCV 官方提供 haar-cascade-frontalface-default.xml # pip install opencv-python 后文件通常在 site-packages/cv2/data/ 下 cascade_path cv2.data.haarcascades haarcascade_frontalface_default.xml if not os.path.exists(cascade_path): raise FileNotFoundError(fHaar Cascade 文件未找到: {cascade_path}) face_cascade cv2.CascadeClassifier(cascade_path)逻辑说明cv2.data.haarcascades是 OpenCV 内置路径常量指向安装包内的data/目录haarcascade_frontalface_default.xml是最成熟、泛化最好的正面人脸检测器。参数说明无需手动下载 XML——pip install opencv-python已内置若报错找不到可手动下载 GitHub 官方仓库 中的 XML 放入自定义路径。3.3 对单张图片执行脸部检测与中心裁剪输出 256×256 正方形def detect_and_crop_face(image_path, output_dir./dataset/faces, target_size(256, 256)): os.makedirs(output_dir, exist_okTrue) # 读取图片BGR 格式 img cv2.imread(image_path) if img is None: print(f无法读取图片: {image_path}) return None # 转灰度图Haar 只接受单通道 gray cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 检测脸部参数详解见 3.4 节 faces face_cascade.detectMultiScale( gray, scaleFactor1.1, # 每次缩放比例1.05~1.3 间调整 minNeighbors5, # 至少被多少个矩形框包围才认为是脸 minSize(30, 30), # 最小检测尺寸像素过滤过小噪点 flagscv2.CASCADE_SCALE_IMAGE ) if len(faces) 0: print(f未在 {os.path.basename(image_path)} 中检测到人脸) return None # 取最大面积的脸通常为主角 x, y, w, h max(faces, keylambda rect: rect[2] * rect[3]) # 计算正方形裁剪区域以脸中心为原点 center_x, center_y x w // 2, y h // 2 half max(w, h) // 2 * 1.2 # 放大 20% 包含更多脸部上下文 left max(0, int(center_x - half)) top max(0, int(center_y - half)) right min(img.shape[1], int(center_x half)) bottom min(img.shape[0], int(center_y half)) # 裁剪并缩放到目标尺寸 face_roi img[top:bottom, left:right] if face_roi.size 0: return None face_resized cv2.resize(face_roi, target_size, interpolationcv2.INTER_AREA) # 生成输出文件名原文件名 _face_001.jpg base_name os.path.splitext(os.path.basename(image_path))[0] output_path os.path.join(output_dir, f{base_name}_face_001.jpg) cv2.imwrite(output_path, face_resized) print(f已裁剪保存: {output_path} ({face_resized.shape})) return output_path # 示例对 raw 目录下所有图片处理 raw_dir ./dataset/raw for img_file in os.listdir(raw_dir): if img_file.lower().endswith((.jpg, .jpeg, .png)): detect_and_crop_face(os.path.join(raw_dir, img_file))逻辑说明detectMultiScale返回(x,y,w,h)列表max(..., keylambda rect: w*h)取最大脸center_x/y计算确保裁剪框居中half max(w,h)//2 * 1.2是经验值保证额头和下巴完整cv2.INTER_AREA适合缩小画质优于INTER_LINEAR。参数说明scaleFactor1.1是平衡速度与精度的起点若漏检多可降到1.05变慢minNeighbors5过高会漏检过低如2会出多个重叠框。3.4 Haar Cascade 的 3 个必调参数与效果对比附实测截图逻辑参数推荐范围调低影响调高影响实测建议scaleFactor1.05 ~ 1.3检出率↑速度↓需更多尺度遍历检出率↓速度↑跳过小尺度写真图集用1.1证件照用1.05minNeighbors3 ~ 8误检↑噪点被当脸框数↑漏检↑框数↓光照好用5暗光用3minSize(20,20) ~ (60,60)小脸/远脸被漏近距离大脸必检但可能把肩膀当脸写真统一设(30,30)避坑 / 常见问题 / 排查现象detectMultiScale返回空列表但肉眼明显有人脸原因图片过曝/欠曝导致灰度图对比度不足或minSize设得过大如(100,100)解决先cv2.equalizeHist(gray)增强对比度将minSize降至(20,20)测试现象裁剪出的脸严重偏斜如只切到半张脸原因Haar 本身不输出旋转角度x,y,w,h是轴对齐矩形侧脸时 w/h 比异常解决加判断if w/h 0.5 or w/h 2.0: continue过滤畸形框或换 MTCNN见 3.4现象同一张图检测出 5~10 个重叠小框原因minNeighbors设太低如1且scaleFactor过小导致多尺度冗余检测解决提高minNeighbors至5~8或对结果做 NMS非极大值抑制但 Haar 通常不需现象cv2.imread读出全黑/全白图原因图片路径含中文或特殊字符cv2.imread不支持 Unicode 路径Windows 高发解决改用np.fromfile(path, dtypenp.uint8)cv2.imdecode见下方代码import numpy as np def imread_chinese_path(path): 解决 OpenCV 读取中文路径失败问题 img_array np.fromfile(path, dtypenp.uint8) img cv2.imdecode(img_array, cv2.IMREAD_COLOR) return img # 替换原 cv2.imread(image_path) 为 imread_chinese_path(image_path)4. 用 PyTorch DCGAN 训练人脸生成模型从数据加载到 loss 收敛的完整训练循环4.1 为什么 DCGAN 是写真人脸生成的合理起点结构简洁Generator 用ConvTranspose2d上采样Discriminator 用Conv2d下采样无 attention、无 residual调试成本低收敛稳定相比 WGAN-GP 或 StyleGANDCGAN 的 loss 曲线更平滑初学者能直观看到D_loss和G_loss交替下降显存友好在 6GB 显存GTX 1060上可训 128×128 输入Batch Size32可解释性强z向量插值生成序列图能直观验证 latent space 是否解耦如z1→z2过渡中发型/肤色/表情是否独立变化。注意DCGAN 生成质量上限约等于 CelebA 数据集水平清晰但细节略糊若需照片级真实感应升级至 StyleGAN3但需 24GB 显存与 100h 训练时间。4.2 构建人脸数据集 DataLoader自动 resize 归一化import torch from torch.utils.data import Dataset, DataLoader from torchvision import transforms, datasets import os from PIL import Image class FaceDataset(Dataset): def __init__(self, root_dir, transformNone): self.root_dir root_dir self.transform transform or transforms.Compose([ transforms.Resize((128, 128)), # 统一分辨率 transforms.ToTensor(), # [0,255] → [0,1], HWC → CHW transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)) # [-1,1] 归一化 ]) self.image_files [ os.path.join(root_dir, f) for f in os.listdir(root_dir) if f.lower().endswith((.jpg, .jpeg, .png)) ] def __len__(self): return len(self.image_files) def __getitem__(self, idx): img_path self.image_files[idx] try: image Image.open(img_path).convert(RGB) return self.transform(image) except Exception as e: print(f读取 {img_path} 失败: {e}) # 返回空白图占位避免 dataloader 中断 return torch.zeros(3, 128, 128) # 创建 DataLoadernum_workers2 平衡 IO 与内存 dataset FaceDataset(./dataset/faces) dataloader DataLoader( dataset, batch_size32, shuffleTrue, num_workers2, drop_lastTrue # 确保每 batch 大小一致简化 loss 计算 ) print(f数据集大小: {len(dataset)}, Batch 数: {len(dataloader)})逻辑说明transforms.Resize统一分辨率避免 DCGAN 输入尺寸不一致Normalize((0.5,0.5,0.5),(0.5,0.5,0.5))将[0,1]映射到[-1,1]匹配 DCGAN Generator 输出层tanh激活函数drop_lastTrue防止最后一个 batch 尺寸不足引发 shape error。参数说明batch_size32是 GTX 1060 的安全值num_workers2避免主线程阻塞过高如8反而因进程通信开销降低吞吐。4.3 DCGAN Generator 与 Discriminator 的 PyTorch 实现逐层注释import torch.nn as nn # Generator: z (100,) → 128x128 RGB 图像 class Generator(nn.Module): def __init__(self, nz100, ngf64, nc3): # nzz维度, ngffeature map基数, nc通道数 super().__init__() self.main nn.Sequential( # 输入: (nz, 1, 1) → 输出: (ngf*8, 4, 4) nn.ConvTranspose2d(nz, ngf * 8, 4, 1, 0, biasFalse), nn.BatchNorm2d(ngf * 8), nn.ReLU(True), # (ngf*8, 4, 4) → (ngf*4, 8, 8) nn.ConvTranspose2d(ngf * 8, ngf * 4, 4, 2, 1, biasFalse), nn.BatchNorm2d(ngf * 4), nn.ReLU(True), # (ngf*4, 8, 8) → (ngf*2, 16, 16) nn.ConvTranspose2d(ngf * 4, ngf * 2, 4, 2, 1, biasFalse), nn.BatchNorm2d(ngf * 2), nn.ReLU(True), # (ngf*2, 16, 16) → (ngf, 32, 32) nn.ConvTranspose2d(ngf * 2, ngf, 4, 2, 1, biasFalse), nn.BatchNorm2d(ngf), nn.ReLU(True), # (ngf, 32, 32) → (nc, 128, 128) nn.ConvTranspose2d(ngf, nc, 4, 4, 0, biasFalse), nn.Tanh() # 输出范围 [-1,1]匹配 Normalize ) def forward(self, input): return self.main(input) # Discriminator: 128x128 RGB 图像 → 二分类概率 class Discriminator(nn.Module): def __init__(self, nc3, ndf64): # ndfdiscriminator feature map基数 super().__init__() self.main nn.Sequential( # 输入: (nc, 128, 128) → (ndf, 32, 32) nn.Conv2d(nc, ndf, 4, 4, 0, biasFalse), nn.LeakyReLU(0.2, inplaceTrue), # (ndf, 32, 32) → (ndf*2, 16, 16) nn.Conv2d(ndf, ndf * 2, 4, 2, 1, biasFalse), nn.BatchNorm2d(ndf * 2), nn.LeakyReLU(0.2, inplaceTrue), # (ndf*2, 16, 16) → (ndf*4, 8, 8) nn.Conv2d(ndf * 2, ndf * 4, 4, 2, 1, biasFalse), nn.BatchNorm2d(ndf * 4), nn.LeakyReLU(0.2, inplaceTrue), # (ndf*4, 8, 8) → (ndf*8, 4, 4) nn.Conv2d(ndf * 4, ndf * 8, 4, 2, 1, biasFalse), nn.BatchNorm2d(ndf * 8), nn.LeakyReLU(0.2, inplaceTrue), # (ndf*8, 4, 4) → (1, 1, 1) nn.Conv2d(ndf * 8, 1, 4, 1, 0, biasFalse), nn.Sigmoid() # 输出 [0,1] 概率 ) def forward(self, input): return self.main(input).view(-1, 1).squeeze(1) # 展平为 (batch,)逻辑说明Generator 用ConvTranspose2d上采样 4 次1→4→8→16→32→128每次kernel4,stride2,padding1保证尺寸翻倍Discriminator 对称下采样LeakyReLU避免神经元死亡nn.Sigmoid输出判别概率nn.Tanh匹配归一化范围。参数说明nz100是标准 latent vector 维度ngf64/ndf64是 feature map 基数调大提升容量但增加显存nc3固定为 RGB。4.4 训练循环Adam 优化器 BCELoss 梯度惩罚关键技巧import torch.optim as optim import torch.nn.functional as F # 初始化模型与优化器 device torch.device(cuda if torch.cuda.is_available() else cpu) netG Generator(nz100, ngf64, nc3).to(device) netD Discriminator(nc3, ndf64).to(device) optimizerG optim.Adam(netG.parameters(), lr0.0002, betas(0.5, 0.999)) optimizerD optim.Adam(netD.parameters(), lr0.0002, betas(0.5, 0.999)) criterion nn.BCELoss() # 固定噪声用于生成可视化图 fixed_noise torch.randn(64, 100, 1, 1, devicedevice) # 64 张图 # 训练主循环 num_epochs 50 for epoch in range(num_epochs): for i, data in enumerate(dataloader, 0): ############################ # (1) 更新 Discriminator: 最大化 log(D(x)) log(1-D(G(z))) ########################### netD.zero_grad() real_cpu data.to(device) b_size real_cpu.size(0) # 真实标签为 1假标签为 0 label torch.full((b_size,), 1, dtypetorch.float, devicedevice) output netD(real_cpu).view(-1) errD_real criterion(output, label) errD_real.backward() # 生成假图 noise torch.randn(b_size, 100, 1, 1, devicedevice) fake netG(noise) label.fill_(0) output netD(fake.detach()).view(-1) # detach 防止 G 梯度流入 D errD_fake criterion(output, label) errD_fake.backward() errD errD_real errD_fake optimizerD.step() ############################ # (2) 更新 Generator: 最大化 log(D(G(z))) ########################### netG.zero_grad() label.fill_(1) # 假图也想被判为真 output netD(fake).view(-1) errG criterion(output, label) errG.backward() optimizerG.step() # 每 100 batch 打印一次 loss if i % 100 0: print(f[{epoch}/{num_epochs}][{i}/{len(dataloader)}] fLoss_D: {errD.item():.4f} Loss_G: {errG.item():.4f}) # 每 epoch 保存生成图 with torch.no_grad(): fake netG(fixed_noise).detach().cpu() # 反归一化 [-1,1] → [0,1] fake (fake 1) / 2 # 保存为 grid from torchvision.utils import make_grid grid make_grid(fake, nrow8, padding2, normalizeFalse) import matplotlib.pyplot as plt plt.figure(figsize(10,10)) plt.imshow(grid.permute(1,2,0)) plt.axis(off) plt.savefig(f./results/epoch_{epoch:03d}.png) plt.close() # 每 10 epoch 保存模型 if epoch % 10 0: torch.save(netG.state_dict(), f./checkpoints/netG_epoch_{epoch}.pth) torch.save(netD.state_dict(), f./checkpoints/netD_epoch_{epoch}.pth)逻辑说明fake.detach()是关键防止 Discriminator 的梯度意外流入 Generatorlabel.fill_(0/1)复用 tensor 减少内存分配make_grid生成 8×8 可视化图直观监控生成质量。参数说明lr0.0002是 DCGAN 论文推荐值betas(0.5,0.999)中0.5降低一阶动量权重稳定 GAN 训练num_epochs50是写真数据集~2000 张的收敛阈值。4.5 DCGAN 训练的 4 个致命陷阱与绕过方案避坑 / 常见问题 / 排查现象Loss_D迅速降为 0Loss_G居高不下生成图全为噪点或单一色块原因Discriminator 过强轻易判假Generator 无法学习或lr过大导致震荡解决降低lr至0.0001或给 D 加 dropout在Conv2d后加nn.Dropout2d(0.3)或减少 D 的层数现象Loss_G和Loss_D均缓慢下降但生成图始终模糊、无五官原因数据集质量差如人脸未对齐、背景杂乱、或nz100维度不足表达多样性本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?