《机器学习》实验三:利用BP神经网络实现鲍鱼的性别分类

《机器学习》实验三:利用BP神经网络实现鲍鱼的性别分类

实验目的

  1. 掌握BP神经网络的基本原理;
  2. 了解TensorFlow框架。

实验原理

  1. BP神经网络
    BP(Back Propagation)神经网络是一种按照误差反向传播算法训练的多层前馈网络,也是目前应用最广泛的神经网络模型之一。BP神经网络包含多层神经元,如图1所示。输入层的神经元负责接受外界发来的各种信息,并将信息传递给中间层神经元,中间隐含层神经元负责将接收到的信息进行处理变换,根据需求处理信息,实际应用中可将中间隐含层设置为一层或者多层隐含层结构,并通过最后一层的隐含层将信息传递到输出层。

在这里插入图片描述

图1 BP神经网络结构

BP神经网络的计算过程由正向计算过程和反向计算过程组成。正向传播过程,输入模式从输入层经隐单元层逐层处理,并转向输出层,每一层神经元的状态只影响下一层神经元的状态。如果在输出层不能得到期望的输出,则转入反向传播,将误差信号沿原来的连接通路返回,通过修改各神经元的权值,使得误差信号最小。当输出的误差减小到期望程度或者预先设定的学习迭代次数时,训练结束,BP神经网络完成学习。
2. TensorFlow框架
TensorFlow是由Google团队开发的深度学习框架之一,它是一个完全基于Python语言设计的开源的软件。TensorFlow的初衷是以最简单的方式实现机器学习和深度学习的概念,它结合了计算代数的优化技术,使它便计算许多数学表达式。
TensorFlow可以训练和运行深度神经网络,它能应用在许多场景下,比如,图像识别、手写数字分类、递归神经网络、单词嵌入、自然语言处理、视频检测等等。TensorFlow可以运行在多个CPU或GPU上,同时它也可以运行在移动端操作系统上(如安卓、IOS 等),它的架构灵活,具有良好的可扩展性,能够支持各种网络模型(如OSI七层和TCP/IP四层)。
TensorFlow这个词由Tensor和Flow两个词组成,这两者是TensorFlow最基础的要素。Tensor代表张量(也就是数据),它的表现形式是一个多维数组;而Flow意味着流动,代表着计算与映射,它用于定义操作中的数据流。

实验内容与要求

  1. 数据预处理;
  2. 构造BP神经网络模型;
  3. 训练模型,迭代计算训练损失、测试损失和测试集的准确率;
  4. 绘制图像。

实验器材(设备、元器件)

处理器:Intel® Core™ i5-8300H CPU @ 2.30GHz
Python 3.9.0
matplotlib 3.4.0
tensorflow 2.11.0rc1
xlrd 1.2.0

实验步骤

  1. 数据预处理
    给定的训练集和测试集是data文件,先把它们改为xlsx文件。设计一个LoadData函数,输入为abalone_train.xlsx和abalone_test.xlsx的文件路径,再调用Python第三方库——xlrd,将当中的数据转换为列表x_train、y_train、x_test、y_test,最后返回这四个列表。代码如下:
def LoadData(trainpath, testpath):
    file_train_path = trainpath
    file_train_xlsx = xd.open_workbook(file_train_path)
    file_train_sheet = file_train_xlsx.sheet_by_name('Sheet1')
    x_train = []
    y_train = []
    for row in range(file_train_sheet.nrows):
        x_data = []
        for col in range(file_train_sheet.ncols):
            if col == 0:
                if file_train_sheet.cell_value(row, col) == 'M':
                    y_train.append(1)
                elif file_train_sheet.cell_value(row, col) == 'F':
                    y_train.append(-1)
                else:
                    y_train.append(0)
            else:
                x_data.append(file_train_sheet.cell_value(row, col))

        x_train.append(list(x_data))

    file_test_path = testpath
    file_test_xlsx = xd.open_workbook(file_test_path)
    file_test_sheet = file_test_xlsx.sheet_by_name('Sheet1')
    x_test = []
    y_test = []
    for row in range(file_test_sheet.nrows):
        x_data = []
        for col in range(file_test_sheet.ncols):
            if col == 0:
                if file_test_sheet.cell_value(row, col) == 'M':
                    y_test.append(1)
                elif file_test_sheet.cell_value(row, col) == 'F':
                    y_test.append(-1)
                else:
                    y_test.append(0)
            else:
                x_data.append(file_test_sheet.cell_value(row, col))

        x_test.append(list(x_data))

    # print(x_train)
    # print(y_train)
    # print(x_test)
    # print(y_test)

    # 将特征值的类型转换为tensor类型,避免后面的矩阵乘法报错
    x_train = tf.cast(x_train, tf.float32)
    x_test = tf.cast(x_test, tf.float32)
    return x_train, x_test, y_train, y_test

  1. 构造BP神经网络模型
    在BP.py中构造一个BP神经网络类。类中包含BP神经网络类的构造函数、训练函数和测试函数。构造函数定义了输入层神经元个数、隐藏层神经元个数、输出层层神经元个数和正则化系数等参数,还定义了损失函数,均方误差加入L2正则化。训练函数定义了训练数据集及其标签、测试数据集及其标签、学习率、训练趟数、样本规模等超参数。测试函数用于计算测试集的测试精度。代码如下:
