'During initialization, the input data will be converted to backend tensor objects
(e.g. CPUTensor or GPUTensor). If the backend uses the GPU, the data is copied over to the
device.
Args:
X (ndarray, shape: [# examples, feature size]): Input features of the
dataset.
y (ndarray, shape:[# examples, 1 or feature size], optional): Labels corresponding to
the input features. If absent, the input features themselves will be returned as
target values (e.g. autoencoder)
nclass (int, optional): The number of classes in labels. Not necessary if
labels are not provided or where the labels are non-categorical.
lshape (tuple, optional): Local shape for the input features
(e.g. # channels, height, width)
make_onehot (bool, optional): True if y is a categorical label that has to be converted
to a one hot representation.'

def __init__(self, X, y=None, nclass=None, lshape=None, make_onehot=True, name=None):

    super(ArrayIterator, self).__init__(name=name)
    X = (X if isinstance(X, list) else [X])
    self.ndata = len(X[0])
    assert (self.ndata >= self.be.bsz)
    self.start = 0
    self.nclass = nclass
    self.ybuf = None
    if (make_onehot and (nclass is None) and (y is not None)):
        raise AttributeError('Must    provide    number    of    classes    when    creating    onehot    labels')
    if (y is not None):
        assert all([(y.shape[0] == x.shape[0]) for x in X]), 'Input    features    and    labels    must    have    equal    number    of    examples.'
        if make_onehot:
            assert ((y.max() <= (nclass - 1)) and (y.min() >= 0)), 'Labels    must    range    from    0    to    {}    (nclass-1).'.format((nclass - 1))
            assert (np.floor(y) == y).all(), 'Labels    must    only    contain    integers.'
    if (lshape is not None):
        assert all([(x.shape[1] == np.prod(lshape)) for x in X]), 'product    of    lshape    {}    does    not    match    input    feature    size'.format(lshape)
    self.shape = [(x.shape[1] if (lshape is None) else lshape) for x in X]
    if (len(self.shape) == 1):
        self.shape = self.shape[0]
        self.lshape = lshape
    def transpose_gen(z):
        return (self.be.array(z), self.be.iobuf(z.shape[1]), (lambda _in, _out: self.be.copy_transpose(_in, _out)))
    def onehot_gen(z):
        return (self.be.array(z.reshape(((-1), 1)), dtype=np.int32), self.be.iobuf(nclass), (lambda _in, _out: self.be.onehot(_in, axis=0, out=_out)))
    (self.Xdev, self.Xbuf, self.unpack_func) = list(zip(*[transpose_gen(x) for x in X]))
    (self.dbuf, self.hbuf) = (list(self.Xdev), list(self.Xbuf))
    self.unpack_func = list(self.unpack_func)
    if (y is not None):
        (self.ydev, self.ybuf, yfunc) = (onehot_gen(y) if make_onehot else transpose_gen(y))
        self.dbuf.append(self.ydev)
        self.hbuf.append(self.ybuf)
        self.unpack_func.append(yfunc)
