深度学习分类回归(衣帽数据集)

一、步骤

1 加载数据集fashion_minst

2 搭建class NeuralNetwork模型

3 设置损失函数,优化器

4 编写评估函数

5 编写训练函数

6 开始训练

7 绘制损失,准确率曲线

二、代码

导包,打印版本号:

import matplotlib as mpl
import matplotlib.pyplot as plt
%matplotlib inline
import numpy as np
import sklearn
import pandas as pd
import os
import sys
import time
from tqdm.auto import tqdm
import torch
import torch.nn as nn
import torch.nn.functional as F

print(sys.version_info)
for module in mpl, np, pd, sklearn, torch:
    print(module.__name__, module.__version__)
    
device = torch.device("cuda:0") if torch.cuda.is_available() else torch.device("cpu")
print(device)

torch的运算过程都是张量,也叫算子(tensor)

torchvision的包可以提供数据集,图片就是datasets:

这里下载到data目录,如果已有数据则不会下载。这段代码可以实现数据向tensor的转换:

做预处理的时候把图片变成tensor,啥都没写的时候就不会转换成tensor 

from torchvision import datasets
from torchvision.transforms import ToTensor
from torchvision import transforms


# 定义数据集的变换
transform = transforms.Compose([
])
# fashion_mnist图像分类数据集,衣服分类,60000张训练图片,10000张测试图片
train_ds = datasets.FashionMNIST(
    root="data",
    train=True,
    download=True,
    transform=transform
)

test_ds = datasets.FashionMNIST(
    root="data",
    train=False,
    download=True,
    transform=transform
)

# torchvision 数据集里没有提供训练集和验证集的划分
# 当然也可以用 torch.utils.data.Dataset 实现人为划分
type(train_ds[0]) # 元组,第一个元素是图片,第二个元素是标签

如果使用了数据类型变换:

img_tensor, label = train_ds[0]
img_tensor.shape  #img这时是一个tensor,shape=(1, 28, 28)

在PyTorch中,DataLoader是一个迭代器,它封装了数据的加载和预处理过程,使得在训练机器学习模型时可以方便地批量加载数据。DataLoader主要负责以下几个方面:

  1. 批量加载数据DataLoader可以将数据集(Dataset)切分为更小的批次(batch),每次迭代提供一小批量数据,而不是单个数据点。这有助于模型学习数据中的统计依赖性,并且可以更高效地利用GPU等硬件的并行计算能力。

  2. 数据打乱:默认情况下,DataLoader会在每个epoch(训练周期)开始时打乱数据的顺序。这有助于模型训练时避免陷入局部最优解,并且可以提高模型的泛化能力。

  3. 多线程数据加载DataLoader支持多线程(通过参数num_workers)来并行地加载数据,这可以显著减少训练过程中的等待时间,尤其是在处理大规模数据集时。

  4. 数据预处理DataLoader可以与transforms结合使用,对加载的数据进行预处理,如归一化、标准化、数据增强等操作。

  5. 内存管理DataLoader负责管理数据的内存使用,确保在训练过程中不会耗尽内存资源。

  6. 易用性DataLoader提供了一个简单的接口,可以很容易地集成到训练循环中。

# 从数据集到dataloader
train_loader = torch.utils.data.DataLoader(train_ds, batch_size=32, shuffle=True) #batch_size分批,shuffle洗牌
val_loader = torch.utils.data.DataLoader(test_ds, batch_size=32, shuffle=False)

这里每32个样本就会算一次平均损失,更新一次w。

定义模型:继承nn.Module

class NeuralNetwork(nn.Module):
    def __init__(self):
        super().__init__() # 继承父类的初始化方法,子类有父类的属性
        self.flatten = nn.Flatten()  # 展平层
        self.linear_relu_stack = nn.Sequential(
            nn.Linear(784, 300),  # in_features=784, out_features=300, 784是输入特征数,300是输出特征数
            nn.ReLU(), # 激活函数
            nn.Linear(300, 100),#隐藏层神经元数100
            nn.ReLU(), # 激活函数
            nn.Linear(100, 10),#输出层神经元数10 
        )

    def forward(self, x): # 前向计算,前向传播
        # x.shape [batch size, 1, 28, 28],1是通道数
        x = self.flatten(x)  
        # print(f'x.shape--{x.shape}')
        # 展平后 x.shape [batch size, 784]
        logits = self.linear_relu_stack(x)
        # logits.shape [batch size, 10]
        return logits #没有经过softmax,称为logits
    
