3、Spark MLlib Deep Learning Convolution Neural Network (深度学习-卷积神经网络)3.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)

1、源代码

2、源代码解析

3、实例

第三章Convolution Neural Network(CNN)

1、源代码

2、源代码解析

3、实例

第四章 Stacked Auto-Encoders(SAE)

第五章CAE



第三章Convolution Neural Network (卷积神经网络)

1 源代码

眼下SparkMLlib Deep Learning工具箱源代码的github地址为:

https://github.com/sunbow1/SparkMLlibDeepLearn

1.1 CNN代码

  1. package CNN
  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. accumulate => Accumulate,
  21. rot90 => Rot90,
  22. sum => Bsum
  23. }
  24. import breeze.numerics.{
  25. exp => Bexp,
  26. tanh => Btanh
  27. }
  28.  
  29. import scala.collection.mutable.ArrayBuffer
  30. import java.util.Random
  31. import scala.math._
  32.  
  33. /**
  34. * types:网络层类别
  35. * outputmaps:特征map数量
  36. * kernelsize:卷积核k大小
  37. * k: 卷积核
  38. * b: 偏置
  39. * dk: 卷积核的偏导
  40. * db: 偏置的偏导
  41. * scale: pooling大小
  42. */
  43. case class CNNLayers(
  44. types: String,
  45. outputmaps: Double,
  46. kernelsize: Double,
  47. scale: Double,
  48. k: Array[Array[BDM[Double]]],
  49. b: Array[Double],
  50. dk: Array[Array[BDM[Double]]],
  51. db: Array[Double]) extends Serializable
  52.  
  53. /**
  54. * CNN(convolution neural network)卷积神经网络
  55. */
  56.  
  57. class CNN(
  58. private var mapsize: BDM[Double],
  59. private var types: Array[String],
  60. private var layer: Int,
  61. private var onum: Int,
  62. private var outputmaps: Array[Double],
  63. private var kernelsize: Array[Double],
  64. private var scale: Array[Double],
  65. private var alpha: Double,
  66. private var batchsize: Double,
  67. private var numepochs: Double) extends Serializable with Logging {
  68. // var mapsize = new BDM(1, 2, Array(28.0, 28.0))
  69. // var types = Array("i", "c", "s", "c", "s")
  70. // var layer = 5
  71. // var onum = 10
  72. // var outputmaps = Array(0.0, 6.0, 0.0, 12.0, 0.0)
  73. // var kernelsize = Array(0.0, 5.0, 0.0, 5.0, 0.0)
  74. // var scale = Array(0.0, 0.0, 2.0, 0.0, 2.0)
  75. // var alpha = 1.0
  76. // var batchsize = 50.0
  77. // var numepochs = 1.0
  78.  
  79. def this() = this(new BDM(1, 2, Array(28.0, 28.0)),
  80. Array("i", "c", "s", "c", "s"), 5, 10,
  81. Array(0.0, 6.0, 0.0, 12.0, 0.0),
  82. Array(0.0, 5.0, 0.0, 5.0, 0.0),
  83. Array(0.0, 0.0, 2.0, 0.0, 2.0),
  84. 1.0, 50.0, 1.0)
  85.  
  86. /** 设置输入层大小. Default: [28, 28]. */
  87. def setMapsize(mapsize: BDM[Double]): this.type = {
  88. this.mapsize = mapsize
  89. this
  90. }
  91.  
  92. /** 设置网络层类别. Default: [1"i", "c", "s", "c", "s"]. */
  93. def setTypes(types: Array[String]): this.type = {
  94. this.types = types
  95. this
  96. }
  97.  
  98. /** 设置网络层数. Default: 5. */
  99. def setLayer(layer: Int): this.type = {
  100. this.layer = layer
  101. this
  102. }
  103.  
  104. /** 设置输出维度. Default: 10. */
  105. def setOnum(onum: Int): this.type = {
  106. this.onum = onum
  107. this
  108. }
  109.  
  110. /** 设置特征map数量. Default: [0.0, 6.0, 0.0, 12.0, 0.0]. */
  111. def setOutputmaps(outputmaps: Array[Double]): this.type = {
  112. this.outputmaps = outputmaps
  113. this
  114. }
  115.  
  116. /** 设置卷积核k大小. Default: [0.0, 5.0, 0.0, 5.0, 0.0]. */
  117. def setKernelsize(kernelsize: Array[Double]): this.type = {
  118. this.kernelsize = kernelsize
  119. this
  120. }
  121.  
  122. /** 设置scale大小. Default: [0.0, 0.0, 2.0, 0.0, 2.0]. */
  123. def setScale(scale: Array[Double]): this.type = {
  124. this.scale = scale
  125. this
  126. }
  127.  
  128. /** 设置学习因子. Default: 1. */
  129. def setAlpha(alpha: Double): this.type = {
  130. this.alpha = alpha
  131. this
  132. }
  133.  
  134. /** 设置迭代大小. Default: 50. */
  135. def setBatchsize(batchsize: Double): this.type = {
  136. this.batchsize = batchsize
  137. this
  138. }
  139.  
  140. /** 设置迭代次数. Default: 1. */
  141. def setNumepochs(numepochs: Double): this.type = {
  142. this.numepochs = numepochs
  143. this
  144. }
  145.  
  146. /** 卷积神经网络层參数初始化. */
  147. def CnnSetup: (Array[CNNLayers], BDM[Double], BDM[Double], Double) = {
  148. var inputmaps1 = 1.0
  149. var mapsize1 = mapsize
  150. var confinit = ArrayBuffer[CNNLayers]()
  151. for (l <- 0 to layer - 1) { // layer
  152. val type1 = types(l)
  153. val outputmap1 = outputmaps(l)
  154. val kernelsize1 = kernelsize(l)
  155. val scale1 = scale(l)
  156. val layersconf = if (type1 == "s") { // 每一层參数初始化
  157. mapsize1 = mapsize1 / scale1
  158. val b1 = Array.fill(inputmaps1.toInt)(0.0)
  159. val ki = Array(Array(BDM.zeros[Double](1, 1)))
  160. new CNNLayers(type1, outputmap1, kernelsize1, scale1, ki, b1, ki, b1)
  161. } else if (type1 == "c") {
  162. mapsize1 = mapsize1 - kernelsize1 + 1.0
  163. val fan_out = outputmap1 * math.pow(kernelsize1, 2)
  164. val fan_in = inputmaps1 * math.pow(kernelsize1, 2)
  165. val ki = ArrayBuffer[Array[BDM[Double]]]()
  166. for (i <- 0 to inputmaps1.toInt - 1) { // input map
  167. val kj = ArrayBuffer[BDM[Double]]()
  168. for (j <- 0 to outputmap1.toInt - 1) { // output map
  169. val kk = (BDM.rand[Double](kernelsize1.toInt, kernelsize1.toInt) - 0.5) * 2.0 * sqrt(6.0 / (fan_in + fan_out))
  170. kj += kk
  171. }
  172. ki += kj.toArray
  173. }
  174. val b1 = Array.fill(outputmap1.toInt)(0.0)
  175. inputmaps1 = outputmap1
  176. new CNNLayers(type1, outputmap1, kernelsize1, scale1, ki.toArray, b1, ki.toArray, b1)
  177. } else {
  178. val ki = Array(Array(BDM.zeros[Double](1, 1)))
  179. val b1 = Array(0.0)
  180. new CNNLayers(type1, outputmap1, kernelsize1, scale1, ki, b1, ki, b1)
  181. }
  182. confinit += layersconf
  183. }
  184. val fvnum = mapsize1(0, 0) * mapsize1(0, 1) * inputmaps1
  185. val ffb = BDM.zeros[Double](onum, 1)
  186. val ffW = (BDM.rand[Double](onum, fvnum.toInt) - 0.5) * 2.0 * sqrt(6.0 / (onum + fvnum))
  187. (confinit.toArray, ffb, ffW, alpha)
  188. }
  189.  
  190. /**
  191. * 执行卷积神经网络算法.
  192. */
  193. def CNNtrain(train_d: RDD[(BDM[Double], BDM[Double])], opts: Array[Double]): CNNModel = {
  194. val sc = train_d.sparkContext
  195. var initStartTime = System.currentTimeMillis()
  196. var initEndTime = System.currentTimeMillis()
  197. // 參数初始化配置
  198. var (cnn_layers, cnn_ffb, cnn_ffW, cnn_alpha) = CnnSetup
  199. // 样本数据划分:训练数据、交叉检验数据
  200. val validation = opts(2)
  201. val splitW1 = Array(1.0 - validation, validation)
  202. val train_split1 = train_d.randomSplit(splitW1, System.nanoTime())
  203. val train_t = train_split1(0)
  204. val train_v = train_split1(1)
  205. // m:训练样本的数量
  206. val m = train_t.count
  207. // 计算batch的数量
  208. val batchsize = opts(0).toInt
  209. val numepochs = opts(1).toInt
  210. val numbatches = (m / batchsize).toInt
  211. var rL = Array.fill(numepochs * numbatches.toInt)(0.0)
  212. var n = 0
  213. // numepochs是循环的次数
  214. for (i <- 1 to numepochs) {
  215. initStartTime = System.currentTimeMillis()
  216. val splitW2 = Array.fill(numbatches)(1.0 / numbatches)
  217. // 依据分组权重,随机划分每组样本数据
  218. for (l <- 1 to numbatches) {
  219. // 权重
  220. val bc_cnn_layers = sc.broadcast(cnn_layers)
  221. val bc_cnn_ffb = sc.broadcast(cnn_ffb)
  222. val bc_cnn_ffW = sc.broadcast(cnn_ffW)
  223.  
  224. // 样本划分
  225. val train_split2 = train_t.randomSplit(splitW2, System.nanoTime())
  226. val batch_xy1 = train_split2(l - 1)
  227.  
  228. // CNNff是进行前向传播
  229. // net = cnnff(net, batch_x);
  230. val train_cnnff = CNN.CNNff(batch_xy1, bc_cnn_layers, bc_cnn_ffb, bc_cnn_ffW)
  231.  
  232. // CNNbp是后向传播
  233. // net = cnnbp(net, batch_y);
  234. val train_cnnbp = CNN.CNNbp(train_cnnff, bc_cnn_layers, bc_cnn_ffb, bc_cnn_ffW)
  235.  
  236. // 权重更新
  237. // net = cnnapplygrads(net, opts);
  238. val train_nnapplygrads = CNN.CNNapplygrads(train_cnnbp, bc_cnn_ffb, bc_cnn_ffW, cnn_alpha)
  239. cnn_ffW = train_nnapplygrads._1
  240. cnn_ffb = train_nnapplygrads._2
  241. cnn_layers = train_nnapplygrads._3
  242.  
  243. // error and loss
  244. // 输出误差计算
  245. // net.L = 1/2* sum(net.e(:) .^ 2) / size(net.e, 2);
  246. val rdd_loss1 = train_cnnbp._1.map(f => f._5)
  247. val (loss2, counte) = rdd_loss1.treeAggregate((0.0, 0L))(
  248. seqOp = (c, v) => {
  249. // c: (e, count), v: (m)
  250. val e1 = c._1
  251. val e2 = (v :* v).sum
  252. val esum = e1 + e2
  253. (esum, c._2 + 1)
  254. },
  255. combOp = (c1, c2) => {
  256. // c: (e, count)
  257. val e1 = c1._1
  258. val e2 = c2._1
  259. val esum = e1 + e2
  260. (esum, c1._2 + c2._2)
  261. })
  262. val Loss = (loss2 / counte.toDouble) * 0.5
  263. if (n == 0) {
  264. rL(n) = Loss
  265. } else {
  266. rL(n) = 0.09 * rL(n - 1) + 0.01 * Loss
  267. }
  268. n = n + 1
  269. }
  270. initEndTime = System.currentTimeMillis()
  271. // 打印输出结果
  272. printf("epoch: numepochs = %d , Took = %d seconds; batch train mse = %f.\n", i, scala.math.ceil((initEndTime - initStartTime).toDouble / 1000).toLong, rL(n - 1))
  273. }
  274. // 计算训练误差及交叉检验误差
  275. // Full-batch train mse
  276. var loss_train_e = 0.0
  277. var loss_val_e = 0.0
  278. loss_train_e = CNN.CNNeval(train_t, sc.broadcast(cnn_layers), sc.broadcast(cnn_ffb), sc.broadcast(cnn_ffW))
  279. if (validation > 0) loss_val_e = CNN.CNNeval(train_v, sc.broadcast(cnn_layers), sc.broadcast(cnn_ffb), sc.broadcast(cnn_ffW))
  280. printf("epoch: Full-batch train mse = %f, val mse = %f.\n", loss_train_e, loss_val_e)
  281. new CNNModel(cnn_layers, cnn_ffW, cnn_ffb)
  282. }
  283.  
  284. }
  285.  
  286. /**
  287. * NN(neural network)
  288. */
  289. object CNN extends Serializable {
  290.  
  291. // Initialization mode names
  292.  
  293. /**
  294. * sigm激活函数
  295. * X = 1./(1+exp(-P));
  296. */
  297. def sigm(matrix: BDM[Double]): BDM[Double] = {
  298. val s1 = 1.0 / (Bexp(matrix * (-1.0)) + 1.0)
  299. s1
  300. }
  301.  
  302. /**
  303. * tanh激活函数
  304. * f=1.7159*tanh(2/3.*A);
  305. */
  306. def tanh_opt(matrix: BDM[Double]): BDM[Double] = {
  307. val s1 = Btanh(matrix * (2.0 / 3.0)) * 1.7159
  308. s1
  309. }
  310.  
  311. /**
  312. * 克罗内克积
  313. *
  314. */
  315. def expand(a: BDM[Double], s: Array[Int]): BDM[Double] = {
  316. // val a = BDM((1.0, 2.0), (3.0, 4.0), (5.0, 6.0))
  317. // val s = Array(3, 2)
  318. val sa = Array(a.rows, a.cols)
  319. var tt = new Array[Array[Int]](sa.length)
  320. for (ii <- sa.length - 1 to 0 by -1) {
  321. var h = BDV.zeros[Int](sa(ii) * s(ii))
  322. h(0 to sa(ii) * s(ii) - 1 by s(ii)) := 1
  323. tt(ii) = Accumulate(h).data
  324. }
  325. var b = BDM.zeros[Double](tt(0).length, tt(1).length)
  326. for (j1 <- 0 to b.rows - 1) {
  327. for (j2 <- 0 to b.cols - 1) {
  328. b(j1, j2) = a(tt(0)(j1) - 1, tt(1)(j2) - 1)
  329. }
  330. }
  331. b
  332. }
  333.  
  334. /**
  335. * convn卷积计算
  336. */
  337. def convn(m0: BDM[Double], k0: BDM[Double], shape: String): BDM[Double] = {
  338. //val m0 = BDM((1.0, 1.0, 1.0, 1.0), (0.0, 0.0, 1.0, 1.0), (0.0, 1.0, 1.0, 0.0), (0.0, 1.0, 1.0, 0.0))
  339. //val k0 = BDM((1.0, 1.0), (0.0, 1.0))
  340. //val m0 = BDM((1.0, 1.0, 1.0), (1.0, 1.0, 1.0), (1.0, 1.0, 1.0))
  341. //val k0 = BDM((1.0, 2.0, 3.0), (4.0, 5.0, 6.0), (7.0, 8.0, 9.0))
  342. val out1 = shape match {
  343. case "valid" =>
  344. val m1 = m0
  345. val k1 = k0.t
  346. val row1 = m1.rows - k1.rows + 1
  347. val col1 = m1.cols - k1.cols + 1
  348. var m2 = BDM.zeros[Double](row1, col1)
  349. for (i <- 0 to row1 - 1) {
  350. for (j <- 0 to col1 - 1) {
  351. val r1 = i
  352. val r2 = r1 + k1.rows - 1
  353. val c1 = j
  354. val c2 = c1 + k1.cols - 1
  355. val mi = m1(r1 to r2, c1 to c2)
  356. m2(i, j) = (mi :* k1).sum
  357. }
  358. }
  359. m2
  360. case "full" =>
  361. var m1 = BDM.zeros[Double](m0.rows + 2 * (k0.rows - 1), m0.cols + 2 * (k0.cols - 1))
  362. for (i <- 0 to m0.rows - 1) {
  363. for (j <- 0 to m0.cols - 1) {
  364. m1((k0.rows - 1) + i, (k0.cols - 1) + j) = m0(i, j)
  365. }
  366. }
  367. val k1 = Rot90(Rot90(k0))
  368. val row1 = m1.rows - k1.rows + 1
  369. val col1 = m1.cols - k1.cols + 1
  370. var m2 = BDM.zeros[Double](row1, col1)
  371. for (i <- 0 to row1 - 1) {
  372. for (j <- 0 to col1 - 1) {
  373. val r1 = i
  374. val r2 = r1 + k1.rows - 1
  375. val c1 = j
  376. val c2 = c1 + k1.cols - 1
  377. val mi = m1(r1 to r2, c1 to c2)
  378. m2(i, j) = (mi :* k1).sum
  379. }
  380. }
  381. m2
  382. }
  383. out1
  384. }
  385.  
  386. /**
  387. * cnnff是进行前向传播
  388. * 计算神经网络中的每一个节点的输出值;
  389. */
  390. def CNNff(
  391. batch_xy1: RDD[(BDM[Double], BDM[Double])],
  392. bc_cnn_layers: org.apache.spark.broadcast.Broadcast[Array[CNNLayers]],
  393. bc_cnn_ffb: org.apache.spark.broadcast.Broadcast[BDM[Double]],
  394. bc_cnn_ffW: org.apache.spark.broadcast.Broadcast[BDM[Double]]): RDD[(BDM[Double], Array[Array[BDM[Double]]], BDM[Double], BDM[Double])] = {
  395. // 第1层:a(1)=[x]
  396. val train_data1 = batch_xy1.map { f =>
  397. val lable = f._1
  398. val features = f._2
  399. val nna1 = Array(features)
  400. val nna = ArrayBuffer[Array[BDM[Double]]]()
  401. nna += nna1
  402. (lable, nna)
  403. }
  404. // 第2至n-1层计算
  405. val train_data2 = train_data1.map { f =>
  406. val lable = f._1
  407. val nn_a = f._2
  408. var inputmaps1 = 1.0
  409. val n = bc_cnn_layers.value.length
  410. // for each layer
  411. for (l <- 1 to n - 1) {
  412. val type1 = bc_cnn_layers.value(l).types
  413. val outputmap1 = bc_cnn_layers.value(l).outputmaps
  414. val kernelsize1 = bc_cnn_layers.value(l).kernelsize
  415. val scale1 = bc_cnn_layers.value(l).scale
  416. val k1 = bc_cnn_layers.value(l).k
  417. val b1 = bc_cnn_layers.value(l).b
  418. val nna1 = ArrayBuffer[BDM[Double]]()
  419. if (type1 == "c") {
  420. for (j <- 0 to outputmap1.toInt - 1) { // output map
  421. // create temp output map
  422. var z = BDM.zeros[Double](nn_a(l - 1)(0).rows - kernelsize1.toInt + 1, nn_a(l - 1)(0).cols - kernelsize1.toInt + 1)
  423. for (i <- 0 to inputmaps1.toInt - 1) { // input map
  424. // convolve with corresponding kernel and add to temp output map
  425. // z = z + convn(net.layers{l - 1}.a{i}, net.layers{l}.k{i}{j}, 'valid');
  426. z = z + convn(nn_a(l - 1)(i), k1(i)(j), "valid")
  427. }
  428. // add bias, pass through nonlinearity
  429. // net.layers{l}.a{j} = sigm(z + net.layers{l}.b{j})
  430. val nna0 = sigm(z + b1(j))
  431. nna1 += nna0
  432. }
  433. nn_a += nna1.toArray
  434. inputmaps1 = outputmap1
  435. } else if (type1 == "s") {
  436. for (j <- 0 to inputmaps1.toInt - 1) {
  437. // z = convn(net.layers{l - 1}.a{j}, ones(net.layers{l}.scale) / (net.layers{l}.scale ^ 2), 'valid'); replace with variable
  438. // net.layers{l}.a{j} = z(1 : net.layers{l}.scale : end, 1 : net.layers{l}.scale : end, :);
  439. val z = convn(nn_a(l - 1)(j), BDM.ones[Double](scale1.toInt, scale1.toInt) / (scale1 * scale1), "valid")
  440. val zs1 = z(::, 0 to -1 by scale1.toInt).t + 0.0
  441. val zs2 = zs1(::, 0 to -1 by scale1.toInt).t + 0.0
  442. val nna0 = zs2
  443. nna1 += nna0
  444. }
  445. nn_a += nna1.toArray
  446. }
  447. }
  448. // concatenate all end layer feature maps into vector
  449. val nn_fv1 = ArrayBuffer[Double]()
  450. for (j <- 0 to nn_a(n - 1).length - 1) {
  451. nn_fv1 ++= nn_a(n - 1)(j).data
  452. }
  453. val nn_fv = new BDM[Double](nn_fv1.length, 1, nn_fv1.toArray)
  454. // feedforward into output perceptrons
  455. // net.o = sigm(net.ffW * net.fv + repmat(net.ffb, 1, size(net.fv, 2)));
  456. val nn_o = sigm(bc_cnn_ffW.value * nn_fv + bc_cnn_ffb.value)
  457. (lable, nn_a.toArray, nn_fv, nn_o)
  458. }
  459. train_data2
  460. }
  461.  
  462. /**
  463. * CNNbp是后向传播
  464. * 计算权重的平均偏导数
  465. */
  466. def CNNbp(
  467. train_cnnff: RDD[(BDM[Double], Array[Array[BDM[Double]]], BDM[Double], BDM[Double])],
  468. bc_cnn_layers: org.apache.spark.broadcast.Broadcast[Array[CNNLayers]],
  469. bc_cnn_ffb: org.apache.spark.broadcast.Broadcast[BDM[Double]],
  470. bc_cnn_ffW: org.apache.spark.broadcast.Broadcast[BDM[Double]]): (RDD[(BDM[Double], Array[Array[BDM[Double]]], BDM[Double], BDM[Double], BDM[Double], BDM[Double], BDM[Double], Array[Array[BDM[Double]]])], BDM[Double], BDM[Double], Array[CNNLayers]) = {
  471. // error : net.e = net.o - y
  472. val n = bc_cnn_layers.value.length
  473. val train_data3 = train_cnnff.map { f =>
  474. val nn_e = f._4 - f._1
  475. (f._1, f._2, f._3, f._4, nn_e)
  476. }
  477. // backprop deltas
  478. // 输出层的 灵敏度 或者 残差
  479. // net.od = net.e .* (net.o .* (1 - net.o))
  480. // net.fvd = (net.ffW' * net.od)
  481. val train_data4 = train_data3.map { f =>
  482. val nn_e = f._5
  483. val nn_o = f._4
  484. val nn_fv = f._3
  485. val nn_od = nn_e :* (nn_o :* (1.0 - nn_o))
  486. val nn_fvd = if (bc_cnn_layers.value(n - 1).types == "c") {
  487. // net.fvd = net.fvd .* (net.fv .* (1 - net.fv));
  488. val nn_fvd1 = bc_cnn_ffW.value.t * nn_od
  489. val nn_fvd2 = nn_fvd1 :* (nn_fv :* (1.0 - nn_fv))
  490. nn_fvd2
  491. } else {
  492. val nn_fvd1 = bc_cnn_ffW.value.t * nn_od
  493. nn_fvd1
  494. }
  495. (f._1, f._2, f._3, f._4, f._5, nn_od, nn_fvd)
  496. }
  497. // reshape feature vector deltas into output map style
  498. val sa1 = train_data4.map(f => f._2(n - 1)(1)).take(1)(0).rows
  499. val sa2 = train_data4.map(f => f._2(n - 1)(1)).take(1)(0).cols
  500. val sa3 = 1
  501. val fvnum = sa1 * sa2
  502.  
  503. val train_data5 = train_data4.map { f =>
  504. val nn_a = f._2
  505. val nn_fvd = f._7
  506. val nn_od = f._6
  507. val nn_fv = f._3
  508. var nnd = new Array[Array[BDM[Double]]](n)
  509. val nnd1 = ArrayBuffer[BDM[Double]]()
  510. for (j <- 0 to nn_a(n - 1).length - 1) {
  511. val tmp1 = nn_fvd((j * fvnum) to ((j + 1) * fvnum - 1), 0)
  512. val tmp2 = new BDM(sa1, sa2, tmp1.data)
  513. nnd1 += tmp2
  514. }
  515. nnd(n - 1) = nnd1.toArray
  516. for (l <- (n - 2) to 0 by -1) {
  517. val type1 = bc_cnn_layers.value(l).types
  518. var nnd2 = ArrayBuffer[BDM[Double]]()
  519. if (type1 == "c") {
  520. for (j <- 0 to nn_a(l).length - 1) {
  521. val tmp_a = nn_a(l)(j)
  522. val tmp_d = nnd(l + 1)(j)
  523. val tmp_scale = bc_cnn_layers.value(l + 1).scale.toInt
  524. val tmp1 = tmp_a :* (1.0 - tmp_a)
  525. val tmp2 = expand(tmp_d, Array(tmp_scale, tmp_scale)) / (tmp_scale.toDouble * tmp_scale)
  526. nnd2 += (tmp1 :* tmp2)
  527. }
  528. } else if (type1 == "s") {
  529. for (i <- 0 to nn_a(l).length - 1) {
  530. var z = BDM.zeros[Double](nn_a(l)(0).rows, nn_a(l)(0).cols)
  531. for (j <- 0 to nn_a(l + 1).length - 1) {
  532. // z = z + convn(net.layers{l + 1}.d{j}, rot180(net.layers{l + 1}.k{i}{j}), 'full');
  533. z = z + convn(nnd(l + 1)(j), Rot90(Rot90(bc_cnn_layers.value(l + 1).k(i)(j))), "full")
  534. }
  535. nnd2 += z
  536. }
  537. }
  538. nnd(l) = nnd2.toArray
  539. }
  540. (f._1, f._2, f._3, f._4, f._5, f._6, f._7, nnd)
  541. }
  542. // dk db calc gradients
  543. var cnn_layers = bc_cnn_layers.value
  544. for (l <- 1 to n - 1) {
  545. val type1 = bc_cnn_layers.value(l).types
  546. val lena1 = train_data5.map(f => f._2(l).length).take(1)(0)
  547. val lena2 = train_data5.map(f => f._2(l - 1).length).take(1)(0)
  548. if (type1 == "c") {
  549. for (j <- 0 to lena1 - 1) {
  550. for (i <- 0 to lena2 - 1) {
  551. val rdd_dk_ij = train_data5.map { f =>
  552. val nn_a = f._2
  553. val nn_d = f._8
  554. val tmp_d = nn_d(l)(j)
  555. val tmp_a = nn_a(l - 1)(i)
  556. convn(Rot90(Rot90(tmp_a)), tmp_d, "valid")
  557. }
  558. val initdk = BDM.zeros[Double](rdd_dk_ij.take(1)(0).rows, rdd_dk_ij.take(1)(0).cols)
  559. val (dk_ij, count_dk) = rdd_dk_ij.treeAggregate((initdk, 0L))(
  560. seqOp = (c, v) => {
  561. // c: (m, count), v: (m)
  562. val m1 = c._1
  563. val m2 = m1 + v
  564. (m2, c._2 + 1)
  565. },
  566. combOp = (c1, c2) => {
  567. // c: (m, count)
  568. val m1 = c1._1
  569. val m2 = c2._1
  570. val m3 = m1 + m2
  571. (m3, c1._2 + c2._2)
  572. })
  573. val dk = dk_ij / count_dk.toDouble
  574. cnn_layers(l).dk(i)(j) = dk
  575. }
  576. val rdd_db_j = train_data5.map { f =>
  577. val nn_d = f._8
  578. val tmp_d = nn_d(l)(j)
  579. Bsum(tmp_d)
  580. }
  581. val db_j = rdd_db_j.reduce(_ + _)
  582. val count_db = rdd_db_j.count
  583. val db = db_j / count_db.toDouble
  584. cnn_layers(l).db(j) = db
  585. }
  586. }
  587. }
  588.  
  589. // net.dffW = net.od * (net.fv)' / size(net.od, 2);
  590. // net.dffb = mean(net.od, 2);
  591. val train_data6 = train_data5.map { f =>
  592. val nn_od = f._6
  593. val nn_fv = f._3
  594. nn_od * nn_fv.t
  595. }
  596. val train_data7 = train_data5.map { f =>
  597. val nn_od = f._6
  598. nn_od
  599. }
  600. val initffW = BDM.zeros[Double](bc_cnn_ffW.value.rows, bc_cnn_ffW.value.cols)
  601. val (ffw2, countfffw2) = train_data6.treeAggregate((initffW, 0L))(
  602. seqOp = (c, v) => {
  603. // c: (m, count), v: (m)
  604. val m1 = c._1
  605. val m2 = m1 + v
  606. (m2, c._2 + 1)
  607. },
  608. combOp = (c1, c2) => {
  609. // c: (m, count)
  610. val m1 = c1._1
  611. val m2 = c2._1
  612. val m3 = m1 + m2
  613. (m3, c1._2 + c2._2)
  614. })
  615. val cnn_dffw = ffw2 / countfffw2.toDouble
  616. val initffb = BDM.zeros[Double](bc_cnn_ffb.value.rows, bc_cnn_ffb.value.cols)
  617. val (ffb2, countfffb2) = train_data7.treeAggregate((initffb, 0L))(
  618. seqOp = (c, v) => {
  619. // c: (m, count), v: (m)
  620. val m1 = c._1
  621. val m2 = m1 + v
  622. (m2, c._2 + 1)
  623. },
  624. combOp = (c1, c2) => {
  625. // c: (m, count)
  626. val m1 = c1._1
  627. val m2 = c2._1
  628. val m3 = m1 + m2
  629. (m3, c1._2 + c2._2)
  630. })
  631. val cnn_dffb = ffb2 / countfffb2.toDouble
  632. (train_data5, cnn_dffw, cnn_dffb, cnn_layers)
  633. }
  634.  
  635. /**
  636. * NNapplygrads是权重更新
  637. * 权重更新
  638. */
  639. def CNNapplygrads(
  640. train_cnnbp: (RDD[(BDM[Double], Array[Array[BDM[Double]]], BDM[Double], BDM[Double], BDM[Double], BDM[Double], BDM[Double], Array[Array[BDM[Double]]])], BDM[Double], BDM[Double], Array[CNNLayers]),
  641. bc_cnn_ffb: org.apache.spark.broadcast.Broadcast[BDM[Double]],
  642. bc_cnn_ffW: org.apache.spark.broadcast.Broadcast[BDM[Double]],
  643. alpha: Double): (BDM[Double], BDM[Double], Array[CNNLayers]) = {
  644. val train_data5 = train_cnnbp._1
  645. val cnn_dffw = train_cnnbp._2
  646. val cnn_dffb = train_cnnbp._3
  647. var cnn_layers = train_cnnbp._4
  648. var cnn_ffb = bc_cnn_ffb.value
  649. var cnn_ffW = bc_cnn_ffW.value
  650. val n = cnn_layers.length
  651.  
  652. for (l <- 1 to n - 1) {
  653. val type1 = cnn_layers(l).types
  654. val lena1 = train_data5.map(f => f._2(l).length).take(1)(0)
  655. val lena2 = train_data5.map(f => f._2(l - 1).length).take(1)(0)
  656. if (type1 == "c") {
  657. for (j <- 0 to lena1 - 1) {
  658. for (ii <- 0 to lena2 - 1) {
  659. cnn_layers(l).k(ii)(j) = cnn_layers(l).k(ii)(j) - cnn_layers(l).dk(ii)(j)
  660. }
  661. cnn_layers(l).b(j) = cnn_layers(l).b(j) - cnn_layers(l).db(j)
  662. }
  663. }
  664. }
  665. cnn_ffW = cnn_ffW + cnn_dffw
  666. cnn_ffb = cnn_ffb + cnn_dffb
  667. (cnn_ffW, cnn_ffb, cnn_layers)
  668. }
  669.  
  670. /**
  671. * nneval是进行前向传播并计算输出误差
  672. * 计算神经网络中的每一个节点的输出值,并计算平均误差;
  673. */
  674. def CNNeval(
  675. batch_xy1: RDD[(BDM[Double], BDM[Double])],
  676. bc_cnn_layers: org.apache.spark.broadcast.Broadcast[Array[CNNLayers]],
  677. bc_cnn_ffb: org.apache.spark.broadcast.Broadcast[BDM[Double]],
  678. bc_cnn_ffW: org.apache.spark.broadcast.Broadcast[BDM[Double]]): Double = {
  679. // CNNff是进行前向传播
  680. val train_cnnff = CNN.CNNff(batch_xy1, bc_cnn_layers, bc_cnn_ffb, bc_cnn_ffW)
  681. // error and loss
  682. // 输出误差计算
  683. val rdd_loss1 = train_cnnff.map { f =>
  684. val nn_e = f._4 - f._1
  685. nn_e
  686. }
  687. val (loss2, counte) = rdd_loss1.treeAggregate((0.0, 0L))(
  688. seqOp = (c, v) => {
  689. // c: (e, count), v: (m)
  690. val e1 = c._1
  691. val e2 = (v :* v).sum
  692. val esum = e1 + e2
  693. (esum, c._2 + 1)
  694. },
  695. combOp = (c1, c2) => {
  696. // c: (e, count)
  697. val e1 = c1._1
  698. val e2 = c2._1
  699. val esum = e1 + e2
  700. (esum, c1._2 + c2._2)
  701. })
  702. val Loss = (loss2 / counte.toDouble) * 0.5
  703. Loss
  704. }
  705. }

