处理多维特征的输入
具有多维特征的数据集
前面我们处理特征维数一直是一维特征,在本节中,我们将处理具有多维特征的数据集,并且对其进行预测分类

对于具有多维输入的数据集,每一行叫做一个样本Sample,每一列叫做特征feature
当特征是多维(如上图是8维)时,逻辑回归模型的函数如下:
y
^
(
i
)
=
σ
(
∑
n
=
1
8
x
n
(
i
)
ω
n
+
b
)
\hat y^{(i)} = \sigma(\sum_{n=1}^{8}x_n^{(i)}\omega _n + b)
y^(i)=σ(n=1∑8xn(i)ωn+b)
即:
y
^
(
i
)
=
σ
(
[
x
i
(
i
)
…
x
8
(
i
)
]
[
ω
1
⋮
ω
8
]
+
b
)
=
σ
(
z
(
i
)
)
\hat y^{(i)} = \sigma(\begin{bmatrix} x_i^{(i)} \ \dots \ x_8^{(i)} \end{bmatrix}\begin{bmatrix}\omega _1 \\ \vdots \\ \omega _8 \end{bmatrix} + b) = \sigma (z^{(i)})
y^(i)=σ([xi(i) … x8(i)]
ω1⋮ω8
+b)=σ(z(i))

只需要在源代码中改变一下线性模型的定义即可
self.linear = torch.nn.Linear(8, 1)
使用多层神经网络进行分类任务
多层神经网络主要是利用了矩阵相乘,实现不断地降维或者升维,不断增加模型的复杂性,但必须要保证输入和输出的维度与数据集一致
矩阵
→
\to
→ 空间变换的函数
在多层神经网络里,每一层通过对线性模型增加非线性因子,即激活函数,实现非线性的变换

但同时,还不能过多的增加层数,因为层数越多,学习能力越强,可能会更多地学习到数据中的噪声,使模型不具有较强的泛化能力
对于每层的输出,一般是要进行超参数搜索,寻找最优的组合
在此次代码实践中,采用如下组合:
- 第一层实现8维向6维的非线性转换
- 第二层实现6维向4维的非线性转换
- 第三层实现4为向1维的非线性转换
self.linear1 = torch.nn.Linear(8, 6)
self.linear2 = torch.nn.Linear(6, 4)
self.linear3 = torch.nn.Linear(4, 1)

使用多层神经网络对糖尿病数据集进行分类
三层神经网络全部采用Sigmoid
import torch
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
######### 数据集的准备 ##########
xy = np.array(pd.read_csv("./dataset/diabetes.csv"))
x_data = torch.Tensor(xy[:, :-1]) # 最后一列不要
y_data = torch.Tensor(xy[:, [-1]]) # 加入中括号[]保证拿出来的是一个矩阵
########### 模型定义 ###########
class Model(torch.nn.Module):
def __init__(self):
super(Model, self).__init__()
self.linear1 = torch.nn.Linear(8, 6)
self.linear2 = torch.nn.Linear(6, 4)
self.linear3 = torch.nn.Linear(4, 1)
self.sigmoid = torch.nn.Sigmoid() # 将sigmoid单独作为一层
# 因此要实例化
def forward(self, x):
## 注意书写习惯 要始终用x
x = self.sigmoid(self.linear1(x))
x = self.sigmoid(self.linear2(x))
x = self.sigmoid(self.linear3(x))
return x
model = Model()
########### 定义损失函数和优化器 ###########
criterion = torch.nn.BCELoss(reduction='mean')
optimizer = torch.optim.SGD(model.parameters(), lr = 0.01)
########## 模型训练 ###########
loss_history = []
epoch_history = []
for epoch in range(10000):
y_pred = model(x_data)
loss = criterion(y_pred, y_data)
print(epoch, loss.item())
epoch_history.append(epoch)
loss_history.append(loss.item())
optimizer.zero_grad()
loss.backward()
optimizer.step()
plt.plot(epoch_history, loss_history)
plt.xlabel('epoch')
plt.ylabel("loss")
plt.grid()
plt.show()
注意:
- 这里把
Sigmoid单独作为了神经网络的一层,而不是简单的函数的使用 - 损失函数使用样本
BCE损失的平均值,即criterion = torch.nn.BCELoss(reduction='mean')
最终每一步的损失如下所示:

前两层神经网络使用Relu,最后一层使用Sigmoid
考虑到最后的平均损失为0.64+,不是特别理想,因此改变模型,增加模型的非线性程度
将前两层神经网络使用Relu作为激活函数,最后一层使用Sigmoid
模型改变如下:
class Model(torch.nn.Module):
def __init__(self):
super(Model, self).__init__()
self.linear1 = torch.nn.Linear(8, 6)
self.linear2 = torch.nn.Linear(6, 4)
self.linear3 = torch.nn.Linear(4, 1)
self.sigmoid = torch.nn.Sigmoid() # 将sigmoid单独作为一层
# 因此要实例化
self.activate = torch.nn.ReLU() # 增加Relu激活函数
def forward(self, x):
## 注意书写习惯 要始终用x
x = self.activate(self.linear1(x))
x = self.activate(self.linear2(x))
x = self.sigmoid(self.linear3(x))
return x
整体代码:
import torch
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
######### 数据集的准备 ##########
xy = np.array(pd.read_csv("./dataset/diabetes.csv"))
x_data = torch.Tensor(xy[:, :-1]) # 最后一列不要
y_data = torch.Tensor(xy[:, [-1]]) # 加入中括号[]保证拿出来的是一个矩阵
########### 模型定义 ###########
class Model(torch.nn.Module):
def __init__(self):
super(Model, self).__init__()
self.linear1 = torch.nn.Linear(8, 6)
self.linear2 = torch.nn.Linear(6, 4)
self.linear3 = torch.nn.Linear(4, 1)
self.sigmoid = torch.nn.Sigmoid() # 将sigmoid单独作为一层
# 因此要实例化
self.activate = torch.nn.ReLU()
def forward(self, x):
## 注意书写习惯 要始终用x
x = self.activate(self.linear1(x))
x = self.activate(self.linear2(x))
x = self.sigmoid(self.linear3(x))
return x
model = Model()
########### 定义损失函数和优化器 ###########
criterion = torch.nn.BCELoss(reduction='mean')
optimizer = torch.optim.SGD(model.parameters(), lr = 0.01)
########## 模型训练 ###########
loss_history = []
epoch_history = []
for epoch in range(10000):
y_pred = model(x_data)
loss = criterion(y_pred, y_data)
print(epoch, loss.item())
epoch_history.append(epoch)
loss_history.append(loss.item())
optimizer.zero_grad()
loss.backward()
optimizer.step()
plt.plot(epoch_history, loss_history)
plt.xlabel('epoch')
plt.ylabel("loss")
plt.grid()
plt.show()
最终损失收敛到0.475左右

2178

被折叠的 条评论
为什么被折叠?



