新手小白的pytorch学习第八弹------分类问题模型和简单预测

这篇是接着新手小白的pytorch学习第七弹------分类问题模型这一篇的,代码也是哟~

1 启动损失函数和优化器

对于我们的二分类问题,我们经常使用 binary cross entropy 作为损失函数
可以使用torch.optim.SGD()torch.optim.Adam() 作为优化器

有两个 binary cross entropy 函数

  1. torch.nn.BCELoss()-在label(target)和features(input)之间进行衡量
  2. torch.nn.BCEWithLogitsLoss()-这个和上面这个一样,不过它有一个sigmoid嵌入层(nn.Sigmoid)[之后我们会看这个方式的]

下面我们会创建损失函数和优化器,优化器我们使用SGD,优化器使用模型的参数,学习率为0.1

import torch.nn as nn
import torch.optim as optim
# 创建一个损失函数
loss_fn = nn.BCEWithLogitsLoss() # 嵌入sigmoid()函数

# 创建一个优化器
optimizer = optim.SGD(params=model_0.parameters(),
                      lr=0.1)

我们再引入一个新的东西,评估标准,它也可以像损失函数一样,来衡量你的模型怎么样。毕竟使用多个角度来衡量模型,能够让模型更加的公正客观。Accuracy准确度,可以看出在总样本中正确样本的数量,所以100%是最好的,毕竟我们期望它全部预测对,对吧。

# 创建一个计算准确率的accuracy函数
def accuracy_fn(y_true, y_pred):
    correct = torch.eq(y_true, y_pred).sum().item() # torch.eq()计算两个相同的张量
    acc = (correct/len(y_pred))*100
    return acc

现在我们可以使用这个函数来衡量我们的模型啦。

2 训练模型

这里使用的损失函数是nn.BCEWithLogits(),因此这个损失函数的输入是logits.
什么是logits呢,我的理解就是我们的模型输出的原始值,不经过处理的值,由于这个损失函数是有一个torch.sigmoid()函数的,所以数据的转换有三个步骤:logits -> prediction probability -> prediction labels

# 查看测试数据的前5个输出
with torch.inference_mode():
    y_logits = model_0(X_test.to(device))[:5]
y_logits

tensor([[0.6003],
[0.6430],
[0.5095],
[0.6260],
[0.5431]], device=‘cuda:0’)

因为我们的模型没有被训练,因此这些输出都是随机的。
并且我们模型的原始输出是logits,这些数字难以解释,我们需要能够和真实数据相比较的数据。
我们可以使用torch.sigmoid()激活函数来将数据转换为我们需要的形式.

# 使用 torch.sigmoid() 激活函数
y_pred_probs = torch.sigmoid(y_logits)
y_pred_probs

tensor([[0.6457],
[0.6554],
[0.6247],
[0.6516],
[0.6325]], device=‘cuda:0’)

y_pred_probs 现在是 prediction probability 预测概率的形式,概率就是有多大的可能,有多大的几率。在我们的情况中,我们理想的输出是0或1,所以这些值可以被看做一个决定的边界。比如说值越靠近零,那模型就将这个样本分类为0, 值越接近1,模型就将这个样本分类为1.

更具体地说:
if y_pred_probs >= 0.5, y=1(class 1)
if y_pred_probs < 0.5, y=0(class 0)

将预测概率转变成预测标签,我们四舍五入torch.sigmoid()函数的输出即可

# 将概率转变为标签
y_preds = torch.round(y_pred_probs)

# 将刚才的过程连起来放在一起
y_preds_labels = torch.round(torch.sigmoid(model_0(X_test.to(device))[:5]))

# 查看预测值和标签相等
print(torch.eq(y_preds.squeeze(), y_preds_labels.squeeze()))

# 去掉额外的维度
y_preds.squeeze()

tensor([True, True, True, True, True], device=‘cuda:0’)
tensor([1., 1., 1., 1., 1.], device=‘cuda:0’)

y_test[:5]

y_test[:5]

创建训练和测试循环

# 设置随机种子,有利于代码的复现
torch.manual_seed(42)

epochs = 100

# 将数据放到指定的设备上
X_train, y_train = X_train.to(device), y_train.to(device)
X_test, y_test = X_test.to(device), y_test.to(device)

# 创建训练和测试循环
for epoch in range(epochs):
    # 进入训练模式
    model_0.train()
    
    # 预测
    y_logits = model_0(X_train).squeeze()
    y_pred_prob = torch.sigmoid(y_logits)
    y_pred = torch.round(y_pred_prob)
    
    # 计算损失函数和准确率
    loss = loss_fn(y_logits, 
                   y_train)
    acc = accuracy_fn(y_true = y_train, 
                      y_pred = y_pred)
    
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()
    
    # 测试
    model_0.eval()
    with torch.inference_mode():
        test_logits = model_0(X_test).squeeze()
        test_pred = torch.round(torch.sigmoid(test_logits))
        test_loss = loss_fn(test_logits, 
                            y_test)
        test_acc = accuracy_fn(y_true = y_test,
                               y_pred = test_pred)
    
    # 打印出内容
    if epoch % 10 == 0:
        print(f"Epoch:{epoch} | Loss:{loss:.5f} | Accuracy:{acc:.2f}% | Test loss:{test_loss:.2f} | Test accuracy:{test_acc:.2f}%")

