95 KiB
95 KiB
In [1]:
import numpy as np
# 生成 1000 个随机样本,假设它们是某个状态的奖励
np.random.seed(42)
samples = np.random.normal(loc=10.0, scale=2.0, size=1000)
print("--- 传统方法 (非增量式) ---")
true_mean = np.mean(samples)
print(f"一次性求平均结果: {true_mean:.4f}")
print("\n--- 增量式均值估计 (Incremental) ---")
w_k = 0.0 # 初始猜测
for k, x_k in enumerate(samples, start=1):
alpha_k = 1 / k # 步长 (对应公式 1/k)
# 核心公式: 新估计 = 老估计 - 步长 * (老估计 - 新样本)
w_k = w_k - alpha_k * (w_k - x_k)
if k in [10, 100, 1000]:
print(f"收到 {k} 个样本后的均值估计: {w_k:.4f}")
print("\n结论:增量式更新完美逼近了真实均值,且不需要保存历史样本!")--- 传统方法 (非增量式) --- 一次性求平均结果: 10.0387 --- 增量式均值估计 (Incremental) --- 收到 10 个样本后的均值估计: 10.8961 收到 100 个样本后的均值估计: 9.7923 收到 1000 个样本后的均值估计: 10.0387 结论:增量式更新完美逼近了真实均值,且不需要保存历史样本!
In [11]:
import matplotlib.pyplot as plt
import numpy as np
# 真实函数 (我们假装不知道它的表达式)
def g(w):
return w**3 - 5
# 带噪声的黑盒观测器
def noisy_observation(w):
noise = np.random.normal(0, 1) # 标准正态分布噪声
return g(w) + noise
w_k = 0.0 # 初始猜测 w1 = 0
w_history = [w_k]
# 迭代 100 次
for k in range(1, 101):
a_k = 0.1 / k # 满足 RM 定理的收敛步长,减小初始步长防止发散
# 观测带噪声的输出
g_tilde = noisy_observation(w_k)
# RM 核心更新公式
w_k = w_k - a_k * g_tilde
w_history.append(w_k)
# 绘图展示收敛过程 (类似图 6.3)
plt.figure(figsize=(8, 4))
plt.plot(range(101), w_history, marker='o', linestyle='-', color='b')
plt.axhline(y=5**(1/3), color='r', linestyle='--', label='True Root (~1.71)')
plt.title('Robbins-Monro Algorithm: Finding root of $w^3 - 5 = 0$ with noise')
plt.xlabel('Iteration index k')
plt.ylabel('Estimated root $w_k$')
plt.legend()
plt.grid(True)
plt.show()In [ ]:
# 目标: 寻找二维平面上一堆散点的中心 (均值)
# 对应优化问题: 最小化均方误差 J(w)
np.random.seed(0)
n_samples = 100
# 在边长 20 的正方形内均匀分布采样,中心(期望)为 [0,0]
X = np.random.uniform(-10, 10, size=(n_samples, 2))
# 初始化
w_init = np.array([20.0, 20.0]) # 故意从很远的地方开始
w_sgd = w_init.copy()
w_mbgd_5 = w_init.copy()
dist_sgd = [np.linalg.norm(w_sgd)]
dist_mbgd_5 = [np.linalg.norm(w_mbgd_5)]
# 模拟前 30 步迭代
for k in range(1, 31):
alpha_k = 1 / k
# SGD: 每次随机抽 1 个样本 [cite: 7173]
idx_sgd = np.random.choice(n_samples, 1)
grad_sgd = w_sgd - X[idx_sgd[0]] # 梯度: w - x
w_sgd = w_sgd - alpha_k * grad_sgd
dist_sgd.append(np.linalg.norm(w_sgd))
# MBGD (m=5): 每次随机抽 5 个样本
idx_mbgd = np.random.choice(n_samples, 5)
grad_mbgd = w_mbgd_5 - np.mean(X[idx_mbgd], axis=0)
w_mbgd_5 = w_mbgd_5 - alpha_k * grad_mbgd
dist_mbgd_5.append(np.linalg.norm(w_mbgd_5))
plt.figure(figsize=(8, 4))
plt.plot(dist_sgd, marker='d', label='SGD (m=1)', alpha=0.7)
plt.plot(dist_mbgd_5, marker='>', label='MBGD (m=5)', alpha=0.7)
plt.title('Distance to True Mean (0,0) over iterations')
plt.xlabel('Iteration step')
plt.ylabel('Distance to mean')
plt.legend()
plt.grid(True)
plt.show()
print("结论:离真值越远,SGD下降得越快;靠近真值时,SGD 会有一定的波动,而 MBGD (使用更多样本) 波动更小。")结论:离真值越远,SGD下降得越快;靠近真值时,SGD 会有一定的波动,而 MBGD (使用更多样本) 波动更小 [cite: 7129-7134]。