实验五 前馈神经网络(1)二分类任务

目录

前言

一、神经元

1、净活性值

2、激活函数

2.1 Sigmoid 型函数

2.2 ReLU型函数

二、基于前馈神经网络的二分类任务

1、数据集构建

2、模型构建

2.1 线性算子

2.2 Logistic算子

2.3 层的串行组合

3、损失函数

4、模型优化

4.1 反向传播算法

 4.2 损失函数

4.3 Logistic算子

4.4 线性层

4.5 整个网络

4.6 优化器

5、完善Runner类:RunnerV2_1

6、模型训练

7、性能评价

三、体会

参考:


前言

前馈神经网络(feedforward neural network,FNN),简称前馈网络,是人工神经网络的一种。前馈神经网络采用一种单向多层结构。其中每一层包含若干个神经元。在此种神经网络中,各神经元可以接收前一层神经元的信号,并产生输出到下一层。第0层叫输入层,最后一层叫输出层,其他中间层叫做隐含层(或隐藏层、隐层)。隐层可以是一层。也可以是多层  

一、神经元

神经网络的基本组成单元为带有非线性激活函数的神经元,其结构如如下图所示。神经元是对生物神经元的结构和特性的一种简化建模,接收一组输入信号并产生输出。

1、净活性值

假设一个神经元接收的输入为x\epsilon R^D,其权重向量为w\epsilon R^D,神经元所获得的输入信号,即净活性值z的计算方法为

z=w^Tx+b,其中b为偏置

为了提高预测样本的效率,我们通常会将N个样本归为一组进行成批地预测。

z=Xw+b,其中X\epsilon R^{N\times D}N个样本的特征矩阵,z\epsilon R^NN个预测值组成的列向量。

使用pytorch计算一组输入的净活性值:

import torch

# 2个特征数为5的样本
X = torch.rand([2, 5])

#参数
w = torch.rand([5, 1])
b = torch.rand([1, 1])

# 使用'torch.matmul'实现矩阵相乘
z = torch.matmul(X, w) + b
print("input X:", X)
print("weight w:", w, "\nbias b:", b)
print("output z:", z)

执行结果:

思考题:

加权求和与仿射变换之间有什么区别和联系?

在我看来加权求和在本质是就是一个线性变换,线性变换 ,变换前是直线,变换后依然是直线; 直线比例保持不变; 变换前是原点,变换后依然是原点。而仿射变换是线性变换接了一个平移,从一个向量空间进入另一个向量空间计算; 变换前是直线,变换后依然是直线; 直线比例保持不变。

2、激活函数

净活性值z再经过一个非线性函数f(\cdot )后,得到神经元的活性值a

a=f(z),

激活函数通常为非线性函数,可以增强神经网络的表示能力和学习能力。常用的激活函数有S型函数和ReLU函数。

2.1 Sigmoid 型函数

Sigmoid 型函数是指一类S型曲线函数,为两端饱和函数。常用的 Sigmoid 型函数有 Logistic 函数和 Tanh 函数,其数学表达式为

Logistic 函数:

\sigma (z)=\frac{1}{1+exp(-z)}.

Tanh 函数:

tanh(z)=\frac{exp(z)-exp(-z)}{exp(z)+exp(-z)}.

实现并可视化“Logistic函数、Tanh函数”

实现如下:

import torch
import matplotlib.pyplot as plt

# Logistic函数
def logistic(z):
    return 1.0 / (1.0 + torch.exp(-z))

# Tanh函数
def tanh(z):
    return (torch.exp(z) - torch.exp(-z)) / (torch.exp(z) + torch.exp(-z))

# 在[-10,10]的范围内生成10000个输入值,用于绘制函数曲线
z = torch.linspace(-10, 10, 10000)

plt.figure()
plt.plot(z.tolist(), logistic(z).tolist(), color='#e4007f', label="Logistic Function")
plt.plot(z.tolist(), tanh(z).tolist(), color='#f19ec2', linestyle ='--', label="Tanh Function")

ax = plt.gca() # 获取轴,默认有4个
# 隐藏两个轴,通过把颜色设置成none
ax.spines['top'].set_color('none')
ax.spines['right'].set_color('none')
# 调整坐标轴位置
ax.spines['left'].set_position(('data',0))
ax.spines['bottom'].set_position(('data',0))
plt.legend(loc='lower right', fontsize='large')

