有一糖尿病数据集,在文件中,每个样本(sample)有8个维度的信息(feature),并以此进行二分类。

原模型改进
前篇中,单维度逻辑回归模型为
$$ \widehat y^{(i)} = \sigma(x^{(i)} \omega+b) $$
其中的
$$ x^{(i)} $$
表示第i个样本的维度,对于多维度,输入要变为8个维度的输入因此,模型应当变为
$$ \widehat y^{(i)} = \sigma(\sum _{n=1}^8 x^{(i)}_n \omega _n+b) $$
其中的
$$ x^{(i)}_n $$
表示第i个样本的第n个维度。由于在实际代码运算中是以矩阵进行计算的,因此其中
$$ \sum _{n=1}^8 x^{(i)}_n \omega _n = \begin{bmatrix} {x_1^{(i)}}&{\cdots}&{x_8^{(i)}} \end{bmatrix} \begin{bmatrix} {w_1}\ {\vdots}\ {w_8} \end{bmatrix} $$
则原式可以表示成
$$ \widehat y^{(i)} = \sigma( \begin{bmatrix} {x_1^{(i)}}&{\cdots}&{x_8^{(i)}} \end{bmatrix} \begin{bmatrix} {w_1}\ {\vdots}\ {w_8} \end{bmatrix}+b)\ =\sigma(z^{(i)}) $$
pytorch中的sigmoid函数,是一种按向量计算的函数。即
$$ \begin{bmatrix} {\widehat y^{(1)}}\ {\vdots}\ {\widehat y^{(N)}} \end{bmatrix} = \begin{bmatrix} {\sigma(z^{(1)})}\ {\vdots}\ {\sigma(z^{(N)})} \end{bmatrix} =\sigma( \begin{bmatrix} {z^{(1)}}\ {\vdots}\ {z^{(N)}} \end{bmatrix}) $$
其中
$$ z^{(i)} = \begin{bmatrix} {x_1^{(i)}}&{\cdots}&{x_8^{(i)}} \end{bmatrix} \begin{bmatrix} {w_1}\ {\vdots}\ {w_8} \end{bmatrix}+b\ $$
则
$$ \begin{bmatrix} {z^{(1)}}\ {\vdots}\ {z^{(N)}} \end{bmatrix} = \begin{bmatrix} {x_1^{(1)}} & {\cdots} & {x_8^{(1)}}\ {\vdots} & {\vdots} & {\vdots}\ {x_1^{(N)}} & {\cdots} & {x_8^{(N)}}\ \end{bmatrix} \begin{bmatrix} {w_1}\ {\vdots}\ {w_8} \end{bmatrix} + \begin{bmatrix} {b}\ {\vdots}\ {b} \end{bmatrix} $$
整体上将原先的标量运算,转换为矩阵运算,以方便进行并行计算,提高算法效率。
网络增加
矩阵实质上是一种空间变换的函数
按照原先的代码思路,只需要将Linear()中的参数改成下面代码,即可完成从8维输入到1位输出的过程。
python
self.linear = torch.nn.Linear(8,1)
同时,也可以将输出的部分转换为其他维度,来实现分布的维度下降,比如8维转6维,6维转4维,4维转1维,由此可以增加网络层数,增加网络复杂度。同理,对网络结构先增后减也是可以的。
理论上来说网络层数越多,网络越复杂,学习能力越强。但是太强会导致过拟合,需要找到一个泛化能力和拟合能力的平衡点。
所以,网络的层数和维度数需要超参数搜索。
代码部分
```python import torch import numpy as np
读取文件,一般GPU只支持32位浮点数
xy = np.loadtxt('diabetes.csv', delimiter=',', dtype = np.float32)
-1行-1列不取
x_data = torch.from_numpy(xy[:-1, :-1])
单取-1列作为矩阵
y_data = torch.from_numpy(xy[:-1, [-1]])
取-1行的测试集部分
test_data = torch.from_numpy(xy[[-1], :-1]) pred_test = torch.from_numpy(xy[[-1],[-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()
def forward(self, 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.1)
for epoch in range(1000): #Forward 并非mini-batch的设计,只是mini-batch的风格 y_pred = model(x_data) loss = criterion(y_pred,y_data) print(epoch, loss.item())
#Backward
optimizer.zero_grad()
loss.backward()
#Update
optimizer.step()
print("test_pred = ", model(test_data).item()) print("infact_pred = ", pred_test.item()) ```

本文参考自B站《PyTorch深度学习实践》P7