深度学习03-多层神经网络
1. 异或门问题
很多时候,我们的分类问题,就是使用一条之间,讲平面上的点划分为两个部分。
1. 矩阵乘法的已补充:
Tensor进行乘法的过程中,会把一维向量,默认作为列向量进行运算。
下面程序的结果:
import torch
X = torch.tensor([[1, 2], [3, 4],[5,6], [7, 8]], dtype=torch.float)
y = torch.tensor([2, 3], dtype=torch.float)
z = torch.tensor([[1], [3]], dtype=torch.float)
print(z.shape) # torch.Size([2])
print(y.shape) # torch.Size([2, 1])
print(X @ y) # tensor([ 8., 18., 28., 38.]) 形状是 torch.Size([4])
print(X @ z) # tensor([[ 8.],
# [18.],
# [28.],
# [38.]]) 形状是 4 * 1 二位矩阵。
简单的单层神经网络,我们可以进行线性分类,方便的把内容分为两类或者多类。但是对于异或这种数据,我们是不可能使用简单的线性关系来分离数据的。

所以,引入多层神经网络,来拟合曲线寻找分类边界,进行分类。多层神经网络,理论上来讲可以拟合/接近任意形状的曲线。
单层神经网络,不能解决异或门的分类问题。但是只要我们增加一层,我们就可以解决这个分类问题。(实际上,我们增加多层,可以处理任意的分类问题)
深层神经网络的不可解释性
数据量越大,神经网络层数越深,效果就会越好。
深度神经网络的核心理解:

1 输入的神经元的个数,其实就是我们的特征数量。
2 每一层的神经元,其实就是一个矩阵。(一层就是一个矩阵,转换矩阵)
3 神经网络传递的过程,其实相当于把我们的特征分解,再处理,之后根据输出要求,综合形成输出。
在实际工程中,我们实际数据可能有成百上千个特征,所以我们的神经网络的层数和中间特征会很大。中间会有各种各样的参数,他们之间究竟是如何作用生成了我们最后的结果,所以通常情况下,我们可以认为整个神经网络处理的过程是一个"黑箱"。
所以我们很难通过神经网络的传播,来获取特征权重的重要性。
深度探索神经网络
增加神经网络的层数并不会增加神经网络的表达能力
神经网络的表达能力的提升,其实是通过激活函数实现的。(相当于引入非线性因素)
常见的神经网络的激活函数:
sigmoid,ReLU,tanh, softmax等。
从0实现神经网络的正向传播
复习:torch.nn中,包含两个内容,一个function 包含我们所需要的各种激活函数。一个Module,包含我们建立神经网络所需要的各种层。
所以我们建立神经网络的时候,可以直接使用nn来搭建。
import torch
from torch import nn
# 生成 500,2 的矩阵
torch.random.manual_seed(0)
x = torch.randint(0, 10, (500, 20))
y = torch.randint(0, 3, (500, ))
print(x.shape)
print(y.shape)
x = x.float()
y = y.float()
class Net(nn.Module):
def __init__(self, input_dim, output_dim):
super(Net, self).__init__() # 必须写上,因为父类在init方法中的,如果有自定义的内容,就不会执行。所以还是手动调用该__init__()
self.fc1 = nn.Linear(input_dim, 64)
self.fc2 = nn.Linear(64, 32)
self.fc3 = nn.Linear(32, output_dim)
self.relu = nn.ReLU()
# self.softmax = nn.functional.softmax(dim=1)
# 通常情况下,最后一层我们不会使用激活函数,因为后面求解梯度时,
# 最后一层会自动求解,但是这里为了方便,还是加上了
def forward(self, x):
x = self.fc1(x)
x = self.relu(x)
x = self.fc2(x)
x = self.relu(x)
x = self.fc3(x)
x = nn.functional.softmax(x, dim=1)
return x
input_dim = x.shape[-1] # 通常输入特征是x的最后一个维度,这里我们直接获取
print(input_dim)
output_dim = len(y.unique())
print(output_dim)
# 分类
model = Net(input_dim, output_dim)
# 会自动执行forward函数
model(x)
# 查看数据
n1 = model.fc1.weight.data
n1_b = model.fc1.bias.data
print(n1)
print(n1_b)
print(n1.shape)
print(n1_b.shape)
我们直接使用nn模块提供的 Module和 function,像是搭积木一样,搭建我们自己的神经网络。
这个三层的神经网络,其实就是输入了我们的数据x(500, 20)。
进入第一层网络,(其实就是一个矩阵w1,x与w1进行运算,得到第一层的输出h1)
h1进入第二层网络(其实就是与矩阵 w2进行运算,得到输出h2)
继续进入第三层网路,得到输出。
所有的神经网络的前向传播过程,其实都是这种类似的过程。
详细解析流程:
每一层的权重的形状如下:
输入的形状是 (500, 20)

计算过程如下:
output = input @ weight.T + bias
对于我们继承的nn.Module中,一些重要的参数
print(model.training) # True 是否训练
print(model.cpu()) # 把模型放在CPU上
print(model.cuda()) # 把模型放在GPU上(要有GPU)
params = model.parameters()
for item in params:
print(item)
# 也可以查看具体的参数和名称
for name, param in model.named_parameters():
print(name, param)
这些参数相对来说比较重要,但是即便不会也不用担心,我们开发过程中,会经常用到一些函数,比如 model.parameters(),和model.training 完全不用死记硬背。
更多推荐


所有评论(0)