Example #1
0
def prepare_noniid_dataset(data, pivot_label: str, data_path: str, pickle_path: str, nb_cluster: int, double_check: bool =False):

    # The TSNE representation is independent of the number of devices.
    tsne_file = "{0}-tsne".format(data_path)
    if not file_exist("{0}.pkl".format(tsne_file)):
        # Running TNSE to obtain a 2D representation of data
        logging.debug("The TSNE representation ({0}) doesn't exist."
              .format(tsne_file))
        embedded_data = tsne(data)
        pickle_saver(embedded_data, tsne_file)

    tsne_cluster_file = "{0}/tsne-cluster".format(pickle_path)
    if not file_exist("{0}.pkl".format(tsne_cluster_file)):
        # Finding clusters in the TNSE.
        logging.debug("Finding non-iid clusters in the TNSE represesentation: {0}.pkl".format(tsne_file))
        embedded_data = pickle_loader("{0}".format(tsne_file))
        logging.debug("Saving found clusters : {0}.pkl".format(tsne_cluster_file))
        predicted_cluster = find_cluster(embedded_data, nb_cluster)
        pickle_saver(predicted_cluster, "{0}".format(tsne_cluster_file))

    predicted_cluster = pickle_loader("{0}".format(tsne_cluster_file))

    # With the found clusters, splitting data.
    X, Y = clustering_data(data, predicted_cluster, pivot_label, nb_cluster)

    if double_check:
        logging.debug("Checking data cluserization, wait until completion before seeing the plots.")
        # Checking that splitting data by cluster is valid.
        check_data_clusterisation(X, Y, nb_cluster)

    return X, Y
Example #2
0
def run_one_scenario(cost_models,
                     list_algos,
                     logs_file: str,
                     experiments_settings: str,
                     batch_size: int = 1,
                     stochastic: bool = True,
                     nb_epoch: int = 250,
                     step_size=None,
                     compression: CompressionModel = None,
                     use_averaging: bool = False,
                     fraction_sampled_workers: int = 1,
                     modify_run=None) -> None:

    pickle_file = "{0}/descent-{1}".format(logs_file, experiments_settings)

    if modify_run is None:
        if file_exist(pickle_file + ".pkl"):
            remove_file(pickle_file + ".pkl")
        algos = list_algos
    else:
        algos = [list_algos[i] for i in modify_run]
    for type_params in tqdm(algos):
        multiple_sg_descent = multiple_run_descent(
            type_params,
            cost_models=cost_models,
            compression_model=compression,
            use_averaging=use_averaging,
            stochastic=stochastic,
            nb_epoch=nb_epoch,
            step_formula=step_size,
            batch_size=batch_size,
            logs_file=logs_file,
            fraction_sampled_workers=fraction_sampled_workers)

        if logs_file:
            logs = open("{0}/logs.txt".format(logs_file), "a+")
            logs.write(
                "{0} size of the multiple SG descent: {1:.2e} bits\n".format(
                    type_params.name(), asizeof.asizeof(multiple_sg_descent)))
            logs.close()

        if file_exist(pickle_file + ".pkl"):
            res = pickle_loader(pickle_file)
            res.add_descent(multiple_sg_descent,
                            type_params.name(),
                            deep_learning_run=False)
        else:
            res = ResultsOfSeveralDescents(len(cost_models))
            res.add_descent(multiple_sg_descent,
                            type_params.name(),
                            deep_learning_run=False)

        pickle_saver(res, pickle_file)
        del res
        del multiple_sg_descent
Example #3
0
        if (epoch+1) % 20 == 0:
            curr_lr /= 3
            update_lr(optimizer, curr_lr)

    # Test the model
    model.eval()
    with torch.no_grad():
        correct = 0
        total = 0
        for images, labels in test_loader:
            images = images.to(device)
            labels = labels.to(device)
            outputs = model(images)
            _, predicted = torch.max(outputs.data, 1)
            total += labels.size(0)
            correct += (predicted == labels).sum().item()

        print('Accuracy of the model on the test images: {} %'.format(100 * correct / total))

    # Save the model checkpoint
    torch.save(model.state_dict(), 'resnet.ckpt')

    res = pickle_loader("run_cifar10")

    plt.plot(list(range(num_epochs)), run.train_losses)
    plt.savefig('{0}.eps'.format("cifar10_train_losses"), format='eps')
    plt.plot(list(range(num_epochs)), run.test_losses)
    plt.savefig('{0}.eps'.format("cifar10_test_losses"), format='eps')
    plt.plot(list(range(num_epochs)), run.test_accuracies)
    plt.savefig('{0}.eps'.format("cifar10_accuracy"), format='eps')
