1. 程式人生 > >跟著吳恩達學深度學習:用Scala實現神經網路-第二課:用Scala實現多層神經網路

跟著吳恩達學深度學習:用Scala實現神經網路-第二課:用Scala實現多層神經網路

上一章我們講了如何使用Scala實現LogisticRegression,這一張跟隨著吳恩達的腳步我們用Scala實現基礎的深度神經網路。順便再提一下,吳恩達對於深度神經網路的解釋是我如今聽過的最清楚的課,感嘆一句果然越是大牛知識解釋得越清晰明瞭。

本文分為以下四個部分。按照軟體開發top-down的思路,第一部分我先展示一下使用構建好的神經網路對Gas Censor資料進行分類的demo,這一部分重點關注介面的頂層設計,如何達到易用、簡潔、邏輯清晰以及新手友好,這是軟體工程一個比較難的領域,所以我的介面設計不一定是最優的,歡迎在評論區提出自己的想法,我們共用探討~

第二個部分給出了NeuralNetworkModel類的具體實現。從介面的角度來看,NeuralNetworkModel實現了名為Model的trait(類似於Java中的interface),所有的model都擁有一些common protocol,在本專案中所有的model都擁有setLearningRate,setIterationTime,train,predict,accuracy,getCostHistory方法,此外NeuralNetworkModel也擁有自己獨有的setHiddenLayerStructure,setOutputLayerStructure方法。

第三部分我們介紹了各種神經網路Layer的實現,包含ReluLayer,SigmoidLayer,TanhLayer這三個類。所有的layer都實現了名叫Layer的trait,提供etNumHiddenUnits,forward和backward三個方法。

第一部分:demo介紹

首先我們先看看使用神經網路模型的使用demo。

package org.mengpan.deeplearning.demo

import breeze.stats.{mean, stddev}
import org.mengpan.deeplearning.data.{Cat, GasCensor}
import

org.mengpan.deeplearning.helper.{CatDataHelper, DlCollection, GasCensorDataHelper}
import org.mengpan.deeplearning.model.{Model, NeuralNetworkModel, ShallowNeuralNetworkModel}
import org.mengpan.deeplearning.utils.{MyDict, NormalizeUtils, PlotUtils}

/**
  * Created by mengpan on 2017/8/15.
  */
object ClassThreeNeuralNetworkDemo
extends App{
  
// Dataset Download Website:http://archive.ics.uci.edu/ml/machine-learning-databases/00224/
  //
載入Gas Censor的資料集val data: DlCollection[GasCensor] = GasCensorDataHelper.getAllData

 
//歸一化資料特徵矩陣val normalizedCatData = NormalizeUtils.normalizeBy(data){col =>
    (col - mean(col)) / stddev(col)
  }

 
//獲取training settest set
 
val (training, test) = normalizedCatData.split(0.8)

 
//分別獲取訓練集和測試集的featurelabel
 
val trainingFeature = training.getFeatureAsMatrix
 
val trainingLabel = training.getLabelAsVector
 
val testFeature = test.getFeatureAsMatrix
 
val testLabel = test.getLabelAsVector

 
//初始化演算法模型val nnModel: Model = new NeuralNetworkModel()
    .setHiddenLayerStructure(
Map(
      (
200, MyDict.ACTIVATION_RELU),
     
(100, MyDict.ACTIVATION_RELU)
    ))
    .setOutputLayerStructure((
1, MyDict.ACTIVATION_SIGMOID))
    .setLearningRate(
0.01)
    .setIterationTime(
5000)

 
//用訓練集的資料訓練演算法val trainedModel: Model = nnModel.train(trainingFeature, trainingLabel)

 
//測試演算法獲得演算法優劣指標val yPredicted = trainedModel.predict(testFeature)
 
val trainYPredicted = trainedModel.predict(trainingFeature)

 
val testAccuracy = trainedModel.accuracy(testLabel, yPredicted)
 
val trainAccuracy = trainedModel.accuracy(trainingLabel, trainYPredicted)
  println(
"\n The trainaccuracy of this model is: " + trainAccuracy)
  println(
"\n The testaccuracy of this model is: " + testAccuracy)

 
//對演算法的訓練過程中cost與迭代次數變化關係進行畫圖val costHistory = trainedModel.getCostHistory
  PlotUtils.plotCostHistory(
costHistory)
}

