<jupyter_start><jupyter_text>AI: K-Nearest Neighbors Classification problem with KNN: should we give a loan or no?In this project I use my own designed K-Nearest Neighbors and DataTable packages to predict if a person with respective attributes will pay loan back.I'll walk you through this process of model definition, fine-tuning and evaluation. You might want to jump to the interesting section immediately.Before exploring this work with KNN, go explore first [Logistic Regression note](https://github.com/kotsky/ai-dev/blob/main/logistic_regression_workflow.ipynb) which covers same data set. It's done to compare results of 2 different classification algorithms.1. [Section 1](id_1)- preparation2. [Section 2](id_2)- model building3. [Section 3](id_3)- k-evaluation4. [Section 4](id_4)- results IntroductionI had developed my own Pandas-like simplified package data_reader.py to fetch different kind of data faster than Pandas can do and contains main features for KNN AI like data preparation for training/testing, split data, adding new features, creating combined one, ploting and many others. In addition, to enhance my AI regression model's knowledge, I designed a knn.py package based on **a special k-size max heap data structure** to optimize a speed and memory complexities storing/comparing of nearest points to unknown data point. Moreover there is logs feature to monitor regression model learning and evaluation of its performance. All these features and techniques I would like to show in this notebook.For additional package usage, refer to doxy in its src code.For that session, I'm going to use a /data/loan_train.csv file, which contains table-like structure data of various cases when a person returns/not returns his loan back. It might be interesting to try to predict if the given person can get loan.  Section 1 - preparation<jupyter_code>import classification.knn as knn
import data_reader as dr
import matplotlib.pyplot as plt
from helper_methods import *
# Use same data as it was in LR work
main_data = dr.DataTable("data/loan_train.csv")<jupyter_output><empty_output><jupyter_text>![image.png](attachment:image.png)<jupyter_code>main_data.head<jupyter_output><empty_output><jupyter_text>Loan_status is going to be our target which we try to predict. It has 2 options: PAIDOFF and COLLECTION. DataTable helps to read csv file in a way that words (as a string data type) will be converted to numbers, which we can easily restore back.<jupyter_code>target_name = "loan_status"
main_data.select_target(target_name)
main_data.target[target_name].data[0:5]
main_data.class_dict[target_name]  # to check which number represent which word<jupyter_output><empty_output><jupyter_text>So, COLLECTION is 0, and PAIDOFF is 1. With that, let's move further. What about features?<jupyter_code>main_data.plot(parameter1='age', parameter2='Gender', classifier=target_name)<jupyter_output><empty_output><jupyter_text>Well, we can see that we don't have strongly marked relationship between features and target. Might be hard to predict with hight accurace loan returning. But we will try.  Section 2 - model building Let's create the same model as we had for Logistic regression, so we can compare their results.<jupyter_code>main_data.activate_features(['Principal',
 'terms',
 'effective_date',
 'age',
 'education',
 'Gender'])
main_data.add_new_feature(['education', 'age'])
main_data.add_new_feature(['Gender', 'age'])
main_data.max_scaling()
main_data.split_data(0.6, shuffle=True)
training_features_data, training_target_data = main_data.get_training_data()  # returns (features data, target data)
# cv_data = main_data.get_cv_data()
testing_data = main_data.get_testing_data()
# check how 0 and 1 were split after shuffling
axis_x = [x for x in range(len(training_target_data))]
plt.scatter(axis_x, training_target_data)
plt.show()
model_knn = knn.KNN()
model_knn.set_data([training_features_data, training_target_data])
model_knn.set_labels = main_data.get_labels()
model_knn.set_labels  # to check what we have in our model<jupyter_output><empty_output><jupyter_text>Section 3 - k-evaluation In this section I would like to explore which value of k might be the best for our model to predict.<jupyter_code>def get_accuracy_from_cm(cm):
    accuracy = (cm[0][0] + cm[1][1]) / (cm[0][0] + cm[1][1] + cm[0][1] + cm[1][0])
    return round(accuracy, 2)

k_array = [1, 3, 5, 7, 9, 11]
accuracy_array = []
precision_array = []
recall_array = []
f1_score_array = []

for k in k_array:
    model_knn.k_nn = k
    confusion_matrix, precision, recall = model_knn.evaluation(testing_data)
    precision_array.append(precision)
    recall_array.append(recall)
    accuracy_array.append(get_accuracy_from_cm(confusion_matrix))
    f1_score_array.append(2 * precision * recall / (precision + recall))

accuracy_array
f1_score_array
recall_array
precision_array<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.08261933904528763, 'fraction_numerical': 0.01040391676866585, 'mean_word_length': 5.88623595505618, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 25, 'https://': 1, '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': '101180', 'license': 'MIT', 'n_tokens_mistral': 1512, 'n_tokens_neox': 1455, 'n_words': 532, 'path': 'knn_workflow.ipynb', 'repo_name': 'kotsky/ai_dev', 'size': '4902'}