Пример #1
0
def build_jc_combined_distributions(averaged_distributions: Dict[Tuple[AccessPoint, ...],
                                                                 Tuple[NormalizedMatrix, List[svm_model]]],
                                    num_combinations: int,
                                    training_data: List[Sample]
                                    ) -> List[FinalCombinationContainer]:
    # Set combination method:
    combine_vectors = __weighted_combine_vectors

    averaged_normalized_list = sorted(averaged_distributions.values(),
                                      key=lambda x: x[0].average_matrix_success, reverse=True)

    primary_matrix = averaged_normalized_list[0][0]
    primary_svm_list = averaged_normalized_list[0][1]
    access_point_tuple = primary_matrix.access_points_tuple
    zones = primary_matrix.zones

    # Containers to hold matrices being returned.
    final_combination_container = list()  # type: List[FinalCombinationContainer]
    combined_distributions = list()  # type: List[CombinedMatrix]
    normalized_combined_distributions = list()  # type: List[NormalizedMatrix]

    # Containers to hold data from the passed param.
    # access_point_combinations = list(averaged_distributions.keys())

    # amount = __nCr(len(averaged_distributions), num_combinations)
    # print("------ There will be {} combinations.".format(int(amount)))
    tracker = 1

    primary_predict_zone = list()
    primary_predict = list()
    ap_test_features = list()
    test_features = [data.scan for data in training_data]
    test_class = [data.answer.num for data in training_data]
    aps_being_used = [x for x in access_point_tuple]

    for feature_set in test_features:
        ap_test_features.append(
            [value for key, value in feature_set.items() if key in aps_being_used])
    for svm in primary_svm_list:
        # 通过找出最好的svm_model来进行online stage
        p_labs, p_acc, p_vals = svm_predict(y=test_class, x=ap_test_features, m=svm, options="-q")
        # print("the accuracy for primary is {}".format(p_acc[0]))
        primary_predict.append(p_labs)

    # my_combo = m.get_combination()
    # final_count = list()
    # for p in p_vals:
    #     count_dict = dict()
    #     for index in range(len(p)):
    #         big_one = classfications[index][0]
    #         small_one = classfications[index][1]
    #         if p[index] > 0:
    #             if big_one in count_dict.keys():
    #                 count_dict[big_one] += 1
    #             else:
    #                 count_dict[big_one] = 1
    #         else:
    #             if small_one in count_dict.keys():
    #                 count_dict[small_one] += 1
    #             else:
    #                 count_dict[small_one] = 1
    #     final_count.append(max(count_dict, key=count_dict.get))

    for d in range(len(primary_predict[0])):
        zone_predictions = list()
        for p in primary_predict:
            zone_predictions.append(p[d])
        best_predict_zone = max(zone_predictions, key=zone_predictions.count)
        predicted_zone = zones[int(best_predict_zone) - 1]
        primary_predict_zone.append(predicted_zone)
    # For every possible ap combination: # TODO: This should pick the best normalized dist, instead of combining all.
    for ap_combination in __ap_combinations(averaged_normalized_list, num_combinations):
        print("------ Combination number {}:".format(tracker))
        print("------ Combining {}.".format(ap_combination))

        features = list()
        secondary_predict_zone = list()

        # Get the normalizations being combined:
        normalizations = [norm[0] for norm in [averaged_distributions[ap] for ap in ap_combination]]

        # Create an empty combined distribution:
        combined_distribution = CombinedMatrix(*normalizations, size=normalizations[0].size)

        aps_being_used = normalizations[1].access_points_tuple
        svms = averaged_distributions[aps_being_used][1]
        matrix = averaged_distributions[aps_being_used][0]

        for feature_set in test_features:
            features.append(
                [value for key, value in feature_set.items() if key in ap_combination[1]])

        secondary_predict = list()
        for svm in svms:
            p_labs, p_acc, p_vals = svm_predict(y=test_class, x=features, m=svm, options="-q")
            # print("the accuracy for secondary is {}".format(p_acc[0]))
            secondary_predict.append(p_labs)

        for d in range(len(secondary_predict[0])):
            zone_predictions = list()
            for p in secondary_predict:
                zone_predictions.append(p[d])
            best_predict_zone = max(zone_predictions, key=zone_predictions.count)
            predicted_zone = zones[int(best_predict_zone) - 1]
            secondary_predict_zone.append(predicted_zone)

        for z in range(len(secondary_predict_zone)):
            secondary_vector = matrix.get_vector(secondary_predict_zone[z])
            primary_vector = primary_matrix.get_vector(primary_predict_zone[z])
            vectors = [primary_vector, secondary_vector]
            answers = [training_data[z].answer, training_data[z].answer]
            combined_vector = combine_vectors(answers, *vectors)
            combined_distribution.increment_cell(training_data[z].answer, combined_vector)

        # Normalize the combined matrix.
        normalized_combination = NormalizedMatrix(combined_distribution, combine_ids=True)

        # Store both matrices.
        combined_distributions.append(combined_distribution)
        normalized_combined_distributions.append(normalized_combination)

        # Create the final container object:

        ap_svm_dict = dict()  # type: Dict[Tuple[AccessPoint, ...], List[svm_model]]
        ap_svm_dict[access_point_tuple] = primary_svm_list
        ap_svm_dict[aps_being_used] = svms

        combined_features = list()
        half = int(len(features) / 2)
        for f in range(len(features)):
            combined_features.append(features[f] + ap_test_features[f])

        combined_svm = svm_train(test_class[:half], combined_features[:half], '-q')

        p_labs, p_acc, p_vals = svm_predict(y=test_class[half:], x=combined_features[half:], m=combined_svm,
                                            options="-q")
        # print("the accuracy for combined is {}".format(p_acc[0]))
        # Create the object needed:
        final_container = FinalCombinationContainer(
            ap_svm_dict=ap_svm_dict,
            ap_tuples=ap_combination,
            combined_svm=combined_svm,
            normalization=normalized_combination,
            combined_distribution=combined_distribution
        )

        final_combination_container.append(final_container)
        tracker += 1

    return final_combination_container
