dl学习笔记(9):pytorch数据处理的完整流程

news/2025/2/8 13:03:59 标签: 学习, 笔记

1)自动导入常用库的设置方式

在开始之前,这里介绍一下自动导入常用的你需要加载的库的操作方式。

首先在我们的目录下找到ipython文件,如下图:

然后找到里面的startup文件:

然后新建一个文本文档,输入你每次要导入的库的代码,例子如下:

注意这里要符合python的缩进格式。然后改名字为start.py

然后我们重启一下kernel或者随便新建一个python文件来验证是否成功导入

如果结果如上图所示没有导入任何库直接能调用说明已经自动导入成功。

2)手动实现简单数据生成函数

为了后续做实验的方便,我们需要手动实现一个自己的数据生成函数。当我们可以自定义数据生成的规律,我们将数据喂给模型就可以判断模型是否掌握了我们定义的规律,从而判断模型的性能,这也是从炼丹师进步到化学家的必经之路。

下面我们以最简单的回归类数据集来举例:

def TensorGenRe(num_examples=1000,w=[2,1,1],bias=True,delta=0.01,deg=1):
    '''
    回归类数据集创建函数
    1 num_examples:创建数据集的数据量
    2 w:包括截距的(如果存在)特征系数向量
    3 bias:是否需要截距
    4 delta:扰动项取值
    5 deg 方程的最高次数
    '''
    if bias == True:
        #如果有偏差项,最后一位是b应该从特征张量中舍去
        num_inputs = len(w)-1 
        #这里一律用标注正太分布举例
        features_true = torch.randn(num_examples,num_inputs)
        #这里由于最后一列是偏差所以去掉,然后转化为列向量,最后由于后面要进行矩阵乘法所以转化为浮点数
        w_true = torch.tensor(w[:-1]).reshape(-1,1).float()
        b_true = torch.tensor(w[-1]).float()
        #这里需要判断是否只有一列,决定了是用矩阵乘法还是简单的pow
        if num_inputs == 1:
            labels_true=torch.pow(features_true, deg)* w_true + b_true
        else:
            labels_true = torch.mm(torch.pow(features_true, deg),w_true)+ b_true
        #这里需要加上一列1,为了方便后续的矩阵乘法,相当于w*x+1*b
        features = torch.cat((features_true, torch.ones(len(features_true), 1)),1)
        #最后乘以扰动项的系数delta
        labels= labels_true + torch.randn(size = labels_true.shape)* delta
    else:
        #下面的逻辑和上面一样
        num_inputs=len(w)
        features =torch.randn(num_examples,num_inputs)
        w_true =torch.tensor(w).reshape(-1,1).float()
        if num_inputs == 1:
            labels_true =torch.pow(features,deg)*w_true
        else:
            labels_true =torch.mm(torch.pow(features, deg),w_true)
        labels = labels_true + torch.randn(size= labels_true.shape)* delta
    return features, labels

关于上面代码的解释写在注释里面,另外需要注意的是上面这个函数不能实现含有交叉项的方程,下面我们可以尝试调用实验一下:

我们可以通过画图来验证结果:

#绘制图像查看结果
plt.subplot(223)
plt.scatter(features[:,0],labels)#第一个特征和标签的关系
plt. subplot(224)
plt.scatter(features[:, 1],labels)#第二个特征和标签的关系

3)手动实现训练集和测试集的切分

def data_split(features,labels,rate=0.7):
    #rate是训练集占所有数据的比例
    num_examples = len(features)
    #这里是创建一个数据集的行索引列表
    indices = list(range(num_examples))
    #通过打乱索引,然后再映射到原数据集实现随机
    random.shuffle(indices)
    num_train = int(num_examples*rate)
    #由于这里已经打乱过了所以直接选前num_train个就行
    indices_train = torch.tensor(indices[:num_train])
    indices_test = torch.tensor(indices[num_train:])
    x_train = features[indices_train]
    y_train = labels[indices_train]
    x_test = features[indices_test]
    y_test = labels[indices_test]
    return x_train,y_train,x_test,y_test

我们可以做一个简单的调用来验证一下:

4)再谈Dataset和Dataloader

random_split函数:

我们发现pytorch内置的split函数返回的不是数据的实体张量,而是两个迭代器,这其实和pytorch设计哲学有关。当我们处理海量数据的时候,如果我们直接分别存储训练集和测试集的两部分实体数据会非常占用内存和计算资源。在很多教程中数据集划分过程会推荐使用scikit-learn中的train_test_split函数,该函数就是直接存储数据实体,对于初学者更加友好一点。所以这里pytorch并没有真正的实际存储,而是和上面我们手动实现的一样,是进行映射处理成迭代器,我们可以通过和之前一样的循环操作来遍历打印出来。

