基于梯度法的L2正则化最小二乘图像去噪代码无效果问题求助
问题排查与修正方案
让我来帮你梳理代码中的问题,你遇到的去噪效果不佳主要源于几个关键错误:
1. 学习率过小,迭代收敛速度极慢
你的优化问题是逐像素独立的(因为L2正则化和平方损失都是逐像素运算),其闭式解为:
$$x^* = \frac{y}{1+\lambda}$$
也就是说每个像素的最优解是含噪像素值除以$(1+\lambda)$。
而梯度下降的收敛速度严重依赖学习率:
- 目标函数的Lipschitz常数$L=2(1+\lambda)$,当$\lambda=5$时,$L=12$,所以学习率$p$的合理上限是$\frac{1}{L}≈0.083$。
- 你设置的$p=0.0001$远小于这个值,即使迭代600次,参数更新的幅度也极小,几乎和初始的含噪图像没有差异。
2. PSNR计算逻辑错误
你连续两次对psnr变量赋值,第二次会直接覆盖第一次的结果,而且没有打印最终的PSNR值,导致无法直观看到去噪后的指标变化。
3. 冗余代码未清理
你导入了scipy.ndimage.filters但并未使用,可以移除该导入语句,让代码更简洁。
修正后的代码
import numpy as np from skimage import img_as_float from skimage.util import random_noise from skimage.metrics import peak_signal_noise_ratio # 生成测试图像(换成真实图像效果更直观,这里用随机图像演示) img = img_as_float(np.random.random((2, 2))) # 添加高斯噪声 noise = np.random.normal(0, 1, size=(2, 2)) * 0.2 img_noise = img + noise # 修正学习率和迭代次数 p = 0.01 # 处于合理收敛步长范围内 N = 100 # 足够收敛的迭代次数 Lambda = 5 Cur_u = img_noise weight_history = [] print("原始图像:\n", img) print("含噪图像:\n", img_noise) for k in range(N): Prev_u = Cur_u # 梯度更新公式本身是正确的,这里保留 Cur_u = Prev_u - p * (2 * (Prev_u - img_noise) + 2 * Lambda * Prev_u) weight_history.append(Cur_u) # 计算并打印PSNR对比 psnr_noise = peak_signal_noise_ratio(img, img_noise) psnr_denoised = peak_signal_noise_ratio(img, weight_history[-1]) print(f"含噪图像PSNR: {psnr_noise:.2f} dB") print(f"去噪后图像PSNR: {psnr_denoised:.2f} dB") print("去噪后图像:\n", weight_history[-1]) # 对比闭式解验证结果正确性 closed_form_solution = img_noise / (1 + Lambda) print("闭式解结果(最优解):\n", closed_form_solution)
效果说明
修正后:
- 去噪后的图像会接近闭式解的结果,和含噪图像有明显差异
- PSNR值会比含噪图像显著提升
- 如果换成真实图像(比如用
img = img_as_float(Image.open("your_image.jpg").convert("L"))),视觉上的去噪效果会更直观
内容的提问来源于stack exchange,提问作者fatemeh hirbodvash
相关产品推荐
相关产品推荐