Пример #2
0
def create_kflod_combination(train_mode: str, selection_mode: str,
                             num_combination: int, centroids: List[Centroid],
                             grid_points: List[GridPoint],
                             access_points: List[AccessPoint],
                             zones: List[Zone], num_splits: int,
                             training_data: List[Sample]):
    # Initialize the k-fold
    X = np.array(training_data)
    kf = KFold(n_splits=num_splits)

    fold_number = 1
    split_kf = kf.split(X)
    folds = dict()  # type: Dict[int, Fold]
    best_ap_list = dict()  # type: Dict[int, List[Tuple[AccessPoint, ...]]]
    accuracy_check = dict(
    )  # type: Dict[Tuple[AccessPoint, ...], List[svm_model]]
    best_gd_models = dict(
    )  # type: Dict[Tuple[AccessPoint, ...], Tuple[NormalizedMatrix, List[svm_model]]]
    best_jc_models = dict(
    )  # type: Dict[Tuple[AccessPoint, ...], Tuple[NormalizedMatrix, List[svm_model]]]
    all_access_point_combinations = get_ap_combinations(
        access_points=access_points)
    for train_indices, test_indices in split_kf:
        print("Starting Fold {} with {}.".format(fold_number, train_mode))

        fold = Fold()
        train_samples = list()  # type: List[Sample]
        test_samples = list()  # type: List[Sample]
        train_features = list()  # type: List[Dict[AccessPoint, int]]
        train_classes = list()  # type: List[int]
        test_features = list()  # type: List[Dict[AccessPoint, int]]
        test_classes = list()  # type: List[int]

        # prepare data for train and test
        for num in train_indices:
            train_samples.append(training_data[num])
            train_features.append(training_data[num].scan)
            train_classes.append(training_data[num].answer.num)

        for num in test_indices:
            test_samples.append(training_data[num])
            test_features.append(training_data[num].scan)
            test_classes.append(training_data[num].answer.num)
        # Train SVM model
        d = 2
        trained_models = list()  # type: List[IndividualModel]
        while d < len(access_points) + 1:
            # Get list of ap combinations
            access_point_combinations = get_n_ap_combinations(
                access_points, d)  # type: List[Tuple[AccessPoint, ...]]
            # Get dict for store score
            score_dict = dict()  # type: Dict[Tuple[AccessPoint, ...], float]
            for access_point_tuple in access_point_combinations:
                # for every ap tuple, get the RSSIs
                ap_train_features = list()
                ap_test_features = list()
                aps_being_used = [x for x in access_point_tuple]
                for feature_set in train_features:
                    ap_train_features.append([
                        value for key, value in feature_set.items()
                        if key in aps_being_used
                    ])

                for feature_set in test_features:
                    ap_test_features.append([
                        value for key, value in feature_set.items()
                        if key in aps_being_used
                    ])
                # Train svm model
                m = svm_train(train_classes, ap_train_features, '-q')
                margins = m.get_labels()
                score = 0
                for margin in margins:
                    score += 0.5 * margin
                score_dict[access_point_tuple] = score
                p_labs, p_acc, p_vals = svm_predict(y=test_classes,
                                                    x=ap_test_features,
                                                    m=m,
                                                    options='-q')
                if access_point_tuple in accuracy_check:
                    accuracy_check[access_point_tuple].append(m)
                else:
                    accuracy_check[access_point_tuple] = [m]
                individual_model = IndividualModel(
                    svm=m,
                    access_point_tuple=access_point_tuple,
                    zones=zones,
                    train_features=ap_train_features,
                    train_classes=train_classes,
                    test_features=ap_test_features,
                    test_classes=test_classes,
                    predictions=p_labs,
                    percentage_correct=p_acc[0])
                fold.add_trained_models({access_point_tuple: individual_model})
                trained_models.append(individual_model)
            best_one = tuple()  # type:Tuple[AccessPoint, ...]
            min_value = min(score_dict.values())
            for keys, values in score_dict.items():
                if values == min_value:
                    best_one = keys
            if d in best_ap_list.keys():
                best_ap_list[d].append(best_one)
            else:
                best_ap_list[d] = [best_one]
            if train_mode != "SVM":
                distributions = create_all_matrices_from_rssi_data(
                    access_points=access_points,
                    access_point_combinations=access_point_combinations,
                    centroids=centroids,
                    grid_points=grid_points,
                    zones=zones,
                    training_data=train_samples,
                    testing_data=test_samples,
                    combination_mode="WGT",
                    location_mode=train_mode,
                    num_combinations=num_combination,
                    do_combination=False)

                probability_distributions = distributions[0]
                normalized_distributions = distributions[1]
                test_distributions = distributions[2]
                fold.create_distributions(
                    access_point_combinations=access_point_combinations,
                    p_list=probability_distributions,
                    n_list=normalized_distributions)
            d += 1
        folds[fold_number] = fold
        print("Completed Fold {}.".format(fold_number))
        fold_number += 1

    if train_mode == "SVM":
        for fold in folds.values():
            fold.create_probability_distributions()
            fold.create_normalized_distributions()
        print(
            "Completed. There are {} Probability and Normalized Distributions."
            .format(len(folds)))
    print("Averaging the matrices produced from Folding...")
    averaged_normalized_distributions = dict()
    for ap_tuple in all_access_point_combinations:
        distributions_to_average = list()  # type: List[NormalizedMatrix]
        svms_to_store = list()  # type: List[svm_model]
        for fold in folds.values():
            distributions_to_average.append(
                fold.get_normalized_distribution(ap_tuple))
            svms_to_store.append(fold.get_SVM(ap_tuple))
        # Get the average normalized distribution:
        averaged_normalized_distribution = Fold.get_average_distribution(
            access_points=[*ap_tuple],
            zones=zones,
            distributions=distributions_to_average)
        if selection_mode == "GD":
            averaged_normalized_distributions[
                ap_tuple] = averaged_normalized_distribution, svms_to_store
        else:
            averaged_normalized_distributions[
                ap_tuple] = averaged_normalized_distribution
    print(
        "Completed. There are {} Normalized Distributions ready for combination."
        .format(len(averaged_normalized_distributions.values())))

    if selection_mode == "JC":
        averaged_normalized_list = sorted(
            averaged_normalized_distributions.values(),
            key=lambda x: x.average_matrix_success,
            reverse=True)
        for i in range(2, len(access_points) + 1):
            best_normalization = next(
                normalized_dist for normalized_dist in averaged_normalized_list
                if len(normalized_dist.access_points) == i)
            jc_ap_tuple = best_normalization.access_points_tuple
            best_jc_models[jc_ap_tuple] = best_normalization, accuracy_check[
                jc_ap_tuple]
            print("JC select:{}".format(jc_ap_tuple))
        return best_jc_models
    else:
        for index, value in best_ap_list.items():
            ap_set = max(set(value), key=value.count)
            best_matrix = averaged_normalized_distributions[ap_set][0]
            best_d_model = accuracy_check[ap_set]
            best_gd_models[ap_set] = best_matrix, best_d_model
        return best_gd_models