Example #4
0
def run_experiments_in_deeplearning(dataset: str):

    with open("log.txt", 'a') as f:
        print("==== NEW RUN ====", file=f)

    fraction_sampled_workers = 1
    batch_size = 128
    nb_devices = 20
    algos = "mcm-vs-existing"
    iid = "non-iid"

    data_path, pickle_path, algos_pickle_path, picture_path = create_path_and_folders(
        nb_devices, dataset, iid, algos, fraction_sampled_workers)

    default_up_compression = SQuantization(quantization_levels[dataset],
                                           norm=norm_quantization[dataset])
    default_down_compression = SQuantization(quantization_levels[dataset],
                                             norm=norm_quantization[dataset])

    exp_name = "{0}_m{1}_lr{2}_sup{3}_sdwn{4}_b{5}_wd{6}".format(
        models[dataset].__name__, momentums[dataset],
        optimal_steps_size[dataset], default_up_compression.level,
        default_down_compression.level, batch_size, weight_decay[dataset])

    all_descent = {}
    for type_params in [VanillaSGD(), Diana(), Artemis(), MCM()]:
        print(type_params)
        torch.cuda.empty_cache()
        params = type_params.define(
            cost_models=None,
            n_dimensions=None,
            nb_epoch=200,
            nb_devices=nb_devices,
            batch_size=batch_size,
            fraction_sampled_workers=1,
            up_compression_model=default_up_compression,
            down_compression_model=default_down_compression)

        params = cast_to_DL(params, dataset, models[dataset],
                            optimal_steps_size[dataset], weight_decay[dataset])
        params.log_file = "log.txt"
        params.momentum = momentums[dataset]
        params.print()

        with open(params.log_file, 'a') as f:
            print(type_params, file=f)
            print("Optimal step size: ", params.optimal_step_size, file=f)

        multiple_sg_descent = run_tuned_exp(params)

        all_descent[type_params.name()] = multiple_sg_descent

        res = ResultsOfSeveralDescents(all_descent, nb_devices)
        # res.add_descent(multiple_sg_descent, type_params.name())
        pickle_saver(res, "{0}/{1}".format(algos_pickle_path, exp_name))

    res = pickle_loader("{0}/{1}".format(algos_pickle_path, exp_name))

    # Plotting without averaging
    plot_error_dist(res.get_loss(np.array(0), in_log=True),
                    res.names,
                    res.nb_devices_for_the_run,
                    batch_size=batch_size,
                    all_error=res.get_std(np.array(0), in_log=True),
                    x_legend="Number of passes on data",
                    ylegends="train_loss",
                    picture_name="{0}/{1}_train_losses".format(
                        picture_path, exp_name))
    plot_error_dist(res.get_loss(np.array(0), in_log=True),
                    res.names,
                    res.nb_devices_for_the_run,
                    batch_size=batch_size,
                    x_points=res.X_number_of_bits,
                    ylegends="train_loss",
                    all_error=res.get_std(np.array(0), in_log=True),
                    x_legend="Communicated bits",
                    picture_name="{0}/{1}_train_losses_bits".format(
                        picture_path, exp_name))
    plot_error_dist(res.get_test_accuracies(),
                    res.names,
                    res.nb_devices_for_the_run,
                    ylegends="accuracy",
                    all_error=res.get_test_accuracies_std(),
                    x_legend="Number of passes on data",
                    batch_size=batch_size,
                    picture_name="{0}/{1}_test_accuracies".format(
                        picture_path, exp_name))
    plot_error_dist(res.get_test_losses(in_log=True),
                    res.names,
                    res.nb_devices_for_the_run,
                    batch_size=batch_size,
                    all_error=res.get_test_losses_std(in_log=True),
                    x_legend="Number of passes on data",
                    ylegends="test_loss",
                    picture_name="{0}/{1}_test_losses".format(
                        picture_path, exp_name))