import numpy as np
import tensorflow as tf
from sklearn.metrics import accuracy_score


class BP(object):
    def __init__(self, input_n, hidden_n, output_n, lambd):
        """
        这是BP神经网络类的构造函数
        :param input_n:输入层神经元个数
        :param hidden_n: 隐藏层神经元个数
        :param output_n: 输出层神经元个数
        :param lambd: 正则化系数
        """
        self.Train_Data = tf.placeholder(tf.float64, shape=(None, input_n), name='input_dataset')  # 训练数据集
        self.Train_Label = tf.placeholder(tf.float64, shape=(None, output_n), name='input_labels')  # 训练数据集标签
        self.input_n = input_n  # 输入层神经元个数
        self.hidden_n = hidden_n  # 隐含层神经元个数
        self.output_n = output_n  # 输出层神经元个数
        self.lambd = lambd  # 正则化系数
        self.input_weights = tf.Variable(
            tf.random_normal((self.input_n, self.hidden_n), mean=0, stddev=1, dtype=tf.float64),
            trainable=True)  # 输入层与隐含层之间的权重
        self.hidden_weights = tf.Variable(
            tf.random_normal((self.hidden_n, self.output_n), mean=0, stddev=1, dtype=tf.float64),
            trainable=True)  # 隐含层与输出层之间的权重
        self.hidden_threshold = tf.Variable(tf.random_normal((1, self.hidden_n), mean=0, stddev=1, dtype=tf.float64),
                                            trainable=True)  # 隐含层的阈值
        self.output_threshold = tf.Variable(tf.random_normal((1, self.output_n), mean=0, stddev=1, dtype=tf.float64),
                                            trainable=True)  # 输出层的阈值
        # 将层与层之间的权重与偏置项加入损失集合
        tf.add_to_collection('loss', tf.contrib.layers.l2_regularizer(self.lambd)(self.input_weights))
        tf.add_to_collection('loss', tf.contrib.layers.l2_regularizer(self.lambd)(self.hidden_weights))
        tf.add_to_collection('loss', tf.contrib.layers.l2_regularizer(self.lambd)(self.hidden_threshold))
        tf.add_to_collection('loss', tf.contrib.layers.l2_regularizer(self.lambd)(self.output_threshold))
        # 定义前向传播过程
        self.hidden_cells = tf.sigmoid(tf.matmul(self.Train_Data, self.input_weights) + self.hidden_threshold)
        self.output_cells = tf.sigmoid(tf.matmul(self.hidden_cells, self.hidden_weights) + self.output_threshold)
        # 定义损失函数,并加入损失集合
        self.MSE = tf.reduce_mean(tf.square(self.output_cells - self.Train_Label))
        tf.add_to_collection('loss', self.MSE)
        # 定义损失函数,均方误差加入L2正则化
        self.loss = tf.add_n(tf.get_collection('loss'))

    def train_test(self, Train_Data, Train_Label, Test_Data, Test_Label, learn_rate, epoch, iteration, batch_size):
        """
        这是BP神经网络的训练函数
        :param Train_Data: 训练数据集
        :param Train_Label: 训练数据集标签
        :param Test_Data: 测试数据集
        :param Test_Label: 测试数据集标签
        :param learn_rate:  学习率
        :param epoch:  时期数
        :param iteration: 一个epoch的迭代次数
        :param batch_size:  小批量样本规模
        """
        train_loss = []  # 训练损失
        test_loss = []  # 测试损失
        test_accarucy = []  # 测试精度
        with tf.Session() as sess:
            datasize = len(Train_Label)
            self.train_step = tf.train.GradientDescentOptimizer(learn_rate).minimize(self.loss)
            sess.run(tf.global_variables_initializer())
            for e in np.arange(epoch):
                for i in range(iteration):
                    start = (i * batch_size) % datasize
                    end = np.min([start + batch_size, datasize])
                    sess.run(self.train_step,
                             feed_dict={self.Train_Data: Train_Data[start:end],
                                        self.Train_Label: Train_Label[start:end]})
                    if i % 10000 == 0:
                        total_MSE = sess.run(self.MSE,
                                             feed_dict={self.Train_Data: Train_Data, self.Train_Label: Train_Label})
                        print("第%d个epoch中,%d次迭代后,训练MSE为:%g" % (e + 1, i + 10000, total_MSE))
                # 训练损失
                _train_loss = sess.run(self.MSE, feed_dict={self.Train_Data: Train_Data, self.Train_Label: Train_Label})
                train_loss.append(_train_loss)
                # 测试损失
                _test_loss = sess.run(self.MSE, feed_dict={self.Train_Data: Test_Data, self.Train_Label: Test_Label})
                test_loss.append(_test_loss)
                # 测试精度
                test_result = sess.run(self.output_cells, feed_dict={self.Train_Data: Test_Data})
                test_accarucy.append(self.Accuracy(test_result, Test_Label))
        return train_loss, test_loss, test_accarucy

    def Accuracy(self, test_result, test_label):
        """
        这是BP神经网络的测试函数
        :param test_result: 测试集预测结果
        :param test_label: 测试集真实标签
        """
        predict_ans = []
        label = []
        for (test, _label) in zip(test_result, test_label):
            test = np.exp(test)
            test = test / np.sum(test)
            predict_ans.append(np.argmax(test))
            label.append(np.argmax(_label))
        return accuracy_score(label, predict_ans)

  1. 训练模型
    在run.py中创建一个主函数run_main(),首先实现导入数据,设置abalone_train.xlsx和abalone_test.xlsx的文件路径,调用LoadData函数得到训练集和测试集的样本与标签。接着设置神经网络参数,学习率为0.01,训练趟数为1000,然后训练并测试网络。代码如下:
    # 导入数据
    trainpath = 'data/abalone_train.xlsx'
    testpath = 'data/abalone_test.xlsx'
    Train_Data, Test_Data, Train_Label, Test_Label = LoadData(trainpath, testpath)
    Train_Data = Normalizer().fit_transform(Train_Data)
    Test_Data = Normalizer().fit_transform(Test_Data)

    # 设置网络参数
    input_n = np.shape(Train_Data)[1] + np.shape(Test_Data)[1]
    output_n = np.shape(Train_Label)[1] + np.shape(Test_Label)[1]
    hidden_n = int(np.sqrt(input_n * output_n))
    lambd = 0.001
    batch_size = 64
    learn_rate = 0.01
    epoch = 1000
    iteration = 10000

    # 训练并测试网络
    bp = BP(input_n, hidden_n, output_n, lambd)
    train_loss, test_loss, test_accuracy = bp.train_test(Train_Data, Train_Label, Test_Data, Test_Label, learn_rate,
                                                         epoch, iteration, batch_size)

  1. 绘制图像
    在run.py的run_main函数中绘制训练与测试损失和测试集的测试精度2张图像。代码如下:
    # 解决画图是的中文乱码问题
    mpl.rcParams['font.sans-serif'] = [u'simHei']
    mpl.rcParams['axes.unicode_minus'] = False

    # 结果可视化
    col = ['Train_Loss', 'Test_Loss']
    epoch = np.arange(epoch)
    plt.plot(epoch, train_loss, 'r')
    plt.plot(epoch, test_loss, 'b-.')
    plt.xlabel('Epoch')
    plt.ylabel('Loss')
    plt.grid(True)
    plt.legend(labels=col, loc='best')
    plt.savefig('./训练与测试损失.jpg')
    plt.show()
    plt.close()

    plt.plot(epoch, test_accuracy, 'r')
    plt.xlabel('Epoch')
    plt.ylabel('Test Accuracy')
    plt.grid(True)
    plt.legend(loc='best')
    plt.savefig('./测试精度.jpg')
    plt.show()
    plt.close()
  1. 实验结果
    编写好代码后,运行run.py。
    训练与测试过程中损失随训练趟数的曲线如图2所示。

在这里插入图片描述
图2 训练与测试损失

测试过程中测试集的准确率随训练趟数增加的折线如图3所示。其中,每一个点的横坐标是训练趟数,纵坐标是该趟时的测试集的准确率。

在这里插入图片描述
图3 测试集准确率

在本次实验中,预设的学习率为0.01。从图2中我们可以看出,训练与测试损失随迭代趟数的增加而降低;而从图3中我们可以看出,当训练趟数很小时,测试集的准确率随迭代趟数的增加而增加,小幅降低后,当训练趟数超过70轮后,测试集的准确率稳定在72.1%。

心得体会

本实验利用BP神经网络实现了鲍鱼的性别分类,使用了TensorFlow框架,用张量表示数据,用计算图搭建神经网络,用会话执行计算图,优化线上的权重(参数),最后得到模型。测试集的准确率为0.7214,达到预期目标。通过此次实验,很好地掌握了BP神经网络前向传播和反向传播的原理,熟悉了Python第三方库——tensorflow、matplotlib和xlrd的使用。

  • 1
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

UestcXiye

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

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

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

打赏作者

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

抵扣说明:

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

余额充值