對於神經網路的模型介面,我們採用了Scala中典型的鏈式程式設計法:

//初始化演算法模型val nnModel: Model = new NeuralNetworkModel()
  .setHiddenLayerStructure(Map(
    (200, MyDict.ACTIVATION_RELU),
    (100, MyDict.ACTIVATION_RELU)
  ))
  .setOutputLayerStructure((1, MyDict.ACTIVATION_SIGMOID))
  .setLearningRate(0.01)
  .setIterationTime(5000)

setHiddenLayerStructure方法用於設定神經網路隱含層的結構,接受多個二元元祖為引數,二元元祖的第一個引數為該層隱含層層的神經單元個數;第二個引數為該層隱含層層的啟用函式型別。如上圖中構建的神經網路擁有兩個隱含層,第一個隱含層擁有200個神經元,啟用函式型別為ReLU,第二個隱含層擁有100個神經元,啟用函式型別也為ReLU。setOutputLayerStructure方法接受一個二元元祖為引數,元祖的含義與前面相同。

第二部分:NeuralNetworkModel類的具體實現

首先我把此類中的重要的方法解釋一下,完整的程式碼附在本部分最後面。首先我們來看一下train()方法:

override def train(feature: DenseMatrix[Double], label: DenseVector[Double]): NeuralNetworkModel.this.type = {
  val numExamples = feature.rows
  val inputDim = feature.cols

  logger.debug("hidden layers: " + hiddenLayers)
  logger.debug("output layer: " + outputLayer)

  //隨機初始化模型引數var paramsList: List[(DenseMatrix[Double], DenseVector[Double])] =
    initializeParams(numExamples, inputDim, hiddenLayers, outputLayer)

  (0 until this.iterationTime).foreach{i =>
    val forwardResList: List[ForwardRes] = forward(feature, paramsList,
      hiddenLayers, outputLayer)

    logger.debug(forwardResList)

    val cost = calCost(forwardResList.last, label)
    if (i % 100 == 0) {
      logger.info("Cost in " + i + "th time of iteration: " + cost)
    }
    costHistory.put(i, cost)

    val backwardResList: List[BackwardRes] = backward(feature, label, forwardResList,
      paramsList, hiddenLayers, outputLayer)

    logger.debug(backwardResList)

    paramsList = updateParams(paramsList, this.learningRate, backwardResList, i, cost)
  }

  this.paramsList = paramsList
  this
}

可以看到,在神經網路模型的train()方法中,有五個主要的私有功能函式:首先用initializeParams(numExamples, inputDim, hiddenLayers, outputLayer)初始化引數;然後在每一次迭代過程中:

l   先使用forward()計算前向傳播的結果;

l   在使用calCost()計算此次的損失函式值;

l   然後使用backward()計算反向傳播的結果;

l   最後使用updateParams()更新引數;

接下來看看隨機初始化引數的方法initializeParams(),一些需要關注的語法點都寫在註釋裡面了。

private def initializeParams(numExamples: Int, inputDim: Int,
                             hiddenLayers: Seq[Layer], outputLayer: Layer):
List[(DenseMatrix[Double], DenseVector[Double])] = {

  /*
   *把輸入層,隱含層,輸出層的神經元個數組合成一個Vector
   *inputDim=3outputDim=1hiddenDim=(3, 3, 2),則layersDim=(3, 3, 3, 2, 1)
   *兩個List的操作符,A.::(b)為在A前面加上元素bA.:+(B)為在A的後面加上元素b
   *這裡使用Vector儲存layersDim,因為Vectorindexed sequence,訪問任意位置的元素時間相同
  */
  val layersDim = hiddenLayers.map(_.numHiddenUnits)
    .toList
    .::(inputDim)
    .:+(outputLayer.numHiddenUnits)
    .toVector

  val numLayers = layersDim.length

  /*
   *W(l)的維度為(layersDim(l-1), layersDim(l))
   *b(l)的維度為(layersDim(l), )
   *注意隨機初始化的數值在0-1之間,為保證模型穩定性,需在wb後面*0.01
  */
  (1 until numLayers).map{i =>
    val w = DenseMatrix.rand[Double](layersDim(i-1), layersDim(i)) * 0.01
    val b = DenseVector.rand[Double](layersDim(i)) * 0.01
    (w, b)
  }.toList
}

然後看看計算前向傳播的函式forward()的具體實現,相關需要注意的知識點也寫在註釋裡了,另外layer.forward()的實現我們在下一部分講解Layer類時會解釋:

