<jupyter_start><jupyter_text>create a function to calculate the distance between any row and the training data<jupyter_code># function to calculate distance between two rows
def distance(row1, row2):
    # row[:-1] beacause the label shouldn't be included
    distance = (row2[:-1] - row1[:-1])**2
    sum = 0
    for i in distance:
        sum += i
    return math.sqrt(sum)<jupyter_output><empty_output><jupyter_text>next will create a function to return an array containing the distances between a certain row and the whole training dataset<jupyter_code># find the distance array between the sample row and the complete dataset
# returns an array of distances
def distances_array(example, dataset):
    distances = np.empty((0,2), int)
    id_ = 0
    for row in dataset:
        distances = np.append(distances, np.array([[id_, distance(example, row)]]), axis=0) # must return id and distance
        id_ += 1
    return distances<jupyter_output><empty_output><jupyter_text>to get the K-NN we need to sort the array resulting from the distances_array() and return the first K neighbors as an array<jupyter_code># k neighbours array 
# outputs the nearest K neighbors to a data example 
# returns an array with the nearest K neighbours and their id's
def k_neighbours(row, K, dataset):
    all_data = distances_array(row, dataset)
    sorted_all_data =  all_data[np.argsort(all_data[:,1])]
    KNN = sorted_all_data[:K]
    return KNN<jupyter_output><empty_output><jupyter_text>the below predict function will use the row, and k_neighbours() to predict the outcome and return the accuracy:<jupyter_code>def predict2(row, k, dataset_train):
    x = k_neighbours(row, k, dataset_train)
    ids = np.array([int(id[0]) for id in x])
    neighbors_labels = []
    for example in range(len(dataset_train)):
        for id_ in ids:
            if id_ == example:
                neighbors_labels.append(int(dataset_train[example][-1]))            
    true_label = row[-1]
    neighbors_labels_set = set(neighbors_labels)
    # we need to find p and accuracy
    # case 1: len(set(neighbour labels)) = 1
    if len(neighbors_labels_set) == 1:
        # neigb label consists only of true label
        if true_label in neighbors_labels_set:
            p = neighbors_labels[0]
            accuracy = 1
            return p, accuracy
        # same but tl is not in neigh label
        else:
            # len(neighbors_labels_set) == 1 and true_label not in neighbors_labels_set:
            p = neighbors_labels[0]
            accuracy = 0
            return p, accuracy
    # case 2: neighbor labels are mixed values
    else:
        nominees = find_ties(neighbors_labels)
        max_label = max(neighbors_labels, key = neighbors_labels.count)
        # pred label is in the neigh labels and not in the nominees then it has the majority
        if true_label == max_label and max_label not in nominees:
            p = max_label
            accuracy = 1
            return p, accuracy
        elif true_label != max_label and max_label not in nominees:
            p = max_label
            accuracy = 0
            return p, accuracy
        # tl is in nominees
        elif true_label in nominees:
            p = nominees
            accuracy = 1/len(p)
            return p, accuracy
        else:
            p = nominees
            accuracy = 0
            return p, accuracy<jupyter_output><empty_output><jupyter_text>find_ties() is a helper function, that will examine the list of k_neighbours and retun a set of ties in the outcome<jupyter_code>def find_ties(outcomes):
    # find number of labels in the final array
    unique_items, counts = np.unique(outcomes, return_counts=True)
    nominees = []
    k = 0
    for i in counts:
        m = 0
        for j in counts:
            if i == j and unique_items[k] != unique_items[m]:
                nominees.append(unique_items[k])
            m += 1
        k += 1
    return set(nominees)<jupyter_output><empty_output><jupyter_text>Start here<jupyter_code># load our training and testing sets
data_train = np.loadtxt('UCI_Dataset/pendigits_training.txt')
data_test = np.loadtxt('UCI_Dataset/pendigits_test.txt')
k=5

# normalize the data

data_train = (data_train - np.mean(data_train))/np.std(data_train)
data_test = (data_train - np.mean(data_train))/np.std(data_train)

result = []
id_=0
for row in data_test[:50]:
    p,a = predict2(row, k, data_train)
    result.append([id_, row[-1], p, a])
    id_ += 1
    # print something to show that its working
    if id_%20 == 0:
        print('reached id: ', id_)
# print results    
result
# save output to file:
with open('5nn2.txt', 'w') as f:
    for item in result:
        f.write("%s\n" % item)
data_train[:-1]<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.08766029009880176, 'fraction_numerical': 0.010300609627916754, 'mean_word_length': 2.877750611246944, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '6', 'dir': 'jupyter-structured-clean-dedup', 'id': '45708', 'license': 'MIT', 'n_tokens_mistral': 1505, 'n_tokens_neox': 1469, 'n_words': 481, 'path': 'KNN.ipynb', 'repo_name': 'ahmedqasem/ml_algos', 'size': '4757'}