《零基础实践深度学习》2.3.3 校验数据有效性 基于飞桨Dataset和DataLoader API完成数据处理

简介: 这篇文章详细介绍了在深度学习任务中进行数据处理的步骤,包括数据校验、封装数据读取与处理函数、使用飞桨Dataset和DataLoader API完成数据加载,以及数据增强/增广的方法和实践,旨在确保数据的有效性和提高模型训练效果。

2.3.3 校验数据有效性

在实际应用中,原始数据可能存在标注不准确、数据杂乱或格式不统一等情况。因此在完成数据处理流程后,还需要进行数据校验,一般有两种方式:

  • 机器校验:加入一些校验和清理数据的操作
  • 人工校验:先打印数据输出结果,观察是否是设置的格式。再从训练的结果验证数据处理和读取的有效性

2.3.3.1 机器校验

如下代码所示,如果数据集中的图片数量和标签数量不等,说明数据逻辑存在问题,可使用assert语句校验图像数量和标签数据是否一致。

In [5]

imgs_length = len(imgs)
assert len(imgs) == len(labels), \
        "length of train_imgs({}) should be the same as train_labels({})".format(len(imgs), len(labels))

2.3.3.2 人工校验

人工校验是指打印数据输出结果,观察是否是预期的格式。实现数据处理和加载函数后,我们可以调用它读取一次数据,观察数据的形状和类型是否与函数中设置的一致。

In [6]

# 声明数据读取函数,从训练集中读取数据
train_loader = data_generator
# 以迭代的形式读取数据
for batch_id, data in enumerate(train_loader()):
    image_data, label_data = data
    if batch_id == 0:
        # 打印数据shape和类型
        print("打印第一个batch数据的维度,以及数据的类型:")
        print("图像维度: {}, 标签维度: {}, 图像数据类型: {}, 标签数据类型: {}".format(image_data.shape, label_data.shape, type(image_data), type(label_data)))
    break

打印第一个batch数据的维度,以及数据的类型:

图像维度: (100, 784), 标签维度: (100,), 图像数据类型: <class 'numpy.ndarray'>, 标签数据类型: <class 'numpy.ndarray'>

2.3.4 封装数据读取与处理函数

上文我们从读取数据、划分数据集、到打乱训练数据、构建数据读取器以及数据数据校验,完成了一整套一般性的数据处理流程,下面将这些步骤放在一个函数中实现,方便在神经网络训练时直接调用。

In [7]

def load_data(mode='train'):
    datafile = './work/mnist.json.gz'
    print('loading mnist dataset from {} ......'.format(datafile))
    # 加载json数据文件
    data = json.load(gzip.open(datafile))
    print('mnist dataset load done')
   
    # 读取到的数据区分训练集,验证集,测试集
    train_set, val_set, eval_set = data
    if mode=='train':
        # 获得训练数据集
        imgs, labels = train_set[0], train_set[1]
    elif mode=='valid':
        # 获得验证数据集
        imgs, labels = val_set[0], val_set[1]
    elif mode=='eval':
        # 获得测试数据集
        imgs, labels = eval_set[0], eval_set[1]
    else:
        raise Exception("mode can only be one of ['train', 'valid', 'eval']")
    print("训练数据集数量: ", len(imgs))
    
    # 校验数据
    imgs_length = len(imgs)
    assert len(imgs) == len(labels), \
          "length of train_imgs({}) should be the same as train_labels({})".format(len(imgs), len(labels))
    
    # 获得数据集长度
    imgs_length = len(imgs)
    
    # 定义数据集每个数据的序号,根据序号读取数据
    index_list = list(range(imgs_length))
    # 读入数据时用到的批次大小
    BATCHSIZE = 100
    
    # 定义数据生成器
    def data_generator():
        if mode == 'train':
            # 训练模式下打乱数据
            random.shuffle(index_list)
        imgs_list = []
        labels_list = []
        for i in index_list:
            # 将数据处理成希望的类型
            img = np.array(imgs[i]).astype('float32')
            label = np.array(labels[i]).astype('float32')
            imgs_list.append(img) 
            labels_list.append(label)
            if len(imgs_list) == BATCHSIZE:
                # 获得一个batchsize的数据,并返回
                yield np.array(imgs_list), np.array(labels_list)
                # 清空数据读取列表
                imgs_list = []
                labels_list = []
    
        # 如果剩余数据的数目小于BATCHSIZE,
        # 则剩余数据一起构成一个大小为len(imgs_list)的mini-batch
        if len(imgs_list) > 0:
            yield np.array(imgs_list), np.array(labels_list)
    return data_generator