private def forward(feature: DenseMatrix[Double],
                    params: List[(DenseMatrix[Double],
                      DenseVector[Double])],
                    hiddenLayers: Seq[Layer],
                    outputLayer: Layer): List[ForwardRes] = {
  var yi = feature

  /*
   *這裡注意Scalazip的用法。假設A=List(1, 2, 3), B=List(3, 4), 
   * A.zip(B)  List((1, 3), (2, 4))
   * 複習:A.:+(b)的作用是在A後面加上b元素,注意因為immutable,實際上是生成了一個新物件
   */
  params.zip(hiddenLayers.:+(outputLayer))
    .map{f =>
      val w = f._1._1
      val b = f._1._2
      val layer = f._2

      //forward方法需要yPrevious, w, b三個引數val forwardRes = layer.forward(yi, w, b)
      yi = forwardRes.yCurrent

      forwardRes
    }
}

接下來看看計算損失函式值calCost()的具體實現:

private def calCost(res: ResultUtils.ForwardRes, label: DenseVector[Double]):
Double = {
  val yHat = res.yCurrent(::, 0)

  //log函式內加上pow(10.0, -9),防止出現log(0)從而NaN的情況-(label.t * log(yHat + pow(10.0, -9)) + (1.0 - label).t * log(1.0 - yHat + pow(10.0, -9))) / label.length.toDouble
}

剩餘的backward()方法以及updateParams()的程式碼以及其他的NeuralNetworkModel類的完整程式碼如下:

package org.mengpan.deeplearning.model
import java.util

import breeze.linalg.{DenseMatrix, DenseVector}
import breeze.numerics.{log, pow}
import org.apache.log4j.Logger
import org.mengpan.deeplearning.layers.Layer
import org.mengpan.deeplearning.utils.{DebugUtils, LayerUtils, ResultUtils}
import org.mengpan.deeplearning.utils.ResultUtils.{BackwardRes, ForwardRes}

import scala.collection.mutable

/**
  * Created by mengpan on 2017/8/26.
  */
class NeuralNetworkModel extends Model{
  //記錄log
  val logger = Logger.getLogger("NeuralNetworkModel")

  //神經網路的四個超引數override var learningRate: Double = _
  override var iterationTime: Int = _
  var hiddenLayerStructure: Map[Int, Byte] = _
  var outputLayerStructure: (Int, Byte) = _

  //記錄每一次迭代cost變化的歷史資料override val costHistory: mutable.TreeMap[Int, Double] = new mutable.TreeMap[Int, Double]()

  //神經網路模型的引數var paramsList: List[(DenseMatrix[Double], DenseVector[Double])] = _

  //神經網路的隱含層與輸出層的結構,根據hiddenLayerStructureoutputLayerStructure兩個超引數得到private var hiddenLayers: Seq[Layer] = _
  private var outputLayer: Layer = _

  def setHiddenLayerStructure(hiddenLayerStructure: Map[Int, Byte]): this.type = {
    if (hiddenLayerStructure.isEmpty) {
      throw new Exception("hidden layer should be at least one layer!")
    }

    this.hiddenLayerStructure = hiddenLayerStructure
    this.hiddenLayers = getHiddenLayers(this.hiddenLayerStructure)
    this
  }

  def setOutputLayerStructure(outputLayerStructure: (Int, Byte)): this.type = {
    this.outputLayerStructure = outputLayerStructure
    this.outputLayer = getOutputLayer(this.outputLayerStructure)
    this
  }

  override def train(feature: DenseMatrix[Double], label: DenseVector[Double]): NeuralNetworkModel.this.type = {
    val numExamples = feature.rows
    val inputDim = feature.cols

    logger.debug("hidden layers: " + hiddenLayers)
    logger.debug("output layer: " + outputLayer)

    //隨機初始化模型引數var paramsList: List[(DenseMatrix[Double], DenseVector[Double])] =
      initializeParams(numExamples, inputDim, hiddenLayers, outputLayer)

    (0 until this.iterationTime).foreach{i =>
      val forwardResList: List[ForwardRes] = forward(feature, paramsList,
        hiddenLayers, outputLayer)

      logger.debug(forwardResList)

      val cost = calCost(forwardResList.last, label)
      if (i % 100 == 0) {
        logger.info("Cost in " + i + "th time of iteration: " + cost)
      }
      costHistory.put(i, cost)

      val backwardResList: List[BackwardRes] = backward(feature, label, forwardResList,
        paramsList, hiddenLayers, outputLayer)

      logger.debug(backwardResList)

      paramsList = updateParams(paramsList, this.learningRate, backwardResList, i, cost)
    }

    this.paramsList = paramsList
    this
  }

