『跟著雨哥學AI』系列:詳解飛槳框架數據管道

2021-01-18 飛槳PaddlePaddle
「跟著雨哥學AI」是百度飛槳開源框架近期針對高層API推出的系列課。本課程由多位資深飛槳工程師精心打造,不僅提供了從數據處理、到模型組網、模型訓練、模型評估和推理部署全流程講解;還提供了豐富的趣味案例,旨在幫助開發者更全面清晰地掌握百度飛槳框架的用法,並能夠舉一反三、靈活使用飛槳框架進行深度學習實踐。本章分別對內置數據集、數據集定義、數據增強、數據採樣以及數據加載這幾個功能點進行詳細的講解。
在上個月發布的 飛槳開源框架2.0,帶你走進全新高層API,十行代碼搞定深度學習模型開發  中,已經給大家簡單介紹了飛槳高層API的定義、特點、整體框架以及具體API。這節課我們將介紹飛槳高層API的第一個模塊--數據管道。俗話說『九層之臺,起於壘土』,數據管道是模型訓練過程中最重要的前置工作。在飛槳的整個框架中,數據管道包含了五個功能點:內置數據集、數據集定義、數據增強、數據採樣以及數據加載。接下來我將分別對這五個功能點進行詳細的講解。好的,那下面就讓我們進入今天的內容吧。在完成深度學習領域的任務時,我們最先面臨的挑戰就是數據處理,即需要將數據處理成模型能夠"看懂"的語言,從而進行模型的訓練。比如,在圖像分類任務中,我們需要按格式處理圖像數據與其對應的標籤,然後才能將其輸入到模型中,開始訓練。在這個過程中,我們需要將圖片數據從jpg、png或其它格式轉換為numpy array的格式,然後對其進行一些加工,如重置大小、旋轉變換、改變亮度等等,從而進行數據增強。所以,數據的預處理和加載方式很大程度上決定了模型最終的性能水平。傳統框架常常包含著複雜的數據加載模式,多重的預處理操作常常會勸退許多人。而飛槳框架為了簡化數據管道的流程,對數據管道相關的場景進行了高級封裝,通過非常少量代碼,即可實現數據的處理,更愉快的進行深度學習模型研發。
在數據管道總共包含5個模塊,分別是飛槳框架內置數據集、自定義數據集、數據增強、數據採樣以及數據加載5個部分。關係圖如下: 為了節約大家處理數據時所耗費的時間和精力,飛槳框架將一些我們常用到的數據集作為領域API對用戶進行開放,用戶通過調用paddle.vision.datasets和paddle.text.datasets即可直接使用領域API,這兩個API內置包含了許多CV和NLP領域相關的常見數據集,具體如下:

import paddle
import numpy as np

paddle.__version__
'2.0.0-rc1'

print('視覺相關數據集:', paddle.vision.datasets.__all__)
print('自然語言相關數據集:', paddle.text.datasets.__all__)
視覺相關數據集: ['DatasetFolder', 'ImageFolder', 'MNIST', 'FashionMNIST', 'Flowers', 'Cifar10', 'Cifar100', 'VOC2012']
自然語言相關數據集: ['Conll05st', 'Imdb', 'Imikolov', 'Movielens', 'UCIHousing', 'WMT14', 'WMT16']

為了方便大家理解,這裡我演示一下如何使用內置的手寫數字識別的數據集,其他數據集的使用方式也類似,大家可以動手試一下哦。具體可以見下面的代碼,注意,我們通過使用mode參數用來標識訓練集與測試集。調用數據集接口後,相應的API會自動下載數據集到本機緩存目錄~/.cache/paddle/dataset。

import paddle.vision as vision


print("訓練集下載中...")
# 訓練數據集
train_dataset = vision.datasets.MNIST(mode='train')
print("訓練集下載完成!")
print("測試集下載中...")
# 驗證數據集
test_dataset = vision.datasets.MNIST(mode='test')
print("測試集下載完成!")
訓練集下載中...
Cache file /home/aistudio/.cache/paddle/dataset/mnist/train-images-idx3-ubyte.gz not found, downloading https://dataset.bj.bcebos.com/mnist/train-images-idx3-ubyte.gz 
Begin to download

Download finished
Cache file /home/aistudio/.cache/paddle/dataset/mnist/train-labels-idx1-ubyte.gz not found, downloading https://dataset.bj.bcebos.com/mnist/train-labels-idx1-ubyte.gz 
Begin to download
........
Download finished
訓練集下載完成!
測試集下載中...
Cache file /home/aistudio/.cache/paddle/dataset/mnist/t10k-images-idx3-ubyte.gz not found, downloading https://dataset.bj.bcebos.com/mnist/t10k-images-idx3-ubyte.gz 
Begin to download