下面定义一层神经网络,利用定义好的数据处理函数,完成神经网络的训练

In [8]

# 数据处理部分之后的代码,数据读取的部分调用Load_data函数
# 定义网络结构,同上一节所使用的网络结构
class MNIST(paddle.nn.Layer):
    def __init__(self):
        super(MNIST, self).__init__()
        # 定义一层全连接层,输出维度是1
        self.fc = paddle.nn.Linear(in_features=784, out_features=1)
    def forward(self, inputs):
        outputs = self.fc(inputs)
        return outputs

In [9]

# 训练配置,并启动训练过程
def train(model):
    model = MNIST()
    model.train()
    #调用加载数据的函数
    train_loader = load_data('train')
    opt = paddle.optimizer.SGD(learning_rate=0.001, parameters=model.parameters())
    EPOCH_NUM = 10
    for epoch_id in range(EPOCH_NUM):
        for batch_id, data in enumerate(train_loader()):
            #准备数据,变得更加简洁
            images, labels = data
            images = paddle.to_tensor(images)
            labels = paddle.to_tensor(labels) 
            #前向计算的过程
            predits = model(images)
            
            #计算损失,取一个批次样本损失的平均值
            loss = F.square_error_cost(predits, labels)
            avg_loss = paddle.mean(loss)      
            
            #每训练了200批次的数据,打印下当前Loss的情况
            if batch_id % 200 == 0:
                print("epoch: {}, batch: {}, loss is: {}".format(epoch_id, batch_id, avg_loss.numpy()))
            
            #后向传播,更新参数的过程
            avg_loss.backward()
            opt.step()
            opt.clear_grad()
    # 保存模型
    paddle.save(model.state_dict(), './mnist.pdparams')
# 创建模型           
model = MNIST()
# 启动训练过程
train(model)

loading mnist dataset from ./work/mnist.json.gz ......

mnist dataset load done

训练数据集数量: 50000

epoch: 0, batch: 0, loss is: [15.857997]

epoch: 0, batch: 200, loss is: [9.080583]

epoch: 0, batch: 400, loss is: [9.78436]

epoch: 1, batch: 0, loss is: [7.9140673]

epoch: 1, batch: 200, loss is: [9.839129]

epoch: 1, batch: 400, loss is: [8.720339]...

epoch: 9, batch: 0, loss is: [9.359872]

epoch: 9, batch: 200, loss is: [9.66635]

epoch: 9, batch: 400, loss is: [6.984814]

2.3.5 基于飞桨Dataset和DataLoader API完成数据处理

上面我们对数据划分、训练样本乱序、生成批次数据以及如何封装数据读取与处理函数进行了详细的介绍。在飞桨框架中,可通过如下两个核心步骤完成数据集的定义与加载。

2.3.5.1 定义数据集

将磁盘中保存的原始图片、文字等样本和对应的标签映射到Dataset,方便后续通过索引index读取数据,在Dataset中还可以进行一些数据变换、数据增广等预处理操作。在飞桨框架中推荐使用paddle.io.Dataset自定义数据集,另外在paddle.vision.datasetspaddle.text目录下飞桨内置了一些经典数据集方便直接调用。

2.3.5.2 迭代读取数据集

自动将数据集的样本进行分批、乱序等操作,方便训练时迭代读取,同时还支持多进程异步读取功能可加快数据读取速度。在飞桨框架中可使用paddle.io.DataLoader迭代读取数据集。对于样本量较大、数据读取较慢的场景,建议采用异步数据读取方式。异步读取数据时,数据读取和模型训练并行执行,从而加快了数据读取速度,牺牲一小部分内存换取数据读取效率的提升,二者关系如图4所示。

图4:同步数据读取和异步数据读取示意图

(1)同步数据读取:数据读取与模型训练行。当模型需要数据时,才运行数据读取函数获得当前批次的数据。在读取数据期间,模型一直等待数据读取结束才进行训练,数据读取速度相对较慢。

(2)异步数据读取:数据读取和模型训练行。读取到的数据不断的放入缓存区,无需等待模型训练就可以启动下一轮数据读取。当模型训练完一个批次后,不用等待数据读取过程,直接从缓存区获得下一批次数据进行训练,从而加快了数据读取速度。

(3)异步队列:数据读取和模型训练交互的仓库,二者均可以从仓库中读取数据,它的存在使得两者的工作节奏可以解耦

通过飞桨paddle.io.Datasetpaddle.io.DataLoader两个API可以轻松创建异步数据读取的迭代器。

接下来我们具体来看如何借助这两个API轻松完成上述功能,具体代码如下:

In [10]

import json
import gzip
import paddle
from paddle.vision.transforms import Normalize
from paddle.io import Dataset
# 定义图像归一化处理方法,这里的CHW指图像格式需为 [C通道数,H图像高度,W图像宽度]
transform = Normalize(mean=[127.5], std=[127.5], data_format='CHW')
class MNISTDataset(Dataset):
    """
    步骤一:继承paddle.io.Dataset类
    """
    
    def __init__(self, datafile, mode='train', transform = None):
        """
        步骤二:实现构造函数
        """
        super().__init__()
        self.mode = mode
        self.transform = transform
        print('loading mnist dataset from {} ......'.format(datafile))
        # 加载json数据文件
        data = json.load(gzip.open(datafile))
        print('mnist dataset load done')
   
        # 读取到的数据区分训练集,验证集,测试集
        train_set, val_set, eval_set = data
        if mode=='train':
            # 获得训练数据集
            self.imgs, self.labels = train_set[0], train_set[1]
        elif mode=='valid':
            # 获得验证数据集
            self.imgs, self.labels = val_set[0], val_set[1]
        elif mode=='test':
            # 获得测试数据集
            self.imgs, self.labels = eval_set[0], eval_set[1]
        else:
            raise Exception("mode can only be one of ['train', 'valid', 'test']")
    
    def __getitem__(self, index):
        """
        步骤三:实现__getitem__方法,定义指定index时如何获取数据
        """
        data = self.imgs[index]
        label = self.labels[index]
        return self.transform(data),label
    def __len__(self):
        """
        步骤四:实现__len__方法,返回数据集总数目
        """
        return len(self.imgs)
datafile = './work/mnist.json.gz'
# 下载数据集并初始化 DataSet
train_dataset = MNISTDataset(datafile, mode='train', transform=transform)
test_dataset = MNISTDataset(datafile, mode='test', transform=transform)
print('train images: ', train_dataset.__len__(), ', test images: ', test_dataset.__len__())

loading mnist dataset from ./work/mnist.json.gz ......

mnist dataset load done

loading mnist dataset from ./work/mnist.json.gz ......

mnist dataset load done

train images: 50000 , test images: 10000

另外可通过transform字段传入一些对图像进行变换的操作,飞桨在paddle.vision.transforms下提供了一些常用的图像变换操作,如对图像进行中心裁剪、水平翻转图像和对图像进行归一化等。

完成数据集初始化之后,可以使用下面的代码打印数据的shape。

In [11]

from matplotlib import pyplot as plt
for data in train_dataset:
    image, label = data
    print('shape of image: ',image.shape)
    plt.title(str(label))
    plt.imshow(image[0])    
    break

/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/matplotlib/__init__.py:107: DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated, and in 3.8 it will stop working

from collections import MutableMapping

/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/matplotlib/rcsetup.py:20: DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated, and in 3.8 it will stop working

from collections import Iterable, Mapping

/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/matplotlib/colors.py:53: DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated, and in 3.8 it will stop working

from collections import Sized

shape of image: (1, 1, 784)

/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/matplotlib/cbook/__init__.py:2349: DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated, and in 3.8 it will stop working

if isinstance(obj, collections.Iterator):

/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/matplotlib/cbook/__init__.py:2366: DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated, and in 3.8 it will stop working

return list(data) if isinstance(data, collections.MappingView) else data

/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/matplotlib/image.py:425: DeprecationWarning: np.asscalar(a) is deprecated since NumPy v1.16, use a.item() instead

a_min = np.asscalar(a_min.astype(scaled_dtype))

/opt/coda/envs/python35-paddle120-env/lib/python3.7/site-packages/matplotlib/image.py:426: DeprecationWarning: np.asscalar(a) is deprecated since NumPy v1.16, use a.item() instead

a_max = np.asscalar(a_max.astype(scaled_dtype))

在定义完paddle.io.Dataset后,使用paddle.io.DataLoaderAPI即可实现异步数据读取,数据会由Python线程预先读取,并异步送入一个队列中,并且可自动完成划分 batch 的工作。

classpaddle.io.DataLoader(dataset, batch_size=100, shuffle=True, num_workers=2)

DataLoader返回一个迭代器,迭代的返回dataset中的数据内容;

dataset是支持map-style的数据集(可通过下标索引样本),map-style的数据集请参考paddle.io.DatasetAPI。

使用paddle.io.DataLoaderAPI以batch的方式进行迭代数据,代码如下:

In [4]

# 定义并初始化数据读取器
train_loader = paddle.io.DataLoader(train_dataset, batch_size=64, shuffle=True, 
                                    num_workers=1, 
                                    drop_last=True)
print('step num:',len(train_loader))

step num: 781

通过上述方法,初始化了一个数据读取train_loader,用于加载训练数据集。在数据读取器中几个常用的字段如下:

  • batch_size:每批次读取样本数,示例中 batch_size=64 表示每批次读取 64 个样本。
  • shuffle:样本乱序,示例中 shuffle=True 表示在取数据时打乱样本顺序,以减少过拟合发生的可能。
  • drop_last:丢弃不完整的批次样本,示例中 drop_last=True 表示丢弃因数据集样本数不能被 batch_size 整除而产生的最后一个不完整的 batch 样本。
  • num_workers:同步/异步读取数据,通过 num_workers 来设置加载数据的子进程个数,num_workers的值设为大于0时,即开启多进程方式异步加载数据,可提升数据读取速度。

为了方便后续过程对数据的使用,将数据处理过程封装data_process.py中,后面小节直接调用该文件的实现即可。

数据处理完成后,接下来让我们开始模型训练:

数据迭代器train_loader在每次迭代时的数据shape为[batch_size, 1, 28, 28],因此需要将该数据形 式reshape为向量形式。

In [6]

def train(model):
    print('train:')
    model.train()
    opt = paddle.optimizer.SGD(learning_rate=0.001, parameters=model.parameters())
    EPOCH_NUM = 3
    for epoch_id in range(EPOCH_NUM):
        print('epoch:',epoch_id)
        for batch_id, data in enumerate(train_loader()):
            images, labels = data
            images = paddle.to_tensor(images).astype('float32')
            labels = paddle.to_tensor(labels).astype('float32')
            
            images = paddle.reshape(images, [images.shape[0], images.shape[2]*images.shape[3]])
            #前向计算的过程  
            predicts = model(images)
            #计算损失,取一个批次样本损失的平均值
            loss = F.square_error_cost(predicts, labels)
            avg_loss = paddle.mean(loss)       
            
            #每训练了200批次的数据,打印下当前Loss的情况
            if batch_id % 200 == 0:
                print("epoch: {}, batch: {}, loss is: {}".format(epoch_id, batch_id, avg_loss.numpy()))
            
            #后向传播,更新参数的过程
            avg_loss.backward()
            opt.step()
            opt.clear_grad()
    #保存模型参数
    paddle.save(model.state_dict(), 'mnist.pdparams')
#创建模型
print("create model:")
model = MNIST()
#启动训练过程
train(model)

create model:

train:

epoch: 0

epoch: 0, batch: 0, loss is: [33.800125]

epoch: 0, batch: 200, loss is: [15.026532]

epoch: 0, batch: 400, loss is: [7.312279]

epoch: 0, batch: 600, loss is: [8.8055935].......

epoch: 2

epoch: 2, batch: 0, loss is: [10.347084]

epoch: 2, batch: 200, loss is: [7.91061]

epoch: 2, batch: 400, loss is: [9.701729]

epoch: 2, batch: 600, loss is: [8.192236]

2.3.6 数据增强/增广

任何数学技巧都不能弥补信息的缺失-Cornelius Lanczos(匈牙利数学家、物理学家)

本节介绍的各种数据处理方法仅限于为了实现深度学习任务,所必要的数据处理流程。但在实际任务中,原始数据集未必完全含有解决任务所需要的充足信息。这时候,通过分析任务场景,有针对性的做一些数据增强/增广的策略,往往可以显著的提高模型效果。

