Python实现二层BP神经网络

前 言

        随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。主要是利用BP神经网络来实现数据的二分类。


提示:以下是本篇文章正文内容,下面案例可供参考

一、BP神经网络的推导

二、使用步骤

 导入数据集:训练集x_train、y_train和测试集x_test、y_test。进行训练并输出结果。

三、完整代码

import numpy as np
import pandas as pd
import scipy.io as sio
import matplotlib.pyplot as plt

def load_dataset():
    # 读取.mat文件
    x_train = u'x_train.mat'
    x_train = sio.loadmat(x_train)
    x_test = u'x_test.mat'
    x_test = sio.loadmat(x_test)
    y_train = u'y_train.mat'
    y_train = sio.loadmat(y_train)
    y_test = u'y_test.mat'
    y_test = sio.loadmat(y_test)

    # 拆分训练数据与测试数据
    x_train = x_train['x_train']
    y_train = y_train['y_train']
    x_test = x_test['x_test']
    y_test = y_test['y_test']

    # 将训练和测试数据分别用表格的形式查看
    print("训练集:", pd.concat([pd.DataFrame(x_train), pd.DataFrame(y_train)], axis=1))
    print("测试集:", pd.concat([pd.DataFrame(x_test), pd.DataFrame(y_test)], axis=1))

    return x_train, y_train, x_test, y_test

def sigmoid(x):
    # Sigmoid activation function: f(x) = 1 / (1 + e^(-x))
    return 1 / (1 + np.exp(-x))

def deriv_sigmoid(x):
    # Derivative of sigmoid: f'(x) = f(x) * (1 - f(x))
    fx = sigmoid(x)
    return fx * (1 - fx)

def mse_loss(y_true, y_pred):
    # MSE:平均方差损失(即为所有方差((y_true - y_pred)^2) 的平均值)
    # y_true and y_pred are numpy arrays of the same length.
    return ((y_true - y_pred) ** 2).mean()

class OurNeuralNetwork:
    '''
    A neural network with:
    - 2 inputs
    - a hidden layer with 2 neurons (h1, h2)
    - an output layer with 1 neuron (o1)

    '''
    def __init__(self):
        # 权重,Weights
        self.w1 = np.random.normal()
        self.w2 = np.random.normal()
        self.w3 = np.random.normal()
        self.w4 = np.random.normal()
        self.w5 = np.random.normal()
        self.w6 = np.random.normal()

        # 截距项,Biases
        self.b1 = np.random.normal()
        self.b2 = np.random.normal()
        self.b3 = np.random.normal()

    def feedforward(self, x):
        # x is a numpy array with 2 elements.
        h1 = sigmoid(self.w1 * x[0] + self.w2 * x[1] + self.b1)
        h2 = sigmoid(self.w3 * x[0] + self.w4 * x[1] + self.b2)
        o1 = sigmoid(self.w5 * h1 + self.w6 * h2 + self.b3)
        return o1

    def train(self, data, all_y_trues):
        '''
        - data is a (n x 2) numpy array, n = # of samples in the dataset.
        - all_y_trues is a numpy array with n elements.
        Elements in all_y_trues correspond to those in data.
        '''
        learn_rate = 0.1
        epochs = 1000                   # number of times to loop through the entire dataset
        list_epoch = []
        list_loss = []
        w1 = []
        w2 = []
        w3 = []
        w4 = []
        w5 = []
        w6 = []
        b1 = []
        b2 = []
        b3 = []
        for epoch in range(epochs):
            for x, y_true in zip(data, all_y_trues):
                # Do a feedforward (we'll need these values later)
                sum_h1 = self.w1 * x[0] + self.w2 * x[1] + self.b1
                h1 = sigmoid(sum_h1)

                sum_h2 = self.w3 * x[0] + self.w4 * x[1] + self.b2
                h2 = sigmoid(sum_h2)

                sum_o1 = self.w5 * h1 + self.w6 * h2 + self.b3
                o1 = sigmoid(sum_o1)
                y_pred = o1

                # --- Calculate partial derivatives.
                # --- Naming: d_L_d_w1 represents "partial L / partial w1"
                d_L_d_ypred = -2 * (y_true - y_pred)

                # Neuron o1
                d_ypred_d_w5 = h1 * deriv_sigmoid(sum_o1)
                d_ypred_d_w6 = h2 * deriv_sigmoid(sum_o1)
                d_ypred_d_b3 = deriv_sigmoid(sum_o1)

                d_ypred_d_h1 = self.w5 * deriv_sigmoid(sum_o1)
                d_ypred_d_h2 = self.w6 * deriv_sigmoid(sum_o1)

                # Neuron h1
                d_h1_d_w1 = x[0] * deriv_sigmoid(sum_h1)
                d_h1_d_w2 = x[1] * deriv_sigmoid(sum_h1)
                d_h1_d_b1 = deriv_sigmoid(sum_h1)

                # Neuron h2
                d_h2_d_w3 = x[0] * deriv_sigmoid(sum_h2)
                d_h2_d_w4 = x[1] * deriv_sigmoid(sum_h2)
                d_h2_d_b2 = deriv_sigmoid(sum_h2)

                # --- Update weights and biases
                # Neuron h1
                w1.append(self.w1)
                w2.append(self.w2)
                b1.append(self.b1)
                self.w1 -= learn_rate * d_L_d_ypred * d_ypred_d_h1 * d_h1_d_w1
                self.w2 -= learn_rate * d_L_d_ypred * d_ypred_d_h1 * d_h1_d_w2
                self.b1 -= learn_rate * d_L_d_ypred * d_ypred_d_h1 * d_h1_d_b1

                # Neuron h2
                w3.append(self.w3)
                w4.append(self.w4)
                b2.append(self.b2)
                self.w3 -= learn_rate * d_L_d_ypred * d_ypred_d_h2 * d_h2_d_w3
                self.w4 -= learn_rate * d_L_d_ypred * d_ypred_d_h2 * d_h2_d_w4
                self.b2 -= learn_rate * d_L_d_ypred * d_ypred_d_h2 * d_h2_d_b2

                # Neuron o1
                w5.append(self.w5)
                w6.append(self.w6)
                b3.append(self.b3)
                self.w5 -= learn_rate * d_L_d_ypred * d_ypred_d_w5
                self.w6 -= learn_rate * d_L_d_ypred * d_ypred_d_w6
                self.b3 -= learn_rate * d_L_d_ypred * d_ypred_d_b3

            # --- Calculate total loss at the end of each epoch

            if epoch % 10 == 0:
                y_preds = np.apply_along_axis(self.feedforward, 1, data)   #np.apply_along_axis(function,aixs,data):将一个函数沿一个轴作用到数组中
                loss = mse_loss(all_y_trues, y_preds)
                print("Epoch %d loss: %.3f" % (epoch, loss))
                list_epoch.append(epoch)
                list_loss.append(loss)
        return list_epoch,list_loss,w1,w2,w3,w4,w5,w6,b1,b2,b3

    def predict(self, data, all_y_trues):
        # 计算将测试集带入模型后得到的预测值
        y_preds = []
        for i in range(len(data)):
            y_pre = self.feedforward(data[i])[0]
            y_preds.append(y_pre)
        # 利用不同的阈值对y_preds进行分割,找到num_normal、num_normal_correct、num_freeze和num_freeze_correct
        x = []
        num_normal = []
        num_normal_correct = []
        num_freeze = []
        num_freeze_correct = []
        for i in range(1, 10):
            num1 = 0
            num2 = 0
            num3 = 0
            num4 = 0
            i /= 200
            x.append(i)
            for j in range(len(y_preds)):
                if y_preds[j] < i:
                    num1 += 1
                    for k in range(len(all_y_trues)):
                        if all_y_trues[k] == 0 and j == k:
                            num2 += 1
            for j in range(len(y_preds)):
                if y_preds[j] >= i:
                    num3 += 1
                    for k in range(len(all_y_trues)):
                        if all_y_trues[k] == 1 and j == k:
                            num4 += 1
            num_normal.append(num3)
            num_normal_correct.append(num4)
            num_freeze.append(num1)
            num_freeze_correct.append(num2)
        print("num_freeze:", num_freeze)
        print("num_freeze_correct:", num_freeze_correct)
        print("num_normal:", num_normal)
        print("num_normal_correct:", num_normal_correct)

        # 根据不同的阈值对预测准确率{(TP+FN)/(TP+TN+FP+FN)}的影响
        y = []
        for i, j in zip(num_normal_correct, num_freeze_correct):
            y.append((i + j) / len(all_y_trues))
        plt.plot(x, y)
        plt.xlabel('阈值', fontproperties="SimHei", fontsize=14)
        plt.ylabel('准确率', fontproperties="SimHei", fontsize=14)
        plt.title("不同的阈值对预测准确率的影响", fontproperties="SimHei", fontsize=14)
        plt.show()

        # 利用找到的最佳的阈值,进行分类,并得到预测标签test_predict_labels
        test_predict_labels = []
        accuracy = max(y)
        thresh = x[y.index(max(y))]
        for j in range(len(y_preds)):
            if y_preds[j] < thresh:
                test_predict_labels.append(0)
            else:
                test_predict_labels.append(1)
        return thresh, accuracy, test_predict_labels

