手写BP神经网络

现在的深度学习模型能够借助一些功能十分强大的集成框架(tensorflow,pytorch,keras,caffe)很轻松的实现。但自己动手写一个BP神经网络,亲手实现网络的前向传播,计算损失,链式法则逐层求导,更新模型参数还是很有意义的,对网络训练也会有更加深刻的理解。同时,为了让初学者能够轻松的理解代码的含义,我为每一行代码都加了详细的注解。PS:转载请注明本文链接。

1.数据集下载地址

Forest type mapping Data Set

2.相关资源

我的另一篇博文是利用朴素贝叶斯实现相同任务,感兴趣的同学可以去看看。

3.代码运行结果

先放一个代码运行完的曲线图,证明这个代码是可以运行的


在这里插入图片描述

4.实现代码

# 导入程序依赖包
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import time
from sklearn.decomposition import PCA
from mpl_toolkits.mplot3d import Axes3D


def relu(Z):
    """
    功能:
        relu激活函数,网络前向传播的非线性计算部分,在网络中的前L-1层使用
    输入参数:
        Z - 线性运算后的值
    返回值:
        A - 神经元激活值
        cache - 激活函数数据缓存区,为反向传播提供数据
    """
    A = np.maximum(0, Z)  # 将Z中所有负数置0
    cache = Z  # 将Z存入缓存区
    return A, cache


def relu_backward(dA, cache):
    """
    功能:
        relu激活函数值的反向传播
    输入参数:
        dA - 神经元激活值的导数
        cache - 数据缓存区,为反向传播提供数据
    返回值:
        dZ - 线性运算部分的导数,用来更新神经元权重和偏置
    """
    Z = cache  # 从缓存区中取出Z
    dZ = np.array(dA, copy=True)  # 将dA进行复制,并转换为array赋值给dZ
    dZ[Z <= 0] = 0  # 将dZ中负数部分置0
    return dZ


def softmax(Z):
    """
    功能:
        softmax激活函数,网络前向传播的非线性计算部分,在网络中的第L层,也就是最后一层使用,实现多分类任务
    输入参数:
        Z - 线性运算后的值
    返回值:
        A - 神经元激活值
        cache - 激活函数数据缓存区,为反向传播提供数据
    """
    A = np.exp(Z) / (np.sum(np.exp(Z), axis=0))  # 计算激活值
    cache = Z  # 将Z存入缓存区
    return A, cache


def load_datasets(filepath):
    """
    功能:
        导入数据,并将标签集进行one-hot编码
    输入参数:
        filepath - 数据文件路径
    返回值:
        feature - 特征集,一个n*m矩阵,n为特征维度,m为样本数
        label - 标签集,一个4*m的one-hot矩阵,4为标签维度,m为样本数
    """
    dataset = pd.read_csv(filepath)  # 读取csv文件,数据类型为DataFrame
    dataset['class'] = dataset['class'].map({"s ": 0, "h ": 1, "d ": 2, "o ": 3})  # 将字符转换为数值,注意字符后面的空格不能去掉,这是一个坑
    label = dataset.loc[:, ['class']]  # 读取标签,数据类型为DataFrame
    label = np.array(label)  # 转换为array
    label = np.eye(4).reshape(dataset.shape[0], 4).T  # 将array转换为one-hot
    feature = dataset.iloc[:, 1:dataset.shape[1]]  # 将特征数据分割出来
    feature = np.array(feature).T  # 转换为array
    return feature, label


def decoding(labels_one_hot):
    """
    功能:
        进行one_hot解码,将one_hot矩阵还原为原始标签
    输入参数:
        labels_one_hot - 标签集,一个m*4的one-hot矩阵,m为样本数,4为标签维度
    返回值:
        label - 标签集,一个m*1的数据帧,m为样本数,元素为字符类别
    """
    labels = labels_one_hot.argmax(axis=1).reshape(labels_one_hot.shape[0], -1)  # 按行提取矩阵中最大的元素的索引
    labels = pd.DataFrame(labels)  # 将array转换为dataframe
    labels.columns = ['class']  # 设置帧头
    labels['class'] = labels['class'].map({0: "s ", 1: "h ", 2: "d ", 3: "o "})  # 将数字类别还原为原始的字符类别
    return labels