Download finished
Cache file /home/aistudio/.cache/paddle/dataset/mnist/t10k-labels-idx1-ubyte.gz not found, downloading https://dataset.bj.bcebos.com/mnist/t10k-labels-idx1-ubyte.gz 
Begin to download
..
Download finished
測試集下載完成!

通過上面的步驟,我們就定義好了訓練集與測試集,接下來,讓我們來看一下數據集的內容吧。

import numpy as np
import matplotlib.pyplot as plt


train_data_0, train_label_0 = np.array(train_dataset[0][0]), train_dataset[0][1]
train_data_0 = train_data_0.reshape([28, 28])

plt.figure(figsize=(2, 2))
plt.imshow(train_data_0, cmap=plt.cm.binary)
print('train_data0 label is: ' + str(train_label_0))
train_data0 label is: [5]

從上例中可以看出,train_dataset 是一個 map-style 式的數據集,我們可以通過下標直接獲取單個樣本的圖像數據與標籤,從而進行可視化。
Note: map-style 是指可以通過下標的方式來獲取指定樣本,除此之外,還有 iterable-style 式的數據集,只能通過迭代的方式來獲取樣本,具體說明可以見下一節。有同學提出雖然飛槳框架提供了許多領域數據集供我們使用,但是在實際的使用場景中,如果我們需要使用已有的數據來訓練模型怎麼辦呢?別慌,飛槳也貼心地準備了 map-style 的 paddle.io.Dataset 基類 和 iterable-style 的 paddle.io.IterableDataset 基類 ,來完成數據集定義。此外,針對一些特殊的場景,飛槳框架也提供了 paddle.io.TensorDataset 基類,可以直接處理 Tensor 數據為 dataset,一鍵完成數據集的定義。
這個是我們最推薦使用的API,來完成數據的定義。使用 paddle.io.Dataset,最後會返回一個 map-style 的 Dataset 類。可以用於後續的數據增強、數據加載等。而使用 paddle.io.Dataset 也非常簡單,只需要按格式完成以下四步即可。

class MyDataset(paddle.io.IterableDataset):
    """
    步驟一:繼承paddle.io.IterableDataset類
    """
    def __init__(self, mode='train'):
        """
        步驟二:實現構造函數,定義數據讀取方式,劃分訓練和測試數據集
        """
        super(MyDataset, self).__init__()

        if mode == 'train':
            self.data = [
                ['train_image_0.jpg', '1'],
                ['train_image_1.jpg', '2'],
                ['train_image_2.jpg', '3'],
                ['train_image_3.jpg', '4'],
            ]
        else:
            self.data = [
                ['test_image_0.jpg', '1'],
                ['test_image_1.jpg', '2'],
                ['test_image_2.jpg', '3'],
                ['test_image_3.jpg', '4'],
            ]

    def _load_img(self, image_path):
        # 實際使用時使用Pillow相關庫進行圖片讀取即可,這裡我們對數據先做個模擬
        image = np.random.randn(32, 32, 3)

        return image

    def __getitem__(self, index):
        """
        步驟三:實現__getitem__方法,定義指定index時如何獲取數據,並返回單條數據(訓練數據,對應的標籤)
        """
        image = self._load_img(self.data[index][0])
        label = self.data[index][1]

        return image, np.array(label, dtype='int64')

    def __len__(self):
        """
        步驟四:實現__len__方法,返回數據集總數目
        """
        return len(self.data)

# 測試定義的數據集
train_dataset = MyDataset(mode='train')
test_dataset = MyDataset(mode='test')

print('=============train dataset=============')
for image, label in train_dataset:
    print('image shape: {}, label: {}'.format(image.shape, label))

print('=============evaluation dataset=============')
for image, label in test_dataset:
    print('image shape: {}, label: {}'.format(image.shape, label))
=============train dataset=============
image shape: (32, 32, 3), label: 1
image shape: (32, 32, 3), label: 2
image shape: (32, 32, 3), label: 3
image shape: (32, 32, 3), label: 4
=============evaluation dataset=============
image shape: (32, 32, 3), label: 1
image shape: (32, 32, 3), label: 2
image shape: (32, 32, 3), label: 3
image shape: (32, 32, 3), label: 4

看了上面的例子,你是否想自己動手寫一個Dataset呢?就讓我用實戰來演示一下:

