CoolFace
Apppublic

Greygt/data-mining-tools

sourceHugging Faceupdated 11mo agoView on Hugging Face
0likes
app.py260 linesDownload Raw Back to root
1# Import all necessary libraries2import gradio as gr3import math4import pandas as pd5import numpy as np6from sklearn.preprocessing import OneHotEncoder, LabelEncoder7from sklearn.tree import DecisionTreeClassifier, plot_tree8import matplotlib.pyplot as plt9import io10import contextlib11 12# ==============================================================================13# TAB 1 FUNCTIONS: MUTUAL INFORMATION CALCULATOR14# ==============================================================================15 16def calculate_mutual_information(ug_a, ug_b, ug_c, g_a, g_b, g_c):17    """18    Calculates probabilities, entropies, and mutual information based on the19    provided student and grade counts, returning a formatted text output.20    """21    22    # Define data and total number of students23    total_students = ug_a + ug_b + ug_c + g_a + g_b + g_c24    if total_students == 0:25        return "Error: Total number of students cannot be 0.", ""26        27    counts = {28        'undergrad_A': ug_a, 'undergrad_B': ug_b, 'undergrad_C': ug_c,29        'grad_A': g_a, 'grad_B': g_b, 'grad_C': g_c30    }31 32    # --- Marginal Probabilities ---33    count_undergrad = ug_a + ug_b + ug_c34    count_grad = g_a + g_b + g_c35    p_undergrad = count_undergrad / total_students36    p_grad = count_grad / total_students37 38    count_A = ug_a + g_a39    count_B = ug_b + g_b40    count_C = ug_c + g_c41    p_A = count_A / total_students42    p_B = count_B / total_students43    p_C = count_C / total_students44 45    # --- Individual Entropies ---46    entropy_status = 047    if p_undergrad > 0: entropy_status -= p_undergrad * math.log2(p_undergrad)48    if p_grad > 0: entropy_status -= p_grad * math.log2(p_grad)49 50    entropy_grade = 051    if p_A > 0: entropy_grade -= p_A * math.log2(p_A)52    if p_B > 0: entropy_grade -= p_B * math.log2(p_B)53    if p_C > 0: entropy_grade -= p_C * math.log2(p_C)54 55    # --- Joint Entropy ---56    joint_entropy = 057    for count in counts.values():58        if count > 0:59            p_joint = count / total_students60            joint_entropy -= p_joint * math.log2(p_joint)61 62    # --- Mutual Information ---63    mutual_information = entropy_status + entropy_grade - joint_entropy64    65    # Prepare the results as formatted text66    results = f"""67    ### Marginal Probabilities68    - **P(Status=Undergrad):** {p_undergrad:.4f} ({count_undergrad}/{total_students})69    - **P(Status=Grad):** {p_grad:.4f} ({count_grad}/{total_students})70    - **P(Grade=A):** {p_A:.4f} ({count_A}/{total_students})71    - **P(Grade=B):** {p_B:.4f} ({count_B}/{total_students})72    - **P(Grade=C):** {p_C:.4f} ({count_C}/{total_students})73 74    ### Individual Entropies75    - **Entropy of Student Status, H(Status):** {entropy_status:.4f}76    - **Entropy of Grade, H(Grade):** {entropy_grade:.4f}77 78    ### Joint Entropy79    - **Joint Entropy, H(Status, Grade):** {joint_entropy:.4f}80    81    ---82    83    ### FINAL RESULT: MUTUAL INFORMATION84    **I(Status; Grade) = H(Status) + H(Grade) - H(Status, Grade)**85    **I(Status; Grade) = {entropy_status:.4f} + {entropy_grade:.4f} - {joint_entropy:.4f} = {mutual_information:.4f}**86    """87    88    summary = f"""89    - **H(Status):** {entropy_status:.4f}90    - **H(Grade):** {entropy_grade:.4f}91    - **H(Status, Grade):** {joint_entropy:.4f}92    - **Mutual Information I(Status; Grade):** {mutual_information:.4f}93    """94    95    return results, summary96 97# ==============================================================================98# TAB 2 FUNCTIONS: DECISION TREE BUILDER99# ==============================================================================100 101def calculate_entropy(data_column):102    class_counts = data_column.value_counts()103    total_samples = len(data_column)104    entropy = 0105    for count in class_counts:106        probability = count / total_samples107        if probability > 0:108            entropy -= probability * np.log2(probability)109    return entropy110 111def generate_decision_tree(df):112    """113    Calculates the steps for building a Decision Tree from a given DataFrame,114    plots the tree, and returns the steps as text and the plot object.115    """116    log_stream = io.StringIO()117    with contextlib.redirect_stdout(log_stream):118        # --- Data Preprocessing and Validation ---119        if df.shape[1] < 2:120            return "Error: The dataset must contain at least one feature and one target column.", None121        122        target_name = df.columns[-1]123        feature_names = df.columns[:-1].tolist()124 125        # --- Initial Entropy ---126        initial_entropy = calculate_entropy(df[target_name])127        print(f"### 1. Initial Entropy (Root Node) H(S)")128        print(f"Target Column: '{target_name}'")129        print(f"H(S) = {initial_entropy:.4f}\n")130 131        # --- Information Gain ---132        print("### 2. Calculating Information Gain for Each Attribute\n")133        gains = {}134        for attribute in feature_names:135            total_entropy = initial_entropy136            weighted_entropy = 0137            attribute_values = df[attribute].unique()138            print(f"--- Information Gain for '{attribute}' ---")139            for value in attribute_values:140                subset = df[df[attribute] == value]141                subset_entropy = calculate_entropy(subset[target_name])142                weight = len(subset) / len(df)143                weighted_entropy += weight * subset_entropy144                print(f"  Value='{value}': Weight={weight:.2f}, Entropy={subset_entropy:.4f}")145            146            information_gain = total_entropy - weighted_entropy147            gains[attribute] = information_gain148            print(f"Weighted Average Entropy E({attribute}) = {weighted_entropy:.4f}")149            print(f"Information Gain Gain({attribute}) = {total_entropy:.4f} - {weighted_entropy:.4f} = {information_gain:.4f}\n")150        151        # --- Root Node Selection ---152        if not gains:153             root_node = "N/A"154        else:155             root_node = max(gains, key=gains.get)156        print(f"### 3. Determining the Root Node")157        for attr, gain in gains.items():158            print(f"Gain({attr}) = {gain:.4f}")159        print(f"\nThe highest information gain belongs to '{root_node}'. Therefore, the **Root Node = '{root_node}'**\n")160 161        # --- Decision Tree Visualization (with Scikit-learn) ---162        print("### 4. Decision Tree Structure and Visualization")163        X_categorical = df[feature_names]164        y_target = df[target_name]165 166        # OneHotEncoder converts categorical data into a numerical format167        encoder = OneHotEncoder(sparse_output=False, handle_unknown='ignore')168        X_encoded = encoder.fit_transform(X_categorical)169        encoded_feature_names = encoder.get_feature_names_out(feature_names)170 171        # LabelEncoder converts the target variable into a numerical format172        le = LabelEncoder()173        y_encoded = le.fit_transform(y_target)174 175        model = DecisionTreeClassifier(criterion='entropy', random_state=42)176        model.fit(X_encoded, y_encoded)177 178        plt.figure(figsize=(12, 8))179        plot_tree(model,180                  feature_names=encoded_feature_names,181                  class_names=le.classes_,182                  filled=True,183                  rounded=True,184                  fontsize=10)185        plt.title("Visual Representation of the Generated Decision Tree", fontsize=16)186        187    calculation_steps = log_stream.getvalue()188    return calculation_steps, plt189 190# ==============================================================================191# GRADIO INTERFACE CREATION192# ==============================================================================193 194with gr.Blocks(theme=gr.themes.Soft()) as demo:195    gr.Markdown(196        """197        This tool allows you to interactively perform the calculations from the SWE-513 Data Mining course.198        """199    )200    201    with gr.Tabs():202        # --- TAB 1: MUTUAL INFORMATION CALCULATOR ---203        with gr.TabItem("Mutual Information Calculator"):204            with gr.Row():205                with gr.Column(scale=1):206                    gr.Markdown("### Input Values\nPlease enter the student counts.")207                    ua_input = gr.Number(label="Undergrad - Grade A", value=10)208                    ub_input = gr.Number(label="Undergrad - Grade B", value=25)209                    uc_input = gr.Number(label="Undergrad - Grade C", value=10)210                    ga_input = gr.Number(label="Graduate - Grade A", value=30)211                    gb_input = gr.Number(label="Graduate - Grade B", value=15)212                    gc_input = gr.Number(label="Graduate - Grade C", value=10)213                    btn_quiz1 = gr.Button("Calculate", variant="primary")214                with gr.Column(scale=2):215                    gr.Markdown("### Calculation Summary")216                    summary_output_q1 = gr.Markdown()217                    gr.Markdown("### Detailed Results")218                    detailed_output_q1 = gr.Markdown()219 220        # --- TAB 2: DECISION TREE BUILDER ---221        with gr.TabItem("Decision Tree Builder"):222            with gr.Row():223                with gr.Column(scale=1):224                    gr.Markdown("### Input Dataset\nYou can edit the table below or paste your own data.")225                    # Sample dataset from Quiz-2226                    initial_df = pd.DataFrame({227                        'Age': ['Young', 'Middle-age', 'Young', 'Older', 'Middle-age'],228                        'Weight': ['Thin', 'Thin', 'Fat', 'Thin', 'Fat'],229                        'Diagnosis': ['Negative', 'Negative', 'Negative', 'Positive', 'Positive']230                    })231                    df_input = gr.Dataframe(232                        value=initial_df, 233                        headers=['Age', 'Weight', 'Diagnosis'], 234                        row_count=5, 235                        col_count=(3, "fixed"),236                        label="Dataset (The last column should be the target)"237                    )238                    btn_quiz2 = gr.Button("Generate Decision Tree", variant="primary")239                with gr.Column(scale=2):240                    gr.Markdown("### Calculation Steps")241                    steps_output_q2 = gr.Markdown()242                    gr.Markdown("### Visualized Decision Tree")243                    plot_output_q2 = gr.Plot()244                    245    # Connect button clicks to their respective functions246    btn_quiz1.click(247        fn=calculate_mutual_information, 248        inputs=[ua_input, ub_input, uc_input, ga_input, gb_input, gc_input], 249        outputs=[detailed_output_q1, summary_output_q1]250    )251    252    btn_quiz2.click(253        fn=generate_decision_tree,254        inputs=df_input,255        outputs=[steps_output_q2, plot_output_q2]256    )257 258# Launch the interface259if __name__ == "__main__":260    demo.launch()