{"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":"markdown","source":"# This is not the main code that we used\n# It only represents the data analysis and augmentation part\n# The main code that we run is not a notebook.\n# It is however heavily inspired by the following github repo: https://github.com/y-kawagu/dcase2020_task2_baseline\nPls check it for reference","metadata":{}},{"cell_type":"code","source":"!pip install kaggle\n\nfrom google.colab import files\n\nuploaded = files.upload()\n\nfor fn in uploaded.keys():\n  print('User uploaded file \"{name}\" with length {length} bytes'.format(\n      name=fn, length=len(uploaded[fn])))\n  \n# Then move kaggle.json into the folder where the API expects to find it.\n!mkdir -p ~/.kaggle/ && mv kaggle.json ~/.kaggle/ && chmod 600 ~/.kaggle/kaggle.json\n\n!kaggle competitions download -c eurecom-aml-2022-challenge-2\n!unzip eurecom-aml-2022-challenge-2.zip\n\n!pip install torchsummary\n!pip install dl-cliche\n!pip install librosa\n!pip install torch\n!pip install pytorch-lightning\n\nfrom shutil import copyfile\nimport wave\nimport contextlib\nimport soundfile as sf\n\n# public modules\nimport torch\nimport torch.nn.functional as F\nimport torchsummary\nimport pytorch_lightning as pl\nimport random\nimport librosa\nimport os\nimport glob\nimport csv\nimport re\nimport itertools\nimport sys\n#import path\nfrom pathlib import Path\nimport numpy\nimport seaborn as sns\nfrom torch import nn\nfrom tqdm import tqdm\nfrom sklearn import metrics\nfrom dlcliche.utils import *\nfrom dlcliche.notebook import *\nfrom dlcliche.utils import (\n    sys, random, Path, np, plt, EasyDict,\n    ensure_folder, deterministic_everything,\n)","metadata":{"id":"X-cQD9Izal9B","outputId":"ff6fc44b-4da9-426f-8905-df5e6e1b5ca4"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Data Exploration\n\nHow many samples included?\n\nHow are the raw wave files?\n\nHow are the log mel spectrogram of the wave files?","metadata":{"id":"6f0c31b1"}},{"cell_type":"code","source":"def check_duration_framerate(directory):\n  max_duration = 0\n  min_duration = 1000000\n  max_rate = 0\n  min_rate = 1000000\n  for filename in os.listdir(directory):\n    fname = os.path.join(directory, filename)\n    with contextlib.closing(wave.open(fname,'r')) as f:\n        frames = f.getnframes()\n        rate = f.getframerate()\n        duration = frames / float(rate)\n\n        if duration >= max_duration:\n          max_duration = duration\n        if duration <= min_duration:\n          min_duration = duration\n        if rate >= max_rate:\n          max_rate = rate\n        if rate <= min_rate:\n          min_rate = rate\n  print(\"Directory:\",directory)  \n  print(\"\\tMax duration:\",max_duration,\"Min duration:\",min_duration)\n  print(\"\\tMax Rate:\",max_rate,\"Min Rate:\",min_rate)","metadata":{"id":"er06nXr3aX1O"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"check_duration_framerate(\"dev_data/dev_data/slider/test\")\ncheck_duration_framerate(\"dev_data/dev_data/slider/train\")\ncheck_duration_framerate(\"eval_data/eval_data/slider/test\")\ncheck_duration_framerate(\"eval_data/eval_data/slider/train\")","metadata":{"id":"kmTPMQ9WbWG3","outputId":"2d9f3d23-6f37-4cfd-e127-f5a107b5842c"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def calc_test_total(path):\n  DATA_ROOT=Path(path)\n  types = [t.name for t in sorted(DATA_ROOT.glob('*')) if t.is_dir()]\n  print('Machine types:', types)\n\n  df = pd.DataFrame()\n  df['file'] = sorted(DATA_ROOT.glob('*/*/*.wav'))\n  df['type'] = df.file.map(lambda f: f.parent.parent.name)\n  df['split'] = df.file.map(lambda f: f.parent.name)\n  df['id'] = df.file.map(lambda s: str(s).split('/')[-1].split('_')[-2])\n\n  agg = df.groupby(['split']).agg('count')\n  fig = plt.figure(figsize=(12.0, 6.0))\n  g = sns.barplot(x=\"id\", y=\"file\", hue=\"split\", data=agg.reset_index())\n  plt.ylabel(\"number of files\")\n  plt.show()\n\n  print(agg.transpose())\n  agg = df.groupby(['id', 'split']).agg('count')\n  fig = plt.figure(figsize=(12.0, 6.0))\n  g = sns.barplot(x=\"id\", y=\"file\", hue=\"split\", data=agg.reset_index())\n  plt.xlabel(\"machine id\")\n  plt.ylabel(\"number of files\")\n  plt.show()\n  print(agg.transpose())\n  return df, types","metadata":{"id":"fS2geGUXIoBW"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def calc_test_ratios(df):\n  name_list = [\"total\"]+df[\"id\"].unique().tolist()\n  ratio_list = []\n\n  agg = df.groupby(['split']).agg('count')\n\n  test_nr = agg.iloc[0]['file']\n  train_nr = agg.iloc[1]['file']\n\n  ratio = test_nr/(test_nr+train_nr)\n  ratio_list.append(ratio)\n\n  agg = df.groupby([\"id\",'split']).agg('count')\n\n  for i in range(0,5,2):\n    test_nr = agg.iloc[i]['file']\n    train_nr = agg.iloc[i+1]['file']\n\n    ratio = test_nr/(test_nr+train_nr)\n    ratio_list.append(ratio)\n\n\n  plt.bar(name_list,ratio_list)\n  plt.xlabel(\"machine id\")\n  plt.ylabel(\"ratio: test/all\")\n  plt.title('Test ratio')\n  plt.show()\n  return name_list,ratio_list","metadata":{"id":"Yk2_PsaKdj2S"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def calc_anomaly_ratios(df):\n\n  df_in_work = df\n\n  df_in_work['anomaly'] = df['file'].astype('str').str.contains('anomaly', na=\"Error\")\n  #df_normal['normal'] = df['file'].astype('str').str.contains('normal', na=\"Error\")\n  \n  df_anomaly = df_in_work[df_in_work[\"anomaly\"]==True]\n  df_normal = df_in_work[df_in_work[\"anomaly\"]==False]\n\n  if df_anomaly.shape[0] > 0:\n\n    agg_anomaly = df_anomaly.groupby(['id', 'split']).agg('count')\n    \n    fig = plt.figure(figsize=(12.0, 6.0))\n    g = sns.barplot(x=\"id\", y=\"file\", hue=\"split\", data=agg_anomaly.reset_index())\n    plt.xlabel(\"machine id\")\n    plt.ylabel(\"number of files\")\n    plt.title('Anomaly files')\n    plt.show()\n    print(agg_anomaly.transpose())\n\n  agg_normal = df_normal.groupby(['id', 'split']).agg('count')\n\n  fig = plt.figure(figsize=(12.0, 6.0))\n  g = sns.barplot(x=\"id\", y=\"file\", hue=\"split\", data=agg_normal.reset_index())\n  plt.xlabel(\"machine id\")\n  plt.ylabel(\"number of files\")\n  plt.title('Normal files')\n  plt.show()\n  print(agg_normal.transpose())","metadata":{"id":"IA6jAEWC_LZO"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"path = \"dev_data/dev_data\"\n\ndf, types = calc_test_total(path)\ncalc_test_ratios(df)\ncalc_anomaly_ratios(df)","metadata":{"id":"f7Wmws0l9pnG","outputId":"c86a9b88-72b6-4af5-8ed1-d2a23a3062ce"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"path = \"eval_data/eval_data\"\n\ndf,types = calc_test_total(path)\ncalc_test_ratios(df)\ncalc_anomaly_ratios(df)","metadata":{"id":"ZNlqmMxxROv3","outputId":"24ccf18e-aed0-464c-df1b-3ca1705282dd"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def manipulate(data, sampling_rate, shift_max, shift_direction):\n    shift = np.random.randint(sampling_rate * shift_max)\n    if shift_direction == 'right':\n        shift = -shift\n    elif shift_direction == 'both':\n        direction = np.random.randint(0, 2)\n        if direction == 1:\n            shift = -shift\n    augmented_data = np.roll(data, shift)\n    # Set to silence for heading/ tailing\n    if shift > 0:\n        augmented_data[:shift] = 0\n    else:\n        augmented_data[shift:] = 0\n    return augmented_data","metadata":{"id":"oKCbTg7Uv87Q"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"The raw audio file is time-seris data which indicates the amplitude of the sound over time (right figures). \n\nHowever, deep learning models rarely take this raw audio directly as input, the common practice is to convert the audio into a spectrogram (left figures). The spectrogram is a concise ‘snapshot’ of an audio wave and since it is an image, it is well suited to being input to CNN-based architectures developed for handling images. If you want to understand the audio spectrogram, this Audio Deep Learning [series](https://towardsdatascience.com/audio-deep-learning-made-simple-part-1-state-of-the-art-techniques-da1d3dff2504) is very useful. In this notebook, we use the spectrogram as input.","metadata":{"id":"fac8ec5e"}},{"cell_type":"code","source":"def data_augmentation(dirname,ext = '.wav',type=\"noise\",frame_rate = 16000,shift_max=0.2):\n\n  print(\"Nr files before: \",len(os.listdir(dirname)))\n  # iterating over all files\n  for files in os.listdir(dirname):\n\n    if files.endswith(ext) and \"_augmentation\" in files:\n      file_path = os.path.join(dirname,files)\n      #print(\"Delete\",file_path)\n      os.remove(file_path)\n\n  for files in os.listdir(dirname):\n    if files.endswith(ext):\n\n      file_path = os.path.join(dirname,files)\n      wav, sr = librosa.load(file_path,sr=None)\n      file_path_output = os.path.join(file_path.split(ext)[0]+\"_augmentation\"+ext)\n\n      if type == \"noise\":\n        wav_n = wav + 0.009*np.random.normal(0,1,len(wav))\n\n      elif type == \"shift\":\n        wav_n = manipulate(wav, frame_rate, shift_max, \"both\")\n      else:\n        print(\"Deleted all augmented files. Could not find new augmentation type\")\n        return\n      sf.write(file_path_output, wav_n, frame_rate)\n    else:\n      print(\"Found a non wave file in folder\")\n\n\n  print(\"Nr files after: \",len(os.listdir(dirname)))","metadata":{"id":"VIGR-WoVspHB"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"data_augmentation(\"eval_data/eval_data/slider/train\",type=\"shift\")\ndata_augmentation(\"eval_data/eval_data/slider/train\",type=\"noise\")","metadata":{"id":"ovmamIFfsw5o","outputId":"5faccae4-c83c-49ac-d3bb-9d60e6225ff6"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"check_duration_framerate(\"eval_data/eval_data/slider/train\")","metadata":{"id":"upImE0aLxteC","outputId":"f75e29dd-26bb-4b32-aee2-a67ddd517b0e"},"execution_count":null,"outputs":[]}]}