PyTorch 入门与实践(二)处理多维特征的输入

来自 B 站刘二大人的《PyTorch深度学习实践》P7 的学习笔记

回顾

上一篇逻辑斯蒂回归中,分类的最终结果是输出概率对应的分类,是离散的集合,虽然神经网络预测的概率的分布拟合的是 Sigmoid,但这些概率是用于决策分类的,类别是离散的集合;

而线性回归的输出结果是实数集,它们拟合目标函数。
1

数据表示

对于关系型数据表,在 PyTorch 中读取时是以下面的方式表示的:

  • 一行是一个 Sample(样本):
    2
  • 一列是一个 Feature(特征):
    3
多维数据

需要转换成矩阵运算
4

  • Mini-Batch(N Samples)

    得益于 PyTorch Tensor 的矩阵广播能力,我们可以很轻松地构建矩阵输入进行 Mini-Batch 运算:
    5
    由于输入的矩阵特征维度(列数)增加了,从上一章的 N × 1 N \times 1 N×1 变成了 N × 8 N \times 8 N×8 ,我们在模型 Linear 层中也需要更改相应参数:
    6

  • Linear Layer

    torch.nn.Linear(in_features, out_features)

    对输入数据应用线性变换: y = x ⋅ A T + b y = x \cdot A^T+b y=xAT+b

    • 输入维度: ( N , ∗ , H i n ) (N, *, H_{in}) (N,,Hin)* 表示 sample 数(行数), H i n = H_{in} = Hin= in_features
    • 输出维度: ( N , ∗ , H o u t ) (N, *, H_{out}) (N,,Hout)。除了最后一个维度外,其他所有维度都与输入的形状相同, H o u t = H_{out} = Hout= out_features

    Examples:

    >>> m = nn.Linear(20,30)
    >>> input = torch.randn(128,20)
    >>> output = m(input)
    >>> print(output.size())
    torch.size([128,30])
    

    对于以下矩阵,每一行是一个 sample,size of each sample 表示一行的大小,也即列数(Feature):7
    所以说神经网络可以做空间变换, σ ( ⋅ ) \sigma(\cdot) σ() 提供了非线性变换:
    8

神经网络构造

多个非线性变换的链接可以拟合更复杂的函数,网络层的输出可降维也可升维,是升是降,这是超参数的哲学。
9
这里老师即兴穿插读书的哲学 🐶 :
10
三层 Linear Layer 构建的神经网络:
11
代码与计算图一一对应,一目了然
在这里插入图片描述

试验不同的激活函数

不同的激活函数的输出区间不同,由于我们最后要计算 log(x),x 不能为 0(ReLU 把小于 0 的都取为 0),所以要注意最后输出的仍然要经过 sigmoid()
在这里插入图片描述
经过测试的完整代码如下:

import copy

import numpy as np
import torch
from torch import nn, optim
from torch.nn import functional as F

xy = np.loadtxt("../datasets/diabetes/diabetes.csv.gz", delimiter=",", dtype=np.float32)
# 除了最后一列,都是 x_data
x_data = torch.from_numpy(xy[:, :-1])
# 只取最后一列,得到 759 × 1 的矩阵,若是这样取 xy[:, -1],则是 1 × 759 的向量
y_data = torch.from_numpy(xy[:, [-1]])


class Model(nn.Module):
    def __init__(self):
        super(Model, self).__init__()
        self.linear1 = nn.Linear(8, 6)
        self.linear2 = nn.Linear(6, 4)
        self.linear3 = nn.Linear(4, 1)
        
        # 可以任意选择一个激活函数,当然还有更多
        self.activate = nn.Sigmoid()
        # self.activate = nn.Tanh()
        # self.activate = nn.ReLU()
        # self.activate = nn.LeakyReLU()
        # self.activate = nn.CELU()
        # self.activate = nn.Softplus()

    def forward(self, x):
        x = self.activate(self.linear1(x))
        x = self.activate(self.linear2(x))
        x = F.sigmoid((self.linear3(x)))
        return x


model = Model()

criterion = nn.BCELoss()
optimizer = optim.Adam(model.parameters(), lr=0.03)  # SGD 的效果很不好,我换成了 Adam

npz_dict = {"loss": [], "acc": []}  # 用于保存 loss 和 acc 数值,便于后面可视化比较

for epoch in range(1000):
    # forward
    y_pred = model(x_data)
    loss = criterion(y_pred, y_data)

    # 我添加了训练过程中的精度测试
    y_pred_hat = copy.copy(y_pred.data.numpy())
    y_pred_hat[y_pred_hat >= 0.5] = 1.0
    y_pred_hat[y_pred_hat < 0.5] = 0.0
    acc = np.sum(y_pred_hat.flatten() == y_data.data.numpy().flatten()) / len(y_data)
    print("epoch:", epoch, "loss:", loss.item(), "acc:", acc)

    # 持久化数值
    npz_dict["loss"].append(loss.item())
    npz_dict["acc"].append(acc)

    # backward
    optimizer.zero_grad()
    loss.backward()

    # update
    optimizer.step()

np.savez("./npz_file/sigmoid.npz", loss = npz_dict["loss"], acc = npz_dict["acc"])  # 保存数值

注意我们虽然输入训练的是多维特征的数据,但是我们实际上还没有用 Mini-Batch 来训练,这部分详细内容在下一篇:PyTorch 加载数据集(Dataset、DataLoader)
在这里插入图片描述

读取 npz 文件得到数值后绘图结果如下:
在这里插入图片描述
读取文件的绘图函数如下:

import numpy as np
import matplotlib.pyplot as plt


def draw(name, title="acc"):
    loss_acc = np.load(f"./npz_file/{name}.npz")
    y = loss_acc[f"{title}"]
    x = np.arange(len(y))
    plt.plot(x, y, label=f"best:{max(y)}" if title == "acc" else None)

    plt.title(title)
    plt.xlabel("x")
    plt.ylabel(name)
    plt.legend()
    plt.grid()
    plt.show()


filename = ["sigmoid", "relu", "leakyrelu", "tanh", "softplus"]

draw(filename[0], title="acc")  # title = "loss" 或 "acc"

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Skr.B

WUHOOO~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值