有没有办法在 DL4J 中更改神经网络的拓扑结构而无需重新训练?
Is there a way to change a neural network's topology in DL4J without having to retrain it?
我需要对已经训练过的现有 deeplearning4j (DL4J) 模型进行更改。该网络由一个输入层、一个 Graves LSTM 和一个 RNN 输出层组成。
我的问题是:是否可以将一个或多个未经训练的神经元添加到 LSTM 层,而无需从新配置重建模型(我认为这需要重新训练)?我想做一些事情,例如,将一个或多个神经元添加到现有层,或将整个层(未训练)添加到训练模型。
这些可能吗?我找不到对此的任何参考,但我看到人们在其他 languages/frameworks 中这样做,所以我想知道我是否也可以在 DL4J 中这样做。
顺便说一句,我知道这是一件不寻常的事情。请忽略它会弄乱训练有素的网络这一事实,我只需要知道我是否可以做到以及如何去做。 :)
任何指点都会有所帮助!
谢谢!
爱德华多
您可以使用迁移学习 api 来做到这一点。请在此处查看我们的示例。
https://github.com/deeplearning4j/dl4j-examples/blob/master/dl4j-spark-examples/dl4j-spark/src/main/java/org/deeplearning4j/transferlearning/vgg16/TransferLearning.md
以下文档:
DL4J 的迁移学习API
概览
DL4J 迁移学习 API 使用户能够:
- 修改现有模型的架构
- 微调现有模型的学习配置。
- 在训练期间保持指定层的参数不变,也称为“冻结”
将某些层冻结在网络上并进行训练实际上与对输入的转换版本进行训练相同,转换版本是冻结层边界处的中间输出。这是从输入数据中“提取特征”的过程,在本文中称为“特征化”。
迁移学习助手
在大型相关网络上“特征化”输入数据的前向传递可能非常耗时。 DL4J 还提供了具有以下功能的 TransferLearningHelper class。
- 特征化输入数据集以保存以备将来使用
- 用特征化数据集拟合具有冻结层的模型
- 在给定特征化输入的情况下,具有冻结层的模型的输出。
当 运行 多个 epochs 用户将节省计算时间,因为冻结 layers/vertices 上昂贵的前向传播只需要进行一次。
显示代码
此示例将使用 VGG16 classify 属于五类花卉的图像。数据集将从 http://download.tensorflow.org/example_images/flower_photos.tgz
自动下载
一、导入VGG16
TrainedModelHelper modelImportHelper = new TrainedModelHelper(TrainedModels.VGG16);
ComputationGraph org.deeplearning4j.transferlearning.vgg16 = modelImportHelper.loadModel();
二。设置微调配置
FineTuneConfiguration fineTuneConf = new FineTuneConfiguration.Builder()
.learningRate(5e-5)
.updater(Updater.NESTEROVS)
.seed(seed)
.build();
三、基于VGG16构建新模型
A.Modifying只有最后一层,其他都冻结
VGG16 的最后一层对 ImageNet 中的 1000 classes 进行 softmax 回归。我们修改最后一层以给出五个 classes 的预测,同时保持其他层冻结。
ComputationGraph vgg16Transfer = new TransferLearning.GraphBuilder(org.deeplearning4j.transferlearning.vgg16)
.fineTuneConfiguration(fineTuneConf)
.setFeatureExtractor(“fc2”)
.removeVertexKeepConnections("predictions")
.addLayer(“predictions”,
new OutputLayer.Builder(LossFunctions.LossFunction.NEGATIVELOGLIKELIHOOD)
.nIn(4096).nOut(numClasses)
.weightInit(WeightInit.Xavier)
.activation(Activation.SOFTMAX).build(), ”fc2")
.build();
经过仅仅 30 次迭代(在本例中是暴露于 450 张图像)之后,该模型在测试数据集上的准确度 > 75%。考虑到从头开始训练图像 classifier 的复杂性,这是相当了不起的。
B. 将新层附加到瓶颈 (block5_pool)
在这里,我们将除最后三个致密层之外的所有致密层都冻结,并在其上附加新的致密层。请注意,这里的主要目的是演示 API 的使用,其次是可能会提供更好的结果。
ComputationGraph vgg16Transfer = new TransferLearning.GraphBuilder(org.deeplearning4j.transferlearning.vgg16)
.fineTuneConfiguration(fineTuneConf)
.setFeatureExtractor("block5_pool")
.nOutReplace("fc2",1024, WeightInit.XAVIER)
.removeVertexAndConnections("predictions")
.addLayer(“fc3",new DenseLayer.Builder()
.activation(Activation.RELU)
.nIn(1024).nOut(256).build(),"fc2")
.addLayer(“newpredictions”,new OutputLayer
.Builder(LossFunctions.LossFunction.NEGATIVELOGLIKELIHOOD)
.activation(Activation.SOFTMAX)
.nIn(256).nOut(numClasses).build(),”fc3")
.setOutputs("newpredictions")
.build();
C. 从先前保存的模型微调图层
假设我们已经从 (B) 中保存了我们的模型,现在想要允许“block_5”层进行训练。
ComputationGraph vgg16FineTune = new TransferLearning.GraphBuilder(vgg16Transfer)
.fineTuneConfiguration(fineTuneConf)
.setFeatureExtractor(“block4_pool”)
.build();
四、保存“特征化”数据集并使用它们进行训练。
我们使用迁移学习助手API。请注意,这会冻结传入的模型层。
下面是获取指定层“fc2”数据集的特征版本的方法。
TransferLearningHelper transferLearningHelper =
new TransferLearningHelper(org.deeplearning4j.transferlearning.vgg16, “fc2”);
while(trainIter.hasNext()) {
DataSet currentFeaturized = transferLearningHelper.featurize(trainIter.next());
saveToDisk(currentFeaturized,trainDataSaved,true);
trainDataSaved++;
}
以下是如何适应特色数据集。 vgg16Transfer 是第 III 节 (A) 中的模型设置。
TransferLearningHelper transferLearningHelper =
new TransferLearningHelper(vgg16Transfer);
while (trainIter.hasNext()) {
transferLearningHelper.fitFeaturized(trainIter.next());
}
注意事项:
- TransferLearning 构建器 returns dl4j 模型的新实例。
请记住,这是第二个模型,原始模型保持不变。对于大型相关网络,请考虑内存要求并相应地调整 JVM 堆 space。
- 经过训练的模型助手从 Keras 导入模型而不强制执行训练配置。
因此最后一层(如打印摘要时所见)是密集层而不是具有损失函数的输出层。因此,为了修改输出层的 nOut,我们删除层顶点,保留它的连接并添加回具有相同名称的新输出层、不同的 nOut、合适的损失函数等。
- 更改 layer/vertex 处的 nOuts 将修改扇入的 layers/vertices 的 nIn。
当更改 nOut 时,用户可以指定层的权重初始化方案或分布,以及它扇出的层的单独权重初始化方案或分布。
- 将模型写入磁盘时不保存冻结层配置。
换句话说,具有冻结层的模型在序列化和读回时不会有任何冻结层。为了继续训练保持特定层不变,用户需要通过迁移学习助手或迁移学习 API。在 dl4j 模型中有两种“冻结”层的方法。
- On a copy: With the transfer learning API which will return a new model with the relevant frozen layers
- In place: With the transfer learning helper API which will apply the frozen layers to the given model.
- FineTune 配置将有选择地更新学习参数。
例如,如果指定了学习率,则该学习率将应用于模型中的所有 unfrozen/trainable 层。但是,新添加的层可以通过在层构建器中指定自己的学习率来覆盖此学习率。
我需要对已经训练过的现有 deeplearning4j (DL4J) 模型进行更改。该网络由一个输入层、一个 Graves LSTM 和一个 RNN 输出层组成。
我的问题是:是否可以将一个或多个未经训练的神经元添加到 LSTM 层,而无需从新配置重建模型(我认为这需要重新训练)?我想做一些事情,例如,将一个或多个神经元添加到现有层,或将整个层(未训练)添加到训练模型。
这些可能吗?我找不到对此的任何参考,但我看到人们在其他 languages/frameworks 中这样做,所以我想知道我是否也可以在 DL4J 中这样做。
顺便说一句,我知道这是一件不寻常的事情。请忽略它会弄乱训练有素的网络这一事实,我只需要知道我是否可以做到以及如何去做。 :)
任何指点都会有所帮助!
谢谢!
爱德华多
您可以使用迁移学习 api 来做到这一点。请在此处查看我们的示例。 https://github.com/deeplearning4j/dl4j-examples/blob/master/dl4j-spark-examples/dl4j-spark/src/main/java/org/deeplearning4j/transferlearning/vgg16/TransferLearning.md
以下文档:
DL4J 的迁移学习API
概览
DL4J 迁移学习 API 使用户能够:
- 修改现有模型的架构
- 微调现有模型的学习配置。
- 在训练期间保持指定层的参数不变,也称为“冻结”
将某些层冻结在网络上并进行训练实际上与对输入的转换版本进行训练相同,转换版本是冻结层边界处的中间输出。这是从输入数据中“提取特征”的过程,在本文中称为“特征化”。
迁移学习助手
在大型相关网络上“特征化”输入数据的前向传递可能非常耗时。 DL4J 还提供了具有以下功能的 TransferLearningHelper class。
- 特征化输入数据集以保存以备将来使用
- 用特征化数据集拟合具有冻结层的模型
- 在给定特征化输入的情况下,具有冻结层的模型的输出。
当 运行 多个 epochs 用户将节省计算时间,因为冻结 layers/vertices 上昂贵的前向传播只需要进行一次。
显示代码
此示例将使用 VGG16 classify 属于五类花卉的图像。数据集将从 http://download.tensorflow.org/example_images/flower_photos.tgz
自动下载 一、导入VGG16
TrainedModelHelper modelImportHelper = new TrainedModelHelper(TrainedModels.VGG16);
ComputationGraph org.deeplearning4j.transferlearning.vgg16 = modelImportHelper.loadModel();
FineTuneConfiguration fineTuneConf = new FineTuneConfiguration.Builder()
.learningRate(5e-5)
.updater(Updater.NESTEROVS)
.seed(seed)
.build();
VGG16 的最后一层对 ImageNet 中的 1000 classes 进行 softmax 回归。我们修改最后一层以给出五个 classes 的预测,同时保持其他层冻结。
ComputationGraph vgg16Transfer = new TransferLearning.GraphBuilder(org.deeplearning4j.transferlearning.vgg16)
.fineTuneConfiguration(fineTuneConf)
.setFeatureExtractor(“fc2”)
.removeVertexKeepConnections("predictions")
.addLayer(“predictions”,
new OutputLayer.Builder(LossFunctions.LossFunction.NEGATIVELOGLIKELIHOOD)
.nIn(4096).nOut(numClasses)
.weightInit(WeightInit.Xavier)
.activation(Activation.SOFTMAX).build(), ”fc2")
.build();
经过仅仅 30 次迭代(在本例中是暴露于 450 张图像)之后,该模型在测试数据集上的准确度 > 75%。考虑到从头开始训练图像 classifier 的复杂性,这是相当了不起的。
在这里,我们将除最后三个致密层之外的所有致密层都冻结,并在其上附加新的致密层。请注意,这里的主要目的是演示 API 的使用,其次是可能会提供更好的结果。
ComputationGraph vgg16Transfer = new TransferLearning.GraphBuilder(org.deeplearning4j.transferlearning.vgg16)
.fineTuneConfiguration(fineTuneConf)
.setFeatureExtractor("block5_pool")
.nOutReplace("fc2",1024, WeightInit.XAVIER)
.removeVertexAndConnections("predictions")
.addLayer(“fc3",new DenseLayer.Builder()
.activation(Activation.RELU)
.nIn(1024).nOut(256).build(),"fc2")
.addLayer(“newpredictions”,new OutputLayer
.Builder(LossFunctions.LossFunction.NEGATIVELOGLIKELIHOOD)
.activation(Activation.SOFTMAX)
.nIn(256).nOut(numClasses).build(),”fc3")
.setOutputs("newpredictions")
.build();
假设我们已经从 (B) 中保存了我们的模型,现在想要允许“block_5”层进行训练。
ComputationGraph vgg16FineTune = new TransferLearning.GraphBuilder(vgg16Transfer)
.fineTuneConfiguration(fineTuneConf)
.setFeatureExtractor(“block4_pool”)
.build();
我们使用迁移学习助手API。请注意,这会冻结传入的模型层。
下面是获取指定层“fc2”数据集的特征版本的方法。
TransferLearningHelper transferLearningHelper =
new TransferLearningHelper(org.deeplearning4j.transferlearning.vgg16, “fc2”);
while(trainIter.hasNext()) {
DataSet currentFeaturized = transferLearningHelper.featurize(trainIter.next());
saveToDisk(currentFeaturized,trainDataSaved,true);
trainDataSaved++;
}
以下是如何适应特色数据集。 vgg16Transfer 是第 III 节 (A) 中的模型设置。
TransferLearningHelper transferLearningHelper =
new TransferLearningHelper(vgg16Transfer);
while (trainIter.hasNext()) {
transferLearningHelper.fitFeaturized(trainIter.next());
}
注意事项:
- TransferLearning 构建器 returns dl4j 模型的新实例。
请记住,这是第二个模型,原始模型保持不变。对于大型相关网络,请考虑内存要求并相应地调整 JVM 堆 space。
- 经过训练的模型助手从 Keras 导入模型而不强制执行训练配置。
因此最后一层(如打印摘要时所见)是密集层而不是具有损失函数的输出层。因此,为了修改输出层的 nOut,我们删除层顶点,保留它的连接并添加回具有相同名称的新输出层、不同的 nOut、合适的损失函数等。
- 更改 layer/vertex 处的 nOuts 将修改扇入的 layers/vertices 的 nIn。
当更改 nOut 时,用户可以指定层的权重初始化方案或分布,以及它扇出的层的单独权重初始化方案或分布。
- 将模型写入磁盘时不保存冻结层配置。
换句话说,具有冻结层的模型在序列化和读回时不会有任何冻结层。为了继续训练保持特定层不变,用户需要通过迁移学习助手或迁移学习 API。在 dl4j 模型中有两种“冻结”层的方法。
- On a copy: With the transfer learning API which will return a new model with the relevant frozen layers
- In place: With the transfer learning helper API which will apply the frozen layers to the given model.
- FineTune 配置将有选择地更新学习参数。
例如,如果指定了学习率,则该学习率将应用于模型中的所有 unfrozen/trainable 层。但是,新添加的层可以通过在层构建器中指定自己的学习率来覆盖此学习率。