根据Nielsen存储库中的代码,绘制了迷你批而不进行替换:
def SGD(self, training_data, epochs, mini_batch_size, eta, test_data=None):
n = len(training_data)
for j in range(epochs):
random.shuffle(training_data)
mini_batches = [
training_data[k:k+mini_batch_size]
for k in range(0, n, mini_batch_size)
]
for mini_batch in mini_batches:
self.update_mini_batch(mini_batch, eta)
我们可以看到在一个纪元内没有替换训练样本。有趣的是,我们还可以看到尼尔森选择不担心eta
针对最后一个mini_batch大小进行调整(学习率),后者可能没有以前的mini-batch那样多的训练样本。大概这是他留给以后章节的高级修改。**
**编辑:实际上,此缩放发生在def update_mini_batch
函数中。例如,使用权重:
self.weights = [w-(eta/len(mini_batch))*nw for w, nw in zip(self.weights, nabla_w)]
这是必要的,因为如果每个mini_batch的训练样本数未均等地划分为可用的训练样本总数,则最后一个mini_batch可能小于先前的mini_batches。
mylist = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']
n = len(mylist)
mini_batch_size = 2
mini_batches = [
mylist[k:k+mini_batch_size]
for k in range(0, n, mini_batch_size)
]
for mini_batch in mini_batches:
print(mini_batch)
输出:
['1', '2']
['3', '4']
['5', '6']
['7', '8']
['9', '10']
更改mini_batch_size
为3
,不能将其平均分为10个训练样本。对于输出,我们得到:
['1', '2', '3']
['4', '5', '6']
['7', '8', '9']
['10']
在评估列表索引的范围时(形式为[x:y]
where x
和y
list中的一些索引),如果我们的右边值超出列表长度,python会简单地从列表中返回所有项目,直到该值超出索引范围。
因此,最后的迷你批处理可能比以前的迷你批处理小,但是如果将其按相同的权重进行加权,则与eta
其他较大的迷你批处理中的样本相比,这些训练样本将对学习做出更大的贡献。由于这只是最后一个迷你批处理,因此可能不必担心太多,但可以通过缩放eta
至迷你批处理的长度轻松解决。