【chatGPT4结对编程】chatGPT4教我做图像分类

news2024/11/26 2:54:06

开始接触深度学习

大语言模型火了之后,我也想过是否要加入深度学习的行业当中来,一开始的想法就是AI大模型肯定会被各大厂垄断,我们作为普通应用型软件工程师直接调用api就完事,另外对自己的学历也自卑(刚刚够线的二本)。因此有一段时间,专门尝试去折腾chatGPT的各种应用,不过始终觉得不够,有很多疑问: 这些通用的人工机器人是如何工作的呢?GPT4的1750亿参数到底是指什么?为何指定一个不同的prompt,相同的问题答案会差别这么大?为何它的代码能力这么强?我有太多的疑问,我觉得AI颠覆了我的认知,我从业10多年了,为何现在才开始接触AI呢?我想了解大模型背后的原理,我也想做这些cool的事情,10多年的CURD太没意思了。
那么问题来了,我该怎么入门深度学习呢?
在京东搜索深度学习,排名前2名的书籍是:《深度学习》和《动手学深度学习》,对比了下发现动手学深度学习是大神李沐编撰的,有对应的在线书籍,B站上有视频课程,github上有代码样例,这么高质量的作品,居然这一切都是免费的,还有什么理由不入坑呢,因此我果断加入深度学习的队列。

每天上一节课持续有1个多月了,目前学到30节课了,但目前我感觉还未真正上手,要掌握原理,需要的掌握背景知识太多了:微积分、线性代数、概率论等,毕业10多年后的我,自觉连初高中的数学都不一定能完全搞定,要学习起来真的觉得很痛苦。

实践比赛Classify Leaves

学完第二阶段开始第二次实践比赛,比赛题目是《Classify Leaves》给叶子图像分类,有了上一次的房价预测比赛实践之后,大致知道深度学习的流程:

  1. 读取数据预处理
  2. 设置超参数
  3. 训练和验证(验证用于进行超参数调整)
  4. 跑测试集后保存

图像分类与房价预测不同之处:

  1. 房价预测是表格数据,图像分类是图像数据
  2. 另外房价预测使用简单的线模型即可,图像预测需要使用卷积神经网络
  3. 房价预测对非熟知数据预处理对最后结果影响比较大,分类数据比较简单预处理简单。

查看数据格式

数据样例如下:包含3个文件和一个图片文件夹。
在这里插入图片描述

  1. 训练数据train.csv如下表格,包含了2列:image表示图片文件路径,label图片所属分类。
    image| label
    —|—
    images/0.jpg|maclura_pomifera
    images/1.jpg|maclura_pomifera
    images/2.jpg|maclura_pomifera
    images/3.jpg|maclura_pomifera
    …|…

  2. sample_submission.csv 是提交样例,样例数据格式与训练数据集一样。

  3. test.csv 是测试数据,训练好模型后,使用测试数据跑出结果提交,测试数据只有一列:image, label需要我们使用训练好的模型进行预测,然后提交预测后的结果。

导入包

from torch.utils.data import DataLoader
import torch
from torch import nn
from d2l import torch as d2l
import os
import pandas as pd
from torchvision.io import read_image
from torch.utils.data import Dataset
from torchvision import transforms
import matplotlib.pyplot as plt
from PIL import Image
import torchvision.models as models
from numpy import random

数据预处理

自定义数据读取

自己实现Dataset来读取图片分类数据

class CustomImageDataset(Dataset):
    def __init__(self, annotations_file, img_dir, dict_label, transform=None, target_transform=None):
        self.img_labels = pd.read_csv(annotations_file)
        self.img_dir = img_dir
        self.transform = transform
        self.target_transform = target_transform
        self.dict_label = dict_label

    def __len__(self):
        return len(self.img_labels)

    def __getitem__(self, idx):
        img_path = os.path.join(self.img_dir, self.img_labels.iloc[idx, 0])
        image = Image.open(img_path)
        if self.dict_label != None:
            label = self.img_labels.iloc[idx, 1]
        if self.transform:
            image = self.transform(image)
        if self.target_transform:
            label = self.target_transform(label)
        if self.dict_label != None: #通过这个来判断是否是测试数据的读取
            return image, torch.tensor(self.dict_label[label],dtype=torch.long)
        return image # 测试数据没有label

读取数据并初始化

# 直接读取csv列数据,用于处理列数据label的与处理,主要用于将数字分类和文本分类相互映像转换
train_data_csv = pd.read_csv('data/train.csv')
# 读取图片,用于输出提交结果
test_data_csv = pd.read_csv('data/test.csv')
# 读取所有文本分类
all_text_labels = train_data_csv['label']
# 去重
uni_text_labels = all_text_labels.unique()
# 数字映射文本分类字典
dict_num2text_labels = {}
# 文本映射数字分类字典
dict_text2num_labels = {}
# 分类打乱,有点多此一举
random.shuffle(uni_text_labels)
num_classes = 0 # 分类总数
# 相互映射
for label in uni_text_labels:
    dict_num2text_labels[num_classes] = label
    dict_text2num_labels[label] = num_classes
    num_classes += 1