def random_dataset(train_x, train_y, test_x, test_y, seed):
    """
    功能:
        打乱训练集和测试集数据,使数据同分布
    输入参数:
        train_x - 训练特征集,一个n*m1矩阵,n为特征维度,m1为训练样本数
        train_y - 训练标签集,一个4*m1的one-hot矩阵,4为标签维度,m1为训练样本数
        test_x - 测试特征集,一个n*m2矩阵,n为特征维度,m2为测试样本数
        test_y - 测试标签集,一个4*m2的one-hot矩阵,4为标签维度,m2为测试样本数
        seed - 程序随机种子
    返回值:
        new_train_x.T - 打乱后的训练特征集,一个n*m1矩阵,n为特征维度,m1为训练样本数
        new_train_y.T - 打乱后的训练标签集,一个4*m1的one-hot矩阵,4为标签维度,m1为训练样本数
        new_test_x.T - 打乱后的测试特征集,一个n*m2矩阵,n为特征维度,m2为测试样本数
        new_test_y.T - 打乱后的测试标签集,一个4*m2的one-hot矩阵,4为标签维度,m2为测试样本数
    """
    if seed > 0:
        np.random.seed(seed)  # 随机种子大于0,就打乱数据集
        m = train_x.shape[1]  # 训练样本数
        new_x = np.concatenate((train_x.T, test_x.T), axis=0)  # 将特征集进行拼接
        new_y = np.concatenate((train_y.T, test_y.T), axis=0)  # 将标签集进行拼接
        per = np.random.permutation(new_x.shape[0])  # 打乱特征集行号
        new_x = new_x[per, :]  # 获取打乱后的特征数据
        new_y = new_y[per, :]  # 获取打乱后的标签数据
        new_train_x, new_test_x = np.vsplit(new_x, [m])  # 按原训练样本数进行分割
        new_train_y, new_test_y = np.vsplit(new_y, [m])  # 按原训练样本数进行分割
    else:
        new_train_x, new_train_y, new_test_x, new_test_y = train_x, train_y, test_x, test_y  # 随机种子小于零就不打乱数据集
    return new_train_x.T, new_train_y.T, new_test_x.T, new_test_y.T


def data_preprocessing(features):
    """
    功能:
        进行特征集预处理,对特征集进行归一化,返回均值和方差
    输入参数:
        features - 特征集,一个n*m的矩阵,n为特征维度,m为样本数
    返回值:
        features - 经过归一化的特征集,一个n*m的矩阵,n为特征维度,m为样本数
        mu - 特征集均值
        sigma2 - 特征集方差
    """
    mu = np.mean(features, axis=1).reshape(features.shape[0], -1)  # 计算特征集均值
    features -= mu  # 对特征集进行零均值
    sigma2 = np.var(features, axis=1).reshape(features.shape[0], -1)  # 计算特征集方差
    features /= sigma2  # 对特征集方差进行归一化
    return features, mu, sigma2


def initialize_parameters(layers_dims, seed):
    """
    功能:
        按照输入的神经网络结构进行权值抑梯度异常初始化,偏置零初始化
    输入参数:
        layers_dims - 列表,表示神经网络的结构
        seed - 随机种子
    返回值:
        parameters - 参数字典,包含进行初始化后的权值和偏置
    """
    seed = max(seed, 1)  # 随机种子要大于0
    np.random.seed(seed)  # 为了实验能够复现,固定随机种子
    parameters_init = {}  # 初始化参数字典
    L = len(layers_dims)  # 网络层数
    for l in range(1, L):
        parameters_init["W" + str(l)] = np.random.randn(layers_dims[l], layers_dims[l - 1]) / np.sqrt(
            layers_dims[l - 1])  # 对网络权重进行抑梯度异常初始化
        parameters_init["b" + str(l)] = np.zeros((layers_dims[l], 1))  # 对网络偏置进行零初始化
    return parameters_init


