From 940d035638010e8102ec107d3bf6e001b98c6a9f Mon Sep 17 00:00:00 2001 From: Shaun Reed Date: Sun, 6 Feb 2022 13:39:26 -0500 Subject: [PATCH] Add Python project examples + Neural network CLI + Hidden Markov Model CLI + K-Means clustering CLI + Linear regression CLI + Screenshots, updated README instructions --- python/README.md | 13 + python/k-means/README.md | 95 +++ python/k-means/input.txt | 15 + python/k-means/k-means.py | 438 ++++++++++++ python/k-means/requirements.txt | 2 + python/k-means/screenshot.png | Bin 0 -> 45138 bytes python/linear-regression/README.md | 65 ++ python/linear-regression/input.txt | 17 + python/linear-regression/linear-regression.py | 198 ++++++ python/linear-regression/screenshot.png | Bin 0 -> 31108 bytes python/markov-model/README.md | 119 ++++ python/markov-model/input.json | 16 + python/markov-model/markov-model.py | 481 +++++++++++++ python/markov-model/requirements.txt | 3 + python/markov-model/screenshot.png | Bin 0 -> 53806 bytes python/neural-network/IRIS.csv | 151 ++++ python/neural-network/README.md | 200 ++++++ python/neural-network/input-test.json | 44 ++ python/neural-network/input.json | 12 + python/neural-network/neural-network.py | 649 ++++++++++++++++++ python/neural-network/requirements.txt | 5 + python/neural-network/screenshot.png | Bin 0 -> 117148 bytes 22 files changed, 2523 insertions(+) create mode 100644 python/README.md create mode 100644 python/k-means/README.md create mode 100644 python/k-means/input.txt create mode 100644 python/k-means/k-means.py create mode 100644 python/k-means/requirements.txt create mode 100644 python/k-means/screenshot.png create mode 100644 python/linear-regression/README.md create mode 100644 python/linear-regression/input.txt create mode 100644 python/linear-regression/linear-regression.py create mode 100644 python/linear-regression/screenshot.png create mode 100644 python/markov-model/README.md create mode 100644 python/markov-model/input.json create mode 100644 python/markov-model/markov-model.py create mode 100644 python/markov-model/requirements.txt create mode 100644 python/markov-model/screenshot.png create mode 100755 python/neural-network/IRIS.csv create mode 100644 python/neural-network/README.md create mode 100644 python/neural-network/input-test.json create mode 100644 python/neural-network/input.json create mode 100644 python/neural-network/neural-network.py create mode 100644 python/neural-network/requirements.txt create mode 100644 python/neural-network/screenshot.png diff --git a/python/README.md b/python/README.md new file mode 100644 index 0000000..aed010a --- /dev/null +++ b/python/README.md @@ -0,0 +1,13 @@ + +This directory contains a collection of Python scripts or CLI tools that I've made. +Each of these projects provide a `requirements.txt` that can be used to +install the required Python packages and dependencies. + +To install Python 3.9 and `pip` + +```bash +sudo apt install python3.9 python3-pip +python3.9 -m pip install -U pip +``` + +Additional setup instructions specific to each project provided in project README diff --git a/python/k-means/README.md b/python/k-means/README.md new file mode 100644 index 0000000..33e5cb6 --- /dev/null +++ b/python/k-means/README.md @@ -0,0 +1,95 @@ +Install required dependencies for matplotlib GUI frontend and all pip other packages for this project + +```bash +sudo apt install python3-tk +python3.9 -m pip install -r requirements.txt +``` + +CLI to run K-Means clustering algorithm on a set of data. +Data can be provided or randomly generated for testing. + +```bash +python3.9 k-means.py -h +usage: k-means.py [-h] [--data [X,Y ...]] [--seeds [X,Y ...]] [--silent] [--verbose] [--random] [--radius [RADIUS]] + [--lock-radius] [--file [FILE_PATH]] + [CLUSTER_COUNT] [CENTROID_SHIFT] [LOOP_COUNT] + +K-means clustering program for clustering data read from a file, terminal, or randomly generated + +positional arguments: + CLUSTER_COUNT Total number of desired clusters + (default: '2') + + CENTROID_SHIFT Centroid shift threshold. If cluster centroids move less-than this value, clustering is finished + (default: '1.0') + + LOOP_COUNT Maximum count of loops to perform clustering + (default: '3') + + +optional arguments: + -h, --help show this help message and exit + --data [X,Y ...], -d [X,Y ...] + A list of data points separated by spaces as: x,y x,y x,y ... + (default: '[(1.0, 2.0), (2.0, 3.0), (2.0, 2.0), (5.0, 6.0), (6.0, 7.0), (6.0, 8.0), (7.0, 11.0), (1.0, 1.0)]') + + --seeds [X,Y ...], --seed [X,Y ...], -s [X,Y ...] + A list of seed points separated by spaces as: x,y x,y x,y ... + Number of seeds provided must match CLUSTER_COUNT, or else CLUSTER_COUNT will be overriden. + + --silent When this flag is set, scatter plot visualizations will not be shown + (default: 'False') + + --verbose, -v When this flag is set, cluster members will be shown in output + (default: 'False') + + --random, -r When this flag is set, data will be randomly generated + (default: 'False') + + --radius [RADIUS] Initial radius to use for clusters + (default: 'None') + + --lock-radius, -l When this flag is set, centroid radius will not be recalculated + (default: 'False') + + --file [FILE_PATH], -f [FILE_PATH] + Optionally provide file for data to be read from. Each point must be on it's own line with format x,y +``` + +Running k-means clustering program +```bash +python3.9 k-means.py --file ./input.txt --silent +Finding K-means clusters for given data [(1.0, 2.0), (2.0, 3.0), (2.0, 2.0), (5.0, 6.0), (6.0, 7.0), (6.0, 8.0), (7.0, 11.0), (1.0, 1.0), (5.0, 5.0), (10.0, 10.0), (15.0, 15.0), (25.0, 25.0), (20.0, 20.0), (21.0, 21.0), (22.0, 22.0)] + Using 2 clusters, 1.0 max centroid shift, and 3 iterations + +Clustering iteration 0 +Updating cluster membership using cluster seeds, radius: + ((5.0000, 5.0000), 10.6066) + ((20.0000, 20.0000), 10.6066) +Outliers present: set() + +Updated clusters ([(5.0, 5.0), (20.0, 20.0)]) with new centroids [(4.5, 5.5), (20.6, 20.6)] +New centroids [(4.5, 5.5), (20.6, 20.6)] shifted [0.7071, 0.8485] respectively + + +Showing final cluster result... +Initial cluster at (5.0000, 5.0000) moved to (4.5000, 5.5000) + Total shift: 0.7071 + Final radius: 11.0365 + Initial radius: 10.6066 +Initial cluster at (20.0000, 20.0000) moved to (20.6000, 20.6000) + Total shift: 0.8485 + Final radius: 11.0365 + Initial radius: 10.6066 + +Stopping... +Cluster centroids have not shifted at least 1.0, clusters are stable +``` + +Running k-means clustering program on some random example data shows the following visual output +```bash +python3.9 k-means.py --random +# Output removed for GUI example +``` + +![](screenshot.png) diff --git a/python/k-means/input.txt b/python/k-means/input.txt new file mode 100644 index 0000000..b3f394d --- /dev/null +++ b/python/k-means/input.txt @@ -0,0 +1,15 @@ +1,2 +2,3 +2,2 +5,6 +6,7 +6,8 +7,11 +1,1 +5,5 +10,10 +15,15 +25,25 +20,20 +21,21 +22,22 \ No newline at end of file diff --git a/python/k-means/k-means.py b/python/k-means/k-means.py new file mode 100644 index 0000000..b5f8549 --- /dev/null +++ b/python/k-means/k-means.py @@ -0,0 +1,438 @@ +################################################################################ +# Author: Shaun Reed # +# About: K-Means clustering CLI # +# Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 # +################################################################################ + +from ast import literal_eval +from itertools import chain +from matplotlib import pyplot as plt +from typing import List +import argparse +import math +import numpy as np +import random +import sys + + +################################################################################ +# CLI Argument Parser +################################################################################ + +# ============================================================================== + +def init_parser(): + parser = argparse.ArgumentParser( + description='K-means clustering program for clustering data read from a file, terminal, or randomly generated', + formatter_class=argparse.RawTextHelpFormatter + ) + + parser.add_argument( + 'clusters', metavar='CLUSTER_COUNT', type=int, nargs='?', + help= + '''Total number of desired clusters + (default: '%(default)s') + ''', + default=2 + ) + + parser.add_argument( + 'shift', metavar='CENTROID_SHIFT', type=float, nargs='?', + help= + '''Centroid shift threshold. If cluster centroids move less-than this value, clustering is finished + (default: '%(default)s') + ''', + default=1.0 + ) + + parser.add_argument( + 'loops', metavar='LOOP_COUNT', type=int, nargs='?', + help= + '''Maximum count of loops to perform clustering + (default: '%(default)s') + ''', + default=3 + ) + + parser.add_argument( + '--data', '-d', metavar='X,Y', type=point, nargs='*', + help= + '''A list of data points separated by spaces as: x,y x,y x,y ... + (default: '%(default)s') + ''', + default=[(1.0, 2.0), (2.0, 3.0), (2.0, 2.0), (5.0, 6.0), (6.0, 7.0), (6.0, 8.0), (7.0, 11.0), (1.0, 1.0)] + ) + + parser.add_argument( + '--seeds', '--seed', '-s', metavar='X,Y', type=point, nargs='*', + help= + '''A list of seed points separated by spaces as: x,y x,y x,y ... + Number of seeds provided must match CLUSTER_COUNT, or else CLUSTER_COUNT will be overriden. + ''', + ) + + parser.add_argument( + '--silent', action='store_true', + help= + '''When this flag is set, scatter plot visualizations will not be shown + (default: '%(default)s') + ''', + default=False + ) + + parser.add_argument( + '--verbose', '-v', action='store_true', + help= + '''When this flag is set, cluster members will be shown in output + (default: '%(default)s') + ''', + default=False + ) + + parser.add_argument( + '--random', '-r', action='store_true', + help= + '''When this flag is set, data will be randomly generated + (default: '%(default)s') + ''', + default=False + ) + + parser.add_argument( + '--radius', metavar='RADIUS', type=float, nargs='?', + help= + '''Initial radius to use for clusters + (default: '%(default)s') + ''', + default=None + ) + + parser.add_argument( + '--lock-radius', '-l', action='store_true', + help= + '''When this flag is set, centroid radius will not be recalculated + (default: '%(default)s') + ''', + default=False + ) + + parser.add_argument( + '--file', '-f', metavar='FILE_PATH', nargs='?', type=open, + help= + '''Optionally provide file for data to be read from. Each point must be on it\'s own line with format x,y + ''', + ) + return parser + + +################################################################################ +# Helper Functions +################################################################################ + +# ============================================================================== + +def point(arg): + """ + Helper function for parsing x,y points provided through argparse CLI + + :param arg: A single argument passed to an option or positional argument + :return: A tuple (x, y) representing a data point + """ + try: + x, y = literal_eval(arg) + return float(x), float(y) # Cast all point values to float + except: + raise argparse.ArgumentTypeError("Please provide data points in x,y format") + + +def random_data(): + """ + Generates random data points for testing clustering + + :return: A list of random data point tuples [(1, 1), (2, 4), ...] + """ + data_size = random.randint(50, random.randint(100, 200)) + data = [] + for x in range(0, data_size): + data.append((random.randint(0, 100), random.randint(0, 100))) + return data + + +def round_points(points, precision=4): + """ + Rounds all points in a list to a given decimal place + + :param points: A list of data points to round to requested decimal place + :param precision: The decimal place to round to + :return: A list of points where (x, y) has been rounded to match requested precision value + """ + points = [(round(x, precision), round(y, precision)) for x,y in points] + return points + + +################################################################################ +# K-means Clustering +################################################################################ + +# ============================================================================== + +def select_seeds(data): + """ + Randomly select N seeds where N is the number of clusters requested through the CLI + + :param data: A list of data points [(0, 1), (2, 2), (1, 4), ...] + :return: Dictionary of {seeds: radius}; For example {(2, 2): 5.0, (1, 4): 5.0} + """ + assert(len(data) > context.clusters) + x, y = zip(*data) + seeds = {} # Store seeds in a dictionary + for i in range(0, context.clusters): + while True: + new_seed = data[random.randint(0, len(data) - 1)] + if new_seed not in seeds: + break + seeds[new_seed] = i if not context.radius else context.radius + + if context.radius: + # An initial radius was provided and applied. Use it. + return seeds + else: + # No initial radius was provided, so calculate one + return update_clusters(seeds) + + +def points_average(data): + """ + Finds average (x, y) for points in data list [(x, y), (x, y), ...] + Used for updating cluster centroid positions + + :param data: List [(x, y), (x, y), ...] + :return: An average (x, y) position for the list of points + """ + x, y = 0, 0 + for pair in data: + x += pair[0] + y += pair[1] + x = float(x / len(data)) + y = float(y / len(data)) + return x, y + + +def update_clusters(seeds, clusters=None): + """ + Seeds {(x, y), radius} for clusters must be provided + If no clusters {(x, y), [members, ...]} are provided, initialize cluster radius given seeds + If clusters are provided, update centroids and radius + + :param seeds: Dictionary of {cluster_seed: radius}; Example {(x, y), radius, (x, y): radius, ...} + :param clusters: Dictionary of {cluster_seed: member_list}; Example {(x, y): [(x, y), (x, y), ...], ...} + :return: Cluster seeds dictionary with updates positions and radius values + """ + radius = sys.maxsize + new_seeds = dict() + if clusters is None: # If we only provided seeds, initialize their radius + for seed in seeds: + for other_seed in seeds.copy(): + if other_seed == seed: + continue + dist = math.dist(seed, other_seed) + # Track the smallest distance between 2 centroids + radius = dist if dist < radius else radius + + # Update all seeds to the initial cluster radius + radius /= 2 + for seed in seeds: + seeds[seed] = radius + else: + # Update centroid positions for clusters if they were provided + for centroid, members in clusters.items(): + cluster_data = set(members) | {centroid} + avgX, avgY = points_average(cluster_data) + new_seeds[tuple((avgX, avgY))] = seeds[centroid] + # If we have passed the CLI flag to lock cluster radius, return new seeds without updating radius + # + If we have not passed the -l flag, update cluster radius + seeds = new_seeds if context.lock_radius else update_clusters(new_seeds) + return seeds + + +def cluster_data(data, seeds): + """ + Runs K-Means clustering on some provided data using a dictionary of cluster seeds {centroid: radius} + + :param data: A list of data points to cluster [(x, y), (x, y), ...] + :param seeds: Dictionary of cluster centroid positions and radius {centroid: radius} + :return: Dictionary of final clusters found {centroid: member_list, ...} and updated seeds dictionary + """ + outliers = set() + clusters = {} + for seed in seeds: # Initialize empty clusters for each seed + # If centroid is a data point, it is also a member of the cluster + clusters[seed] = [seed] if seed in data else [] + + print(f'Updating cluster membership using cluster seeds, radius: ') + for seed, radius in seeds.items(): + print(f'\t(({seed[0]:.4f}, {seed[1]:.4f}), {radius:.4f})') + + # For each point, calculate the distance from all seeds + for point in data: + for seed, radius in seeds.items(): + if point is seed: # Do not check for distance(point, point) + continue + dist = math.dist(point, seed) + if dist <= radius: # If the distance from any cluster is within range, add point to the cluster + # This print statement is noisy, but it can be uncommented to see output for each new cluster member + # print(f'{point} added to cluster {seed}\n\tDistance ({dist}) is within radius ({radius})') + # Take union of point and cluster data + clusters.update({seed: list(set(clusters[seed]) | set([point]))}) + + # Initialize outliers using difference between sets + outliers = set(data) - (set(chain(*clusters.values())) | set(clusters.keys())) + print(f'Outliers present: {outliers}') + return clusters, seeds + + +def show_clusters(data, seeds, plot, show=True): + """ + Shows clusters using matplotlib + + :param data: Data points to draw on the scatter plot + :param seeds: Cluster seed dictionary {centroid: radius, ...} + :param plot: The subplot to plot data on + :param show: Toggles displaying a window for the plot. + Allows two plots to be drawn on the same subplot and then shown together using a subsequent call to plt.show() + """ + dataX, dataY = zip(*data) + plot.set_aspect(1. / plot.get_data_ratio()) + + plot.scatter(dataX, dataY, c='k') + # Draw circles for clusters + cs = [] + while len(cs) < context.clusters: # Ensure we have enough colors to display all clusters + cs.extend(['b', 'g', 'r', 'c', 'm', 'y', 'k']) + for seed, radius, c in zip(seeds.keys(), seeds.values(), cs): + plot.scatter(seed[0], seed[1], color=c) + circle = plt.Circle(seed, radius, alpha=0.25, color=c) + plot.add_patch(circle) + + plot.grid() + if show: + print(f'Close window to update centroid positions and re-cluster data...') + plt.show() + + +def print_cluster_info(initial_clusters, seeds, centroid_diff): + """ + Outputs some information on clusters after each iteration + + :param initial_clusters: The clusters as they were before reclustering + :param seeds: The new seeds dictionary {centroid: radius, ...} + :param centroid_diff: List of difference in centroid positions for each cluster + """ + for initial_point, initial_radius, updated, radius, dist in\ + zip(initial_clusters.keys(), initial_clusters.values(), seeds.keys(), seeds.values(), centroid_diff): + print(f'Initial cluster at ({initial_point[0]:.4f}, {initial_point[1]:.4f}) ' + f'moved to ({updated[0]:.4f}, {updated[1]:.4f})' + f'\n\tTotal shift: {dist:.4f}' + f'\n\tFinal radius: {radius:.4f}') + if initial_radius != radius: + print(f'\tInitial radius: {initial_radius:.4f}') + + +################################################################################ +# Main +################################################################################ + +# ============================================================================== + +def main(args: List[str]): + parser = init_parser() + global context + context = parser.parse_args(args[1:]) + if context.file: # If a file was provided, use that data instead + context.data = [literal_eval(line.rstrip()) for line in context.file] + context.data = [(float(x), float(y)) for x, y in context.data] + elif context.random: # If random flag was set, randomly generate some data + print("TODO: Randomly generate data") + context.data = random_data() + + print( + f'Finding K-means clusters for given data {context.data}\n' + f'\tUsing {context.clusters} clusters, {context.shift} max centroid shift, and {context.loops} iterations' + ) + + seeds = {} + if context.seeds: # Enforce CLUSTER_COUNT matching initial number of seeds + context.clusters = len(context.seeds) + seeds = update_clusters(dict.fromkeys(context.seeds, 0)) + else: # Select 2 random seeds once, before we enter clustering loop + seeds = select_seeds(context.data) + + # Save a copy of the initial clusters to show comparison at the end + initial_clusters = seeds.copy() + for loop in range(0, context.loops): + print(f'\nClustering iteration {loop}') + plt.title(f'Cluster iteration {loop}') + # Check distance from all points to seed + clusters, seeds = cluster_data(context.data, seeds) + if loop > 0: # The initial graph has no centroid shift to print + # If we are on any iteration beyond the first, print updated cluster information + # + The first iteration shows initial data, since it has no updated data yet + print_cluster_info(prev_centroids, seeds, centroid_diff) + if context.verbose: + print(f'Cluster members:') + for member in [f'{np.round(cent, 4)}: {members}' for cent, members in clusters.items()]: + print(member) + elif loop == 0 and not context.silent: + # If we are on the first iteration, show the initial data provided through CLI + print( + f'Showing initial data with {context.clusters} clusters ' + f'given seed points {round_points(seeds.keys())}' + ) + + # Show the plot for every iteration if it is not suppressed by the CLI --silent flag + if not context.silent: + show_clusters(context.data, seeds, plt.subplot()) + + # Update centroids for new cluster data + prev_centroids = seeds.copy() + seeds = update_clusters(seeds, clusters) + print( + f'\nUpdated clusters ({round_points(prev_centroids.keys())}) ' + f'with new centroids {round_points(seeds.keys())}' + ) + + # Find the difference in position for all centroids using their previous and current positions + centroid_diff = [round(math.dist(prev, curr), 4) for prev, curr in + list(zip(prev_centroids.keys(), seeds.keys()))] + print(f'New centroids {round_points(seeds.keys())} shifted {centroid_diff} respectively') + + # If any centroid has moved more than context.shift, the clusters are not stable + stable = not any((diff > context.shift for diff in centroid_diff)) + if stable: # If centroid shift is not > context.shift, centroids have not changed + break # Stop re-clustering process and show final result + + print("\n\nShowing final cluster result...") + centroid_diff = [round(math.dist(prev, curr), 4) for prev, curr in + list(zip(initial_clusters.keys(), seeds.keys()))] + print_cluster_info(initial_clusters, seeds, centroid_diff) + + # If the clusters reached a point where they were stable, show output to warn + if stable: + print( + f'\nStopping...\n' + f'Cluster centroids have not shifted at least {context.shift}, clusters are stable' + ) + + if not context.silent: + # Create a side-by-side subplot to compare first iteration with final clustering results + print(f'Close window to exit...') + f, arr = plt.subplots(1, 2) + arr[0].set_title(f'Cluster {0} (Initial result)') + show_clusters(context.data, initial_clusters, arr[0], False) + arr[1].set_title(f'Cluster {loop} (Final result)') + show_clusters(context.data, seeds, arr[1], False) + plt.show() + + +if __name__ == "__main__": + sys.exit(main(sys.argv)) diff --git a/python/k-means/requirements.txt b/python/k-means/requirements.txt new file mode 100644 index 0000000..3f642d5 --- /dev/null +++ b/python/k-means/requirements.txt @@ -0,0 +1,2 @@ +matplotlib==3.5.0 +numpy==1.21.4 diff --git a/python/k-means/screenshot.png b/python/k-means/screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..640a2935e711c869563673bb623510cd09b24271 GIT binary patch literal 45138 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 Iiq@h324fSmApigX literal 0 HcmV?d00001 diff --git a/python/markov-model/README.md b/python/markov-model/README.md new file mode 100644 index 0000000..9c130d6 --- /dev/null +++ b/python/markov-model/README.md @@ -0,0 +1,119 @@ +Install required dependencies for matplotlib GUI frontend and all pip other packages for this project + +```bash +sudo apt install python3-tk +python3.9 -m pip install -r requirements.txt +``` + +CLI tool to determine most probably path of Hidden Markov Model given an observation sequence of emissions. + +Given an observation sequence of emissions, find the most probable path of traversal for a Hidden Markov Model. +Since this is just an example of HMM, a graph can be automatically generated by specifying only the node count. +Edges and weights connecting the nodes will be randomly assigned. +If required, an input graph can be provided through the JSON configuration option. +See provided examples of JSON input files for more detail on options available. + +```bash +python3.9 markov-model.py -h + + +usage: markov-model.py [-h] [--nodes [GRAPH_NODE_COUNT]] [--edges [GRAPH_EDGE_COUNT]] [--show-all] [--interactive] [--silent] + [--file [FILE_PATH]] + [OBSERVATION_SEQUENCE ...] + +Calculates most probable path of HMM given an observation sequence + +positional arguments: + OBSERVATION_SEQUENCE An observation sequence to calculate the most probable path + (default: '['A', 'B', 'D', 'C']') + + +optional arguments: + -h, --help show this help message and exit + --nodes [GRAPH_NODE_COUNT], -n [GRAPH_NODE_COUNT] + The total number of node states in the HMM graph + (default: '4') + + --edges [GRAPH_EDGE_COUNT], -e [GRAPH_EDGE_COUNT] + The total number of edges in the HMM graph + (default: '8') + + --show-all When this flag is set, all path probabilities and their calculations will be output + (default: 'False') + + --interactive Allow taking input to update matrices with triple (row, col, value) + (default: 'False') + + --silent When this flag is set, final graph will not be shown + (default: 'False') + + --file [FILE_PATH], -f [FILE_PATH] + Optionally provide file for data to be read from. Each point must be on it's own line with format x,y +``` + +Running HMM with a graph using 4 nodes, 8 edges, and random transition / emission matrices +Sometimes there can be a sequence with no possible path due to a constrained transition matrix +Sometimes there can be a sequence with no possible path due to a limited emission matrix + +```bash +python3.9 markov-model.py --nodes 4 --edges 8 --show-all A B D C G --silent + + +1->3: 0.89 +1->0: 0.6 +3->3: 0.81 +3->1: 0.29 +0->2: 0.67 +0->1: 0.89 +2->0: 0.12 +2->1: 0.41 +Calculating (0, 2, 1, 0, 2): (0.98 * 0.67) * (0.74 * 0.41) * (0.22 * 0.60) * (0.22 * 0.67) * 0.36 = 0.001395 +Calculating (0, 2, 1, 3, 3): (0.98 * 0.67) * (0.74 * 0.41) * (0.22 * 0.89) * (0.11 * 0.81) * 0.52 = 0.001807 +Finding most probable path for given observation sequence: ['A', 'B', 'D', 'C', 'G'] + Total nodes in graph: 4 + Total edges in graph: 8 + Number of sequences: 5 + Interactive mode: False + Emitting nodes: {'A': [0, 2], 'B': [1, 2], 'C': [0, 2, 3], 'D': [1, 2], 'G': [0, 2, 3]} +Transition matrix: +[[0. 0.89 0.67 0. ] + [0.6 0. 0. 0.89] + [0.12 0.41 0. 0. ] + [0. 0.29 0. 0.81]] +Emission matrix: +[[ 0.98 0. 0.22 0. 0.11] + [ 0. 0.1 -0. 0.22 0. ] + [ 0.67 0.74 0.46 0.62 0.36] + [-0. 0. 0.11 0. 0.52]] +Final paths sorted by probability: +(0, 2, 1, 3, 3) has probability: 0.001807 +(0, 2, 1, 0, 2) has probability: 0.001395 +``` + +By default, a random Hidden Markov Model and visualization will be generated + +```bash +python3.9 markov-model.py + + +Finding most probable path for given observation sequence: ['A', 'B', 'D', 'C'] + Total nodes in graph: 4 + Total edges in graph: 8 + Number of sequences: 4 + Interactive mode: False + Emitting nodes: {'A': [0, 2, 3], 'B': [1, 2, 3], 'C': [0, 3], 'D': [1, 2]} +Transition matrix: +[[0. 0. 0.31 0. ] + [0.55 0.25 0. 0. ] + [0.79 0.47 0. 0.12] + [0.92 0. 0.81 0. ]] +Emission matrix: +[[0.45 0. 0.4 0. ] + [0. 0.89 0. 0.51] + [0.12 0.24 0. 0.78] + [0.08 0.42 0.96 0. ]] +(0, 2, 1, 0) has the highest probability of 0.00176553432 +``` + +![](screenshot.png) + diff --git a/python/markov-model/input.json b/python/markov-model/input.json new file mode 100644 index 0000000..325a15b --- /dev/null +++ b/python/markov-model/input.json @@ -0,0 +1,16 @@ +{ + "sequence": ["A", "B", "D", "C"], + "nodes": 4, + "edges": 10, + "interactive": true, + "transition_matrix": [ + [0.2, 0.7, 0.0], + [0.0, 0.0, 0.7], + [0.2, 0.3, 0.0] + ], + "emission_matrix": [ + [0.7, 0.3, 0.0, 0.0], + [0.2, 0.2, 0.4, 0.2], + [0.0, 0.0, 0.2, 0.8] + ] +} diff --git a/python/markov-model/markov-model.py b/python/markov-model/markov-model.py new file mode 100644 index 0000000..8ef54f6 --- /dev/null +++ b/python/markov-model/markov-model.py @@ -0,0 +1,481 @@ +################################################################################ +# Author: Shaun Reed # +# About: HMM implementation to calculate most probable path for sequence # +# Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 # +################################################################################ + +from matplotlib import pyplot as plt +from typing import List +import argparse +import itertools +import json +import networkx as nx +import numpy as np +import random +import sys + + +################################################################################ +# CLI Argument Parser +################################################################################ + +# ============================================================================== + +def init_parser(): + parser = argparse.ArgumentParser( + description='Calculates most probable path of HMM given an observation sequence', + formatter_class=argparse.RawTextHelpFormatter + ) + + parser.add_argument( + 'sequence', metavar='OBSERVATION_SEQUENCE', nargs='*', + help= + '''An observation sequence to calculate the most probable path + (default: '%(default)s') + ''', + default=['A', 'B', 'D', 'C'] + ) + + parser.add_argument( + '--nodes', '-n', metavar='GRAPH_NODE_COUNT',type=int, nargs='?', + help= + '''The total number of node states in the HMM graph + (default: '%(default)s') + ''', + default=4 + ) + + parser.add_argument( + '--edges', '-e', metavar='GRAPH_EDGE_COUNT',type=int, nargs='?', + help= + '''The total number of edges in the HMM graph + (default: '%(default)s') + ''', + default=8 + ) + + parser.add_argument( + '--show-all', action='store_true', + help= + '''When this flag is set, all path probabilities and their calculations will be output + (default: '%(default)s') + ''', + default=False + ) + + parser.add_argument( + '--interactive', action='store_true', + help= + '''Allow taking input to update matrices with triple (row, col, value) + (default: '%(default)s') + ''', + default=False + ) + + parser.add_argument( + '--silent', action='store_true', + help= + '''When this flag is set, final graph will not be shown + (default: '%(default)s') + ''', + default=False + ) + + parser.add_argument( + '--file', '-f', metavar='FILE_PATH', nargs='?', type=open, + help= + '''Optionally provide file for data to be read from. Each point must be on it\'s own line with format x,y + ''', + ) + return parser + + +################################################################################ +# Helper Functions +################################################################################ + +# ============================================================================== + +def parse_file(): + """ + Validates keys in JSON file and updates CLI input context + + Initializes a MultiDiGraph object using input data model_graph + Initializes a matrix of emission probabilities emission_matrix + :return: model_graph, emission_matrix + """ + # Load the JSON input file, validate keys + file_data = json.load(context['file']) + for key in file_data: + if key == "transition_matrix" or key == "emission_matrix": + continue + assert key in context + # Update the CLI context with JSON input + context.update(file_data) + + model_graph = nx.MultiDiGraph(build_graph(np.array(file_data['transition_matrix']))) + emission_matrix = np.array(file_data['emission_matrix']) + return model_graph, emission_matrix + + +def random_emission(): + """ + Initialize an emission matrix size SxE + Where S is number of states and E is number of emissions + + :return: Initialized emission_matrix + """ + emission_matrix = np.zeros((context["nodes"], len(set(context["sequence"])))) + shape = emission_matrix.shape + for row in range(0, shape[0]): + for col in range(0, shape[1]): + # Let random number swing below 0 to increase chance of nodes not emitting + emit_prob = round(random.uniform(-0.25, 1.0), 2) + emit_prob = 0.0 if emit_prob < 0.0 else emit_prob + emission_matrix[row][col] = emit_prob + return emission_matrix + + +def random_graph(nodes, edges=2): + """ + Create a random graph represented as a list [(from_node, to_node, {'weight': edge_weight}), ...] + Networkx can use this list in constructors for graph objects + + :param nodes: The number of nodes in the graph + :param edges: The number of edges connecting nodes in the graph + :return: A list [(from_node, to_node, {'weight': edge_weight}), ...] + """ + # By default, make twice as many edges as there are nodes + edges *= nodes if edges == 2 else 1 + r_graph = [] + for x in range(0, edges): + while True: + new_edge = ( + random.randint(0, nodes - 1), # Randomly select a from_node index + random.randint(0, nodes - 1), # Randomly select a to_node index + { + # Randomly set an edge weight between from_node and to_node + 'weight': + round(random.uniform(0.0, 1.0), 2) + } + ) + if not any((new_edge[0], new_edge[1]) == (a, b) for a, b, w in r_graph): + break + r_graph.append(new_edge) + return r_graph + + +def build_graph(t_matrix): + """ + Converts a transition matrix to a list of edges and weights + This list can then be passed to NetworkX graph constructors + + :param t_matrix: The transition matrix to build the graph from + :return: A list [(from_node, to_node, {'weight': edge_weight}), ...] + """ + n_graph = [] + shape = t_matrix.shape + for row in range(0, shape[0]): + for col in range(0, shape[1]): + if t_matrix[row][col] <= 0.0: + continue + new_edge = (row, col, {'weight': t_matrix[row][col]}) + n_graph.append(new_edge) + return n_graph + + +def transition_matrix(graph: nx.MultiDiGraph): + """ + Build a transition matrix from a Networkx MultiDiGraph object + + :param graph: An initialized MultiDiGraph graph object + :return: An initialized transition matrix with shape (NODE_COUNT, NODE_COUNT) + """ + # Initialize a matrix of zeros with size ExE where E is total number of states (nodes) + t_matrix = np.zeros((context["nodes"], context["nodes"])) + # Build matrices from iterating over the graph + for a, b, weight in graph.edges(data='weight'): + t_matrix[a][b] = weight + if context["show_all"]: + print(f'{a}->{b}: {weight}') + return t_matrix + + +def make_emission_dict(emission_matrix): + """ + Create a dictionary that maps to index keys for each emission. emission_keys + Create a dictionary that maps to a list of emitting nodes for each emission. emission_dict + + :param emission_matrix: An emission_matrix size NxE + Where N is the number of nodes (states) and E is the number of emissions + :return: emission_dict, emission_keys + """ + emission_dict = {} + for emission in sorted(set(context["sequence"])): + emission_dict[emission] = [] + emission_keys = dict.fromkeys(emission_dict.keys()) + + # Initialize emission_dict to store a list of all nodes that emit the key value + shape = emission_matrix.shape + i = 0 + for key in emission_dict.keys(): + for row in range(0, shape[0]): + if emission_matrix[row][i] > 0: + emission_dict[key].append(row) + emission_keys[key] = i + i += 1 + return emission_dict, emission_keys + + +def int_input(prompt): + """ + Forces integer input. Retries and warns if bogus values are entered. + + :param prompt: The initial prompt message to show for input + :return: The integer input by the user at runtime + """ + while True: + try: + value = int(input(prompt)) + break + except ValueError: + print("Please enter an integer value") + return value + + +def triple_input(matrix): + """ + Takes 3 integer input, validates it makes sense for the selected matrix + If row or column selected is outside the limits of the matrix, warn and retry input until valid + + :param matrix: The matrix to use for input validation + :return: The validated input + """ + row = int_input("Row: ") + col = int_input("Col: ") + value = int_input("Value: ") + row, col = check_input(row, col, matrix) + return row, col, value + + +def check_input(row, col, matrix): + """ + Checks that row, col input values are within the bounds of matrix + If valid values are passed initially, no additional prompts are made. + Retries input until valid values are input. + + :param row: The row index input by the user + :param col: The col index input by the user + :param matrix: The matrix to use for input validation + :return: The validated input for row and column index + """ + while row > matrix.shape[0] - 1: + print(f'{row} is too large for transition matrix of shape {matrix.shape}') + row = int_input("Row : ") + while col > matrix.shape[1] - 1: + print(f'{col} is too large for transition matrix of shape {matrix.shape}') + col = int_input("Col: ") + return row, col + + +################################################################################ +# Hidden Markov Model +################################################################################ + +# ============================================================================== + +def find_paths(emission_dict, t_matrix): + """ + Find all possible paths for an emission sequence + + :param emission_dict: A dictionary of emitters for emissions {emission_1: [0, 1], emission_2: [1, 3], ...} + :param t_matrix: A transition matrix size NxN where N is the total number of nodes in the graph + :return: A list of validated paths for the emission given through the CLI + """ + paths = [] + for emission in context["sequence"]: + paths.append(emission_dict[emission]) + # Take the cartesian product of the emitting nodes to get a list of all possible paths + # + Return only the paths which have > 0 probability given the transition matrix + return validate_paths(list(itertools.product(*paths)), t_matrix) + + +def validate_paths(path_list: list, t_matrix): + """ + Checks all paths in path_list [[0, 1, 2, 3], [0, 1, 1, 2], ...] + If the transition matrix t_matrix indicates any node in a path can't reach the next node in path + The path can't happen given our graph. Remove it from the list of paths. + + :param path_list: A list of paths to validate + :param t_matrix: A transition matrix size NxN where N is the total number of nodes in the graph + :return: A list of validated paths [[0, 1, 2, 3], [0, 1, 1, 2], ...] + """ + valid_paths = [] + for path in path_list: + valid = True + for step in range(0, len(path) - 1): + current_node = path[step] + # If the transition matrix indicates that the chance to move to next step in path is 0 + if t_matrix[current_node][path[step+1]] <= 0.0: + # The path cannot possibly happen. Don't consider it. + valid = False + break + if valid: + # We reached the end of our path without hitting a dead-end. The path is valid. + valid_paths.append(path) + return valid_paths + + +def find_probability(emission_matrix, t_matrix, emission_keys, valid_paths): + """ + Find probability of paths occurring given our current HMM + Store result in a dictionary {probability: (0, 1, 2, 3), probability_2: (0, 0, 1, 2)} + + :param emission_matrix: A matrix of emission probabilities NxE where N is the emitting node and E is the emission + :param t_matrix: A transition matrix NxN where N is the total number of nodes in the graph + :param emission_keys: A dictionary mapping to index values for emissions as E in the emission_matrix + :param valid_paths: A list of valid paths to calculate probability given an emission sequence + :return: A dictionary of {prob: path}; For example {probability: (0, 1, 2, 3), probability_2: (0, 0, 1, 2)} + """ + path_prob = {} + seq = list(context["sequence"]) + for path in valid_paths: + calculations = f'Calculating {path}: ' + prob = 1.0 + for step in range(0, len(path) - 1): + current_node = path[step] + next_node = path[step + 1] + emission_index = emission_keys[seq[step]] + emission_prob = emission_matrix[current_node][emission_index] + transition_prob = t_matrix[current_node][next_node] + calculations += f'({emission_prob:.2f} * {transition_prob:.2f}) * ' + prob *= emission_prob * transition_prob + emission_index = emission_keys[seq[step + 1]] + final_emission_prob = emission_matrix[next_node][emission_index] + prob *= final_emission_prob + calculations += f'{final_emission_prob:.2f} = {prob:.6f}' + if prob > 0.0: # Don't keep paths which aren't possible due to emission sequence + path_prob[prob] = path + if context["show_all"]: + print(calculations) + return path_prob + + +def run_problem(transition_matrix, emission_matrix): + """ + Runs the HMM calculations given a transition_matrix and emission_matrix + + :param transition_matrix: A matrix size NxN where N is the total number of nodes and values represent probability + :param emission_matrix: A matrix size NxE where N is total nodes and E is total number of emissions + :return: A dictionary of {probability: path} sorted by probability key from in descending order + """ + # Dictionary of {emission: [emitter, ...]} + emission_dict, emission_keys = make_emission_dict(emission_matrix) + valid_paths = find_paths(emission_dict, transition_matrix) + path_prob = find_probability(emission_matrix, transition_matrix, emission_keys, valid_paths) + result = {key: path_prob[key] for key in dict.fromkeys(sorted(path_prob.keys(), reverse=True))} + print(f'Finding most probable path for given observation sequence: {context["sequence"]}\n' + f'\tTotal nodes in graph: {context["nodes"]}\n' + f'\tTotal edges in graph: {context["edges"]}\n' + f'\tNumber of sequences: {len(set(context["sequence"]))}\n' + f'\tInteractive mode: {context["interactive"]}\n' + f'\tEmitting nodes: {emission_dict}\n' + f'Transition matrix: \n{transition_matrix}\n' + f'Emission matrix: \n{emission_matrix}' + ) + return result + + +def show_result(result): + """ + Prints results from running the HMM calculations + + :param result: The result dictionary returned by run_problem() + """ + if len(result) == 0: + print(f'No valid paths found for sequence {context["sequence"]}') + elif context["show_all"]: + print(f'Final paths sorted by probability:') + [print(f'{path} has probability:\t {prob:.6f}') for prob, path in result.items()] + else: + print(f'{list(result.values())[0]} has the highest probability of {list(result.keys())[0]}') + + +def draw_graph(graph): + """ + Draws the model_graph for the current HMM using NetworkX + + :param graph: An initialized MultiDiGraph object with edge weights representing transition probability + """ + # Get a dictionary of {node: position} for drawing the graph + dict_pos = nx.spring_layout(graph) + nx.draw( + graph, dict_pos, + with_labels=True, + node_size=[x * 200 for x in dict(graph.degree).values()], + alpha=1, + arrowstyle="->", + arrowsize=25, + ) + # TODO: Fix parallel path weight display + nx.draw_networkx_edge_labels(graph, dict_pos) + plt.show() + + +################################################################################ +# Main +################################################################################ + +# ============================================================================== + +def main(args: List[str]): + parser = init_parser() + global context + context = vars(parser.parse_args(args[1:])) + if context["file"]: # If a file was provided, use that data instead + model_graph, emission_matrix = parse_file() + else: + # If no file was provided, build a random graph with the requested number of nodes and edges + model_graph = nx.MultiDiGraph(random_graph(context["nodes"], context["edges"])) + # Create a random emission matrix + emission_matrix = random_emission() + + t_matrix = transition_matrix(model_graph) + result = run_problem(t_matrix, emission_matrix) + show_result(result) + + # Draw the graph for a visual example to go with output + if not context["silent"]: + draw_graph(model_graph) + + # Unless we are in interactive mode, we're finished. Return. + if not context["interactive"]: + return + + # Prompt to update the transition or emission matrix, then rerun problem with new values + print("Choose matrix to update:\n\t1. Transition\n\t2. Emission\n\t3. Both", end='') + choice = input() + if choice == '1': + row, col, value = triple_input(t_matrix) + t_matrix[row][col] = value + elif choice == '2': + row, col, value = triple_input(emission_matrix) + emission_matrix[row][col] = value + elif choice == '3': + print('\nInput for updating transition matrix') + row, col, value = triple_input(t_matrix) + t_matrix[row][col] = value + print('\nInput for updating emission matrix') + row, col, value = triple_input(emission_matrix) + emission_matrix[row][col] = value + result = run_problem(t_matrix, emission_matrix) + show_result(result) + + # Draw the graph for a visual example to go with output + if not context["silent"]: + model_graph = nx.MultiDiGraph(build_graph(np.array(t_matrix))) + draw_graph(model_graph) + + +if __name__ == "__main__": + sys.exit(main(sys.argv)) diff --git a/python/markov-model/requirements.txt b/python/markov-model/requirements.txt new file mode 100644 index 0000000..8362d6b --- /dev/null +++ b/python/markov-model/requirements.txt @@ -0,0 +1,3 @@ +matplotlib==3.5.0 +networkx==2.6.3 +numpy==1.21.4 diff --git a/python/markov-model/screenshot.png b/python/markov-model/screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..8d5fac838bfd3cf298025c82956eeb247975074e GIT binary patch literal 53806 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 literal 0 HcmV?d00001 diff --git a/python/neural-network/IRIS.csv b/python/neural-network/IRIS.csv new file mode 100755 index 0000000..21ae196 --- /dev/null +++ b/python/neural-network/IRIS.csv @@ -0,0 +1,151 @@ +sepal_length,sepal_width,petal_length,petal_width,species +5.1,3.5,1.4,0.2,Iris-setosa +4.9,3,1.4,0.2,Iris-setosa +4.7,3.2,1.3,0.2,Iris-setosa +4.6,3.1,1.5,0.2,Iris-setosa +5,3.6,1.4,0.2,Iris-setosa +5.4,3.9,1.7,0.4,Iris-setosa +4.6,3.4,1.4,0.3,Iris-setosa +5,3.4,1.5,0.2,Iris-setosa +4.4,2.9,1.4,0.2,Iris-setosa +4.9,3.1,1.5,0.1,Iris-setosa +5.4,3.7,1.5,0.2,Iris-setosa +4.8,3.4,1.6,0.2,Iris-setosa +4.8,3,1.4,0.1,Iris-setosa +4.3,3,1.1,0.1,Iris-setosa +5.8,4,1.2,0.2,Iris-setosa +5.7,4.4,1.5,0.4,Iris-setosa +5.4,3.9,1.3,0.4,Iris-setosa +5.1,3.5,1.4,0.3,Iris-setosa +5.7,3.8,1.7,0.3,Iris-setosa +5.1,3.8,1.5,0.3,Iris-setosa +5.4,3.4,1.7,0.2,Iris-setosa +5.1,3.7,1.5,0.4,Iris-setosa +4.6,3.6,1,0.2,Iris-setosa +5.1,3.3,1.7,0.5,Iris-setosa +4.8,3.4,1.9,0.2,Iris-setosa +5,3,1.6,0.2,Iris-setosa +5,3.4,1.6,0.4,Iris-setosa +5.2,3.5,1.5,0.2,Iris-setosa +5.2,3.4,1.4,0.2,Iris-setosa +4.7,3.2,1.6,0.2,Iris-setosa +4.8,3.1,1.6,0.2,Iris-setosa +5.4,3.4,1.5,0.4,Iris-setosa +5.2,4.1,1.5,0.1,Iris-setosa +5.5,4.2,1.4,0.2,Iris-setosa +4.9,3.1,1.5,0.1,Iris-setosa +5,3.2,1.2,0.2,Iris-setosa +5.5,3.5,1.3,0.2,Iris-setosa +4.9,3.1,1.5,0.1,Iris-setosa +4.4,3,1.3,0.2,Iris-setosa +5.1,3.4,1.5,0.2,Iris-setosa +5,3.5,1.3,0.3,Iris-setosa +4.5,2.3,1.3,0.3,Iris-setosa +4.4,3.2,1.3,0.2,Iris-setosa +5,3.5,1.6,0.6,Iris-setosa +5.1,3.8,1.9,0.4,Iris-setosa +4.8,3,1.4,0.3,Iris-setosa +5.1,3.8,1.6,0.2,Iris-setosa +4.6,3.2,1.4,0.2,Iris-setosa +5.3,3.7,1.5,0.2,Iris-setosa +5,3.3,1.4,0.2,Iris-setosa +7,3.2,4.7,1.4,Iris-versicolor +6.4,3.2,4.5,1.5,Iris-versicolor +6.9,3.1,4.9,1.5,Iris-versicolor +5.5,2.3,4,1.3,Iris-versicolor +6.5,2.8,4.6,1.5,Iris-versicolor +5.7,2.8,4.5,1.3,Iris-versicolor +6.3,3.3,4.7,1.6,Iris-versicolor +4.9,2.4,3.3,1,Iris-versicolor +6.6,2.9,4.6,1.3,Iris-versicolor +5.2,2.7,3.9,1.4,Iris-versicolor +5,2,3.5,1,Iris-versicolor +5.9,3,4.2,1.5,Iris-versicolor +6,2.2,4,1,Iris-versicolor +6.1,2.9,4.7,1.4,Iris-versicolor +5.6,2.9,3.6,1.3,Iris-versicolor +6.7,3.1,4.4,1.4,Iris-versicolor +5.6,3,4.5,1.5,Iris-versicolor +5.8,2.7,4.1,1,Iris-versicolor +6.2,2.2,4.5,1.5,Iris-versicolor +5.6,2.5,3.9,1.1,Iris-versicolor +5.9,3.2,4.8,1.8,Iris-versicolor +6.1,2.8,4,1.3,Iris-versicolor +6.3,2.5,4.9,1.5,Iris-versicolor +6.1,2.8,4.7,1.2,Iris-versicolor +6.4,2.9,4.3,1.3,Iris-versicolor +6.6,3,4.4,1.4,Iris-versicolor +6.8,2.8,4.8,1.4,Iris-versicolor +6.7,3,5,1.7,Iris-versicolor +6,2.9,4.5,1.5,Iris-versicolor +5.7,2.6,3.5,1,Iris-versicolor +5.5,2.4,3.8,1.1,Iris-versicolor +5.5,2.4,3.7,1,Iris-versicolor +5.8,2.7,3.9,1.2,Iris-versicolor +6,2.7,5.1,1.6,Iris-versicolor +5.4,3,4.5,1.5,Iris-versicolor +6,3.4,4.5,1.6,Iris-versicolor +6.7,3.1,4.7,1.5,Iris-versicolor +6.3,2.3,4.4,1.3,Iris-versicolor +5.6,3,4.1,1.3,Iris-versicolor +5.5,2.5,4,1.3,Iris-versicolor +5.5,2.6,4.4,1.2,Iris-versicolor +6.1,3,4.6,1.4,Iris-versicolor +5.8,2.6,4,1.2,Iris-versicolor +5,2.3,3.3,1,Iris-versicolor +5.6,2.7,4.2,1.3,Iris-versicolor +5.7,3,4.2,1.2,Iris-versicolor +5.7,2.9,4.2,1.3,Iris-versicolor +6.2,2.9,4.3,1.3,Iris-versicolor +5.1,2.5,3,1.1,Iris-versicolor +5.7,2.8,4.1,1.3,Iris-versicolor +6.3,3.3,6,2.5,Iris-virginica +5.8,2.7,5.1,1.9,Iris-virginica +7.1,3,5.9,2.1,Iris-virginica +6.3,2.9,5.6,1.8,Iris-virginica +6.5,3,5.8,2.2,Iris-virginica +7.6,3,6.6,2.1,Iris-virginica +4.9,2.5,4.5,1.7,Iris-virginica +7.3,2.9,6.3,1.8,Iris-virginica +6.7,2.5,5.8,1.8,Iris-virginica +7.2,3.6,6.1,2.5,Iris-virginica +6.5,3.2,5.1,2,Iris-virginica +6.4,2.7,5.3,1.9,Iris-virginica +6.8,3,5.5,2.1,Iris-virginica +5.7,2.5,5,2,Iris-virginica +5.8,2.8,5.1,2.4,Iris-virginica +6.4,3.2,5.3,2.3,Iris-virginica +6.5,3,5.5,1.8,Iris-virginica +7.7,3.8,6.7,2.2,Iris-virginica +7.7,2.6,6.9,2.3,Iris-virginica +6,2.2,5,1.5,Iris-virginica +6.9,3.2,5.7,2.3,Iris-virginica +5.6,2.8,4.9,2,Iris-virginica +7.7,2.8,6.7,2,Iris-virginica +6.3,2.7,4.9,1.8,Iris-virginica +6.7,3.3,5.7,2.1,Iris-virginica +7.2,3.2,6,1.8,Iris-virginica +6.2,2.8,4.8,1.8,Iris-virginica +6.1,3,4.9,1.8,Iris-virginica +6.4,2.8,5.6,2.1,Iris-virginica +7.2,3,5.8,1.6,Iris-virginica +7.4,2.8,6.1,1.9,Iris-virginica +7.9,3.8,6.4,2,Iris-virginica +6.4,2.8,5.6,2.2,Iris-virginica +6.3,2.8,5.1,1.5,Iris-virginica +6.1,2.6,5.6,1.4,Iris-virginica +7.7,3,6.1,2.3,Iris-virginica +6.3,3.4,5.6,2.4,Iris-virginica +6.4,3.1,5.5,1.8,Iris-virginica +6,3,4.8,1.8,Iris-virginica +6.9,3.1,5.4,2.1,Iris-virginica +6.7,3.1,5.6,2.4,Iris-virginica +6.9,3.1,5.1,2.3,Iris-virginica +5.8,2.7,5.1,1.9,Iris-virginica +6.8,3.2,5.9,2.3,Iris-virginica +6.7,3.3,5.7,2.5,Iris-virginica +6.7,3,5.2,2.3,Iris-virginica +6.3,2.5,5,1.9,Iris-virginica +6.5,3,5.2,2,Iris-virginica +6.2,3.4,5.4,2.3,Iris-virginica +5.9,3,5.1,1.8,Iris-virginica diff --git a/python/neural-network/README.md b/python/neural-network/README.md new file mode 100644 index 0000000..b49b761 --- /dev/null +++ b/python/neural-network/README.md @@ -0,0 +1,200 @@ +Install required dependencies for matplotlib GUI frontend and all pip other packages for this project + +```bash +sudo apt install python3-tk +python3.9 -m pip install -r requirements.txt +``` + +Neural network implementation using Python CLI to dynamically generate a resizable network + and then run a given number of learning cycles on the provided data set. +As an example, the IRIS dataset is used to classify flower types using petal measurements. +Input layer perceptron count can be adjusted with `INPUTS` positional parameter +Hidden layer perceptron count can be adjusted with `PERCEPTRONS` positional parameter +Output layer perceptron count can be adjusted with `OUTPUTS` positional parameter +Hidden layers can be added or removed using`--hidden-layers` option setting +Node bias can be initialized randomly or with provided data. +Perceptron edge weight bias can be initialized randomly or with provided data. +Threshold for perceptron fire can be initialized randomly or with provided data. + +Setup instructions and output of `neural-network.py -h`- +```bash +python3.9 neural-network.py -h + + +usage: neural-network.py [-h] [--hidden-layers [HIDDEN_LAYERS]] [--cycles [CYCLES]] [--learn-rate [LEARNING_RATE]] + [--bias [INITIAL_BIAS]] [--weight [INITIAL_EDGE_WEIGHTS]] [--error-threshold [ERROR_THRESHOLD]] + [--fire-threshold [FIRE_THRESHOLD]] [--spacing [LAYER_SPACING]] [--horizontal] [--silent] [--verbose] + [--file [file_path]] + [INPUTS] [PERCEPTRONS] [OUTPUTS] + +Neural network implementation + +positional arguments: + INPUTS Number of inputs for the neural network + (default: '3') + + PERCEPTRONS Number of perceptrons in each hidden layer + (default: '8') + + OUTPUTS Number of outputs for the neural network + (default: '3') + + +optional arguments: + -h, --help show this help message and exit + --hidden-layers [HIDDEN_LAYERS], -l [HIDDEN_LAYERS] + Number of hidden layers + (default: '1') + + --cycles [CYCLES], -c [CYCLES] + Number of cycles to run through the network + (default: '3') + + --learn-rate [LEARNING_RATE] + Learning rate to use for the network. + Must be within range of 0.0 < rate <= 1.0 + (default: '0.25') + + --bias [INITIAL_BIAS], -b [INITIAL_BIAS] + The initial bias to use for perceptrons within the network. + Must be within range of -1.0 <= bias <= 1.0 + If value is unset, bias will be initialized randomly + + --weight [INITIAL_EDGE_WEIGHTS], -w [INITIAL_EDGE_WEIGHTS] + The initial edge weight to use for node connections in the network + If value is unset, edge weights will be initialized randomly + + --error-threshold [ERROR_THRESHOLD], --error [ERROR_THRESHOLD] + The acceptable error threshold to use for training the network. + (default: '0.5') + + --fire-threshold [FIRE_THRESHOLD], --fire [FIRE_THRESHOLD] + The fire threshold for perceptrons in the network. + If a perceptron's cumulative inputs reach this value, the perceptron fires + (default: '0.25') + + --spacing [LAYER_SPACING] + Distance between origin of network layers within visualization + (default: '2.0') + + --horizontal, --flip The network visualization will flow left-to-right + (default: 'False') + + --silent Do not show the network visualization, only print output to console + (default: 'False') + + --verbose, -v When this flag is set, error rate and change in weight will be output for each calculation + (default: 'False') + + --file [file_path], -f [file_path] + Optionally provide a json file to configure any option available through the cli + json keys match --long version of each option, where --long-split option key is "long_split" in json +``` + +Input and output layers are sized by the length of a single input sequence and the number of possible label classifications. +If the length of an input sequence does not match the number of input nodes requested, a warning will show. +If the length of possible label classifications does not match the number of output nodes requested, a warning will show. +In both cases, the program corrects the node count to match the input data / labels, and not the requested node count. + +The total number of output labels provided must match the total number of the number of input sequences. + +Running NN program uses IRIS data set by default. +Warnings will be shown if input and output node count is changed without providing new input. +```bash +python3.9 neural-network.py --file input.json --silent + + +Warning: Input sequences each contain 3 entries but 5 input nodes were requested. + Using 3 input nodes instead of 5 +Warning: Output labels contain 3 possible classifications but 8 output were nodes requested. + Using 3 output nodes instead of 8 +Creating a single layer neural network: + Total input nodes: 3 + Number of perceptrons in each hidden layer: 8 + Total output nodes: 3 + Number of hidden layers: 3 + Fire threshold: 0.25 + Error threshold: 0.5 + Learn rate: 0.25 + Initial bias: Random + Initial edge weights: Random +Network visualization settings: + Graph visualization is enabled: False + Graph visualization is horizontal: True + Graph visualization is vertical: False + Graph visualization layer spacing: 2.0 + Test data input count: 150 +inputs layer: [0, 1, 2] +hidden layer: [[3, 4, 5, 6, 7, 8, 9, 10], [11, 12, 13, 14, 15, 16, 17, 18], [19, 20, 21, 22, 23, 24, 25, 26]] +outputs layer: [27, 28, 29] +[Cycle 1] Accuracy: 92.6667% [139 / 11] +[Cycle 2] Accuracy: 95.3333% [286 / 14] +[Cycle 3] Accuracy: 96.2222% [433 / 17] +[Cycle 4] Accuracy: 96.6667% [580 / 20] +[Cycle 5] Accuracy: 96.9333% [727 / 23] +[Cycle 6] Accuracy: 97.1111% [874 / 26] +[Cycle 7] Accuracy: 97.2381% [1021 / 29] +[Cycle 8] Accuracy: 97.3333% [1168 / 32] +[Cycle 9] Accuracy: 97.4074% [1315 / 35] +[Cycle 10] Accuracy: 97.4667% [1462 / 38] + +Correct: 1462 Wrong: 38 Total: 1500 +Cycle 1 accuracy: 92.6667% Cycle 10 accuracy: 97.4667% +4.8% change over 10 cycles 0.48% average change per cycle +``` + + +Running NN program with garbage data in `input-test.json` to test resizing of input / output layers. +A single input sequence is `[0, 1, 0, 1, 1, 1]` which is length of 6, so 6 input nodes are created. +Within the output labels, there are 8 unique labels in the set, so 8 output nodes are created. +The length a single label must match the number of output nodes. +For 8 output nodes, the labels `[1, 0, 0, 0, 0, 0, 0, 0]` and `[0, 1, 0, 0, 0, 0, 0, 0]` are valid. + +```bash +python3.9 neural-network.py --file ./input-test.json --silent + + +Warning: Output labels contain 8 possible classifications but 10 output were nodes requested. + Using 8 output nodes instead of 10 +Creating a single layer neural network: + Total input nodes: 6 + Number of perceptrons in each hidden layer: 8 + Total output nodes: 8 + Number of hidden layers: 3 + Fire threshold: 0.25 + Error threshold: 0.5 + Learn rate: 0.25 + Initial bias: Random + Initial edge weights: Random +Network visualization settings: + Graph visualization is enabled: False + Graph visualization is horizontal: True + Graph visualization is vertical: False + Graph visualization layer spacing: 2.0 + Test data input count: 14 +inputs layer: [0, 1, 2, 3, 4, 5] +hidden layer: [[6, 7, 8, 9, 10, 11, 12, 13], [14, 15, 16, 17, 18, 19, 20, 21], [22, 23, 24, 25, 26, 27, 28, 29]] +outputs layer: [30, 31, 32, 33, 34, 35, 36, 37] +[Cycle 1] Accuracy: 35.7143% [5 / 9] +[Cycle 2] Accuracy: 39.2857% [11 / 17] +[Cycle 3] Accuracy: 40.4762% [17 / 25] +[Cycle 4] Accuracy: 41.0714% [23 / 33] +[Cycle 5] Accuracy: 41.4286% [29 / 41] +[Cycle 6] Accuracy: 41.6667% [35 / 49] +[Cycle 7] Accuracy: 41.8367% [41 / 57] +[Cycle 8] Accuracy: 41.9643% [47 / 65] +[Cycle 9] Accuracy: 42.0635% [53 / 73] +[Cycle 10] Accuracy: 42.1429% [59 / 81] + +Correct: 59 Wrong: 81 Total: 140 +Cycle 1 accuracy: 35.7143% Cycle 10 accuracy: 42.1429% +6.4286% change over 10 cycles 0.6429% average change per cycle +``` + +By default, the following network and visualization will be generated + +```bash +python3.9 neural-network.py +# Output removed for GUI example +``` +![](screenshot.png) diff --git a/python/neural-network/input-test.json b/python/neural-network/input-test.json new file mode 100644 index 0000000..0a7fa4e --- /dev/null +++ b/python/neural-network/input-test.json @@ -0,0 +1,44 @@ +{ + "inputs": 6, + "perceptrons": 8, + "outputs": 10, + "hidden_layers": 3, + "learn_rate": 0.25, + "fire_threshold": 0.25, + "error_threshold": 0.5, + "cycles": 10, + "spacing": 2.0, + "horizontal": true, + "input_sequence": [ + [0, 1, 0, 1, 1, 1], + [0, 0, 0, 0, 1, 1], + [0, 1, 0, 1, 1, 1], + [0, 1, 0, 1, 1, 1], + [0, 1, 0, 1, 1, 1], + [1, 1, 1, 1, 1, 1], + [1, 1, 1, 1, 1, 1], + [1, 1, 1, 1, 1, 1], + [1, 1, 1, 1, 1, 1], + [0, 1, 0, 1, 1, 1], + [0, 1, 0, 1, 1, 1], + [0, 1, 0, 1, 1, 1], + [0, 1, 0, 1, 1, 1], + [0, 1, 0, 1, 1, 1] + ], + "label_sequence": [ + [1, 0, 0, 0, 0, 0, 0, 0], + [0, 1, 0, 0, 0, 0, 0, 0], + [0, 0, 1, 0, 0, 0, 0, 0], + [0, 0, 0, 1, 0, 0, 0, 0], + [0, 0, 0, 0, 1, 0, 0, 0], + [0, 0, 0, 0, 0, 1, 0, 0], + [0, 0, 0, 0, 0, 0, 1, 0], + [0, 0, 0, 0, 0, 0, 0, 1], + [0, 0, 0, 0, 0, 0, 0, 1], + [0, 0, 0, 0, 0, 0, 0, 1], + [0, 0, 0, 0, 0, 0, 0, 1], + [0, 0, 0, 0, 0, 0, 0, 1], + [0, 0, 0, 0, 0, 0, 0, 1], + [0, 0, 0, 0, 0, 0, 0, 1] + ] +} diff --git a/python/neural-network/input.json b/python/neural-network/input.json new file mode 100644 index 0000000..5ba2c6b --- /dev/null +++ b/python/neural-network/input.json @@ -0,0 +1,12 @@ +{ + "inputs": 5, + "perceptrons": 8, + "outputs": 8, + "hidden_layers": 3, + "learn_rate": 0.25, + "fire_threshold": 0.25, + "error_threshold": 0.5, + "cycles": 10, + "spacing": 2.0, + "horizontal": true +} diff --git a/python/neural-network/neural-network.py b/python/neural-network/neural-network.py new file mode 100644 index 0000000..53dfe09 --- /dev/null +++ b/python/neural-network/neural-network.py @@ -0,0 +1,649 @@ +################################################################################ +# Author: Shaun Reed # +# About: ANN implementation with adjustable layers and layer lengths # +# Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 # +################################################################################ + +from matplotlib import pyplot as plt +from sklearn.datasets import load_iris +from typing import List +import argparse +import json +import math +import numpy as np +import pandas as pd # Unused unless optional code is manually uncommented +import random +import sys +import viznet as vn + + +################################################################################ +# CLI Argument Parser +################################################################################ + +# ============================================================================== + +def init_parser(): + parser = argparse.ArgumentParser( + description='Neural network implementation', + formatter_class=argparse.RawTextHelpFormatter + ) + + parser.add_argument( + 'inputs', metavar='INPUTS', type=int, nargs='?', + help= + '''Number of inputs for the neural network + (default: '%(default)s') + ''', + default=3 + ) + + parser.add_argument( + 'perceptrons', metavar='PERCEPTRONS', type=int, nargs='?', + help= + '''Number of perceptrons in each hidden layer + (default: '%(default)s') + ''', + default=8 + ) + + parser.add_argument( + 'outputs', metavar='OUTPUTS', type=int, nargs='?', + help= + '''Number of outputs for the neural network + (default: '%(default)s') + ''', + default=3 + ) + + parser.add_argument( + '--hidden-layers', '-l', metavar='HIDDEN_LAYERS', type=int, nargs='?', + help= + '''Number of hidden layers + (default: '%(default)s') + ''', + default=1 + ) + + parser.add_argument( + '--cycles', '-c', metavar='CYCLES', type=int, nargs='?', + help= + '''Number of cycles to run through the network + (default: '%(default)s') + ''', + default=3 + ) + + parser.add_argument( + '--learn-rate', metavar='LEARNING_RATE', type=float, nargs='?', + help= + '''Learning rate to use for the network. + Must be within range of 0.0 < rate <= 1.0 + (default: '%(default)s') + ''', + default=0.25 + ) + + parser.add_argument( + '--bias', '-b', metavar='INITIAL_BIAS', type=float, nargs='?', + help= + '''The initial bias to use for perceptrons within the network. + Must be within range of -1.0 <= bias <= 1.0 + If value is unset, bias will be initialized randomly + ''', + ) + + parser.add_argument( + '--weight', '-w', metavar='INITIAL_EDGE_WEIGHTS', type=float, nargs='?', + help= + '''The initial edge weight to use for node connections in the network + If value is unset, edge weights will be initialized randomly + ''' + ) + + parser.add_argument( + '--error-threshold', '--error', metavar='ERROR_THRESHOLD', type=float, nargs='?', + help= + '''The acceptable error threshold to use for training the network. + (default: '%(default)s') + ''', + default=0.5 + ) + + parser.add_argument( + '--fire-threshold', '--fire', metavar='FIRE_THRESHOLD', type=float, nargs='?', + help= + '''The fire threshold for perceptrons in the network. + If a perceptron\'s cumulative inputs reach this value, the perceptron fires + (default: '%(default)s') + ''', + default=0.25 + ) + + parser.add_argument( + '--spacing', metavar='LAYER_SPACING', type=float, nargs='?', + help= + '''Distance between origin of network layers within visualization + (default: '%(default)s') + ''', + default=2.0 + ) + + parser.add_argument( + '--horizontal', '--flip', action='store_true', + help= + '''The network visualization will flow left-to-right + (default: '%(default)s') + ''', + default=False + ) + + parser.add_argument( + '--silent', action='store_true', + help= + '''Do not show the network visualization, only print output to console + (default: '%(default)s') + ''', + default=False + ) + + parser.add_argument( + '--verbose', '-v', action='store_true', + help= + '''When this flag is set, error rate and change in weight will be output for each calculation + (default: '%(default)s') + ''', + default=False + ) + + parser.add_argument( + '--file', '-f', metavar='file_path', nargs='?', type=open, + help= + '''Optionally provide a json file to configure any option available through the cli + json keys match --long version of each option, where --long-split option key is "long_split" in json + ''', + ) + + return parser + + +################################################################################ +# Neural Network +################################################################################ + +# ============================================================================== + +def parse_file(): + """ + Validates keys in JSON file and updates CLI input context + + :return: (seq_input, seq_label) Initialized to input and label sequences in JSON file if present + """ + + # Load the JSON input file, validate keys + file_data = json.load(context['file']) + for key in file_data: + if key == "input_sequence" or key == "label_sequence": + continue + assert key in context + # Update the CLI context with JSON input + context.update(file_data) + + # If JSON file provided input and label sequences, load and return them + seq_input = seq_label = None + if 'input_sequence' in file_data: + seq_input = np.array(file_data['input_sequence']) + if 'label_sequence' in file_data: + seq_label = np.array(file_data['label_sequence']) + return seq_input, seq_label + + +def network_layers(): + """ + Initialize a dictionary of layers where each layer is a list of nodes: {'input': [0, 1, 2]} + The hidden layer in this dictionary is a list of lists for each hidden layer: {'hidden': [[3, 4, 5], [6, 7, 8]]} + + :return: A dictionary, as an example: {'input': [0, 1, 2], 'hidden': [[3, 4, 5], [6, 7, 8]], 'output': [9, 10, 11] } + """ + inputs = [i for i in range(context["inputs"])] + offset = context["inputs"] + + # For each hidden layer add the requested number of perceptrons + hidden = [[] for x in range(context["hidden_layers"])] + for x in range(context["hidden_layers"]): + hidden[x] = [i for i in range(offset, context["perceptrons"] + offset)] + offset += context["perceptrons"] + + outputs = [i for i in range(offset, context["outputs"] + offset)] + offset += context["outputs"] + + layers = {"inputs": inputs, "hidden": hidden, "outputs": outputs} + [print(f'{layer} layer: {layers[layer]}') for layer in layers] + return layers + + +def random_matrix(rows, cols, low=-1.0, high=1.0): + """ Produce a random matrix of size ROWSxCOLS using LOW and HIGH as upper and lower bounds """ + return np.random.uniform(low, high, (rows, cols)) + + +def get_matrix_dict(): + """ + Produces a dictionary that holds edge weight transition matrices for each layer of the network + matrix_dict['input'] maps to a single 2D matrix + + matrix_dict['hidden'] maps to a 3D matrix + + where matrix_dict['hidden'][0] is the 2D transition matrix for the first hidden layer + + :return: A dictionary, as an example: {'input': [[...]], 'hidden': [[[...]], [[...]]], 'output': [[...]] } + """ + if context["weight"] is None: + # Create matrices to represent edges and weights for each layer of the network + input_matrix = random_matrix(context["inputs"], context["perceptrons"]) + hidden_matrices = [random_matrix(context["perceptrons"], context["perceptrons"]) + for x in range(context["hidden_layers"]-1)] + output_matrix = random_matrix(context["perceptrons"], context["outputs"]) + else: + # If an initial edge weight was specified, fill matrices with that value instead of generating randomly + input_matrix = np.full((context["inputs"], context["perceptrons"]), context["weight"]) + hidden_matrices = [np.full((context["perceptrons"], context["perceptrons"]), context["weight"]) + for x in range(context["hidden_layers"]-1)] + output_matrix = np.full((context["perceptrons"], context["outputs"]), context["weight"]) + + matrix_dict = {'input': input_matrix, 'hidden': np.array(hidden_matrices), 'output': output_matrix} + return matrix_dict + + +def get_bias_dict(): + """ + Produces a dictionary that stores bias vectors for perceptrons in each layer of the network + The hidden layer in this dictionary is a list of lists for bias in each hidden layer: {'hidden': [[...], [...]]} + + :return: A dictionary, as an example: {'input': [0.5, 0.5], 'hidden': [[0.5, 0.5 0.5], ...], 'output': [...] } + """ + # If there was a bias provided, use it; Else use random perceptron bias + bias = round(random.uniform(-1.0, 1.0), 2) if context["bias"] is None else context["bias"] + # Create vectors to represent perceptron bias in each layer + input_bias = [bias for x in range(0, context["inputs"])] + hidden_bias = [[bias for x in range(0, context["perceptrons"])] for x in range(0, context["hidden_layers"])] + output_bias = [bias for x in range(0, context["outputs"])] + bias_dict = {'input': input_bias, 'hidden': hidden_bias, 'output': output_bias} + return bias_dict + + +def threshold_fire(input_sum): + """ + Applies step function using fire_threshold set by CLI to determine if perceptron is firing or not + + :param input_sum: The sum of inputs for this perceptron + :return: A list of outputs for each perceptron in the layer. If only the first fired: [1, 0, 0, 0] + """ + output = [1 if val > context["fire_threshold"] else 0 for val in input_sum.tolist()] + return output + + +def adjust_weight(matrix_dict, out_output, label): + """ + Back propagation for adjusting edge weights of nodes that produces incorrect output + + :param matrix_dict: A dictionary of matrices for the network produces by get_matrix_dict() + :param out_output: The actual output for this input sequence + :param label: The desired result for this input sequence + :return: A dictionary of transition matrices for the network with adjusted edge weights + """ + # Find erroneous indices + bad_nodes = error_nodes(out_output, label) + if len(bad_nodes) == 0: + return matrix_dict + + # Adjust the edge weights leading to the error nodes; Don't adjust correct nodes + for layer, mat in reversed(matrix_dict.items()): + if layer == 'output': + for node in bad_nodes: + for row in range(len(mat)): + mod = context['learn_rate'] * (label[node] - out_output[node]) # * Input (???) + if context['verbose']: + print(f'Adjusting output weights at ({row}, {node}) with {mod}') + mat[row][node] += mod + + # In a fully connected neural network, all edges are updated if any output node is wrong + # + Every node of every layer connects to every node in the next layer + # + Any wrong node updates all edges in previous layers + if layer == 'hidden': + # If there are any hidden layers that do not connect to input or output layers directly + if mat.size > 0: + # For each hidden layer matrix, update all edge weights + for i, hl_mat in enumerate(mat): + for row in range(len(hl_mat)): + mod = context['learn_rate'] + for col in range(len(hl_mat[row])): + # print(f'Adjusting output weights at ({row}, {col}) with {mod}') + mat[i][row][col] += context["learn_rate"] + + if layer == 'input': + for row in range(len(mat)): + mod = context['learn_rate'] + for col in range(len(mat[row])): + # print(f'Adjusting output weights at ({row}, {col}) with {mod}') + mat[row][col] += mod + return matrix_dict + + +def error_rate(actual_output, label): + """ + Determines error rate for this input sequence + Error rate is later used to determine if edge weights should be adjusted + + :param actual_output: The actual output for this input sequence + :param label: The desired output for this input sequence + :return: The error rate for the sequence + """ + error_sum = 0 + for n, output in enumerate(actual_output): + err = label[n] - output + error_sum += math.pow(err, 2) + err = math.sqrt(error_sum) + return err + + +def error_nodes(out_output, label): + """ + Find which output nodes are incorrect + + :param out_output: Actual output for this input sequence + :param label: The desired output for this input sequence + :return: A list of node indices that produced the wrong output for this sequence + """ + # Loop through each output, check if it matches the label; If it doesn't add index to returned list + return [i for i, output in enumerate(out_output) if output != label[i]] + + +def layer_pass(weight_matrix, input_vector, bias_vector): + """ + Passes input from layer A to layer B + + :param weight_matrix: Transition matrix of edge weights where perceptrons from layer A are rows and B are columns + :param input_vector: An input vector that represents the output from A to B + :param bias_vector: The bias vector for perceptrons in layer B + :return: Final output from the layer, after step function is applied in threshold_fire() + """ + layer_edge_weights = np.array(weight_matrix).T + prev_output = np.atleast_2d(input_vector).T + this_layer_input = layer_edge_weights.dot(prev_output).T.flatten() + this_layer_input += np.array(bias_vector) + + return threshold_fire(this_layer_input) + + +def train_network(seq_input, seq_label, bias_dict, matrix_dict): + """ + Performs forward pass through network, moving through the number of cycles requested by the CLI + + :param seq_input: Sequence of inputs to feed into the network + :param seq_label: Sequence of labels to verify network output and indicate error + :param bias_dict: Dictionary of bias vectors for the perceptrons in each layer + :param matrix_dict: Dictionary of transition matrices for the edge weights between layers in the network + :return: Information gathered from training the network used to output final accuracy + """ + # Info dictionary used to track accuracy + info = {'correct': 0, 'wrong': 0, 'total': len(seq_input) * context["cycles"], 'first_acc': 0} + + # A list of error rates for each cycle + # + These aren't used much for the program, but they hold nice data to explore while debugging + cycle_errors = [] + cycle_outputs = [[] for x in range(context["cycles"])] + for cycle_index in range(1, context["cycles"] + 1): + # print(f'\nCycle number {cycle_index}') + for seq_index in range(0, len(seq_input)): + # One list for storing the outputs of each layer, and another to store inputs + seq_outputs = [] + + # Input layer -> Hidden layer + # Apply input perceptron bias vector to initial inputs of the input layer + in_input = np.array(np.array(seq_input[seq_index]) + np.array(bias_dict['input'])) + # Find output of the input layer + in_output = threshold_fire(in_input) + seq_outputs.append(in_output) + + # Find output for first hidden layer + hl_output = layer_pass(matrix_dict["input"], seq_outputs[-1], bias_dict['hidden'][0]) + seq_outputs.append(hl_output) + + # For each hidden layer find inputs and outputs, up until the last hidden layer + # + Start at 1 since we already have the output from first hidden layer + for layer_index in range(1, context["hidden_layers"]): + # Hidden layer -> Hidden layer + edges = matrix_dict['hidden'][layer_index - 1] + bias = bias_dict['hidden'][layer_index - 1] + # Find output for hidden layer N + hl_output = layer_pass(edges, seq_outputs[-1], bias) + seq_outputs.append(hl_output) + + # Hidden layer -> Output layer + # Find output for output layer + out_output = layer_pass(matrix_dict['output'], seq_outputs[-1], bias_dict['output']) + seq_outputs.append(out_output) + + # Forward pass through network finished + # Find error rate for this input sequence + err = error_rate(out_output, seq_label[seq_index]) + + if context['verbose'] and err > 0: + print(f'Error rate for sequence {seq_index} cycle {cycle_index}: {err}') + # If error rate for this sequence is above threshold, adjust weighted edges + if err > context["error_threshold"]: + matrix_dict = adjust_weight(matrix_dict, out_output, seq_label[seq_index]) + + # Track correctness of sequences and cycles + if err == 0: + info['correct'] += 1 + else: + info['wrong'] += 1 + + # Append the result to the cycle_outputs list for this cycle; -1 for 0 index array offset + # cycle_outputs contains a list for each cycle. Each list contains N outputs for N input sequences + cycle_outputs[cycle_index - 1].append(out_output) + cycle_errors.append(err) + + # Move to next learning cycle in for loop + info_total_temp = info['correct'] + info['wrong'] + if cycle_index == 1: + info['first_acc'] = round(100.0 * float(info["correct"] / info_total_temp), 4) + print( + f'[Cycle {cycle_index}] \tAccuracy: {100.0 * float(info["correct"] / info_total_temp):.4f}% \t' + f'[{info["correct"]} / {info["wrong"]}]' + ) + if context["verbose"]: + for layer in matrix_dict: + print( + f'Network {layer} layer: \n{matrix_dict[layer]}\n' + # Bias vector doesn't change, so it's not very interesting output per-cycle + # f'{layer} bias vector: {bias_dict[layer]}' + ) + + info['cycle_error'] = cycle_errors + return info + + +def draw_graph(net_plot, net_layers, draw_horizontal=None, spacing=None): + """ + This is the only function where viznet is used. Viznet is a module to visualize network graphs using matplotlib. + https://viznet.readthedocs.io/en/latest/core.html + https://viznet.readthedocs.io/en/latest/examples.html#examples + + To draw the graph, we need to at least specify the following information for-each layer in the network - + 1. The number of nodes in the layer + 2. The type of nodes that make up each layer (https://viznet.readthedocs.io/en/latest/viznet.theme.html) + 3. The distance between the center (origin) of each layer + With this we can use viznet helper functions to draw network + + :param net_plot: A matplotlib subplot to draw the network on + :param net_layers: A dictionary of layers that make up the network nodes + :param draw_horizontal: True if graph should be drawn so direction flows left->right; False for bottom->top + :param spacing: The distance between the center of origin for each layer in the network + """ + # If no spacing was provided to the call, use spacing set by CLI + spacing = context["spacing"] if spacing is None else spacing + # If no draw mode was provided to the call, use mode set by CLI + draw_horizontal = context["horizontal"] if draw_horizontal is None else draw_horizontal + + # 1. Number of nodes in each layer is provided by dictionary: len(net_layers['input']) + + # 2. Define node type to draw for each layer in the network (default ['nn.input', 'nn.hidden', nn.output]) + node_types = ['nn.input'] + ['nn.hidden'] * context["hidden_layers"] + ['nn.output'] + + # 3. Use spacing distance to create list of X positions with equal distance apart (default [0, 1.5, 3.0]) + # 1.5 * 0 = 0; 1.5 * 1 = 1.5; 1.5 * 2 = 3.0; 1.5 * 3 = 4.5; etc + layer_pos = spacing * np.arange(context["hidden_layers"] + 2) + + # Create a sequence of Node objects using viznet helper function node_sequence + # + Allows defining a NodeBrush for-each node, which is used by the library to style nodes + node_sequence = [] + layer_index = 0 + for layer in net_layers: + # If we are on the hidden layers, iterate through each + if layer == 'hidden': + for hl in net_layers[layer]: + brush = vn.NodeBrush(node_types[layer_index], net_plot) + ctr = (layer_pos[layer_index], 0) if draw_horizontal else (0, layer_pos[layer_index]) + node_sequence.append(vn.node_sequence( + brush, len(hl), + center=ctr, space=(0, 1) if draw_horizontal else (1, 0)) + ) + layer_index += 1 + else: + brush = vn.NodeBrush(node_types[layer_index], net_plot) + ctr = (layer_pos[layer_index], 0) if draw_horizontal else (0, layer_pos[layer_index]) + node_sequence.append(vn.node_sequence( + brush, len(net_layers[layer]), + center=ctr, space=(0, 1) if draw_horizontal else (1, 0)) + ) + layer_index += 1 + + # Define an EdgeBrush that draws arrows between nodes using matplotlib axes + edge_brush = vn.EdgeBrush('-->', net_plot) + for start, end in zip(node_sequence[:-1], node_sequence[1:]): + # Connect each node in `start` layer to each node in `end` layer + for start_node in start: + for end_node in end: + # Apply the EdgeBrush using matplotlib axes and node edge tuple + edge_brush >> (start_node, end_node) + + plt.show() + + +################################################################################ +# Main +################################################################################ + +# ============================================================================== + +def main(args: List[str]): + parser = init_parser() + global context + context = vars(parser.parse_args(args[1:])) + seq_input = None + seq_label = None + if context['file']: + seq_input, seq_label = parse_file() + + if seq_input is None or seq_label is None: + # You cannot provide input or label sequences via the CLI + # If no file was provided with data, use iris dataset as example data + + # Use sklearn.dataset to grab example data + iris = load_iris() + # iris_data = iris.data[:, (0, 1, 2, 3)] + iris_data = iris.data[:, (0, 2, 3)] + # iris_data = iris.data[:, (2, 3)] + iris_label = iris.target + + # Or read a CSV manually using pandas + # iris = pd.read_csv('/home/kapper/Code/School/CS/AI/Assignment/two/IRIS.csv').to_dict() + # iris_data = [[x, y] for x, y in zip(iris['petal_length'].values(), iris['petal_width'].values())] + # iris_data = [[x, y, z] for x, y, z in zip(iris['petal_length'].values(), + # iris['petal_width'].values(), + # iris['sepal_length'].values())] + # iris_label = [x for x in iris['species'].values()] + + # To change the number of output nodes, we need to adjust the number of labels for classification + # iris_data = iris.data[0:99, (0, 2, 3)] + # iris_label = [l for l in iris_label if l != 2] + + # Convert labels to: 0-> [1, 0, 0]; 1-> [0, 1, 0]; 2->[0, 0, 1] + seq_input = iris_data + seq_label = [] + for i, label in enumerate(set(iris_label)): + same = [s for s in iris_label if s == label] + for l in same: + new_label = np.zeros(len(set(iris_label))).tolist() + new_label[i] = 1 + seq_label.append(new_label) + + # Assert that the provided learning rate is valid + assert(0.0 < context['learn_rate'] <= 1.0) + + # This check ensures that the number of inputs match the number of input nodes + # + And does the same for output nodes with possible classifications + # + But, this removes the ability to grow / shrink input / output layers through CLI + if context["inputs"] != len(seq_input[0]): + print(f'Warning: Input sequences each contain {len(seq_input[0])} entries ' + f'but {context["inputs"]} input nodes were requested.\n' + f'\tUsing {len(seq_input[0])} input nodes instead of {context["inputs"]}' + ) + context["inputs"] = len(seq_input[0]) + if context["outputs"] != len(set(map(tuple, seq_label))): + print(f'Warning: Output labels contain {len(set(map(tuple, seq_label)))} possible classifications ' + f'but {context["outputs"]} output were nodes requested.\n' + f'\tUsing {len(set(map(tuple, seq_label)))} output nodes instead of {context["outputs"]}' + ) + context["outputs"] = len(set(map(tuple, seq_label))) + + # Output the problem settings + print(f'Creating a single layer neural network: \n' + f'\tTotal input nodes: {context["inputs"]}\n' + f'\tNumber of perceptrons in each hidden layer: {context["perceptrons"]}\n' + f'\tTotal output nodes: {context["outputs"]}\n' + f'\tNumber of hidden layers: {context["hidden_layers"]}\n' + f'\tFire threshold: {context["fire_threshold"]}\n' + f'\tError threshold: {context["error_threshold"]}\n' + f'\tLearn rate: {context["learn_rate"]}\n' + f'\tInitial bias: {context["bias"] if context["bias"] is not None else "Random"}\n' + f'\tInitial edge weights: {context["weight"] if context["weight"] is not None else "Random"}\n' + f'Network visualization settings: \n' + f'\tGraph visualization is enabled: {not context["silent"]}\n' + f'\tGraph visualization is horizontal: {context["horizontal"]}\n' + f'\tGraph visualization is vertical: {not context["horizontal"]}\n' + f'\tGraph visualization layer spacing: {context["spacing"]}\n' + f'\tTest data input count: {len(seq_input)}' + ) + + # Initialize a dictionary of vectors for mapping to each layer node + # + layers['hidden'][0] = [3, 4, 5, 6] --> Hidden layer nodes are at index 3, 4, 5, 6 + layers = network_layers() + + # A dictionary where matrix_dict['input'] maps to edge weight matrix for input_layer->first_hidden_layer + # matrix_dict['hidden'] maps to a list of matrices; matrix_dict['hidden'][0] is edge weights for first_hl->second_hl + # matrix_dict['output'] maps to edge weight matrix for last_hl->output_layer + matrix_dict = get_matrix_dict() + # Randomly generate perceptron bias if none was provided through CLI + bias_dict = get_bias_dict() + + info = train_network(seq_input, seq_label, bias_dict, matrix_dict) + # Final console output for overall results + info_total_temp = info['correct'] + info['wrong'] + acc = 100.0 * float(info["correct"] / info_total_temp) + print( + f'\nCorrect: {info["correct"]} \t Wrong: {info["wrong"]} \t Total: {context["cycles"] * len(seq_input)}' + f'\nCycle 1 accuracy: {info["first_acc"]}% \tCycle {context["cycles"]} accuracy: {acc:.4f}%' + f'\n{round(acc - info["first_acc"], 4)}% change over {context["cycles"]} cycles ' + f'\t{round((acc - info["first_acc"]) / context["cycles"], 4)}% average change per cycle' + ) + + # All cycles have finished; Draw the network for a visual example to go with output + if not context["silent"]: + draw_graph(plt.subplot(), layers) + + +if __name__ == "__main__": + sys.exit(main(sys.argv)) diff --git a/python/neural-network/requirements.txt b/python/neural-network/requirements.txt new file mode 100644 index 0000000..85fa333 --- /dev/null +++ b/python/neural-network/requirements.txt @@ -0,0 +1,5 @@ +matplotlib==3.5.0 +numpy==1.21.4 +pandas==1.3.4 +scikit_learn==1.0.2 +viznet==0.3.0 diff --git a/python/neural-network/screenshot.png b/python/neural-network/screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..8a4409db720d46c530bab271cf834da1bb07245f GIT binary patch literal 117148 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

C-EbS$Jo*~E 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 OH{x3c| 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 literal 0 HcmV?d00001