一个随机初始化的密集的神经网络包含着一个初始化的子网络(中奖彩票),经过训练后,这个子网络和原始网络经过训练同样的迭代次数之后精度可能会相同甚至更高。
一、算法主要步骤:
1.随机初始化一个神经网络
2.对这个网络训练j个iterations(iterations = batchs = N /batch_size 也等于一个epoch),使网络到达参数
3.将修剪p%,建立一个掩码矩阵m
4.将剩下的权重参数重置为,建立中奖彩票
二、该文献的主要贡献有三点:
2.1.修剪揭示了可训练的子网络,达到了与原始网络相当的测试精度,从原始网络中得到了相当数量的迭代。
2.2.修剪发现中奖彩票的学习速率比原始网络更快,同时达到更高的测试准确性和更好的泛化。
2.3.提出彩票假设作为神经网络剪枝的新视角。
三、构建迭代修剪策略的两种不同方法
3.1带有重置的迭代修剪
1.随机初始化一个神经网络,其中
m是一个掩码矩阵
2.训练j次,使网络参数为
3.修剪s%的参数,更新掩码矩阵 其中
4.将网络剩余部分的权重置为,
5.让,并重复第2-4步
3.2持续训练的迭代修剪
1.随机初始化一个神经网络,其中
m是一个掩码矩阵
2.训练j次
3.修剪s%的参数,更新掩码矩阵 其中
4.让,并重复第2-3步
5.让网络剩余部分的权重置为
四、原文附带剪枝函数代码
def prune_by_percent(percents, masks, final_weights):
"""percents 一个字典,用于指定每个层应该剪枝多少百分比
masks 一个字典,用于存储每个层的当前剪枝掩码
final_weights 最后一次训练后的权重。
"""
def prune_by_percent_once(percent, mask, final_weight):
"""
prune_by_percent_once 的内部函数,该函数用于按百分比剪枝每个层的权重,返回更新后的剪枝掩码
percent 表示要剪枝多少百分比的权重
mask 表示当前的掩码
final_weight 表示最后一次训练后的权重
"""
# 将未被掩码屏蔽的权重按照绝对值大小排序
sorted_weights = np.sort(np.abs(final_weight[mask == 1]))
# 计算应该被剪枝的权重阈值
cutoff_index = np.round(percent * sorted_weights.size).astype(int)
cutoff = sorted_weights[cutoff_index]
# 将低于该阈值的权重所对应的掩码置为零.
return np.where(np.abs(final_weight) <= cutoff, np.zeros(mask.shape), mask)
new_masks = {}
for k, percent in percents.items():
new_masks[k] = prune_by_percent_once(percent, masks[k], final_weights[k])
#返回更新后的剪枝掩码
return new_masks