  override def predict(feature: DenseMatrix[Double]): DenseVector[Double] = {
    val forwardResList: List[ForwardRes] = forward(feature, this.paramsList,
      this.hiddenLayers, this.outputLayer)
    forwardResList.last.yCurrent(::, 0).map{yHat =>
      if (yHat > 0.5) 1.0 else 0.0
    }
  }

  private def getHiddenLayers(hiddenLayerStructure: Map[Int, Byte]): Seq[Layer] = {
    hiddenLayerStructure.map{structure =>
      getLayerByStructure(structure)
    }.toList
  }

  private def getOutputLayer(structure: (Int, Byte)): Layer = {
    getLayerByStructure(structure)
  }

  private def getLayerByStructure(structure: (Int, Byte)): Layer = {
    val numHiddenUnits = structure._1
    val activationType = structure._2

    val layer: Layer = LayerUtils.getLayerByActivationType(activationType)
      .setNumHiddenUnits(numHiddenUnits)
    layer
  }

  private def initializeParams(numExamples: Int, inputDim: Int,
                               hiddenLayers: Seq[Layer], outputLayer: Layer):
  List[(DenseMatrix[Double], DenseVector[Double])] = {

    /*
     *把輸入層,隱含層,輸出層的神經元個數組合成一個Vector
     *inputDim=3outputDim=1hiddenDim=(3, 3, 2),則layersDim=(3, 3, 3, 2, 1)
     *兩個List的操作符,A.::(b)為在A前面加上元素BA.:+(B)為在A的後面加上元素B
     *這裡使用Vector儲存layersDim,因為Vectorindexed sequence,訪問任意位置的元素時間相同
    */
    val layersDim = hiddenLayers.map(_.numHiddenUnits)
      .toList
      .::(inputDim)
      .:+(outputLayer.numHiddenUnits)
      .toVector

    val numLayers = layersDim.length

    /*
     *W(l)的維度為(layersDim(l-1), layersDim(l))
     *b(l)的維度為(layersDim(l), )
     *注意隨機初始化的數值在0-1之間,為保證模型穩定性,需在wb後面*0.01
    */
    (1 until numLayers).map{i =>
      val w = DenseMatrix.rand[Double](layersDim(i-1), layersDim(i)) * 0.01
      val b = DenseVector.rand[Double](layersDim(i)) * 0.01
      (w, b)
    }.toList
  }

  private def forward(feature: DenseMatrix[Double],
                      params: List[(DenseMatrix[Double],
                        DenseVector[Double])],
                      hiddenLayers: Seq[Layer],
                      outputLayer: Layer): List[ForwardRes] = {
    var yi = feature

    /*
     *這裡注意Scalazip的用法。假設A=List(1, 2, 3), B=List(3, 4), 
     * A.zip(B)  List((1, 3), (2, 4))
     * 複習:A.:+(b)的作用是在A後面加上b元素,注意因為immutable,實際上是生成了一個新物件
     */
    params.zip(hiddenLayers.:+(outputLayer))
      .map{f =>
        val w = f._1._1
        val b = f._1._2
        val layer = f._2

        //forward方法需要yPrevious, w, b三個引數val forwardRes = layer.forward(yi, w, b)
        yi = forwardRes.yCurrent

        forwardRes
      }
  }

  private def calCost(res: ResultUtils.ForwardRes, label: DenseVector[Double]):
  Double = {
    val yHat = res.yCurrent(::, 0)

    //log函式內加上pow(10.0, -9),防止出現log(0)從而NaN的情況-(label.t * log(yHat + pow(10.0, -9)) + (1.0 - label).t * log(1.0 - yHat + pow(10.0, -9))) / label.length.toDouble
  }