Пример #3
0
def gd_approach(num_splits: int, data: List[Sample],
                access_points: List[AccessPoint]):
    # 4. Set K-Fold Splits
    X = np.array(data)
    kf = KFold(n_splits=num_splits)

    # 5. For every fold, for every AP combination, train a new SVM.
    fold_number = 1
    split_kf = kf.split(X)

    best_ap_set = dict()  # type: Dict[int, Tuple[AccessPoint, ...]]
    best_ap_list = dict()  # type: Dict[int, List[Tuple[AccessPoint, ...]]]

    for train_indices, test_indices in split_kf:
        print("Starting Fold {}.".format(fold_number))

        train_features = list()  # type: List[Dict[AccessPoint, int]]
        train_classes = list()  # type: List[int]
        test_features = list()  # type: List[Dict[AccessPoint, int]]
        test_classes = list()  # type: List[int]

        # change to NNv4 mode
        for num in train_indices:
            train_features.append(data[num].scan)
            train_classes.append(data[num].answer.num)

        for num in test_indices:
            test_features.append(data[num].scan)
            test_classes.append(data[num].answer.num)

        d = 2
        while d < len(access_points) + 1:
            access_point_combinations = get_n_ap_combinations(
                access_points, d)  # type: List[Tuple[AccessPoint, ...]]
            # 6. Get all AP Combinations
            S_score = dict()  # type: Dict[Tuple[AccessPoint, ...], float]
            accuracy_check = dict(
            )  # type: Dict[Tuple[AccessPoint, ...], float]
            ap_features = list()

            for feature_set in train_features:
                ap_features.append(
                    [value for key, value in feature_set.items()])
            param_grid = {
                "gamma": [
                    0.0001, 0.001, 0.01, 0.1, 1, 10, 100, 0.25, 0.5, 0.75, 0.3,
                    0.2, 0.15, 1000
                ],
                "C": [0.001, 0.01, 0.1, 1, 10, 100, 1000]
            }
            grid_search = GridSearchCV(SVC(decision_function_shape='ovo'),
                                       param_grid,
                                       cv=5)
            grid_search.fit(ap_features, train_classes)
            print("Best parameters:{}".format(grid_search.best_params_))
            gamma = grid_search.best_params_['gamma']
            c = grid_search.best_params_['C']

            for access_point_tuple in access_point_combinations:
                # print("--- Working on AP Combination: {}".format(access_point_tuple))
                ap_train_features = list()
                ap_test_features = list()

                aps_being_used = [x for x in access_point_tuple]
                for feature_set in train_features:
                    ap_train_features.append([
                        value for key, value in feature_set.items()
                        if key in aps_being_used
                    ])

                for feature_set in test_features:
                    ap_test_features.append([
                        value for key, value in feature_set.items()
                        if key in aps_being_used
                    ])

                m = svm_train(train_classes, ap_train_features,
                              '-q -c {} -g {}'.format(c, gamma))
                margins = m.get_labels()
                score = 0
                for margin in margins:
                    score += 0.5 * margin
                S_score[access_point_tuple] = score
                p_labs, p_acc, p_vals = svm_predict(y=test_classes,
                                                    x=ap_test_features,
                                                    m=m)
                accuracy_check[access_point_tuple] = p_acc[0]

            best_one = tuple()  # type:Tuple[AccessPoint, ...]
            best_accuracy = tuple()  # type:Tuple[AccessPoint, ...]
            min_value = min(S_score.values())
            max_value = max(accuracy_check.values())
            for key, value in accuracy_check.items():
                if value == max_value:
                    best_accuracy = key
            for keys, values in S_score.items():
                if values == min_value:
                    best_one = keys
            # best_accuracy = accuracy_check[best_one]
            if d in best_ap_list.keys():
                best_ap_list[d].append(best_one)
            else:
                best_ap_list[d] = [best_one]
            print(
                "finish GD training for d = {}, best ap combination is {}, best accuracy is {}"
                .format(d, best_one, best_accuracy))
            d += 1
        print("Completed Fold {}.".format(fold_number))
        fold_number += 1
    for index, value in best_ap_list.items():
        ap_set = max(set(value), key=value.count)
        best_ap_set[index] = ap_set
        print("d = {}, the Best AP Combination is: {}".format(index, ap_set))
    return best_ap_set
