diff --git a/ai/classifier/checkpoint b/ai/classifier/checkpoint index 2ae7edc..0a7c9a6 100644 --- a/ai/classifier/checkpoint +++ b/ai/classifier/checkpoint @@ -1,2 +1,2 @@ -model_checkpoint_path: "pero-model" -all_model_checkpoint_paths: "pero-model" +model_checkpoint_path: "weed-model" +all_model_checkpoint_paths: "weed-model" diff --git a/ai/classifier/dataset.py b/ai/classifier/dataset.py index e55469b..c766761 100644 --- a/ai/classifier/dataset.py +++ b/ai/classifier/dataset.py @@ -12,7 +12,7 @@ def load_train(train_path, image_size, classes): cls = [] print('Going to read training images') - for fields in classes: + for fields in classes: index = classes.index(fields) print('Now going to read {} files (Index: {})'.format(fields, index)) path = os.path.join(train_path, fields, '*g') @@ -83,7 +83,6 @@ def next_batch(self, batch_size): self._epochs_done += 1 start = 0 self._index_in_epoch = batch_size - assert batch_size <= self._num_examples end = self._index_in_epoch @@ -96,7 +95,7 @@ class DataSets(object): data_sets = DataSets() images, labels, img_names, cls = load_train(train_path, image_size, classes) - images, labels, img_names, cls = shuffle(images, labels, img_names, cls) + images, labels, img_names, cls = shuffle(images, labels, img_names, cls) if isinstance(validation_size, float): validation_size = int(validation_size * images.shape[0]) @@ -115,3 +114,5 @@ class DataSets(object): data_sets.valid = DataSet(validation_images, validation_labels, validation_img_names, validation_cls) return data_sets + + diff --git a/ai/classifier/demo.py b/ai/classifier/demo.py deleted file mode 100644 index 71c2641..0000000 --- a/ai/classifier/demo.py +++ /dev/null @@ -1,39 +0,0 @@ -#!/usr/bin/python - -import sys, getopt - -import tensorflow as tf -from model import Model -#import cv2 -import matplotlib.image as mpimg - -graph_path = 'pero-model.meta' -checkpoints_path = './' - -def run_demo(): - with tf.Session() as sess: - nn = Model() - nn.init(graph_path, checkpoints_path, sess) - #image = cv2.imread(image_path) - while True: - image_path = raw_input("Image path:") - image = mpimg.imread(image_path) - bad, good = nn.predict(image)[0] - print 'Bad', str(bad*100), '%' - print 'Good', str(good*100), '%' - -def main(argv): - inputfile = '' - outputfile = '' - # try: - # opts, args = getopt.getopt(argv,"hi:o:",["ifile=","ofile="]) - # except getopt.GetoptError: - # print 'test.py -i ' - # sys.exit(2) - # for opt, arg in opts: - # if opt in ("-i", "--ifile"): - # image_path = arg - run_demo() - -if __name__ == "__main__": - main(sys.argv[1:]) diff --git a/ai/classifier/model.py b/ai/classifier/model.py deleted file mode 100644 index f588760..0000000 --- a/ai/classifier/model.py +++ /dev/null @@ -1,57 +0,0 @@ -import tensorflow as tf -import numpy as np -import os,glob -import sys,argparse -from PIL import Image - - -class Model: - - graph = None # Netwok graph - sess = None # Tensorflow session - - def init(self, grap_path, checkpoints_path, sess): - '''Initialize network model''' - # Save tensorflow session - self.sess = sess - # Load netwok graph from grap_path - saver = tf.train.import_meta_graph(grap_path) - self.graph = tf.get_default_graph() - # Load the latest weights from checkpoints_path - saver.restore(sess, tf.train.latest_checkpoint(checkpoints_path)) - - - def predict(self, image): - '''Predict single image''' - - # Resize image to desired size and preprocessing done during training - image_size = 128 - num_channels = 3 - images = [] - #image = cv2.resize(image, (image_size, image_size), cv2.INTER_LINEAR) - pix = Image.fromarray(image, 'RGB') - pix = pix.resize((image_size, image_size), Image.ANTIALIAS) - image = np.array(pix) - - images.append(image) - images = np.array(images, dtype=np.uint8) - images = images.astype('float32') - images = np.multiply(images, 1.0/255.0) - - # Reshape for network input [None image_size image_size num_channels] - x_batch = images.reshape(1, image_size,image_size,num_channels) - - # y_pred is the tensor predicts (:0 is 0-th element of the bacth) - y_pred = self.graph.get_tensor_by_name("y_pred:0") - - # Feed image to the input placeholder - x= self.graph.get_tensor_by_name("x:0") - y_true = self.graph.get_tensor_by_name("y_true:0") - y_test_images = np.zeros((1, 2)) - - - # Calculate y_pred - feed_dict_testing = {x: x_batch, y_true: y_test_images} - result=self.sess.run(y_pred, feed_dict=feed_dict_testing) - - return result diff --git a/ai/classifier/pero-model.data-00000-of-00001 b/ai/classifier/pero-model.data-00000-of-00001 deleted file mode 100644 index 1257ed5..0000000 Binary files a/ai/classifier/pero-model.data-00000-of-00001 and /dev/null differ diff --git a/ai/classifier/pero-model.index b/ai/classifier/pero-model.index deleted file mode 100644 index 327eb49..0000000 Binary files a/ai/classifier/pero-model.index and /dev/null differ diff --git a/ai/classifier/train.py b/ai/classifier/train.py index cdd76d3..e47a4b2 100644 --- a/ai/classifier/train.py +++ b/ai/classifier/train.py @@ -6,7 +6,7 @@ import random import numpy as np -# Adding seed so that random initialization is consistent +#Adding Seed so that random initialization is consistent from numpy.random import seed seed(1) from tensorflow import set_random_seed @@ -15,18 +15,17 @@ batch_size = 32 -# Prepare input data -classes = ['bad','good'] +#Prepare input data +classes = ['good','bad'] num_classes = len(classes) -# 20% of the data will be used for validation +# 20% of the data will automatically be used for validation validation_size = 0.2 img_size = 128 num_channels = 3 -train_path='./data/train/' -check_point_name = './pero-model' +train_path='training_data' -# Load training and validation images and labels +# We shall load all the training and validation images and labels into memory using openCV and use that during training data = dataset.read_train_sets(train_path, img_size, classes, validation_size=validation_size) @@ -39,14 +38,13 @@ session = tf.Session() x = tf.placeholder(tf.float32, shape=[None, img_size,img_size,num_channels], name='x') -# Labels +## labels y_true = tf.placeholder(tf.float32, shape=[None, num_classes], name='y_true') y_true_cls = tf.argmax(y_true, dimension=1) -# Network graph params - +##Network graph params filter_size_conv1 = 3 num_filters_conv1 = 32 @@ -61,51 +59,65 @@ def create_weights(shape): return tf.Variable(tf.truncated_normal(shape, stddev=0.05)) - def create_biases(size): return tf.Variable(tf.constant(0.05, shape=[size])) -def create_convolutional_layer(input, num_input_channels, conv_filter_size, num_filters): - '''Create a convolutional layer + max pool + relu activation''' - # Trainable weights and biases +def create_convolutional_layer(input, + num_input_channels, + conv_filter_size, + num_filters): + + ## We shall define the weights that will be trained using create_weights function. weights = create_weights(shape=[conv_filter_size, conv_filter_size, num_input_channels, num_filters]) + ## We create biases using the create_biases function. These are also trained. biases = create_biases(num_filters) - # Create the convolutional layer - layer = tf.nn.conv2d(input=input, filter=weights, strides=[1, 1, 1, 1], padding='SAME') - layer += biases + ## Creating the convolutional layer + layer = tf.nn.conv2d(input=input, + filter=weights, + strides=[1, 1, 1, 1], + padding='SAME') - # Max-pooling. - layer = tf.nn.max_pool(value=layer, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME') + layer += biases - # Relu activation function + ## We shall be using max-pooling. + layer = tf.nn.max_pool(value=layer, + ksize=[1, 2, 2, 1], + strides=[1, 2, 2, 1], + padding='SAME') + ## Output of pooling is fed to Relu which is the activation function for us. layer = tf.nn.relu(layer) return layer -def create_flatten_layer(layer): - '''Flatten layer of dimension [batch_size img_size img_size num_channels] to single column tensor''' +def create_flatten_layer(layer): + #We know that the shape of the layer will be [batch_size img_size img_size num_channels] + # But let's get it from the previous layer. layer_shape = layer.get_shape() + + ## Number of features will be img_height * img_width* num_channels. But we shall calculate it in place of hard-coding it. num_features = layer_shape[1:4].num_elements() - # Flatten layer reshaped to num_features + ## Now, we Flatten the layer so we shall have to reshape to num_features layer = tf.reshape(layer, [-1, num_features]) return layer -def create_fc_layer(input, num_inputs, num_outputs, use_relu=True): - '''Create fully connected layer''' +def create_fc_layer(input, + num_inputs, + num_outputs, + use_relu=True): - #Trainable weights and biases + #Let's define trainable weights and biases. weights = create_weights(shape=[num_inputs, num_outputs]) biases = create_biases(num_outputs) - # Fully connected layer takes input x and produces wx+b + # Fully connected layer takes input x and produces wx+b.Since, these are matrices, we use matmul function in Tensorflow layer = tf.matmul(input, weights) + biases if use_relu: layer = tf.nn.relu(layer) @@ -113,14 +125,10 @@ def create_fc_layer(input, num_inputs, num_outputs, use_relu=True): return layer - -# Netwok graph - layer_conv1 = create_convolutional_layer(input=x, num_input_channels=num_channels, conv_filter_size=filter_size_conv1, num_filters=num_filters_conv1) - layer_conv2 = create_convolutional_layer(input=layer_conv1, num_input_channels=num_filters_conv1, conv_filter_size=filter_size_conv2, @@ -144,13 +152,11 @@ def create_fc_layer(input, num_inputs, num_outputs, use_relu=True): use_relu=False) y_pred = tf.nn.softmax(layer_fc2,name='y_pred') -y_pred_cls = tf.argmax(y_pred, dimension=1) +y_pred_cls = tf.argmax(y_pred, dimension=1) session.run(tf.global_variables_initializer()) - - -# Training functions -cross_entropy = tf.nn.softmax_cross_entropy_with_logits(logits=layer_fc2, labels=y_true) +cross_entropy = tf.nn.softmax_cross_entropy_with_logits(logits=layer_fc2, + labels=y_true) cost = tf.reduce_mean(cross_entropy) optimizer = tf.train.AdamOptimizer(learning_rate=1e-4).minimize(cost) correct_prediction = tf.equal(y_pred_cls, y_true_cls) @@ -161,42 +167,39 @@ def create_fc_layer(input, num_inputs, num_outputs, use_relu=True): def show_progress(epoch, feed_dict_train, feed_dict_validate, val_loss): - '''Show progress while training''' acc = session.run(accuracy, feed_dict=feed_dict_train) val_acc = session.run(accuracy, feed_dict=feed_dict_validate) msg = "Training Epoch {0} --- Training Accuracy: {1:>6.1%}, Validation Accuracy: {2:>6.1%}, Validation Loss: {3:.3f}" print(msg.format(epoch + 1, acc, val_acc, val_loss)) - total_iterations = 0 saver = tf.train.Saver() def train(num_iteration): - '''Training loop''' - global total_iterations - for i in range(total_iterations, total_iterations + num_iteration): + for i in range(total_iterations, + total_iterations + num_iteration): - # Fecth batch - x_batch, y_true_batch, _, _ = data.train.next_batch(batch_size) - x_valid_batch, y_valid_batch, _, _ = data.valid.next_batch(batch_size) + x_batch, y_true_batch, _, cls_batch = data.train.next_batch(batch_size) + x_valid_batch, y_valid_batch, _, valid_cls_batch = data.valid.next_batch(batch_size) - feed_dict_tr = {x: x_batch, y_true: y_true_batch} - feed_dict_val = {x: x_valid_batch, y_true: y_valid_batch} + feed_dict_tr = {x: x_batch, + y_true: y_true_batch} + feed_dict_val = {x: x_valid_batch, + y_true: y_valid_batch} session.run(optimizer, feed_dict=feed_dict_tr) - # Show progress and save learnt parameters if i % int(data.train.num_examples/batch_size) == 0: val_loss = session.run(cost, feed_dict=feed_dict_val) epoch = int(i / int(data.train.num_examples/batch_size)) show_progress(epoch, feed_dict_tr, feed_dict_val, val_loss) - saver.save(session, check_point_name) + saver.save(session, 'weed-model') total_iterations += num_iteration -train(num_iteration=3000) +train(num_iteration=1000) diff --git a/ai/classifier/weed-model.data-00000-of-00001 b/ai/classifier/weed-model.data-00000-of-00001 new file mode 100644 index 0000000..84565c6 Binary files /dev/null and b/ai/classifier/weed-model.data-00000-of-00001 differ diff --git a/ai/classifier/weed-model.index b/ai/classifier/weed-model.index new file mode 100644 index 0000000..0d1f965 Binary files /dev/null and b/ai/classifier/weed-model.index differ diff --git a/ai/classifier/pero-model.meta b/ai/classifier/weed-model.meta similarity index 75% rename from ai/classifier/pero-model.meta rename to ai/classifier/weed-model.meta index b48d582..a930e20 100644 Binary files a/ai/classifier/pero-model.meta and b/ai/classifier/weed-model.meta differ