Spark MLlib Deep Learning Neural Net(深度学习-神经网络)1.1

Spark MLlib Deep Learning Neural Net(深度学习-神经网络)1.1

http://blog.csdn.net/sunbow0

Spark MLlib Deep Learning工具箱,是根据现有深度学习教程《UFLDL教程》中的算法,在SparkMLlib中的实现。具体Spark MLlib Deep Learning(深度学习)目录结构:

第一章Neural Net(NN)

1、源码

2、源码解析

3、实例

第二章Deep Belief Nets(DBNs)

第三章Convolution Neural Network(CNN)

第四章 Stacked Auto-Encoders(SAE)

第五章CAE 


第一章Neural Net(神经网络)

1源码

目前Spark MLlib Deep Learning工具箱源码的github地址为:

https://github.com/sunbow1/SparkMLlibDeepLearn

1.1 NeuralNet代码 

[java]  view plain  copy
  1. package NN  
  2.   
  3. import org.apache.spark._  
  4. import org.apache.spark.SparkContext._  
  5. import org.apache.spark.rdd.RDD  
  6. import org.apache.spark.Logging  
  7. import org.apache.spark.mllib.regression.LabeledPoint  
  8. import org.apache.spark.mllib.linalg._  
  9. import org.apache.spark.mllib.linalg.distributed.RowMatrix  
  10.   
  11. import breeze.linalg.{  
  12.   Matrix => BM,  
  13.   CSCMatrix => BSM,  
  14.   DenseMatrix => BDM,  
  15.   Vector => BV,  
  16.   DenseVector => BDV,  
  17.   SparseVector => BSV,  
  18.   axpy => brzAxpy,  
  19.   svd => brzSvd  
  20. }  
  21. import breeze.numerics.{  
  22.   exp => Bexp,  
  23.   tanh => Btanh  
  24. }  
  25.   
  26. import scala.collection.mutable.ArrayBuffer  
  27. import java.util.Random  
  28. import scala.math._  
  29.   
  30. /** 
  31.  * label:目标矩阵 
  32.  * nna:神经网络每层节点的输出值,a(0),a(1),a(2) 
  33.  * error:输出层与目标值的误差矩阵 
  34.  */  
  35. case class NNLabel(label: BDM[Double], nna: ArrayBuffer[BDM[Double]], error: BDM[Double]) extends Serializable  
  36.   
  37. /** 
  38.  * 配置参数 
  39.  */  
  40. case class NNConfig(  
  41.   size: Array[Int],  
  42.   layer: Int,  
  43.   activation_function: String,  
  44.   learningRate: Double,  
  45.   momentum: Double,  
  46.   scaling_learningRate: Double,  
  47.   weightPenaltyL2: Double,  
  48.   nonSparsityPenalty: Double,  
  49.   sparsityTarget: Double,  
  50.   inputZeroMaskedFraction: Double,  
  51.   dropoutFraction: Double,  
  52.   testing: Double,  
  53.   output_function: String) extends Serializable  
  54.   
  55. /** 
  56.  * NN(neural network) 
  57.  */  
  58.   
  59. class NeuralNet(  
  60.   private var size: Array[Int],  
  61.   private var layer: Int,  
  62.   private var activation_function: String,  
  63.   private var learningRate: Double,  
  64.   private var momentum: Double,  
  65.   private var scaling_learningRate: Double,  
  66.   private var weightPenaltyL2: Double,  
  67.   private var nonSparsityPenalty: Double,  
  68.   private var sparsityTarget: Double,  
  69.   private var inputZeroMaskedFraction: Double,  
  70.   private var dropoutFraction: Double,  
  71.   private var testing: Double,  
  72.   private var output_function: String) extends Serializable with Logging {  
  73.   //          var size=Array(5, 7, 1)  
  74.   //          var layer=3  
  75.   //          var activation_function="tanh_opt"  
  76.   //          var learningRate=2.0  
  77.   //          var momentum=0.5  
  78.   //          var scaling_learningRate=1.0  
  79.   //          var weightPenaltyL2=0.0  
  80.   //          var nonSparsityPenalty=0.0  
  81.   //          var sparsityTarget=0.05  
  82.   //          var inputZeroMaskedFraction=0.0  
  83.   //          var dropoutFraction=0.0  
  84.   //          var testing=0.0  
  85.   //          var output_function="sigm"  
  86.   /** 
  87.    * size = architecture; 
  88.    * n = numel(nn.size); 
  89.    * activation_function = sigm   隐含层函数Activation functions of hidden layers: 'sigm' (sigmoid) or 'tanh_opt' (optimal tanh). 
  90.    * learningRate = 2;            学习率learning rate Note: typically needs to be lower when using 'sigm' activation function and non-normalized inputs. 
  91.    * momentum = 0.5;              Momentum 
  92.    * scaling_learningRate = 1;    Scaling factor for the learning rate (each epoch) 
  93.    * weightPenaltyL2  = 0;        正则化L2 regularization 
  94.    * nonSparsityPenalty = 0;      权重稀疏度惩罚值on sparsity penalty 
  95.    * sparsityTarget = 0.05;       Sparsity target 
  96.    * inputZeroMaskedFraction = 0; 加入noise,Used for Denoising AutoEncoders 
  97.    * dropoutFraction = 0;         每一次mini-batch样本输入训练时,随机扔掉x%的隐含层节点Dropout level (http://www.cs.toronto.edu/~hinton/absps/dropout.pdf) 
  98.    * testing = 0;                 Internal variable. nntest sets this to one. 
  99.    * output = 'sigm';             输出函数output unit 'sigm' (=logistic), 'softmax' and 'linear'   * 
  100.    */  
  101.   def this() = this(NeuralNet.Architecture, 3, NeuralNet.Activation_Function, 2.00.51.00.00.00.050.00.00.0, NeuralNet.Output)  
  102.   
  103.   /** 设置神经网络结构. Default: [10, 5, 1]. */  
  104.   def setSize(size: Array[Int]): this.type = {  
  105.     this.size = size  
  106.     this  
  107.   }  
  108.   
  109.   /** 设置神经网络层数据. Default: 3. */  
  110.   def setLayer(layer: Int): this.type = {  
  111.     this.layer = layer  
  112.     this  
  113.   }  
  114.   
  115.   /** 设置隐含层函数. Default: sigm. */  
  116.   def setActivation_function(activation_function: String): this.type = {  
  117.     this.activation_function = activation_function  
  118.     this  
  119.   }  
  120.   
  121.   /** 设置学习率因子. Default: 2. */  
  122.   def setLearningRate(learningRate: Double): this.type = {  
  123.     this.learningRate = learningRate  
  124.     this  
  125.   }  
  126.   
  127.   /** 设置Momentum. Default: 0.5. */  
  128.   def setMomentum(momentum: Double): this.type = {  
  129.     this.momentum = momentum  
  130.     this  
  131.   }  
  132.   
  133.   /** 设置scaling_learningRate. Default: 1. */  
  134.   def setScaling_learningRate(scaling_learningRate: Double): this.type = {  
  135.     this.scaling_learningRate = scaling_learningRate  
  136.     this  
  137.   }  
  138.   
  139.   /** 设置正则化L2因子. Default: 0. */  
  140.   def setWeightPenaltyL2(weightPenaltyL2: Double): this.type = {  
  141.     this.weightPenaltyL2 = weightPenaltyL2  
  142.     this  
  143.   }  
  144.   
  145.   /** 设置权重稀疏度惩罚因子. Default: 0. */  
  146.   def setNonSparsityPenalty(nonSparsityPenalty: Double): this.type = {  
  147.     this.nonSparsityPenalty = nonSparsityPenalty  
  148.     this  
  149.   }  
  150.   
  151.   /** 设置权重稀疏度目标值. Default: 0.05. */  
  152.   def setSparsityTarget(sparsityTarget: Double): this.type = {  
  153.     this.sparsityTarget = sparsityTarget  
  154.     this  
  155.   }  
  156.   
  157.   /** 设置权重加入噪声因子. Default: 0. */  
  158.   def setInputZeroMaskedFraction(inputZeroMaskedFraction: Double): this.type = {  
  159.     this.inputZeroMaskedFraction = inputZeroMaskedFraction  
  160.     this  
  161.   }  
  162.   
  163.   /** 设置权重Dropout因子. Default: 0. */  
  164.   def setDropoutFraction(dropoutFraction: Double): this.type = {  
  165.     this.dropoutFraction = dropoutFraction  
  166.     this  
  167.   }  
  168.   
  169.   /** 设置testing. Default: 0. */  
  170.   def setTesting(testing: Double): this.type = {  
  171.     this.testing = testing  
  172.     this  
  173.   }  
  174.   
  175.   /** 设置输出函数. Default: linear. */  
  176.   def setOutput_function(output_function: String): this.type = {  
  177.     this.output_function = output_function  
  178.     this  
  179.   }  
  180.   
  181.   /** 
  182.    * 运行神经网络算法. 
  183.    */  
  184.   def NNtrain(train_d: RDD[(BDM[Double], BDM[Double])], opts: Array[Double]): NeuralNetModel = {  
  185.     val sc = train_d.sparkContext  
  186.     var initStartTime = System.currentTimeMillis()  
  187.     var initEndTime = System.currentTimeMillis()  
  188.     // 参数配置 广播配置  
  189.     var nnconfig = NNConfig(size, layer, activation_function, learningRate, momentum, scaling_learningRate,  
  190.       weightPenaltyL2, nonSparsityPenalty, sparsityTarget, inputZeroMaskedFraction, dropoutFraction, testing,  
  191.       output_function)  
  192.     // 初始化权重  
  193.     var nn_W = NeuralNet.InitialWeight(size)  
  194.     var nn_vW = NeuralNet.InitialWeightV(size)  
  195.     //        val tmpw = nn_W(1)  
  196.     //        for (i <- 0 to tmpw.rows -1) {  
  197.     //          for (j <- 0 to tmpw.cols - 1) {  
  198.     //            print(tmpw(i, j) + "\t")  
  199.     //          }  
  200.     //          println()  
  201.     //        }  
  202.   
  203.     // 初始化每层的平均激活度nn.p  
  204.     // average activations (for use with sparsity)  
  205.     var nn_p = NeuralNet.InitialActiveP(size)  
  206.   
  207.     // 样本数据划分:训练数据、交叉检验数据  
  208.     val validation = opts(2)  
  209.     val splitW1 = Array(1.0 - validation, validation)  
  210.     val train_split1 = train_d.randomSplit(splitW1, System.nanoTime())  
  211.     val train_t = train_split1(0)  
  212.     val train_v = train_split1(1)  
  213.   
  214.     // m:训练样本的数量  
  215.     val m = train_t.count  
  216.     // batchsize是做batch gradient时候的大小   
  217.     // 计算batch的数量  
  218.     val batchsize = opts(0).toInt  
  219.     val numepochs = opts(1).toInt  
  220.     val numbatches = (m / batchsize).toInt  
  221.     var L = Array.fill(numepochs * numbatches.toInt)(0.0)  
  222.     var n = 0  
  223.     var loss_train_e = Array.fill(numepochs)(0.0)  
  224.     var loss_val_e = Array.fill(numepochs)(0.0)  
  225.     // numepochs是循环的次数   
  226.     for (i <- 1 to numepochs) {  
  227.       initStartTime = System.currentTimeMillis()  
  228.       val splitW2 = Array.fill(numbatches)(1.0 / numbatches)  
  229.       // 根据分组权重,随机划分每组样本数据    
  230.       val bc_config = sc.broadcast(nnconfig)  
  231.       for (l <- 1 to numbatches) {  
  232.         // 权重   
  233.         val bc_nn_W = sc.broadcast(nn_W)  
  234.         val bc_nn_vW = sc.broadcast(nn_vW)  
  235.   
  236.         //        println(i + "\t" + l)  
  237.         //        val tmpw0 = bc_nn_W.value(0)  
  238.         //        for (i <- 0 to tmpw0.rows - 1) {  
  239.         //          for (j <- 0 to tmpw0.cols - 1) {  
  240.         //            print(tmpw0(i, j) + "\t")  
  241.         //          }  
  242.         //          println()  
  243.         //        }  
  244.         //        val tmpw1 = bc_nn_W.value(1)  
  245.         //        for (i <- 0 to tmpw1.rows - 1) {  
  246.         //          for (j <- 0 to tmpw1.cols - 1) {  
  247.         //            print(tmpw1(i, j) + "\t")  
  248.         //          }  
  249.         //          println()  
  250.         //        }  
  251.   
  252.         // 样本划分  
  253.         val train_split2 = train_t.randomSplit(splitW2, System.nanoTime())  
  254.         val batch_xy1 = train_split2(l - 1)  
  255.         //        val train_split3 = train_t.filter { f => (f._1 >= batchsize * (l - 1) + 1) && (f._1 <= batchsize * (l)) }  
  256.         //        val batch_xy1 = train_split3.map(f => (f._2, f._3))  
  257.         // Add noise to input (for use in denoising autoencoder)  
  258.         // 加入noise,这是denoising autoencoder需要使用到的部分    
  259.         // 这部分请参见《Extracting and Composing Robust Features with Denoising Autoencoders》这篇论文    
  260.         // 具体加入的方法就是把训练样例中的一些数据调整变为0,inputZeroMaskedFraction表示了调整的比例    
  261.         //val randNoise = NeuralNet.RandMatrix(batch_x.numRows.toInt, batch_x.numCols.toInt, inputZeroMaskedFraction)  
  262.         val batch_xy2 = if (bc_config.value.inputZeroMaskedFraction != 0) {  
  263.           NeuralNet.AddNoise(batch_xy1, bc_config.value.inputZeroMaskedFraction)  
  264.         } else batch_xy1  
  265.   
  266.         //        val tmpxy = batch_xy2.map(f => (f._1.toArray,f._2.toArray)).toArray.map {f => ((new ArrayBuffer() ++ f._1) ++ f._2).toArray}  
  267.         //        for (i <- 0 to tmpxy.length - 1) {  
  268.         //          for (j <- 0 to tmpxy(i).length - 1) {  
  269.         //            print(tmpxy(i)(j) + "\t")  
  270.         //          }  
  271.         //          println()  
  272.         //        }  
  273.   
  274.         // NNff是进行前向传播  
  275.         // nn = nnff(nn, batch_x, batch_y);  
  276.         val train_nnff = NeuralNet.NNff(batch_xy2, bc_config, bc_nn_W)  
  277.   
  278.         //        val tmpa0 = train_nnff.map(f => f._1.nna(0)).take(20)  
  279.         //        println("tmpa0")  
  280.         //        for (i <- 0 to 10) {  
  281.         //          for (j <- 0 to tmpa0(i).cols - 1) {  
  282.         //            print(tmpa0(i)(0, j) + "\t")  
  283.         //          }  
  284.         //          println()  
  285.         //        }  
  286.         //        val tmpa1 = train_nnff.map(f => f._1.nna(1)).take(20)  
  287.         //        println("tmpa1")  
  288.         //        for (i <- 0 to 10) {  
  289.         //          for (j <- 0 to tmpa1(i).cols - 1) {  
  290.         //            print(tmpa1(i)(0, j) + "\t")  
  291.         //          }  
  292.         //          println()  
  293.         //        }  
  294.         //        val tmpa2 = train_nnff.map(f => f._1.nna(2)).take(20)  
  295.         //        println("tmpa2")  
  296.         //        for (i <- 0 to 10) {  
  297.         //          for (j <- 0 to tmpa2(i).cols - 1) {  
  298.         //            print(tmpa2(i)(0, j) + "\t")  
  299.         //          }  
  300.         //          println()  
  301.         //        }  
  302.   
  303.         // sparsity计算,计算每层节点的平均稀疏度  
  304.         nn_p = NeuralNet.ActiveP(train_nnff, bc_config, nn_p)  
  305.         val bc_nn_p = sc.broadcast(nn_p)  
  306.   
  307.         // NNbp是后向传播  
  308.         // nn = nnbp(nn);  
  309.         val train_nnbp = NeuralNet.NNbp(train_nnff, bc_config, bc_nn_W, bc_nn_p)  
  310.   
  311.         //        val tmpd0 = rdd5.map(f => f._2(2)).take(20)  
  312.         //        println("tmpd0")  
  313.         //        for (i <- 0 to 10) {  
  314.         //          for (j <- 0 to tmpd0(i).cols - 1) {  
  315.         //            print(tmpd0(i)(0, j) + "\t")  
  316.         //          }  
  317.         //          println()  
  318.         //        }  
  319.         //        val tmpd1 = rdd5.map(f => f._2(1)).take(20)  
  320.         //        println("tmpd1")  
  321.         //        for (i <- 0 to 10) {  
  322.         //          for (j <- 0 to tmpd1(i).cols - 1) {  
  323.         //            print(tmpd1(i)(0, j) + "\t")  
  324.         //          }  
  325.         //          println()  
  326.         //        }  
  327.         //        val tmpdw0 = rdd5.map(f => f._3(0)).take(20)  
  328.         //        println("tmpdw0")  
  329.         //        for (i <- 0 to 10) {  
  330.         //          for (j <- 0 to tmpdw0(i).cols - 1) {  
  331.         //            print(tmpdw0(i)(0, j) + "\t")  
  332.         //          }  
  333.         //          println()  
  334.         //        }  
  335.         //        val tmpdw1 = rdd5.map(f => f._3(1)).take(20)  
  336.         //        println("tmpdw1")  
  337.         //        for (i <- 0 to 10) {  
  338.         //          for (j <- 0 to tmpdw1(i).cols - 1) {  
  339.         //            print(tmpdw1(i)(0, j) + "\t")  
  340.         //          }  
  341.         //          println()  
  342.         //        }  
  343.   
  344.         // nn = NNapplygrads(nn) returns an neural network structure with updated  
  345.         // weights and biases  
  346.         // 更新权重参数:w=w-α*[dw + λw]      
  347.         val train_nnapplygrads = NeuralNet.NNapplygrads(train_nnbp, bc_config, bc_nn_W, bc_nn_vW)  
  348.         nn_W = train_nnapplygrads(0)  
  349.         nn_vW = train_nnapplygrads(1)  
  350.   
  351.         //        val tmpw2 = train_nnapplygrads(0)(0)  
  352.         //        for (i <- 0 to tmpw2.rows - 1) {  
  353.         //          for (j <- 0 to tmpw2.cols - 1) {  
  354.         //            print(tmpw2(i, j) + "\t")  
  355.         //          }  
  356.         //          println()  
  357.         //        }  
  358.         //        val tmpw3 = train_nnapplygrads(0)(1)  
  359.         //        for (i <- 0 to tmpw3.rows - 1) {  
  360.         //          for (j <- 0 to tmpw3.cols - 1) {  
  361.         //            print(tmpw3(i, j) + "\t")  
  362.         //          }  
  363.         //          println()  
  364.         //        }  
  365.   
  366.         // error and loss  
  367.         // 输出误差计算  
  368.         val loss1 = train_nnff.map(f => f._1.error)  
  369.         val (loss2, counte) = loss1.treeAggregate((0.0, 0L))(  
  370.           seqOp = (c, v) => {  
  371.             // c: (e, count), v: (m)  
  372.             val e1 = c._1  
  373.             val e2 = (v :* v).sum  
  374.             val esum = e1 + e2  
  375.             (esum, c._2 + 1)  
  376.           },  
  377.           combOp = (c1, c2) => {  
  378.             // c: (e, count)  
  379.             val e1 = c1._1  
  380.             val e2 = c2._1  
  381.             val esum = e1 + e2  
  382.             (esum, c1._2 + c2._2)  
  383.           })  
  384.         val Loss = loss2 / counte.toDouble  
  385.         L(n) = Loss * 0.5  
  386.         n = n + 1  
  387.       }  
  388.       // 计算本次迭代的训练误差及交叉检验误差  
  389.       // Full-batch train mse  
  390.       val evalconfig = NNConfig(size, layer, activation_function, learningRate, momentum, scaling_learningRate,  
  391.         weightPenaltyL2, nonSparsityPenalty, sparsityTarget, inputZeroMaskedFraction, dropoutFraction, 1.0,  
  392.         output_function)  
  393.       loss_train_e(i - 1) = NeuralNet.NNeval(train_t, sc.broadcast(evalconfig), sc.broadcast(nn_W))  
  394.       if (validation > 0) loss_val_e(i - 1) = NeuralNet.NNeval(train_v, sc.broadcast(evalconfig), sc.broadcast(nn_W))  
  395.   
  396.       // 更新学习因子  
  397.       // nn.learningRate = nn.learningRate * nn.scaling_learningRate;  
  398.       nnconfig = NNConfig(size, layer, activation_function, nnconfig.learningRate * nnconfig.scaling_learningRate, momentum, scaling_learningRate,  
  399.         weightPenaltyL2, nonSparsityPenalty, sparsityTarget, inputZeroMaskedFraction, dropoutFraction, testing,  
  400.         output_function)  
  401.       initEndTime = System.currentTimeMillis()  
  402.   
  403.       // 打印输出结果  
  404.       printf("epoch: numepochs = %d , Took = %d seconds; Full-batch train mse = %f, val mse = %f.\n", i, scala.math.ceil((initEndTime - initStartTime).toDouble / 1000).toLong, loss_train_e(i - 1), loss_val_e(i - 1))  
  405.     }  
  406.     val configok = NNConfig(size, layer, activation_function, learningRate, momentum, scaling_learningRate,  
  407.       weightPenaltyL2, nonSparsityPenalty, sparsityTarget, inputZeroMaskedFraction, dropoutFraction, 1.0,  
  408.       output_function)  
  409.     new NeuralNetModel(configok, nn_W)  
  410.   }  
  411.   
  412. }  
  413.   
  414. /** 
  415.  * NN(neural network) 
  416.  */  
  417. object NeuralNet extends Serializable {  
  418.   
  419.   // Initialization mode names  
  420.   val Activation_Function = "sigm"  
  421.   val Output = "linear"  
  422.   val Architecture = Array(1051)  
  423.   
  424.   /** 
  425.    * 增加随机噪声 
  426.    * 若随机值>=Fraction,值不变,否则改为0 
  427.    */  
  428.   def AddNoise(rdd: RDD[(BDM[Double], BDM[Double])], Fraction: Double): RDD[(BDM[Double], BDM[Double])] = {  
  429.     val addNoise = rdd.map { f =>  
  430.       val features = f._2  
  431.       val a = BDM.rand[Double](features.rows, features.cols)  
  432.       val a1 = a :>= Fraction  
  433.       val d1 = a1.data.map { f => if (f == true1.0 else 0.0 }  
  434.       val a2 = new BDM(features.rows, features.cols, d1)  
  435.       val features2 = features :* a2  
  436.       (f._1, features2)  
  437.     }  
  438.     addNoise  
  439.   }  
  440.   
  441.   /** 
  442.    * 初始化权重 
  443.    * 初始化为一个很小的、接近零的随机值 
  444.    */  
  445.   def InitialWeight2(size: Array[Int]): Array[BDM[Double]] = {  
  446.     // 初始化权重参数  
  447.     // weights and weight momentum  
  448.     // nn.W{i - 1} = (rand(nn.size(i), nn.size(i - 1)+1) - 0.5) * 2 * 4 * sqrt(6 / (nn.size(i) + nn.size(i - 1)));  
  449.     // nn.vW{i - 1} = zeros(size(nn.W{i - 1}));  
  450.     val n = size.length  
  451.     val nn_W = ArrayBuffer[BDM[Double]]()  
  452.     val d1 = BDM((2.54631575950577, -2.72375471180638, -1.83131523622017, -0.832303531504013, -1.28869970471936, -0.460188104184124), (-1.520910242012131.81815348316090, -0.5334062093404141.77153723107141, -1.703763789302311.95852409868481), (0.604392922735100, -0.3128050083412652.46338861792203, -2.77264318419692, -2.742024745725550.142284005609256), (-0.07929513144919020.6529839688789052.35836765255640, -2.042741648932271.39603060318734, -1.68208055847319), (2.213521219481391.65144527075334, -0.507588360889342, -1.68141383648426, -0.3105814803242210.973756570035639), (1.482643583689512.386134496048742.22681802175890, -1.704287190305012.442712133163631.91268676272635), (-0.2462560732827931.34750367072394, -2.500944451268640.587138926992906, -0.192365052800164, -2.71732925728203))  
  453.     nn_W += d1  
  454.     val d2 = BDM((1.25592501437006, -0.8349800002079402.298750240995430.01948823198921581.45126037957791, -0.492648144141757, -1.35365058999520, -2.15014190874756))  
  455.     nn_W += d2  
  456.     nn_W.toArray  
  457.   }  
  458.   def InitialWeight(size: Array[Int]): Array[BDM[Double]] = {  
  459.     // 初始化权重参数  
  460.     // weights and weight momentum  
  461.     // nn.W{i - 1} = (rand(nn.size(i), nn.size(i - 1)+1) - 0.5) * 2 * 4 * sqrt(6 / (nn.size(i) + nn.size(i - 1)));  
  462.     // nn.vW{i - 1} = zeros(size(nn.W{i - 1}));  
  463.     val n = size.length  
  464.     val nn_W = ArrayBuffer[BDM[Double]]()  
  465.     for (i <- 1 to n - 1) {  
  466.       val d1 = BDM.rand(size(i), size(i - 1) + 1)  
  467.       d1 :-= 0.5  
  468.       val f1 = 2 * 4 * sqrt(6.0 / (size(i) + size(i - 1)))  
  469.       val d2 = d1 :* f1  
  470.       //val d3 = new DenseMatrix(d2.rows, d2.cols, d2.data, d2.isTranspose)  
  471.       //val d4 = Matrices.dense(d2.rows, d2.cols, d2.data)  
  472.       nn_W += d2  
  473.     }  
  474.     nn_W.toArray  
  475.   }  
  476.   
  477.   /** 
  478.    * 初始化权重vW 
  479.    * 初始化为0 
  480.    */  
  481.   def InitialWeightV(size: Array[Int]): Array[BDM[Double]] = {  
  482.     // 初始化权重参数  
  483.     // weights and weight momentum  
  484.     // nn.vW{i - 1} = zeros(size(nn.W{i - 1}));  
  485.     val n = size.length  
  486.     val nn_vW = ArrayBuffer[BDM[Double]]()  
  487.     for (i <- 1 to n - 1) {  
  488.       val d1 = BDM.zeros[Double](size(i), size(i - 1) + 1)  
  489.       nn_vW += d1  
  490.     }  
  491.     nn_vW.toArray  
  492.   }  
  493.   
  494.   /** 
  495.    * 初始每一层的平均激活度 
  496.    * 初始化为0 
  497.    */  
  498.   def InitialActiveP(size: Array[Int]): Array[BDM[Double]] = {  
  499.     // 初始每一层的平均激活度  
  500.     // average activations (for use with sparsity)  
  501.     // nn.p{i}     = zeros(1, nn.size(i));    
  502.     val n = size.length  
  503.     val nn_p = ArrayBuffer[BDM[Double]]()  
  504.     nn_p += BDM.zeros[Double](11)  
  505.     for (i <- 1 to n - 1) {  
  506.       val d1 = BDM.zeros[Double](1, size(i))  
  507.       nn_p += d1  
  508.     }  
  509.     nn_p.toArray  
  510.   }  
  511.   
  512.   /** 
  513.    * 随机让网络某些隐含层节点的权重不工作 
  514.    * 若随机值>=Fraction,矩阵值不变,否则改为0 
  515.    */  
  516.   def DropoutWeight(matrix: BDM[Double], Fraction: Double): Array[BDM[Double]] = {  
  517.     val aa = BDM.rand[Double](matrix.rows, matrix.cols)  
  518.     val aa1 = aa :> Fraction  
  519.     val d1 = aa1.data.map { f => if (f == true1.0 else 0.0 }  
  520.     val aa2 = new BDM(matrix.rows: Int, matrix.cols: Int, d1: Array[Double])  
  521.     val matrix2 = matrix :* aa2  
  522.     Array(aa2, matrix2)  
  523.   }  
  524.   
  525.   /** 
  526.    * sigm激活函数 
  527.    * X = 1./(1+exp(-P)); 
  528.    */  
  529.   def sigm(matrix: BDM[Double]): BDM[Double] = {  
  530.     val s1 = 1.0 / (Bexp(matrix * (-1.0)) + 1.0)  
  531.     s1  
  532.   }  
  533.   
  534.   /** 
  535.    * tanh激活函数 
  536.    * f=1.7159*tanh(2/3.*A); 
  537.    */  
  538.   def tanh_opt(matrix: BDM[Double]): BDM[Double] = {  
  539.     val s1 = Btanh(matrix * (2.0 / 3.0)) * 1.7159  
  540.     s1  
  541.   }  
  542.   
  543.   /** 
  544.    * nnff是进行前向传播 
  545.    * 计算神经网络中的每个节点的输出值; 
  546.    */  
  547.   def NNff(  
  548.     batch_xy2: RDD[(BDM[Double], BDM[Double])],  
  549.     bc_config: org.apache.spark.broadcast.Broadcast[NNConfig],  
  550.     bc_nn_W: org.apache.spark.broadcast.Broadcast[Array[BDM[Double]]]): RDD[(NNLabel, Array[BDM[Double]])] = {  
  551.     // 第1层:a(1)=[1 x]  
  552.     // 增加偏置项b  
  553.     val train_data1 = batch_xy2.map { f =>  
  554.       val lable = f._1  
  555.       val features = f._2  
  556.       val nna = ArrayBuffer[BDM[Double]]()  
  557.       val Bm1 = new BDM(features.rows, 1, Array.fill(features.rows * 1)(1.0))  
  558.       val features2 = BDM.horzcat(Bm1, features)  
  559.       val error = BDM.zeros[Double](lable.rows, lable.cols)  
  560.       nna += features2  
  561.       NNLabel(lable, nna, error)  
  562.     }  
  563.   
  564.     //    println("bc_size " + bc_config.value.size(0) + bc_config.value.size(1) + bc_config.value.size(2))  
  565.     //    println("bc_layer " + bc_config.value.layer)  
  566.     //    println("bc_activation_function " + bc_config.value.activation_function)  
  567.     //    println("bc_output_function " + bc_config.value.output_function)  
  568.     //  
  569.     //    println("tmpw0 ")  
  570.     //    val tmpw0 = bc_nn_W.value(0)  
  571.     //    for (i <- 0 to tmpw0.rows - 1) {  
  572.     //      for (j <- 0 to tmpw0.cols - 1) {  
  573.     //        print(tmpw0(i, j) + "\t")  
  574.     //      }  
  575.     //      println()  
  576.     //    }  
  577.   
  578.     // feedforward pass  
  579.     // 第2至n-1层计算,a(i)=f(a(i-1)*w(i-1)')  
  580.     //val tmp1 = train_data1.map(f => f.nna(0).data).take(1)(0)  
  581.     //val tmp2 = new BDM(1, tmp1.length, tmp1)  
  582.     //val nn_a = ArrayBuffer[BDM[Double]]()  
  583.     //nn_a += tmp2  
  584.     val train_data2 = train_data1.map { f =>  
  585.       val nn_a = f.nna  
  586.       val dropOutMask = ArrayBuffer[BDM[Double]]()  
  587.       dropOutMask += new BDM[Double](11, Array(0.0))  
  588.       for (j <- 1 to bc_config.value.layer - 2) {  
  589.         // 计算每层输出  
  590.         // Calculate the unit's outputs (including the bias term)  
  591.         // nn.a{i} = sigm(nn.a{i - 1} * nn.W{i - 1}')  
  592.         // nn.a{i} = tanh_opt(nn.a{i - 1} * nn.W{i - 1}');              
  593.         val A1 = nn_a(j - 1)  
  594.         val W1 = bc_nn_W.value(j - 1)  
  595.         val aw1 = A1 * W1.t  
  596.         val nnai1 = bc_config.value.activation_function match {  
  597.           case "sigm" =>  
  598.             val aw2 = NeuralNet.sigm(aw1)  
  599.             aw2  
  600.           case "tanh_opt" =>  
  601.             val aw2 = NeuralNet.tanh_opt(aw1)  
  602.             //val aw2 = Btanh(aw1 * (2.0 / 3.0)) * 1.7159  
  603.             aw2  
  604.         }  
  605.         // dropout计算  
  606.         // Dropout是指在模型训练时随机让网络某些隐含层节点的权重不工作,不工作的那些节点可以暂时认为不是网络结构的一部分  
  607.         // 但是它的权重得保留下来(只是暂时不更新而已),因为下次样本输入时它可能又得工作了  
  608.         // 参照 http://www.cnblogs.com/tornadomeet/p/3258122.html     
  609.         val dropoutai = if (bc_config.value.dropoutFraction > 0) {  
  610.           if (bc_config.value.testing == 1) {  
  611.             val nnai2 = nnai1 * (1.0 - bc_config.value.dropoutFraction)  
  612.             Array(new BDM[Double](11, Array(0.0)), nnai2)  
  613.           } else {  
  614.             NeuralNet.DropoutWeight(nnai1, bc_config.value.dropoutFraction)  
  615.           }  
  616.         } else {  
  617.           val nnai2 = nnai1  
  618.           Array(new BDM[Double](11, Array(0.0)), nnai2)  
  619.         }  
  620.         val nnai2 = dropoutai(1)  
  621.         dropOutMask += dropoutai(0)  
  622.         // Add the bias term  
  623.         // 增加偏置项b  
  624.         // nn.a{i} = [ones(m,1) nn.a{i}];  
  625.         val Bm1 = BDM.ones[Double](nnai2.rows, 1)  
  626.         val nnai3 = BDM.horzcat(Bm1, nnai2)  
  627.         nn_a += nnai3  
  628.       }  
  629.       (NNLabel(f.label, nn_a, f.error), dropOutMask.toArray)  
  630.     }  
  631.   
  632.     // 输出层计算  
  633.     val train_data3 = train_data2.map { f =>  
  634.       val nn_a = f._1.nna  
  635.       // nn.a{n} = sigm(nn.a{n - 1} * nn.W{n - 1}');  
  636.       // nn.a{n} = nn.a{n - 1} * nn.W{n - 1}';            
  637.       val An1 = nn_a(bc_config.value.layer - 2)  
  638.       val Wn1 = bc_nn_W.value(bc_config.value.layer - 2)  
  639.       val awn1 = An1 * Wn1.t  
  640.       val nnan1 = bc_config.value.output_function match {  
  641.         case "sigm" =>  
  642.           val awn2 = NeuralNet.sigm(awn1)  
  643.           //val awn2 = 1.0 / (Bexp(awn1 * (-1.0)) + 1.0)  
  644.           awn2  
  645.         case "linear" =>  
  646.           val awn2 = awn1  
  647.           awn2  
  648.       }  
  649.       nn_a += nnan1  
  650.       (NNLabel(f._1.label, nn_a, f._1.error), f._2)  
  651.     }  
  652.   
  653.     // error and loss  
  654.     // 输出误差计算  
  655.     // nn.e = y - nn.a{n};  
  656.     // val nn_e = batch_y - nnan  
  657.     val train_data4 = train_data3.map { f =>  
  658.       val batch_y = f._1.label  
  659.       val nnan = f._1.nna(bc_config.value.layer - 1)  
  660.       val error = (batch_y - nnan)  
  661.       (NNLabel(f._1.label, f._1.nna, error), f._2)  
  662.     }  
  663.     train_data4  
  664.   }  
  665.   
  666.   /** 
  667.    * sparsity计算,网络稀疏度 
  668.    * 计算每个节点的平均值 
  669.    */  
  670.   def ActiveP(  
  671.     train_nnff: RDD[(NNLabel, Array[BDM[Double]])],  
  672.     bc_config: org.apache.spark.broadcast.Broadcast[NNConfig],  
  673.     nn_p_old: Array[BDM[Double]]): Array[BDM[Double]] = {  
  674.     val nn_p = ArrayBuffer[BDM[Double]]()  
  675.     nn_p += BDM.zeros[Double](11)  
  676.     // calculate running exponential activations for use with sparsity  
  677.     // sparsity计算,计算sparsity,nonSparsityPenalty 是对没达到sparsitytarget的参数的惩罚系数   
  678.     for (i <- 1 to bc_config.value.layer - 1) {  
  679.       val pi1 = train_nnff.map(f => f._1.nna(i))  
  680.       val initpi = BDM.zeros[Double](1, bc_config.value.size(i))  
  681.       val (piSum, miniBatchSize) = pi1.treeAggregate((initpi, 0L))(  
  682.         seqOp = (c, v) => {  
  683.           // c: (nnasum, count), v: (nna)  
  684.           val nna1 = c._1  
  685.           val nna2 = v  
  686.           val nnasum = nna1 + nna2  
  687.           (nnasum, c._2 + 1)  
  688.         },  
  689.         combOp = (c1, c2) => {  
  690.           // c: (nnasum, count)  
  691.           val nna1 = c1._1  
  692.           val nna2 = c2._1  
  693.           val nnasum = nna1 + nna2  
  694.           (nnasum, c1._2 + c2._2)  
  695.         })  
  696.       val piAvg = piSum / miniBatchSize.toDouble  
  697.       val oldpi = nn_p_old(i)  
  698.       val newpi = (piAvg * 0.01) + (oldpi * 0.09)  
  699.       nn_p += newpi  
  700.     }  
  701.     nn_p.toArray  
  702.   }  
  703.   
  704.   /** 
  705.    * NNbp是后向传播 
  706.    * 计算权重的平均偏导数 
  707.    */  
  708.   def NNbp(  
  709.     train_nnff: RDD[(NNLabel, Array[BDM[Double]])],  
  710.     bc_config: org.apache.spark.broadcast.Broadcast[NNConfig],  
  711.     bc_nn_W: org.apache.spark.broadcast.Broadcast[Array[BDM[Double]]],  
  712.     bc_nn_p: org.apache.spark.broadcast.Broadcast[Array[BDM[Double]]]): Array[BDM[Double]] = {  
  713.     // 第n层偏导数:d(n)=-(y-a(n))*f'(z),sigmoid函数f'(z)表达式:f'(z)=f(z)*[1-f(z)]  
  714.     // sigm: d{n} = - nn.e .* (nn.a{n} .* (1 - nn.a{n}));  
  715.     // {'softmax','linear'}: d{n} = - nn.e;  
  716.     val train_data5 = train_nnff.map { f =>  
  717.       val nn_a = f._1.nna  
  718.       val error = f._1.error  
  719.       val dn = ArrayBuffer[BDM[Double]]()  
  720.       val nndn = bc_config.value.output_function match {  
  721.         case "sigm" =>  
  722.           val fz = nn_a(bc_config.value.layer - 1)  
  723.           (error * (-1.0)) :* (fz :* (1.0 - fz))  
  724.         case "linear" =>  
  725.           error * (-1.0)  
  726.       }  
  727.       dn += nndn  
  728.       (f._1, f._2, dn)  
  729.     }  
  730.     // 第n-1至第2层导数:d(n)=-(w(n)*d(n+1))*f'(z)   
  731.     val train_data6 = train_data5.map { f =>  
  732.       // 假设 f(z) 是sigmoid函数 f(z)=1/[1+e^(-z)],f'(z)表达式,f'(z)=f(z)*[1-f(z)]      
  733.       // 假设 f(z) tanh f(z)=1.7159*tanh(2/3.*A) ,f'(z)表达式,f'(z)=1.7159 * 2/3 * (1 - 1/(1.7159)^2 * f(z).^2)     
  734.       //val di = ArrayBuffer( BDM((1.765226346140333)))  
  735.       //      val nn_a = ArrayBuffer[BDM[Double]]()  
  736.       //      val a1=BDM((1.0,0.312605257000000,0.848582961000000,0.999014768000000,0.278330771000000,0.462701179000000))  
  737.       //      val a2= BDM((1.0,0.838091550300577,0.996782915917104,0.118033012437165))  
  738.       //      val a3= BDM((2.18788852054974))  
  739.       //      nn_a += a1  
  740.       //      nn_a += a2  
  741.       //      nn_a += a3  
  742.       val nn_a = f._1.nna  
  743.       val di = f._3  
  744.       val dropout = f._2  
  745.       for (i <- bc_config.value.layer - 2 to 1) {  
  746.         // f'(z)表达式  
  747.         val nnd_act = bc_config.value.activation_function match {  
  748.           case "sigm" =>  
  749.             val d_act = nn_a(i) :* (1.0 - nn_a(i))  
  750.             d_act  
  751.           case "tanh_opt" =>  
  752.             val fz2 = (1.0 - ((nn_a(i) :* nn_a(i)) * (1.0 / (1.7159 * 1.7159))))  
  753.             val d_act = fz2 * (1.7159 * (2.0 / 3.0))  
  754.             d_act  
  755.         }  
  756.         // 稀疏度惩罚误差计算:-(t/p)+(1-t)/(1-p)  
  757.         // sparsityError = [zeros(size(nn.a{i},1),1) nn.nonSparsityPenalty * (-nn.sparsityTarget ./ pi + (1 - nn.sparsityTarget) ./ (1 - pi))];  
  758.         val sparsityError = if (bc_config.value.nonSparsityPenalty > 0) {  
  759.           val nn_pi1 = bc_nn_p.value(i)  
  760.           val nn_pi2 = (bc_config.value.sparsityTarget / nn_pi1) * (-1.0) + (1.0 - bc_config.value.sparsityTarget) / (1.0 - nn_pi1)  
  761.           val Bm1 = new BDM(nn_pi2.rows, 1, Array.fill(nn_pi2.rows * 1)(1.0))  
  762.           val sparsity = BDM.horzcat(Bm1, nn_pi2 * bc_config.value.nonSparsityPenalty)  
  763.           sparsity  
  764.         } else {  
  765.           val nn_pi1 = bc_nn_p.value(i)  
  766.           val sparsity = BDM.zeros[Double](nn_pi1.rows, nn_pi1.cols + 1)  
  767.           sparsity  
  768.         }  
  769.         // 导数:d(n)=-( w(n)*d(n+1)+ sparsityError )*f'(z)   
  770.         // d{i} = (d{i + 1} * nn.W{i} + sparsityError) .* d_act;  
  771.         val W1 = bc_nn_W.value(i)  
  772.         val nndi1 = if (i + 1 == bc_config.value.layer - 1) {  
  773.           //in this case in d{n} there is not the bias term to be removed    
  774.           val di1 = di(i - 1)  
  775.           val di2 = (di1 * W1 + sparsityError) :* nnd_act  
  776.           di2  
  777.         } else {  
  778.           // in this case in d{i} the bias term has to be removed  
  779.           val di1 = di(i - 1)(::, 1 to -1)  
  780.           val di2 = (di1 * W1 + sparsityError) :* nnd_act  
  781.           di2  
  782.         }  
  783.         // dropoutFraction  
  784.         val nndi2 = if (bc_config.value.dropoutFraction > 0) {  
  785.           val dropouti1 = dropout(i)  
  786.           val Bm1 = new BDM(nndi1.rows: Int, 1: Int, Array.fill(nndi1.rows * 1)(1.0))  
  787.           val dropouti2 = BDM.horzcat(Bm1, dropouti1)  
  788.           nndi1 :* dropouti2  
  789.         } else nndi1  
  790.         di += nndi2  
  791.       }  
  792.       di += BDM.zeros(11)  
  793.       // 计算最终需要的偏导数值:dw(n)=(1/m)∑d(n+1)*a(n)  
  794.       //  nn.dW{i} = (d{i + 1}' * nn.a{i}) / size(d{i + 1}, 1);  
  795.       val dw = ArrayBuffer[BDM[Double]]()  
  796.       for (i <- 0 to bc_config.value.layer - 2) {  
  797.         val nndW = if (i + 1 == bc_config.value.layer - 1) {  
  798.           (di(bc_config.value.layer - 2 - i).t) * nn_a(i)  
  799.         } else {  
  800.           (di(bc_config.value.layer - 2 - i)(::, 1 to -1)).t * nn_a(i)  
  801.         }  
  802.         dw += nndW  
  803.       }  
  804.       (f._1, di, dw)  
  805.     }  
  806.     val train_data7 = train_data6.map(f => f._3)  
  807.   
  808.     // Sample a subset (fraction miniBatchFraction) of the total data  
  809.     // compute and sum up the subgradients on this subset (this is one map-reduce)  
  810.     val initgrad = ArrayBuffer[BDM[Double]]()  
  811.     for (i <- 0 to bc_config.value.layer - 2) {  
  812.       val init1 = if (i + 1 == bc_config.value.layer - 1) {  
  813.         BDM.zeros[Double](bc_config.value.size(i + 1), bc_config.value.size(i) + 1)  
  814.       } else {  
  815.         BDM.zeros[Double](bc_config.value.size(i + 1), bc_config.value.size(i) + 1)  
  816.       }  
  817.       initgrad += init1  
  818.     }  
  819.     val (gradientSum, miniBatchSize) = train_data7.treeAggregate((initgrad, 0L))(  
  820.       seqOp = (c, v) => {  
  821.         // c: (grad, count), v: (grad)  
  822.         val grad1 = c._1  
  823.         val grad2 = v  
  824.         val sumgrad = ArrayBuffer[BDM[Double]]()  
  825.         for (i <- 0 to bc_config.value.layer - 2) {  
  826.           val Bm1 = grad1(i)  
  827.           val Bm2 = grad2(i)  
  828.           val Bmsum = Bm1 + Bm2  
  829.           sumgrad += Bmsum  
  830.         }  
  831.         (sumgrad, c._2 + 1)  
  832.       },  
  833.       combOp = (c1, c2) => {  
  834.         // c: (grad, count)  
  835.         val grad1 = c1._1  
  836.         val grad2 = c2._1  
  837.         val sumgrad = ArrayBuffer[BDM[Double]]()  
  838.         for (i <- 0 to bc_config.value.layer - 2) {  
  839.           val Bm1 = grad1(i)  
  840.           val Bm2 = grad2(i)  
  841.           val Bmsum = Bm1 + Bm2  
  842.           sumgrad += Bmsum  
  843.         }  
  844.         (sumgrad, c1._2 + c2._2)  
  845.       })  
  846.     // 求平均值  
  847.     val gradientAvg = ArrayBuffer[BDM[Double]]()  
  848.     for (i <- 0 to bc_config.value.layer - 2) {  
  849.       val Bm1 = gradientSum(i)  
  850.       val Bmavg = Bm1 :/ miniBatchSize.toDouble  
  851.       gradientAvg += Bmavg  
  852.     }  
  853.     gradientAvg.toArray  
  854.   }  
  855.   
  856.   /** 
  857.    * NNapplygrads是权重更新 
  858.    * 权重更新 
  859.    */  
  860.   def NNapplygrads(  
  861.     train_nnbp: Array[BDM[Double]],  
  862.     bc_config: org.apache.spark.broadcast.Broadcast[NNConfig],  
  863.     bc_nn_W: org.apache.spark.broadcast.Broadcast[Array[BDM[Double]]],  
  864.     bc_nn_vW: org.apache.spark.broadcast.Broadcast[Array[BDM[Double]]]): Array[Array[BDM[Double]]] = {  
  865.     // nn = nnapplygrads(nn) returns an neural network structure with updated  
  866.     // weights and biases  
  867.     // 更新权重参数:w=w-α*[dw + λw]      
  868.     val W_a = ArrayBuffer[BDM[Double]]()  
  869.     val vW_a = ArrayBuffer[BDM[Double]]()  
  870.     for (i <- 0 to bc_config.value.layer - 2) {  
  871.       val nndwi = if (bc_config.value.weightPenaltyL2 > 0) {  
  872.         val dwi = train_nnbp(i)  
  873.         val zeros = BDM.zeros[Double](dwi.rows, 1)  
  874.         val l2 = BDM.horzcat(zeros, dwi(::, 1 to -1))  
  875.         val dwi2 = dwi + (l2 * bc_config.value.weightPenaltyL2)  
  876.         dwi2  
  877.       } else {  
  878.         val dwi = train_nnbp(i)  
  879.         dwi  
  880.       }  
  881.       val nndwi2 = nndwi :* bc_config.value.learningRate  
  882.       val nndwi3 = if (bc_config.value.momentum > 0) {  
  883.         val vwi = bc_nn_vW.value(i)  
  884.         val dw3 = nndwi2 + (vwi * bc_config.value.momentum)  
  885.         dw3  
  886.       } else {  
  887.         nndwi2  
  888.       }  
  889.       // nn.W{i} = nn.W{i} - dW;  
  890.       W_a += (bc_nn_W.value(i) - nndwi3)  
  891.       // nn.vW{i} = nn.momentum*nn.vW{i} + dW;  
  892.       val nnvwi1 = if (bc_config.value.momentum > 0) {  
  893.         val vwi = bc_nn_vW.value(i)  
  894.         val vw3 = nndwi2 + (vwi * bc_config.value.momentum)  
  895.         vw3  
  896.       } else {  
  897.         bc_nn_vW.value(i)  
  898.       }  
  899.       vW_a += nnvwi1  
  900.     }  
  901.     Array(W_a.toArray, vW_a.toArray)  
  902.   }  
  903.   
  904.   /** 
  905.    * nneval是进行前向传播并计算输出误差 
  906.    * 计算神经网络中的每个节点的输出值,并计算平均误差; 
  907.    */  
  908.   def NNeval(  
  909.     batch_xy: RDD[(BDM[Double], BDM[Double])],  
  910.     bc_config: org.apache.spark.broadcast.Broadcast[NNConfig],  
  911.     bc_nn_W: org.apache.spark.broadcast.Broadcast[Array[BDM[Double]]]): Double = {  
  912.     // NNff是进行前向传播  
  913.     // nn = nnff(nn, batch_x, batch_y);  
  914.     val train_nnff = NeuralNet.NNff(batch_xy, bc_config, bc_nn_W)  
  915.     // error and loss  
  916.     // 输出误差计算  
  917.     val loss1 = train_nnff.map(f => f._1.error)  
  918.     val (loss2, counte) = loss1.treeAggregate((0.0, 0L))(  
  919.       seqOp = (c, v) => {  
  920.         // c: (e, count), v: (m)  
  921.         val e1 = c._1  
  922.         val e2 = (v :* v).sum  
  923.         val esum = e1 + e2  
  924.         (esum, c._2 + 1)  
  925.       },  
  926.       combOp = (c1, c2) => {  
  927.         // c: (e, count)  
  928.         val e1 = c1._1  
  929.         val e2 = c2._1  
  930.         val esum = e1 + e2  
  931.         (esum, c1._2 + c2._2)  
  932.       })  
  933.     val Loss = loss2 / counte.toDouble  
  934.     Loss * 0.5  
  935.   }  
  936. }  

1.2 NeuralNetModel代码

[java]  view plain  copy
  1. package NN  
  2.   
  3. import breeze.linalg.{  
  4.   Matrix => BM,  
  5.   CSCMatrix => BSM,  
  6.   DenseMatrix => BDM,  
  7.   Vector => BV,  
  8.   DenseVector => BDV,  
  9.   SparseVector => BSV  
  10. }  
  11. import org.apache.spark.rdd.RDD  
  12.   
  13. /** 
  14.  * label:目标矩阵 
  15.  * features:特征矩阵 
  16.  * predict_label:预测矩阵 
  17.  * error:误差 
  18.  */  
  19. case class PredictNNLabel(label: BDM[Double], features: BDM[Double], predict_label: BDM[Double], error: BDM[Double]) extends Serializable  
  20.   
  21. /** 
  22.  * NN(neural network) 
  23.  */  
  24.   
  25. class NeuralNetModel(  
  26.   val config: NNConfig,  
  27.   val weights: Array[BDM[Double]]) extends Serializable {  
  28.   
  29.   /** 
  30.    * 返回预测结果 
  31.    *  返回格式:(label, feature,  predict_label, error) 
  32.    */  
  33.   def predict(dataMatrix: RDD[(BDM[Double], BDM[Double])]): RDD[PredictNNLabel] = {  
  34.     val sc = dataMatrix.sparkContext  
  35.     val bc_nn_W = sc.broadcast(weights)  
  36.     val bc_config = sc.broadcast(config)  
  37.     // NNff是进行前向传播  
  38.     // nn = nnff(nn, batch_x, batch_y);  
  39.     val train_nnff = NeuralNet.NNff(dataMatrix, bc_config, bc_nn_W)  
  40.     val predict = train_nnff.map { f =>  
  41.       val label = f._1.label  
  42.       val error = f._1.error  
  43.       val nnan = f._1.nna(bc_config.value.layer - 1)  
  44.       val nna1 = f._1.nna(0)(::, 1 to -1)  
  45.       PredictNNLabel(label, nna1, nnan, error)  
  46.     }  
  47.     predict  
  48.   }  
  49.   
  50.   /** 
  51.    * 计算输出误差 
  52.    * 平均误差; 
  53.    */  
  54.   def Loss(predict: RDD[PredictNNLabel]): Double = {  
  55.     val predict1 = predict.map(f => f.error)  
  56.     // error and loss  
  57.     // 输出误差计算  
  58.     val loss1 = predict1  
  59.     val (loss2, counte) = loss1.treeAggregate((0.0, 0L))(  
  60.       seqOp = (c, v) => {  
  61.         // c: (e, count), v: (m)  
  62.         val e1 = c._1  
  63.         val e2 = (v :* v).sum  
  64.         val esum = e1 + e2  
  65.         (esum, c._2 + 1)  
  66.       },  
  67.       combOp = (c1, c2) => {  
  68.         // c: (e, count)  
  69.         val e1 = c1._1  
  70.         val e2 = c2._1  
  71.         val esum = e1 + e2  
  72.         (esum, c1._2 + c2._2)  
  73.       })  
  74.     val Loss = loss2 / counte.toDouble  
  75.     Loss * 0.5  
  76.   }  
  77.   
  78. }  

转载请注明出处:

http://blog.csdn.net/sunbow0

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值