1.2 CNNModel代码

  1. package CNN
  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 PredictCNNLabel(label: BDM[Double], features: BDM[Double], predict_label: BDM[Double], error: BDM[Double]) extends Serializable
  20.  
  21. class CNNModel(
  22. val cnn_layers: Array[CNNLayers],
  23. val cnn_ffW: BDM[Double],
  24. val cnn_ffb: BDM[Double]) extends Serializable {
  25.  
  26. /**
  27. * 返回预測结果
  28. * 返回格式:(label, feature, predict_label, error)
  29. */
  30. def predict(dataMatrix: RDD[(BDM[Double], BDM[Double])]): RDD[PredictCNNLabel] = {
  31. val sc = dataMatrix.sparkContext
  32. val bc_cnn_layers = sc.broadcast(cnn_layers)
  33. val bc_cnn_ffW = sc.broadcast(cnn_ffW)
  34. val bc_cnn_ffb = sc.broadcast(cnn_ffb)
  35. // CNNff是进行前向传播
  36. val train_cnnff = CNN.CNNff(dataMatrix, bc_cnn_layers, bc_cnn_ffb, bc_cnn_ffW)
  37. val rdd_predict = train_cnnff.map { f =>
  38. val label = f._1
  39. val nna1 = f._2(0)(0)
  40. val nnan = f._4
  41. val error = f._4 - f._1
  42. PredictCNNLabel(label, nna1, nnan, error)
  43. }
  44. rdd_predict
  45. }
  46.  
  47. /**
  48. * 计算输出误差
  49. * 平均误差;
  50. */
  51. def Loss(predict: RDD[PredictCNNLabel]): Double = {
  52. val predict1 = predict.map(f => f.error)
  53. // error and loss
  54. // 输出误差计算
  55. val loss1 = predict1
  56. val (loss2, counte) = loss1.treeAggregate((0.0, 0L))(
  57. seqOp = (c, v) => {
  58. // c: (e, count), v: (m)
  59. val e1 = c._1
  60. val e2 = (v :* v).sum
  61. val esum = e1 + e2
  62. (esum, c._2 + 1)
  63. },
  64. combOp = (c1, c2) => {
  65. // c: (e, count)
  66. val e1 = c1._1
  67. val e2 = c2._1
  68. val esum = e1 + e2
  69. (esum, c1._2 + c2._2)
  70. })
  71. val Loss = (loss2 / counte.toDouble) * 0.5
  72. Loss
  73. }
  74.  
  75. }

