本文是笔者进行神经网络学习的个人学习日记
图片和链接均源自网络,侵删
1 torch的调用
在深度学习中,数据的量级通常是十分庞大的,一般情况下,我们无法将所有数据同时加载到内存中。因此,在训练模型之前,我们会对数据集进行分批——既是分训练集与测试集,也是分批载入。
为了实现上述功能,我们使用torch库中的Dataset
类和DataLoader
类来实现数据的加载和存储。同时,我们也需要一些其他的辅助方法来将数据读取,分批和储存,所有需要使用的库如下:
import os
import numpy as np
import pandas as pd
import torch
from sklearn.model_selection import train_test_split
from torch.utils.data import DataLoader
from torch.utils.data import Dataset
其中,os库以及numpy和pandas库主要用于数据的读取,处理和储存,在我的实例中,我会先将数据储存在DataFrame
中方便读取和修改。而sklearn库在这里主要用于分训练集和测试集,其train_test_split
方法可以方便将数据集分开。
下面我们先来定义我们用来储存数据的MyDataset
类。
2 MyDataset类的定义
这是我们自行定义的类,它继承于torch库的Dataset
类,在定义时需要注意:除了__init__
方法外,还需要重写 __len__
和__getitem__
类,用于获取数据长度以及输入输出。我们来看一看MyDataset
类的实现代码(我在这里顺便进行了数据的归一化和分类操作,也可以不进行):
class MyDataset(Dataset):
def __init__(self, path, iCols, oCols, normalize, coding='utf-8', is_train=True):
"""
Dataset类,读取数据并归一化后分成训练集和测试集
:param str path: 文件路径
:param list[str] iCols: 输入列名
:param list[str] oCols: 输出列名
:param Any normalize: 归一化方法(StandardScale)
:param str coding: 文件编码方式
:param bool is_train: 用于分训练集和测试集
"""
self.path = path
self.iCols = iCols
self.oCols = oCols
self.normalize = normalize
# 数据读取,由于我的数据存在不同文件中,故读取一个文件夹中的所有文件
fileNames = os.listdir(self.path)
dfs = [pd.read_csv(os.path.join(self.path, fileName), names=[iCols + oCols], encoding=coding) for fileName in fileNames]
allDf = pd.concat(dfs, ignore_index=True) # 将不同文件中的数据整合
# 归一化
allDf[:] = self.normalize.fit_transform(allDf[:])
# 分类
x, y = allDf[iCols], allDf[oCols]
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=22)
# 将输入(data)和输出(labels)转化格式并储存
self.data = torch.Tensor(np.array(x_train if is_train else x_test))
self.labels = torch.Tensor(np.array(y_train if is_train else y_test))
def __len__(self):
return len(self.labels)
def __getitem__(self, idx):
"""
获取输入和输出
:param int idx: 索引值
:return: tuple[tensor[float], tensor[float]]
"""
return self.data[idx], self.labels[idx]
我将数据进行了归一化,按照8:2的比例分成了训练集和测试集(random_state
的作用类似随机种子,固定后每次随机都相同),并将输入和输出分到了data
和labels
两个Tensor
变量中,方便__getitem__
方法对他们进行调用。其他的,代码中注释都讲的比较清楚了,就不再赘述。
数据储存的容器有了,那么下面就要对数据进行加载。
3 myDataLoader方法的定义
数据加载器的调用其实非常简单,就一个函数DataLoader
就可以解决了。之所以定义一个自己的方法,主要是为了装逼主要是为了把MyDataset
的定义和DataLoader
方法的调用放在一个函数里,方便后续调用。话不多说了,直接上代码。
def myDataLoader(path, batch_size, iCols, oCols, normalize, coding='utf-8'):
"""
将Dataset数据和参数储存到DataLoader中,返回DataLoader和各项参数
:param str path: 文件路径
:param int batch_size: 批量归一数
:param list[str] iCols: 输入列名
:param list[str] oCols: 输出列名
:param Any normalize: 归一化方法
:param str coding: 文件编码方式
:return: tuple[DataLoader, DataLoader, list[float], list[float], int]
"""
# 实例化MyDataset
train_dataset = MyDataset(path, iCols, oCols, normalize, coding, True)
test_dataset = MyDataset(path, iCols, oCols, normalize, coding, False)
# 创建DataLoader
train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False)
return train_loader, test_loader
batch_size
是批量归一数,可以理解为一次加载的数据数量,一般为2的次方(64,128等)。在定义完MyDataset
类之后,直接用DataLoader
将整个数据集加载到加载器中。shuffle
可以通俗理解为将数据打乱,在训练时有一定程度上强化训练效果的作用,但是测试集中显然用不到。
以上就是全部数据加载器的使用了,至于如何使用这个数据加载器,可以看我的另一篇博客:神经网络学习日记(二)——全连接神经网络及Pytorch代码实现
个人神经网络学习日记:
【神经网络学习日记(1)】神经网络基本概念
【神经网络学习日记(2)】全连接神经网络(FCNN)及Pytorch代码实现
【神经网络学习日记(3)】卷积神经网络(CNN)
【神经网络学习日记(4)】循环神经网络(RNN、LSTM、BiLSTM、GRU)
【神经网络学习日记(5)】数据加载器(DataLoader)的调用
【神经网络学习日记(6)】Transformer结构详解
【神经网络学习日记(7)】Transformer的应用(BERT、Longformer、LLM)
【神经网络学习日记(8)】一些图神经网络的简单介绍(GCN、GAT、rGCN)
文中引用部分都尽可能写出了,如果有侵犯其他人文章版权的问题,请务必联系我,谢谢!