Epoch:0 | Loss:0.69313 | Accuracy:51.75% | Test loss:0.69 | Test accuracy:48.50%
Epoch:10 | Loss:0.69310 | Accuracy:51.75% | Test loss:0.69 | Test accuracy:48.00%
Epoch:20 | Loss:0.69308 | Accuracy:51.25% | Test loss:0.69 | Test accuracy:49.00%
Epoch:30 | Loss:0.69307 | Accuracy:50.75% | Test loss:0.69 | Test accuracy:48.00%
Epoch:40 | Loss:0.69306 | Accuracy:50.38% | Test loss:0.69 | Test accuracy:48.00%
Epoch:50 | Loss:0.69305 | Accuracy:51.12% | Test loss:0.69 | Test accuracy:47.50%
Epoch:60 | Loss:0.69304 | Accuracy:51.12% | Test loss:0.69 | Test accuracy:48.00%
Epoch:70 | Loss:0.69303 | Accuracy:50.75% | Test loss:0.69 | Test accuracy:47.50%
Epoch:80 | Loss:0.69303 | Accuracy:50.75% | Test loss:0.69 | Test accuracy:47.00%
Epoch:90 | Loss:0.69303 | Accuracy:50.38% | Test loss:0.69 | Test accuracy:46.50%

通过上面的数据,损失函数几乎没变化,精确度50%左右,感觉模型啥也没有学到,这就意味着它分类是随机的

3 预测和评估模型

从上面的数据,感觉我们的模型好像是随机猜测,我们来可视化一下看看究竟是怎么个事儿。

我们接着会写代码下载并导入helper_functions.py script来自Learn PyTorch for Deep Learning repo.

在这里有一个叫做 plot_decision_boundary() 的函数,它来可视化我们模型的分类的不同的点

我们也会导入我们在 01 中自己写的 plot_predictions()

import requests
from pathlib import Path
# 从仓库下载文档
if Path("helper_functions.py").is_file():
    print("helper_functions.py already exists, skipping download")
else:
    print("Downloading helper_functions.py")
    request = requests.get("https://raw.githubusercontent.com/mrdbourke/pytorch-deep-learning/main/helper_functions.py")
    with open("helper_functions.py", "wb") as f:
        f.write(request.content)

from helper_functions import plot_predictions, plot_decision_boundary

Downloading helper_functions.py

这里可能需要科学上网,我把文件helper_functions.py的代码放到文末了,可以自己创建一个.py文件粘进去。

plt.figure(figsize=(12, 6))
plt.subplot(1, 2, 1)
plt.title("Train")
plot_decision_boundary(model_0, X_train, y_train)
plt.subplot(1, 2, 2)
plt.title("Test")
plot_decision_boundary(model_0, X_test, y_test)

在这里插入图片描述
看中间这条白色的线,模型是通过这条直线来区分红色和蓝色的点,所以是50%的准确率,明显是不对的,因为我们的数据明显是圈圈。

从机器学习的方面看,我们的模型欠拟合(underfitting),即没有从数据中学习到数据的模式.

那我们如何改善呢?请听下回分解

终于把今天的学习整理出来了,BB啊,今天中午吃了个超级物美价廉的套餐,里面的土豆炖牛腩和我平常吃的不一样,它这个带汤,尊嘟很好吃,熏过的香干一定要尝尝啊,皮蛋也很八错。还喝了一杯瑞幸的美式,一般般吧,室友说苦,我就喜欢喝这种苦苦的,嘻嘻嘻。

师姐通过一个电话说我喜欢一个男孩子,就说我喜欢他,哈哈哈哈,不知道咋听出来的,乌龙可是闹大了呢,话说,我们见面次数确实不多,但听到她的声音,莫名有点想她了,晚上就是多愁善感啊,别管我!

BB啊,今天就到这吧,不敢想象明天的学习有多开心,终于到了要改善模型啦~

如果文章对您有帮助的话,记得给俺点个呐!

靴靴,谢谢~

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-21 03:38:02       52 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-21 03:38:02       54 阅读
  3. 在Django里面运行非项目文件

    2024-07-21 03:38:02       45 阅读
  4. Python语言-面向对象

    2024-07-21 03:38:02       55 阅读

热门阅读

  1. Hi6278

    Hi6278

    2024-07-21 03:38:02      21 阅读
  2. 安装archlinux

    2024-07-21 03:38:02       18 阅读
  3. 如何通过结构体来观察内存对齐和填充

    2024-07-21 03:38:02       15 阅读
  4. cd命令学习

    2024-07-21 03:38:02       20 阅读
  5. git rebase 和 git merge区别

    2024-07-21 03:38:02       16 阅读
  6. go语言的基础语法

    2024-07-21 03:38:02       16 阅读
  7. 华为OD机试(C卷+D卷)2024真题目录

    2024-07-21 03:38:02       18 阅读
  8. docker 安装 使用 ubuntu

    2024-07-21 03:38:02       20 阅读