<jupyter_start><jupyter_text>Arabic Font ClassificationAuthor: <NAME>Date: 18-7-2020  Ensure Reproducibility<jupyter_code>import tensorflow as tf
assert tf.__version__ == '2.2.0'
!pip install tensorflow-determinism
import numpy as np
import random as rn
import os

rn.seed(42)
np.random.seed(42)
tf.random.set_seed(42)
rng = tf.random.experimental.Generator.from_seed(1234)

os.environ['TF_DETERMINISTIC_OPS'] = '1'
os.environ['PYTHONHASHSEED']=str(0)
# os.environ['CUDA_VISIBLE_DEVICES'] = ''<jupyter_output><empty_output><jupyter_text>Fetch and load data<jupyter_code>!wget 'https://github.com/mhmoodlan/arabic-font-classification/releases/download/v0.1.0/rufa.tar.gz' && tar -xzf '/content/rufa.tar.gz'
print('# of real Ruqaa images: ', len(os.listdir('/content/rufa/real/ruqaa/')))
print('# of real Farsi images: ', len(os.listdir('/content/rufa/real/farsi/')))
print('# synthesized Ruqaa: ', len(os.listdir('/content/rufa/synth/ruqaa/')))
print('# synthesized Farsi: ', len(os.listdir('/content/rufa/synth/farsi/')))
from pathlib import Path

synth_dir = Path('/content/rufa/synth')
real_dir = Path('/content/rufa/real')

CLASS_NAMES = np.array([item.name for item in real_dir.glob('*')])
CLASS_NAMES
synth_paths = tf.data.Dataset.list_files(str(synth_dir / '*/*.jpg'), seed=42)
real_paths = tf.data.Dataset.list_files(str(real_dir / '*/*.jpg'), seed=42)<jupyter_output><empty_output><jupyter_text>Train, val, mismatch, test split<jupyter_code>_max_data_size = 2**np.int('32')
_test_ratio = '0.2'


def test_set_check(item):
    id = tf.strings.split(tf.strings.split(item, os.sep)[-1], '.')[0]
    hash = tf.strings.to_hash_bucket_fast(id, _max_data_size)
    return tf.cast(hash, tf.float64) < float(_test_ratio) * _max_data_size

def train_set_check(item):
    id = tf.strings.split(tf.strings.split(item, os.sep)[-1], '.')[0]
    hash = tf.strings.to_hash_bucket_fast(id, _max_data_size)
    return tf.cast(hash, tf.float64) >= float(_test_ratio) * _max_data_size
train_paths = synth_paths.filter(train_set_check)
val_paths = synth_paths.filter(test_set_check)
mismatch_paths = real_paths.filter(test_set_check)
test_paths = real_paths.filter(train_set_check)<jupyter_output><empty_output><jupyter_text>Preprocessing<jupyter_code>AUTOTUNE = tf.data.experimental.AUTOTUNE
BATCH_SIZE = 32
mapping = {0: 'farsi', 1: 'ruqaa'}

def prepare_for_training(ds, cache=True, shuffle_buffer_size=1000):
  if cache:
    if isinstance(cache, str):
      ds = ds.cache(cache)
    else:
      ds = ds.cache()

  ds = ds.shuffle(buffer_size=shuffle_buffer_size, seed=42)
  ds = ds.batch(BATCH_SIZE)
  ds = ds.prefetch(buffer_size=AUTOTUNE)

  return ds

def parse_image(data_instance):
  parts = tf.strings.split(data_instance, os.sep)
  label = tf.cast(tf.argmax(tf.cast(parts[-2] == np.array(list(mapping.values())), dtype=tf.float16)), tf.float16)

  image = tf.io.read_file(data_instance)
  image = tf.image.decode_jpeg(image, 1)
  image = tf.image.convert_image_dtype(image, tf.float32)

  if parts[-3] == 'synth':
    noise = rng.normal(shape=tf.shape(image), mean=0.0, stddev=0.015, dtype=tf.float32)
    image = tf.add( image, noise)
    image = tf.clip_by_value(image, 0.0, 1.0)

    image = tf.image.adjust_jpeg_quality(image, 90)

  return image, label
train_ds = train_paths.map(parse_image)
val_ds = val_paths.map(parse_image)
mismatch_ds = mismatch_paths.map(parse_image)
full_train_ds = train_ds.concatenate(val_ds.concatenate(mismatch_ds))
test_ds = test_paths.map(parse_image)

