目前我的SGD收敛标准检查MSE错误率是否在特定边界内。
def compute_mse(data, labels, weights):
m = len(labels)
hypothesis = np.dot(data,weights)
sq_errors = (hypothesis - labels) ** 2
mse = np.sum(sq_errors)/(2.0*m)
return mse
cur_mse = 1.0
prev_mse = 100.0
m = len(labels)
while cur_mse/prev_mse < 0.99999:
prev_mse = cur_mse
for i in range(m):
d = np.array(data[i])
hypothesis = np.dot(d, weights)
gradient = np.dot((labels[i] - hypothesis), d)/m
weights = weights + (alpha * gradient)
cur_mse = compute_mse(data, labels, weights)
if cur_mse > prev_mse:
return
权重更新w.r.t.到训练集中的单个数据点。
使用0.001的alpha,模型应该在几次迭代中收敛但是我没有收敛。这种收敛标准是否过于严格?
答案 0 :(得分:1)
我会尝试回答这个问题。首先,随机梯度下降的伪代码看起来像这样:
input: f(x), alpha, initial x (guess or random)
output: min_x f(x) # x that minimizes f(x)
while True:
shuffle data # good practice, not completely needed
for d in data:
x -= alpha * grad(f(x)) # df/dx
if <stopping criterion>:
break
可以为要最小化的函数添加其他regularization
个参数,例如l1 penalty
以避免过度拟合。
回到你的问题,查看你的数据和梯度的定义,看起来你想解决一个简单的线性方程组形式:
Ax = b
产生了客观的功能:
f(x) = ||Ax - b||^2
随机梯度下降一次使用一行数据:
||A_i x - b||
其中|| o ||
是欧几里德范数,_i
表示行的索引。
此处A
为data
,x
为weights
,b
为labels
。
然后将函数的梯度计算为:
grad(f(x)) = 2 * A.T (Ax - b)
或者在随机梯度下降的情况下:
2 * A_i.T (A_i x - b)
其中.T
表示转置。
将所有内容放回代码中......首先,我将设置合成数据:
A = np.random.randn(100, 2) # 100x2 data
x = np.random.randn(2, 1) # 2x1 weights
b = np.random.randint(0, 2, 100).reshape(100, 1) # 100x1 labels
b[b == 0] = -1 # labels in {-1, 1}
然后,定义参数:
alpha = 0.001
cur_mse = 100.
prev_mse = np.inf
it = 0
max_iter = 100
m = A.shape[0]
idx = range(m)
然后循环!
while cur_mse/prev_mse < 0.99999 and it < max_iter:
prev_mse = cur_mse
shuffle(idx)
for i in idx:
d = A[i:i+1]
y = b[i:i+1]
h = np.dot(d, x)
dx = 2 * np.dot(d.T, (h - y))
x -= (alpha * dx)
cur_mse = np.mean((A.dot(x) - b)**2)
if cur_mse > prev_mse:
raise Exception("Not converging")
it += 1
此代码几乎与您的代码相同,但增加了几个代码:
基于迭代次数的另一个停止标准(如果系统不收敛或做得太慢,则避免永远循环)
重新定义渐变dx
(仍与您的相似)。您的符号已被反转,因此权重更新为正+
,因为在我的示例中为负-
(因为您在渐变中下降所以有意义)。
data
和labels
的索引编制。虽然data[i]
提供了一个大小为(2,)
的元组(在这种情况下为100x2
数据),但使用花式索引data[i:i+1]
将返回数据视图而不对其进行重新整理(例如具有形状(1, 2)
),因此将允许您执行适当的矩阵乘法。
您可以根据可接受的mse
错误添加第三个停止标准,即:if cur_mse < 1e-3: break
。
该算法具有随机数据,为我收敛20-40次迭代(取决于生成的随机数据)。
所以...假设这是你想要最小化的函数,如果这个方法对你不起作用,可能意味着你的系统未被确定(你的训练数据少于特征,这意味着{{1比...更宽广。)
希望它有所帮助!