def main():
    # load dataset
    [x_train, y_train, x_test, y_test] = load_dataset()
    # Define train set
    data_train = x_train[:, 1:3]
    all_y_trues_train = y_train

    # Train our neural network!
    network = OurNeuralNetwork()
    [list_epoch, list_loss, w1, w2, w3, w4, w5, w6, b1, b2, b3] = network.train(data_train, all_y_trues_train)
    plt.plot(list_epoch, list_loss)
    plt.xlabel('epoch')
    plt.ylabel('loss')
    plt.title('Neural network loss vs epoch')
    plt.show()

    print(">>>>>>开始预测>>>>>>>")
    # get the predicted result  of x_test
    data_test = x_test[:, 1:3]  # 测试集,并用测试集的wind_speed和power进行预测
    all_y_trues_test = y_test
    [thresh, accuracy, test_predict_labels] = network.predict(data_test, all_y_trues_test)
    print("根据阈值:{},得到的预测准确率:{}".format(thresh, accuracy))
    print("x_test的预测标签:", test_predict_labels)

    plt.scatter(range(len(x_test)), test_predict_labels)
    plt.xlabel('测试数据位数', fontproperties="SimHei", fontsize=14)
    plt.ylabel('标签', fontproperties="SimHei", fontsize=14)
    plt.title("测试集的预测分类图", fontproperties="SimHei", fontsize=14)
    plt.show()

if __name__ == '__main__':
    main()

四、实验结果 

 

         预测准确率accuracy = (TP+FN)/(TP+TN+FP+FN),其中num_freeze = TN+FN ,num_normal =TP+FP,分别表示利用训练的网络模型预测结冰和未结冰的数据点的个数;  num_freeze_correct = TN, num_normal_correct =TP, 分别表示预测正常的结冰和为结冰的数据点的个数。

 ANN_BP的程序和数据集.rar-机器学习文档类资源-CSDN下载

  • 1
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小白要努力sgy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值