# 下載訓練集
!wget http://fashion-mnist.s3-website.eu-central-1.amazonaws.com/train-images-idx3-ubyte.gz
# 下載訓練集標籤
!wget http://fashion-mnist.s3-website.eu-central-1.amazonaws.com/train-labels-idx1-ubyte.gz
# 下載測試集
!wget http://fashion-mnist.s3-website.eu-central-1.amazonaws.com/t10k-images-idx3-ubyte.gz
# 下載測試集標籤
!wget http://fashion-mnist.s3-website.eu-central-1.amazonaws.com/t10k-labels-idx1-ubyte.gz

import os
import gzip


class FashionMNISTDataset(paddle.io.Dataset):
    """
    步驟一:繼承paddle.io.Dataset類
    """
    def __init__(self, path='./', mode='train'):
        """
        步驟二:實現構造函數,定義數據讀取方式,劃分訓練和測試數據集
        """
        super(FashionMNISTDataset, self).__init__()

        images_data_path = os.path.join(path,
                               '%s-images-idx3-ubyte.gz'
                               % mode)
        labels_data_path = os.path.join(path,
                               '%s-labels-idx1-ubyte.gz'
                               % mode)
        with gzip.open(labels_data_path, 'rb') as lbpath:
            self.labels = np.frombuffer(lbpath.read(), dtype=np.uint8,
                               offset=8)

        with gzip.open(images_data_path, 'rb') as imgpath:
            self.images = np.frombuffer(imgpath.read(), dtype=np.uint8,
                               offset=16).reshape(len(self.labels), 784)

    def __getitem__(self, index):
        """
        步驟三:實現__getitem__方法,定義指定index時如何獲取數據,並返回單條數據(訓練數據,對應的標籤)
        """
        image = self.images[index]
        label = self.labels[index]

        return image, label

    def __len__(self):
        """
        步驟四:實現__len__方法,返回數據集總數目
        """
        return len(self.images)

# 測試定義的數據集
fashion_mnist_train_dataset = FashionMNISTDataset(mode='train')
fashion_mnist_test_dataset = FashionMNISTDataset(mode='t10k')

# 可視化訓練集
fashion_mnist_train_data_0 = np.array(fashion_mnist_train_dataset[0][0])
fashion_mnist_train_label_0 = fashion_mnist_train_dataset[0][1]
fashion_mnist_train_data_0 = fashion_mnist_train_data_0.reshape([28,28])
plt.figure(figsize=(2,2))
plt.imshow(fashion_mnist_train_data_0, cmap=plt.cm.binary)
print('train_data0 label is: ' + str(fashion_mnist_train_label_0))
train_data0 label is: 9

paddle.io.IterableDataset 的使用方式使用 paddle.io.IterableDataset,最後會返回一個 iterable-style 的 Dataset 類。而使用 paddle.io.IterableDataset 也非常簡單,只需要按格式完成以下兩步即可。

import math
import paddle
import numpy as np
from paddle.io import IterableDataset, DataLoader, get_worker_info

class SplitedIterableDataset(IterableDataset):
    """
    步驟一:繼承paddle.io.Dataset類
    """
    def __init__(self, start, end):
        self.start = start
        self.end = end

    def __iter__(self):
        """
        步驟二:實現__iter__方法,
        """    
        worker_info = get_worker_info()
        if worker_info is None:
            iter_start = self.start
            iter_end = self.end
        else:
            per_worker = int(
                math.ceil((self.end - self.start) / float(
                    worker_info.num_workers)))
            worker_id = worker_info.id
            iter_start = self.start + worker_id * per_worker
            iter_end = min(iter_start + per_worker, self.end)
        for i in range(iter_start, iter_end):
            yield np.array([i])


dataset = SplitedIterableDataset(start=2, end=9)
dataloader = DataLoader(dataset, num_workers=2, batch_size=1, drop_last=True)

for data in dataloader:
    print(data[0].numpy())
[[2]]
[[6]]
[[3]]
[[7]]
[[4]]
[[8]]
[[5]]

paddle.io.TensorDataset的使用方式上面介紹了兩種數據集的定義方式,分別通過繼承paddle.io.Dataset與paddle.io.IterableDataset就可以實現。不過,還有一種場景,如果我們已經有了Tensor類型的數據,想要快速、直接的創建Dataset,而不去實現paddle.io.Dataset的各種方法,可以麼?這時,我們就可以使用 paddle.io.TensorDataset,直接將 Tensor 類型的 數據與標籤傳入 TensorDataset 類即可。