plt.savefig('fw-logistic-tanh.pdf')
plt.show()

 

2.2 ReLU型函数

常见的ReLU函数有ReLU和带泄露的ReLU(Leaky ReLU),数学表达式分别为:

ReLU(z)=max(0,z),

LeakyReLU(z)=max(0,z)+\lambda min(0,z),

其中\lambda为超参数。

实现并可视化可视化“ReLU、带泄露的ReLU的函数”

实现如下:

def relu(z):
    return torch.maximum(z, torch.tensor(0.))

def leaky_relu(z, negative_slope=0.1):
    # 当前版本torch暂不支持直接将bool类型转成int类型,因此调用了torch的cast函数来进行显式转换
    a1 = (torch.can_cast((z > 0).dtype, to=torch.float32) * z)
    a2 = (torch.can_cast((z <= 0).dtype, to=torch.float32) * (negative_slope * z))
    return a1 + a2

# 在[-10,10]的范围内生成一系列的输入值,用于绘制relu、leaky_relu的函数曲线
z = torch.linspace(-10, 10, 10000)

plt.figure()
plt.plot(z.tolist(), relu(z).tolist(), color="#e4007f", label="ReLU Function")
plt.plot(z.tolist(), leaky_relu(z).tolist(), color="#f19ec2", linestyle="--", label="LeakyReLU Function")

ax = plt.gca()
ax.spines['top'].set_color('none')
ax.spines['right'].set_color('none')
ax.spines['left'].set_position(('data',0))
ax.spines['bottom'].set_position(('data',0))
plt.legend(loc='upper left', fontsize='large')
plt.savefig('fw-relu-leakyrelu.pdf')
plt.show()

 

二、基于前馈神经网络的二分类任务

前馈神经网络的网络结构如下图所示。每一层获取前一层神经元的活性值,并重复上述计算得到该层的活性值,传入到下一层。整个网络中无反馈,信号从输入层向输出层逐层的单向传播,得到网络最后的输出 a^{(L)}

1、数据集构建

使用上次实验中构建的二分类数据集:Moon1000数据集,其中训练集640条、验证集160条、测试集200条。该数据集的数据是从两个带噪音的弯月形状数据分布中采样得到,每个样本包含2个特征。

from nndl2.dataset import make_moons
 
n_samples = 1000
X, y = make_moons(n_samples=n_samples, shuffle=True, noise=0.15)
 
num_train = 640
num_dev = 160
num_test = 200
 
X_train, y_train = X[:num_train], y[:num_train]
X_dev, y_dev = X[num_train:num_train + num_dev], y[num_train:num_train + num_dev]
X_test, y_test = X[num_train + num_dev:], y[num_train + num_dev:]
 
y_train = y_train.reshape([-1,1])
y_dev = y_dev.reshape([-1,1])
y_test = y_test.reshape([-1,1])

2、模型构建

为了更高效的构建前馈神经网络,先定义每一层的算子,然后再通过算子组合构建整个前馈神经网络。

假设网络的第l层的输入为第l-1层的神经元活性值a^{(l-1)},经过一个仿射变换,得到该层神经元的净活性值z,再输入到激活函数得到该层神经元的活性值a

在实践中,为了提高模型的处理效率,通常将N个样本归为一组进行成批地计算。假设网络第ll层的输入为A{(l-1)}\epsilon R^{N\times M_{l-1}},其中每一行为一个样本,则前馈网络中第l层的计算公式为

Z^{(l)}=A^{(l-1)}W^{(l)}+b^{(l)}\epsilon R^{N\times M_{l}}

A^{(l)}=f_l(Z^{(l)})\epsilon R^{N\times M_{l}}

其中Z^{(l)}为NN个样本第ll层神经元的净活性值,A^{(l)}为NN个样本第ll层神经元的活性值,W^{(l)}\epsilon R^{M_{l-1}M_{l}}为第l层的权重矩阵,b^{(l)}\epsilon R^{(1\times M_{l})}为第l层的偏置。

2.1 线性算子

from nndl.op import Op
 
# 实现线性层算子
class Linear(Op):
    def __init__(self, input_size, output_size, name, weight_init=torch.normal, bias_init=torch.zeros):
 
        self.params = {}
        # 初始化权重
        self.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值