  private def backward(feature: DenseMatrix[Double], label: DenseVector[Double],
                       forwardResList: List[ResultUtils.ForwardRes],
                       paramsList: List[(DenseMatrix[Double], DenseVector[Double])],
                       hiddenLayers: Seq[Layer], outputLayer: Layer):
  List[BackwardRes] = {
    val yHat = forwardResList.last.yCurrent(::, 0)

    //+ pow(10.0, -9)防止出現被除數為0NaN的情況val dYL = -(label /:/ (yHat + pow(10.0, -9)) - (1.0 - label) /:/ (1.0 - yHat + pow(10.0, -9)))
    var dYCurrent = DenseMatrix.zeros[Double](feature.rows, 1)
    dYCurrent(::, 0) := dYL

    paramsList
      .zip(forwardResList)
      .zip(hiddenLayers.:+(outputLayer))
      .reverse
      .map{f =>
        val w = f._1._1._1
        val b = f._1._1._2
        val forwardRes = f._1._2
        val layer = f._2

        logger.debug(DebugUtils.matrixShape(w, "w"))
        logger.debug(layer)

        /*
         *backward方法需要dYCurrent, forwardRes, w, b四個引數
         * 其中,forwardRes中有用的為:yPrevious(計算dW)zCurrent(計算dZCurrent
         */
        val backwardRes = layer.backward(dYCurrent, forwardRes, w, b)
        dYCurrent = backwardRes.dYPrevious
        backwardRes
      }
      .reverse
  }

