跳转至

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

image-20210302173422666

原模型改进

前篇中,单维度逻辑回归模型为

$$ \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()) ```

微信截图_20220926103003

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