def linear_forward(A, W, b):
    """
    功能:
        网络前向传播的线性计算部分
    输入参数:
        A - 上一层神经元的激活值
        W - 本层神经元的权重
        b - 本层神经元的偏置
    返回值:
        Z - 线性运算后的值
        cache - 单层神经网络前向传播线性部分数据缓存区,元组,包含输入参数的值,在该部分的反向传播会用到
    """
    Z = np.dot(W, A) + b  # 进行矩阵乘法
    cache = (A, W, b)  # 将输入参数存入缓冲区
    return Z, cache


def linear_activation_forward(A_prev, W, b):
    """
    功能:
        单层网络的前向传播
    输入参数:
        A_prev - 上一层神经元的激活值
        W - 本层神经元的权重
        b - 本层神经元的偏置
    返回值:
        A - 本层神经元的激活值
        cache - 单层神经网络前向传播数据缓存区,元组,包含线性部分和激活函数部分的数据
    """
    Z, linear_cache = linear_forward(A_prev, W, b)  # 本层神经元的线性运算
    A, activation_cache = relu(Z)  # 本层神经元的激活函数运算
    cache = (linear_cache, activation_cache)  # 将本层的相关参数存入缓存区
    return A, cache


def model_forward(X, parameters, keep_prob):
    """
    功能:
        实现神经网络的前向传播
    输入参数:
        X - 样本
        parameters - 神经网络的参数
        keep_prob - dropout正则化的阈值
    返回值:
        AL - 神经网络对样本的类别预测概率
        caches - 前向传播数据缓存区,元组,包含前向传播的所有中间参数,会在反向传播用到
    """
    caches = []  # 开辟数据缓存区
    # np.random.seed()  # 取消随机种子效果,实现dropout,其实也可以注释掉,同样有正则化的效果,并且结果能够复现
    L = len(parameters) // 2  # 计算神经网络层数
    # 神经网络第一层,输入层的激活值为输入样本
    A = X
    # 神经网络的隐藏层[1,L-1]为Liner + relu
    for l in range(1, L):
        A_prev = A  # 本层的输入值为上一层的激活值
        A, cache = linear_activation_forward(A_prev, parameters['W' + str(l)], parameters['b' + str(l)])  # 计算一层网络的前向传播
        # dropout正则化,防止网络过拟合
        D = np.random.rand(A.shape[0], A.shape[1])  # 按照激活值的大小随机初始化矩阵dropout矩阵D
        D = D < keep_prob  # 使​​用keep_prob作为阈值,将D矩阵中大于keep_prob的元素值置0
        A = A * D  # 舍弃A的一些节点(D中为0的节点将被舍弃)
        A = A / keep_prob  # 缩放未舍弃的节点(不为0)的值
        D_cache = (D, cache)  # 保存dropout矩阵D
        caches.append(D_cache)  # 将dropout矩阵D和每一层的数据缓存区存入前向缓存区
    # 神经网络的输出层为Liner + softmax
    Z, linear_cache = linear_forward(A, parameters['W' + str(L)], parameters['b' + str(L)])  # 输出层的线性计算
    AL, activation_cache = softmax(Z)  # 输出层的softmax激活函数计算
    cache = (linear_cache, activation_cache)  # 保存输出层的中间参数
    caches.append(cache)  # 将输出层的中间参数存入前向缓存区
    return AL, caches


def compute_cost(AL, Y):
    """
    功能:
        计算网络交叉熵损失值
    输入参数:
        AL - 神经网络对样本的类别预测概率
        Y - 样本的真实标签,一个4*m的one_hot矩阵
    返回值:
        cost - 交叉熵损失值
    """
    m = Y.shape[1]  # 样本数
    cost = -np.sum(np.multiply(np.log(AL), Y)) / m  # 计算交叉熵
    cost = np.squeeze(cost)  # 数据降维,将array变为标量
    return cost


