深度学习Deeplearning4j 入门实战(5):基于多层感知机的Mnist压缩以及在Spark实现

在上一篇博客中,我们用基于RBM的的Deep AutoEncoder对Mnist数据集进行压缩,应该说取得了不错的效果。这里,我们将神经网络这块替换成传统的全连接的前馈神经网络对Mnist数据集进行压缩,看看两者的效果有什么异同。整个代码依然是利用Deeplearning4j进行实现,并且为了方便以后的扩展,我们将其与Spark平台结合。下面,就具体来说一下模型的结构、训练过程以及最终的压缩效果。

首先,我们新建Maven工程并加入Deeplearning4j的相关依赖(这一块内容在之前的文章中多次提及,因此这里就不再啰嗦了)。接下来,我们新建Spark任务,读取已经存放在HDFS上的Mnist数据集(和之前文章中提到的一样,Mnist数据集已经事先以JavaRDD<DataSet>的形式存储在HDFS上,具体操作可以参考之前的博客。),并生成训练数据集JavaRDD。具体代码如下:

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. SparkConf conf = new SparkConf()  
  2.                     .set("spark.kryo.registrator""org.nd4j.Nd4jRegistrator")  
  3.                     .setAppName("MLP AutoEncoder Mnist(Java)");  
  4. JavaSparkContext jsc = new JavaSparkContext(conf);  
  5. //  
  6. final String inputPath = args[0];  
  7. final String savePath = args[1];  
  8. double lr = Double.parseDouble(args[2]);  
  9. final int batchSize = Integer.parseInt(args[3]);  
  10. final int numEpoch = Integer.parseInt(args[4]);  
  11. //  
  12. JavaRDD<DataSet> javaRDDMnist = jsc.objectFile(inputPath);//read mnist data from HDFS  
  13. JavaRDD<DataSet> javaRDDTrain = javaRDDMnist.map(new Function<DataSet, DataSet>() {  
  14.   
  15.     @Override  
  16.     public DataSet call(DataSet next) throws Exception {  
  17.         return new DataSet(next.getFeatureMatrix(),next.getFeatureMatrix());  
  18.     }  
  19. });  

构筑完训练数据集之后,我们就可以定义网络结构并配以相应的超参数:

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. MultiLayerConfiguration netconf = new NeuralNetConfiguration.Builder()  
  2.         .seed(123)  
  3.         .iterations(1)  
  4.         .learningRate(lr)  
  5.         .learningRateScoreBasedDecayRate(0.5)  
  6.         .optimizationAlgo(OptimizationAlgorithm.STOCHASTIC_GRADIENT_DESCENT)  
  7.         .updater(Updater.ADAM).adamMeanDecay(0.9).adamVarDecay(0.999)  
  8.         .list()  
  9.         .layer(0new DenseLayer.Builder().nIn(784).nOut(1000).activation("relu").build())  
  10.         .layer(1new DenseLayer.Builder().nIn(1000).nOut(500).activation("relu").build())  
  11.         .layer(2new DenseLayer.Builder().nIn(500).nOut(250).activation("relu").build())  
  12.         .layer(3new DenseLayer.Builder().nIn(250).nOut(500).activation("relu").build())  
  13.         .layer(4new DenseLayer.Builder().nIn(500).nOut(1000).activation("relu").build())  
  14.         .layer(5new OutputLayer.Builder(LossFunctions.LossFunction.MSE)  
  15.                                 .nIn(1000)  
  16.                                 .nOut(784)  
  17.                                 .activation("relu")  
  18.                                 .build())  
  19.         .backprop(true).pretrain(false)  
  20.         .build();  
  21. ParameterAveragingTrainingMaster trainMaster = new ParameterAveragingTrainingMaster.Builder(batchSize)  
  22.                                                     .workerPrefetchNumBatches(0)  
  23.                                                     .saveUpdater(true)  
  24.                                                     .averagingFrequency(5)  
  25.                                                     .batchSizePerWorker(batchSize)  
  26.                                                     .build();  
  27. MultiLayerNetwork net = new MultiLayerNetwork(netconf);  
  28. net.init();  
  29. SparkDl4jMultiLayer sparkNetwork = new SparkDl4jMultiLayer(jsc, net, trainMaster);  
  30. sparkNetwork.setListeners(Collections.<IterationListener>singletonList(new ScoreIterationListener(1)));  
这里我们做一些简要的说明:我们一共定义了5层的神经网络,并且每一层都是普通的全连接网络。学习率等超参数可以通过入口参数传递进来,损失函数用的是均方误差。后面的ParameterAveragingTrainingMaster以及Spark网络的定义在之前的文章中有过说明,这里就略过了。

那么,接下来就是训练的代码:

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. forint i = 0; i < numEpoch; ++i ){  
  2.             sparkNetwork.fit(javaRDDTrain);   //train modek  
  3.             System.out.println("----- Epoch " + i + " complete -----");  
  4.             MultiLayerNetwork trainnet = sparkNetwork.getNetwork();  
  5.             System.out.println("Epoch " + i + " Score: " + sparkNetwork.getScore());  
  6.             List<DataSet> listDS = javaRDDTrain.takeSample(false50);   
  7.             for( DataSet ds : listDS ){   
  8.                 INDArray testFeature = ds.getFeatureMatrix();   
  9.                 INDArray testRes = trainnet.output(testFeature);   
  10.                 System.out.println("Euclidean Distance: " + testRes.distance2(testFeature));   
  11.             }  
  12.             DataSet first = listDS.get(0);   
  13.             INDArray testFeature = first.getFeatureMatrix();   
  14.             double[] doubleFeature = testFeature.data().asDouble();   
  15.             INDArray testRes = trainnet.output(testFeature);   
  16.             double[] doubleRes = testRes.data().asDouble();   
  17.             forint j = 0; j < doubleFeature.length && j < doubleRes.length; ++j ){   
  18.                 double f = doubleFeature[j]; double t = doubleRes[j];   
  19.                 System.out.print(f + ":" + t + " ");   
  20.             }   
  21.             System.out.println();   
  22.         }  

训练过程中我们将在每一轮训练结束后随机抽取一些数据进行预测,并将预测值和原值进行欧氏距离的计算。同时我们也会随机抽取一张图片直接比较每个像素点值的不同。具体可以看下面的两张图:

完整的训练过程,Spark任务截图:

随机抽取的数据的比较:

在经过多轮次的训练后,我们将模型保存在HDFS上(具体的代码实现可以参考之前的博客)并且将其拉到本地后,随机预测/重构一些图片来看看效果,具体的,我随机选择了9张图进行重构,如下图:

   

 

 

  

  

最后做下小结。

这里我们用多层感知机来对Mnsit数据集进行压缩,并且也取得不错的压缩效果。和之前利用Deep AutoEncoder进行数据进行压缩的不同在于我们将每一层中RBM替换成了FNN。应当说,从肉眼的角度我们没法分辨两种网络对Mnist数据集压缩的好坏程度,但是从理论上,基于RBM的压缩网络应该会取得更好的效果,在Hinton教授的论文中,也拿两者做了比较,结论也是基于RBM的Deep AutoEncoder效果更好,实际中,两者都会应用到。所以还得还情况而定!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值