忘川彼岸|Zero进行神经网络训练,用PyTorch对Leela


PyTorchLightning:https://github.com/PyTorchLightning/pytorch-lightningHydra:为了练习使用它们 , 我决定为LeelaZero()编写一个训练管道 。 我这样做 , 是因为这是一个范围很广的项目 , 涉及到使用多个gpu在大数据集上训练大型网络 , 可以说是一个十分有趣的技术挑战 。 此外 , 我以前曾经实现过一个更小版本的AlphaGo国际象棋(@peterkeunwoo/beating-my-brother-in-chess-cb17739ffe2) , 所以我认为这将是一个有趣的业余项目 。
代码:
LeelaZero第一步是找出LeelaZero神经网络的内部工作原理 。 我大量引用了LeelaZero的文档和它的Tensorflow训练管道 。
神经网络结构LeelaZero的神经网络由一个残差塔(ResNet“tower”)组成 , 塔上有两个“head” , 即AlphaGoZero论文()中描述的负责策略的“头”(policyhead)和负责计算价值的“头”(valuehead) 。 就像论文所述 , 策略“头”和值“头”开始的那几个卷积滤波器都是1x1 , 其他所有的卷积滤波器都是3x3 。 游戏和棋盘特征被编码为[批次大小 , 棋盘宽度 , 棋盘高度 , 特征数量]形状的张量 , 首先通过残差塔输入 。 然后 , 塔提取出抽象的特征 , 并通过每个“头”输入这些特征 , 以计算下一步棋的策略概率分布和游戏的价值 , 从而预测游戏的获胜者 。
你可以在下面的代码片段中找到网络的实现细节 。
卷积层有2个权重行:
与[output,input,filtersize,filtersize]形状的卷积权值通道的偏差Batchnorm层有2个权重行:
Batchnorm平均值Batchnorm方差内积(完全连接)层有2个权重行:
带有[output,input]形状的层权重输出偏差我编写了单元测试来确保我的权重文件是正确的 。 我使用的另一个简单的完整性检查是计算层的数量 , 在加载我的权值文件后 , 将其与LeelaZero进行比较 。 层数公式为:
n_layers=1(versionnumber)+2(inputconvolution)+2(inputbatchnorm)+n_res(numberofresidualblocks)*8(firstconv+firstbatchnorm+secondconv+secondbatchnorm)+2(policyheadconvolution)+2(policyheadbatchnorm)+2(policyheadlinear)+2(valueheadconvolution)+2(valueheadbatchnorm)+2(valueheadfirstlinear)+2(valueheadsecondlinear)到目前为止 , 这看起来很简单 , 但是你需要注意一个实现细节 。 LeelaZero实际上使用卷积层的偏差来表示下一个归一化层(batchnorm)的可学习参数(gamma和beta) 。 这样做是为了使权值文件的格式(只有一行表示层权值 , 另一行表示偏差)在添加归一化层时不必更改 。
目前 , LeelaZero只使用归一化层的beta项 , 将gamma设置为1 。 那么 , 实际上我们该如何使用卷积偏差 , 来产生与在归一化层中应用可学习参数相同的结果呢?我们先来看看归一化层的方程:
y=gamma*(x—mean)/sqrt(var—eps)+beta由于LeelaZero将gamma设为1 , 则方程为:
y=(x—mean)/sqrt(var—eps)+beta现在 , 设定x_conv是没有偏差的卷积层的输出 。 然后 , 我们想给x_conv添加一些偏差 , 这样当你在没有beta的归一化层中运行它时 , 结果与在只有beta的归一化层方程中运行x_conv是一样的: