如何构建AI数据集

 
随机地,灵活地 生成符合业务特性的数据,以快速验证模型的有效性,是算法工程师的必备技能
    
不要在边缘的事情上浪费太多的精力,要直奔主题,否则 事情容易夭折... 

模型比的不是代码多,是效果,是性能,笨重的模型往往难以落地... 

主体流程

 
1. 分析业务,明白业务主要流程

2. 将业务数据,转化为深度学习批处理格式

3. 输入,这个通常比较固定

4. 输出:这个有较强的业务依赖
    4.1 分类业务,输出类似是这样的[[是/否]]
    4.2 多任务,输出类似是这样的[[是/否label1, label2, label3]], 
        即模型的输出是一个向量,向量的每个元素都可以是一个业务指标

关于数据的多少与好坏

 
数据不均衡问题,数据集少,数据集噪声太多等等 

这些问题导致模型训练时,学习不到真实的规律 

怎么办?
 
自己做一个数据生成器,有以下功能:
去除不重要的数据 
去除一部分噪声 
去除价值小的 
去除负面影响大的 
保留重要的 
尽量让各种样本的比例一致 

若有可能,可从真实业务的角度提取规律,然后生成部分数据,以补充现有数据的不足 
毕竟,客观世界中有些事情发生的概率极低,意味着此类数据极少,但也是模型需要学习的

数据集的格式

 
数据目录:存放具体的数据
标注文件:存放数据的路径

make_regression生成回归数据
from sklearn.datasets import make_regression
X,y = make_regression(n_samples=10000,n_features=100,noise=0.01,random_state=73)
print(X.shape,y.shape)  # ((10000, 100), (10000,))
print(X.max(),X.min(),X.mean())  # 4.706468475449477 -4.619144643601296 -0.0016766413978336362
print(y.max(),y.min(),y.mean())  # 581.843352146498 -622.724779439007 -0.1939345112009748

make classification

 
from sklearn.datasets import make_classification
X,y = make_classification(n_samples=10000,n_features=2000,n_classes=2,)

import collections
data_count2=collections.Counter(y)
data_count2
{0: 4999, 1: 5001}

Dataset

实现两个功能:

 
继承Dataset,重载两个方法:__len__,__getitem__
len(train_dataset):可以方便查看数据集的大小
train_dataset[1]:可以根据索引查看某个数据

item返回格式

 
getitem方法
- 参数是索引
- 返回是x,y 
  - x为数据,类型通常是torch.tensor(x).float(),默认32位,但且不强制,为long也行
  - y为类别索引,即x对应的 类别/label 的索引,类型为torch.tensor(y).long(),也不强制但分类问题都是long 
    

自定义dataset

import torch 
from torch import nn 
import torch.nn.functional as F 

# torch 批次处理
from torch.utils.data import Dataset
from torch.utils.data import DataLoader
from sklearn.datasets import make_regression

class MyDataSet(Dataset):
    
    def __init__(self):
        """
        构建数据集
        """
        X,y = make_regression(n_samples=10000,n_features=100,noise=0.01,random_state=73)
        self.X = X
        self.y = y
        print(f"seq_len={len(X[0])}")
    
    def __len__(self):
        return len(self.X)
    
    def __getitem__(self, idx):
        x = self.X[idx]
        y = self.y[idx]

        return torch.tensor(data=x).long(), torch.tensor(data=y).long()

# 自定义数据加载器
train_dataset = MyDataSet()

DataLoader

DataLoader

 
# 从数据集中批次取数据
train_dataloader = DataLoader(dataset=train_dataset, shuffle=True, batch_size = 128)
for X,y in train_dataloader:
    print(X.shape,X.ndim,y.shape,y.ndim)  # torch.Size([128, 100]) 2 torch.Size([128]) 1
    

drop_last=True

 
# 从数据集中批次取数据
train_dataloader = DataLoader(dataset=train_dataset, shuffle=True, batch_size = 128, drop_last=True,)
for X,y in train_dataloader:
    print(X.shape,X.ndim,y.shape,y.ndim)  # torch.Size([128, 100]) 2 torch.Size([128]) 1
    break

drop_last=True会舍弃最后一个批次,
因为最后一个批次中样本的个数通常不是批次个数,而是总个数%batch_size的余数

由于不是batch_size可能会在计算上带来一些不便,
舍弃是最方便的,不舍弃可能需要单独处理一下

 
另外,期望一个批次的性质可以表示整体数据集的性质,
如果,数据量达不到一个批次,可能这种规律也不应该去学习

参考