<jupyter_start><jupyter_text>Helper Functions  Getting the potential split<jupyter_code>def get_potential_splits(data,random_subspace):
    
    potential_splits = {}
    column_indices = list(range(data.shape[1]-1))
    
    
    if random_subspace and random_subspace < data.shape[1]:
        column_indices = random.sample(population = column_indices,k = random_subspace)
    
    for column_index in  column_indices :
            
            values =data[:,column_index] 
            
            if FEATURE_TYPES[column_index] == 'Continious':
                
                unique_values = np.unique(values)
                potential_splits[column_index] = []
                
                for i in range(len(unique_values)-1):
                    current_value = unique_values[i]
                    next_value = unique_values[i+1]
                    potential_split = (current_value+next_value)/2
                
                    potential_splits[column_index].append(potential_split)
            
            else:
                potential_splits[column_index]=list(set(values))
             
            
    return potential_splits<jupyter_output><empty_output><jupyter_text>Checking type of features<jupyter_code>def determine_type_of_feature(data):
    
    feature_types = []
    threshold = 15
    
    for column_index in range(data.shape[1]-1):
        
        unique_values = np.unique(data[:,column_index])
            
        if(len(unique_values)<=threshold)or isinstance(unique_values[0],str):
            feature_types.append('Categorical')
        else:
            feature_types.append('Continious')
            
    return feature_types<jupyter_output><empty_output><jupyter_text>Split Function<jupyter_code>def split_data(data,split_column,split_value):
    
    values = data[:,split_column]
    type_of_feature = FEATURE_TYPES[split_column] 
    
    if type_of_feature == 'Continious':
        data_above = data[values > split_value]
        data_below = data[values <= split_value]
    else:
        data_below = data[values == split_value]
        data_above = data[values != split_value]
        
    return data_below,data_above<jupyter_output><empty_output><jupyter_text>Metric Functions  Gini Index<jupyter_code>def gini(data):
    
    label_column= data[:,-1]
    _,counts = np.unique(label_column,return_counts=True)
    
    p=counts/counts.sum()
    gini =1- np.dot(p,p)
    
    return gini<jupyter_output><empty_output><jupyter_text>Entropy<jupyter_code>def entropy(data):
    
    label_columns = data[:,-1]
    _,counts = np.unique(label_columns,return_counts= True)
    
    p = counts/counts.sum()
    entropy = sum(p*-np.log2(p))
    
    
    return entropy<jupyter_output><empty_output><jupyter_text>Overall Metric<jupyter_code>def overall_metric(data_below,data_above,metric_function):
    
    n=len(data_above)+len(data_below)
    p_data_below = len(data_below)/n
    p_data_above = len(data_above)/n
    
    overall_metric = p_data_above*metric_function(data_above) + p_data_below*metric_function(data_below)
    
    return overall_metric<jupyter_output><empty_output><jupyter_text>Getting the best split<jupyter_code>def get_best_split(data, potential_splits, metric_function = gini):
    
    first_iteration = True
    for column_index in potential_splits:
        for value in potential_splits[column_index]:
            
            data_below,data_above = split_data(data,split_column=column_index,split_value = value)
            current_metric = overall_metric(data_above,data_below,metric_function)
            
            if first_iteration:
                
                best_metric = current_metric
                first_iteration = False
            
            if current_metric <= best_metric :
                
                best_metric = current_metric
                best_column =column_index
                best_value = value
                
                
    return best_column,best_value<jupyter_output><empty_output><jupyter_text>Check Purity<jupyter_code>def  check_purity(data):
    label_columns = data[:,-1]
    
    if len(np.unique(label_columns))==1:
        return True
    else:
        return False<jupyter_output><empty_output><jupyter_text>Creating Leaf<jupyter_code>def create_leaf(data):
    
    label_columns = data[:,-1]
    unique_labels,counts = np.unique(label_columns,return_counts =True)
    
    index = counts.argmax()
    leaf = unique_labels[index]
    
    return leaf<jupyter_output><empty_output><jupyter_text>Train Test Split<jupyter_code>def train_test_split(df,split_ratio = 0.7,random_state=123):
    
    np.random.seed(random_state)
    indices = np.random.rand(len(df))<split_ratio
    return df.iloc[indices,:],df.iloc[~indices,:]<jupyter_output><empty_output><jupyter_text>Bootstrapping<jupyter_code>def bootstrap(data,n_bootstrap):
    
    indices =np.random.randint(low=0,high=len(data),size=n_bootstrap)
    
    return data[indices]<jupyter_output><empty_output><jupyter_text>Decision Tree Algorithm<jupyter_code>def decision_tree_algorithm(data,counter =0, max_depth =5,min_samples = 10,random_subspace=None,metric_function = gini):
    
    if counter == 0:
    
        global FEATURE_TYPES
        FEATURE_TYPES = determine_type_of_feature(data)
    
    
    if (check_purity(data)) or (counter == max_depth) or (len(data) < min_samples):
        return create_leaf(data)
    
    else:
        
        counter += 1
        
        potential_splits = get_potential_splits(data, random_subspace)
        column_index,split_value = get_best_split(data, potential_splits, metric_function)
        data_below,data_above = split_data(data, column_index, split_value)
         
        if len(data_below)==0 or len(data_above)==0 :
            return create_leaf(data)
        
        
        type_of_feature = FEATURE_TYPES[column_index]
        #column_name = COLUMN_NAMES[column_index]
        
        if type_of_feature == 'Continious':
            question = "{} <= {}".format(column_index,split_value)
        else:
            question ="{} = {}".format(column_index,split_value)
        sub_tree={question:[]}
        
        yes_answer = decision_tree_algorithm(data_below, counter, max_depth, min_samples,random_subspace  ,metric_function )
        no_answer = decision_tree_algorithm(data_above, counter, max_depth, min_samples,random_subspace  ,metric_function )
        
        if yes_answer == no_answer:
            sub_tree =yes_answer
        else:
            sub_tree[question].append(yes_answer)
            sub_tree[question].append(no_answer)
       
        return sub_tree<jupyter_output><empty_output><jupyter_text>Decision Tree Classifier<jupyter_code>def decision_tree_classifer(example,tree):
    question = list(tree.keys())[0]
    column_index,comparison_operator,value =question.split()
    column_index =int(column_index)
    
    if comparison_operator == "<=":
        if example[column_index] <= float(value):
            answer = tree[question][0]
        else:
            answer = tree[question][1]
    
    
    else:
        if str(example[column_index]) == value:
            answer = tree[question][0]
        else:
            answer = tree[question][1]

    if not isinstance(answer,dict):
        return answer
    
    else:
        residual_tree = answer
        return decision_tree_classifer(example, residual_tree)<jupyter_output><empty_output><jupyter_text>Random Forest Algorithm<jupyter_code>def random_forest_algorithm(train_data, n_trees,max_depth = 5,min_samples =10,random_state = 123, n_features = 3, n_bootstrap=50,metric_function =gini):
    
    np.random.seed(random_state)
    forest = []
    for i in range(n_trees):
        
        bootstrapped_data = bootstrap(train_data,n_bootstrap)
        tree = decision_tree_algorithm(data = bootstrapped_data, counter=0, random_subspace = n_features, max_depth = max_depth,metric_function=metric_function)
        forest.append(tree)
        
    return forest<jupyter_output><empty_output><jupyter_text>Random Forest Classifier<jupyter_code>def random_tree_classifier(example,forest):
    
    results =[]
    for index in range(len(forest)):
        
        result = decision_tree_classifer(example, forest[index] )
        results.append(result)
        
    mode = max(set(results),key=results.count)
    return mode<jupyter_output><empty_output><jupyter_text>Accuracy<jupyter_code>def classify_data(test_df,forest):
    
    Predictions = test_df.apply(func = random_tree_classifier, axis = 1, raw=True,args=(forest,))
    
    return Predictions
