<jupyter_start><jupyter_text>Self-Driving Car Engineer Nanodegree Deep Learning Project: Build a Traffic Sign Recognition ClassifierIn this notebook, a template is provided for you to implement your functionality in stages which is required to successfully complete this project. If additional code is required that cannot be included in the notebook, be sure that the Python code is successfully imported and included in your submission, if necessary. Sections that begin with **'Implementation'** in the header indicate where you should begin your implementation for your project. Note that some sections of implementation are optional, and will be marked with **'Optional'** in the header.In addition to implementing code, there will be questions that you must answer which relate to the project and your implementation. Each section where you will answer a question is preceded by a **'Question'** header. Carefully read each question and provide thorough answers in the following text boxes that begin with **'Answer:'**. Your project submission will be evaluated based on your answers to each of the questions and the implementation you provide.>**Note:** Code and Markdown cells can be executed using the **Shift + Enter** keyboard shortcut. In addition, Markdown cells can be edited by typically double-clicking the cell to enter edit mode. --- Step 0: Load The Data<jupyter_code># Load pickled data
import pickle
from keras.datasets import cifar10

# TODO: Fill this in based on where you saved the training and testing data

training_file = "traffic-signs-data/train.p"
testing_file = "traffic-signs-data/test.p"

with open(training_file, mode='rb') as f:
    train = pickle.load(f)
with open(testing_file, mode='rb') as f:
    test = pickle.load(f)
    
X_train, y_train = train['features'], train['labels']
X_test, y_test = test['features'], test['labels']

print('Read of training and testing file complete.')<jupyter_output>Read of training and testing file complete.<jupyter_text>--- Step 1: Dataset Summary & ExplorationThe pickled data is a dictionary with 4 key/value pairs:- `'features'` is a 4D array containing raw pixel data of the traffic sign images, (num examples, width, height, channels).- `'labels'` is a 2D array containing the label/class id of the traffic sign. The file `signnames.csv` contains id -> name mappings for each id.- `'sizes'` is a list containing tuples, (width, height) representing the the original width and height the image.- `'coords'` is a list containing tuples, (x1, y1, x2, y2) representing coordinates of a bounding box around the sign in the image. **THESE COORDINATES ASSUME THE ORIGINAL IMAGE. THE PICKLED DATA CONTAINS RESIZED VERSIONS (32 by 32) OF THESE IMAGES**Complete the basic data summary below.<jupyter_code>### Replace each question mark with the appropriate value.

# TODO: Number of training examples
n_train = X_train.shape[0]

# TODO: Number of testing examples.
n_test = X_test.shape[0]

# TODO: What's the shape of an traffic sign image?
image_shape = X_test[0].shape

# TODO: How many unique classes/labels there are in the dataset.
n_classes = len(set(y_train))

assert(len(X_train) == len(y_train))
assert(len(X_test) == len(y_test))
assert(image_shape == (32, 32, 3))