from paddle.io import TensorDataset


input_np = np.random.random([2, 3, 4]).astype('float32')
input_tensor = paddle.to_tensor(input_np)
label_np = np.random.random([2, 1]).astype('int32')
label_tensor = paddle.to_tensor(label_np)

dataset = TensorDataset([input_tensor, label_tensor])

for i in range(len(dataset)):
    input, label = dataset[i]
    print(input, label)
Tensor(shape=[3, 4], dtype=float32, place=CUDAPlace(0), stop_gradient=True,
       [[0.91451722, 0.94088864, 0.52030772, 0.80783033],
        [0.74379814, 0.18669823, 0.41893899, 0.89299613],
        [0.67413408, 0.82801068, 0.02079745, 0.95862854]]) Tensor(shape=[1], dtype=int32, place=CUDAPlace(0), stop_gradient=True,
       [0])
Tensor(shape=[3, 4], dtype=float32, place=CUDAPlace(0), stop_gradient=True,
       [[0.30733261, 0.82390237, 0.99652219, 0.93594497],
        [0.62558615, 0.83836132, 0.34213212, 0.72257715],
        [0.80075997, 0.38913822, 0.25709155, 0.00520579]]) Tensor(shape=[1], dtype=int32, place=CUDAPlace(0), stop_gradient=True,
       [0])

可以看出,我們將Tensor類型的 input 與 label 直接傳入TensorDataset中,就可以完成 Dataset 的定義,完全不需要實現上述自定義的那四個步驟。在我們的實際使用中,如果想要簡單的做個測試,完全可以直接使用TensorDataset來創建數據集。那麼,使用 TensorDataset 有什麼要求呢?只有一個要求,就是傳入的 Tensor,它們的第一維維度要相同,從上例中可以看出, input 與 label 的第一維都是2,代表數據集的大小。在訓練模型的過程中,我們偶爾會遇到過擬合的問題。這時,最好的做法是增加訓練集的數量,以此提升模型的泛化能力。但是,由於獲取數據集的成本比較高,所以通常我們都會採用增強訓練數據的方式對數據進行處理,從而得到更多不同的數據集。在計算機視覺領域中,常見的數據增強的方式包括隨機裁剪、旋轉變換、改變圖像亮度、對比度等等。可以看出,這些方法都是對圖像的常見處理方式,所以,飛槳框架直接提供了這類的API,定義在paddle.vision.transofrms下,包含了計算機視覺中對圖像的各種常用的處理,具體如下:

print("飛槳支持的數據預處理方式:" + str(paddle.vision.transforms.__all__))
飛槳支持的數據預處理方式:['BaseTransform', 'Compose', 'Resize', 'RandomResizedCrop', 'CenterCrop', 'RandomHorizontalFlip', 'RandomVerticalFlip', 'Transpose', 'Normalize', 'BrightnessTransform', 'SaturationTransform', 'ContrastTransform', 'HueTransform', 'ColorJitter', 'RandomCrop', 'Pad', 'RandomRotation', 'Grayscale', 'ToTensor', 'to_tensor', 'hflip', 'vflip', 'resize', 'pad', 'rotate', 'to_grayscale', 'crop', 'center_crop', 'adjust_brightness', 'adjust_contrast', 'adjust_hue', 'normalize']

那麼該怎麼使用呢?我們這裡分兩種場景來介紹,一種是飛槳內置數據集使用數據增強,另一種是自定義數據集使用數據增強。內置數據集使用數據增強的方式非常簡單,我們可以直接定義一個數據預處理的方式,然後將其作為參數,在加載內置數據集的時候,傳給 transform 參數即可;而如果我們想對一個數據集進行多個數據預處理的方式,可以先定義一個 transform 的容器 Compose,將我們需要的數據預處理方法以 list 的格式傳入 Compose,然後在加載內置數據集的時候,傳給 transform 參數即可。

import paddle.vision.transforms as T


# 方式一 只對圖像進行調整亮度的操作
transform = T.BrightnessTransform(0.4)
# 通過transform參數傳遞定義好的數據增方法即可完成對自帶數據集的數據增強
train_dataset_without_transform = vision.datasets.Cifar10(mode='train')
train_dataset_with_transform = vision.datasets.Cifar10(mode='train', transform=transform)

index = 10
print("未調整亮度的圖像")
train_dataset_without_data_0 = np.array(train_dataset_without_transform[index][0])
train_dataset_without_data_0 = train_dataset_without_data_0.astype('float32') / 255.
plt.imshow(train_dataset_without_data_0)
未調整亮度的圖像
<matplotlib.image.AxesImage at 0x7fb13e129090>

