I am trying to do transfer learning with InceptionV3 on the MNIST dataset.
The plan is to read in the MNIST dataset, resize the images, and then use these to train, like so:
import numpy as np
import os
import numpy as np
import matplotlib.pyplot as plt
from PIL import Image
import tensorflow.compat.v2 as tf
import tensorflow.compat.v1 as tfv1
from tensorflow.python.keras.applications import InceptionV3
tfv1.enable_v2_behavior()
print(tf.version.VERSION)
img_size = 299
def preprocess_tf_image(image, label):
image = tf.image.grayscale_to_rgb(image)
image = tf.image.resize(image, [img_size, img_size])
return image, label
#Acquire MNIST data
mnist = tf.keras.datasets.mnist
(x_train, y_train), (x_test, y_test) = mnist.load_data()
#Convert data to [0,1] range
x_train, x_test = x_train / 255.0, x_test / 255.0
#Add extra dimension to images so that they can be converted to RGB
x_train = x_train.reshape(x_train.shape[0], 28, 28, 1)
x_test = x_test.reshape (x_test.shape[0], 28, 28, 1)
x_train = tf.data.Dataset.from_tensor_slices((x_train, y_train))
x_test = tf.data.Dataset.from_tensor_slices((x_test, y_test))
#Convert images to RGB space and resize
x_train = x_train.map(preprocess_tf_image)
x_test = x_test.map(preprocess_tf_image)
img_shape = (img_size, img_size, 3)
#Get trained model, but leave off the head
base_model = InceptionV3(input_shape = img_shape, weights='imagenet', include_top=False)
base_model.trainable = False
#Make a model with a new head
model = tf.keras.Sequential([
base_model,
tf.keras.layers.GlobalAveragePooling2D(),
tf.keras.layers.Dropout(0.2),
tf.keras.layers.Dense(10, activation='softmax')
])
#Compile model
model.compile(
optimizer='adam', #tf.keras.optimizers.RMSprop(lr=BASE_LEARNING_RATE),
loss='binary_crossentropy',
metrics=['accuracy']
)
model.fit(x_train, epochs=5)
model.evaluate(x_test)
But, when I run this, things stop at model.fit() with the error:
ValueError: Error when checking input: expected inception_v3_input to have 4 dimensions, but got array with shape (299, 299, 3)
What's going on?
After you apply map to a dataset the response has no information about the batch size, you have to invoke the batch function to add it:
x_train = x_train.batch(batch_size = BATCH_SIZE) # adds batch size dimension to train dataset
x_test = x_test.batch(batch_size = BATCH_SIZE) # idem for test.
After that I could fully train and evaluate the model using Google's Colab as you can check here.
Related
I have read through the following discussion (not saying how to load pic to MNIST database)
MNIST trained network tested with my own samples
I also planning to train my own mnist by input img, but most of the tutorial doen't teach how to load our personal img (with answer, teach AI to reconize)
such as load all img "5" image into MNIST database, and teach them that number 5
how can we do so?
the following .py script is training by MNIST own database (credit by student_DC), then reconize, but accuracy result is not ideal (about 10%), so I come up training my samply img too, before doing the MNIST
but if I store the img on local file how to load them to MNIST model to train?
script after trained (both train and test from MNIST img databse) can load my own img to pridict
import keras
from keras.datasets import mnist
import matplotlib.pyplot as plt
import PIL
from PIL import Image
(train_images,train_labels),(test_images,test_labels) = mnist.load_data()
train_images.shape
len(train_labels)
train_labels
test_images.shape
len(test_labels)
test_labels
from keras import models
from keras import layers
network = models.Sequential()
network.add(layers.Dense(512,activation='relu',input_shape=(28*28,)))
network.add(layers.Dense(10,activation='softmax'))
network.compile(optimizer='rmsprop',
loss='categorical_crossentropy',
metrics=['accuracy'])
train_images = train_images.reshape((60000,28*28))
train_images = train_images.astype('float32')/255
test_images = test_images.reshape((10000,28*28))
test_images = test_images.astype('float32')/255
from keras.utils import to_categorical
train_labels = to_categorical(train_labels)
test_labels = to_categorical(test_labels)
network.fit(train_images,train_labels,epochs= 3 ,batch_size=128)
test_loss , test_acc = network.evaluate(test_images,test_labels)
print('test_acc:',test_acc)
network.save('m_lenet.h5')
#########
import numpy as np
from keras.models import load_model
import matplotlib.pyplot as plt
from PIL import Image
model = load_model('/content/m_lenet.h5')
picPath = '/content/02_a.png'
img = Image.open(picPath)
reIm = img.resize((28,28),Image.ANTIALIAS)
plt.imshow(reIm)
plt.savefig('/content/result.png')
im1 = np.array(reIm.convert("L"))
im1 = im1.reshape((1,28*28))
im1 = im1.astype('float32')/255
# predict = model.predict_classes(im1)
predict_x=model.predict(im1)
classes_x=np.argmax(predict_x,axis=1)
print ("---------------------------------")
print ('predict as:')
print (predict_x)
print ("")
print ("")
print ('predict number as:')
print (classes_x)
print ("---------------------------------")
print ("Original img : ")
the sample img screenshot:
by export suggestion:
to pass img to model.fit ,
that mine network.fit(train_images,train_labels,epochs= 3 ,batch_size=128) and let AI train my img logically can solve the problem
I am stocking on how to create an array of train images and an array of corresponding labels for now, I search online don't get similar tutorial (with topic: Training MNIST by loading my own img )
cridet by this site, seems this is what you what for loading your own img to train
https://blog.tanka.la/2018/10/28/build-the-mnist-model-with-your-own-handwritten-digits-using-tensorflow-keras-and-python/
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import Dropout
from keras.layers import Flatten
from keras.layers.convolutional import Conv2D
from keras.layers.convolutional import MaxPooling2D
from keras.optimizers import Adam
from keras.utils import np_utils
from PIL import Image
import numpy as np
import os
import matplotlib.pyplot as plt
# load data
(X_train, y_train), (X_test, y_test) = mnist.load_data()
# Reshaping to format which CNN expects (batch, height, width, channels)
X_train = X_train.reshape(X_train.shape[0], X_train.shape[1], X_train.shape[2], 1).astype('float32')
X_test = X_test.reshape(X_test.shape[0], X_test.shape[1], X_test.shape[2], 1).astype('float32')
# To load images to features and labels
def load_images_to_data(image_label, image_directory, features_data, label_data):
list_of_files = os.listdir(image_directory)
for file in list_of_files:
image_file_name = os.path.join(image_directory, file)
if ".png" in image_file_name:
img = Image.open(image_file_name).convert("L")
img = np.resize(img, (28,28,1))
im2arr = np.array(img)
im2arr = im2arr.reshape(1,28,28,1)
features_data = np.append(features_data, im2arr, axis=0)
label_data = np.append(label_data, [image_label], axis=0)
return features_data, label_data
# Load your own images to training and test data
X_train, y_train = load_images_to_data('1', '/content/01', X_train, y_train)
X_test, y_test = load_images_to_data('1', '/content/01', X_test, y_test)
# normalize inputs from 0-255 to 0-1
X_train/=255
X_test/=255
# one hot encode
number_of_classes = 10
y_train = np_utils.to_categorical(y_train, number_of_classes)
y_test = np_utils.to_categorical(y_test, number_of_classes)
# create model
model = Sequential()
model.add(Conv2D(32, (5, 5), input_shape=(X_train.shape[1], X_train.shape[2], 1), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Conv2D(32, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.5))
model.add(Flatten())
model.add(Dense(128, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(number_of_classes, activation='softmax'))
# Compile model
model.compile(loss='categorical_crossentropy', optimizer=Adam(), metrics=['accuracy'])
# Fit the model
model.fit(X_train, y_train, validation_data=(X_test, y_test), epochs=1, batch_size=200)
img = Image.open('/content/01/userlmn_01.png').convert("L")
plt.imshow(img)
img = np.resize(img, (28,28,1))
im2arr = np.array(img)
im2arr = im2arr.reshape(1,28,28,1)
# y_pred = model.predict_classes(im2arr)
predict_x=model.predict(im2arr)
classes_x=np.argmax(predict_x,axis=1)
print(classes_x)
I am trying to learn MNIST dataset with a simple dense layer using Keras.
I want my images to have the size of 16*16 instead of 28*28. I use many methods but they don't work. This is the simple dense network:
import keras
import numpy as np
import mnist
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
from tensorflow.keras.utils import to_categorical
train_images = mnist.train_images()
train_labels = mnist.train_labels()
test_images = mnist.test_images()
test_labels = mnist.test_labels()
# Normalize the images.
train_images = (train_images / 255) - 0.5
test_images = (test_images / 255) - 0.5
print(train_images.shape)
print(test_images.shape)
# Flatten the images.
train_images = train_images.reshape((-1, 784))
test_images = test_images.reshape((-1, 784))
print(train_images.shape)
print(test_images.shape)
# Build the model.
model = Sequential([
Dense(10, activation='softmax', input_shape=(784,)),
])
# Compile the model.
model.compile(
optimizer='adam',
loss='categorical_crossentropy',
metrics=['accuracy'],
)
# Train the model.
model.fit(
train_images,
to_categorical(train_labels),
epochs=5,
batch_size=32,
)
# Evaluate the model.
model.evaluate(
test_images,
to_categorical(test_labels)
)
# Save the model to disk.
model.save_weights('model.h5')
Try this method to resize all the images at once -
#!pip install --upgrade tensorflow
#Assuming you are using tensorflow 2
import numpy as np
import tensorflow as tf
#creating dummy images
imgs = np.stack([np.eye(28), np.eye(28)])
print(imgs.shape)
#Output - (2,28,28) 2 images of 28*28
imgt = imgs.transpose(1,2,0) #Bring the batch channel to the end (28,28,2)
imgs_resize = tf.image.resize(imgt, (16,16)).numpy() #apply resize (14,14,2)
imgs2 = imgs_resize.transpose(2,0,1) #bring the batch channel back to front (2,14,14)
print(imgs2.shape)
#Output - (2,16,16)
I'm trying to make my code recognize numbers using tensorflow for my school project. But I keep getting this error. Can someone help me with it? Thank you soo much!
Tried like flatten, changing the size etc but no vail...
Here are my code:
import tensorflow as tf
mnist = tf.keras.datasets.mnist
(x_train, y_train),(x_test, y_test) = mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0
model = tf.keras.models.Sequential([
tf.keras.layers.Flatten(input_shape=(28,28)),
tf.keras.layers.Dense(512, activation=tf.nn.relu),
tf.keras.layers.Dropout(0.2),
tf.keras.layers.Dense(10, activation=tf.nn.softmax)
])
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
model.fit(x_train, y_train, epochs=1)
model.evaluate(x_test, y_test)
# Part 3 - Making new predictions
import numpy as np
from keras.preprocessing import image
import keras
test_image = image.load_img('Number 8.jpg', target_size=(28, 28))
test_image = image.img_to_array(test_image)
test_image = np.expand_dims(test_image, axis=0)
result = model.predict(test_image)
print(np.argmax(result[0]))
Expected to be an array of 3
I think it is coming from this line
tf.keras.layers.Flatten(input_shape=(28,28)),
You can replace it with
tf.keras.layers.Flatten()
Even though your image is (28,28), when training there will be a batch dimension [batch_size, 28,28]. Since you do not pass batch size in model.fit a default value is used.
Im busy building an OCR with MNIST, Tensorflow and Keras but I am having problems uploading the MNIST datasets because of an error with in MNIST. Can I upload only the first few items with out setting of an error
Your question is not quite clear. However, below is how to load a data sample of MNIST using simple functions in TensorFlow and Keras.
1). To load part of MNIST with TensorFlow.
from tensorflow.examples.tutorials.mnist import input_data
data = input_data.read_data_sets('./tmp/mnist_data', one_hot = True)
data_slice = 3000
train_x = data.train.images[:data_slice,:]
train_y = data.train.labels[:data_slice,:]
test_x = data.test.images[:data_slice,:]
test_y = data.test.labels[:data_slice,:]
train_x.shape
'Output': (3000, 784)
2).To load part of MNIST with Keras.
import keras
# import dataset
(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data()
# flatten the features from 28*28 pixel to 784 wide vector
x_train = np.reshape(x_train, (-1, 784)).astype('float32')
x_test = np.reshape(x_test, (-1, 784)).astype('float32')
# one-hot encode the targets
y_train = keras.utils.to_categorical(y_train)
y_test = keras.utils.to_categorical(y_test)
data_slice = 3000
x_train = x_train[:data_slice,:]
y_train = y_train[:data_slice,:]
x_test = x_test[:data_slice,:]
y_test = y_test[:data_slice,:]
x_train.shape
'Output': (3000, 784)
y_train.shape
'Output': (3000, 10)
You can download the dataset manually from here and use what you need:
MNIST
(Attempt #2, see below for history)
I'm a total newbie with Deep Learning and Keras, and trying to play with the MNIST sample, following the tutorial at https://elitedatascience.com/keras-tutorial-deep-learning-in-python.
With regard to that sample, I just made some minimal adjustments to the code, to make it compatible with the latest API. Then, I added a sample Python script which loads the saved model and a BMP image file (specified as the script first argument), and outputs the class prediction in the form of an exit code.
I trained the model getting accuracy 0.9911, and saved it.
Yet, when testing with some BMP samples I get inconsistent results: only some of the digits are recognized correctly. Probably I'm missing something obvious in preprocessing my data. After Toyo's reply, I changed both the scripts, following https://nextjournal.com/schmudde/ml4a-mnist, so here I quote the newer versions. The older ones are at the bottom.
I also added a sample visualization of the preprocessed array representing an image, and looking at it I can see the digit, 'white on black', as expected (in the predict preprocessing I added color inversion by setting each value equal to 255-value, as my input BMP are 'black on white').
Yet, the issue is still there.
Thanks!
New Scripts
Training:
# numpy with a specific seed for reproducibility
import numpy as np
np.random.seed(123)
# keras
from keras.models import Sequential
from keras.layers import Dense, Dropout, Activation, Flatten
from keras.layers import Convolution2D, MaxPooling2D
from keras.utils import np_utils
from keras.datasets import mnist
# load pre-shuffled MNIST data into train and test sets
# MNIST: 60k samples of 28x28 grayscale (0-255) images,
# and additional 10k samples for test.
((x_train, y_train), (x_test, y_test)) = mnist.load_data()
n_train, height, width = x_train.shape
n_test, _, _ = x_test.shape
print('x_train shape: {}'.format(x_train.shape))
print('n_train: {}'.format(n_train))
print('height: {}'.format(height))
print('width: {}'.format(width))
print('n_test: {}'.format(n_test))
# we require shape (count, height, width, channel), where count
# is the count of our samples, and channel is the number of channels,
# here equal to 1 as these are grayscale images (for RGB it would be 3).
x_train = x_train.reshape(n_train, height, width, 1).astype('float32')
x_test = x_test.reshape(n_test, height, width, 1).astype('float32')
# normalize from [0, 255] to [0, 1]
x_train /= 255
x_test /= 255
# show image array
print('Sample array: {}\n'.format(x_train[0].shape))
print(x_train[0])
from matplotlib import pyplot as plt
plt.imshow(x_train[0].reshape(28, 28))
plt.show()
# the labels need to be converted into one-hot vectors,
# which are nc-element arrays (nc is the number of classes),
# which are 0 for all classes except 1 for the class the label
# is assigned to.
# convert integer labels into one-hot vectors
n_classes = 10
y_train = np_utils.to_categorical(y_train, n_classes)
y_test = np_utils.to_categorical(y_test, n_classes)
# define model architecture.
model = Sequential()
# number of convolutional filters
n_filters = 32
# convolution filter size
n_conv = 3
# pooling window size
n_pool = 2
# (1) convolution
model.add(Convolution2D(
n_filters,
kernel_size=(n_conv, n_conv),
# we have a 28x28 single channel (grayscale) image
# so the input shape should be (28, 28, 1)
input_shape=(height, width, 1)
))
model.add(Activation('relu'))
model.add(Convolution2D(n_filters, kernel_size=(n_conv, n_conv)))
model.add(Activation('relu'))
# apply pooling to summarize the features extracted thus far
model.add(MaxPooling2D(pool_size=(n_pool, n_pool)))
# (2) connected layers
model.add(Dropout(0.25))
# flatten the data for the 1D layers
model.add(Flatten())
# Dense(n_outputs)
model.add(Dense(128))
model.add(Activation('relu'))
model.add(Dropout(0.5))
# (3) the softmax output layer gives us a probablity for each class
model.add(Dense(n_classes))
model.add(Activation('softmax'))
model.compile(
loss='categorical_crossentropy',
optimizer='adam',
metrics=['accuracy']
)
# how many examples to look at during each update step
batch_size = 128
# how many times to run through the full set of examples
n_epochs = 10
model.fit(x_train,
y_train,
batch_size=batch_size,
epochs=n_epochs,
validation_data=(x_test, y_test))
# how'd we do?
loss, accuracy = model.evaluate(x_test, y_test, verbose=0)
print('loss:', loss)
print('accuracy:', accuracy)
# save the model. Use load_model(path) to load it later
model.save('/projects/python/mnist/mnist.h5')
Prediction:
# get the path to the image to be recognized from 1st arg
import sys
if len(sys.argv) < 2:
print('Missing image file path')
exit(-1)
# load the pretrained MNIST model
print('Loading model...')
import numpy as np
import keras
model = keras.models.load_model('/projects/python/mnist/mnist.h5')
# load the image ensuring that its size is 28x28
print('Loading image ' + sys.argv[1])
from keras.preprocessing import image
x = image.load_img(sys.argv[1], color_mode='grayscale', target_size=(28, 28))
# convert image to NumPy array
x = image.img_to_array(x, data_format='channels_last')
print('np from image:\n')
print(x.shape)
print(x)
# add a major dimension to represent the number of samples, i.e. 1
x = x.reshape(1, 28, 28, 1)
# convert data type to float32 and normalize 0-255 values to range [0, 1]
x = x.astype('float32')
# invert colors, we need white on black
x = 255 - x
x /= 255
print('np before predicting:\n')
print(x.shape)
print(x)
from matplotlib import pyplot as plt
plt.imshow(x.reshape(28, 28))
plt.show()
# predict
classes = model.predict_classes(x)
print(classes[0])
exit(classes[0])
Old scripts
# numpy with a specific seed for reproducibility
import numpy as np
np.random.seed(123)
from keras.models import Sequential
from keras.layers import Dense, Dropout, Activation, Flatten
from keras.layers import Convolution2D, MaxPooling2D
from keras.utils import np_utils
from keras.datasets import mnist
from matplotlib import pyplot as plt
# load pre-shuffled MNIST data into train and test sets
# 60k samples of 28x28 images
((x_train, y_train), (x_test, y_test)) = mnist.load_data()
print(x_train.shape)
plt.imshow(x_train[0])
input("Press enter to continue...")
# preprocess input data, as Theano requires explicit depth:
# from shape (n, width, height) to (n, depth=1, width, height)
x_train = x_train.reshape(x_train.shape[0], 1, 28, 28)
x_test = x_test.reshape(x_test.shape[0], 1, 28, 28)
# convert our data type to float32 and normalize our data values to the range [0, 1]
x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
x_train /= 255
x_test /= 255
# convert 1-dimensional class arrays (with values 0-9)
# to 10-dimensional class matrices (with values 0-1)
y_train = np_utils.to_categorical(y_train, 10)
y_test = np_utils.to_categorical(y_test, 10)
# define model architecture
model = Sequential()
# input_shape is the shape of each single parameter:
# here it is depth=1, width=28, height=28
# 32 convolution filters
# 3 rows in each convolution kernel
# 3 cols in each convolution kernel
model.add(Convolution2D(32, (3, 3), activation='relu', input_shape=(1, 28, 28), data_format="channels_first"))
model.add(Convolution2D(32, (3, 3), activation='relu', data_format="channels_first"))
# reduce the model's parameters by sliding a 2x2 pooling filter
# across the previous layer and taking the max of the 4 values in the 2x2 filter
model.add(MaxPooling2D(pool_size=(2,2)))
# regularize the model to prevent overfitting
model.add(Dropout(0.25))
# flatten (make 1-dimensional)
model.add(Flatten())
# dense: 128=output size of the layer
model.add(Dense(128, activation='relu'))
model.add(Dropout(0.5))
# final layer has size 10 for the 10 digits
model.add(Dense(10, activation='softmax'))
# compile model (loss function and optimizer)
model.compile(loss='categorical_crossentropy',
optimizer='adam',
metrics=['accuracy'])
# fit model on training data
model.fit(x_train, y_train,
batch_size=32, nb_epochs=10, verbose=1)
# evaluate model on test data
score = model.evaluate(x_test, y_test, verbose=0)
# save the model. Use load_model(path) to load it later
model.save('/projects/python/mnist/mnist.h5')
The consuming script:
# get the path to the image to be recognized from 1st arg
import sys
if len(sys.argv) < 2:
print('Missing image file path')
exit(-1)
# load the pretrained MNIST model
print('Loading model...')
import numpy as np
import keras
model = keras.models.load_model('/projects/python/mnist/mnist.h5')
# load the image ensuring that its size is 28x28
print('Loading image ' + sys.argv[1])
from keras.preprocessing import image
x = image.load_img(sys.argv[1], color_mode='grayscale', target_size=(28, 28))
# convert image to NumPy array
x = image.img_to_array(x, data_format='channels_first')
# add a major dimension to represent the number of samples, i.e. 1
x = x.reshape(1, 1, 28, 28)
# convert data type to float32 and normalize 0-255 values to range [0, 1]
x = x.astype('float32')
x /= 255
print(x.shape)
print(x)
# evaluate
classes = model.predict_classes(x)
print(classes[0])
exit(classes[0])