「ニューラルネットワーク自作入門」Swiftで書く

概要

書籍「ニューラルネットワーク自作入門」をSwiftでコーディング。

「Matrix」は別記事参照。

2.4.8 完成版ニューラルネットワークコード」

書籍

172〜174頁
Python

Swiftコード

import Foundation

class neuralNetwork {
    var inodes:Int
    var hnodes:Int
    var onodes:Int
    var lr:Double
    var wih:Matrix
    var who:Matrix
    
    init(inputnodes:Int, hidedennodes:Int, outputnodes:Int, learningrate:Double) {
        // 入力層、隠れ層、出力層のノード数の設定
        inodes = inputnodes
        hnodes = hidedennodes
        onodes = outputnodes

        // リンクの重み行列 wihとwho
        // 行列内の重み w_i_j,ノードIから次の層のノードjへのリンクの重み
        // w11 w21
        // w12 w22 など
        wih = Matrix.rand(rows: hnodes, colums: inodes) - 0.5
        who = Matrix.rand(rows: onodes, colums: hnodes) - 0.5
        
        // 学習率の設定
        lr = learningrate
    }
    
    // ニューラルネットワークの学習
    func train(inputs_list:[Double], targets_list:[Double]) {
        // 入力リストを行列に変換
        var inputs = Matrix()
        inputs.matrix = [[Double]](repeating: [Double](repeating: 0.0, count: 1), count: inputs_list.count)
        for r in 0..<inputs_list.count - 1{
            inputs.matrix[r][0] = inputs_list[r]
        }
        var targets = Matrix()
        targets.matrix = [[Double]](repeating: [Double](repeating: 0.0, count: 1), count: targets_list.count)
        for r in 0..<targets_list.count - 1{
            targets.matrix[r][0] = targets_list[r]
        }
        
        // 隠れ層に入ってくる信号の計算
        let hidden_inputs = Matrix.dot(left: wih, right: inputs)
        // 隠れ層で結合された信号を活性化関数により出力
        let hidden_outputs = activation_function(input: hidden_inputs)

        // 出力層に入ってくる信号の計算
        let final_inputs = Matrix.dot(left: who, right: hidden_outputs)
        // 出力層で結合された信号を活性化関数により出力
        let final_outputs = activation_function(input: final_inputs)

        // 出力層の誤差 = (目標出力 - 最終出力)
        let output_errors = targets - final_outputs
        // 隠れ層の誤差おは出力層の誤差をリンクの重みの配合で分配
        let hidden_errors = Matrix.dot(left: who, right: output_errors)
        
        // 隠れ層と出力層の間のリンクの重みを更新
        who = who + lr * Matrix.dot(left: (output_errors * final_outputs) * (1.0 - final_outputs), right: Matrix.transpose(input: hidden_outputs))
        
        // 入力層と隠れ層の間のリンクの重みを更新
        wih = wih + lr * Matrix.dot(left: (hidden_errors * hidden_outputs) * (1.0 - hidden_outputs), right: Matrix.transpose(input: inputs))
    }
    
    // ニューラルネットワークへの照会
    func query(inputs_list:[Double]) -> Matrix {
        var inputs = Matrix()
        inputs.matrix = [[Double]](repeating: [Double](repeating: 0.0, count: 1), count: inputs_list.count)
        for r in 0..<inputs_list.count - 1{
            inputs.matrix[r][0] = inputs_list[r]
        }
        // 隠れ層に入ってくる信号の計算
        let hidden_inputs = Matrix.dot(left: wih, right: inputs)
        // 隠れ層で結合された信号を活性化関数により出力
        let hidden_outputs = activation_function(input: hidden_inputs)

        // 出力層に入ってくる信号の計算
        let final_inputs = Matrix.dot(left: who, right: hidden_outputs)
        // 出力層で結合された信号を活性化関数により出力
        let final_outputs = activation_function(input: final_inputs)
        
        return final_outputs
    }
    
    func activation_function(input:Matrix) -> Matrix {
        var result = Matrix()
        result.matrix = [[Double]](repeating: [Double](repeating: 0.0, count: input.matrix[0].count), count: input.matrix.count)
        for r in 0..<input.matrix.count {
            for c in 0..<input.matrix[r].count {
                // シグモイド関数 1 / (1 + exp(-(x)))
                result.matrix[r] = 1 / (1 + exp(-(input.matrix[r])))
            }
        }
        return result
    }
    
}

Swift

Posted by shi-n