数据增强是一种挖掘数据集潜力的方法,可以让数据集蕴含更多让模型有效学习的信息。这些方法是领域和任务特定的,通过分析任务场景的复杂性和当前数据集的短板,对现有数据做有针对性的修改,以提供更加多样性的、匹配任务场景复杂性的新数据。下面以计算机视觉相关问题的数据增强为例,给读者一些具体增强方法和背后的思考。

2.3.6.1 基础的数据增强/增广方法和实践

图5所示为一些基础的图像增强方法,如果我们发现数据集中的猫均是标准姿势,而真实场景中的猫时常有倾斜身姿的情况,那么在原始图片数据的基础上采用旋转的方法造一批数据加入到数据集会有助于提升模型效果。类似的,如果数据集中均是高清图片,而真实场景中经常有拍照模糊或曝光异常的情况,则采用降采样和调整饱和度的方式造一批数据,回有助于提升模型的效果。

图5:基础的图像增强方法

接下来我们通过几个简单的小demo展示如何基于paddle.vision.transforms实现上述变换。

(1)亮度调整

In [13]

import numpy as np
from PIL import Image
from paddle.vision.transforms import functional as F
img_path = "/home/aistudio/work/cat.jpg"
image=Image.open(img_path)
# adjust_brightness对输入图像进行亮度值调整
new_img = F.adjust_brightness(image, 0.4)
# 显示图像
display(image.resize((300,400)))
display(new_img.resize((300,400)))

<PIL.Image.Image image mode=RGB size=300x400 at 0x7F9FA8D7A690>

<PIL.Image.Image image mode=RGB size=300x400 at 0x7F9FA961C910>

(2)色调调整

In [14]

import numpy as np
from PIL import Image
from paddle.vision.transforms import functional as F
img_path = "/home/aistudio/work/cat.jpg"
image=Image.open(img_path)
# adjust_hue对输入图像进行色调的调整
F.adjust_hue(image, 0.1)
# 显示图像
display(image.resize((300,400)))
display(new_img.resize((300,400)))

<PIL.Image.Image image mode=RGB size=300x400 at 0x7FA1289856D0>

<PIL.Image.Image image mode=RGB size=300x400 at 0x7F9FA9673490>

(3)随机旋转

In [15]

import numpy as np
from PIL import Image
from paddle.vision.transforms import RandomRotation
img_path = "/home/aistudio/work/cat.jpg"
image=Image.open(img_path)
# RandomRotation依据90度,按照均匀分布随机产生一个角度对图像进行旋转
transform = RandomRotation(90)
new_img = transform(image)
# 显示图像
display(image.resize((300,400)))
display(new_img.resize((300,400)))

<PIL.Image.Image image mode=RGB size=300x400 at 0x7F9FA8D98A90>

<PIL.Image.Image image mode=RGB size=300x400 at 0x7F9FA8DB0BD0>

2.3.6.2 高阶的数据增强/增广方法和实践

图6展示了一些高阶的图像增强方法,裁剪和拼接分别适合于“数据集中物体完整,但实际场景中物体存在遮挡”,以及“数据集中物体背景单一,而实际场景中物体的背景多变”的两种情况。具体数据增广实现,参见PaddleClas

图6:高阶的图像增强方法

(1)文本识别的数据增强方法

图7展示了专门针对文本识别的数据增强方法TIA(Text Image augmentation),对应到“数据集中字体多是平面,而真实场景中的字体往往会在曲面上扭曲的情况,比如拿着相机对一张凸凹不平摆放的纸面拍摄的文字就会存在该效果”。

图7:文本识别数据增强方法

(2)一种新颖的数据增强技巧CopyPaste

现实中的文字检测要面临复杂多样的背景,比如店铺牌匾上的文字周围的背景可能是非常多样的。我们将部分文本区域剪辑出来,随机摆放到图片的各种位置来生成数据用于训练,会大大提高模型在复杂背景中,检测到文字内容的能力

图8:一种新颖的数据增强技巧CopyPaste

由上述案例可见,数据增强/增广的方法是要根据实际领域和任务来进行设计的,在本书后续更深度的章节我们会展示如何基于飞桨来实现各种数据增强方法。在当前,读者仅需要了解,在深度学习任务的数据处理流程中常要采用这样的技巧。手写数字识别的任务比较简单,数据集也相对规整,并没有必要采用这些方法。

