4.2 神经网络算法代码实现

时间:2025-03-31 07:23:01

参考前一篇文章“4.1 神经网络算法原理” , 用Python实现了一个版本,不过这个版本有一些坑,懒得去调了,

以后会出一个新的版本,这个版本就这样了吧

python代码

 
import numpy as np


# 双曲正切函数
def tanh(x):
    return (x)


# 双曲正切函数导数
def tanh_derivative(x):
    return 1 - (x) * (x)


# sigmoid函数
def sigmoid(x):
    return 1 / (1 + (-x))


# sigmoid函数导数
def sigmoid_derivative(x):
    return sigmoid(x) * (1 - sigmoid(x))


# 神经网络实现类
class NeuralNetwork():

    # layers:神经网络
    # activation:激励函数
    # learning_rate 学习率
    # loss_threshold:损失阀值
    # epoch:最大训练次数
    def __init__(self, layers=[], activation="sigmoid",
                 learning_rate=0.1, epoch=1000, loss_threshold=0.01):
        if activation == "sigmoid":
             = sigmoid
            self.activation_derivative = sigmoid_derivative
        elif activation == "tanh":
             = tanh
            self.activation_derivative = tanh_derivative
        else:
             = sigmoid
            self.activation_derivative = sigmoid_derivative
         = layers
        self.init_weights(layers)
        self.init_bias(layers)
        self.init_nodes()
        self.init_errors()
        self.learning_rate = learning_rate
         = epoch
        self.loss_threshold = loss_threshold

    # 校验二维数组
    def valiad_two_array(self, data):
        if isinstance(data, list) and len(data) > 0:
            if isinstance(data[0], list) == False or len(data[0]) == 0:
                raise RuntimeError("参数错误,请传一个不为空的二维数组")
        else:
            raise RuntimeError("参数错误,请传一个不为空的二维数组")

    # 校验一维数组
    def valid_one_array(self, data):
        if isinstance(data, list) == False or len(data) == 0:
            raise RuntimeError("参数错误,请传入一个不为空的一维数组")

    # 初始化权重
    def init_weights(self, layers):
         = []
        for i in range(1, len(layers)):
            (((layers[i - 1], layers[i])))

    # 初始化偏向
    def init_bias(self, layers):
         = []
        for i in range(1, len(layers)):
            (((layers[i], 1)))

    # 训练模型
    def fit(self, data):
        self.valiad_two_array(data)
         = 0
        for i in range(len(data)):
            self.training_data(data[i], i)

    # 预测数据
    def predict(self, data):
        self.valiad_two_array(data)
        counter = 0
        for one_data in data:
            self.forward_propagation(one_data)
            predict = [len() - 1]
            for i in range(len(predict)):
                predict[i] = self.handle_by_threshold(predict[i])
            print("predict[{}] = {} ".format(counter, predict))
            counter += 1

    # 根据阀值处理数据
    def handle_by_threshold(self, data):
        if data >= 0.5:
            return 1
        else:
            return 0

    # 一次训练流程
    def training_data(self, one_data, number):
         = 1
        one_training_counter = 0
        while  > self.loss_threshold and one_training_counter < :
             += 1
            one_training_counter += 1
            self.forward_propagation(one_data)
            self.back_propagation_error(one_data)
            self.back_propagation_update_weights()
            self.back_propagation_update_bias()
            # print("总次数{},第{}行数据,当前次数:{},\n{}".
            #       format(, number, one_training_counter, self.get_obj_info()))

    # 获取对象信息
    def get_obj_info(self):
        info = "\n\n weights: " + str() \
               + "\n\n bais: " + str() \
               + "\n\n nodes: " + str() \
               + "\n\n errors: " + str() \
               + "\n\n loss: " + str()
        return info

    # 输出层错误计算
    # out:经过激励函数计算后的结果
    # predict:原始预测的结果
    def calculate_out_layer_error(self, out, predict):
        return out * (1 - out) * (predict - out)

    # 隐藏层错误计算
    # out:经过激励函数计算后的结果
    # errors:下一层所有节点的损失合计
    def calculate_hidden_layer_error(self, out, errors):
        return out * (1 - out) * errors

    # 前向传播,递归得到每一个节点的值
    # one_row_data:一行数据
    # counter: 计数器
    def forward_propagation(self, one_row_data, counter=0):
        if counter == 0:
            input = self.get_input(one_row_data)
             = input
            for i in range(len()):
                [0][i] = [i]
            counter += 1
        if counter == len():
            return
        current_nodes = [counter]
        pre_nodes = [counter - 1]
        for i in range(len(current_nodes)):
            current_value = 0
            for j in range(len(pre_nodes)):
                pre_node = pre_nodes[j]
                pre_weights = [counter - 1][j][i]
                current_value += pre_node * pre_weights
            current_bias = [counter - 1][i][0]
            current_value = (current_value + current_bias)[0]
            current_node = (current_value)
            current_nodes[i] = current_node
        self.forward_propagation(one_row_data, counter + 1)

    # 得到特征值
    def get_input(self, one_row_data):
        return one_row_data[:[0]]

    # 根据特征值真实结果
    def get_out(self, one_row_data):
        return one_row_data[[0]:]

    # 后向传播,得到误差
    def back_propagation_error(self, one_row_data, counter=-1):
        if counter == -1:  # 第一次进入方法,初始化
            counter = len() - 1
            out = self.get_out(one_row_data)
             = out
        if counter == 0:  # 遍历集合(第一层输入层不计算损失)
            return
        current_nodes = [counter]
        if counter == len() - 1:  # 输出层损失计算
            loss = 0
            for i in range(len(current_nodes)):
                current_node = current_nodes[i]
                predict = [i]
                error_value = self.calculate_out_layer_error(current_node, predict)
                [counter][i] = error_value
                loss += pow(predict - current_node, 2)
             = loss
        else:  # 隐藏层损失计算
            next_errors = [counter + 1]
            for i in range(len(current_nodes)):
                current_node = current_nodes[i]
                errors = 0
                for j in range(len(next_errors)):
                    error = next_errors[j]
                    weight = [counter][i]
                    errors += error * weight
                error_value = self.calculate_hidden_layer_error(current_node, errors)
                [counter][i] = error_value
        self.back_propagation_error(one_row_data, counter - 1)

    # 后向传播,更新权重
    def back_propagation_update_weights(self):
        for i in reversed(range(len() - 1)):
            current_nodes = [i]
            errors = [i + 1]
            for j in range(len(current_nodes)):
                for m in range(len(errors)):
                    error = errors[m]
                    current_node = current_nodes[j]
                    weight = [i][j][m]
                    weight_delta = self.learning_rate * error * current_node
                    update_weight = weight + weight_delta
                    [i][j][m] = update_weight

    # 后向传播,更新偏向
    def back_propagation_update_bias(self):
        for i in reversed(range(len() - 1)):
            bias = [i]
            for j in range(len(bias)):
                error = [i + 1][j]
                bias_delta = self.learning_rate * error
                bias[j] += bias_delta

    # 设置权重
    def set_weights(self, weights):
         = weights

    # 设置偏向
    def set_bias(self, bias):
         = bias

    # 初始化所有节点(节点值设置为一个随机数)
    def init_nodes(self):
         = []
        for i in range(len()):
            ((([i], 1)))

    # 初始化所有节点损失值(损失值设置为一个随机数)
    def init_errors(self):
         = []
        for i in range(len()):
            ((([i], 1)))

 

