import torch


def test(model, data_loader, silent=False, device=None, test_batch=1000):
    """
    Evaluate model on given data.

    Args:
        model (RNDModel): model object
        data_loader (iterable): iterable of (x, y) samples
        silent (bool): if True prints nothing
        device (pt.device): pytorch device to train on
        test_batch (int): size of the test batch

    Returns (float): accuracy value

    """
    model.eval()
    correct = 0
    with torch.no_grad():
        for batch_i, (x, y) in enumerate(data_loader):
            x = x.view(-1, 784).to(device)
            y = y.to(device)

            predictor_z, target_z = model.predict(x)

            mses = []
            for predict in predictor_z:
                mses.append((target_z - predict).pow(2).sum(1) / 2)
            mses_tensor = torch.Tensor(10, test_batch).to(device)
            torch.cat(mses, out=mses_tensor)
            mses_tensor = mses_tensor.view(10, test_batch)
            class_min_mse = torch.argmin(mses_tensor, dim=0)
            correct += torch.sum(torch.eq(y, class_min_mse)).item()
        acc = correct / 10_000
        if not silent:
            print('Accuracy: {}/{} ({:.0f}%)\n'.format(correct, 10000, 100. * acc))
    return acc