diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..12c201f --- /dev/null +++ b/Makefile @@ -0,0 +1,42 @@ +.PHONY: help + +VENV_NAME?=env +PYTHON=${VENV_NAME}/bin/python3 + +.DEFAULT: help +help: + @echo "make env" + @echo " create and prepares the environment" + @echo "make clean" + @echo " clean the development environment" + @echo "make data" + @echo " download and unpack the data" + @echo "make lint" + @echo " run pylint and mpy" + +data: images +images: + wget https://s3.us-east-2.amazonaws.com/naturalimages02/images.tar.gz + tar -xzf images.tar.gz + +env: $(VENV_NAME)/bin/activate images +$(VENV_NAME)/bin/activate: + test -d $(VENV_NAME) || python3 -m venv $(VENV_NAME) + ${PYTHON} -m pip install -U pip + ${PYTHON} -m pip install --upgrade tensorflow + ${PYTHON} -m pip install keras + ${PYTHON} -m pip install matplotlib + ${PYTHON} -m pip install keras_vggface + ${PYTHON} -m pip install pylint + ${PYTHON} -m pip install mypy + touch $(VENV_NAME)/bin/activate + +lint: + ${PYTHON} -m pylint --ignored-modules=tensorflow.keras linear_regression.py + +clean: + rm -rf $(VENV_NAME) + rm -rf images + rm -f images.tar.gz + rm -f fine_tune.h5 + rm -rf .mypy_cache \ No newline at end of file diff --git a/linear_regression.py b/linear_regression.py new file mode 100644 index 0000000..17aded6 --- /dev/null +++ b/linear_regression.py @@ -0,0 +1,36 @@ +""" +Simple linear regression application. + +Source: https://www.guru99.com/keras-tutorial.html +""" + +# import tensorflow.keras +from keras.models import Sequential +from keras.layers import Dense +import numpy as np +import matplotlib.pyplot as plt + +x = data = np.linspace(1,2,200) +y = x*4 + np.random.randn(*x.shape) * 0.3 + +model = Sequential() +model.add(Dense(1, input_dim=1, activation='linear')) + +model.compile(optimizer='sgd', loss='mse', metrics=['mse']) + +weights = model.layers[0].get_weights() +w_init = weights[0][0][0] +b_init = weights[1][0] +print('Linear regression model is initialized with weights w: %.2f, b: %.2f' % (w_init, b_init)) + +model.fit(x,y, batch_size=1, epochs=30, shuffle=False) + +weights = model.layers[0].get_weights() +w_final = weights[0][0][0] +b_final = weights[1][0] +print('Linear regression model is trained to have weight w: %.2f, b: %.2f' % (w_final, b_final)) + +predict = model.predict(data) + +plt.plot(data, predict, 'b', data , y, 'k.') +plt.show() diff --git a/prepare_train_model.py b/prepare_train_model.py new file mode 100644 index 0000000..64f9154 --- /dev/null +++ b/prepare_train_model.py @@ -0,0 +1,130 @@ +# Source: https://www.guru99.com/keras-tutorial.html + +#### Data preparation +from keras.preprocessing.image import ImageDataGenerator +import numpy as np +import matplotlib.pyplot as plt + +train_path = 'images/train/' +test_path = 'images/test/' +batch_size = 16 +image_size = 224 +num_class = 8 + +''' +The ImageDataGenerator will make an X_training data from a directory. +The sub-directory in that directory will be used as a class for each object. +The image will be loaded with the RGB color mode, with the categorical class +mode for the Y_training data, with a batch size of 16. Finally, shuffle the +data. +''' +train_datagen = ImageDataGenerator(validation_split=0.3, + shear_range=0.2, + zoom_range=0.2, + horizontal_flip=True) + +train_generator = train_datagen.flow_from_directory( + directory=train_path, + target_size=(image_size,image_size), + batch_size=batch_size, + class_mode='categorical', + color_mode='rgb', + shuffle=True) + +''' +Let's see our images randomly by plotting them with matplotlib +''' +x_batch, y_batch = train_generator.next() +fig=plt.figure() +columns = 4 +rows = 4 +for i in range(1, columns*rows): + num = np.random.randint(batch_size) + image = x_batch[num].astype(np.int) + fig.add_subplot(rows, columns, i) + plt.imshow(image) +plt.show() + +### Creating model +import keras +from keras.models import Model, load_model +from keras.layers import Activation, Dropout, Flatten, Dense +from keras.preprocessing.image import ImageDataGenerator +from keras.applications.vgg16 import VGG16 + +''' +Let's create our network model from VGG16 with imageNet pre-trained weight. +We will freeze these layers so that the layers are not trainable to help us +reduce the computation time. +''' + +# Load the VGG model +base_model = VGG16(weights='imagenet', include_top=False, input_shape=(image_size, image_size, 3)) + +print(base_model.summary()) + +# Freeze the layers +for layer in base_model.layers: + layer.trainable = False + +# Create the model +model = keras.models.Sequential() + +# Add the vgg convolutional base model +model.add(base_model) + +# Add new layers +model.add(Flatten()) +model.add(Dense(1024, activation='relu')) +model.add(Dense(1024, activation='relu')) +model.add(Dense(num_class, activation='softmax')) + +# Show a summary of the model. Check the number of trainable parameters +print(model.summary()) + +input("Press Enter to continue...") + +''' +As you can see, the summary of our network model. From an input from +VGG16 Layers, then we add 2 Fully Connected Layer which will extract 1024 +features and an output layer that will compute the 8 classes with the softmax +activation. +''' + +#### Training +# Compile the model +from keras.optimizers import SGD + +model.compile(loss='categorical_crossentropy', + optimizer=SGD(lr=1e-3), + metrics=['accuracy']) + +''' +# Start the training process +model.fit(x_train, y_train, validation_split=0.30, batch_size=32, epochs=50, verbose=2) + +# Save the model +model.save('catdog.h5') +''' + +history = model.fit_generator(train_generator, + steps_per_epoch=train_generator.n/batch_size, + epochs=10) + +model.save('fine_tune.h5') + +# summarize history for accuracy +import matplotlib.pyplot as plt + +plt.plot(history.history['loss']) +plt.title('loss') +plt.ylabel('loss') +plt.xlabel('epoch') +plt.legend(['loss'], loc='upper left') +plt.show() + +''' +As you can see, our losses are dropped significantly and the accuracy is +almost 100%. For testing our model, we randomly picked images over the internet +and put it on the test folder with a different class to test +''' \ No newline at end of file diff --git a/test_model.py b/test_model.py new file mode 100644 index 0000000..910aa3d --- /dev/null +++ b/test_model.py @@ -0,0 +1,66 @@ +import keras +from keras.models import Model, load_model +from keras.preprocessing.image import ImageDataGenerator +import matplotlib.pyplot as plt +import numpy as np + +train_datagen = ImageDataGenerator(validation_split=0.3, + shear_range=0.2, + zoom_range=0.2, + horizontal_flip=True) + +train_path = 'images/train/' +test_path = 'images/test/' +batch_size = 16 +image_size = 224 +num_class = 8 + +### Testing our model +model = load_model('fine_tune.h5') + +test_datagen = ImageDataGenerator() +train_generator = train_datagen.flow_from_directory( + directory=train_path, + target_size=(image_size,image_size), + batch_size=batch_size, + class_mode='categorical', + color_mode='rgb', + shuffle=True) + +test_generator = test_datagen.flow_from_directory( + directory=test_path, + target_size=(image_size, image_size), + color_mode='rgb', + shuffle=False, + class_mode='categorical', + batch_size=1) + +filenames = test_generator.filenames +nb_samples = len(filenames) + +fig=plt.figure() +columns = 4 +rows = 4 +for i in range(1, columns*rows -1): + x_batch, y_batch = test_generator.next() + + name = model.predict(x_batch) + name = np.argmax(name, axis=-1) + true_name = y_batch + true_name = np.argmax(true_name, axis=-1) + + label_map = (test_generator.class_indices) + label_map = dict((v,k) for k,v in label_map.items()) #flip k,v + predictions = [label_map[k] for k in name] + true_value = [label_map[k] for k in true_name] + + image = x_batch[0].astype(np.int) + fig.add_subplot(rows, columns, i) + plt.title(str(predictions[0]) + ':' + str(true_value[0])) + plt.imshow(image) +plt.show() + +''' +And our test is as given below! Only 1 image is predicted wrong from a test of +14 images! +''' \ No newline at end of file