<jupyter_start><jupyter_text>Train MobileNet Here, there is a small data set containing my up, down, left, right hand gesture.You can create your own hand gesture dataset by following below folder structure then zip it and upload a zip file to file hosting service such as Dropbox. Then get a shareable URL and replace it in wget command below.<jupyter_code># https://webcamera.io/
'''
pacman_dataset_v2
├── train
│   ├── 0_up
│   │   ├── Photo\ on\ 21-2-2562\ BE\ at\ 19.40\ #2.jpg
│   │   ├── Photo\ on\ 21-2-2562\ BE\ at\ 19.40\ #4.jpg
│   │   ├── Photo\ on\ 21-2-2562\ BE\ at\ 19.40\ #5.jpg
│   │   ├── Photo\ on\ 21-2-2562\ BE\ at\ 19.40.jpg
│   │   ├── Photo\ on\ 21-2-2562\ BE\ at\ 19.41\ #2.jpg
│   │   ├── Photo\ on\ 21-2-2562\ BE\ at\ 19.41\ #4.jpg
│   │   ├── Photo\ on\ 21-2-2562\ BE\ at\ 19.41\ #5.jpg
│   │   ├── Photo\ on\ 21-2-2562\ BE\ at\ 19.41\ #6.jpg
│   │   └── Photo\ on\ 21-2-2562\ BE\ at\ 19.41.jpg
│   ├── 1_down
│   │   ├── Photo\ on\ 21-2-2562\ BE\ at\ 19.43\ #2.jpg
│   │   ├── Photo\ on\ 21-2-2562\ BE\ at\ 19.43\ #4.jpg
│   │   ├── Photo\ on\ 21-2-2562\ BE\ at\ 19.43\ #5.jpg
│   │   ├── Photo\ on\ 21-2-2562\ BE\ at\ 19.43\ #6.jpg
│   │   ├── Photo\ on\ 21-2-2562\ BE\ at\ 19.43\ #7.jpg
│   │   ├── Photo\ on\ 21-2-2562\ BE\ at\ 19.44\ #2.jpg
│   │   ├── Photo\ on\ 21-2-2562\ BE\ at\ 19.44\ #3.jpg
│   │   └── Photo\ on\ 21-2-2562\ BE\ at\ 19.44.jpg
│   ├── 2_left
│   │   ├── Photo\ on\ 21-2-2562\ BE\ at\ 19.45\ #2.jpg
│   │   ├── Photo\ on\ 21-2-2562\ BE\ at\ 19.45\ #3.jpg
│   │   ├── Photo\ on\ 21-2-2562\ BE\ at\ 19.45\ #5.jpg
│   │   ├── Photo\ on\ 21-2-2562\ BE\ at\ 19.45\ #6.jpg
│   │   ├── Photo\ on\ 21-2-2562\ BE\ at\ 19.45\ #7.jpg
│   │   ├── Photo\ on\ 21-2-2562\ BE\ at\ 19.45.jpg
│   │   ├── Photo\ on\ 21-2-2562\ BE\ at\ 19.46\ #3.jpg
│   │   └── Photo\ on\ 21-2-2562\ BE\ at\ 19.46.jpg
│   └── 3_right
│       ├── Photo\ on\ 21-2-2562\ BE\ at\ 19.47\ #2.jpg
│       ├── Photo\ on\ 21-2-2562\ BE\ at\ 19.47\ #3.jpg
│       ├── Photo\ on\ 21-2-2562\ BE\ at\ 19.47\ #5.jpg
│       ├── Photo\ on\ 21-2-2562\ BE\ at\ 19.47\ #6.jpg
│       ├── Photo\ on\ 21-2-2562\ BE\ at\ 19.47\ #7.jpg
│       ├── Photo\ on\ 21-2-2562\ BE\ at\ 19.47\ #8.jpg
│       ├── Photo\ on\ 21-2-2562\ BE\ at\ 19.48\ #2.jpg
│       └── Photo\ on\ 21-2-2562\ BE\ at\ 19.48.jpg
└── val
    ├── 0_up
    │   ├── Photo\ on\ 21-2-2562\ BE\ at\ 19.40\ #3.jpg
    │   └── Photo\ on\ 21-2-2562\ BE\ at\ 19.41\ #3.jpg
    ├── 1_down
    │   ├── Photo\ on\ 21-2-2562\ BE\ at\ 19.43\ #3.jpg
    │   └── Photo\ on\ 21-2-2562\ BE\ at\ 19.43.jpg
    ├── 2_left
    │   ├── Photo\ on\ 21-2-2562\ BE\ at\ 19.45\ #4.jpg
    │   └── Photo\ on\ 21-2-2562\ BE\ at\ 19.46\ #2.jpg
    └── 3_right
        ├── Photo\ on\ 21-2-2562\ BE\ at\ 19.47\ #4.jpg
        └── Photo\ on\ 21-2-2562\ BE\ at\ 19.47.jpg
'''
!rm -rf dataset/* models/ model.zip
!mkdir -p dataset models
!wget -q 'https://www.dropbox.com/s/zkbytp247820n0j/pacman_dataset_v3.zip?dl=0' -O dataset/pacman_dataset_v2.zip
!cd dataset && unzip -q pacman_dataset_v2.zip
!pip install -q tensorflowjs
import tensorflowjs as tfjs

from tensorflow import keras
from tensorflow.keras.applications import MobileNet
from tensorflow.keras.layers import Dense,GlobalAveragePooling2D
from tensorflow.keras.models import Model
from tensorflow.keras.applications.mobilenet import preprocess_input
from tensorflow.keras.preprocessing.image import ImageDataGenerator

input_your_code = None
'''Define a base model from MobileNet without the network head
Transfer weights from MobileNet training from ImageNet dataset.
'''
base_model = MobileNet(
    weights='imagenet',
    input_shape=(224, 224, 3),
    include_top=False
)
x = base_model.output
x = GlobalAveragePooling2D()(x)

# Add dense layers so that the model can learn more complex functions and classify for better results.
# The first Dense layer here has 1024 outputs with ReLU activation
x = Dense(1024, activation='relu')(x)

# Dense layer 2 with 1024 outputs and ReLU activation
x = Dense(1024, activation='relu')(x)

# Dense layer 3 with 512 outputs and ReLU activation
x = Dense(512, activation='relu')(x)

# Final Dense layer with softmax activation, the number of class if 4
predictions = Dense(4, activation='softmax')(x)
# inputs is training set (number of training set, 224, 224, 3)
# outputs is the layers defined previously.
model=Model(
    inputs=base_model.input,
    outputs=predictions
)
# List of all layers.
# You can select which layers you want to freeze the weights.
for i, layer in enumerate(model.layers):
  print(i, layer.name)
# Freeze the first 20 layers
freeze_before_layer = 20
for i, layer in enumerate(model.layers[:freeze_before_layer]):
    layer.trainable=False
    print(i, layer.name)
# Update weights for the rest layers.
for i, layer in enumerate(model.layers[20:]):
    layer.trainable=True
    print(i + freeze_before_layer, layer.name)
model.summary()
# See more parameters: https://keras.io/preprocessing/image/
# Adjust data augmentation here:
train_datagen = ImageDataGenerator(
    preprocessing_function=preprocess_input,
    rotation_range=2,
    shear_range=0.1,
    zoom_range=0.2
)
!ls dataset
# Generate training set from pacman_dataset_v2.
# Adjust batch size here depending on number of samples and GPU memory.
train_generator=train_datagen.flow_from_directory(
    'dataset/pacman_dataset_v3/train',
    target_size=(224, 224),
    color_mode='rgb',
    batch_size=12,
    class_mode='categorical'
)
# Generate validation set from pacman_dataset_v2
validation_datagen = ImageDataGenerator(preprocessing_function=preprocess_input)
validation_generator = validation_datagen.flow_from_directory(
    directory='dataset/pacman_dataset_v3/val',
    target_size=(224, 224),
    color_mode="rgb",
    batch_size=1,
    class_mode="categorical"
)
'''Create TensorFlow model graph.
Adam is similar to stochastic gradient descent but it is automatically adjust
learning rate.
'''
model.compile(
    optimizer='Adam',
    loss=keras.losses.categorical_crossentropy,
    metrics=['accuracy']
)
# Step size depends on your batch size, 1 epoch should run through all samples.
step_size_train = train_generator.n // train_generator.batch_size
step_size_validation = validation_generator.n // validation_generator.batch_size

# Run training and validation
model.fit_generator(
    generator=train_generator,
    steps_per_epoch=step_size_train,
    epochs=1,
    validation_data=validation_generator,
    validation_steps=step_size_validation
)
# Convert a model to TensorFlow.js JSON format
tfjs.converters.save_keras_model(model, 'models/')
# group1-shard\*of\* are collection of binary weight files
!ls -lh models
'''Currently, TensorFlow.js model conversion does not compatible with ReLU6.
"max_value": {"type": "ndarray", "value": 6.0} in model.js need to be replaced
by "max_value": 6
Reference: https://github.com/tensorflow/tfjs/issues/908
'''
!sed -i 's/{"type": "ndarray", "value": 6.0}/6/g' models/model.json
!zip -q -r model.zip models
# Uncomment these lines and run to download model files
from google.colab import files

files.download('model.zip')
from google.colab import drive
drive.mount('/content/gdrive')
!mkdir /content/gdrive/My\ Drive/models
!cp model.zip /content/gdrive/My\ Drive/models/<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.1519352182267362, 'fraction_numerical': 0.08083996706011529, 'mean_word_length': 2.9906900328587076, 'pattern_counts': {'":': 6, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 4, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '1', 'dir': 'jupyter-structured-clean-dedup', 'id': '35882', 'license': 'MIT', 'n_tokens_mistral': 3254, 'n_tokens_neox': 2834, 'n_words': 880, 'path': 'day12/Lab/lab10-problem4-mobilenet-training.ipynb', 'repo_name': 'WhatTheFar/practical-ai-bootcamp', 'size': '7286'}