model = NeuralNetwork()

model的结构:第一层是展平层,然后激活,然后隐藏层,激活,输出层


 在训练之前需要测试一下模型能不能用,所以我们随机一个或者从样本拿一个,同尺寸就行:

#为了查看模型运算的tensor尺寸
x = torch.randn(32, 1, 28, 28)
print(x.shape)
logits = model(x) # 把x输入到模型中,得到logits
print(logits.shape)

 然后开始训练,pytorch的训练需要自行实现,包括定义损失函数、优化器、训练步,训练

# 1. 定义损失函数 采用交叉熵损失
loss_fct = nn.CrossEntropyLoss() #内部先做softmax,然后计算交叉熵
# 2. 定义优化器 采用SGD
# Optimizers specified in the torch.optim package,随机梯度下降
optimizer = torch.optim.SGD(model.parameters(), lr=0.001, momentum=0.9)
from sklearn.metrics import accuracy_score # sk里面有一个算子,可以计算准确率

@torch.no_grad() # 装饰器,禁止反向传播,节省内存,就是不求导的意思
def evaluating(model, dataloader, loss_fct): # 评估函数,评估也要做一次向前计算,不需要求梯度
    loss_list = [] # 记录损失
    pred_list = [] # 记录预测
    label_list = [] # 记录标签
    for datas, labels in dataloader:#10000/32=312
        datas = datas.to(device) # 转到GPU
        labels = labels.to(device) # 转到GPU 这两行代码torch必写,把tensor放到GPU上
        # 前向计算
        logits = model(datas)  # 进行前向计算
        loss = loss_fct(logits, labels)         # 验证集损失,loss尺寸是一个数值
        loss_list.append(loss.item()) # 记录损失,item是把tensor转换为数值
        
        preds = logits.argmax(axis=-1)    # 验证集预测,argmax返回最大值索引,-1就是最后一个维度
        print(f'评估中的preds.shape--{preds.shape}')
        pred_list.extend(preds.cpu().numpy().tolist())#将PyTorch张量转换为NumPy数组。只有当张量在CPU上时,这个转换才是合法的
        # print(preds.cpu().numpy().tolist())
        label_list.extend(labels.cpu().numpy().tolist())
        
    acc = accuracy_score(label_list, pred_list) # 计算准确率
    return np.mean(loss_list), acc
# 训练
def training(model, train_loader, val_loader, epoch, loss_fct, optimizer, eval_step=500):
    #参数分别是模型,训练集,验证集,训练epoch,损失函数,优化器,评估步数(500评估一次)
    record_dict = { # 记录字典,用于记录训练过程中的信息
        "train": [],
        "val": []
    }
    
    global_step = 0 # 全局步数,记录训练的步数
    model.train() # 进入训练模式,模型可以切换模式
    #tqdm是一个进度条库
    with tqdm(total=epoch * len(train_loader)) as pbar: # 进度条 加入epoch等于10,就是所有样本搞10次,不断地把样本带进去学习,1875*10,60000/32=1875
        for epoch_id in range(epoch): # 训练epoch次
            # training
            for datas, labels in train_loader: #执行次数是60000/32=1875
                datas = datas.to(device) #datas尺寸是[batch_size,1,28,28]
                labels = labels.to(device) #labels尺寸是[batch_size]
                # 梯度清空
                optimizer.zero_grad() # 每次训练前都要把梯度清空,不然会累加
                # 模型前向计算
                logits = model(datas)
                # 计算损失
                loss = loss_fct(logits, labels)
                # 梯度回传,loss.backward()会计算梯度,loss对模型参数求导
                loss.backward()
                # 调整优化器,包括学习率的变动等,优化器的学习率会随着训练的进行而减小,更新w,b
                optimizer.step() #梯度是计算并存储在模型参数的 .grad 属性中,优化器使用这些存储的梯度来更新模型参数

                preds = logits.argmax(axis=-1) # 训练集预测
                acc = accuracy_score(labels.cpu().numpy(), preds.cpu().numpy())   # 计算准确率,numpy可以,每个step都算一次
                loss = loss.cpu().item() # 损失转到CPU,item()取值,一个数值
                # tensor如果只有一个值(标量),一维是向量,二维是矩阵,可以用item()取出值,如果有多个值,则需要用tolist()转为列表
                # record
                # record
                
                record_dict["train"].append({
                    "loss": loss, "acc": acc, "step": global_step
                }) # 记录训练集信息,每一步的损失,准确率,步数
                
                # evaluating
                if global_step % eval_step == 0:
                    model.eval() # 进入评估模式,不会求梯度
                    val_loss, val_acc = evaluating(model, val_loader, loss_fct)
                    record_dict["val"].append({
                        "loss": val_loss, "acc": val_acc, "step": global_step
                    })
                    model.train() # 进入训练模式

                # udate step
                global_step += 1 # 全局步数加1
                pbar.update(1) # 更新进度条
                pbar.set_postfix({"epoch": epoch_id}) # 设置进度条显示信息
        
    return record_dict
        

