{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.10","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# This notebook submit my final model\nFor more details see my GitHub [HERE](https://github.com/shlomoron/Google---American-Sign-Language-Fingerspelling-Recognition-12th-place-solution).","metadata":{}},{"cell_type":"code","source":"import gc\nimport json\nimport math\nimport pickle\nimport numpy as np\nimport pandas as pd\nfrom tqdm import tqdm\nimport matplotlib.pyplot as plt\nimport tensorflow as tf\nimport tensorflow_addons as tfa\n\n!pip install cached-property\nfrom cached_property import cached_property\nfrom shutil import copyfile\n\n!pip install fastparquet\nimport fastparquet\n\n!pip install Levenshtein\nimport Levenshtein as lev","metadata":{"execution":{"iopub.status.busy":"2023-09-01T14:16:01.915464Z","iopub.execute_input":"2023-09-01T14:16:01.916086Z","iopub.status.idle":"2023-09-01T14:16:34.125618Z","shell.execute_reply.started":"2023-09-01T14:16:01.916041Z","shell.execute_reply":"2023-09-01T14:16:34.124193Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"input_folder = '/kaggle/input'\nworking_folder = '/kaggle/working/'","metadata":{"execution":{"iopub.status.busy":"2023-09-01T14:16:34.13096Z","iopub.execute_input":"2023-09-01T14:16:34.13307Z","iopub.status.idle":"2023-09-01T14:16:34.139561Z","shell.execute_reply.started":"2023-09-01T14:16:34.13302Z","shell.execute_reply":"2023-09-01T14:16:34.138274Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# copy our file into the working directory (make sure it has .py suffix)\ncopyfile(src = f\"{input_folder}/ctc-tpu/CTC_TPU.py\", dst = f\"{working_folder}//CTC_TPU.py\")\n\n# import all our functions\nfrom CTC_TPU import classic_ctc_loss","metadata":{"execution":{"iopub.status.busy":"2023-09-01T14:16:34.140978Z","iopub.execute_input":"2023-09-01T14:16:34.141294Z","iopub.status.idle":"2023-09-01T14:16:34.156851Z","shell.execute_reply.started":"2023-09-01T14:16:34.141269Z","shell.execute_reply":"2023-09-01T14:16:34.155889Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Configure Strategy. Assume TPU...if not set default for GPU\ntpu = None\ntry:\n    tpu = tf.distribute.cluster_resolver.TPUClusterResolver.connect(tpu=\"local\") # \"local\" for 1VM TPU\n    strategy = tf.distribute.TPUStrategy(tpu)\n    print(\"on TPU\")\n    print(\"REPLICAS: \", strategy.num_replicas_in_sync)\nexcept:\n    strategy = tf.distribute.get_strategy()","metadata":{"execution":{"iopub.status.busy":"2023-09-01T14:16:34.159335Z","iopub.execute_input":"2023-09-01T14:16:34.159836Z","iopub.status.idle":"2023-09-01T14:16:34.626957Z","shell.execute_reply.started":"2023-09-01T14:16:34.159805Z","shell.execute_reply":"2023-09-01T14:16:34.626002Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"tfrecords_path = '/kaggle/input/aslfr-tfrecords'","metadata":{"execution":{"iopub.status.busy":"2023-09-01T14:16:34.628295Z","iopub.execute_input":"2023-09-01T14:16:34.628601Z","iopub.status.idle":"2023-09-01T14:16:34.633292Z","shell.execute_reply.started":"2023-09-01T14:16:34.628576Z","shell.execute_reply":"2023-09-01T14:16:34.632123Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Landmark indices","metadata":{}},{"cell_type":"code","source":"NOSE_old=[\n    1,2,98,327\n]\nLNOSE_old = [98]\nRNOSE_old = [327]\nLIP_old = [ 0,\n    61, 185, 40, 39, 37, 267, 269, 270, 409,\n    291, 146, 91, 181, 84, 17, 314, 405, 321, 375,\n    78, 191, 80, 81, 82, 13, 312, 311, 310, 415,\n    95, 88, 178, 87, 14, 317, 402, 318, 324, 308,\n]\nLLIP_old = [84,181,91,146,61,185,40,39,37,87,178,88,95,78,191,80,81,82]\nRLIP_old = [314,405,321,375,291,409,270,269,267,317,402,318,324,308,415,310,311,312]\n\nFACE_old = LIP_old+NOSE_old\nFACE_old.sort()\n\nLPOSE_old = [11, 13, 15, 17, 19, 21, 23]\nRPOSE_old = [12, 14, 16, 18, 20, 22, 24]\nPOSE_old = LPOSE_old + RPOSE_old\n\nX = [f'x_right_hand_{i}' for i in range(21)] + [f'x_left_hand_{i}' for i in range(21)] + [f'x_face_{i}' for i in FACE_old] + [f'x_pose_{i}' for i in POSE_old]\nY = [f'y_right_hand_{i}' for i in range(21)] + [f'y_left_hand_{i}' for i in range(21)] + [f'y_face_{i}' for i in FACE_old] + [f'y_pose_{i}' for i in POSE_old]\n\nSEL_COLS = X + Y\n\nprint('SEL_COLS size:' + str(len(SEL_COLS)))\n\nSEL_COLS_x = [x for x in SEL_COLS if 'x' in x]\nNOSE = [i for i, x in enumerate(SEL_COLS_x) if 'face' in x and int(x.split('_')[-1]) in NOSE_old]\nLNOSE = [i for i, x in enumerate(SEL_COLS_x) if 'face' in x and int(x.split('_')[-1]) in LNOSE_old]\nRNOSE = [i for i, x in enumerate(SEL_COLS_x) if 'face' in x and int(x.split('_')[-1]) in RNOSE_old]\nLIP = [i for i, x in enumerate(SEL_COLS_x) if 'face' in x and int(x.split('_')[-1]) in LIP_old]\nLLIP = [i for i, x in enumerate(SEL_COLS_x) if 'face' in x and int(x.split('_')[-1]) in LLIP_old]\nRLIP = [i for i, x in enumerate(SEL_COLS_x) if 'face' in x and int(x.split('_')[-1]) in RLIP_old]\nFACE = [i for i, x in enumerate(SEL_COLS_x) if 'face' in x and int(x.split('_')[-1]) in FACE_old]\n\nLPOSE = [i for i, x in enumerate(SEL_COLS_x) if 'pose' in x and int(x.split('_')[-1]) in LPOSE_old]\nRPOSE = [i for i, x in enumerate(SEL_COLS_x) if 'pose' in x and int(x.split('_')[-1]) in RPOSE_old]\nPOSE = [i for i, x in enumerate(SEL_COLS_x) if 'pose' in x and int(x.split('_')[-1]) in POSE_old]\n\nLHAND = [i for i, x in enumerate(SEL_COLS_x) if 'left_hand' in x]\nRHAND = [i for i, x in enumerate(SEL_COLS_x) if 'right_hand' in x]\n\nPOINT_LANDMARKS = FACE+RHAND+LHAND+RPOSE+LPOSE\n\nnorm_point = [i for i, x in enumerate(SEL_COLS_x) if 'face' in x and x.split('_')[-1] == '17'][0]","metadata":{"execution":{"iopub.status.busy":"2023-09-01T14:16:34.635354Z","iopub.execute_input":"2023-09-01T14:16:34.635794Z","iopub.status.idle":"2023-09-01T14:16:34.658842Z","shell.execute_reply.started":"2023-09-01T14:16:34.635755Z","shell.execute_reply":"2023-09-01T14:16:34.657637Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Config and stuff","metadata":{}},{"cell_type":"code","source":"DEBUG = False\n\nROWS_PER_FRAME = int(len(SEL_COLS)/2)\nPAD = 0.\nNUM_NODES = len(POINT_LANDMARKS)\nCHANNELS = 6*NUM_NODES\nprint(\"Number of landmarks: \" + str(NUM_NODES))\nprint(\"Number of features: \" + str(CHANNELS))\npad_token = 'P'\npad_token_idx = 59\n\n\nwith open (f\"{input_folder}/asl-fingerspelling/character_to_prediction_index.json\", \"r\") as f:\n    char_to_num = json.load(f)\n\nchar_to_num[pad_token] = pad_token_idx\nnum_to_char = {j:i for i,j in char_to_num.items()}\n\ninpdir = f\"{input_folder}/asl-fingerspelling\"\ndf = pd.read_csv(f'{inpdir}/train.csv')\n\ntffiles = df.file_id.map(lambda x: f'{tfrecords_path}/tfds/{x}.tfrecord').unique()\n\ntable = tf.lookup.StaticHashTable(\n    initializer=tf.lookup.KeyValueTensorInitializer(\n        keys=list(char_to_num.keys()),\n        values=list(char_to_num.values()),\n    ),\n    default_value=tf.constant(-1),\n    name=\"class_weight\"\n)\n\nMAX_LEN = 320\nbatch_size = 64*4\ndim = 384\nval_len = int(0.05 * len(tffiles))\ncache = True\nSHUFFLE = -1\n\nif DEBUG:\n  MAX_LEN = 64\n  batch_size = 16\n  dim=48\n  val_len = 1\n  cache = False\n  SHUFFLE = 50\n\nprint(\"Val len: \" + str(val_len))","metadata":{"execution":{"iopub.status.busy":"2023-09-01T14:16:34.660378Z","iopub.execute_input":"2023-09-01T14:16:34.660918Z","iopub.status.idle":"2023-09-01T14:16:34.826781Z","shell.execute_reply.started":"2023-09-01T14:16:34.660878Z","shell.execute_reply":"2023-09-01T14:16:34.825701Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Helper functions","metadata":{}},{"cell_type":"code","source":"def tf_nan_mean(x, axis=0, keepdims=False):\n    return tf_nan_sum(x, axis=axis, keepdims=keepdims) / tf_nan_count(x, axis=axis, keepdims=keepdims)\n\ndef tf_nan_std(x, center=None, axis=0, keepdims=False):\n    if center is None:\n        center = tf_nan_mean(x, axis=axis,  keepdims=True)\n    d = x - center\n    return tf.math.sqrt(tf_nan_mean(d * d, axis=axis, keepdims=keepdims))\n\ndef tf_nan_sum(x, axis=0, keepdims=False):\n    return tf.reduce_sum(tf.where(tf.math.is_nan(x), tf.zeros_like(x), x), axis=axis, keepdims=keepdims)\n\ndef tf_nan_count(x, axis=0, keepdims=False):\n    return tf.reduce_sum(tf.where(tf.math.is_nan(x), tf.zeros_like(x), tf.ones_like(x)), axis=axis, keepdims=keepdims)\n\ndef combine_datasets(x, y):\n  x['lev'] = y['lev']\n  return x","metadata":{"execution":{"iopub.status.busy":"2023-09-01T14:16:34.82801Z","iopub.execute_input":"2023-09-01T14:16:34.829924Z","iopub.status.idle":"2023-09-01T14:16:34.839952Z","shell.execute_reply.started":"2023-09-01T14:16:34.829888Z","shell.execute_reply":"2023-09-01T14:16:34.838714Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Decode","metadata":{}},{"cell_type":"code","source":"def decode_tfrec(record_bytes):\n    schema = {}\n    schema[\"frames\"] = tf.io.VarLenFeature(dtype=tf.float32)\n    schema[\"phrase\"] = tf.io.VarLenFeature(dtype=tf.float32)\n    features = tf.io.parse_single_example(record_bytes, schema)\n\n    frames = tf.sparse.to_dense(features[\"frames\"])\n    frames = tf.transpose(tf.reshape(frames,(-1, 2, int(len(SEL_COLS)/2))),[0, 2, 1])\n    phrase = tf.cast(tf.sparse.to_dense(features[\"phrase\"]), tf.int32)\n\n    out = {}\n    out['coordinates']  = frames\n    out['phrase'] = phrase\n    return out\n\ndef decode_tfrec_levs(record_bytes):\n    schema = {}\n    schema[\"lev\"] = tf.io.VarLenFeature(dtype=tf.float32)\n    features = tf.io.parse_single_example(record_bytes, schema)\n    lev = tf.cast(tf.sparse.to_dense(features[\"lev\"]), tf.float32)\n    out = {}\n    out['lev']  = lev\n    return out","metadata":{"execution":{"iopub.status.busy":"2023-09-01T14:16:34.841341Z","iopub.execute_input":"2023-09-01T14:16:34.841724Z","iopub.status.idle":"2023-09-01T14:16:34.852875Z","shell.execute_reply.started":"2023-09-01T14:16:34.841697Z","shell.execute_reply":"2023-09-01T14:16:34.852095Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Preprocess","metadata":{}},{"cell_type":"code","source":"def preprocess_continue(inputs, point_landmarks, max_len):\n    if tf.rank(inputs) == 3:\n        x = inputs[None,...]\n    else:\n        x = inputs\n\n    mean = tf_nan_mean(tf.gather(x, [norm_point], axis=2), axis=[1,2], keepdims=True)\n    mean = tf.where(tf.math.is_nan(mean), tf.constant(0.5,x.dtype), mean)\n    x = tf.gather(x, point_landmarks, axis=2)\n    std = tf_nan_std(x, center=mean, axis=[1,2], keepdims=True)\n    x = (x - mean)/std\n\n    length = tf.shape(x)[1]\n\n    x = x[...,:2]\n    dx = tf.cond(tf.shape(x)[1]>1,lambda:tf.pad(x[:,1:] - x[:,:-1], [[0,0],[0,1],[0,0],[0,0]]),lambda:tf.zeros_like(x))\n    dx2 = tf.cond(tf.shape(x)[1]>2,lambda:tf.pad(x[:,2:] - x[:,:-2], [[0,0],[0,2],[0,0],[0,0]]),lambda:tf.zeros_like(x))\n\n    x = tf.concat([\n        tf.reshape(x, (-1,length,len(point_landmarks), 2)),\n        tf.reshape(dx, (-1,length,len(point_landmarks), 2)),\n        tf.reshape(dx2, (-1,length,len(point_landmarks), 2)),\n    ], axis = -1)\n\n    if max_len is not None and tf.shape(x)[1] > max_len:\n        x = tf.image.resize(x[0], (max_len, tf.shape(x)[2]))\n        x = x[None]\n\n    x = tf.concat([\n        tf.reshape(x, (-1,tf.shape(x)[1],6*len(point_landmarks))),\n    ], axis = -1)\n    return tf.cast(x, tf.float32)\n\ndef normalize(x, MEANs, STDs):\n  x = (x-MEANs)/STDs\n  return x\n\ndef remove_nans(x):\n  x = tf.where(tf.math.is_nan(x),tf.constant(0.,x.dtype),x)\n  return x\n\ndef preprocess(x, point_landmarks, max_len, MEANs, STDs, augment=False):\n    coord = x['coordinates']\n    coord = tf.concat([coord, tf.zeros(( tf.shape(coord)[0],  tf.shape(coord)[1], 1))], axis = -1)\n    if augment:\n        coord = augment_fn(coord, max_len=MAX_LEN)\n    coord = tf.ensure_shape(coord, (None,ROWS_PER_FRAME,3))\n    coord = preprocess_continue(coord, point_landmarks, max_len)[0]\n    coord = normalize(coord, MEANs, STDs)\n    coord = remove_nans(coord)\n    return coord, x['phrase']","metadata":{"execution":{"iopub.status.busy":"2023-09-01T14:16:34.856652Z","iopub.execute_input":"2023-09-01T14:16:34.856987Z","iopub.status.idle":"2023-09-01T14:16:34.876339Z","shell.execute_reply.started":"2023-09-01T14:16:34.856931Z","shell.execute_reply":"2023-09-01T14:16:34.875411Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Define sets\n**val_files_unfiltered** checks the loss and Levenshtein distance on the validation set, unfiltered (different distribution than the train set, similar distribution to the leaderboard set).  ","metadata":{}},{"cell_type":"code","source":"indices = [i for i in range(len(tffiles))]\nval_files_unfiltered_indices = indices[:val_len]","metadata":{"execution":{"iopub.status.busy":"2023-09-01T14:16:34.877594Z","iopub.execute_input":"2023-09-01T14:16:34.878252Z","iopub.status.idle":"2023-09-01T14:16:34.896352Z","shell.execute_reply.started":"2023-09-01T14:16:34.8782Z","shell.execute_reply":"2023-09-01T14:16:34.895472Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Load MEANs and STDs","metadata":{}},{"cell_type":"code","source":"MEANs = pickle.load(open(f\"{input_folder}/aslfr-means-and-stds/MEANs.p\", \"rb\"))\nSTDs = pickle.load(open(f\"{input_folder}/aslfr-means-and-stds/STDs.p\", \"rb\"))","metadata":{"execution":{"iopub.status.busy":"2023-09-01T14:16:34.897684Z","iopub.execute_input":"2023-09-01T14:16:34.898059Z","iopub.status.idle":"2023-09-01T14:16:34.916355Z","shell.execute_reply.started":"2023-09-01T14:16:34.898031Z","shell.execute_reply":"2023-09-01T14:16:34.915237Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Get dataset function","metadata":{}},{"cell_type":"code","source":"### Get datasets","metadata":{"execution":{"iopub.status.busy":"2023-09-01T14:16:34.917908Z","iopub.execute_input":"2023-09-01T14:16:34.918299Z","iopub.status.idle":"2023-09-01T14:16:34.92943Z","shell.execute_reply.started":"2023-09-01T14:16:34.918271Z","shell.execute_reply":"2023-09-01T14:16:34.928681Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_tfrec_dataset(tfrecords_indices, MEANs = MEANs, STDs = STDs, point_landmarks = POINT_LANDMARKS, batch_size=64, max_len=64, drop_remainder=False,\n                      augment=False, shuffle=False,to_filter = False, cache = False):\n    # Initialize dataset with TFRecords\n    ds = tf.data.TFRecordDataset(tffiles[tfrecords_indices], num_parallel_reads=tf.data.AUTOTUNE, compression_type = 'GZIP').prefetch(tf.data.AUTOTUNE)\n    ds = ds.map(decode_tfrec, tf.data.AUTOTUNE)\n    \n    if DEBUG:\n        ds = ds.take(64)\n\n    if cache:\n        ds = ds.cache()\n\n    ds = ds.map(lambda x: preprocess(x, point_landmarks, max_len, MEANs, STDs, augment=augment), tf.data.AUTOTUNE)\n\n    if batch_size:\n        ds = ds.padded_batch(batch_size, padding_values=(PAD, pad_token_idx), padded_shapes=([max_len,CHANNELS],[64]), drop_remainder=drop_remainder)\n\n    ds = ds.prefetch(tf.data.AUTOTUNE)\n\n    return ds","metadata":{"execution":{"iopub.status.busy":"2023-09-01T14:16:34.931298Z","iopub.execute_input":"2023-09-01T14:16:34.931696Z","iopub.status.idle":"2023-09-01T14:16:34.943963Z","shell.execute_reply.started":"2023-09-01T14:16:34.931659Z","shell.execute_reply":"2023-09-01T14:16:34.943213Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"val_dataset_unfiltered = get_tfrec_dataset(val_files_unfiltered_indices, batch_size=batch_size, max_len=MAX_LEN, drop_remainder=True,\n                                        shuffle=False, to_filter = False, cache = cache)\n\nINPUT_SHAPE = [MAX_LEN, CHANNELS]\nbatch = next(iter(val_dataset_unfiltered))\nbatch[0].shape, batch[1].shape","metadata":{"execution":{"iopub.status.busy":"2023-09-01T14:16:34.945818Z","iopub.execute_input":"2023-09-01T14:16:34.946685Z","iopub.status.idle":"2023-09-01T14:16:36.795109Z","shell.execute_reply.started":"2023-09-01T14:16:34.946645Z","shell.execute_reply":"2023-09-01T14:16:36.79386Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Copied from previous comp 1st place model: https://www.kaggle.com/code/hoyso48/1st-place-solution-training\nclass ECA(tf.keras.layers.Layer):\n    def __init__(self, kernel_size=5, **kwargs):\n        super().__init__(**kwargs)\n        self.supports_masking = True\n        self.kernel_size = kernel_size\n        self.conv = tf.keras.layers.Conv1D(1, kernel_size=kernel_size, strides=1, padding=\"same\", use_bias=False)\n\n    def call(self, inputs, mask=None):\n        nn = tf.keras.layers.GlobalAveragePooling1D()(inputs, mask=mask)\n        nn = tf.expand_dims(nn, -1)\n        nn = self.conv(nn)\n        nn = tf.squeeze(nn, -1)\n        nn = tf.nn.sigmoid(nn)\n        nn = nn[:,None,:]\n        return inputs * nn\n\nclass CausalDWConv1D(tf.keras.layers.Layer):\n    def __init__(self, \n        kernel_size=17,\n        dilation_rate=1,\n        use_bias=False,\n        depthwise_initializer='glorot_uniform',\n        name='', **kwargs):\n        super().__init__(name=name,**kwargs)\n        self.causal_pad = tf.keras.layers.ZeroPadding1D((dilation_rate*(kernel_size-1),0),name=name + '_pad')\n        self.dw_conv = tf.keras.layers.DepthwiseConv1D(\n                            kernel_size,\n                            strides=1,\n                            dilation_rate=dilation_rate,\n                            padding='valid',\n                            use_bias=use_bias,\n                            depthwise_initializer=depthwise_initializer,\n                            name=name + '_dwconv')\n        self.supports_masking = True\n        \n    def call(self, inputs):\n        x = self.causal_pad(inputs)\n        x = self.dw_conv(x)\n        return x\n\ndef Conv1DBlock(channel_size,\n          kernel_size,\n          dilation_rate=1,\n          drop_rate=0.0,\n          expand_ratio=2,\n          se_ratio=0.25,\n          activation='swish',\n          name=None):\n    '''\n    efficient conv1d block, @hoyso48\n    '''\n    if name is None:\n        name = str(tf.keras.backend.get_uid(\"mbblock\"))\n    # Expansion phase\n    def apply(inputs):\n        channels_in = tf.keras.backend.int_shape(inputs)[-1]\n        channels_expand = channels_in * expand_ratio\n\n        skip = inputs\n\n        x = tf.keras.layers.Dense(\n            channels_expand,\n            use_bias=True,\n            activation=activation,\n            name=name + '_expand_conv')(inputs)\n\n        # Depthwise Convolution\n        x = CausalDWConv1D(kernel_size,\n            dilation_rate=dilation_rate,\n            use_bias=False,\n            name=name + '_dwconv')(x)\n\n        x = tf.keras.layers.BatchNormalization(momentum=0.95, name=name + '_bn')(x)\n\n        x  = ECA()(x)\n\n        x = tf.keras.layers.Dense(\n            channel_size,\n            use_bias=True,\n            name=name + '_project_conv')(x)\n\n        if drop_rate > 0:\n            x = tf.keras.layers.Dropout(drop_rate, noise_shape=(None,1,1), name=name + '_drop')(x)\n\n        if (channels_in == channel_size):\n            x = tf.keras.layers.add([x, skip], name=name + '_add')\n        return x\n\n    return apply\n\nclass MultiHeadSelfAttention(tf.keras.layers.Layer):\n    def __init__(self, dim=256, num_heads=4, dropout=0, **kwargs):\n        super().__init__(**kwargs)\n        self.dim = dim\n        self.scale = self.dim ** -0.5\n        self.num_heads = num_heads\n        self.qkv = tf.keras.layers.Dense(3 * dim, use_bias=False)\n        self.drop1 = tf.keras.layers.Dropout(dropout)\n        self.proj = tf.keras.layers.Dense(dim, use_bias=False)\n        self.supports_masking = True\n\n    def call(self, inputs, mask=None):\n        qkv = self.qkv(inputs)\n        qkv = tf.keras.layers.Permute((2, 1, 3))(tf.keras.layers.Reshape((-1, self.num_heads, self.dim * 3 // self.num_heads))(qkv))\n        q, k, v = tf.split(qkv, [self.dim // self.num_heads] * 3, axis=-1)\n\n        attn = tf.matmul(q, k, transpose_b=True) * self.scale\n\n        if mask is not None:\n            mask = mask[:, None, None, :]\n\n        attn = tf.keras.layers.Softmax(axis=-1)(attn, mask=mask)\n        attn = self.drop1(attn)\n\n        x = attn @ v\n        x = tf.keras.layers.Reshape((-1, self.dim))(tf.keras.layers.Permute((2, 1, 3))(x))\n        x = self.proj(x)\n        return x\n\n\ndef TransformerBlock(dim=256, num_heads=6, expand=4, attn_dropout=0.2, drop_rate=0.2, activation='swish'):\n    def apply(inputs):\n        x = inputs\n        x = tf.keras.layers.LayerNormalization(epsilon=1e-6)(x)\n        x = MultiHeadSelfAttention(dim=dim,num_heads=num_heads,dropout=attn_dropout)(x)\n        x = tf.keras.layers.Dropout(drop_rate, noise_shape=(None,1,1))(x)\n        x = tf.keras.layers.Add()([inputs, x])\n        attn_out = x\n\n        x = tf.keras.layers.LayerNormalization(epsilon=1e-6)(x)\n        x = tf.keras.layers.Dense(dim*expand, use_bias=False, activation=activation)(x)\n        x = tf.keras.layers.Dense(dim, use_bias=False)(x)\n        x = tf.keras.layers.Dropout(drop_rate, noise_shape=(None,1,1))(x)\n        x = tf.keras.layers.Add()([attn_out, x])\n        return x\n    return apply\n\ndef positional_encoding(maxlen, num_hid):\n        depth = num_hid/2\n        positions = tf.range(maxlen, dtype = tf.float32)[..., tf.newaxis]\n        depths = tf.range(depth, dtype = tf.float32)[np.newaxis, :]/depth\n        angle_rates = tf.math.divide(1, tf.math.pow(tf.cast(10000, tf.float32), depths))\n        angle_rads = tf.linalg.matmul(positions, angle_rates)\n        pos_encoding = tf.concat(\n          [tf.math.sin(angle_rads), tf.math.cos(angle_rads)],\n          axis=-1)\n        return pos_encoding\n    \n\nclass LateDropout(tf.keras.layers.Layer):\n    def __init__(self, rate, noise_shape=None, start_step=0, **kwargs):\n        super().__init__(**kwargs)\n        self.supports_masking = True\n        self.rate = rate\n        self.start_step = start_step\n        self.dropout = tf.keras.layers.Dropout(rate, noise_shape=noise_shape)\n\n    def build(self, input_shape):\n        super().build(input_shape)\n        agg = tf.VariableAggregation.ONLY_FIRST_REPLICA\n        self._train_counter = tf.Variable(0, dtype=\"int64\", aggregation=agg, trainable=False)\n\n    def call(self, inputs, training=False):\n        x = tf.cond(self._train_counter < self.start_step, lambda:inputs, lambda:self.dropout(inputs, training=training))\n        if training:\n            self._train_counter.assign_add(1)\n        return x","metadata":{"execution":{"iopub.status.busy":"2023-09-01T14:16:36.796636Z","iopub.execute_input":"2023-09-01T14:16:36.797054Z","iopub.status.idle":"2023-09-01T14:16:36.829681Z","shell.execute_reply.started":"2023-09-01T14:16:36.797016Z","shell.execute_reply":"2023-09-01T14:16:36.828629Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def CTCLoss(labels, logits):\n    label_length = tf.reduce_sum(tf.cast(labels != pad_token_idx, tf.int32), axis=-1)\n    logit_length = tf.ones(tf.shape(logits)[0], dtype=tf.int32) * tf.shape(logits)[1]\n    \n    loss = classic_ctc_loss(\n            labels=labels,\n            logits=logits,\n            label_length=label_length,\n            logit_length=logit_length,\n            blank_index=pad_token_idx,\n        )\n\n    loss = tf.reduce_mean(loss)\n    return loss","metadata":{"execution":{"iopub.status.busy":"2023-09-01T14:16:36.831175Z","iopub.execute_input":"2023-09-01T14:16:36.831599Z","iopub.status.idle":"2023-09-01T14:16:36.847588Z","shell.execute_reply.started":"2023-09-01T14:16:36.831561Z","shell.execute_reply":"2023-09-01T14:16:36.84676Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_model(dim = 384, dropout_step=0):\n    with strategy.scope():\n        inp = tf.keras.Input((None, CHANNELS))\n        x = inp\n        \n        x = tf.keras.layers.Masking(mask_value=0.0)(x)\n        x = tf.keras.layers.Dense(dim, use_bias=False,name='stem_conv')(x)\n        x = tf.keras.layers.BatchNormalization(momentum=0.95,name='stem_bn')(x)\n\n        x = Conv1DBlock(dim,11,drop_rate=0.2)(x)\n        x = Conv1DBlock(dim,7,drop_rate=0.2)(x)\n        x = Conv1DBlock(dim,3,drop_rate=0.2)(x)\n        \n        x = x + positional_encoding(INPUT_SHAPE[0], dim)\n        \n        x = TransformerBlock(dim,expand=2)(x)\n        \n        x = Conv1DBlock(dim,11,drop_rate=0.2)(x)\n        x = Conv1DBlock(dim,7,drop_rate=0.2)(x)\n        x = Conv1DBlock(dim,3,drop_rate=0.2)(x)\n        x = TransformerBlock(dim,expand=2)(x)\n        \n        x = Conv1DBlock(dim,11,drop_rate=0.2)(x)\n        x = Conv1DBlock(dim,7,drop_rate=0.2)(x)\n        x = Conv1DBlock(dim,3,drop_rate=0.2)(x)\n        x = TransformerBlock(dim,expand=2)(x)\n        \n        x = Conv1DBlock(dim,11,drop_rate=0.2)(x)\n        x = Conv1DBlock(dim,7,drop_rate=0.2)(x)\n        x = Conv1DBlock(dim,3,drop_rate=0.2)(x)\n        x = TransformerBlock(dim,expand=2)(x)\n        \n        x = Conv1DBlock(dim,11,drop_rate=0.2)(x)\n        x = Conv1DBlock(dim,7,drop_rate=0.2)(x)\n        x = Conv1DBlock(dim,3,drop_rate=0.2)(x)\n        x = TransformerBlock(dim,expand=2)(x)\n        \n        x = tf.keras.layers.Dense(dim*2,activation='relu',name='top_conv')(x)\n        x = LateDropout(0.0, start_step=dropout_step)(x)\n        x = tf.keras.layers.Dense(len(char_to_num))(x)\n\n        model = tf.keras.Model(inp, x)\n        return model\n\ntf.keras.backend.clear_session()\n\nmodel = get_model()\n\nmodel.load_weights('/kaggle/input/aslfr-final-model/final_model_epoch_1449.h5')\n\nmodel(batch[0])\nmodel.summary()","metadata":{"execution":{"iopub.status.busy":"2023-09-01T14:16:36.848969Z","iopub.execute_input":"2023-09-01T14:16:36.84929Z","iopub.status.idle":"2023-09-01T14:17:32.625752Z","shell.execute_reply.started":"2023-09-01T14:16:36.849263Z","shell.execute_reply":"2023-09-01T14:17:32.62454Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def num_to_char_fn(y):\n    return [num_to_char.get(x, \"\") for x in y]\n\n@tf.function()\ndef decode_phrase(pred):\n    x = tf.argmax(pred, axis=1)\n    diff = tf.not_equal(x[:-1], x[1:])\n    adjacent_indices = tf.where(diff)[:, 0]\n    x = tf.gather(x, adjacent_indices)\n    mask = x != pad_token_idx\n    x = tf.boolean_mask(x, mask, axis=0)\n    return x\n\n# A utility function to decode the output of the network\ndef decode_batch_predictions(pred):\n    output_text = []\n    for result in pred:\n        result = \"\".join(num_to_char_fn(decode_phrase(result).numpy()))\n        output_text.append(result)\n    return output_text","metadata":{"execution":{"iopub.status.busy":"2023-09-01T14:17:32.627577Z","iopub.execute_input":"2023-09-01T14:17:32.627933Z","iopub.status.idle":"2023-09-01T14:17:32.637856Z","shell.execute_reply.started":"2023-09-01T14:17:32.627893Z","shell.execute_reply":"2023-09-01T14:17:32.637038Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### This is for calculating the validation set' Levenshtein distance during training","metadata":{}},{"cell_type":"code","source":"test_dataset = get_tfrec_dataset(val_files_unfiltered_indices, batch_size=batch_size, max_len=MAX_LEN, drop_remainder=True,\n                                 shuffle=False, to_filter = False, cache = cache)\ntest_set = [x for x in test_dataset]\n\nwith open (f\"{input_folder}/asl-fingerspelling/character_to_prediction_index.json\", \"r\") as f:\n    character_map = json.load(f)\nrev_character_map = {j:i for i,j in character_map.items()}\n\nclass val_lev_callback(tf.keras.callbacks.Callback):\n    def __init__(self):\n        super().__init__()\n    def on_epoch_end(self, epoch: int, logs=None):\n        print('Val set:')\n        calculate_val_lev(val_set)\n        print('Test set:')\n        calculate_val_lev(test_set)\n        print('Test set 2:')\n        calculate_val_lev(test_set_2)\n        \ndef calculate_val_lev(dataset):\n    preds = []\n    targets = []\n    scores = []\n    for batch_idx in range(len(dataset)):\n        preds_batch = model.predict(dataset[batch_idx][0], verbose = 0)\n        targets_batch = dataset[batch_idx][1]\n        for pred_idx in range(len(preds_batch)):\n            preds.append(\"\".join([rev_character_map.get(s, \"\") for s in decode_phrase(preds_batch[pred_idx]).numpy()]))\n            targets.append(\"\".join([rev_character_map.get(s, \"\") for s in targets_batch[pred_idx].numpy()]))\n\n    N = [len(phrase) for phrase in targets]\n    lev_dist = [lev.distance(preds[i], targets[i]) for i in range(len(targets))]\n    print('Lev distance: '+str((np.sum(N) - np.sum(lev_dist))/np.sum(N)))\n    \n    \ndef calculate_test_lev():\n    preds = []\n    targets = []\n    scores = []\n    for batch_idx in range(len(test_set)):\n        preds_batch = model.predict(test_set[batch_idx][0], verbose = 0)\n        targets_batch = test_set[batch_idx][1]\n        for pred_idx in range(len(preds_batch)):\n            preds.append(\"\".join([rev_character_map.get(s, \"\") for s in decode_phrase(preds_batch[pred_idx]).numpy()]))\n            targets.append(\"\".join([rev_character_map.get(s, \"\") for s in targets_batch[pred_idx].numpy()]))\n\n    N = [len(phrase) for phrase in targets]\n    lev_dist = [lev.distance(preds[i], targets[i]) for i in range(len(targets))]\n    print('TEST Lev distance: '+str((np.sum(N) - np.sum(lev_dist))/np.sum(N)))\n    \n\n\ndef calculate_val_lev_upgraded(dataset, save = False):\n    preds = []\n    targets = []\n    scores = []\n    preds_logits = []\n    for batch_idx in range(len(dataset)):\n        preds_batch = model.predict(dataset[batch_idx][0], verbose = 0)\n        targets_batch = dataset[batch_idx][1]\n        for pred_idx in range(len(preds_batch)):\n            preds_logits.append(preds_batch[pred_idx])\n            preds.append(\"\".join([rev_character_map.get(s, \"\") for s in decode_phrase(preds_batch[pred_idx]).numpy()]))\n            targets.append(\"\".join([rev_character_map.get(s, \"\") for s in targets_batch[pred_idx].numpy()]))\n\n    N = [len(phrase) for phrase in targets]\n    lev_dist = [lev.distance(preds[i], targets[i]) for i in range(len(targets))]\n    print('Lev distance: '+str((np.sum(N) - np.sum(lev_dist))/np.sum(N)))\n    \n    if save:\n        pickle.dump(preds, open( 'preds.p', \"wb\" ) )\n        pickle.dump(targets, open( 'targets.p', \"wb\" ) )\n        pickle.dump(preds_logits, open( 'preds_logits.p', \"wb\" ) )","metadata":{"execution":{"iopub.status.busy":"2023-09-01T14:17:32.639285Z","iopub.execute_input":"2023-09-01T14:17:32.639634Z","iopub.status.idle":"2023-09-01T14:17:39.930846Z","shell.execute_reply.started":"2023-09-01T14:17:32.639604Z","shell.execute_reply":"2023-09-01T14:17:39.929754Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(calculate_val_lev_upgraded(test_set, save = True))","metadata":{"execution":{"iopub.status.busy":"2023-09-01T14:17:39.932382Z","iopub.execute_input":"2023-09-01T14:17:39.932821Z","iopub.status.idle":"2023-09-01T14:24:47.195194Z","shell.execute_reply.started":"2023-09-01T14:17:39.932781Z","shell.execute_reply":"2023-09-01T14:24:47.194025Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"SEL_COLS_indices = [i for i in range(len(SEL_COLS))]\n@tf.function(jit_compile=True)\ndef pre_process0(x):\n    x = tf.transpose(tf.reshape(x,(-1, 2, tf.cast((tf.shape(SEL_COLS)[0]/2), tf.int64))),[0, 2, 1])\n    return x","metadata":{"execution":{"iopub.status.busy":"2023-09-01T14:24:47.736092Z","iopub.execute_input":"2023-09-01T14:24:47.736799Z","iopub.status.idle":"2023-09-01T14:24:47.743884Z","shell.execute_reply.started":"2023-09-01T14:24:47.736754Z","shell.execute_reply":"2023-09-01T14:24:47.743024Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(MAX_LEN)\nprint(POINT_LANDMARKS)\n\n@tf.function(jit_compile=True)\ndef tf_nan_mean(x, axis=0, keepdims=False):\n    return tf.reduce_sum(tf.where(tf.math.is_nan(x), tf.zeros_like(x), x), axis=axis, keepdims=keepdims) / tf.reduce_sum(tf.where(tf.math.is_nan(x), tf.zeros_like(x), tf.ones_like(x)), axis=axis, keepdims=keepdims)\n\n@tf.function(jit_compile=True)\ndef tf_nan_std(x, center=None, axis=0, keepdims=False):\n    if center is None:\n        center = tf_nan_mean(x, axis=axis,  keepdims=True)\n    d = x - center\n    return tf.math.sqrt(tf_nan_mean(d * d, axis=axis, keepdims=keepdims))\n\n@tf.function(jit_compile=True)\ndef pre_process1(x):\n    x = x[None,...]\n    \n    mean = tf_nan_mean(tf.gather(x, [norm_point], axis=2), axis=[1,2], keepdims=True)\n    mean = tf.where(tf.math.is_nan(mean), tf.constant(0.5,x.dtype), mean)\n    x = tf.gather(x, POINT_LANDMARKS, axis=2) #N,T,P,C\n    std = tf_nan_std(x, center=mean, axis=[1,2], keepdims=True)\n    x = (x - mean)/std\n\n    length = tf.shape(x)[1]\n\n    x = x[...,:2]\n    dx = tf.cond(tf.shape(x)[1]>1,lambda:tf.pad(x[:,1:] - x[:,:-1], [[0,0],[0,1],[0,0],[0,0]]),lambda:tf.zeros_like(x))\n    dx2 = tf.cond(tf.shape(x)[1]>2,lambda:tf.pad(x[:,2:] - x[:,:-2], [[0,0],[0,2],[0,0],[0,0]]),lambda:tf.zeros_like(x))\n\n    x = tf.concat([\n        tf.reshape(x, (-1,length,len(POINT_LANDMARKS), 2)),\n        tf.reshape(dx, (-1,length,len(POINT_LANDMARKS), 2)),\n        tf.reshape(dx2, (-1,length,len(POINT_LANDMARKS), 2)),\n    ], axis = -1)\n\n    if MAX_LEN is not None and tf.shape(x)[1]>MAX_LEN:\n        x = tf.image.resize(x[0], (MAX_LEN, tf.shape(x)[2]))\n        x = x[None]\n\n    x = tf.concat([\n        tf.reshape(x, (-1,tf.shape(x)[1],6*len(POINT_LANDMARKS))),\n    ], axis = -1)\n    \n    x = (x-MEANs)/STDs\n    x = tf.where(tf.math.is_nan(x),tf.constant(0.,x.dtype),x)\n    \n    x = tf.concat([x, tf.zeros((1, MAX_LEN - tf.shape(x)[1], CHANNELS))], axis = 1)\n    \n    return x","metadata":{"execution":{"iopub.status.busy":"2023-09-01T14:24:47.745521Z","iopub.execute_input":"2023-09-01T14:24:47.74632Z","iopub.status.idle":"2023-09-01T14:24:47.768437Z","shell.execute_reply.started":"2023-09-01T14:24:47.746279Z","shell.execute_reply":"2023-09-01T14:24:47.767343Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def load_relevant_data_subset(pq_path):\n    return pd.read_parquet(pq_path, columns=SEL_COLS)\n\nfile_id = df.file_id.iloc[0]\ninpdir = \"/kaggle/input/asl-fingerspelling/train_landmarks\"\npqfile = f\"{inpdir}/{file_id}.parquet\"\nseq_refs = df.loc[df.file_id == file_id]\nseqs = load_relevant_data_subset(pqfile)\n\nseq_id = seq_refs.sequence_id.iloc[0]\nframes = seqs.iloc[seqs.index == seq_id]\nphrase = str(df.loc[df.sequence_id == seq_id].phrase.iloc[0])","metadata":{"execution":{"iopub.status.busy":"2023-09-01T14:24:47.770153Z","iopub.execute_input":"2023-09-01T14:24:47.771181Z","iopub.status.idle":"2023-09-01T14:24:50.32922Z","shell.execute_reply.started":"2023-09-01T14:24:47.77114Z","shell.execute_reply":"2023-09-01T14:24:50.328242Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class TFLiteModel(tf.Module):\n    def __init__(self, model):\n        super(TFLiteModel, self).__init__()\n        self.model = model\n    \n    @tf.function(input_signature=[tf.TensorSpec(shape=[None, len(SEL_COLS)], dtype=tf.float32, name='inputs')])\n    def __call__(self, inputs, training=False):\n        # Preprocess Data\n        x = tf.cast(inputs, tf.float32)\n        x = x[None]\n        x = tf.cond(tf.shape(x)[1] == 0, lambda: tf.zeros((1, 1, len(SEL_COLS))), lambda: tf.identity(x))\n        x = x[0]\n        x = pre_process0(x)\n        x = pre_process1(x)\n        #x = tf.reshape(x, INPUT_SHAPE)\n        #x = x[None]\n        x = self.model(x, training=False)\n        x = x[0]\n        x = decode_phrase(x)\n        x = tf.cond(tf.shape(x)[0] == 0, lambda: tf.zeros(1, tf.int64), lambda: tf.identity(x))\n        x = tf.one_hot(x, 59)\n        return {'outputs': x}\n\ntflitemodel_base = TFLiteModel(model)\noutput = tflitemodel_base(frames)[\"outputs\"]\nprint(output.shape)","metadata":{"execution":{"iopub.status.busy":"2023-09-01T14:24:50.333216Z","iopub.execute_input":"2023-09-01T14:24:50.333896Z","iopub.status.idle":"2023-09-01T14:24:54.504859Z","shell.execute_reply.started":"2023-09-01T14:24:50.33386Z","shell.execute_reply":"2023-09-01T14:24:54.504076Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"keras_model_converter = tf.lite.TFLiteConverter.from_keras_model(tflitemodel_base)\nkeras_model_converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS]#, tf.lite.OpsSet.SELECT_TF_OPS]\nkeras_model_converter.optimizations = [tf.lite.Optimize.OPTIMIZE_FOR_LATENCY]\n#keras_model_converter.optimizations = [tf.lite.Optimize.DEFAULT]\nkeras_model_converter.target_spec.supported_types = [tf.float16]\ntflite_model = keras_model_converter.convert()\nwith open('model.tflite', 'wb') as f:\n    f.write(tflite_model)\n    \nwith open('inference_args.json', \"w\") as f:\n    json.dump({\"selected_columns\" : SEL_COLS}, f)\n    \n!zip submission.zip  './model.tflite' './inference_args.json'","metadata":{"execution":{"iopub.status.busy":"2023-09-01T14:24:54.505782Z","iopub.execute_input":"2023-09-01T14:24:54.506093Z","iopub.status.idle":"2023-09-01T14:26:06.575446Z","shell.execute_reply.started":"2023-09-01T14:24:54.506051Z","shell.execute_reply":"2023-09-01T14:26:06.573787Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"with open (\"inference_args.json\", \"r\") as f:\n    SEL_COLS = json.load(f)[\"selected_columns\"]\n    \ndef load_relevant_data_subset(pq_path):\n    return pd.read_parquet(pq_path, columns=SEL_COLS)\n\ndef create_data_gen(file_ids, y_mul=1):\n    def gen():\n        for file_id in file_ids:\n            pqfile = f\"{inpdir}/{file_id}.parquet\"\n            seq_refs = df.loc[df.file_id == file_id]\n            seqs = load_relevant_data_subset(pqfile)\n\n            for seq_id in seq_refs.sequence_id:\n                x = seqs.iloc[seqs.index == seq_id].to_numpy()\n                y = str(df.loc[df.sequence_id == seq_id].phrase.iloc[0])\n                \n                yield x, y\n    return gen\n\npqfiles = df.file_id.unique()\nval_len = int(0.05 * len(pqfiles))\n\ntest_dataset = tf.data.Dataset.from_generator(create_data_gen(pqfiles[:1], 0),\n    output_signature=(tf.TensorSpec(shape=(None, len(SEL_COLS)), dtype=tf.float32), tf.TensorSpec(shape=(), dtype=tf.string))\n).prefetch(buffer_size=2000)","metadata":{"execution":{"iopub.status.busy":"2023-09-01T14:26:06.582185Z","iopub.execute_input":"2023-09-01T14:26:06.582612Z","iopub.status.idle":"2023-09-01T14:26:06.658695Z","shell.execute_reply.started":"2023-09-01T14:26:06.582576Z","shell.execute_reply":"2023-09-01T14:26:06.657722Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"interpreter = tf.lite.Interpreter(\"model.tflite\")\n\nREQUIRED_SIGNATURE = \"serving_default\"\nREQUIRED_OUTPUT = \"outputs\"\n\nwith open (\"/kaggle/input/asl-fingerspelling/character_to_prediction_index.json\", \"r\") as f:\n    character_map = json.load(f)\nrev_character_map = {j:i for i,j in character_map.items()}\n\nprediction_fn = interpreter.get_signature_runner(REQUIRED_SIGNATURE)\n\nfor frame, target in test_dataset.skip(100).take(10):\n    output = prediction_fn(inputs=frame)\n    prediction_str = \"\".join([rev_character_map.get(s, \"\") for s in np.argmax(output[REQUIRED_OUTPUT], axis=1)])\n    target = target.numpy().decode(\"utf-8\")\n    print(\"pred =\", prediction_str, \"; target =\", target)","metadata":{"execution":{"iopub.status.busy":"2023-09-01T14:26:06.660848Z","iopub.execute_input":"2023-09-01T14:26:06.661327Z","iopub.status.idle":"2023-09-01T14:26:11.572268Z","shell.execute_reply.started":"2023-09-01T14:26:06.661288Z","shell.execute_reply":"2023-09-01T14:26:11.571023Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from Levenshtein import distance\n\nscores = []\npreds_tflight = []\ntargets = []\nlev_dist = []\n\nfor i, (frame, target) in tqdm(enumerate(test_dataset.take(1000))):\n    output = prediction_fn(inputs=frame)\n    prediction_str = \"\".join([rev_character_map.get(s, \"\") for s in np.argmax(output[REQUIRED_OUTPUT], axis=1)])\n    target = target.numpy().decode(\"utf-8\")\n    preds_tflight.append(prediction_str)\n    score = (len(target) - distance(prediction_str, target)) / len(target)\n    targets.append(target)\n    lev_dist.append(distance(prediction_str, target))\n    scores.append(score)\n    if i % 50 == 0:\n        print(np.sum(scores) / len(scores))\n    \nscores = np.array(scores)\nprint(np.sum(scores) / len(scores))\n\nN = [len(phrase) for phrase in targets]\nprint((np.sum(N) - np.sum(lev_dist))/np.sum(N))","metadata":{"execution":{"iopub.status.busy":"2023-09-01T14:26:11.574211Z","iopub.execute_input":"2023-09-01T14:26:11.574636Z","iopub.status.idle":"2023-09-01T14:32:47.480651Z","shell.execute_reply.started":"2023-09-01T14:26:11.574599Z","shell.execute_reply":"2023-09-01T14:32:47.479416Z"},"trusted":true},"execution_count":null,"outputs":[]}],"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}}