转载请注明出处:

http://blog.csdn.net/sunbow0

Spark MLlib Deep Learning Convolution Neural Network (深度学习-卷积神经网络)3.1的更多相关文章

  1. Spark MLlib Deep Learning Convolution Neural Network (深度学习-卷积神经网络)3.2

    3.Spark MLlib Deep Learning Convolution Neural Network(深度学习-卷积神经网络)3.2 http://blog.csdn.net/sunbow0 ...

  2. Spark MLlib Deep Learning Convolution Neural Network (深度学习-卷积神经网络)3.3

    3.Spark MLlib Deep Learning Convolution Neural Network(深度学习-卷积神经网络)3.3 http://blog.csdn.net/sunbow0 ...

  3. Spark MLlib Deep Learning Deep Belief Network (深度学习-深度信念网络)2.1

    Spark MLlib Deep Learning Deep Belief Network (深度学习-深度信念网络)2.1 http://blog.csdn.net/sunbow0 Spark ML ...

  4. Spark MLlib Deep Learning Deep Belief Network (深度学习-深度信念网络)2.3

    Spark MLlib Deep Learning Deep Belief Network (深度学习-深度信念网络)2.3 http://blog.csdn.net/sunbow0 第二章Deep ...

  5. Spark MLlib Deep Learning Deep Belief Network (深度学习-深度信念网络)2.2

    Spark MLlib Deep Learning Deep Belief Network (深度学习-深度信念网络)2.2 http://blog.csdn.net/sunbow0 第二章Deep ...

  6. Deep learning与Neural Network

    深度学习是机器学习研究中的一个新的领域,其动机在于建立.模拟人脑进行分析学习的神经网络,它模仿人脑的机制来解释数据,例如图像,声音和文本.深度学习是无监督学习的一种. 深度学习的概念源于人工神经网络的 ...

  7. 通过Visualizing Representations来理解Deep Learning、Neural network、以及输入样本自身的高维空间结构

    catalogue . 引言 . Neural Networks Transform Space - 神经网络内部的空间结构 . Understand the data itself by visua ...

  8. Deep Learning 教程(斯坦福深度学习研究团队)

    http://www.zhizihua.com/blog/post/602.html 说明:本教程将阐述无监督特征学习和深度学习的主要观点.通过学习,你也将实现多个功能学习/深度学习算法,能看到它们为 ...

  9. 【Deep Learning读书笔记】深度学习中的概率论

    本文首发自公众号:RAIS,期待你的关注. 前言 本系列文章为 <Deep Learning> 读书笔记,可以参看原书一起阅读,效果更佳. 概率论 机器学习中,往往需要大量处理不确定量,或 ...