Example #5
0
def run_experiments(nb_devices: int, stochastic: bool, dataset: str, iid: str, algos: str, use_averaging: bool = False,
                    scenario: str = None, fraction_sampled_workers: int = 0.5, plot_only: bool = True):

    print("Running with following parameters: {0}".format(["{0} -> {1}".format(k, v) for (k, v)
                                                           in zip(locals().keys(), locals().values())]))
    assert dataset in ["quantum", "superconduct", 'synth_logistic', 'synth_linear_noised', 'synth_linear_nonoised'], \
        "The available dataset are ['quantum', 'superconduct', 'synth_linear_noised', 'synth_linear_nonoised']."
    assert iid in ['iid', 'non-iid'], "The iid option are ['iid', 'non-iid']."
    assert scenario in [None, "compression", "step"], "The possible scenario are [None, 'compression', 'step']."

    data_path, pickle_path, algos_pickle_path, picture_path = create_path_and_folders(nb_devices, dataset, iid, algos, fraction_sampled_workers)

    list_algos = choose_algo(algos, stochastic, fraction_sampled_workers)
    nb_devices = nb_devices
    nb_epoch = 100 if stochastic else 400

    iid_data = True if iid == 'iid' else False

    # Select the correct dataset
    if dataset == "quantum":
        X, Y, dim_notebook = prepare_quantum(nb_devices, data_path=data_path, pickle_path=pickle_path, iid=iid_data)
        batch_size = 400
        model = LogisticModel
        nb_epoch = 500 if stochastic else 400
    elif dataset == "superconduct":
        X, Y, dim_notebook = prepare_superconduct(nb_devices, data_path= data_path, pickle_path=pickle_path, iid=iid_data)
        batch_size = 50
        model = RMSEModel
        nb_epoch = 500 if stochastic else 400
    elif dataset == 'synth_logistic':
        dim_notebook = 2
        batch_size = 1
        model = LogisticModel
        if not file_exist("{0}/data.pkl".format(pickle_path)):
            w = torch.FloatTensor([10, 10]).to(dtype=torch.float64)
            X, Y = build_data_logistic(w, n_dimensions=2, n_devices=nb_devices, with_seed=False)
            pickle_saver((X, Y), pickle_path + "/data")
        else:
            X, Y = pickle_loader(pickle_path + "/data")
    elif dataset == 'synth_linear_noised':
        dim_notebook = 20
        if not file_exist("{0}/data.pkl".format(pickle_path)):
            w_true = generate_param(dim_notebook-1)
            X, Y = build_data_linear(w_true, n_dimensions=dim_notebook-1,
                                     n_devices=nb_devices, with_seed=False, without_noise=False)
            X = add_bias_term(X)
            pickle_saver((X, Y), pickle_path + "/data")
        else:
            X, Y = pickle_loader(pickle_path + "/data")
        model = RMSEModel
        batch_size = 1
    elif dataset == 'synth_linear_nonoised':
        dim_notebook = 20
        if not file_exist("{0}/data.pkl".format(pickle_path)):
            w_true = generate_param(dim_notebook-1)
            X, Y = build_data_linear(w_true, n_dimensions=dim_notebook-1,
                                     n_devices=nb_devices, with_seed=False, without_noise=True)
            X = add_bias_term(X)
            pickle_saver((X, Y), pickle_path + "/data")
        else:
            X, Y = pickle_loader(pickle_path + "/data")
        model = RMSEModel
        batch_size = 1

    compression_by_default = SQuantization(1, dim_notebook)

    values_compression = [SQuantization(0, dim_notebook),
                          SQuantization(16, dim_notebook),
                          SQuantization(8, dim_notebook),
                          SQuantization(4, dim_notebook),
                          SQuantization(3, dim_notebook),
                          SQuantization(2, dim_notebook),
                          SQuantization(1, dim_notebook)
                          ]

    label_compression = ["SGD"] + [str(value.omega_c)[:4] for value in values_compression[1:]]

    # Rebalancing cluster: the biggest one must not be more than 10times bigger than the smallest one.
    X_r, Y_r = rebalancing_clusters(X, Y)

    # Creating cost models which will be used to computed cost/loss, gradients, L ...
    cost_models = build_several_cost_model(model, X_r, Y_r, nb_devices)

    if not file_exist("{0}/obj_min.pkl".format(pickle_path)):
        obj_min_by_N_descent = SGD_Descent(Parameters(n_dimensions=dim_notebook,
                                                  nb_devices=nb_devices,
                                                  nb_epoch=40000,
                                                  momentum=0.,
                                                  verbose=True,
                                                  cost_models=cost_models,
                                                  stochastic=False
                                                  ))
        obj_min_by_N_descent.run(cost_models)
        obj_min = obj_min_by_N_descent.losses[-1]
        pickle_saver(obj_min, "{0}/obj_min".format(pickle_path))

    # Choice of step size
    if stochastic and batch_size == 1:
        step_size = iid_step_size
    else:
        step_size = batch_step_size
    if 'synth' in dataset and stochastic:
        step_size = deacreasing_step_size

    stochasticity = 'sto' if stochastic else "full"

    if not plot_only:
        if scenario == "compression":
            run_for_different_scenarios(cost_models, list_algos[1:], values_compression, label_compression,
                                        filename=algos_pickle_path, batch_size=batch_size, stochastic=stochastic,
                                        step_formula=step_size, scenario=scenario)
        elif scenario == "step":
            run_for_different_scenarios(cost_models, list_algos, step_formula, label_step_formula,
                                        filename=algos_pickle_path, batch_size=batch_size, stochastic=stochastic,
                                        scenario=scenario, compression=compression_by_default)
        else:
            run_one_scenario(cost_models=cost_models, list_algos=list_algos, filename=algos_pickle_path,
                             batch_size=batch_size, stochastic=stochastic, nb_epoch=nb_epoch, step_size=step_size,
                             use_averaging=use_averaging, compression=compression_by_default,
                             fraction_sampled_workers=fraction_sampled_workers)

    obj_min = pickle_loader("{0}/obj_min".format(pickle_path))

    if stochastic:
        experiments_settings = "{0}-b{1}".format(stochasticity, batch_size)
    else:
        experiments_settings = stochasticity

    if scenario is None:
        res = pickle_loader("{0}/descent-{1}".format(algos_pickle_path, experiments_settings))

        # Plotting without averaging
        plot_error_dist(res.get_loss(obj_min), res.names, res.nb_devices, dim_notebook,
                        all_error=res.get_std(obj_min), x_legend="Number of passes on data\n({0})".format(iid),
                        picture_name="{0}/it-noavg-{1}".format(picture_path, experiments_settings))
        plot_error_dist(res.get_loss(obj_min), res.names, res.nb_devices, dim_notebook,
                        x_points=res.X_number_of_bits, x_legend="Communicated bits ({0})".format(iid),
                        all_error=res.get_std(obj_min), picture_name="{0}/bits-noavg-{1}"
                        .format(picture_path, experiments_settings))

        # Plotting with averaging
        if use_averaging:
            plot_error_dist(res.get_loss(obj_min, averaged=True), res.names, res.nb_devices,
                            dim_notebook, all_error=res.get_std(obj_min, averaged=True),
                            x_legend="Number of passes on data\n(Avg, {0})".format(iid),
                            picture_name="{0}/it-avg-{1}"
                            .format(picture_path, experiments_settings))
            plot_error_dist(res.get_loss(obj_min, averaged=True), res.names, res.nb_devices, dim_notebook,
                            x_points=res.X_number_of_bits, all_error=res.get_std(obj_min, averaged=True),
                            x_legend="Communicated bits (Avg, {0})".format(iid),
                            picture_name="{0}/bits-avg-{1}"
                            .format(picture_path, experiments_settings))

    if scenario == "step":
        res = pickle_loader("{0}/{1}-{2}".format(algos_pickle_path, scenario, experiments_settings))

        plot_error_dist(res.get_loss(obj_min), res.names, res.nb_devices, dim_notebook,
                        batch_size=batch_size,
                        all_error=res.get_std(obj_min),
                        x_legend="Step size ({0}, {1})".format(iid, str(compression_by_default.omega_c)[:4]),
                        one_on_two_points=True, xlabels=label_step_formula,
                        picture_name="{0}/{1}-{2}".format(picture_path, scenario, experiments_settings))

        res = pickle_loader("{0}/{1}-optimal-{2}".format(algos_pickle_path, scenario, experiments_settings))

        plot_error_dist(res.get_loss(obj_min), res.names, res.nb_devices, dim_notebook,
                        all_error=res.get_std(obj_min), batch_size=batch_size,
                        x_legend="(non-iid)", ylim=True,
                        picture_name="{0}/{1}-optimal-it-{2}".format(picture_path, scenario, experiments_settings))
        plot_error_dist(res.get_loss(obj_min), res.names, res.nb_devices, dim_notebook,
                        x_points=res.X_number_of_bits, batch_size=batch_size,
                        x_legend="Communicated bits\n(non-iid)", all_error=res.get_std(obj_min), ylim=True,
                        picture_name="{0}/{1}-optimal-bits-{2}".format(picture_path, scenario, experiments_settings))

    if scenario == "compression":
        res = pickle_loader("{0}/{1}-{2}".format(algos_pickle_path, scenario, experiments_settings))
        plot_error_dist(res.get_loss(obj_min), res.names, res.nb_devices, dim_notebook, batch_size=batch_size,
                        all_error=res.get_std(obj_min), x_legend="$\omega_c$ ({0})".format(iid),
                        one_on_two_points=True, xlabels=label_compression,
                        picture_name="{0}/{1}-{2}".format(picture_path, scenario, experiments_settings))

        res = pickle_loader("{0}/{1}-optimal-{2}".format(algos_pickle_path, scenario, experiments_settings))

        plot_error_dist(res.get_loss(obj_min), res.names, res.nb_devices, dim_notebook,
                        all_error=res.get_std(obj_min), batch_size=batch_size,
                        x_legend="(non-iid)", ylim=True,
                        picture_name="{0}/{1}-optimal-it-{2}".format(picture_path, scenario, experiments_settings))
        plot_error_dist(res.get_loss(obj_min), res.names, res.nb_devices, dim_notebook,
                        x_points=res.X_number_of_bits, batch_size=batch_size,
                        x_legend="Communicated bits\n(non-iid)", all_error=res.get_std(obj_min), ylim=True,
                        picture_name="{0}/{1}-optimal-bits-{2}".format(picture_path, scenario, experiments_settings))