def linear_backward(dZ, cache):
    """
    功能:
        网络线性运算的反向传播
    输入参数:
        dZ - 本层网络激活函数反向传播的输出
        cache - 线性缓存区,存有前向传播的相关数据
    返回值:
        dA_prev - 上一层网络激活函数的输入
        dW - 本层网络权值的梯度
        db - 本层网络偏置的梯度
    """
    A_prev, W, b = cache  # 从缓存区中取得数据
    m = A_prev.shape[1]  # 上一层网络的神经元个数
    dW = np.dot(dZ, A_prev.T) / m  # 计算权值梯度
    db = np.sum(dZ, axis=1, keepdims=True) / m  # 计算偏置梯度
    dA_prev = np.dot(W.T, dZ)  # 计算反向传播时上一层网络激活函数的输入
    return dA_prev, dW, db


def linear_activation_backward(dA, cache):
    """
    功能:
        网络单层反向传播
    输入参数:
        dA - 本层网络激活函数反向传播的输入
        cache - 线性缓存区,存有前向传播的相关数据
    返回值:
        dA_prev - 上一层网络激活函数的输入
        dW - 本层网络权值的梯度
        db - 本层网络偏置的梯度
    """
    linear_cache, activation_cache = cache  # 取得相关数据
    dZ = relu_backward(dA, activation_cache)  # 激活函数反向传播
    dA_prev, dW, db = linear_backward(dZ, linear_cache)  # 线性部分反向传播
    return dA_prev, dW, db


def model_backward(AL, Y, caches, keep_prob):
    """
    功能:
        神经网络模型的反向传播
    输入参数:
        AL - 神经网络对样本的类别预测概率矩阵
        Y - 样本的真实标签,一个4*m的one_hot矩阵
        caches - 前向传播数据缓存区
        keep_prob - dropout正则化的阈值
    返回值:
        grads - 用于更新权值和偏置的梯度
    """
    grads = {}  # 初始化梯度字典
    L = len(caches)  # 计算网络层数
    Y = Y.reshape(AL.shape)  # 匹配预测矩阵和真实标签的维度
    # 输出层linear + softmax的反向传播
    current_cache = caches[L - 1]  # 取得输出层缓冲区
    linear_cache, activation_cache = current_cache  # 取得输出层的前向数据
    dZ = AL - Y  # 损失函数对softmax输入的导数
    A_prev, W, b = linear_cache  # 取得输出层的前向数据
    m = A_prev.shape[1]  # 前一层神经元个数
    dW = np.dot(dZ, A_prev.T) / m  # 输出层的权重梯度
    db = np.sum(dZ, axis=1, keepdims=True) / m  # 输出层的偏置梯度
    dA_prev = np.dot(W.T, dZ)  # 计算前一层的网络激活函数的输入
    grads["dA" + str(L)], grads["dW" + str(L)], grads["db" + str(L)] = dA_prev, dW, db  # 将梯度存入字典
    # 隐藏层到输入层[L-1,0]linear + relu的反向传播
    for l in reversed(range(L - 1)):
        D, current_cache = caches[l]  # 取出数据
        grades = grads["dA" + str(l + 2)]  # 传递输出层的梯度
        # dropout正则化的反向传播
        grades = grades * D  # 使用正向传播期间相同的节点,舍弃那些关闭的节点
        grades = grades / keep_prob  # 缩放未舍弃的节点(不为0)的值
        dA_prev_temp, dW_temp, db_temp = linear_activation_backward(grades, current_cache)  # 当前层的反向传播
        grads["dA" + str(l + 1)] = dA_prev_temp  # 存入当前层的激活值梯度
        grads["dW" + str(l + 1)] = dW_temp  # 存入当前层的权值梯度
        grads["db" + str(l + 1)] = db_temp  # 存入当前层的偏置梯度
    return grads


