{"metadata":{"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"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"from tensorflow.keras import Model, layers\nfrom bs4 import BeautifulSoup\nfrom IPython import display\n\n\nimport tensorflow_io as tfio\nimport tensorflow as tf\nimport pandas as pd\nimport numpy as np\n\nimport requests\nimport librosa\nimport glob\nimport os\nfrom skimage.io import imread","metadata":{"papermill":{"duration":7.076178,"end_time":"2023-03-27T23:18:52.432353","exception":false,"start_time":"2023-03-27T23:18:45.356175","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2023-04-01T10:29:45.959269Z","iopub.execute_input":"2023-04-01T10:29:45.959692Z","iopub.status.idle":"2023-04-01T10:29:45.967391Z","shell.execute_reply.started":"2023-04-01T10:29:45.959633Z","shell.execute_reply":"2023-04-01T10:29:45.966060Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Check for TPU\ntry:\n    tpu = tf.distribute.cluster_resolver.TPUClusterResolver()  # TPU detection\n    print('Running on TPU ', tpu.cluster_spec().as_dict()['worker'])\nexcept ValueError:\n    tpu = None\n\nif tpu:\n    tf.config.experimental_connect_to_cluster(tpu)\n    tf.tpu.experimental.initialize_tpu_system(tpu)\n    strategy = tf.distribute.experimental.TPUStrategy(tpu)\n    device = \"TPU\"\n# Check for GPU\nelif tf.config.list_physical_devices('GPU'):\n    strategy = tf.distribute.MirroredStrategy()\n    device = \"GPU\"\n# Use CPU\nelse:\n    strategy = tf.distribute.get_strategy()\n    device = \"CPU\"\n\nprint(\"Number of accelerators \", strategy.num_replicas_in_sync,\"|\", device)","metadata":{"papermill":{"duration":2.525357,"end_time":"2023-03-27T23:18:54.960878","exception":false,"start_time":"2023-03-27T23:18:52.435521","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2023-04-01T10:29:45.973186Z","iopub.execute_input":"2023-04-01T10:29:45.973803Z","iopub.status.idle":"2023-04-01T10:29:45.983535Z","shell.execute_reply.started":"2023-04-01T10:29:45.973752Z","shell.execute_reply":"2023-04-01T10:29:45.982153Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class cfg:\n    competition = \"birdclef 2023\"\n    \n    frame_duration = 10 # seconde\n    sample_rate = 32_000\n    desired_sample_rate = 16_000\n    frame_length = frame_duration*desired_sample_rate\n    window = 2_048\n    img_shape = [128, 380]\n    strides = int(frame_length/img_shape[1])\n    nfft = 2048\n    \n    \n    root = \"/kaggle/input/birdclef-2023\"\n    output = \"/kaggle/working/\"\n    train_dir = os.path.join(root, \"train_audio/\")\n    metada_file = os.path.join(root, \"train_metadata.csv\")\n    image_path = os.path.join(output, \"images\")\n    preprocessing_dir = os.path.join(output, \"preprocessed\")\n    \n    batch_size = 16*strategy.num_replicas_in_sync\n    records_size = 512\n    epochs = 25\n    model_checkpoint = \"BirdModel.h5\"\n    device = device","metadata":{"papermill":{"duration":0.017756,"end_time":"2023-03-27T23:18:54.983112","exception":false,"start_time":"2023-03-27T23:18:54.965356","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2023-04-01T10:30:38.697671Z","iopub.execute_input":"2023-04-01T10:30:38.698088Z","iopub.status.idle":"2023-04-01T10:30:38.707298Z","shell.execute_reply.started":"2023-04-01T10:30:38.698050Z","shell.execute_reply":"2023-04-01T10:30:38.705677Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if cfg.device==\"TPU\":\n    from kaggle_datasets import KaggleDatasets\n    gcs_path = KaggleDatasets().get_gcs_path(cfg.root.split('/')[-1])\nelse:\n    gcs_path = cfg.root","metadata":{"papermill":{"duration":0.014073,"end_time":"2023-03-27T23:18:55.001145","exception":false,"start_time":"2023-03-27T23:18:54.987072","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2023-04-01T10:29:46.004304Z","iopub.execute_input":"2023-04-01T10:29:46.004943Z","iopub.status.idle":"2023-04-01T10:29:46.017013Z","shell.execute_reply.started":"2023-04-01T10:29:46.004903Z","shell.execute_reply":"2023-04-01T10:29:46.015719Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df = pd.read_csv(cfg.metada_file)\ndf.head(5)","metadata":{"papermill":{"duration":0.167374,"end_time":"2023-03-27T23:18:55.172713","exception":false,"start_time":"2023-03-27T23:18:55.005339","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2023-04-01T10:29:46.018892Z","iopub.execute_input":"2023-04-01T10:29:46.019271Z","iopub.status.idle":"2023-04-01T10:29:46.120773Z","shell.execute_reply.started":"2023-04-01T10:29:46.019237Z","shell.execute_reply":"2023-04-01T10:29:46.119537Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def audio2frames(audio, label):\n    #----------------------\n    # Audio\n    #----------------------\n    frames = tf.signal.frame(\n        audio, \n        frame_length=cfg.frame_length, \n        frame_step=cfg.frame_length,\n        pad_end=True, \n        name=\"frames_audio\"\n    )\n    #----------------------\n    # Label\n    #----------------------\n    nlab = tf.shape(frames)[0]\n    label = tf.repeat(label, repeats=nlab)\n    return frames, label\n\ndef read_file(path, label):\n    file = tf.io.read_file(path)\n    aud = tfio.audio.decode_vorbis(file)\n    aud = tfio.audio.resample(aud, rate_in=cfg.sample_rate, rate_out=cfg.desired_sample_rate)\n    aud = tf.squeeze(aud, axis=-1)\n    aud = tf.cast(aud, tf.float32)\n    frames, label = audio2frames(aud, label)\n    return frames, label \n\nencode = {k:v for v,k in enumerate(df[\"primary_label\"].unique(), 1)}\nsample = df.sample(1)\npath = cfg.root+\"/train_audio/\" +sample[\"filename\"].values[0]\nlabel = sample[\"primary_label\"].replace(encode).values[0]\nframe, label = read_file(path, label)\ndisplay.Audio(frame[0].numpy(), rate=cfg.desired_sample_rate)","metadata":{"papermill":{"duration":0.412336,"end_time":"2023-03-27T23:18:55.590195","exception":true,"start_time":"2023-03-27T23:18:55.177859","status":"failed"},"tags":[],"execution":{"iopub.status.busy":"2023-04-01T10:31:14.172141Z","iopub.execute_input":"2023-04-01T10:31:14.172578Z","iopub.status.idle":"2023-04-01T10:31:14.516463Z","shell.execute_reply.started":"2023-04-01T10:31:14.172538Z","shell.execute_reply":"2023-04-01T10:31:14.515126Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"resize_layer = tf.keras.layers.Resizing(*cfg.img_shape)\ndef _bytes_feature(value):\n    \"\"\"Returns a bytes_list from a string / byte.\"\"\"\n    if isinstance(value, type(tf.constant(0))): # if value ist tensor\n        value = value.numpy() # get value of tensor\n    return tf.train.Feature(bytes_list=tf.train.BytesList(value=[value]))\n\ndef _int64_feature(value):\n    \"\"\"Returns an int64_list from a bool / enum / int / uint.\"\"\"\n    return tf.train.Feature(int64_list=tf.train.Int64List(value=[value]))\n\ndef serialize_array(array):\n    array = tf.io.serialize_tensor(array)\n    return array\n\ndef create_example(frame, label):\n    feature = {\n        \"spec\": _bytes_feature(serialize_array(frame)),\n        \"label\": _int64_feature(label)\n    }\n    example = tf.train.Example(features=tf.train.Features(feature=feature))\n    return example\n\ndef parse_tfrecord(example):\n    feature_description = {\n        \"spec\": tf.io.FixedLenFeature([], tf.string),\n        \"label\": tf.io.FixedLenFeature([], tf.int64),\n    }\n    example = tf.io.parse_single_example(example, feature_description)\n    example[\"spec\"] =tf.io.parse_tensor(example[\"spec\"], tf.float32)\n    return example\n\ndef spectrogram(frame):\n    spec = tf.signal.stft(\n        frame, frame_length=cfg.window, frame_step=cfg.strides,fft_length=cfg.nfft, name=\"spec\"\n    )\n    spec = tf.math.abs(spec)\n    spec = tf.transpose(spec)\n    spec = spec[..., tf.newaxis]\n    std = tf.math.reduce_std(spec, axis=0)\n    mean = tf.math.reduce_mean(spec, axis=0)\n    spec = (spec - mean)/(std + 1e-6)\n    return spec\n\n\ndef process(frames, label):\n    specs = tf.map_fn(spectrogram, elems=frames, dtype=tf.float32)\n    return specs, label","metadata":{"papermill":{"duration":null,"end_time":null,"exception":null,"start_time":null,"status":"pending"},"tags":[],"execution":{"iopub.status.busy":"2023-04-01T10:29:46.274847Z","iopub.execute_input":"2023-04-01T10:29:46.275848Z","iopub.status.idle":"2023-04-01T10:29:46.290258Z","shell.execute_reply.started":"2023-04-01T10:29:46.275808Z","shell.execute_reply":"2023-04-01T10:29:46.288918Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from tqdm.notebook import tqdm\n\ndef create_dataset(paths, labels):\n    with strategy.scope():\n        dataset = tf.data.Dataset.from_tensor_slices((paths, labels))\n        dataset = dataset.map(read_file, num_parallel_calls=tf.data.AUTOTUNE)\n        dataset = dataset.map(process, num_parallel_calls=tf.data.AUTOTUNE)\n        dataset = dataset.prefetch(buffer_size=tf.data.AUTOTUNE)\n    return dataset\n\ndef frame2records(paths, labels, tf_record, record_size=2048):\n    num_records = 0\n    count = 0\n    writer = None\n    dataset = create_dataset(paths, labels)\n    total = 0 \n    for fl, ll in tqdm(dataset):\n        ll = tf.cast(ll, tf.int16)\n        fl = tf.image.resize(fl, size=cfg.img_shape)\n        examples = list(map(create_example, tf.unstack(fl, axis=0), tf.unstack(ll, axis=0)))\n        for example in examples:\n            if writer is None:\n                file = f\"{tf_record}/file_{num_records}.tfrec\"\n                writer = tf.io.TFRecordWriter(file)\n            writer.write(example.SerializeToString())\n            count += 1\n            total += 1\n            if count > record_size:\n                writer.close()\n                num_records += 1\n                writer = None\n                count = 0\n    if writer is not None:\n        writer.close()\n        num_records += 1\n    return total","metadata":{"papermill":{"duration":null,"end_time":null,"exception":null,"start_time":null,"status":"pending"},"tags":[],"execution":{"iopub.status.busy":"2023-04-01T09:57:30.221895Z","iopub.execute_input":"2023-04-01T09:57:30.222363Z","iopub.status.idle":"2023-04-01T09:57:30.235151Z","shell.execute_reply.started":"2023-04-01T09:57:30.222323Z","shell.execute_reply":"2023-04-01T09:57:30.233552Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def train_split_label_balanced(df, labels, test_size=0.3, random_state=1024, seuil=8):\n    # Like we observe before some class are less represented in the dataset \n    # So We want to define this function to split the data taking into account \n    # The weigth of the labels and we define a int seuil for the class that only get\n    # Get in the train_df, in this way the train set will complete will all label sample\n    df_train, df_valid = None, None \n    for lab in tqdm(labels):\n        dff = df[df[\"primary_label\"] == lab]\n        if dff.shape[0] <= seuil:\n            df_train = dff.copy() if df_train is None else pd.concat([df_train, dff.copy()])\n        else:\n            dff_train, dff_valid = train_test_split(dff, test_size=test_size, random_state=random_state)\n            df_train = dff_train if df_train is None else pd.concat([df_train, dff_train])\n            df_valid = dff_valid if df_valid is None else pd.concat([df_valid, dff_valid])\n    return df_train, df_valid","metadata":{"papermill":{"duration":null,"end_time":null,"exception":null,"start_time":null,"status":"pending"},"tags":[],"execution":{"iopub.status.busy":"2023-03-28T09:36:03.867899Z","iopub.execute_input":"2023-03-28T09:36:03.868258Z","iopub.status.idle":"2023-03-28T09:36:03.876451Z","shell.execute_reply.started":"2023-03-28T09:36:03.868224Z","shell.execute_reply":"2023-03-28T09:36:03.875572Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from sklearn.model_selection import train_test_split\nfrom sklearn.utils import shuffle\ndf = shuffle(df, random_state=1024)\ntrain_df, valid_df = train_split_label_balanced(df, labels=df[\"primary_label\"].unique(), test_size=0.3)\nfilepaths = train_df[\"filename\"].map(lambda x: os.path.join(cfg.train_dir, x))\nlabels = train_df[\"primary_label\"].replace(encode)\nprint(\"Training size | Shape: \", len(filepaths))\ndirectory = os.path.join(cfg.preprocessing_dir, \"train\")\nos.makedirs(directory, exist_ok=True)\ntotal = frame2records(filepaths, labels, tf_record=directory)\ndff = pd.DataFrame([[train_df.shape[0], cfg.records_size, total, cfg.frame_duration, cfg.sample_rate]], \n                   columns=[\"Shape\", \"Records_size\", \"NumberOfRecords\", \"frame_duration\", \"sample_rate\"])\ndff.to_csv(os.path.join(cfg.preprocessing_dir, \"train.csv\"))\nprint(\"Train saved with success\")\n# Validation to records\nfilepaths = valid_df[\"filename\"].map(lambda x: os.path.join(cfg.train_dir, x))\nlabels = valid_df[\"primary_label\"].replace(encode)\nprint(\"Validation size | Shape: \", len(filepaths))\ndirectory = os.path.join(cfg.preprocessing_dir, \"validation\")\nos.makedirs(directory, exist_ok=True)\ntotal = frame2records(filepaths, labels, tf_record=directory)\ndff = pd.DataFrame([[valid_df.shape[0], cfg.records_size, total, cfg.frame_duration, cfg.sample_rate]], \n                   columns=[\"Shape\", \"Records_size\", \"NumberOfRecords\", \"frame_duration\", \"sample_rate\"])\ndff.to_csv(os.path.join(cfg.preprocessing_dir, \"validation.csv\"))\nprint(\"Validaton saved with sucess\")\nprint('Notebook ran without error !!!')","metadata":{"papermill":{"duration":null,"end_time":null,"exception":null,"start_time":null,"status":"pending"},"tags":[],"execution":{"iopub.status.busy":"2023-03-28T09:37:42.182280Z","iopub.execute_input":"2023-03-28T09:37:42.183163Z","iopub.status.idle":"2023-03-28T09:37:53.418604Z","shell.execute_reply.started":"2023-03-28T09:37:42.183101Z","shell.execute_reply":"2023-03-28T09:37:53.417142Z"},"trusted":true},"execution_count":null,"outputs":[]}]}