  private def updateParams(paramsList: List[(DenseMatrix[Double], DenseVector[Double])],
                           learningrate: Double,
                           backwardResList: List[ResultUtils.BackwardRes],
                           iterationTime: Int, cost: Double): List[(DenseMatrix[Double], DenseVector[Double])] = {
    paramsList.zip(backwardResList)
      .map{f =>
        val w = f._1._1
        val 
            
           

相關推薦

跟著深度學習Scala實現神經網路-第二Scala實現神經網路

上一章我們講了如何使用Scala實現LogisticRegression,這一張跟隨著吳恩達的腳步我們用Scala實現基礎的深度神經網路。順便再提一下,吳恩達對於深度神經網路的解釋是我如今聽過的最清楚的課,感嘆一句果然越是大牛知識解釋得越清晰明瞭。 本文分為以下四個部分。

跟著深度學習Scala實現神經網路-第一

1.         Introduction        2017年8月,前百度首席科學家吳恩達先生在twitter上宣佈自己從百度離職後的第一個動作:在Coursera上推出一門從零開始構建神經網路的Deep Learning課程,一時間廣為轟動。       

深度學習》第四門(2)卷積神經網絡實例探究

之一 所有 展示 數據擴充 簡介 設置 假設 通道 開源 2.1為什麽要進行實例探究 (1)就跟學編程一樣,先看看別人怎麽寫的,可以模仿。 (2)在計算機視覺中一個有用的模型,,用在另一個業務中也一般有效,所以可以借鑒。 (3)本周會介紹的一些卷積方面的經典網絡經典的包括:

Coursera深度學習課程 deeplearning.ai (5-3) 序列模型和注意力機制--程式設計作業(二)觸發字檢測

Part 2: 觸發字檢測 關鍵詞語音喚醒 觸發字檢測 歡迎來到這個專業課程的最終程式設計任務! 在本週的視訊中,你瞭解瞭如何將深度學習應用於語音識別。在本作業中,您將構建一個語音資料集並實現觸發字檢測演算法(有時也稱為關鍵字檢測或喚醒檢測)。觸發字

Coursera深度學習課程 deeplearning.ai (5-1) 迴圈序列模型--程式設計作業(一)構建迴圈神經網路

Part 1: 構建神經網路 歡迎來到本週的第一個作業,這個作業我們將利用numpy實現你的第一個迴圈神經網路。 迴圈神經網路(Recurrent Neural Networks: RNN) 因為有”記憶”,所以在自然語言處理(Natural Languag

Coursera深度學習課程 deeplearning.ai (5-2) 自然語言處理與詞嵌入--程式設計作業(一)詞向量運算

Part 1: 詞向量運算 歡迎來到本週第一個作業。 由於詞嵌入的訓練計算量龐大切耗費時間長,絕大部分機器學習人員都會匯入一個預訓練的詞嵌入模型。 你將學到: 載入預訓練單詞向量,使用餘弦測量相似度 使用詞嵌入解決類別問題,比如 “Man is to

Coursera深度學習課程 deeplearning.ai (4-2) 深度卷積網路例項探究--課程筆記

本課主要講解了一些典型的卷積神經網路的思路,包括經典神經網路的leNet/AlexNet/VGG, 以及殘差網路ResNet和Google的Inception網路,順便講解了1x1卷積核的應用,便於我們進行學習和借鑑。 2.1 為什麼要進行例項探究 神經

老師深度學習視訊筆記構建機器學習專案(機器學習策略)(1)

        機器學習策略(machine learning strategy):分析機器學習問題的方法。    正交化(orthogonalization):要讓一個監督機器學習系統很好的工作,一般要確保四件事情,如下圖:        (1)、首先,你通常必須確保至少系

Coursera深度學習課程 deeplearning.ai (5-2) 自然語言處理與詞嵌入--程式設計作業(二)Emojify表情包

Part 2: Emojify 歡迎來到本週的第二個作業,你將利用詞向量構建一個表情包。 你有沒有想過讓你的簡訊更具表現力? emojifier APP將幫助你做到這一點。 所以不是寫下”Congratulations on the promotion! L

深度學習工程師】 04.卷積神經網絡 第三周目標檢測 (1)基本的對象檢測算法

元素 需要 有關 卷積 訓練 特定 步長 來看 選擇 該筆記介紹的是《卷積神經網絡》系列第三周:目標檢測(1)基本的對象檢測算法 主要內容有: 1.目標定位 2.特征點檢測 3.目標檢測 目標定位 使用算法判斷圖片中是不是目標物體,如果是還要再圖片中標出其位置並

深度學習》第一門(1)深度學習引言

數據規模 梯度 神經網絡 以及 應該 精確 構建 關於 http 1.1歡迎 主要講了五門課的內容: 第一門課:神經網絡基礎,構建網絡等; 第二門課:神經網絡的訓練技巧; 第三門課:構建機器學習系統的一些策略,下一步該怎麽走(吳恩達老師新書《Machine Learning

深度學習》第一門(4)深層神經網絡

加網 分享 傳遞 height 經驗 技術分享 image 進行 sig 4.1深層神經網絡 (1)到底是深層還是淺層是一個相對的概念,不必太糾結,以下是一個四層的深度神經網絡: (2)一些符號定義: a[0]=x(輸入層也叫做第0層) L=4:表示網絡的層數 g:表示激

深度學習》第四門(1)卷積神經網絡

圖像分割 1.5 共享 信號處理 soft 沒有 樣本 填充 單元 1.1計算機視覺 (1)計算機視覺的應用包括圖像分類、目標檢測、圖像分割、風格遷移等,下圖展示了風格遷移案例: (2)圖像的特征量非常之大,比如一個3通道的1000*1000的照片,其特征為3*1000*

深度學習》第五門(2)自然語言處理與詞嵌入

星級 技術 ima lac 個數 應該 ras 時有 根據 2.1詞匯表征 (1)使用one-hot方法表示詞匯有兩個主要的缺點,以10000個詞為例,每個單詞需要用10000維來表示,而且只有一個數是零,其他維度都是1,造成表示非常冗余,存儲量大;第二每個單詞表示的向量相

深度學習,周志華,機器學習,西瓜書,TensorFlow,Google,軍,數學之美,李航,統計學習方法,深度學習筆記,pdf下載

1. 機器學習入門經典,李航《統計學習方法》 2. 周志華的《機器學習》pdf 3.《數學之美》吳軍博士著pdf 4. Tensorflow 實戰Google深度學習框架.pdf 5.《TensorFlow實戰》黃文堅 高清完整PDF  6. 復旦大

Coursera深度學習課程 course2-week3 超引數除錯和Batch Norm及框架 作業

                                          &

Coursera深度學習課程 course2-week2 優化方法 作業

                                          &

Coursera深度學習課程 deeplearning.ai (4-1) 卷積神經網路--程式設計作業

Part 1:卷積神經網路 本週課程將利用numpy實現卷積層(CONV) 和 池化層(POOL), 包含前向傳播和可選的反向傳播。 變數說明 上標[l][l] 表示神經網路的第幾層 上標(i)(i) 表示第幾個樣本 上標[i][i] 表示第幾個mi

Coursera深度學習課程 DeepLearning.ai 程式設計作業——Regularization(2-1.2)

如果資料集沒有很大,同時在訓練集上又擬合得很好,但是在測試集的效果卻不是很好,這時候就要使用正則化來使得其擬合能力不會那麼強。 import numpy as np import sklearn import matplotlib.pyplot as plt