def update_parameters(parameters, grads, learning_rate):
    """
    功能:
        更新神经网络模型的参数
    输入参数:
        parameters - 神经网络模型的参数
        grads - 参数梯度字典
        learning_rate - 学习率
    返回值:
        parameters - 更新后的参数
    """
    L = len(parameters) // 2  # 神经网络层数
    for l in range(L):
        parameters["W" + str(l + 1)] = parameters["W" + str(l + 1)] - learning_rate * grads["dW" + str(l + 1)]  # 更新权值
        parameters["b" + str(l + 1)] = parameters["b" + str(l + 1)] - learning_rate * grads["db" + str(l + 1)]  # 更新偏置
    return parameters


def predict(X, Y, parameters):
    """
    功能:
        预测输入样本的种类,并根据真实标签计算准确率
    输入参数:
        X - 输入样本,n*m矩阵,n为特征维度,m为样本数
        Y - 真实标签,4*m的one-hot矩阵,4为标签种类数,m为样本数
        parameters - 神经网络模型的参数
    返回值:
        acc - 预测准确率,标量
        Y_pre - 输入样本的预测种类,4*m矩阵
    """
    L = len(parameters) // 2  # 神经网络层数
    A = X  # 输入层的激活值
    # 隐藏层的前向传播[1,L-1],linear + relu
    for l in range(1, L):
        A_prev = A  # 本层神经元的激活值为下一层神经元的输入
        A, cache = linear_activation_forward(A_prev, parameters['W' + str(l)], parameters['b' + str(l)])  # 本层神经元的前向传播
    # 输出层的前向传播,linear + softmax
    Z, linear_cache = linear_forward(A, parameters['W' + str(L)], parameters['b' + str(L)])  # 输出层的前向传播线性部分
    Y_pre, caches = softmax(Z)  # softmax激活函数
    Y_pre = list(map(lambda x: x == max(x), Y_pre.T)) * np.ones(shape=Y_pre.T.shape)  # 将预测矩阵转换为one-hot,m*4矩阵
    Y_pre = Y_pre.T  # 将预测矩阵转置为4*m矩阵
    acc = np.sum(Y * Y_pre) / Y.shape[1]  # 计算预测准确率
    return acc, Y_pre.T


def model(train_features, train_labels, test_features, test_labels, layers_dims, seed, learning_rate,
          num_iterations, keep_prob, print_cost_acc, is_plot):
    """
    功能:
        神经网络模型的搭建和训练
    输入参数:
        train_features - 训练样本的特征,n1*m1矩阵,n1为特征维度,m1为样本数
        train_labels - 训练样本的真实标签,4*m1的one-hot矩阵,4为标签种类数,m1为样本数
        test_features - 测试样本的特征,n2*m2矩阵,n2为特征维度,m2为样本数
        test_labels - 测试样本的真实标签,4*m2的one-hot矩阵,4为标签种类数,m2为样本数
        layers - 网络结构
        seed - 随机种子
        learning_rate - 学习率
        num_iterations - 迭代次数
        keep_prob - dropout正则化阈值
        print_cost_acc - 是否打印损失和准确率
        is_plot - 是否绘图
    返回值:
        parameters - 神经网络模型训练好的参数
    """
    iters = []  # 记录迭代次数
    costs = []  # 记录交叉熵损失值
    acc_trainings = []  # 记录训练集准确率
    acc_testings = []  # 记录测试集准确率
    parameters = initialize_parameters(layers_dims, seed)  # 抑梯度异常随机初始化
    for i in range(0, num_iterations):
        AL, caches = model_forward(train_features, parameters, keep_prob)  # 前向传播
        cost = compute_cost(AL, train_labels)  # 计算交叉熵损失
        grads = model_backward(AL, train_labels, caches, keep_prob)  # 误差反向传播
        parameters = update_parameters(parameters, grads, learning_rate)  # 更新参数
        # 打印成本值,如果print_cost_acc=False则忽略
        if i % 100 == 0:
            # 记录数值
            iters.append(i)  # 记录迭代次数
            costs.append(cost)  # 记录损失值
            acc_training, label_pre = predict(train_features, train_labels, parameters)  # 训练集预测
            acc_testing, label_pre = predict(test_features, test_labels, parameters)  # 测试集预测
            acc_trainings.append(acc_training)  # 记录训练集准确率
            acc_testings.append(acc_testing)  # 记录测试集准确率
            # 是否打印训练过程中的值
            if print_cost_acc:
                print("第", i, "次迭代,成本值为:", np.squeeze(cost), "训练集准确率为:", np.squeeze(acc_training), "测试集准确率为:",
                      np.squeeze(acc_testing))
    # 迭代完成,绘图,is_plot=False则忽略
    if is_plot:
        plt.plot(np.squeeze(costs), color='black', label='cost', linewidth=0.8)
        plt.plot(np.squeeze(acc_trainings), color='blue', label='acc_training', linewidth=0.8)
        plt.plot(np.squeeze(acc_testings), color='red', label='acc_testing', linewidth=0.8)
        plt.legend(loc='upper right')
        plt.xlabel('iterations (per hundred)')
        plt.title("layers:" + str(layers) + "  Seed:" + str(seed) + "  Lr:" + str(learning_rate) + "  Iters:" + str(
            num_iterations) + "  Kp:" + str(keep_prob))
        plt.show()
    return parameters


