コンテンツにスキップ

データローダ

EIPLでは、Pytorchが標準で提供するDatasetクラスを継承した、ロボット動作学習のためのMultimodalDatasetクラスを提供している。 本クラスは毎エポック、モデルへの入力データ x_data と真値 y_data のペアを返す。 入力データx_dataは画像と関節角度のペアになっており、毎エポックデータ拡張を行う。 入力画像には、照明変化に対するロバスト性を向上させるために輝度やコントラストなどをランダムに付与し、入力関節角度には、手先位置誤差に対するロバスト性を向上させるためにガウシアンノイズを付与している。 一方で出力データには一切ノイズを加えていない。 モデルはノイズが混じった入力データから、ノイズを無視した状況(内部表現)を学習することで、推論時は実世界のノイズに対しロバストな動作生成が可能になる。

以下は、AIRECを用いて収集した物体把持タスクを例に、MultimodalDatasetクラスの利用方法を示している。 MultimodalDatasetクラスに5次元の画像時系列データ(データ数、時系列長、チャネル、縦、横)と3次元の関節角度時系列データ(データ数、時系列長、関節数)を渡すことで自動的にデータ拡張などが行われる。 なお、SampleDownloaderはEIPLのサンプルデータのダウンロードを行うクラスであり、必ずしも必要ではない。 numpy.load関数などを用いて、自作データセットを直接読み込んでも良い。

サンプルデータセットの使い方
from eipl.data import SampleDownloader, MultimodalDataset

# サンプルデータをダウンロードし、正規化
grasp_data = SampleDownloader("airec", "grasp_bottle", img_format="CHW")
images, joints = grasp_data.load_norm_data("train", vmin=0.1, vmax=0.9)

# 画像と関節角度をDatasetクラスに渡す
multi_dataset = MultimodalDataset(images, joints)

# 入出力データを戻り値として返す。
x_data, y_data = multi_dataset[1]

下図はMultimodalDatasetクラスが返したロボットのカメラ画像を示しており、 左から順に右はノイズの無い画像、ノイズが付与された画像、そしてロボット関節角度である。 毎エポックランダムなノイズが画像に付与されるため、モデルは多様な視覚状況を学習する。 またロボット関節角度の黒色点線は、ノイズがないオリジナル関節角度、色付き線はガウシアンノイズが付与された関節角度である。

データセット

Note

Proxyなどが原因でデータセットが取得できない場合は、 ここからデータセットを手動でダウンロードし、 ~/.eipl/ フォルダ内に保存してください。

$ cd ~/
$ mkdir .eipl
$ cd .eipl
$ # copy grasp_bottle.tar to ~/.eipl/ directory
$ tar xvf grasp_bottle.tar
$ ls grasp_bottle/*
grasp_bottle/joint_bounds.npy


dataloader.MultimodalDataset

Bases: Dataset

このクラスは、CNNRNN/SARNNのようなマルチモーダルデータ(画像、関節など)を扱うモデルの学習に使用される。

Source code in ja/docs/model/src/dataloader.py
class MultimodalDataset(Dataset):
    #:: MultimodalDataset
    """
    このクラスは、CNNRNN/SARNNのようなマルチモーダルデータ(画像、関節など)を扱うモデルの学習に使用される。
    """

    def __init__(self, images, joints, stdev=0.02):
        """
        画像、関節角度、データ拡張を設定する。

        Args:
            images (numpy array): 画像時系列データ [データ数、時系列長、チャネル、縦、横]
            joints (numpy array): 関節角度時系列データ [データ数、時系列長、関節角度]
            stdev (float, optional): ガウシアンノイズの分散値、なお平均は0である。
        """
        self.stdev = stdev
        self.images = images
        self.joints = joints
        self.transform = transforms.ColorJitter(contrast=0.5, brightness=0.5, saturation=0.1)

    def __len__(self):
        """
        データ数を返す
        """
        return len(self.images)

    def __getitem__(self, idx):
        """
        指定されたインデックスの画像と関節角度にノイズを付与し、モデル学習のための入出力データのペアを返す。

        Args:
            idx (int): インデックス

        Returns:
            input_output_data (list): ノイズが付加された画像と関節角度(x_img, x_joint)と、元の画像と関節角度(y_img, y_joint)のペア
        """
        y_img = self.images[idx]
        y_joint = self.joints[idx]

        x_img = self.transform(self.images[idx])
        x_img = x_img + torch.normal(mean=0, std=self.stdev, size=x_img.shape)

        x_joint = self.joints[idx] + torch.normal(mean=0, std=self.stdev, size=y_joint.shape)

        return [[x_img, x_joint], [y_img, y_joint]]

__getitem__(idx)

指定されたインデックスの画像と関節角度にノイズを付与し、モデル学習のための入出力データのペアを返す。

Parameters:

Name Type Description Default
idx int

インデックス

required

Returns:

Name Type Description
input_output_data list

ノイズが付加された画像と関節角度(x_img, x_joint)と、元の画像と関節角度(y_img, y_joint)のペア

Source code in ja/docs/model/src/dataloader.py
def __getitem__(self, idx):
    """
    指定されたインデックスの画像と関節角度にノイズを付与し、モデル学習のための入出力データのペアを返す。

    Args:
        idx (int): インデックス

    Returns:
        input_output_data (list): ノイズが付加された画像と関節角度(x_img, x_joint)と、元の画像と関節角度(y_img, y_joint)のペア
    """
    y_img = self.images[idx]
    y_joint = self.joints[idx]

    x_img = self.transform(self.images[idx])
    x_img = x_img + torch.normal(mean=0, std=self.stdev, size=x_img.shape)

    x_joint = self.joints[idx] + torch.normal(mean=0, std=self.stdev, size=y_joint.shape)

    return [[x_img, x_joint], [y_img, y_joint]]

__init__(images, joints, stdev=0.02)

画像、関節角度、データ拡張を設定する。

Parameters:

Name Type Description Default
images numpy array

画像時系列データ [データ数、時系列長、チャネル、縦、横]

required
joints numpy array

関節角度時系列データ [データ数、時系列長、関節角度]

required
stdev float

ガウシアンノイズの分散値、なお平均は0である。

0.02
Source code in ja/docs/model/src/dataloader.py
def __init__(self, images, joints, stdev=0.02):
    """
    画像、関節角度、データ拡張を設定する。

    Args:
        images (numpy array): 画像時系列データ [データ数、時系列長、チャネル、縦、横]
        joints (numpy array): 関節角度時系列データ [データ数、時系列長、関節角度]
        stdev (float, optional): ガウシアンノイズの分散値、なお平均は0である。
    """
    self.stdev = stdev
    self.images = images
    self.joints = joints
    self.transform = transforms.ColorJitter(contrast=0.5, brightness=0.5, saturation=0.1)

__len__()

データ数を返す

Source code in ja/docs/model/src/dataloader.py
def __len__(self):
    """
    データ数を返す
    """
    return len(self.images)