print("調整亮度的圖像")
train_dataset_with_data_0 = np.array(train_dataset_with_transform[index][0])
train_dataset_with_data_0 = train_dataset_with_data_0.astype('float32') / 255.
plt.imshow(train_dataset_with_data_0)
調整亮度的圖像
<matplotlib.image.AxesImage at 0x7fb19b1b5f90>

import paddle.vision.transforms as T

# 方式二 對圖像進行多種操作
transform = T.Compose([T.BrightnessTransform(0.4), T.ContrastTransform(0.4)])
# 通過transform參數傳遞定義好的數據增方法即可完成對自帶數據集的數據增強
train_dataset_without_compose = vision.datasets.Cifar10(mode='train')
train_dataset_with_compose = vision.datasets.Cifar10(mode='train', transform=transform)

index = 10
print("未調整的圖像")
train_dataset_without_compose_data_0 = np.array(train_dataset_without_compose[index][0])
train_dataset_without_compose_data_0 = train_dataset_without_compose_data_0.astype('float32') / 255.
plt.imshow(train_dataset_without_compose_data_0)
未調整的圖像
<matplotlib.image.AxesImage at 0x7fb13065fb90>

print("多種調整後的圖像")
train_dataset_with_compose_data_0 = np.array(train_dataset_with_compose[index][0])
train_dataset_with_compose_data_0 = train_dataset_with_compose_data_0.astype('float32') / 255.
plt.imshow(train_dataset_with_compose_data_0)
多種調整後的圖像
<matplotlib.image.AxesImage at 0x7fb1b818c610>

針對自定義數據集使用數據增強的方式, 比較直觀的方式是在在數據集的構造函數中進行數據增強方法的定義,之後對__getitem__中返回的數據進行應用。我們以上述中FashionMNIST數據集為例來說明,具體如下:

class FashionMNISTDataset(paddle.io.Dataset):
    """
    步驟一:繼承paddle.io.Dataset類
    """
    def __init__(self, path='./', mode='train', transform='None'):
        """
        步驟二:實現構造函數,定義數據讀取方式,劃分訓練和測試數據集
        """
        super(FashionMNISTDataset, self).__init__()

        images_data_path = os.path.join(path,
                               '%s-images-idx3-ubyte.gz'
                               % mode)
        labels_data_path = os.path.join(path,
                               '%s-labels-idx1-ubyte.gz'
                               % mode)
        with gzip.open(labels_data_path, 'rb') as lbpath:
            self.labels = np.frombuffer(lbpath.read(), dtype=np.uint8,
                               offset=8)

        with gzip.open(images_data_path, 'rb') as imgpath:
            self.images = np.frombuffer(imgpath.read(), dtype=np.uint8,
                               offset=16).reshape(len(self.labels), 784)
        self.transform = None
        if transform != 'None':
            self.transform = transform

    def __getitem__(self, index):
        """
        步驟三:實現__getitem__方法,定義指定index時如何獲取數據,並返回單條數據(訓練數據,對應的標籤)
        """
        if self.transform:
            image = self.transform(self.images[index].reshape(28, 28))
        else:
            image = self.images[index]
        label = self.labels[index]

        return image, label

    def __len__(self):
        """
        步驟四:實現__len__方法,返回數據集總數目
        """
        return len(self.images)

# 測試未處理的數據集
fashion_mnist_train_dataset_without_transform = FashionMNISTDataset(mode='train')

# 可視化
fashion_mnist_train_dataset_without_transform = np.array(fashion_mnist_train_dataset_without_transform[0][0])
fashion_mnist_train_dataset_without_transform = fashion_mnist_train_dataset_without_transform.reshape([28, 28])
plt.imshow(fashion_mnist_train_dataset_without_transform, cmap=plt.cm.binary)
<matplotlib.image.AxesImage at 0x7fb130421ed0>

# 測試處理的數據集
from paddle.vision.transforms import RandomVerticalFlip
fashion_mnist_train_dataset_with_transform = FashionMNISTDataset(mode='train', transform=RandomVerticalFlip(0.4))

# 可視化
fashion_mnist_train_dataset_with_transform = np.array(fashion_mnist_train_dataset_with_transform[0][0])
fashion_mnist_train_dataset_with_transform = fashion_mnist_train_dataset_with_transform.reshape([28, 28])
plt.imshow(fashion_mnist_train_dataset_with_transform, cmap=plt.cm.binary)
<matplotlib.image.AxesImage at 0x7fb130367b50>