print(f"dict_num2text_labels:{dict_num2text_labels} ")
print(f"dict_text2num_labels:{num_classes} ")
# 训练集,图片转换成tensor
transform_train = transforms.Compose([
                transforms.Resize((224, 224)),
                transforms.RandomHorizontalFlip(p=0.5),   #随机水平翻转 选择一个概率
                transforms.ToTensor()
])
# 测试集,图片转换成tensor
transform_test = transforms.Compose([
                transforms.Resize((224, 224)),
                transforms.ToTensor()
])

training_data = CustomImageDataset("data/train.csv", "data/", dict_text2num_labels,transform = transform_train)
test_data = CustomImageDataset("data/test.csv", "data/", None,  transform = transform_test)

模型定义和超参数

使用深度学习神经网络框架定义

model = models.resnet34(pretrained=True)
model.eval()
# 设置输出分类数
model.fc = nn.Sequential(nn.Linear(model.fc.in_features, num_classes))
# 批次大小, 学习率,训练次数、权重
batch_size,lr, num_epochs,weight_decay = 32, 3e-4, 20, 1e-3 

k折交叉训练

由于数据集合比较小,使用k折交叉读取数据训练

import time
from sklearn.model_selection import KFold
from torch.utils.data import DataLoader, Dataset, random_split, Subset
import torch.optim as optim

# 计算验证集
def evaluate_accuracy_gpu(net, data_iter, device=None):
    """Compute the accuracy for a model on a dataset using a GPU.

    Defined in :numref:`sec_lenet`"""
    if isinstance(net, nn.Module):
        net.eval()  # Set the model to evaluation mode
        if not device:
            device = next(iter(net.parameters())).device
    # No. of correct predictions, no. of predictions
    metric = d2l.Accumulator(2)

    with torch.no_grad():
        for X, y in data_iter:
            if isinstance(X, list):
                # Required for BERT Fine-tuning (to be covered later)
                X = [x.to(device) for x in X]
            else:
                X = X.to(device)
            y = y.to(device)
            metric.add(d2l.accuracy(net(X), y), d2l.size(y))
    return metric[0] / metric[1]