print("Number of training examples =", n_train)
print("Number of testing examples =", n_test)
print("Image data shape =", image_shape)
print("Number of classes =", n_classes)<jupyter_output><empty_output><jupyter_text>Visualize the German Traffic Signs Dataset using the pickled file(s). This is open ended, suggestions include: plotting traffic sign images, plotting the count of each sign, etc.The [Matplotlib](http://matplotlib.org/) [examples](http://matplotlib.org/examples/index.html) and [gallery](http://matplotlib.org/gallery.html) pages are a great resource for doing visualizations in Python.**NOTE:** It's recommended you start with something simple first. If you wish to do more, come back to it after you've completed the rest of the sections.<jupyter_code>### Data exploration visualization goes here.
### Feel free to use as many code cells as needed.
import matplotlib.pyplot as plt
import random
import cv2
# Visualizations will be shown in the notebook.
%matplotlib inline

index = random.randint(0, n_train)
image = X_train[index].squeeze()

plt.figure(figsize=(2, 2))
plt.title('Random Training image')
plt.imshow(cv2.cvtColor(image, cv2.COLOR_RGB2GRAY), cmap='gray')
print('id of image: ', y_train[index])

plt.figure(figsize=(5, 3))
plt.hist(y_train, 'auto')
plt.title('Histogram distribution of count of training labels')
plt.show()<jupyter_output><empty_output><jupyter_text>---- Step 2: Design and Test a Model ArchitectureDesign and implement a deep learning model that learns to recognize traffic signs. Train and test your model on the [German Traffic Sign Dataset](http://benchmark.ini.rub.de/?section=gtsrb&subsection=dataset).There are various aspects to consider when thinking about this problem:- Neural network architecture- Play around preprocessing techniques (normalization, rgb to grayscale, etc)- Number of examples per label (some have more than others).- Generate fake data.Here is an example of a [published baseline model on this problem](http://yann.lecun.com/exdb/publis/pdf/sermanet-ijcnn-11.pdf). It's not required to be familiar with the approach used in the paper but, it's good practice to try to read papers like these.**NOTE:** The LeNet-5 implementation shown in the [classroom](https://classroom.udacity.com/nanodegrees/nd013/parts/fbf77062-5703-404e-b60c-95b78b2f3f9e/modules/6df7ae49-c61c-4bb2-a23e-6527e69209ec/lessons/601ae704-1035-4287-8b11-e2c2716217ad/concepts/d4aca031-508f-4e0b-b493-e7b706120f81) at the end of the CNN lesson is a solid starting point. You'll have to change the number of classes and possibly the preprocessing, but aside from that it's plug and play!  ImplementationUse the code cell (or multiple code cells, if necessary) to implement the first step of your project. Once you have completed your implementation and are satisfied with the results, be sure to thoroughly answer the questions that follow.<jupyter_code>### Preprocess the data here.
### Feel free to use as many code cells as needed.
from sklearn.utils import shuffle

def rgb2gray(rgb):
    return np.dot(rgb[...,:3], [0.299, 0.587, 0.114])

X_train, y_train = shuffle(X_train, y_train)
#I am also converting RGB images to gray but during training with Tensor flow and using tensor flow. 
print('Shuffling of training data complete')<jupyter_output><empty_output><jupyter_text>Question 1 _Describe how you preprocessed the data. Why did you choose that technique?_ **Answer:** I shuffeled the training data so that my neural network is not biased toward the order in which a training data is provided. No matter what the training data order is neural network performance should be similar. I am also converting RGB images to gray but during training with Tensor flow and using tensor flow. I am doing this because during visualization of training I realized that images were better looking when they were gray scale and any significant information was not lost so I converted them to gray scale. It will also help make algorithm faster.<jupyter_code>### Generate data additional data (OPTIONAL!)
### and split the data into training/validation/testing sets here.
### Feel free to use as many code cells as needed.
from sklearn.model_selection import train_test_split
print("-------Before split-------")
print("Number of training examples =", n_train)
X_train, X_validation, y_train, y_validation = train_test_split(X_train, y_train, test_size=0.20)

n_train = X_train.shape[0]
n_validation = X_validation.shape[0]

assert( len(X_validation) == len(y_validation))

print("-------After split-------")
print("Number of training examples =", n_train)
print("Number of validation examples =", n_test)
print("Number of testing examples =", n_test)<jupyter_output><empty_output><jupyter_text>Question 2_Describe how you set up the training, validation and testing data for your model. **Optional**: If you generated additional data, how did you generate the data? Why did you generate the data? What are the differences in the new dataset (with generated data) from the original dataset?_ **Answer:** I took 20% data out of training data as a validation data to evaluate my algorithm during its training phase. As testing data was already given so I am going to use that one.<jupyter_code>### Define your architecture here.
### Feel free to use as many code cells as needed.
import tensorflow as tf
from tensorflow.contrib.layers import flatten 

from tensorflow.contrib.layers import flatten

def conv2d(x, w, b, stride=1):
    x = tf.nn.conv2d(x, w, strides=[1, stride, stride, 1], padding='VALID')
    x = tf.nn.bias_add(x, b)
    return tf.nn.relu(x)
    
def maxpool2d(x, k=2, stride=2):
    return tf.nn.max_pool(x, ksize=[1, k, k, 1], strides=[1, stride, stride, 1], padding='VALID')

def one_hot_encode(x):
    return tf.one_hot(x, n_classes)

def LeNet(x, dropout_prob):    
    # Arguments used for tf.truncated_normal, randomly defines variables for the weights and biases for each layer
    with tf.name_scope("Params"):
        mu = 0
        sigma = 0.1

        weights = {"wc1": tf.Variable(tf.truncated_normal(shape=(5, 5, 1, 6), mean=mu, stddev=sigma)),
                   "wc2": tf.Variable(tf.truncated_normal(shape=(5, 5, 6, 16), mean=mu, stddev=sigma)),
                   "wd1": tf.Variable(tf.truncated_normal(shape=(5*5*16, 120), mean=mu, stddev=sigma)),
                   "wd2": tf.Variable(tf.truncated_normal(shape=(120, 84), mean=mu, stddev=sigma)),
                   "out": tf.Variable(tf.truncated_normal(shape=(84, n_classes), mean=mu, stddev=sigma))}

        biases = {"bc1": tf.Variable(tf.zeros([6])),
                 "bc2": tf.Variable(tf.zeros([16])),
                 "bd1": tf.Variable(tf.zeros([120])),
                 "bd2": tf.Variable(tf.zeros([84])),
                 "out": tf.Variable(tf.zeros([n_classes]))}
    
    # Layer 1: Convolutional. Input = 32x32x3. Output = 28x28x6.
    # Activation.
    with tf.name_scope("Conv1"):
        conv1 = conv2d(x, weights["wc1"], biases["bc1"])
    # Pooling. Input = 28x28x6. Output = 14x14x6.
    with tf.name_scope("Maxpooling1"):
        conv1 = maxpool2d(conv1)
    
    # Layer 2: Convolutional. Output = 10x10x16.
    # Activation.
    with tf.name_scope("Conv2"):
        conv2 = conv2d(conv1, weights["wc2"], biases["bc2"])
    # Pooling. Input = 10x10x16. Output = 5x5x16.
    
    with tf.name_scope("Maxpooling2"):
        conv2 = maxpool2d(conv2)
    
    # Flatten. Input = 5x5x16. Output = 400.
    with tf.name_scope("Flatten"):
        fc1 = flatten(conv2)
    # Layer 3: Fully Connected. Input = 400. Output = 120.
    with tf.name_scope("FC1"):
        fc1 = tf.add(tf.matmul(fc1, weights["wd1"]), biases["bd1"])
    # Activation.
    with tf.name_scope("FC1-Activation"):
        fc1 = tf.nn.relu(fc1)
        fc1 = tf.nn.dropout(fc1, dropout_prob)
    # Layer 4: Fully Connected. Input = 120. Output = 84.
    with tf.name_scope("FC2"):
        fc2 = tf.add(tf.matmul(fc1, weights["wd2"]), biases["bd2"])
    # Activation.
    with tf.name_scope("FC2-Activation"):
        fc2 = tf.nn.relu(fc2)
        fc2 = tf.nn.dropout(fc2, dropout_prob)
    # Layer 5: Fully Connected. Input = 84. Output = 43.
    with tf.name_scope("Output-layer"):
        logits = tf.add(tf.matmul(fc2, weights["out"]), biases["out"])
    return logits<jupyter_output><empty_output><jupyter_text>Question 3_What does your final architecture look like? (Type of model, layers, sizes, connectivity, etc.)  For reference on how to build a deep neural network using TensorFlow, see [Deep Neural Network in TensorFlow](https://classroom.udacity.com/nanodegrees/nd013/parts/fbf77062-5703-404e-b60c-95b78b2f3f9e/modules/6df7ae49-c61c-4bb2-a23e-6527e69209ec/lessons/b516a270-8600-4f93-a0a3-20dfeabe5da6/concepts/83a3a2a2-a9bd-4b7b-95b0-eb924ab14432) from the classroom._ **Answer:** I used the LeNet-5 architecture that I built in a previous lab in class room with parameters, weights and biases optimized for traffic sign classifier project. It has 2 convolution layers each one followed by a max-pooling/subsampling. Then it has 3 fully connected layers with 43 output classes. I have used ReLu as activation function. Here is how each layer transforms data. - **RGB2Gray:** Convert all images to gray, so transforming data from [?, 32, 32, 3] to [?, 32, 32, 1]- **conv1:** Takes input [?, 32, 32, 1] images and transforms it to [?, 28, 28, 6]. Size of W for this layer is [5, 5, 1, 6] and size of bias is [6]. Stride is 1 and padding type is 'VALID'.- **max-pooling1:** It transforms each [28, 28, 6] image to [14, 14, 6]. Filter size is [2,2] and stride is 2 with 'VALID' padding- **conv2:** Takes input [?, 14, 14, 6] images and transforms it to [?, 10, 10, 16]. Size of W for this layer is [5, 5, 6, 16] and size of bias is [16]. Stride is 1 and padding type is 'VALID'.- **max-pooling2:** It transforms each [10, 10, 16] image to [5, 5, 16]. Filter size is [2,2] and stride is 2 with 'VALID' padding- **Flatten Data:** Now flatten the data to 1-D form of [batch_size, 5x5x16].- **FC1:** Takes input [?, 5x5x16], applies weights of size [5x5x16, 120] and produces output of [?, 120]- **FC2:** Takes input [?, 120], applies weights of size [120, 84] and produces output of [?, 84]- **Output:** Takes input [?, 84], applies weights of size [84, 43] and produces output of [?, 43] where 43 is the number of unique classes we have.  **Visualization of the Network**<jupyter_code>### Train your model here.
### Feel free to use as many code cells as needed.

learning_rate = 0.001
EPOCHS = 15
BATCH_SIZE = 120
DROPOUT_PROB_VALUE = 0.75

with tf.name_scope("input"):
    x = tf.placeholder(tf.float32, (None, 32, 32, 3))
    x_gray = tf.image.rgb_to_grayscale(x)
    y = tf.placeholder(tf.int32, (None))
    one_hot_y = tf.one_hot(y, n_classes)
    dropout_prob = tf.placeholder(tf.float32)

logits = LeNet(x_gray, dropout_prob)
with tf.name_scope('cost'):
    cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits, one_hot_y))
# tf.summary.scalar('cost', cost)

with tf.name_scope("Optimizer"):
    optimizer = tf.train.AdamOptimizer(learning_rate = learning_rate).minimize(cost)

with tf.name_scope("Correct-Prediction"):
    correct_prediction = tf.equal(tf.argmax(logits, 1), tf.argmax(one_hot_y, 1))
with tf.name_scope('accuracy'):
    accuracy_operation = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
tf.summary.scalar('accuracy', accuracy_operation)

saver = tf.train.Saver()
merged = tf.summary.merge_all()
def evaluate_model_on_data(x_data, y_data, batch_size, dropout_prob):
    n_examples = len(x_data)
    print('validation examples count: ', n_examples)
    session = tf.get_default_session()
    total_accuracy = 0
    
    for i in range(0, n_examples, batch_size):
        batch_x, batch_y = x_data[i:i + batch_size], y_data[i:i + batch_size]
        
        accuracy = session.run(accuracy_operation, feed_dict={x: batch_x, y: batch_y})
        total_accuracy += (accuracy * len(batch_x))
        
    return total_accuracy / n_examples
with tf.Session() as session:
    session.run(tf.global_variables_initializer())
    summary_writer = tf.summary.FileWriter('logs/test', session.graph)
    num_examples = len(X_train)
    
    print("Training...")
    print()
    
    for epoch in range(EPOCHS):
        #shuffling data for each epoch so that model is 
        #trained of different order of data and is not
        #biased toward any specific order of data
        X_train, y_train = shuffle(X_train, y_train)
        
        for offset in range(0, num_examples, BATCH_SIZE):
            x_batch, y_batch = X_train[offset:offset + BATCH_SIZE], y_train[offset:offset + BATCH_SIZE]
            session.run(optimizer, feed_dict={x: x_batch , y: y_batch, dropout_prob: DROPOUT_PROB_VALUE})
            
            
#         validation_accuracy = evaluate_model_on_data(X_validation, y_validation, BATCH_SIZE)
        summary, validation_accuracy = session.run([merged, accuracy_operation], 
                                                   feed_dict={x: X_validation , y: y_validation, dropout_prob: 1.0})
        print("EPOCH {} ...".format(epoch + 1))
        print("Validation Accuracy = {:.3f}".format(validation_accuracy))
        print()
        summary_writer.add_summary(summary, epoch)
    
    test_accuracy = session.run(accuracy_operation, feed_dict={x: X_test, y: y_test, dropout_prob: 1.0})
    print("Test Accuracy = {:.3f}".format(test_accuracy))
    print()
        
    saver.save(session, 'traffic-sign-classifier.ckpt')
    print('Model saved')<jupyter_output><empty_output><jupyter_text>Question 4_How did you train your model? (Type of optimizer, batch size, epochs, hyperparameters, etc.)_ **Answer:** I used following parameter values during my training of model.- Optimizer: Adam- batch size: 200- epochs = 15- learning rate = 0.001- keep probability for dropout = 0.75- stddev=0.1 and mean=0 for Weights random generation from a normal distribution.   Question 5_What approach did you take in coming up with a solution to this problem? It may have been a process of trial and error, in which case, outline the steps you took to get to the final solution and why you chose those steps. Perhaps your solution involved an already well known implementation or architecture. In this case, discuss why you think this is suitable for the current problem._ **Answer:** I used LeNet architecture learned in class room and adapted it to this problem. LeNet has already been used to classify traffic signs and it showed excellent results. After applying LeNet code learned in classroom as it was I got about 93% accuracy on validation set.**Please discuss how did you choose the optimizer. (Missed Answer)**From my quick research on Adam Optimizer that I did when I first saw this algorithm being used in classroom lab for LeNet-5 I learned that it uses the concept of momentum (moving averages of parameters) to adapt the learning rate and it requires less hyper parameter fine tuning but the down side is it uses more memory and time. After looking at traffic sign data set count I thought my system will be good with Adam as optimizer and I have to do less hyper parameter fine tuning. That’s why Adam was my first choice. I also tried Stochastic Gradient Descent as well on the same parameters but it’s accuracy was low.**Please discuss how did you tell a convolutional layer is well suited for this problem. (Missed Answer)**As input data was images and no matter where in the image the traffic sign is we just need to classify it and translational information of the sign in the image is not important so CNN with weight sharing was an obvious choice. CNNs are well suited for images input and weight sharing is well suited when we need translation invariance. All convolutional layers were taken from LeNet-5 architecture from the lab with exactly same parameters (number of neurons/weights etc.) as I thought (also recommended in project notebook) it will be a good starting point. I only adapted the first convolutional layer parameters depth (from 1 to 3) and output layers output count (from 10 to 43) as those were different in this case. Although I did try different number of neurons, layers to check if I get significant improved accuracy.**Please discuss how did you choose the particular activation (Missed Answer)**Sigmoid and ReLu were the two options I knew of for classifying complex even non-linear data with simple derivatives. According to my research ReLu is more simple, more recent and works well so I simply used it. I did not even try sigmoid even though I think I should have just to see its accuracy.**Please discuss how did you tune the hyperparameter. (Missed Answer)**I picked all the initial hyper parameter values from classroom lab on LeNet-5 as a starting point. Then I experimented with them by changing each and looking at the accuracy I got on validation data set. For example I got a little bit improved accuracy when I set the batch_size = 150-200 or the learning rate=0.0001 or epochs=15. Results were better with batch size=150-200 (I did not tried above that), epochs=13-15 and learning rate=0.001I also added dropout regularization and tried different keep probs like 0.50, 0.70, 0.80 but the best results I got were on 0.75. When I realized that any information was not being lost even in gray scale mode and images were less noisy and more clear to predict so I converted images to gray and it gave a significant accuracy improvement. After combining all these I got a validation accuracy of almost 97% and test accuracy of 91%.  --- Step 3: Test a Model on New ImagesTake several pictures of traffic signs that you find on the web or around you (at least five), and run them through your classifier on your computer to produce example results. The classifier might not recognize some local signs but it could prove interesting nonetheless.You may find `signnames.csv` useful as it contains mappings from the class id (integer) to the actual sign name.  ImplementationUse the code cell (or multiple code cells, if necessary) to implement the first step of your project. Once you have completed your implementation and are satisfied with the results, be sure to thoroughly answer the questions that follow.<jupyter_code>### Load the images and plot them here.
### Feel free to use as many code cells as needed.
import cv2
import numpy as np
import matplotlib.image as mpimg

my_image1 = mpimg.imread('test-images/work.jpg')
my_image2 = mpimg.imread('test-images/yield-sign.jpg')
my_image3 = mpimg.imread('test-images/end-of-speed-limits.jpg')
my_image4 = mpimg.imread('test-images/traffic-signals.jpg')
my_image5 = mpimg.imread('test-images/turn-right.jpeg')

assert(my_image1.shape == (32, 32, 3))
print('My image shape: ', my_image1.shape)

my_test_images = np.array([my_image1, my_image2, my_image3, my_image4, my_image5])
my_test_labels = np.array([25, 13, 32, 26, 33])

# plt.imshow(cv2.cvtColor(my_image1, cv2.COLOR_RGB2GRAY), cmap='gray')
# plt.imshow(cv2.cvtColor(my_test_images[4], cv2.COLOR_RGB2GRAY), cmap='gray')
n_my_test_images = len(my_test_labels)
print('My test images count: ', n_my_test_images)

for index in range(len(my_test_labels)):
    plt.figure(figsize=(2, 2))
    plt.title('Image correct id: {} '.format(my_test_labels[index]))
    plt.imshow(cv2.cvtColor(my_test_images[index], cv2.COLOR_RGB2GRAY), cmap='gray')<jupyter_output><empty_output><jupyter_text>Question 6_Choose five candidate images of traffic signs and provide them in the report. Are there any particular qualities of the image(s) that might make classification difficult? It could be helpful to plot the images in the notebook._ **Answer:** I think some images are not universal so it might be a problem for model to identify. Also, I rescaled images manually and they are not smoothed out so that may affect the prediction of model.<jupyter_code>### Run the predictions here.
### Feel free to use as many code cells as needed.

# softmax_probs = tf.nn.softmax(logits)
predictions = tf.argmax(logits, 1)
with tf.Session() as session:
    saver.restore(session, tf.train.latest_checkpoint('.'))
    logits_values = session.run(predictions, feed_dict={x: my_test_images, dropout_prob: 1.0})
    my_test_accuracy = session.run(accuracy_operation, 
                                   feed_dict={x: my_test_images, y: my_test_labels, dropout_prob: 1.0})
    
    print('Correct ids: ', my_test_labels)
    print('Predicted Ids: ', logits_values)
    print("My test images Accuracy = {:.3f}".format(my_test_accuracy))
    print()<jupyter_output><empty_output><jupyter_text>Question 7_Is your model able to perform equally well on captured pictures when compared to testing on the dataset? The simplest way to do this check the accuracy of the predictions. For example, if the model predicted 1 out of 5 signs correctly, it's 20% accurate.__**NOTE:** You could check the accuracy manually by using `signnames.csv` (same directory). This file has a mapping from the class id (0-42) to the corresponding sign name. So, you could take the class id the model outputs, lookup the name in `signnames.csv` and see if it matches the sign from the image._ **Answer:** No, it gave me 60% accuracy on my collected images which is significantly less than what I obtained on validation and test sets. In fact, on some runs I got 40% accuracy.<jupyter_code>### Visualize the softmax probabilities here.
### Feel free to use as many code cells as needed.
softmax_probs = tf.nn.softmax(logits)
with tf.Session() as session:
    saver.restore(session, tf.train.latest_checkpoint('.'))
    softmax_prob_values = session.run(softmax_probs, feed_dict={x: my_test_images, dropout_prob: 1.0})
    top_values,ids = session.run(tf.nn.top_k(softmax_prob_values, k=4))
    print("Top 4 probabilitis for each prediction: ", np.around(top_values,3))
    print('Correct ids: ', my_test_labels)
    print("Top 4 ids for each prediction: ", ids)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.09547041091543709, 'fraction_numerical': 0.027209265429160717, 'mean_word_length': 4.327065286287767, 'pattern_counts': {'":': 10, '<': 40, '<?xml version=': 0, '>': 42, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 3, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '10', 'dir': 'jupyter-structured-clean-dedup', 'id': '556258', 'license': 'MIT', 'n_tokens_mistral': 7879, 'n_tokens_neox': 7326, 'n_words': 3000, 'path': 'Traffic_Sign_Classifier.ipynb', 'repo_name': 'informramiz/traffic-sign-classifier', 'size': '25212'}