epoch = 20 #改为40
model = model.to(device)
record = training(model, train_loader, val_loader, epoch, loss_fct, optimizer, eval_step=1000)
#画线要注意的是损失是不一定在零到1之间的
def plot_learning_curves(record_dict, sample_step=1000):
    # build DataFrame
    train_df = pd.DataFrame(record_dict["train"]).set_index("step").iloc[::sample_step]
    val_df = pd.DataFrame(record_dict["val"]).set_index("step")
    last_step = train_df.index[-1] # 最后一步的步数
    # print(train_df.columns)
    print(train_df['acc'])
    print(val_df['acc'])
    # plot
    fig_num = len(train_df.columns) # 画几张图,分别是损失和准确率
    fig, axs = plt.subplots(1, fig_num, figsize=(5 * fig_num, 5))
    for idx, item in enumerate(train_df.columns):
        # print(train_df[item].values)
        axs[idx].plot(train_df.index, train_df[item], label=f"train_{item}")
        axs[idx].plot(val_df.index, val_df[item], label=f"val_{item}")
        axs[idx].grid() # 显示网格
        axs[idx].legend() # 显示图例
        axs[idx].set_xticks(range(0, train_df.index[-1], 5000)) # 设置x轴刻度
        axs[idx].set_xticklabels(map(lambda x: f"{int(x/1000)}k", range(0, last_step, 5000))) # 设置x轴标签
        axs[idx].set_xlabel("step")
    
    plt.show()

plot_learning_curves(record)  #横坐标是 steps

# dataload for evaluating

model.eval() # 进入评估模式
loss, acc = evaluating(model, val_loader, loss_fct)
print(f"loss:     {loss:.4f}\naccuracy: {acc:.4f}")

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/984946.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

共享经济时代下,鲲鹏共享科技如何逆袭改命?

2016年,当共享充电宝顶着“资本泡沫”的质疑横空出世时,没人能想到,这个曾被王思聪嘲讽“能成我吃翔”的行业,竟在短短几年内成为共享经济领域最顽强的幸存者。数据显示,2019年共享充电宝用户规模突破3亿,单…

说一下spring的事务隔离级别?

大家好,我是锋哥。今天分享关于【说一下spring的事务隔离级别?】面试题。希望对大家有帮助; 说一下spring的事务隔离级别? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 Spring的事务隔离级别是指在数据库事务管理中…

Web开发第五节

一.结构伪类选择器 (一)选择单个 (二)选择多个 注:1.n5指的是5以后的数字,包含5,n从0开始 2.-n5指的是5以前的数字,同样包含5,并且n从0开始 二.伪元素选择器 注&…

计算机毕业设计:驾校综合信息系统

驾校综合信息系统mysql数据库创建语句驾校综合信息系统oracle数据库创建语句驾校综合信息系统sqlserver数据库创建语句驾校综合信息系统springspringMVChibernate框架对象(javaBean,pojo)设计驾校综合信息系统springspringMVCmybatis框架对象(javaBean,pojo)设计 驾校综合信息系…

无标签数据增强+高效注意力GAN:基于CARLA的夜间车辆检测精度跃升

目录 一、摘要 二、引言 三、框架 四、方法 生成合成夜间数据 昼夜图像风格转换 针对夜间图像的无标签数据增强技术 五、Coovally AI模型训练与应用平台 六、实验 数据 图像风格转换 夜间车辆检测和分类 结论 论文题目:ENHANCING NIGHTTIME VEHICLE D…

RocketMQ面试题:原理部分

