├── README.md ├── LICENSE ├── car-tutorial.py ├── make-dataset.py └── car.py /README.md: -------------------------------------------------------------------------------- 1 | # StupidlySimpleCar 2 | A stupidly simple car neural net that accompanies https://medium.com/@mark_riedl/introduction-to-neural-nets-without-the-brain-metaphor-874e7950bca0#.ffdnfa3h0 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 markriedl 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /car-tutorial.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import tflearn 3 | import sys 4 | 5 | # Load CSV file 6 | # For some reason, the CSV must have a single label column. So the dataset has a last dummy column. 7 | from tflearn.data_utils import load_csv 8 | input_data, dummy = load_csv("data.csv", columns_to_ignore=[5, 6, 7, 8]) 9 | input_labels, dummy = load_csv("data.csv", columns_to_ignore=[1, 2, 3, 4]) 10 | 11 | # Put data and labels into a numpy array (matrix) 12 | data = np.array(input_data, dtype=np.float32) 13 | labels = np.array(input_labels, dtype=np.float32) 14 | 15 | # Build neural network 16 | net = tflearn.input_data(shape=[None, 4]) # 4 inputs 17 | net = tflearn.fully_connected(net, 16, activation='relu') # hidden layer of 16 nodes 18 | net = tflearn.fully_connected(net, 16, activation='relu') # hidden layer of 16 nodes 19 | net = tflearn.fully_connected(net, 4, activation='relu') # 4 outputs 20 | net = tflearn.regression(net, loss='mean_square') 21 | 22 | # Define model 23 | model = tflearn.DNN(net) 24 | 25 | # Start training (apply gradient descent algorithm) 26 | model.fit(data, labels, n_epoch=10, show_metric=True) 27 | 28 | # User testing loop 29 | while True: 30 | # Ask the user for values (0.0 - 1.0) for each sensor 31 | print("front proximity?") 32 | f = sys.stdin.readline() 33 | print("rear proximity?") 34 | b = sys.stdin.readline() 35 | print("left proximity?") 36 | l = sys.stdin.readline() 37 | print("right proximity?") 38 | r = sys.stdin.readline() 39 | 40 | # Make prediction 41 | test = [[f, b, l, r]] # test input 42 | pred = model.predict(test) # run test input through neural net 43 | # Report 44 | print("Prediction: ") 45 | print("brakes: "+str(pred[0][0])) 46 | print("accelerator: "+str(pred[0][1])) 47 | print("steer left: "+str(pred[0][2])) 48 | print("steer right: "+str(pred[0][3])) 49 | print("--") 50 | -------------------------------------------------------------------------------- /make-dataset.py: -------------------------------------------------------------------------------- 1 | import random, sys 2 | 3 | verbose = False 4 | 5 | filename = '' # If data is being loaded from a CSV instead, this is the filename 6 | numRows = 0 # How many samples? 7 | 8 | if len(sys.argv) < 3: 9 | # Invalid command line usage 10 | print("usage: python "+sys.argv[0]+" output.csv num_samples") 11 | exit() 12 | else: 13 | filename = sys.argv[1] 14 | numRows = int(sys.argv[2]) 15 | 16 | # Open the file 17 | with open(filename, 'w') as file: 18 | 19 | #write the header row 20 | file.write('front,back,left,right,brakes,accel,left,right,dummy\n') 21 | 22 | # Make new rows 23 | for n in range(numRows): 24 | 25 | # Generate a random state 26 | # the distance to the nearest car in front/back/left/right is normalized from 0.0 (closest) to 1.0 (farthest) 27 | carInFrontDist = random.random() 28 | carInBackDist = random.random() 29 | carLeftDist = random.random() 30 | carRightDist = random.random() 31 | 32 | # Response to the state. 1 = brakes/accelerator/steer-left/steer-right is activated. 0=not activated 33 | # Though binary, we will be using numbers 34 | brakes = 0.0 35 | accel = 1.0 36 | left = 0.0 37 | right = 0.0 38 | 39 | # Should I accelerate or brake? 40 | if carInFrontDist < 0.50: 41 | # Car is close, brake 42 | # Unless there is another car close behind 43 | if carInBackDist > 0.50: 44 | # Okay to brake 45 | brakes = 1.0 - (carInFrontDist/0.50) 46 | accel = 0 47 | else: 48 | # Not okay to brake, but at least stop accelerating 49 | brakes = 0 50 | accel = 0 51 | else: 52 | # Car in front is not close, continue to accelerate 53 | accel = (carInFrontDist - 0.50)/0.50 54 | brakes = 0 55 | 56 | # Should I turn left or right? (can't do both) 57 | if carLeftDist < 0.50 and carRightDist > 0.50: 58 | # A car is close on the left, there is space on the right 59 | right = 1.0 - (carLeftDist/0.50) 60 | left = 0 61 | elif carRightDist < 0.50 and carLeftDist > 0.50: 62 | # A car is close on the right, there is space on the left 63 | left = 1.0 - (carRightDist/0.50) 64 | right = 0 65 | 66 | # Coma separated row of data 67 | out = str(carInFrontDist)+','+str(carInBackDist)+','+str(carLeftDist)+','+str(carRightDist)+','+str(brakes)+','+str(accel)+','+str(left)+','+str(right)+',0' 68 | 69 | # Maybe print to screen too? 70 | if verbose: 71 | print out 72 | 73 | # Write to file 74 | file.write(out+'\n') 75 | 76 | -------------------------------------------------------------------------------- /car.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | 3 | import numpy as np 4 | import tflearn 5 | import copy, sys 6 | 7 | # Handle command line arguments 8 | loadModel = False # Is the user requesting to use a pre-trained model? 9 | modelname = '' # If so, what is the name of that model filename? 10 | filename = '' # If data is being loaded from a CSV instead, this is the filename 11 | filehead = '' # And this is the part of the filename before the .csv 12 | 13 | if len(sys.argv) < 2: 14 | # Invalid command line usage 15 | print("usage: python "+sys.argv[0]+" file.csv") 16 | print("usage: python "+sys.argv[0]+" -m model.tflearn") 17 | exit() 18 | elif len(sys.argv) >= 3 and sys.argv[1] == '-m': 19 | # User wants to load a model 20 | modelname = sys.argv[2] 21 | loadModel = True 22 | else: 23 | # Default: user wants to load data from a CSV 24 | filename = sys.argv[1] 25 | filehead = filename.split('.')[0] 26 | 27 | # Some initializations 28 | input_data = None # All the data from the CSV will be held here (including supervision labels) 29 | input_labels = None # All the supervision labels from the CSV will be held here 30 | data = None # Data for training 31 | labels = None # supervision labels 32 | 33 | # Read the CSV 34 | if not loadModel: 35 | # Load CSV file 36 | # For some reason, the CSV must have a single label column. So the dataset has a last dummy column. 37 | from tflearn.data_utils import load_csv 38 | input_data, dummy = load_csv(filename, columns_to_ignore=[5, 6, 7, 8]) 39 | input_labels, dummy = load_csv(filename, columns_to_ignore=[1, 2, 3, 4]) 40 | 41 | # Put data and labels into a numpy array (matrix) 42 | #data = preprocess(input_data, num_columns, data_columns) 43 | #labels = preprocess(input_labels, num_columns, label_columns) 44 | data = np.array(input_data, dtype=np.float32) 45 | labels = np.array(input_labels, dtype=np.float32) 46 | 47 | # Build neural network 48 | net = tflearn.input_data(shape=[None, 4]) # 4 inputs 49 | net = tflearn.fully_connected(net, 16, activation='relu') # hidden layer of 16 nodes 50 | net = tflearn.fully_connected(net, 16, activation='relu') # hidden layer of 16 nodes 51 | net = tflearn.fully_connected(net, 4, activation='relu') # 4 outputs 52 | net = tflearn.regression(net, loss='mean_square') 53 | 54 | # Define model 55 | model = tflearn.DNN(net) 56 | 57 | # Load or train? 58 | if loadModel: 59 | # Load the model 60 | model.load(modelname) 61 | else: 62 | # Start training (apply gradient descent algorithm) 63 | model.fit(data, labels, n_epoch=10, show_metric=True) 64 | # Save the model 65 | model.save(filehead+'.tflearn') 66 | 67 | # User testing loop 68 | while True: 69 | # Ask the user for values (0.0 - 1.0) for each sensor 70 | print("front proximity?") 71 | f = sys.stdin.readline() 72 | print("rear proximity?") 73 | b = sys.stdin.readline() 74 | print("left proximity?") 75 | l = sys.stdin.readline() 76 | print("right proximity?") 77 | r = sys.stdin.readline() 78 | 79 | # Make prediction 80 | test = [[f, b, l, r]] # test input 81 | pred = model.predict(test) # run test input through neural net 82 | # Report 83 | print("Prediction: ") 84 | print("brakes: "+str(pred[0][0])) 85 | print("accelerator: "+str(pred[0][1])) 86 | print("steer left: "+str(pred[0][2])) 87 | print("steer right: "+str(pred[0][3])) 88 | print("--") 89 | --------------------------------------------------------------------------------