我正在尝试提取图层激活以将其本地保存为要素。
我对CNN还是陌生的,所以我想展示自己的所作所为,并想知道我在做什么是否正确:
public static void main(String[] args) throws IOException {
ComputationGraph vgg16transfer = getComputationGraph();
for (File file : new File(ImageClassifier.class.getClassLoader().getResource("mydirectory").getFile()).listFiles()) {
Map<String, INDArray> stringINDArrayMap = extractTwo(file, vgg16transfer);
//Extract the features from the last fully connected layers
saveCompressed(file,stringINDArrayMap.get("fc2"));
}
}
/**
* Retrieves the VGG16 computation graph
* @return ComputationGraph from the pretrained VGG16
* @throws IOException
*/
public static ComputationGraph getComputationGraph() throws IOException {
ZooModel zooModel = new VGG16();
return (ComputationGraph) zooModel.initPretrained(PretrainedType.IMAGENET);
}
/**
* Compresses the input INDArray and writes it to file
* @param imageFile the original image file
* @param array INDArray to be saved (features)
* @throws IOException
*/
private static void saveCompressed(File imageFile, INDArray array) throws IOException {
INDArray compress = BasicNDArrayCompressor.getInstance().compress(array);
Nd4j.write(compress,new DataOutputStream(new FileOutputStream(new File("features/" + imageFile.getName()+ "feat"))));
}
/**
* Given an input image and a ComputationGraph it calls the feedForward method after rescaling the image.
* @param imageFile the image whose features need to be extracted
* @param vgg16 the ComputationGraph to be used.
* @return a map of activations for each layer
* @throws IOException
*/
public static Map<String, INDArray> extractTwo(File imageFile, ComputationGraph vgg16) throws IOException {
// Convert file to INDArray
NativeImageLoader loader = new NativeImageLoader(224, 224, 3);
INDArray image = loader.asMatrix(imageFile);
// Mean subtraction pre-processing step for VGG
DataNormalization scaler = new VGG16ImagePreProcessor();
scaler.transform(image);
//Call the feedForward method to get a map of activations for each layer
return vgg16.feedForward(image, false);
}
因此,基本上,我正在调用feedForward方法并从fc2层获取激活信息。
我对此有几个问题:
1)我编写的代码是否确实提取了可以保存和存储以备将来使用的功能?
2)我将如何对提取的功能进行PCA /美白?
3)有什么方法可以按照提议将其编码为VLAD,但此类论文:https://arxiv.org/pdf/1707.00058.pdf
4)然后,我想比较保存的特征,我这样做是使用简单的欧几里德距离进行的,尽管结果不是最好的,但似乎可以正常工作。我应该做某种预处理吗?还是保存的功能可以直接比较?
谢谢。
最佳答案
对于提取的功能,Nd4j具有可使用的PCA:
https://github.com/deeplearning4j/nd4j/blob/master/nd4j-backends/nd4j-api-parent/nd4j-api/src/main/java/org/nd4j/linalg/dimensionalityreduction/PCA.java
不过,这有点多余。我会考虑直接使用转学。您无需手动执行任何此操作。
有关更多示例,请参见此处的文档:
https://github.com/deeplearning4j/dl4j-examples/blob/master/dl4j-spark-examples/dl4j-spark/src/main/java/org/deeplearning4j/transferlearning/vgg16/TransferLearning.md
迁移学习API将为您提供使用预训练模型所需的内容,同时仅对预训练模型进行修改以使用其他输出层。在上面的示例中,我们甚至使用VGG16进行了介绍。