當我們定義了數據集後,就需要加載數據集。我們可以通過 paddle.io.DataLoader 完成數據的加載。

train_loader = paddle.io.DataLoader(train_dataset, batch_size=64, shuffle=True)

for batch_id, data in enumerate(train_loader()):
    x_data = data[0]
    y_data = data[1]
    print(x_data.numpy().shape)
    print(y_data.numpy().shape)
    break
(4, 32, 32, 3)
(4,)

DataLoader 可以加載我們定義好的數據集。雖然看起來很簡單是很簡單的操作,但是,DataLoader 的參數中包含了許多強大的功能。如 shuffle 設為 True, 可以對下標進行隨機打散的操作;drop_last 設為 True 可以丟掉最後一個不滿足 batch_size 大小的 batch;num_workers 可以設置多個子進程來加速數據加載。此外,我們還可以針對不同的數據集,設置不同的採樣器,來完成數據的採樣。飛槳框架提供了多種數據採樣器,用於不同的場景,來提升訓練模型的泛化性能。飛槳框架包含的採樣器如下:paddle.io.BatchSampler 、 paddle.io.DistributedBatchSampler 、paddle.io.RandomSampler、paddle.io.SequenceSampler 等,接下來來一一介紹。

from paddle.io import SequenceSampler, RandomSampler, BatchSampler, DistributedBatchSampler

class RandomDataset(paddle.io.Dataset):
    def __init__(self, num_samples):
        self.num_samples = num_samples

    def __getitem__(self, idx):
        image = np.random.random([784]).astype('float32')
        label = np.random.randint(0, 9, (1, )).astype('int64')
        return image, label

    def __len__(self):
        return self.num_samples

train_dataset = RandomDataset(100)

print('--順序採樣-')
sampler = SequenceSampler(train_dataset)
batch_sampler = BatchSampler(sampler=sampler, batch_size=10)

for index in batch_sampler:
    print(index)

print('--隨機採樣-')
sampler = RandomSampler(train_dataset)
batch_sampler = BatchSampler(sampler=sampler, batch_size=10)

for index in batch_sampler:
    print(index)

print('--分布式採樣-')
batch_sampler = DistributedBatchSampler(train_dataset, num_replicas=2, batch_size=10)

for index in batch_sampler:
    print(index)

--順序採樣-
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
[20, 21, 22, 23, 24, 25, 26, 27, 28, 29]
[30, 31, 32, 33, 34, 35, 36, 37, 38, 39]
[40, 41, 42, 43, 44, 45, 46, 47, 48, 49]
[50, 51, 52, 53, 54, 55, 56, 57, 58, 59]
[60, 61, 62, 63, 64, 65, 66, 67, 68, 69]
[70, 71, 72, 73, 74, 75, 76, 77, 78, 79]
[80, 81, 82, 83, 84, 85, 86, 87, 88, 89]
[90, 91, 92, 93, 94, 95, 96, 97, 98, 99]
--隨機採樣-
[9, 7, 54, 93, 84, 14, 12, 46, 67, 72]
[10, 57, 32, 61, 38, 71, 63, 51, 37, 11]
[21, 76, 69, 22, 48, 88, 19, 59, 47, 60]
[89, 85, 31, 80, 91, 30, 50, 52, 39, 3]
[70, 45, 62, 75, 35, 8, 96, 94, 5, 98]
[49, 33, 28, 13, 18, 42, 90, 0, 36, 79]
[81, 15, 6, 78, 40, 86, 2, 23, 95, 43]
[87, 65, 68, 25, 99, 26, 73, 82, 1, 53]
[77, 29, 17, 44, 55, 4, 56, 64, 97, 83]
[66, 41, 16, 74, 92, 34, 27, 24, 58, 20]
--分布式採樣-
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[20, 21, 22, 23, 24, 25, 26, 27, 28, 29]
[40, 41, 42, 43, 44, 45, 46, 47, 48, 49]
[60, 61, 62, 63, 64, 65, 66, 67, 68, 69]
[80, 81, 82, 83, 84, 85, 86, 87, 88, 89]

