PyTorch Logistics

逻辑斯蒂回归(刘二大人PyTorch第六讲)

上节的内容是回归,这节的内容是分类。
回归与分类的区别
     * 回归的目标是预测一个连续的数值。性输出的是一个具体的数值。可以使用均方误差(MSE)、平均绝对误差(MAE)等进行评估,通过最小化预测值\hat{y}与真实值y之间的距离优化模型。
     * 分类的目标是将数据划分到不同的离散的类别中。输出是属于某个类别的概率。可以使用交叉熵损失函数(Cross-Entropy Loss)、0-1损失函数等进行评估,不同于回归的是,分类计算的是概率分布之间的差异。


  1. 数据准备
    关于数据集:
    torchvision库中自带MNIST数据集、CIFAR数据集,调用时使用torchvision.datasets.来调用。如下:
import torchvision
train_set = torchvision.datasets.MINIST(root='../dataset/mnist', train=True, download=True)
test_set = torchvision.datasets.MINIST(root='../dataset/mnist', train=False, download=True)
  1. 模型构建
    不同于上一讲中线性模型的是,二分类问题需要将线性模型输出的具体数值转换为0-1之间的概率。即,我们需要找到一个函数(Sigmoid函数),能够把输出的实数映射到0-1之间。
    显性地来看,二分类模型是在线性模型的输出后添加了Sigmoid函数。
    二分类模型可以表示为:\hat{y}=\sigma(x*\omega+b)
    Sigmoid函数调用方式:
import torch.nn.functional as F
F.sigmoid(...)
  1. 损失函数
    分类任务输出的是分布,二分类输出的\hat{y}表示p(class=1),则1-\hat{y}表示的是p(class=0)。
    二分类任务常用的损失函数:二分类交叉熵损失函数:
    loss=-(ylog\hat{y}+(1-y)log(1-\hat{y}))
    优化器:SGD
import torch
criterion = torch.nn.BCELoss(size_average=False)   #损失,实例化一个可调用的对象,需要输入的参数为(y_pred,y)
optimizer = torch.optim.SGD(model.parameters(),lr=0.01)   # 使用随机梯度下降优化函数
  1. 训练单元
for epoch in range(1000):
    optimizer.zero_grad()   # 梯度清零
    y_pred = model(x_data)   #计算预测值,用于计算损失
    loss = criterion(y_pred, y_data)   #传入(y_pred,y_data),用于计算损失
    loss.backward()    # loss反向传播
    optimizer.step()    # 梯度更新

整体代码:

import torch
import torch.nn.functional as F
import numpy as np
import matplotlib.pyplot as plt


# 1.准备数据
x_data = torch.Tensor([[1.0],[2.0],[3.0]])
y_data = torch.Tensor([[0],[0],[1]])

# 2.设计模型
class LogisticRegressionModel(torch.nn.Module):
    def __init__(self):
        super(LogisticRegressionModel,self).__init__()
        self.linear = torch.nn.Linear(1,1)

    def forward(self,x):
        y_pred = F.sigmoid(self.linear(x))
        return y_pred
# 模型实例化
model = LogisticRegressionModel()

# 3.设计损失(损失函数实例化),设计优化器
criterion = torch.nn.BCELoss(size_average=False)
optimizer = torch.optim.SGD(model.parameters(),lr=0.01) 

# 4.训练
for epoch in range(1000):
    optimizer.zero_grad()   # 梯度清零
    y_pred = model(x_data)  # 计算预测值
    loss = criterion(y_pred,y_data)  # 计算损失
    print(epoch, loss.item())

    loss.backward()  # loss反向传播
    optimizer.step()  # 梯度更新
    
# 测试
z= torch.Tensor([[4]])
print('z',model(z))

x = np.linspace(0,10,200)    # 生成一个0-10之间均匀分布的包含200个点的一维numpy数组
x_t = torch.Tensor(x).view((200,1))  # 将numpy数组转换为PyTorch张量,并将其形状重塑为(200,1)
y_t = model(x_t)  # 将重塑后的张量作为输入传递给model进行预测
y = y_t.data.numpy()   # 从预测结果中提取数据,转换为numpy数组

plt.plot(x,y)
plt.plot([0,10],[0.5,0.5],c='r')
plt.xlabel('hours')
plt.ylabel('Probaility of Pass')
plt.grid()
plt.show()

输出结果:

0 2.375955820083618
1 2.3335862159729004
2 2.293276071548462
...
998 0.9634450078010559
999 0.9630558490753174
z tensor([[0.8957]], grad_fn=<SigmoidBackward0>)

Figure_1.png

补充:
关于.item().data()
.data()用于获取张量的数据部分,同时将其从计算图中分离出来,后续对这个数据进行的操作不会影响原张量的梯度计算。适用于不需要跟踪梯度的场景下使用,如推理阶段,只关心模型的输出结果而不需要计算梯度,使用 .data 可以避免不必要的梯度计算,提高效率。不过在新的 PyTorch 版本中,更推荐使用 .detach() 方法,因为 .data 在一些复杂的梯度计算场景下可能会引发意外问题。返回值是一个新的张量,其数据与原张量相同,但没有梯度信息。
.item()用于从包含一个元素的张量中提取该元素的值,并将其转换为Python的基本数据类型(如‘float’或‘int’)。返回的是 Python 的基本数据类型,如 floatint,不再是张量对象,不能再进行张量操作,只能进行 Python 原生的数学运算等操作。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容