def calculate_accuracy(labels,predictions):
        
 
    accuracy = np.array(labels == predictions).mean()
    
    return accuracy<jupyter_output><empty_output><jupyter_text>Benchmarking  Importing  the SKLearn Library<jupyter_code>from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import make_classification
from sklearn.metrics import accuracy_score
from sklearn import ensemble<jupyter_output><empty_output><jupyter_text>Loading the data<jupyter_code>columns = ['variance', 'skewness', 'curtosis', 'entropy', 'class']
data = "https://archive.ics.uci.edu/ml/machine-learning-databases/00267/data_banknote_authentication.txt"
banknote = pd.read_csv(data, names= columns)
banknote.head()<jupyter_output><empty_output><jupyter_text>Train Test Split<jupyter_code>train_df ,test_df= train_test_split(banknote)

print(train_df.shape)
print(test_df.shape)<jupyter_output>(967, 5)
(405, 5)<jupyter_text>Implementation of our model<jupyter_code>%%time
forest=random_forest_algorithm(train_df.values,n_trees = 5,n_features=2,n_bootstrap=100,random_state =120)
predictions = classify_data(test_df.iloc[:,:-1],forest)
labels = test_df.iloc[:,-1]

print("Accuracy is : {}".format(calculate_accuracy(predictions,labels)*100))<jupyter_output>Accuracy is : 94.32098765432099<jupyter_text>SKLearn Implementation<jupyter_code>X_train = train_df.values[:,:-1]
y_train = train_df.values[:,-1]
X_test = test_df.values[:,:-1]
y_test = test_df.values[:,-1]
%%time
clf_entropy = RandomForestClassifier( criterion = "entropy", random_state = 100,
                               max_depth=3, min_samples_leaf=5)
clf_entropy.fit(X_train,y_train)
y_pred = clf_entropy.predict(X_test)

print ("Accuracy is ", accuracy_score(y_test , y_pred)*100)<jupyter_output>Accuracy is  93.33333333333333
StarcoderdataJupyterStructuredCleanDedup