Example #6
0
def run_experiments_in_deeplearning(dataset: str,
                                    plot_only: bool = False) -> None:
    """Runs and plots experiments for a given dataset using an appropriate neural network.

    :param dataset: Name of the dataset
    :param plot_only: True if the goal is not to rerun all experiments but only to regenerate figures.
    """
    fraction_sampled_workers = 1
    batch_size = batch_sizes[dataset]
    nb_devices = 20
    algos = sys.argv[2]
    iid = sys.argv[3]
    stochastic = True

    create_folder_if_not_existing(algos)
    log_file = algos + "/log_" + dataset + "_" + iid + ".txt"
    with open(log_file, 'a') as f:
        print("==== NEW RUN ====", file=f)

    with open(log_file, 'a') as f:
        print(
            "stochastic -> {0}, iid -> {1}, batch_size -> {2}, norm -> {3}, s -> {4}, momentum -> {5}, model -> {6}"
            .format(stochastic, iid, batch_size, norm_quantization[dataset],
                    quantization_levels[dataset], momentums[dataset],
                    models[dataset].__name__),
            file=f)

    data_path, pickle_path, algos_pickle_path, picture_path = create_path_and_folders(
        nb_devices, dataset, iid, algos, fraction_sampled_workers)

    default_up_compression = SQuantization(quantization_levels[dataset],
                                           norm=norm_quantization[dataset])
    default_down_compression = SQuantization(quantization_levels[dataset],
                                             norm=norm_quantization[dataset])

    loaders = create_loaders(dataset, iid, nb_devices, batch_size, stochastic)
    _, train_loader_workers_full, _ = loaders
    dim = next(iter(train_loader_workers_full[0]))[0].shape[1]
    if optimal_steps_size[dataset] is None:
        L = compute_L(train_loader_workers_full)
        optimal_steps_size[dataset] = 1 / L
        print("Step size:", optimal_steps_size[dataset])

    exp_name = name_of_the_experiments(dataset, stochastic)
    pickle_file = "{0}/{1}".format(algos_pickle_path, exp_name)

    list_algos = choose_algo(algos, stochastic, fraction_sampled_workers)

    if not plot_only:
        if file_exist(pickle_file + ".pkl"):
            remove_file(pickle_file + ".pkl")

        for type_params in list_algos:
            print(type_params)
            torch.cuda.empty_cache()
            params = type_params.define(
                cost_models=None,
                n_dimensions=dim,
                nb_epoch=300,
                nb_devices=nb_devices,
                stochastic=stochastic,
                batch_size=batch_size,
                fraction_sampled_workers=fraction_sampled_workers,
                up_compression_model=default_up_compression,
                down_compression_model=default_down_compression)

            params = cast_to_DL(params, dataset, models[dataset],
                                optimal_steps_size[dataset],
                                weight_decay[dataset], iid)
            params.log_file = log_file
            params.momentum = momentums[dataset]
            params.criterion = criterion[dataset]
            params.print()

            with open(params.log_file, 'a') as f:
                print(type_params, file=f)
                print("Optimal step size: ", params.optimal_step_size, file=f)

            multiple_descent = AverageOfSeveralIdenticalRun()
            seed_everything(seed=42)
            start = time.time()
            for i in range(NB_RUN):
                print('Run {:3d}/{:3d}:'.format(i + 1, NB_RUN))
                fixed_params = copy.deepcopy(params)
                try:
                    training = Train(loaders, fixed_params)
                    multiple_descent.append_from_DL(training.run_training())
                except ValueError as err:
                    print(err)
                    continue
            with open(log_file, 'a') as f:
                print("Time of the run: {:.2f}s".format(time.time() - start),
                      file=f)

            with open(params.log_file, 'a') as f:
                print("{0} size of the multiple SG descent: {1:.2e} bits\n".
                      format(type_params.name(),
                             asizeof.asizeof(multiple_descent)),
                      file=f)

            if file_exist(pickle_file + ".pkl"):
                res = pickle_loader(pickle_file)
                res.add_descent(multiple_descent,
                                type_params.name(),
                                deep_learning_run=True)
            else:
                res = ResultsOfSeveralDescents(nb_devices)
                res.add_descent(multiple_descent,
                                type_params.name(),
                                deep_learning_run=True)

            pickle_saver(res, pickle_file)

    # obj_min_cvx = pickle_loader("{0}/obj_min".format(pickle_path))
    obj_min = 0  #pickle_loader("{0}/obj_min".format(pickle_path))

    res = pickle_loader(pickle_file)

    # obj_min = min(res.get_loss(np.array(0), in_log=False)[0])

    # print("Obj min in convex:", obj_min_cvx)
    print("Obj min in dl:", obj_min)

    # Plotting
    plot_error_dist(res.get_loss(np.array(obj_min)),
                    res.names,
                    all_error=res.get_std(np.array(obj_min)),
                    x_legend="Number of passes on data",
                    ylegends="train_loss",
                    picture_name="{0}/{1}_train_losses".format(
                        picture_path, exp_name))
    plot_error_dist(res.get_loss(np.array(obj_min)),
                    res.names,
                    x_points=res.X_number_of_bits,
                    ylegends="train_loss",
                    all_error=res.get_std(np.array(obj_min)),
                    x_legend="Communicated bits",
                    picture_name="{0}/{1}_train_losses_bits".format(
                        picture_path, exp_name))
    plot_error_dist(res.get_test_accuracies(),
                    res.names,
                    ylegends="accuracy",
                    all_error=res.get_test_accuracies_std(),
                    x_legend="Number of passes on data",
                    picture_name="{0}/{1}_test_accuracies".format(
                        picture_path, exp_name))
    plot_error_dist(res.get_test_losses(in_log=True),
                    res.names,
                    all_error=res.get_test_losses_std(in_log=True),
                    x_legend="Number of passes on data",
                    ylegends="test_loss",
                    picture_name="{0}/{1}_test_losses".format(
                        picture_path, exp_name))