恭喜同學們學會了數據集的下載、數據集的自定義、數據的預處理以及數據的批加載等知識,大家已經可以很好地應對模型訓練任務的第一步啦。那麼今天的課程到這裡就結束了,對課程內容有疑問或者建議的同學可以在評論區留言,看到後我會及時回復哦,最後希望大家fork一下該項目,不然就找不到這個課程了。我是雨哥,下節課見~
有任何問題可以在本項目中評論或到飛槳Github倉庫(連結)提交Issue。https://www.paddlepaddle.org.cn/GitHub: https://github.com/PaddlePaddle/Paddle 
Gitee: https://gitee.com/paddlepaddle/Paddle

飛槳(PaddlePaddle)以百度多年的深度學習技術研究和業務應用為基礎,是中國首個開源開放、技術領先、功能完備的產業級深度學習平臺,包括飛槳開源平臺和飛槳企業版。飛槳開源平臺包含核心框架、基礎模型庫、端到端開發套件與工具組件,持續開源核心能力,為產業、學術、科研創新提供基礎底座。飛槳企業版基於飛槳開源平臺,針對企業級需求增強了相應特性,包含零門檻AI開發平臺EasyDL和全功能AI開發平臺BML。EasyDL主要面向中小企業,提供零門檻、預置豐富網絡和模型、便捷高效的開發平臺;BML是為大型企業提供的功能全面、可靈活定製和被深度集成的開發平臺。