# 训练
def train_ch6(net, train_iter, test_iter, num_epochs, lr,weight_decay, device):
    """Train a model with a GPU (defined in Chapter 6).

    Defined in :numref:`sec_lenet`"""
    def init_weights(m):
        if type(m) == nn.Linear or type(m) == nn.Conv2d:
            nn.init.xavier_uniform_(m.weight)
    net.apply(init_weights)
    print('training on', device)
    net.to(device)
    optimizer = torch.optim.Adam(net.parameters(), lr=lr, weight_decay=weight_decay)
    #optimizer = torch.optim.SGD(net.parameters(), lr=lr, weight_decay=weight_decay)
    loss = nn.CrossEntropyLoss()
    animator = d2l.Animator(xlabel='epoch', xlim=[1, num_epochs],
                            legend=['train loss', 'train acc', 'test acc'])
    
    timer, num_batches = d2l.Timer(), len(train_iter)
    for epoch in range(num_epochs):
        # Sum of training loss, sum of training accuracy, no. of examples
        metric = d2l.Accumulator(3)
        net.train()
        for i, (X, y) in enumerate(train_iter):
            timer.start()
            optimizer.zero_grad()
            X, y = X.to(device), y.to(device)
            y_hat = net(X)
            l = loss(y_hat, y)
            l.backward()
            optimizer.step()
            with torch.no_grad():
                metric.add(l * X.shape[0], d2l.accuracy(y_hat, y), X.shape[0])
            timer.stop()
            train_l = metric[0] / metric[2]
            train_acc = metric[1] / metric[2]
            if (i + 1) % (num_batches // 5) == 0 or i == num_batches - 1:
                animator.add(epoch + (i + 1) / num_batches,
                             (train_l, train_acc, None))
        test_acc = evaluate_accuracy_gpu(net, test_iter)
        animator.add(epoch + 1, (None, None, test_acc))
    print(f'loss {train_l:.3f}, train acc {train_acc:.3f}, '
          f'test acc {test_acc:.3f}')
    print(f'{metric[2] * num_epochs / timer.sum():.1f} examples/sec '
          f'on {str(device)}')

# 定义 k 折交叉验证参数
k_folds = 5
kfold = KFold(n_splits=k_folds, shuffle=True)

for fold, (train_ids, val_ids) in enumerate(kfold.split(training_data)):
    print(f'FOLD {fold}')
    print('--------------------------------')

    # 根据索引划分训练集和验证集
    train_subsampler = Subset(training_data, train_ids)
    val_subsampler = Subset(training_data, val_ids)

    # 创建数据加载器
    trainloader = DataLoader(train_subsampler, batch_size=64, shuffle=True, num_workers=2)
    valloader = DataLoader(val_subsampler, batch_size=64, shuffle=False, num_workers=2)

    # 训练模型
    train_ch6(model, trainloader, valloader, num_epochs, lr, weight_decay, d2l.try_gpu())
   
# 保存模型
torch.save(model.state_dict(), f"data/resnet34_SGD_model.state_{time}.pth")

生产预测测试数据保存

# 加载保存到文件的模型
model = models.resnet34(pretrained=True)
model.load_state_dict(torch.load("data/resnet34_SGD_model.state_1685356838.1272397.pth"))
model.eval()
model.cuda()

test_dataloader = DataLoader(test_data, batch_size=batch_size, shuffle=False)
preds = []
with torch.no_grad():
    for i, X in enumerate(test_dataloader):
        X = X.to(d2l.try_gpu())
        y_hat = model(X)
        y_hat = torch.argmax(y_hat, axis=1) #获取最大分类
        for num_label in y_hat:
            label_str = dict_num2text_labels[num_label.item()]
            preds.append(label_str)

# 将网络应用于测试集。
# 将其重新格式化以导出到Kaggle
test_data_csv['label'] = preds
submission = pd.concat([test_data_csv['image'], test_data_csv['label']], axis=1)
submission.to_csv('submission.csv', index=False)

使用GPT4的过程

在实现的过程中并不是一帆风顺,GPT4给了很大的帮助,下面是我们的对话。

输出分类参数错误

一开始读取分类标签的时候,转换成了tensor 的float类型,导致出现报错:
RuntimeError: “nll_loss_forward_reduce_cuda_kernel_2d_index” not implemented for ‘Float’
直接复制给GPT4,他清晰的告诉了我是因为nn.NLLLoss() 函数输出的是LongTensor类型。
在这里插入图片描述

怎么使用模型输出分类

不知道如何使用框架模型,直接提问题。
在这里插入图片描述

训练效果不好

深度神经网络训练集的准确率和验证集的差异比较大是什么原因
在这里插入图片描述

使用pandas输入问题

怎么使用pandas 加一个list数组加入输出csv文件的一列是上
在这里插入图片描述

如何使用k折交叉验证法

如何使用k折交叉方法训练图片分类,给定了一个数据集,如何进行k折分别选择测试集合和验证集数据
在这里插入图片描述
给出了非常详细的样例。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2.4. 封装与访问控制

封装(Encapsulation)是面向对象编程的一个核心概念,它意味着将数据(属性)和方法(操作数据的函数)捆绑在一起,形成一个类(Class)。封装的目的是将数据和操作数…

C++插件管理类(下)——实际项目(阉割版)

文章目录 一、背景二、代码结构三、两个CMakeLists.txt3.1 父目录3.2 子目录src 四、代码实例4.1 main.cpp4.2 Plugin.h4.3 Plugin.cpp4.4 Comm.h4.5 calc.cpp 五、 踩坑点 一、背景 请参考C插件管理类(上) 二、代码结构 三、两个CMakeLists.txt 3.1 父目录 #设置cmake的最…

stackqueue的模拟实现

stack模拟: stack的源代码: stack的全部源代码就这些。 stack的代码少,原因在于采用了适配器模式,所谓适配器,以电器为例,每个电器都有电源适配器,中国的家用电源为220V的交流电,但是…

3d虚拟主播形象能提升提升企业销售额

随着科技的不断进步和发展,虚拟人形象正在被广泛地应用于商业宣传中。3D虚拟人形象是指采用计算机图形学、人工智能等技术,模拟真实人类形象的虚拟形象。相比于传统产品营销方式,采用3D虚拟人形象进行产品交互讲解对提升企业销售额具有很多优…

JavaWeb12(实现基础分页模糊查询的分页)

目录 一. 效果预览 ​编辑 二. 实现基本分页 2.1 分页sql --每页3条 取第二页 --由于伪列不能作用与大于符号也不能作用于between....and --因此需要将伪列----->名列 2.2 万能公式 2.3 首页&上一页&下一页实现 ②前端代码 2.4 末页实现&优化 ①底层代…

目标检测复盘 -- 6. YOLOv4

Backbone YOLOv4的骨干是CSPDarknet53 CSP结构的作用:1. 增强CNN的学习能力 2. 移出计算瓶颈 3. 减少内存开销 CSP首先将输入的特征层分成两个部分,这里以densenet为例,part2分支经过denseblock后,进过一个transition&#xff0c…

Redis之高可用方案浅析

在工程项目中,系统应用的高可用性越来越重要,业主越来越重视。其实高可用可以分为应用层高可用和数据层高可用,数据层高可用中常见的有关系型数据库mysql的高可用、非关系型NoSQl数据库redis的高可用等,下面聊聊典型的NoSQL数据库…

C# 事件和委托的区别并说明

1.区别 事件是基于委托的,为委托提供了一个发布/订阅机制。可以说事件是一种特殊的委托,他的调用和委托是一样的。 事件的声明 public event 委托类型 事件名称 通常事件的命名以事件名称Event来命名。如public event delegate NotifyEvent; 事件和委…

C++ Primer Plus 第二章习题

目录 复习题 1.C程序的模块叫什么? 2.#include 预处理器编译指令的用处? 3.using namespace std; 该语句是干什么用的? 4.什么语句可以打印一个语句"hello,world",然后重新换行? 5.什么语句可以用来创…

桂院校园导航 导入 与 配置教程

将 静态项目/云开发项目 文件夹下最新版本的 文件夹下的 项目 的整个文件夹 复制到项目路径下(比如 D:\WeChatProjects),强烈建议不要直接扔在桌面上 云开发项目 需开通 云开发 功能(首月免费,次月19.9)&am…

【论文阅读笔记】CRFL: Certifiably Robust Federated Learning against Backdoor Attacks

个人阅读笔记,如有错误欢迎指出! 会议:PMLR 2021[2106.08283] CRFL: Certifiably Robust Federated Learning against Backdoor Attacks (arxiv.org) 问题: 现有的防御算法缺乏健壮性 创新: 证明了所提出框架得稳定性 通过马尔…

Generative AI 新世界 | 走进文生图(Text-to-Image)领域

在之前的四篇 “Generative AI 新世界” 中,我们带领大家一起探索了生成式 AI(Generative AI),以及大型语言模型(LLMs)的全新世界概览。并在文本生成(Text Generation)领域做了一些概…

javascript基础十:说说你对Javascript中this对象的理解

一、定义 函数的 this 关键字在 JavaScript 中的表现略有不同,此外,在严格模式和非严格模式之间也会有一些差别 在绝大多数情况下,函数的调用方式决定了 this 的值(运行时绑定) this 关键字是函数运行时自动生成的一…

进程控制与进程调度 —— 时间片轮转调度算法(C++版)

目录 实验一 进程控制与进程调度 一、实验目的 二、实验内容 三、数据结构及符号说明 四、运行环境说明 五、代码段 六、 效果展示 实验一 进程控制与进程调度 备注:大二(下)操作系统实验一 一、实验目的 掌握进程状态的转变、…

多次调用java.awt.Toolkit.getDefaultToolkit方法获得是同一个单例的Toolkit

多次调用java.awt.Toolkit.getDefaultToolkit方法获得是同一个单例的Toolkit java.awt.Toolkit.getDefaultToolkit()import java.awt.Toolkit;public class 多次调用Toolkit的getDefaultToolkit方法获得是同一个单例的Toolkit {static public void main (String...arguments)t…

WMS:系统窗口添加过程

WMS:系统窗口添加过程 1、经常使用的两大类窗口2、系统窗口StatusBar2.1 StatusBarWindowView添加流程2.2 简要时序图 android12-release 1、经常使用的两大类窗口 Android中的“窗口”类型有很多,经常使用的“窗口”大致分为两大类:一是,由系…

对于后端Linux的入门知识

为什么使用Linux 文章来自https://librehunt.org/,在这个网站里,你可以根据它提供的选项,最终选出适合你的Linux版本 It’s safe and private. No tracking. No company watching over you, no “big brother is watching you” nonsense. Ju…

article-三自由度机械臂运动学分析+仿真

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rOmeEm3I-1685366971102)(data:image/svgxml;utf8, )] [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kCu0JrBB-1685366971103)(data:image/svgxml;utf8, )] 建立坐标系 1…

ROS:创建工作空间和编译功能包

目录 一、工作空间二、创建工作空间三、编译空代码的工作空间四、功能包五、创建功能包六、设置和检查环境变量七、功能包中的两个重要文件 一、工作空间 存放工程开发相关文件的文件夹。类似一个IDE(例如Pycharm)新建一个工程,就是一个工作…

权威认可!腾讯云EdgeOne入选Gartner® DDoS缓解方案市场指南

近日,Gartner发布《Market Guide for DDoS Mitigation Solutions》报告,腾讯云EdgeOne入选Gartner DDoS缓解方案市场指南。 “分布式拒绝服务(DDoS)缓解市场包括检测和缓解DDoS攻击并将其作为专用产品提供的供应商。它包括专业供…