验证写的代码

 
from NeraulNetwork import NeuralNetwork
import numpy as np

layers = [3, 2, 1]
nn = NeuralNetwork(layers)

weights = ([[[0.2, -0.3], [0.4, 0.1], [-0.5, 0.2]], [[-0.3], [-0.2]]])
nn.set_weights(weights)

bias = ([[[-0.4], [0.2]], [[0.1]]])
nn.set_bias(bias)

data = [
    [1, 0, 1, 1],
    [0, 0, 1, 0],
    [0, 0, 0, 0],
    [0, 0, 1, 0],
    [1, 0, 1, 1],
    [0, 0, 0, 0],
    [0, 0, 1, 0],
    [1, 0, 1, 1],
    [0, 0, 0, 0],
    [1, 0, 1, 1],
    [0, 0, 1, 0],
    [0, 0, 0, 0],
    [1, 0, 1, 1],
    [0, 0, 0, 0],
    [1, 0, 1, 1],
    [0, 0, 0, 0],
    [1, 0, 1, 1],
    [0, 0, 1, 0],
    [0, 0, 0, 0],
    [1, 0, 1, 1],
    [0, 0, 1, 0],
    [0, 0, 0, 0],
]
(data)

predict_data = [[1, 0, 1, 1], [0, 0, 0, 0],[0, 0, 1, 0],[1, 1, 1, 1]]
predict_result = (predict_data)

 

输出结果

predict[0] = [[1.]] 
predict[1] = [[0.]] 
predict[2] = [[0.]] 
predict[3] = [[1.]]