全连接层/线性层
-
全连接层又称线性层
-
计算公式:y = w * x + b
-
w和b是参与训练的参数,w的维度决定了隐含层输出的维度,一般称为隐单元个数(hidden size)
隐含层1 的权重维度为 3×5,表示该层将 3维输入映射到 5维输出,因此该层的隐单元个数(hidden size)为 5。
隐含层2 的权重维度为 5×2,表示该层将 5维输入映射到 2维输出,因此该层的隐单元个数(hidden size)为 2。
-
举例:3维映射到5维再映射到2维
输入:x (维度1 x 3) 隐含层1:w(维度3 x 5) 隐含层2:w(维度5 x 2)
代码
import torch
import torch.nn as nn
import numpy as np
"""
numpy手动实现模拟一个线性层
"""
#搭建一个2层的神经网络模型
#每层都是线性层
class TorchModel(nn.Module):
# 继承Module执行初始化方法
def __init__(self, input_size, hidden_size1, hidden_size2):
super(TorchModel, self).__init__()
self.layer1 = nn.Linear(input_size, hidden_size1) #w:3 * 5
self.layer2 = nn.Linear(hidden_size1, hidden_size2) # 5 * 2
# 前向传播
def forward(self, x):
x = self.layer1(x) # 第一层前向传播
y_pred = self.layer2(x) # 第二层前向传播
return y_pred
#建立torch模型
print("------------------------建立torch模型----------------------------")
torch_model = TorchModel(3, 5, 2)
print(torch_model.state_dict())
#打印torch模型权重,权重为随机初始化
torch_model_w1 = torch_model.state_dict()["layer1.weight"].numpy()
torch_model_b1 = torch_model.state_dict()["layer1.bias"].numpy()
torch_model_w2 = torch_model.state_dict()["layer2.weight"].numpy()
torch_model_b2 = torch_model.state_dict()["layer2.bias"].numpy()
print("--------------------torch模型中 w1和b1的值------------------------")
# 这里w1输出的是5行3列的矩阵,因为torch存储是对3行5列的矩阵转置存储的
print(torch_model_w1, "torch w1 权重")
"""
这里b1输出的是一个有5个数据的数组,因为这里对应的是5个神经元的偏置(bias)
假设x入参是2行3列的矩阵, w是你定义的5个神经元, 对应3行5列的矩阵
x = [1, 0, 2]
[3, 1, 0 ]
w = [1, 0, 0, 1, 2]
[0, 1, 0, 1, 2]
[0, 0, 1, 1, 2]
根据公式 y = w * x + b 在经过第一层线性层发生的过程:
w * x = [(1×1+0×0+2×0), (1×0+0×1+2×0), (1×0+0×0+2×1), (1×1+0×1+2×1), (1×2+0×2+2×2)]
[(3×1+1×0+0×0), (3×0+1×1+0×0), (3×0+1×0+0×1), (3×1+1×1+0×1), (3×2+1×2+0×2)]
w * x = [1, 0, 2, 3, 6]
[3, 1, 0, 4, 8]
加偏置b(bias)[1, 1, 1, 1, 2]
w * x + b = [2, 1, 3, 4, 8]
[4, 2, 1, 5, 10]
"""
print(torch_model_b1, "torch b1 权重")
print("--------------------torch模型中 w2和b2的值------------------------")
print(torch_model_w2, "torch w2 权重")
print(torch_model_b2, "torch b2 权重")
#随便准备一个网络输入
x = np.array([[3.1, 1.3, 1.2],
[2.1, 1.3, 13]])
#使用torch模型做预测
torch_x = torch.FloatTensor(x)
y_pred = torch_model.forward(torch_x)
print("-------------------------torch模型预测结果------------------------")
print(y_pred)
#自定义模型,用自定义模型去模仿torch模型
class DiyModel:
def __init__(self, w1, b1, w2, b2):
self.w1 = w1
self.b1 = b1
self.w2 = w2
self.b2 = b2
def forward(self, x):
# 第一层前向传播
# np.dot():矩阵乘法
# x * w1.T:x 矩阵乘以 w1 的转置矩阵
hidden = np.dot(x, self.w1.T) + self.b1
y_pred = np.dot(hidden, self.w2.T) + self.b2
return y_pred
# 把torch模型权重拿过来自己实现计算过程
diy_model = DiyModel(torch_model_w1, torch_model_b1, torch_model_w2, torch_model_b2)
# 用自己的模型来预测
y_pred_diy = diy_model.forward(np.array(x))
print("--------------------------diy模型预测结果-------------------------")
print(y_pred_diy)
输出
------------------------建立torch模型----------------------------
OrderedDict({'layer1.weight': tensor([[ 0.4222, -0.2010, 0.4468],
[ 0.4383, 0.2954, 0.3002],
[-0.1343, -0.1268, -0.0889],
[-0.5301, -0.1032, -0.3945],
[-0.1364, -0.3857, 0.4068]]), 'layer1.bias': tensor([ 0.3121, 0.0777, -0.1180, 0.4329, -0.2124]), 'layer2.weight': tensor([[-0.3435, -0.2176, 0.1668, -0.2133, 0.0679],
[ 0.2116, 0.1089, 0.1543, 0.1814, -0.1473]]), 'layer2.bias': tensor([-0.1794, 0.2779])})
--------------------torch模型中 w1和b1的值------------------------
[[ 0.42215353 -0.2010363 0.44679868]
[ 0.43831372 0.29535377 0.30020356]
[-0.13434225 -0.1268093 -0.08890268]
[-0.5300533 -0.10321763 -0.3945334 ]
[-0.13641182 -0.38566872 0.40677416]] torch w1 权重
[ 0.31208313 0.07770532 -0.11800259 0.43285227 -0.21239492] torch b1 权重
--------------------torch模型中 w2和b2的值------------------------
[[-0.34354576 -0.21756878 0.16678375 -0.21331859 0.06786793]
[ 0.21155924 0.10893524 0.15426606 0.1814121 -0.14726591]] torch w2 权重
[-0.17937568 0.27791154] torch b2 权重
-------------------------torch模型预测结果------------------------
tensor([[-1.0957, 0.5579],
[-2.3748, 0.3056]], grad_fn=<AddmmBackward0>)
--------------------------diy模型预测结果-------------------------
[[-1.09568031 0.5578599 ]
[-2.37476015 0.30561267]]
激活函数
- 为模型添加非线性因素,使模型具有拟合非线性函数的能力
- 无激活函数时 y = w1(w2(w3 * x + b3) +b2) + b1 仍然是线性函数
- 所以我们可以过一下线性函数后再过非线性函数,这样就是曲线了
激活函数-Sigmoid
读音:/'sɪgmɔɪd/ (类似“sei格-摩诶德”)
激活函数-tanh
tanh(双曲正切函数)
- 读音:
/ˈtænʃ/(类似“坦施'') - 图片第一行,跟Sigmoid有映射关系
- 图片第二行,tanh的公式
激活函数-Relu
读音:/ˈriːluː/(类似“瑞路”)
激活函数-Gelu
读音:/'dʒiːluː/(类似“吉卢”)
激活函数-Softmax
用来做数据的归一化,也就是得到这些数据的映射数据,映射数据相加为1