下面我们回顾一下之前的流程:

我们之前就说dataset是用来进行打包封装操作的,可以发现下面返回的也是一个dataset的一个子类TensorDataset,同样也是一个生成器。这是一个可以用来在上下文环境中互相传的子类,例如可以接着给dataloader,所以在整个pytorch的流程中都是以类迭代器的方式流动的,而并不是以数据实体进行流动。但是这个函数只能用来封装tensor,并不能用来封装更一般的数据类型。

下面用一个库里面有的乳腺癌数据集的例子来说明如何处理一般情况的数据集:

我们还是一样地可以通过data和target来查看特征和标签

下面我们通过创建一个新的dataset子类,并且重写其中的几个方法来实现一般数据的封装

class LBCDataset(Dataset):
    def __init__(self, data):
        self.features = data.data
        self.labels = data.target
        self.lens = len(data.data)
    # 输入index数值,方法最终返回index对应的特征和下标
    def __getitem__ (self,index):
        return self.features[index,:], self.labels[index]
    def __len__(self):
        return self.lens

下面我们用random_split来进行切分:

当我们查看LBC_train会发现它只有dataset和indices两个属性,同样的,是一个映射式的对象,其中dataset属性用于查看原数据集对象,indices属性用于查看切分后数据集的每一条数据的index

我们可以分别调用查看:

下面我们来看dataloader:

我们会发现一个有意思的地方,这里的dataset属性返回的其实是LBC_train,也就是说这里的dataset属性存在一种类似于回溯的还原机制。

最后我们用一张图来总结上面的流程:


http://www.niftyadmin.cn/n/5844878.html

相关文章

猫眼Java开发面试题及参考答案(上)

详细介绍项目,像项目中如何用 Redis,用到 Redis 哪些数据类型,项目中遇到哪些问题,怎么解决的 在我参与的一个电商项目中,Redis 发挥了至关重要的作用。这个电商项目主要是为用户提供商品浏览、购物车管理、订单处理等一系列功能。 在项目中使用 Redis 主要是为了提升系统…

chrome-base 如何实现一个BindOnce

考虑一个问题: worker_thread.task_runner()->PostDelayedTask(FROM_HERE, base::BindOnce(&Ref::Foo, ref, 1), base::Milliseconds(1000)); BindOnce 是如何实现的呢? 翻看源码:base\functional\bind.h 写的 非常简洁 // Bind a…

第三个Qt开发实例:利用之前已经开发好的LED驱动在Qt生成的界面中控制LED2的亮和灭

前言 上一篇博文 https://blog.csdn.net/wenhao_ir/article/details/145459006 中,我们是直接利用GPIO子系统控制了LED2的亮和灭,这篇博文中我们利用之前写好的LED驱动程序在Qt的生成的界面中控制LED2的亮和灭。 之前已经在下面两篇博文中实现了LED驱动…

[数据结构] Set的使用与注意事项

目录 Set的说明 常见方法说明 注意事项 TreeSet使用案例 Set的说明 Set与Map主要的不同有两点: Set是继承自Collection的接口类,Set中只存储了Key. 常见方法说明 方法解释boolean add(E e)添加元素,但重复元素不会被添加成功void clear()清空集合boolean contains(Object…

Chrome 浏览器 支持多账号登录和管理的浏览器容器解决方案

根据搜索结果,目前没有直接提到名为“chrometable”的浏览器容器或插件。不过,从功能描述来看,您可能需要的是一个能够支持多账号登录和管理的浏览器容器解决方案。以下是一些可能的实现方式: 1. 使用 Docker 容器化部署 Chrome …

CVPR2021 | VMI-FGSM VNI-FGSM | 通过方差调整增强对抗攻击的可迁移性

Enhancing the Transferability of Adversarial Attacks through Variance Tuning 摘要-Abstract引言-Introduction相关工作-Related Work方法-Methodology动机-Motivation基于方差调整的梯度攻击-Variance Tuning Gradient-based Attacks不同攻击的关系-Relationships among V…

亚博microros小车-原生ubuntu支持系列:24 巡线驾驶

这篇跟之前的颜色识别类似,亚博microros小车-原生ubuntu支持系列:21 颜色追踪-CSDN博客 1、程序功能说明 程序启动后,调整摄像头的俯仰角,把摄像头往下掰动,使得摄像头可以看到线,然后点击图像窗口&#…

golang命令大全13--相关资源与学习路径【完】

1、官方资源 Go 官方文档: https://golang.org/doc/提供详细的语言特性、标准库和工具链的文档。 Go Blog: https://blog.golang.org/包含关于 Go 语言最新特性、优化和实践的文章。 Go Modules 文档: https://golang.org/ref/mod深入解…