train_ds = prepare_for_training(train_ds)
val_ds = prepare_for_training(val_ds)
mismatch_ds = prepare_for_training(mismatch_ds)
full_train_ds = prepare_for_training(full_train_ds)
test_ds = prepare_for_training(test_ds)<jupyter_output><empty_output><jupyter_text>Model<jupyter_code>def cnn(input_shape, output_shape):
    num_classes = output_shape[0]
    dropout_seed = 708090
    kernel_seed = 42
  
    model = tf.keras.models.Sequential([
      tf.keras.layers.Conv2D(16, 3, activation='relu', input_shape=input_shape, kernel_initializer=tf.keras.initializers.GlorotUniform(seed=kernel_seed)),
      tf.keras.layers.MaxPooling2D(),
      tf.keras.layers.Dropout(0.1, seed=dropout_seed),
      tf.keras.layers.Conv2D(32, 5, activation='relu', kernel_initializer=tf.keras.initializers.GlorotUniform(seed=kernel_seed)),
      tf.keras.layers.MaxPooling2D(),
      tf.keras.layers.Dropout(0.1, seed=dropout_seed),
      tf.keras.layers.Conv2D(64, 10, activation='relu', kernel_initializer=tf.keras.initializers.GlorotUniform(seed=kernel_seed)),
      tf.keras.layers.MaxPooling2D(),
      tf.keras.layers.Dropout(0.1, seed=dropout_seed),
      tf.keras.layers.Flatten(),
      tf.keras.layers.Dense(128, activation='relu', kernel_regularizer='l2', kernel_initializer=tf.keras.initializers.GlorotUniform(seed=kernel_seed)),
      tf.keras.layers.Dropout(0.2, seed=dropout_seed),
      tf.keras.layers.Dense(16, activation='relu', kernel_regularizer='l2', kernel_initializer=tf.keras.initializers.GlorotUniform(seed=kernel_seed)),
      tf.keras.layers.Dropout(0.2, seed=dropout_seed),
      tf.keras.layers.Dense(num_classes, activation='sigmoid', kernel_initializer=tf.keras.initializers.GlorotUniform(seed=kernel_seed))
    ])

    return model
epochs = 6
callbacks = None
model = cnn((100, 100, 1), (1,))
model.compile(loss=tf.keras.losses.BinaryCrossentropy(from_logits=False), optimizer='Adam', metrics='accuracy')
model.summary()<jupyter_output>Model: "sequential_2"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d_6 (Conv2D)            (None, 98, 98, 16)        160       
_________________________________________________________________
max_pooling2d_6 (MaxPooling2 (None, 49, 49, 16)        0         
_________________________________________________________________
dropout_10 (Dropout)         (None, 49, 49, 16)        0         
_________________________________________________________________
conv2d_7 (Conv2D)            (None, 45, 45, 32)        12832     
_________________________________________________________________
max_pooling2d_7 (MaxPooling2 (None, 22, 22, 32)        0         
_________________________________________________________________
dropout_11 (Dropout)         (None, 22, 22, 32)        0         
______________________________________________________[...]<jupyter_text>Training and evaluation  Load pretrained weights, or...<jupyter_code>!wget 'https://raw.githubusercontent.com/mhmoodlan/arabic-font-classification/master/codebase/code/font_classifier/weights/FontModel_RuFaDataset_cnn_weights(4).h5' -O weights.h5
model.load_weights('/content/weights.h5')<jupyter_output>--2020-07-21 06:10:36--  https://raw.githubusercontent.com/mhmoodlan/arabic-font-classification/master/codebase/code/font_classifier/weights/FontModel_RuFaDataset_cnn_weights(4).h5
Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 172.16.17.32, 172.16.31.10, 172.16.31.10, ...
Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|172.16.17.32|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 2090968 (2.0M) [application/octet-stream]
Saving to: ‘weights.h5’


weights.h5            0%[                    ]       0  --.-KB/s               
weights.h5          100%[===================>]   1.99M  --.-KB/s    in 0.07s   

2020-07-21 06:10:36 (27.7 MB/s) - ‘weights.h5’ saved [2090968/2090968]<jupyter_text>or train from scratch<jupyter_code>model.fit(
  full_train_ds,
  epochs=epochs,
  callbacks=callbacks
)<jupyter_output>Epoch 1/6
1004/1004 [==============================] - 124s 123ms/step - loss: 0.3770 - accuracy: 0.8473 - val_loss: 0.0675 - val_accuracy: 0.9943
Epoch 2/6
1004/1004 [==============================] - 37s 37ms/step - loss: 0.0594 - accuracy: 0.9921 - val_loss: 0.0397 - val_accuracy: 0.9963
Epoch 3/6
1004/1004 [==============================] - 38s 38ms/step - loss: 0.0427 - accuracy: 0.9948 - val_loss: 0.0238 - val_accuracy: 0.9992
Epoch 4/6
1004/1004 [==============================] - 37s 37ms/step - loss: 0.0345 - accuracy: 0.9961 - val_loss: 0.0168 - val_accuracy: 0.9982
Epoch 5/6
1004/1004 [==============================] - 36s 36ms/step - loss: 0.0273 - accuracy: 0.9971 - val_loss: 0.0150 - val_accuracy: 0.9997
Epoch 6/6
1004/1004 [==============================] - 37s 37ms/step - loss: 0.0272 - accuracy: 0.9975 - val_loss: 0.0434 - val_accuracy: 0.9960<jupyter_text>Evaluate<jupyter_code>test_score = model.evaluate(test_ds)
print(f"Test score: {test_score}")
assert np.allclose(test_score, [.231625, .971222])<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.16402298850574712, 'fraction_numerical': 0.06045977011494253, 'mean_word_length': 4.927111716621253, 'pattern_counts': {'":': 0, '<': 32, '<?xml version=': 0, '>': 33, 'https://': 3, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 4, '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': '8', 'dir': 'jupyter-structured-clean-dedup', 'id': '388356', 'license': 'MIT', 'n_tokens_mistral': 3463, 'n_tokens_neox': 3099, 'n_words': 478, 'path': 'Interfaces/Notebooks/Arabic_Font_Classification.ipynb', 'repo_name': 'BSA10/ARBML', 'size': '8714'}