相關焦點

  • 飛槳框架高層API,輕鬆玩轉AI
    高層 API,All飛槳框架高層 API 的全景圖如下:從圖中可以看出,飛槳框架高層 API 由五個模塊組成,分別是數據加載、模型組建、模型訓練、模型可視化和高階用法。,在一些典型的任務中,我們完全可以使用飛槳框架內置的數據集,完成數據的加載。
  • 『支原體qPCR檢測』的方法學驗證
    近年來,『支原體qPCR檢測』在工業領域的應用越來越多,但在項目申報前,先需要進行方法學驗證,依據藥典,在檢測限、特異性和耐用性方面達到要求後,才能替代傳統的檢查方法。 就筆者所知,在適合工業的支原體檢測和方法驗證方面,德國Minerva Biolabs(簡稱MB)公司已有很成熟的產品及商業化應用,它不僅提供有符合國際藥典的『支原體qPCR檢測』試劑盒,而且有一系列支原體標準品及輔助產品,用於qPCR方法的全面驗證。這些產品性價比也較高,全球許多客戶都在使用。
  • 新MB |『為了即將到來的對話』:GNT-0000 量子型00高達登陸MB系列!
    MB系列首次搭載LED原件,前後各安裝有2枚LED,再現GN爐發光時的美麗外觀。通過卸除、更換裝甲零件可再現劇中「Quantum Burst」的形態。附帶GN浮遊劍展示用的圓環,可作出劇中令人印象深刻的場景。GN劍單元/浮遊劍不僅可變形為炮擊、巨劍模式,還能通過專用支架和配件再現浮遊、GN立場發生時的狀態。3種浮遊劍依靠收納式的握柄,全部可手持使用。
  • 『哥斯拉 -怪獸行星-』正式預告公開
    虛淵玄 x 靜野孔文 x 瀬下寛之 的『哥斯拉』終於有了正式 PV『哥斯拉 -怪獸行星-』是一個系列作的完全新作動畫。_(:з」∠)_動畫是由 Polygon Pictures 負責製作,怪不得畫風像『亞人』和『希德尼婭的騎士』,尤其是預告裡人的衣服好像希德尼婭啊。
  • 機設 『高達真正的子嗣』擬太陽爐量產機GNX-803T GN-XⅣ
    在名為『天上人』號宇宙飛船內和天上人與變革者之間的決戰後所回收的大量的MS機體殘骸和被天上人的中央控制電腦Veda所緊急制御而當機的MS,Innovator的技術被聯邦軍技術人員開始全力破解,包括V字小型天線控制GN粒子散布、GN粒子壓縮技術在內的新技術都一併運用到了新型GNX的開發當中去。
  • 『因果推斷』主要英文期刊推薦
    很多小夥伴在問,如何快速地獲取最新的『因果推斷』相關研究成果,小編的建議就是有針對性地選擇幾本經常刊發『因果推斷』理論、方法與應用的期刊,跟蹤期刊最新的文章
  • 朋友圈瘋傳過的10條『近視謠言』,90%的人至今仍深信不疑!
    『 眼鏡戴上就摘不下來了, 所以能不戴儘量別戴 』 事實真是這樣嗎?』 你相信過幾條呢?
  • 『表面張力』
    水問題をアートする展覧會『表面張力:水の未來』您是否知道製作雞蛋需要200升水,一件T恤需要2000升水?
  • 『黑科技·27』人造肌肉:對人類運動的探索與建造
    氣動人造肌肉主要運用氣流通過管道結構所造成的壓力,產生變形運動。東京科技大學的 Suzumori Endo Lab 按照人類身體的肌肉纖維比例,利用氣動肌肉連結在骨架上,成功模擬了人類的各種運動。『黑科技·26』Robobee:昆蟲機器人襲來
  • 『因果關係』英文研究熱點知識圖譜
    前面我們分享了『因果關係』中文研究熱點知識圖譜(←超連結)
  • 坂本龍一+12位全球音樂人『INCOMPLETE』系列
    圖片來源:坂本龍一工作室 坂本龍一+12位全球音樂人 『INCOMPLETE』系列 About 『INCOMPLETE』 Series
  • 『求生者對海月水母的理解』
    長按下方二維碼識別免費關注『荒野求生訂閱號>』點擊下方文章以及↓「閱讀原文」↓獲取更多資訊『徒手製作一個加熱煮沸型海水蒸餾裝置』『置身沿海荒野的食物問題』消滅寄生蟲的新技能『如何及時應對迷路的要領』
  • 『點亮屏幕:攝·影·書』開啟冬日閱讀模式
    原創 PHOTOFAIRS PHOTOFAIRS影像藝術博覽會 收錄於話題#2021年影像上海藝術博覽會4#影像藝術博覽會2#『出版』1#『點亮屏幕:攝·影·書』1#如何讀,為什麼讀1
  • 《伊洛納elona》新夥伴——『塞德娜女皇號』介紹
    這是一位在商城中最新推出的夥伴,目前她的入手概率提升,冒險者們有高達1.5%的概率抽中『塞德娜女皇號』哦。 『塞德娜女皇號』的種族職業是機械和觀光客,她具有「洪流(在目標周圍製造一片海的氣息,對目標造成傷害並減速一段時間)」和「傳奇朗姆酒(給周圍的隊友發放朗姆酒,有機率免疫傷害
  • 學習PaddlePaddle(飛槳)是正確的選擇
    學習PaddlePaddle(飛槳)是正確的選擇深耕PaddlePaddle,非常高興和大家一起學習PaddlePaddle。為什麼要學習飛槳?在開始分享之前,我想先簡單聊聊——為什麼要學習飛槳。之所以說簡單聊聊,是我準備在學習飛槳滿一周年的時候再詳細分享一下(這裡算是做一個預告)。我們學習什麼總要有點目的。比如今年三十歲的我就想做一件讓自己覺得很酷的事,所以我學習了滑板,學習了滑板相關的知識,看了相關的影片等等。讓我得瑟一下。
  • 飛槳閃耀2019百度雲智峰會,軟硬結合助力產業智能化
    AI加速器性能提升了近30倍,兼容飛槳深度學習框架,針對圖像、語音、NLP等AI能力專門優化,使得中國的AI跑在自主可控的AI晶片上;企業級AI開發平臺——百度機器學習BML4.0,全面涵蓋從數據到模型再到服務的AI全流程,支撐端、邊、雲一體化,內置飛槳深度學習框架,集成超過70個飛槳自研模型,超過60個高性能算子。
  • 百度統計:一個SEM的『作弊器』
    好了,進入正題,今天談的是百度統計對SEM來說,可能是個作弊器,這裡先普及一個知識,百度統計有兩個版本,一個是百度統計站長版,另外一個是百度統計推廣版,一個是可以統計全站的流量的,一個是只針對百度SEM投放數據進行統計分析的,今天講的就是關於百度統計推廣版。
  • 『PBR材質』正確打開方式
    不管是新觀眾還是老朋友,相信各位大多都看過我的這篇推送:『材質貼圖』正確打開方式表格中的數據均為線性數值,包括 Diffuse 基色。# 往期推薦『陰天』表現思路解析『日景』表現思路解析『室內布光』正確打開方式
  • 小書單 | 兩本獲獎『新書』:現實正走向科幻與奇幻
    一本是打敗大劉《三體3:死神永生》獲得美國科幻奇幻協會『星雲獎』的《群鳥飛舞的世界末日》;一本是今年諾貝爾文學獎獲得者石黑一雄的《被掩埋的巨人》
  • 『認識』鉸刀特點·用途·種類
    鉸刀的特點:鉸刀效率(精鏜孔均是單刃切削,而鉸刀都在4-8刃切削,所以效率遠高於鏜刀)、高精度、鉸刀刃口帶有刃帶,所以獲得更好的粗糙度;『歡迎關注品悅陽光』