Пример #4
0
def gd_train(training_data: List[Sample], num_splits: int,
             access_points: List[AccessPoint]):
    X = np.array(training_data)
    kf = KFold(n_splits=num_splits)
    # folds = dict()  # type: Dict[int, Fold]
    fold_number = 1
    best_ap_set = dict()  # type: Dict[int, Tuple[AccessPoint, ...]]
    best_ap_list = dict()  # type: Dict[int, List[Tuple[AccessPoint, ...]]]
    for train_indices, test_indices in kf.split(X):
        print("Starting Fold {}.".format(fold_number))

        train_features = list()  # type: List[Dict[AccessPoint, int]]
        train_classes = list()  # type: List[Zone]
        test_features = list()  # type: List[Dict[AccessPoint, int]]
        test_classes = list()  # type: List[Zone]

        for num in train_indices:
            train_features.append(training_data[num].scan)
            train_classes.append(training_data[num].answer)

        for num in test_indices:
            test_features.append(training_data[num].scan)
            test_classes.append(training_data[num].answer)

        d = 2
        while d < len(access_points):
            access_point_combinations = get_n_ap_combinations(
                access_points, d)  # type: List[Tuple[AccessPoint, ...]]
            # 6. Get all AP Combinations
            S_score = dict()  # type: Dict[Tuple[AccessPoint, ...], float]
            for access_point_tuple in access_point_combinations:
                print("--- Working on AP Combination: {}".format(
                    access_point_tuple))
                ap_train_features = list()
                ap_test_features = list()

                aps_being_used = [x.num for x in access_point_tuple]
                for feature_set in train_features:
                    ap_train_features.append([
                        x for index, x in enumerate(feature_set)
                        if (index + 1) in aps_being_used
                    ])

                for feature_set in test_features:
                    ap_test_features.append([
                        x for index, x in enumerate(feature_set)
                        if (index + 1) in aps_being_used
                    ])

                print("---------------------------------------------\n")
                m = svm_train(train_classes, ap_train_features)
                margins = m.get_labels()
                score = 0
                for margin in margins:
                    score += 0.5 * margin
                S_score[access_point_tuple] = score
                # p_labs, p_acc, p_vals = svm_predict(y=test_classes, x=ap_test_features, m=m)
            best_one = tuple()  # type:Tuple[AccessPoint, ...]
            min_value = min(S_score.values())
            print(min_value)
            for keys, values in S_score.items():
                if values == min_value:
                    best_one = keys
            if d in best_ap_list.keys():
                best_ap_list[d].append(best_one)
            else:
                best_ap_list[d] = [best_one]
            print("finish GD training for d = {}, best ap combination is {}".
                  format(d, best_one))
            d += 1
        print("Completed Fold {}.".format(fold_number))
        fold_number += 1
    for index, value in best_ap_list.items():
        ap_set = max(set(value), key=value.count)
        best_ap_set[index] = ap_set
        print("d = {}, the Best AP Combination is: {}".format(index, ap_set))

    return best_ap_set
