• 【Deep Learning 5】FNN前馈神经网络


     

    🍊本文详细介绍了FNN的原理,并给出了具体的推导过程

    🍊使用Pytorch搭建了FNN模型,并对糖尿病数据集开展分类任务实战

    一、Introduction

    在神经网络中,最基本的结构就是神经元,给定一组神经元,如何组合成一个神经网络呢?一个最简单的做法就是将神经元分成不同的组,每组作为一个网络层,随后与前一层全连接,如下图中所示,这就是前馈神经网络。

     很多时候我们将前馈神经神经网络称为多层感知机MLP(Mutlti-Layer Perceptron),但是严谨的来讲,此称谓并不合适,因为FNN的每个神经元是LogisticRegression模型,是连续的非线性模型,而MLP的本意是非连续的非线性模型。

    二、Principle

    前馈神经网络的原理也非常简单,即每两层网络层都是全连接,每一层的神经元接受到上一层的神经元信号并传递到下一层。以下是数学公式推导过程

     令a^{0} = 𝒙,前馈神经网络通过不断迭代下面公式进行信息传播:

    三、Experiment

    题目:diabetes是一个糖尿病数据集,一共有8个特征,最终需要判断该人是否患有糖尿病,即二分类任务。其数据集如下(该数据集比较经典,网上很容易下载到)。现需要使用建立FNN模型对其开展分类任务。

    伪代码

    1 数据读取

    2 定义FNN模型

    3 定义损失函数和优化器

    4 模型训练

    5 可视化训练结果

    1. import numpy as np
    2. import torch
    3. import matplotlib.pyplot as plt
    4. # Prepare the dataset
    5. dataset = np.loadtxt('diabetes.csv', delimiter=',', dtype=np.float32, encoding='utf-8')
    6. x_data = torch.from_numpy(dataset[:, :-1])
    7. y_data = torch.from_numpy(dataset[:, [-1]])
    8. # Define the model
    9. class FNNModel(torch.nn.Module):
    10. def __init__(self):
    11. super(FNNModel, self).__init__()
    12. self.linear1 = torch.nn.Linear(8, 6) # 输入数据的特征有8个,也就是有8个维度,随后将其降维到6维
    13. self.linear2 = torch.nn.Linear(6, 4) # 6维降到4维
    14. self.linear3 = torch.nn.Linear(4, 2) # 4维降到2维
    15. self.linear4 = torch.nn.Linear(2, 1) # 2w维降到1维
    16. self.sigmoid = torch.nn.Sigmoid() # 可以视其为网络的一层,而不是简单的函数使用
    17. def forward(self, x):
    18. x = self.sigmoid(self.linear1(x))
    19. x = self.sigmoid(self.linear2(x))
    20. x = self.sigmoid(self.linear3(x))
    21. x = self.sigmoid(self.linear4(x))
    22. return x
    23. model = FNNModel()
    24. # Define the criterion and optimizer
    25. criterion = torch.nn.BCELoss(reduction='mean') # 返回损失的平均值
    26. optimizer = torch.optim.SGD(model.parameters(), lr=0.1)
    27. epoch_list = []
    28. loss_list = []
    29. # Training
    30. for epoch in range(1000000):
    31. y_pred = model(x_data)
    32. loss = criterion(y_pred, y_data)
    33. print('Epoch[{}/{}],loss:{:.6f}'.format(epoch+1, 1000000, loss.item()))
    34. epoch_list.append(epoch)
    35. loss_list.append(loss.item())
    36. optimizer.zero_grad()
    37. loss.backward()
    38. optimizer.step()
    39. # Drawing
    40. plt.plot(epoch_list, loss_list)
    41. plt.xlabel('epoch')
    42. plt.ylabel('loss')
    43. plt.show()

    Result

     可以看到随着时间的推进,该模型的损失值在不断的收敛。说明此FNN模型是有效的

    在正式的项目中,1数据集的处理都是通过Dataset类和DataLoader类进行的

                                 2 使用SGD比较少,更多的是使用mini_batch训练方法

                                 3 使用__main__脚本进行项目的开启

    因此作者重写了上述内容 

    1. import numpy as np
    2. import torch
    3. import matplotlib.pyplot as plt
    4. from torch.utils.data import Dataset, DataLoader
    5. # Prepare the dataset
    6. class DiabetesDateset(Dataset):
    7. # 加载数据集
    8. def __init__(self, filepath):
    9. xy = np.loadtxt(filepath, delimiter=',', dtype=np.float32, encoding='utf-8')
    10. self.len = xy.shape[0] # shape[0]是矩阵的行数,shape[1]是矩阵的列数
    11. self.x_data = torch.from_numpy(xy[:, :-1])
    12. self.y_data = torch.from_numpy(xy[:, [-1]])
    13. # 获取数据索引
    14. def __getitem__(self, index):
    15. return self.x_data[index], self.y_data[index]
    16. # 获得数据总量
    17. def __len__(self):
    18. return self.len
    19. dataset = DiabetesDateset('diabetes.csv')
    20. train_loader = DataLoader(dataset=dataset, batch_size=32, shuffle=True, num_workers=2) # num_workers为多线程
    21. # Define the model
    22. class FNNModel(torch.nn.Module):
    23. def __init__(self):
    24. super(FNNModel, self).__init__()
    25. self.linear1 = torch.nn.Linear(8, 6) # 输入数据的特征有8个,也就是有8个维度,随后将其降维到6维
    26. self.linear2 = torch.nn.Linear(6, 4) # 6维降到4维
    27. self.linear3 = torch.nn.Linear(4, 2) # 4维降到2维
    28. self.linear4 = torch.nn.Linear(2, 1) # 2w维降到1维
    29. self.sigmoid = torch.nn.Sigmoid() # 可以视其为网络的一层,而不是简单的函数使用
    30. def forward(self, x):
    31. x = self.sigmoid(self.linear1(x))
    32. x = self.sigmoid(self.linear2(x))
    33. x = self.sigmoid(self.linear3(x))
    34. x = self.sigmoid(self.linear4(x))
    35. return x
    36. model = FNNModel()
    37. # Define the criterion and optimizer
    38. criterion = torch.nn.BCELoss(reduction='mean') # 返回损失的平均值
    39. optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
    40. epoch_list = []
    41. loss_list = []
    42. # Training
    43. if __name__ == '__main__':
    44. for epoch in range(100):
    45. # i是一个epoch中第几次迭代,一共756条数据,每个mini_batch为32,所以一个epoch需要迭代23次
    46. # data获取的数据为(x,y)
    47. loss_one_epoch = 0
    48. for i, data in enumerate(train_loader, 0):
    49. inputs, labels = data
    50. y_pred = model(inputs)
    51. loss = criterion(y_pred, labels)
    52. loss_one_epoch += loss.item()
    53. optimizer.zero_grad()
    54. loss.backward()
    55. optimizer.step()
    56. loss_list.append(loss_one_epoch / 23)
    57. epoch_list.append(epoch)
    58. print('Epoch[{}/{}],loss:{:.6f}'.format(epoch + 1, 100, loss_one_epoch / 23))
    59. # Drawing
    60. plt.plot(epoch_list, loss_list)
    61. plt.xlabel('epoch')
    62. plt.ylabel('loss')
    63. plt.show()

    Result 

    因为Mini_batch训练的方法虽然最终效果比较好,但是训练的速度实在是太慢了,因此作者将Epoch只设置了100层,因此最终的Loss在67%左右,如果加大训练量如第一个实验中的Epoch中,那么Loss会继续收敛的

    参考资料

    《机器学习》周志华

    《深度学习与机器学习》吴恩达

    《神经网络与与深度学习》邱锡鹏

    Pytorch深度学习实战》刘二大人

  • 相关阅读:
    表单设计中,印刷模式和拖拽模式选哪个?成年人:全都要
    【JavaSpring】spring接口-beanfactory和applicationcontext与事件解耦
    Python学习笔记--字符、变量、数据类型与注释
    10.16 qt作业
    Ubuntu 安装和卸载mysql
    vulnhub靶场之HACK ME PLEASE
    RabbitMQ高级特性 - 生产者消息确认机制
    实验二 逻辑回归算法实验
    【算法设计与分析】6 最大流应用问题
    Linux内核启动流程-第一阶段汇编流程简介
  • 原文地址:https://blog.csdn.net/ccaoshangfei/article/details/127453680