def PCA_plot(feature, label, dimensionality=3):
    """
    功能:
        将输入的数据经过PCA降为二维后,画出种类散点图,方便进行数据分析
    输入参数:
        feature - 特征,一个n*m矩阵,n为特征维度,m为样本数
        label - 标签,一个4*m的one-hot矩阵,4为标签维度,m为样本数
    返回值:
        无
    """
    # PCA降维
    pca = PCA(n_components=dimensionality)  # 设置维度
    feature_reduction = pca.fit_transform(feature.T)  # 特征数据降维
    # print(pca.explained_variance_ratio_)#打印所保留的各个特征的方差百分比,二维可以保留87%信息,三维可以保存91%信息
    label = label.T  # 将标签转置为m*4的矩阵
    label = label.argmax(axis=1).reshape(label.shape[0], -1)  # 取出每一行中最大元素的索引
    # 画二维图
    if dimensionality == 2:
        # 将特征和标签按列进行拼接
        data = np.concatenate((label, np.zeros((label.shape[0], label.shape[1]))), axis=1)  # 为了能够拼接矩阵想要填充0数据
        data = np.concatenate((feature_reduction, data), axis=1)  # 按列将特征和标签进行拼接
        # 将矩阵转化为dataframe,并画图
        data = pd.DataFrame(data)  # 将矩阵转化为dataframe
        data.columns = ['x', 'y', 'class', 'fill']  # 帧头
        colors = ['b', 'g', 'r', 'orange']  # 颜色
        markers = ['v', 's', '*', 'o']  # 图标
        labels = ['s', 'h', 'd', 'o']  # 图标签
        for i in range(4):
            # 根据类别区分样本坐标
            x = data.loc[data['class'] == i]['x']
            y = data.loc[data['class'] == i]['y']
            plt.scatter(x, y, c=colors[i], marker=markers[i], label=labels[i], cmap='brg', alpha=0.8, linewidth=0.2)
        plt.legend(loc='upper right')  # 将图标签设置在右上角
        plt.show()  # 显示图形
    # 画三维图
    elif dimensionality == 3:
        # 将特征和标签按列进行拼接
        data = np.concatenate((label, np.zeros((label.shape[0], label.shape[1] + 1))), axis=1)  # 为了能够拼接矩阵想要填充0数据
        data = np.concatenate((feature_reduction, data), axis=1)  # 按列将特征和标签进行拼接
        # 将矩阵转化为dataframe,并画图
        data = pd.DataFrame(data)  # 将矩阵转化为dataframe
        data.columns = ['x', 'y', 'z', 'class', 'fill1', 'fill2']  # 帧头
        colors = ['b', 'g', 'r', 'orange']  # 颜色
        markers = ['v', 's', '*', 'o']  # 图标
        labels = ['s', 'h', 'd', 'o']  # 图标签
        ax = plt.axes(projection='3d')  # 三维图
        for i in range(4):
            # 根据类别区分样本坐标
            x = data.loc[data['class'] == i]['x']
            y = data.loc[data['class'] == i]['y']
            z = data.loc[data['class'] == i]['z']
            ax.scatter3D(x, y, z, c=colors[i], marker=markers[i], label=labels[i], cmap='brg', alpha=0.8, linewidth=0.2)
        plt.legend(loc='upper right')  # 将图标签设置在右上角
        plt.show()  # 显示图形
    else:
        print("不符合要求的维度!")


