'Training a Machine Learning model on a custom dataset. How do I do it?
I followed the Machine Learning Crash Course from Google and saw they trained a model to predict cats and dogs, so i decided that would be a good starting point (https://colab.research.google.com/github/google/eng-edu/blob/main/ml/pc/exercises/image_classification_part3.ipynb?utm_source=practicum-IC&utm_campaign=colab-external&utm_medium=referral&hl=ro&utm_content=imageexercise3-colab#scrollTo=lRjyAkE62aOG). My dataset contains multiple pictures from inside a bar that frames 4 tables which I labelled as being busy or available. I would like to train a model to feed it a picture and tell me which of the 4 tables are busy or available.
import os
from tensorflow.keras import layers
from tensorflow.keras import Model
import tensorflow as tf
from tensorflow.keras.applications.inception_v3 import InceptionV3
local_weights_file = 'inception_v3_weights_tf_dim_ordering_tf_kernels_notop.h5'
pre_trained_model = InceptionV3(
input_shape=(150, 150, 3), include_top=False, weights=None)
pre_trained_model.load_weights(local_weights_file)
for layer in pre_trained_model.layers:
layer.trainable = False
last_layer = pre_trained_model.get_layer('mixed7')
print('last layer output shape:', last_layer.output_shape)
last_output = last_layer.output
from tensorflow.keras.optimizers import RMSprop
import keras
# Flatten the output layer to 1 dimension
x = layers.Flatten()(last_output)
# Add a fully connected layer with 1,024 hidden units and ReLU activation
x = layers.Dense(1024, activation='relu')(x)
# Add a dropout rate of 0.2
x = layers.Dropout(0.2)(x)
# Add a final sigmoid layer for classification
x = layers.Dense(1, activation='sigmoid')(x)
# Configure and compile the model
model = Model(pre_trained_model.input, x)
model.compile(loss='binary_crossentropy',
optimizer=RMSprop(lr=0.0001),
metrics=['acc'])
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from custom_generator import *
# Define our example directories and files
base_dir = 'imagini'
train_dir = os.path.join(base_dir, 'train')
validation_dir = os.path.join(base_dir, 'validation')
train_df = xml_to_csv(train_dir)
val_df = xml_to_csv(validation_dir)
col=[]
for index, row in train_df.iterrows():
val = {'xmin': train_df.at[index,'xmin'],
'ymin': train_df.at[index,'ymin'],
'xmax': train_df.at[index,'xmax'],
'ymax': train_df.at[index,'ymax']}
col.append(val)
train_df["coordinates"] = col
train_df['class'] = pd.factorize(train_df['class'])[0]
col_1 = []
for index, row in val_df.iterrows():
val = {'xmin':val_df.at[index,'xmin'],
'ymin':val_df.at[index,'ymin'],
'xmax':val_df.at[index,'xmax'],
'ymax':val_df.at[index,'ymax']}
col_1.append(val)
val_df["coordinates"] = col_1
val_df['class'] = pd.factorize(val_df['class'])[0]
#val_df['class'] = np.asarray(val_df['class']).astype('float32').reshape((-1,1))
os.chdir(train_dir)
train_generator = CustomDataGen(train_df,
X_col = {'path': 'filename', 'bbox' : 'coordinates'},
y_col = {'name': 'class'},
batch_size = 20)
os.chdir('C:\\Users\\Alex\\Desktop\\LICENTa\\ML MODEL\\imagini\\validation\\')
validation_generator = CustomDataGen(val_df,
X_col = {'path': 'filename', 'bbox' : 'coordinates'},
y_col = {'name': 'class'},
batch_size = 20)
os.chdir("C:\\Users\\Alex\\Desktop\\LICENTa\\ML MODEL")
history = model.fit_generator(
train_generator,
steps_per_epoch=100,
epochs=2,
validation_data=validation_generator,
validation_steps=50,
verbose=2)
I also made the function 'xml_to_csv' to put my data in DataFrame and a custom generator that looks like this:
def xml_to_csv(path):
xml_list = []
for xml_file in glob.glob(path + '/*.xml'):
tree = ET.parse(xml_file)
root = tree.getroot()
filename = root.find('filename').text
width = int(root.find('size').find('width').text)
height = int(root.find('size').find('height').text)
for member in root.findall('object'):
bndbox = member.find('bndbox')
value = (os.path.join(path, filename),
width,
height,
member.find('name').text,
int(bndbox.find('xmin').text),
int(bndbox.find('ymin').text),
int(bndbox.find('xmax').text),
int(bndbox.find('ymax').text),
)
xml_list.append(value)
column_name = ['filename', 'width', 'height',
'class', 'xmin', 'ymin', 'xmax', 'ymax']
xml_df = pd.DataFrame(xml_list, columns=column_name)
return xml_df
#train_df = xml_to_csv("imagini\\train")
#print(train_df)
class CustomDataGen(tf.keras.utils.Sequence):
def __init__(self, df, X_col, y_col, batch_size, input_size=(150, 150, 3), shuffle=True):
self.df = df.copy()
self.X_col = X_col
self.y_col = y_col
self.batch_size = batch_size
self.input_size = input_size
self.shuffle = shuffle
self.n = len(self.df)
self.n_class = df[y_col['name']].nunique()
def on_epoch_end(self):
if self.shuffle:
self.df = self.df.sample(frac=1).reset_index(drop=True)
def __get_input(self, path, bbox, target_size):
xmin, ymin, xmax, ymax = bbox['xmin'], bbox['ymin'], bbox['xmax'], bbox['ymax']
image = tf.keras.preprocessing.image.load_img(path)
image_arr = tf.keras.preprocessing.image.img_to_array(image)
image_arr = image_arr[ymin:ymax, xmin:xmax]
image_arr = tf.image.resize(image_arr,(target_size[0], target_size[1])).numpy()
#image_arr = np.array(image_arr)
return image_arr/255.
def __get_output(self, label, num_classes):
return tf.keras.utils.to_categorical(label, num_classes=num_classes)
def __get_data(self, batches):
# Generates data containing batch_size samples
path_batch = batches[self.X_col['path']]
bbox_batch = batches[self.X_col['bbox']]
name_batch = batches[self.y_col['name']]
X_batch = np.asarray([self.__get_input(x, y, self.input_size) for x, y in zip(path_batch, bbox_batch)])
y0_batch = np.asarray([self.__get_output(y, self.n_class) for y in name_batch])
return X_batch, [y0_batch]
def __getitem__(self, index):
batches = self.df[index * self.batch_size:(index + 1) * self.batch_size]
X, y = self.__get_data(batches)
return X, y
def __len__(self):
return self.n // self.batch_size
When training I am geting an error:
AttributeError: 'tuple' object has no attribute 'shape'
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
