我下载的DL4J版本是0.9.1。因为没有将源码都贴上,所以阅读时,需要下载DL4J的源码。本文以MLPClassifierLinear为例,分析DL4J的源码流程、架构。
与一般神经网络应用相同,MLPClassifierLinear分为四部分:1、网络初始化;2、数据加载;3、网络定型;4、网络测试。其中,网络定型又可分为三部分:1、信号前传;2、梯度计算;3、误差反传(调优)。本文会按这种结构分析DL4J源码。
看DL4J源码,感觉注释实在太少了。大片的类、成员变量、方法没有一点儿注释。作为API被别人调用,公共方法的注释至少要有吧。
1.1 网络初始化
DL4J使用MultiLayerConfiguration来设定网络的层及其超参数。MLPClassifierLinear中的配置如下:
MultiLayerConfiguration conf = new NeuralNetConfiguration.Builder().seed(seed).iterations(1)
.optimizationAlgo(OptimizationAlgorithm.STOCHASTIC_GRADIENT_DESCENT)
.learningRate(learningRate).updater(Updater.NESTEROVS)
.list()
.layer(0,
new DenseLayer.Builder().nIn(numInputs).nOut(numHiddenNodes)
.weightInit(WeightInit.XAVIER).activation(Activation.RELU).build())
.layer(1, new OutputLayer.Builder(LossFunction.NEGATIVELOGLIKELIHOOD)
.weightInit(WeightInit.XAVIER).activation(Activation.SOFTMAX)
.weightInit(WeightInit.XAVIER).nIn(numHiddenNodes).nOut(numOutputs).build())
.pretrain(false).backprop(true).build();
seed(seed)此方法是为随机生成权重设置种子。如果一个示例运行很多次,而每次开始时都生成一组新的随机权重,那么神经网络的表现(准确率和F1值)有可能会出现很大的差异,因为不同的初始权重可能会将算法导向误差曲面上不同的局部极小值。在其他条件不变的情况下,保持相同的随机权重可以使调整其他超参数所产生的效果表现得更加清晰。
iterations(1)对一个神经网络而言,一次迭代(iteration)指的是一个学习步骤,亦即模型权重的一次更新。神经网络读取数据并对其进行预测,然后根据预测的错误程度来修正自己的参数。因此迭代次数越多,网络的学习步骤和学习量也越多,让误差更接近极小值。我相信说这么多,对于初学者来说还是不太理解iterations(1)的作用。到后面还会遇到其它两个迭代。我们会将这三个不同粒度的迭代放到一起比较,iterations(1)所处的位置就会比较清晰了。
optimizationAlgo (OptimizationAlgorithm.STOCHASTIC_GRADIENT_DESCENT)这个方法是设置了优化阶段使用随机梯度下降算法。优化阶段是梯度计算和误差反传阶段。梯度下降法有批量梯度下降、随机梯度下降和小批量梯度下降。本例中的虽然叫随机梯度下降