随机推荐

  1. AE 中的查找与定位,以城市查找为例

    在文本框输入一个城市,在地图上查找,当找到后让mapcontrol自动跳转到地图上该点. IQueryFilter filter = new QueryFilterClass(); filter.Wh ...

  2. Drupal 7.23:函数drupal_alter()注释

    /** * Passes alterable variables to specific hook_TYPE_alter() implementations. * * This dispatch fu ...

  3. Php 笔记3-----php与 asp的等价关系

    对比asp.net 与 php的对比  ,有助于进一步理解 php. 1  输出. asp.net 输出    Response.Write(str);    // 将string 写入到 服务器向浏 ...

  4. php sortable 动态排序

    php sortable 动态排序未分页版.php 预览图: <?php mysql_connect("localhost","root","r ...

  5. ASP.NET转换人民币大小金额

    public class DecimalToRMB    {        /// <summary>         /// 转换人民币大小金额         /// </sum ...

  6. CAT XQX --- 省市三级级联实现说明

    最终效果: 满足要求, 上代码 : 1.   需要调用这个控件 的地方:添加引用,因为里面写着逻辑呢..... <script type="text/javascript" ...

  7. lua Date和Time

    time和date两个函数在Lua中实现所有的时钟查询功能.函数time在没有参数时返回当前时钟的数值.(在许多系统中该数值是当前距离某个特定时间的秒数.)当为函数调用附加一个特殊的时间表时,该函数就 ...

  8. Struts1与Struts2的异同

    1.都是MVC的WEB框架 2.struts1是老牌框架,应用很广泛,有很好的群众基础,使用它开发风险很小,成本更低: struts2虽然基于这个框架,但是应用群众并不多,相对不成熟,未知的风险和变化 ...

  9. (转)Spring中Bean的命名问题(id和name区别)及ref和idref之间的区别

    Spring中Bean的命名 1.每个Bean可以有一个id属性,并可以根据该id在IoC容器中查找该Bean,该id属性值必须在IoC容器中唯一: 2.可以不指定id属性,只指定全限定类名,如: & ...

  10. 输出(test)

    本题要求从输入的N个整数中查找给定的X.如果找到,输出X的位置(从0开始数):如果没有找到,输出“Not Found”. 输入格式: 输入在第1行中给出2个正整数N(<=20)和X,第2行给出N ...