相关文章
|
1月前
|
机器学习/深度学习 人工智能 自然语言处理
深度学习的魔法:如何用神经网络解锁数据的奥秘
在人工智能的璀璨星空中,深度学习犹如一颗最亮的星,它以其强大的数据处理能力,改变了我们对世界的认知方式。本文将深入浅出地介绍深度学习的核心概念、工作原理及其在不同领域的应用实例,让读者能够理解并欣赏到深度学习技术背后的奇妙和强大之处。
34 3
|
9天前
|
机器学习/深度学习 TensorFlow 算法框架/工具
使用Python实现深度学习模型:智能数据隐私保护
使用Python实现深度学习模型:智能数据隐私保护
22 1
|
12天前
|
机器学习/深度学习 数据采集 计算机视觉
深度学习之缺失数据的图像修复
基于深度学习的缺失数据图像修复是一种通过深度学习技术填补图像中缺失或损坏部分的过程。这种技术在图像处理领域具有重要意义,能够改善图像的视觉质量,并在许多实际应用中发挥作用,如图像恢复、视频编辑和图像生成等。
27 4
|
10天前
|
API 数据处理 开发者
Polars中的急性与惰性API:性能优化与数据处理策略
Polars中的急性与惰性API:性能优化与数据处理策略
11 1
|
12天前
|
机器学习/深度学习 人工智能 自然语言处理
深度学习与神经网络:探索复杂数据的表示
【9月更文挑战第26天】深度学习作为人工智能领域的明珠,通过神经网络自动从大数据中提取高级特征,实现分类、回归等任务。本文介绍深度学习的基础、张量表示、非线性变换、反向传播及梯度下降算法,并探讨其在计算机视觉、自然语言处理等领域的应用与挑战。未来,深度学习将更加智能化,揭示数据背后的奥秘。
|
13天前
|
开发框架 JSON 缓存
震撼发布!Python Web开发框架下的RESTful API设计全攻略,让数据交互更自由!
在数字化浪潮推动下,RESTful API成为Web开发中不可或缺的部分。本文详细介绍了在Python环境下如何设计并实现高效、可扩展的RESTful API,涵盖框架选择、资源定义、HTTP方法应用及响应格式设计等内容,并提供了基于Flask的示例代码。此外,还讨论了版本控制、文档化、安全性和性能优化等最佳实践,帮助开发者实现更流畅的数据交互体验。
35 1
|
2月前
|
存储 JSON API
淘系API接口(解析返回的json数据)商品详情数据解析助力开发者
——在成长的路上,我们都是同行者。这篇关于商品详情API接口的文章,希望能帮助到您。期待与您继续分享更多API接口的知识,请记得关注Anzexi58哦! 淘宝API接口(如淘宝开放平台提供的API)允许开发者获取淘宝商品的各种信息,包括商品详情。然而,需要注意的是,直接访问淘宝的商品数据API通常需要商家身份或开发者权限,并且需要遵循淘宝的API使用协议。
淘系API接口(解析返回的json数据)商品详情数据解析助力开发者
|
1月前
|
XML JSON API
淘宝京东商品详情数据解析,API接口系列
淘宝商品详情数据包括多个方面,如商品标题、价格、图片、描述、属性、SKU(库存量单位)库存、视频等。这些数据对于买家了解商品详情以及卖家管理商品都至关重要。
|
2月前
|
数据采集 API 开发工具
淘系商品详情数据解析(属性youhui券sku详情图等)API接口开发系列
在电商领域,特别是像淘宝(淘系)这样的平台,商品详情数据对于商家、开发者以及数据分析师来说至关重要。这些数据包括但不限于商品属性、优惠券信息、SKU(Stock Keeping Unit)详情、商品图片、售后保障等。然而,直接访问淘宝的内部API接口通常需要特定的权限和认证,这通常只对淘宝的合作伙伴或内部开发者开放。 不过,对于需要这些数据的第三方开发者或商家,有几种方式可以间接获取或解析淘系商品详情数据: ——在成长的路上,我们都是同行者。这篇关于商品详情API接口的文章,希望能帮助到您。期待与您继续分享更多API接口的知识,请记得关注Anzexi58哦!
|
2月前
|
存储 算法 Java
Go 通过 Map/Filter/ForEach 等流式 API 高效处理数据
Go 通过 Map/Filter/ForEach 等流式 API 高效处理数据
下一篇
无影云桌面