if __name__ == '__main__':
    start = time.time()  # 记录当前时间
    seed = 3  # 程序随机种子
    # 训练文件和测试文件路径
    TrainingFilePath = 'training.csv'
    TestingFilePath = 'testing.csv'
    # 加载训练数据和测试数据
    train_x, train_y = load_datasets(TrainingFilePath)
    test_x, test_y = load_datasets(TestingFilePath)
    # 使训练集和测试集同分布
    train_x, train_y, test_x, test_y = random_dataset(train_x, train_y, test_x, test_y, seed)
    # PCA_plot(train_x, train_y,dimensionality = 3)#原始训练集绘图
    # PCA_plot(test_x, test_y,dimensionality = 3)#原始测试集绘图
    # train_x_copy = copy.deepcopy(train_x)# 保存原始训练集特征
    # test_x_copy = copy.deepcopy(test_x)# 保存原始测试集特征
    # 对训练数据进行预处理,进行归一化
    train_x, mu, sigma2 = data_preprocessing(train_x)
    # 对测试数据用相同均值和方差进行归一化
    test_x = (test_x - mu) / sigma2
    # PCA_plot(train_x, train_y,dimensionality = 3)#归一化训练集绘图
    # PCA_plot(test_x, test_y,dimensionality = 3)#归一化测试集绘图
    # 设置神经网络结构
    layers = [27, 21, 15, 9, 4]
    # 搭建神经网络,利用训练数据进行训练,在训练过程中利用测试数据进行模型评估
    parameters = model(train_x, train_y, test_x, test_y, layers, seed=seed, learning_rate=0.02, num_iterations=40000,
                       keep_prob=0.8, print_cost_acc=False, is_plot=True)
    # 对训练集进行预测,返回测试集准确率和预测类别
    print("**************************训练集评估**************************")
    acc_training, train_label_pre = predict(train_x, train_y, parameters)
    # PCA_plot(train_x_copy, train_label_pre.T,dimensionality = 3)#训练集预测效果
    print("训练集准确率为" + str(acc_training))
    # print("训练数据预测类别:\n" + str(decoding(train_label_pre)))
    # 对测试集进行预测,返回测试集准确率和预测类别
    print("**************************测试集评估**************************")
    acc_testing, test_label_pre = predict(test_x, test_y, parameters)
    # PCA_plot(test_x_copy, test_label_pre.T,dimensionality = 3)#测试集预测效果
    print("测试集准确率为" + str(acc_testing))
    # print("测试数据预测类别:\n" + str(decoding(test_label_pre)))
    print("***************************总体评估***************************")
    acc_average = acc_testing * test_x.shape[1] / (test_x.shape[1] + train_x.shape[1]) \
                  + acc_training * train_x.shape[1] / (test_x.shape[1] + train_x.shape[1])  # 计算平均准确率
    print("平均准确率为" + str(acc_average))
    print("程序运行时间为:" + str(time.time() - start))
暂无评论

发送评论 编辑评论


|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
下一篇