【问题标题】:How to use mini-batch instead of SGD如何使用 mini-batch 代替 SGD
【发布时间】:2016-11-20 22:27:58
【问题描述】:

下面是一个用python快速实现的单层神经网络:

import numpy as np

# simulate data
np.random.seed(94106)
X = np.random.random((200, 3)) # 100 3d vectors
# first col is set to 1
X[:, 0] = 1
def simu_out(x):
    return np.sum(np.power(x, 2))
y = np.apply_along_axis(simu_out, 1, X)
# code 1 if above average
y = (y > np.mean(y)).astype("float64")*2 - 1
# split into training and testing sets
Xtr = X[:100]
Xte = X[100:]
ytr = y[:100]
yte = y[100:]
w = np.random.random(3)

# 1 layer network. Final layer has one node
# initial weights,
def epoch():
    err_sum = 0
    global w
    for i in range(len(ytr)):
        learn_rate = .1
        s_l1 = Xtr[i].T.dot(w) # signal at layer 1, pre-activation
        x_l1 = np.tanh(s_l1) # output at layer 1, activation
        err = x_l1 - ytr[i]
        err_sum += err
        # see here: https://youtu.be/Ih5Mr93E-2c?t=51m8s
        delta_l1 = 2 * err * (1 - x_l1**2)
        dw = Xtr[i] * delta_l1
        w -= learn_rate * dw
    print("Mean error: %f" % (err_sum / len(ytr)))
epoch()
for i in range(1000):
    epoch()

def predict(X):
    global w
    return np.sign(np.tanh(X.dot(w)))

# > 80% accuracy!!
np.mean(predict(Xte) == yte)

它使用随机梯度下降进行优化。我在想如何在这里应用小批量梯度下降?

【问题讨论】:

    标签: python machine-learning neural-network


    【解决方案1】:

    “经典”SGD 与小批量梯度下降的区别在于您使用多个样本(所谓的小批量)来计算 w 的更新。这样做的好处是,您在解决方案方向上采取的步骤噪音较小,因为您遵循平滑的梯度。

    为此,您需要一个内部循环来计算更新dw,您可以在其中迭代小批量。例如(quick-n-dirty code):

    def epoch(): 
        err_sum = 0
        learn_rate = 0.1
        global w
        for i in range(int(ceil(len(ytr) / batch_size))):
            batch = Xtr[i:i+batch_size]
            target = ytr[i:i+batch_size]
            dw = np.zeros_like(w)
            for j in range(batch_size):
                s_l1 = batch[j].T.dot(w)
                x_l1 = np.tanh(s_l1)
                err = x_l1 - target[j]
                err_sum += err
                delta_l1 = 2 * err * (1 - x_l1**2)
                dw += batch[j] * delta_l1
            w -= learn_rate * (dw / batch_size)
        print("Mean error: %f" % (err_sum / len(ytr)))
    

    在测试中给出了 87% 的准确率。

    现在,还有一件事:您总是从头到尾遍历训练集。您绝对应该shuffle 每次迭代中的数据。总是以相同的顺序进行会真正影响你的表现,尤其是如果你首先是 A 类的所有样本,然后是 B 类的所有样本。这也可以让你的训练循环进行。所以只需以随机顺序浏览集合,例如与

    order = np.random.permutation(len(ytr))
    

    并在epoch() 函数中将所有出现的i 替换为order[i]

    还有一个更笼统的评论:全局变量通常被认为是糟糕的设计,因为您无法控制哪个 sn-p 修改您的变量。而是将w 作为参数传递。学习率和批量大小也是如此。

    【讨论】:

    • 不错的答案。我知道全局变量的丑陋,当你快速破解一些东西时它很方便。 :-)
    • 当然可以,而且您确实在问题中写了“快速实现”,所以我知道您没有花时间以“不错”的方式制作它(还)。我仍然会在此处留下评论,因为可能不是每个 stackoverflow 用户都会意识到这一点,并且有人可能只是复制代码而不质疑它。
    猜你喜欢
    • 2017-09-29
    • 2020-10-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-08
    • 1970-01-01
    • 2020-03-03
    相关资源
    最近更新 更多