🧑 博主简介:CSDN博客专家,历代文学网(PC端可以访问:https://literature.sinhy.com/#/?__c1000,移动端可微信小程序搜索“历代文学”)总架构师,15年工作经验,精通Java编…

NAFNet:Simple Baselines for Image Restoration

Abstract 近年来,图像复原技术取得了长足的进步,但现有的图像复原方法(SOTA)系统复杂度也在不断增加,不利于对各种方法的分析和比较。在本文中,我们提出了一种简单的基线,它超越了SOTA方法&…

FlinkCDC3.3 使用 Mysql 8.4 报错

一、报错日志 Caused by: io.debezium.DebeziumException: org.apache.flink.util.FlinkRuntimeException: Cannot read the binlog filename and position via SHOW MASTER STATUS. Make sure your server is correctly configuredat org.apache.flink.cdc.connectors.mysql.…

汽车一键启动按钮更换注意事项

汽车一键启动开关更换教程 一键启动开关是现代汽车中常见的便捷配置,但随着时间的推移,这个部件可能会出现失灵的情况。当一键启动开关发生故障时,许多车主选择自行更换。以下是整理的一键启动开关更换教程: 更换前的准备 选择匹…

接入DeepSeek,九牧开启AI卫浴新赛道!

2025年或可被称为AI新纪元元年,“具身智能”“智能机器人”“6G”等新词语出现在《政府工作报告》里,国家对制造业转型和“人工智能”的发展提出殷切期望。 近年来,围绕数智化,制造业开启了一场全球竞赛,在无人机、高…

尚硅谷爬虫note16

一、crawlSpider 1. 安装scrapy 终端中:pip install scrapy 2. 创建项目 1)创建项目 scrapy startproject 项目名 2)切换到spiders目录下 cd 项目名\项目名\spiders 3)创建文件 scrapy genspider -t crawl 文件名 网址 4)运行…

如何在需求分析阶段考虑未来扩展性

在需求分析阶段考虑未来扩展性的关键在于 前瞻规划、灵活架构、标准设计。其中,前瞻规划尤为重要,因为通过全面分析业务发展趋势与技术演进,能够在初期设计阶段预留足够扩展空间,降低后期改造成本,为企业长期发展奠定坚…

大语言模型-全文

简介 本博客内容是《大语言模型》一书的读书笔记,该书是中国人民大学高瓴人工智能学院赵鑫教授团队出品,覆盖大语言模型训练与使用的全流程,从预训练到微调与对齐,从使用技术到评测应用,帮助学员全面掌握大语言模型的…

DeepSeek本地化部署与跨域访问架构构建

1. DeepSeek本地部署基础环境 部署 Ollama 推理框架获取并加载 DeepSeek 大语言模型配置图形化用户界面 (GUI)构建本地知识库并集成 鉴于上述四个步骤已在之前的博客中详尽阐述,为避免重复,以下内容将不再赘述,仅作概要性描述 2. 局域网共享…

深度学习系列78:使用langchain的api进行RAG

用起来很麻烦,看api的工夫都已经能自己写完代码了。但现在有些开源api用的是langchain的接口,还是了解一下。参考官方文档:https://www.langchain.com.cn/docs/how_to/ 1. LLM和langserve示例 以openai接口为例,可以看到分为3步…

LiveCommunicationKit OC 实现

一、实现效果: ‌ LiveCommunicationKit‌是苹果公司在iOS 17.4、watchOS 10.4和visionOS 1.1中引入的一个新框架,旨在优化VoIP通话的交互体验。该框架提供了与

SQL Server查询计划操作符(7.3)——查询计划相关操作符(10)

7.3. 查询计划相关操作符 88)Sequence Project:该操作符通过对一个排序集合增加字段来进行计算。其基于一个或多个字段的值将其输入的数据行分成多个段,这样,该操作符每次输出一个段,这些字段显示为该操作符的参数。该…

mac使用Homebrew安装miniconda(mac搭建python环境),并在IDEA中集成miniconda环境

一、安装Homebrew mac安装brew 二、使用Homebrew安装miniconda brew search condabrew install miniconda安装完成后的截图: # 查看是否安装成功 brew list环境变量(无需手动配置) 先执行命令看能不能正常返回,如果不能正常…

vue-cli + echarts 组件封装 (Vue2版)

在Vue2中使用ECharts还是比较麻烦的,今天做了几个组件让我们能更加简单的调用Echars来显示图表。 效果展示 echarts 导入 这里我们使用 package.json 方式导入Echars。配置好后使用命令 npm install或者其他方式都可以 {// ... "scripts": {// ... &qu…

基于编译器特性浅析C++程序性能优化

最近在恶补计算机基础知识,学到CSAPP第五章的内容,在这里总结并且展开一下C程序性能优化相关的内容。 衡量程序性能的方式 一般而言,程序的性能可以用CPE(Cycles Per Element)来衡量,其指的是处理每个元素…