Пример #5
0
def create_compare_combination(
        num_splits: int, combination_mode: str, location_mode: str,
        num_combinations: int, mm_ap_dict: dict, training_data: List[Sample],
        combine: bool, centroids: List[Centroid], grid_points: List[GridPoint],
        access_points: List[AccessPoint], zones: List[Zone]):
    jc_time = 0
    gd_time = 0
    ig_time = 0
    start_initialize_time = time()
    # 4. Set K-Fold Splits
    X = np.array(training_data)
    kf = KFold(n_splits=num_splits)

    # 5. For every fold, for every AP combination, train a new SVM.
    fold_number = 1
    split_kf = kf.split(X)

    all_access_point_combinations = get_ap_combinations(
        access_points=access_points)  # type: List[Tuple[AccessPoint, ...]]
    normalized_list = dict()  # type: Dict[int, List[NormalizedMatrix]]
    folds = dict()  # type: Dict[int, Fold]
    best_ap_list = dict()  # type: Dict[int, List[Tuple[AccessPoint, ...]]]
    accuracy_check = dict(
    )  # type: Dict[Tuple[AccessPoint, ...], List[svm_model]]
    best_gd_models = dict(
    )  # type: Dict[Tuple[AccessPoint, ...], Tuple[NormalizedMatrix, List[svm_model]]]
    best_jc_models = dict(
    )  # type: Dict[Tuple[AccessPoint, ...], Tuple[NormalizedMatrix, Dict[Tuple[AccessPoint, ...], List[svm_model]]]]
    ig_models = list()
    end_initialize_time = time()
    initialize_time = end_initialize_time - start_initialize_time
    # print("initialize time: {}s.".format(initialize_time))
    jc_time += initialize_time
    gd_time += initialize_time
    for train_indices, test_indices in split_kf:

        start_data_time = time()
        print("Starting Fold {} with {}.".format(fold_number, location_mode))

        fold = Fold()

        train_samples = list()  # type: List[Sample]
        test_samples = list()  # type: List[Sample]
        train_features = list()  # type: List[Dict[AccessPoint, int]]
        train_classes = list()  # type: List[int]
        test_features = list()  # type: List[Dict[AccessPoint, int]]
        test_classes = list()  # type: List[int]

        exam_features = list()  # type: List[Dict[AccessPoint, int]]
        exam_classes = list()  # type: List[int]

        # change to NNv4 mode
        for num in train_indices:
            train_samples.append(training_data[num])
            if num < median(train_indices):
                train_features.append(training_data[num].scan)
                train_classes.append(training_data[num].answer.num)
            else:
                test_features.append(training_data[num].scan)
                test_classes.append(training_data[num].answer.num)

        for num in test_indices:
            test_samples.append(training_data[num])
            exam_features.append(training_data[num].scan)
            exam_classes.append(training_data[num].answer.num)

        end_data_time = time()
        data_time = end_data_time - start_data_time
        # print("data time: {}s.".format(data_time))
        jc_time += data_time
        gd_time += data_time

        d = 3
        trained_models = list()  # type: List[IndividualModel]

        # info gain selection
        start_ig_time = time()
        ig_model = choose_best_info_gain(train_samples, access_points)
        ig_models.append(ig_model)
        end_ig_time = time()
        ig_time += end_ig_time - start_ig_time
        while d < len(access_points) + 1:
            start_combination_time = time()
            access_point_combinations = get_n_ap_combinations(
                access_points, d)  # type: List[Tuple[AccessPoint, ...]]
            end_combination_time = time()
            combination_time = end_combination_time - start_combination_time
            # print("combination time: {}s.".format(combination_time))
            jc_time += combination_time
            gd_time += combination_time
            # 6. Get all AP Combinations
            S_score = dict()  # type: Dict[Tuple[AccessPoint, ...], float]

            # ap_features = list()
            #
            # for feature_set in train_features:
            #     ap_features.append(
            #         [value for key, value in feature_set.items()])
            #
            # param_grid = {"gamma": [0.0001, 0.001, 0.01, 0.1, 1, 10, 100, 0.25, 0.5, 0.75, 0.3, 0.2, 0.15, 1000],
            #               "C": [0.001, 0.01, 0.1, 1, 10, 100, 1000]}
            # grid_search = GridSearchCV(SVC(decision_function_shape='ovo'), param_grid, cv=5)
            # grid_search.fit(ap_features, train_classes)
            # print("Best parameters:{}".format(grid_search.best_params_))
            # gamma = grid_search.best_params_['gamma']
            # c = grid_search.best_params_['C']
            start_svm_time = time()
            for access_point_tuple in access_point_combinations:
                # print("--- Working on AP Combination: {}".format(access_point_tuple))
                ap_train_features = list()
                ap_test_features = list()
                aps_being_used = [x for x in access_point_tuple]
                for feature_set in train_features:
                    ap_train_features.append([
                        value for key, value in feature_set.items()
                        if key in aps_being_used
                    ])

                for feature_set in test_features:
                    ap_test_features.append([
                        value for key, value in feature_set.items()
                        if key in aps_being_used
                    ])

                # m = svm_train(train_classes, ap_train_features, '-q -c {} -g {}'.format(c, gamma))
                m = svm_train(train_classes, ap_train_features, '-q')
                margins = m.get_labels()
                score = 0
                for margin in margins:
                    score += 0.5 * margin
                S_score[access_point_tuple] = score
                p_labs, p_acc, p_vals = svm_predict(y=test_classes,
                                                    x=ap_test_features,
                                                    m=m,
                                                    options='-q')
                if access_point_tuple in accuracy_check:
                    accuracy_check[access_point_tuple].append(m)
                else:
                    accuracy_check[access_point_tuple] = [m]

                individual_model = IndividualModel(
                    svm=m,
                    access_point_tuple=access_point_tuple,
                    zones=zones,
                    train_features=ap_train_features,
                    train_classes=train_classes,
                    test_features=ap_test_features,
                    test_classes=test_classes,
                    predictions=p_labs,
                    percentage_correct=p_acc[0])
                fold.add_trained_models({access_point_tuple: individual_model})
                trained_models.append(individual_model)
            end_svm_time = time()
            svm_time = end_svm_time - start_svm_time
            gd_time += svm_time
            if location_mode == "SVM":
                jc_time += svm_time
            # results = create_all_svm_matrices(trained_models=trained_models)
            # normalized_list[d] = results[1]
            start_find_time = time()
            best_one = tuple()  # type:Tuple[AccessPoint, ...]
            min_value = min(S_score.values())
            for keys, values in S_score.items():
                if values == min_value:
                    best_one = keys
            if d in best_ap_list.keys():
                best_ap_list[d].append(best_one)
            else:
                best_ap_list[d] = [best_one]
            end_find_time = time()
            find_time = end_find_time - start_find_time
            # print("find time: {}s.".format(find_time))
            gd_time += find_time
            # print("finish GD training for d = {}, best ap combination is {}".format(d, best_one))
            start_matrix_time = time()
            if location_mode == "SVM":
                start_distributions_time = time()
                print(
                    "Creating Probability and Normalized Probability Distributions..."
                )
                fold.create_probability_distributions()
                fold.create_normalized_distributions()
                fold.create_test_distributions(zones=zones,
                                               testing_features=exam_features,
                                               testing_class=exam_classes)
                end_distributions_time = time()
                distributions_time = end_distributions_time - start_distributions_time
                jc_time += distributions_time
            else:
                distributions = create_all_matrices_from_rssi_data(
                    access_points=access_points,
                    access_point_combinations=access_point_combinations,
                    centroids=centroids,
                    grid_points=grid_points,
                    zones=zones,
                    training_data=train_samples,
                    testing_data=test_samples,
                    combination_mode=combination_mode,
                    location_mode=location_mode,
                    num_combinations=num_combinations,
                    do_combination=False)
                # print("First Run")
                probability_distributions = distributions[0]
                normalized_distributions = distributions[1]
                test_results = distributions[2]
                fold.create_distributions(
                    access_point_combinations=access_point_combinations,
                    p_list=probability_distributions,
                    n_list=normalized_distributions,
                    t_list=test_results)
            end_matrix_time = time()
            matrix_time = end_matrix_time - start_matrix_time
            jc_time += matrix_time
            d += 1
        folds[fold_number] = fold
        print("Completed Fold {}.".format(fold_number))
        fold_number += 1
    averaged_normalized_distributions = dict()
    start_average_time = time()
    for ap_tuple in all_access_point_combinations:
        # print("--- Working on AP Combination: {}.".format(ap_tuple))
        distributions_to_average = list()  # type: List[NormalizedMatrix]
        svms_to_store = list()  # type: List[svm_model]
        test_to_average = list()  # type: List[TestResult]
        for fold in folds.values():
            distributions_to_average.append(
                fold.get_normalized_distribution(ap_tuple))
            svms_to_store.append(fold.get_SVM(ap_tuple))
            test_to_average.append(fold.get_test_distribution(ap_tuple))

        averaged_normalized_distribution = Fold.get_average_distribution(
            access_points=[*ap_tuple],
            zones=zones,
            distributions=distributions_to_average)
        averaged_test_accuracy = Fold.get_average_test_distribution(
            test_to_average)

        averaged_normalized_distributions[
            ap_tuple] = averaged_normalized_distribution, averaged_test_accuracy, svms_to_store

    print(
        "Completed. There are {} Normalized Distributions ready for combination."
        .format(len(averaged_normalized_distributions.values())))
    end_average_time = time()
    average_time = end_average_time - start_average_time
    # print("Average distribution time: {}s.".format(average_time))
    jc_time += average_time

    start_ig_find = time()
    best_ig_model = list()
    for i in range(len(access_points)):
        ap_list = [model[i] for model in ig_models]
        best_ig_model.append(max(ap_list, key=ap_list.count))
    end_ig_find = time()
    ig_time += end_ig_find - start_ig_find

    start_jc_model_time = time()
    jc_all_combination = dict()

    averaged_normalized_tuple = sorted(
        averaged_normalized_distributions.values(),
        key=lambda x: x[0].average_matrix_success,
        reverse=True)
    averaged_normalized_list = [
        normalized_tuple[0] for normalized_tuple in averaged_normalized_tuple
    ]
    averaged_test_tuple = sorted(averaged_normalized_distributions.values(),
                                 key=lambda x: x[1],
                                 reverse=True)
    averaged_test_list = [test_tuple[0] for test_tuple in averaged_test_tuple]
    for i in range(3, len(access_points) + 1):
        dict_best_model = dict()
        best_normalizations = [
            normalized_dist for normalized_dist in averaged_normalized_list
            if len(normalized_dist.access_points) == i
        ]
        best_tests = [
            test_dist for test_dist in averaged_test_list
            if len(test_dist.access_points) == i
        ]
        best_normalization = best_normalizations[0]
        best_test = best_tests[0]
        jc_all_combination[i] = best_normalizations
        if best_test == best_normalization:
            print("Self correction pass")
            jc_ap_tuple = best_normalization.access_points_tuple
            best_jc_normalized = best_normalization
        else:
            print("Self correction wrong")
            best_index_test = best_tests.index(best_normalization)
            if best_index_test > 2:
                jc_ap_tuple = best_test.access_points_tuple
                best_jc_normalized = best_test
            else:
                jc_ap_tuple = best_normalization.access_points_tuple
                best_jc_normalized = best_normalization
        dict_best_model[jc_ap_tuple] = averaged_normalized_distributions[
            jc_ap_tuple][2]
        best_jc_models[jc_ap_tuple] = best_jc_normalized, {
            jc_ap_tuple: accuracy_check[jc_ap_tuple]
        }
    end_jc_model_time = time()
    jc_time += end_jc_model_time - start_jc_model_time

    if location_mode == "SVM":
        start_gd_model_time = time()
        for index, value in best_ap_list.items():
            ap_set = max(set(value), key=value.count)
            best_matrix = averaged_normalized_distributions[ap_set][0]
            best_d_model = accuracy_check[ap_set]
            best_gd_models[ap_set] = best_matrix, best_d_model
            # print("d = {}, the Best AP Combination is: {}".format(index, ap_set))
        end_gd_model_time = time()
        gd_model_time = end_gd_model_time - start_gd_model_time
        gd_time += gd_model_time

        print("JC Time is {}, GD time is {} when location mode is SVM".format(
            jc_time, gd_time))
    else:
        if combine and len(access_points) >= 4:
            list_svm_model = list()
            best_combined_matrixs = list()

            mm_normalized_list = [
                normalized_tuple[0] for normalized_tuple in list(
                    averaged_normalized_distributions.values()) if
                normalized_tuple[0].access_points in list(mm_ap_dict.values())
            ]
            sort_matrices(mm_normalized_list)
            for num_combinations in range(2, 4):
                combined_distributions, normalized_combined_distributions = build_combined_distributions(
                    normalized_distributions=mm_normalized_list,
                    training_data=training_data,
                    centroids=centroids,
                    grid_points=grid_points,
                    zones=zones,
                    num_combination=num_combinations,
                    combination_mode=combination_mode,
                    location_mode=location_mode)
                sort_matrices(normalized_combined_distributions)
                best_combined_matrix = normalized_combined_distributions[0]
                best_combined_aps = best_combined_matrix.access_points_combo
                best_combined_matrixs.append(best_combined_matrix)
                best_svm_dict = dict()
                for aps in best_combined_aps:
                    best_svm_dict[aps] = accuracy_check[aps]
                list_svm_model.append(best_svm_dict)
            for d in range(len(best_combined_matrixs)):
                best_combined_matrix = best_combined_matrixs[d]
                best_svm_dict = list_svm_model[d]
                best_jc_models[
                    best_combined_matrix.
                    access_points_tuple] = best_combined_matrix, best_svm_dict

        start_gd_model_time = time()
        for index, value in best_ap_list.items():
            ap_set = max(set(value), key=value.count)
            best_matrix = next(
                normalized_dist for normalized_dist in averaged_normalized_list
                if normalized_dist.access_points_tuple == ap_set)
            best_d_model = accuracy_check[ap_set]
            best_gd_models[ap_set] = best_matrix, best_d_model
            # print("d = {}, the Best AP Combination is: {}".format(index, ap_set))
        end_gd_model_time = time()
        gd_model_time = end_gd_model_time - start_gd_model_time
        gd_time += gd_model_time

        print("JC Time is {}, GD time is {} when location mode is not SVM".
              format(jc_time, gd_time))

    return best_jc_models, best_gd_models, jc_time, gd_time, accuracy_check, best_ig_model, ig_time, jc_all_combination