「判斷性別」Demo需求分析和初步設計(中)

  • 2022 年 8 月 24 日
  • 筆記

大家好~我開設了「深度學習基礎班」的線上課程,帶領同學從0開始學習全連接和卷積神經網絡,進行數學推導,並且實現可以運行的Demo程序

線上課程資料:
本節課錄像回放
加QQ群,獲得ppt等資料,與群主交流討論:106047770

本系列文章為線上課程的復盤,每上完一節課就會同步發佈對應的文章

本文為第二節課:「判斷性別」Demo需求分析和初步設計(中)的復盤文章

本課程系列文章可進入索引查看:
深度學習基礎課系列文章索引

回顧相關課程內容

  • 第二節課:「判斷性別」Demo需求分析和初步設計(上)
    • 主問題:什麼是神經元?
    • 已知一個人的身高為150厘米,體重為50公斤,如何使用神經元得到該人的性別(應該為女性)?
    • 什麼是訓練?
    • 什麼是推理?

主問題:什麼是神經網絡

  • 已知兩個人的身高和體重,能否使用神經元得到他們的性別(一男一女)?
    能,因為權重、偏移為未知量,總數量為3,小於方程的數量(2),所有有無數解,所以可確定一組解(權重、偏移)

  • 如何修改代碼?
    修改train函數:給出一組權重、偏移,使得結果為分別為0、1;
    激活函數不變

  • 已知四個人的身高和體重,能否使用神經元得到他們的性別?
    不能

  • 為什麼?
    因為權重、偏移為未知量,總數量為3,小於方程的數量(4),所以無解

  • 如何擴展,才能有解?
    使用神經網絡,增加權重、偏移的數量!

  • 請設計一個最簡單的神經網絡?(有幾層?每層有幾個神經元?)
    image

  • 如何根據輸入層的輸入,最終得到輸出層的輸出?
    計算公式如下所示:
    image

  • 現在有幾個未知解?能夠有解了嗎?
    有解

主問題:什麼是前向傳播

  • 「根據輸入層的輸入,最終得到輸出層的輸出?」的過程稱為前向傳播
  • 前向傳播算法包括哪些步驟?
    從輸入層開始,依次傳入每層,得到每層的輸出;
    最後傳到輸出層,得到最後的輸出

任務:用代碼實現神經網絡

  • 請修改神經元代碼,提出神經元的前向傳播forward函數?
    修改後的相關代碼為:
    Neural_forward_answer
let forward = (state: state, sampleData: sampleData): float => {
  sampleData.height *. state.weight1 +.
  sampleData.weight *. state.weight2 +.
  state.bias->_activateFunc
}

let inference = (state: state, sampleData: sampleData): gender => {
  forward(state, sampleData)->_convert
}
  • 請在神經元代碼的基礎上,實現神經網絡的前向傳播和推理(訓練函數不用實現)?
    • 推理函數需要修改嗎?
      不需要
    • 神經網絡代碼如下所示:
      NeuralNetwork_answer
type state = {
  weight13: float,
  weight14: float,
  weight23: float,
  weight24: float,
  weight35: float,
  weight45: float,
  bias3: float,
  bias4: float,
  bias5: float,
}

type sampleData = {
  weight: float,
  height: float,
}

type gender =
  | Male
  | Female
  | InValid

let createState = (): state => {
  weight13: Js.Math.random(),
  weight14: Js.Math.random(),
  weight23: Js.Math.random(),
  weight24: Js.Math.random(),
  weight35: Js.Math.random(),
  weight45: Js.Math.random(),
  bias3: Js.Math.random(),
  bias4: Js.Math.random(),
  bias5: Js.Math.random(),
}

// not implement
let train = (state: state, allSampleData: array<sampleData>): state => {
  state
}

let _activateFunc = x => x

let _convert = x =>
  switch x {
  | 0. => Male
  | 1. => Female
  | _ => InValid
  }

let forward = (state: state, sampleData: sampleData): float => {
  let y3 = Neural_forward_answer.forward(
    (
      {
        weight1: state.weight13,
        weight2: state.weight23,
        bias: state.bias3,
      }: Neural_forward_answer.state
    ),
    sampleData->Obj.magic,
  )

  let y4 = Neural_forward_answer.forward(
    (
      {
        weight1: state.weight14,
        weight2: state.weight24,
        bias: state.bias4,
      }: Neural_forward_answer.state
    ),
    sampleData->Obj.magic,
  )

  Neural_forward_answer.forward(
    (
      {
        weight1: state.weight35,
        weight2: state.weight45,
        bias: state.bias5,
      }: Neural_forward_answer.state
    ),
    (
      {
        weight: y3,
        height: y4,
      }: Neural_forward_answer.sampleData
    ),
  )
}

let inference = (state: state, sampleData: sampleData): gender => {
  Js.log(forward(state, sampleData))

  forward(state, sampleData)->_convert
}

let state = createState()

let allSampleData = [
  {
    weight: 50.,
    height: 150.,
  },
  {
    weight: 51.,
    height: 149.,
  },
  {
    weight: 60.,
    height: 172.,
  },
  {
    weight: 90.,
    height: 188.,
  },
]

let state = state->train(allSampleData)

allSampleData->Js.Array.forEach(sampleData => {
  inference(state, sampleData)->Js.log
}, _)