{"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":"# AML Challenge 2 Baseline Solution\n\nThis notebook is almost based on the Github [respository](https://github.com/daisukelab/dcase2020_task2_variants). \n\nWe replicate the (Variational Auto-Encoder) VAE method for this AML challenge 2 which is a small scale of the official DCASE challenge [task 2](https://dcase.community/challenge2020/task-unsupervised-detection-of-anomalous-sounds). ","metadata":{"id":"O2a8aWPl7E_8"}},{"cell_type":"markdown","source":"# Required Python Packages\n\nLet's install some python packages used in this notebook.","metadata":{"id":"YLpSJk0L7E__"}},{"cell_type":"code","source":"!pip install torchsummary\n!pip install dl-cliche\n!pip install pytorch_lightning","metadata":{"execution":{"iopub.status.busy":"2022-05-18T10:31:58.463867Z","iopub.execute_input":"2022-05-18T10:31:58.464155Z","iopub.status.idle":"2022-05-18T10:32:16.792888Z","shell.execute_reply.started":"2022-05-18T10:31:58.464125Z","shell.execute_reply":"2022-05-18T10:32:16.792Z"},"id":"RWi-ZtQF7FAB","outputId":"a7a60f73-d9cb-49ea-e161-7079e61512b1","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"To import our own functions, you could upload the .py files in the input folder and do as we do for the \"common.py\" and \"pytorch_common.py\" files.","metadata":{"id":"KPVTf0qX7FAD"}},{"cell_type":"code","source":"!pip install path\n!pip uninstall common","metadata":{"id":"k3TWUa7mvNFA","outputId":"3d9ed19f-58ef-441a-ec10-98d1cf8fb14f"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from google.colab import drive\ndrive.mount('/content/drive')","metadata":{"id":"TLvheL_mvO3r","outputId":"5ad2e60c-f42c-4ef0-9f44-3ca5babd14d4"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"! unzip \"drive/MyDrive/AML/eurecom-aml-2022-challenge-2.zip\" -d \"/content/data\"","metadata":{"id":"TjKj0dpOvp4l","outputId":"4980d42a-88ce-46c1-f086-56f2085a75e0"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from shutil import copyfile\n\n# copy our file into the working directory (make sure it has .py suffix)\ncopyfile(src = \"drive/MyDrive/AML/pytorch_common.py\", dst = \"pytorch_common.py\")\ncopyfile(src = \"drive/MyDrive/AML/common.py\", dst = \"common.py\")\n\n# import all our functions\nimport common as com\nimport pytorch_common\nfrom pytorch_common import *\n\n# public modules\nimport torch\nimport torch.nn.functional as F\nimport torchsummary\nimport pytorch_lightning as pl\nimport random\nimport common as com\nimport librosa\nimport os\nimport glob\nimport csv\nimport re\nimport itertools\nimport sys\nimport 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)\n","metadata":{"scrolled":true,"execution":{"iopub.status.busy":"2022-05-18T10:32:16.79517Z","iopub.execute_input":"2022-05-18T10:32:16.795481Z","iopub.status.idle":"2022-05-18T10:32:16.879435Z","shell.execute_reply.started":"2022-05-18T10:32:16.795425Z","shell.execute_reply":"2022-05-18T10:32:16.878702Z"},"id":"xcCBmsFS7FAE","trusted":true},"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":"U8WR_ZcY7FAG"}},{"cell_type":"markdown","source":"## Baseline Analysis\n","metadata":{"id":"D-Fw7cweyxAT"}},{"cell_type":"code","source":"# development dataset\nDATA_ROOT=Path(\"data/dev_data/dev_data\")\ntypes = [t.name for t in sorted(DATA_ROOT.glob('*')) if t.is_dir()]\nprint('Machine types:', types)\n\ndf = pd.DataFrame()\ndf['file'] = sorted(DATA_ROOT.glob('*/*/*.wav'))\ndf['type'] = df.file.map(lambda f: f.parent.parent.name)\ndf['split'] = df.file.map(lambda f: f.parent.name)\ndf['id'] = df.file.map(lambda s: str(s).split('/')[-1].split('_')[-2])\ndf_dev = df\ndf_dev['file'] = df_dev['file'].astype(\"string\")\n\nagg = df.groupby(['id', 'split']).agg('count')\nfig = plt.figure(figsize=(12.0, 6.0))\ng = sns.barplot(x=\"id\", y=\"file\", hue=\"split\", data=agg.reset_index())\nplt.xlabel(\"machine id\")\nplt.ylabel(\"number of files\")\nplt.show()\nagg.transpose()","metadata":{"execution":{"iopub.status.busy":"2022-05-18T10:32:16.882817Z","iopub.execute_input":"2022-05-18T10:32:16.884169Z","iopub.status.idle":"2022-05-18T10:32:17.351581Z","shell.execute_reply.started":"2022-05-18T10:32:16.88412Z","shell.execute_reply":"2022-05-18T10:32:17.350852Z"},"id":"tJIVfkY07FAH","outputId":"094f49a5-11dd-482a-cfd0-26023696f964","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# evaluation dataset\nEVAL_DATA_ROOT=Path(\"data/eval_data/eval_data\")\ntypes = [t.name for t in sorted(EVAL_DATA_ROOT.glob('*')) if t.is_dir()]\nprint('Machine types:', types)\n\ndf = pd.DataFrame()\ndf['file'] = sorted(EVAL_DATA_ROOT.glob('*/*/*.wav'))\ndf['type'] = df.file.map(lambda f: f.parent.parent.name)\ndf['split'] = df.file.map(lambda f: f.parent.name)\ndf['id'] = df.file.map(lambda s: str(s).split('/')[-1].split('_')[-2])\ndf_eval = df\ndf_eval['file'] = df_eval['file'].astype(\"string\")\n\nagg = df.groupby(['id', 'split']).agg('count')\nfig = plt.figure(figsize=(12.0, 6.0))\ng = sns.barplot(x=\"id\", y=\"file\", hue=\"split\", data=agg.reset_index())\nplt.xlabel(\"machine id\")\nplt.ylabel(\"number of files\")\nplt.show()\nagg.transpose()","metadata":{"execution":{"iopub.status.busy":"2022-05-18T10:32:17.353599Z","iopub.execute_input":"2022-05-18T10:32:17.353946Z","iopub.status.idle":"2022-05-18T10:32:17.979973Z","shell.execute_reply.started":"2022-05-18T10:32:17.353907Z","shell.execute_reply":"2022-05-18T10:32:17.979321Z"},"id":"oTD3cFHd7FAI","outputId":"504d022d-11cf-4a24-e91b-2825d2928933","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_log_mel_spectrogram(filename, n_mels=64,\n                        n_fft=1024,\n                        hop_length=512,\n                        power=2.0):\n    wav, sampling_rate = com.file_load(filename)\n    mel_spectrogram = librosa.feature.melspectrogram(y=wav,\n                                                     sr=sampling_rate,\n                                                     n_fft=n_fft,\n                                                     hop_length=hop_length,\n                                                     n_mels=n_mels,\n                                                     power=power)\n    log_mel_spectrogram = 20.0 / power * np.log10(mel_spectrogram + sys.float_info.epsilon)\n    return log_mel_spectrogram, wav, sampling_rate\n","metadata":{"execution":{"iopub.status.busy":"2022-05-18T11:17:56.222534Z","iopub.execute_input":"2022-05-18T11:17:56.223084Z","iopub.status.idle":"2022-05-18T11:17:57.130993Z","shell.execute_reply.started":"2022-05-18T11:17:56.223047Z","shell.execute_reply":"2022-05-18T11:17:57.130306Z"},"id":"BL836bQs7FAJ","trusted":true},"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":"n3CyxYvH7FAL"}},{"cell_type":"markdown","source":"**Wawe Forms**","metadata":{"id":"Kj5z2PoPvNyC"}},{"cell_type":"code","source":"import librosa\ndef load_sound_file(path, mono=False, channel=0):\n    signal, sr = librosa.load(path, sr=None, mono=mono)\n    if signal.ndim < 2:\n        sound_file = signal, sr\n    else:\n        sound_file = signal[channel, :], sr\n\n    return sound_file","metadata":{"id":"l_RFB0swRgxt"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Code used for styling of the plots\nplt.style.use(\"Solarize_Light2\")\nprop_cycle = plt.rcParams[\"axes.prop_cycle\"]\ncolors = prop_cycle.by_key()[\"color\"]","metadata":{"id":"g3xcIcSvUf7U"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import IPython.display\nimport librosa.display","metadata":{"id":"rhoWB9A_Wrnx"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Machine Sounds","metadata":{"id":"p3BqDLZVY5S5"}},{"cell_type":"code","source":"def get_sound_sample(id, ix, train_test=\"train\", dev_eval=\"dev\", nor_anom=\"normal\"):\n  if dev_eval == \"dev\":\n    selected = df_dev.loc[(df_dev[\"id\"]==id) & (df_dev[\"split\"]==train_test) & (df_dev['file'].str.contains(nor_anom))].reset_index()\n    return  Path(selected.file[ix])\n  elif dev_eval == \"eval\":\n    if nor_anom==\"\":\n      selected = df_eval.loc[(df_eval[\"id\"]==id) & (df_eval[\"split\"]==train_test)].reset_index()\n      return  Path(selected.file[ix])\n    selected = df_eval.loc[(df_eval[\"id\"]==id) & (df_eval[\"split\"]==train_test) & (df_eval['file'].str.contains(nor_anom))].reset_index()\n    return  Path(selected.file[ix])","metadata":{"id":"dZVmb6U7ZJWK"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Machine 00 (01)","metadata":{"id":"6KnzOF35YOJM"}},{"cell_type":"code","source":"file_path = get_sound_sample(\"00\", 4)\nprint(file_path)\nnormal_signal, sr = load_sound_file(file_path)\nIPython.display.Audio(normal_signal, rate=sr) #code to listen to sound of wav-file","metadata":{"id":"XU4we0uqWRGz","outputId":"4d8b27a9-1581-4eda-97a6-3f8a082944a8"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"file_path = get_sound_sample(\"00\", 0, \"test\", \"dev\", \"anomaly\")\nprint(file_path)\nnormal_signal, sr = load_sound_file(file_path)\nIPython.display.Audio(normal_signal, rate=sr) #code to listen to sound of wav-file","metadata":{"id":"mObHOKQAWqB3","outputId":"c4fbb98c-3cb0-4819-f414-5496df58d659"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"file_path = get_sound_sample(\"01\", 7, \"train\", \"eval\", \"normal\")\nprint(file_path)\nnormal_signal, sr = load_sound_file(file_path)\nIPython.display.Audio(normal_signal, rate=sr) #code to listen to sound of wav-file","metadata":{"id":"hGz9TuFBjcoX","outputId":"bd1a8df2-ef86-4b47-cc8e-10f8fc27edb2"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"file_path = get_sound_sample(\"01\", 19, \"test\", \"eval\", \"\")\nprint(file_path)\nnormal_signal, sr = load_sound_file(file_path)\nIPython.display.Audio(normal_signal, rate=sr) #code to listen to sound of wav-file","metadata":{"id":"u_sckKsRmryg","outputId":"2457fd0f-6230-4c2d-b5dd-951eb5b2410c"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Machine 02 (03)","metadata":{"id":"pf_6-u4nYUJ4"}},{"cell_type":"code","source":"file_path = get_sound_sample(\"02\", 2)\nprint(file_path)\nnormal_signal, sr = load_sound_file(file_path)\nIPython.display.Audio(normal_signal, rate=sr) #code to listen to sound of wav-file","metadata":{"outputId":"e244249f-c9b2-4899-eb90-13a6d4bc447e","id":"bhr8DnkYYUJ7"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"file_path = get_sound_sample(\"02\", 5, \"test\", \"dev\", \"anomaly\")\nprint(file_path)\nnormal_signal, sr = load_sound_file(file_path)\nIPython.display.Audio(normal_signal, rate=sr) #code to listen to sound of wav-file","metadata":{"outputId":"c83f7f20-4778-4e9a-ae69-4dc451ef3d0e","id":"FFYodtxpYUJ9"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"file_path = get_sound_sample(\"03\",11, \"train\", \"eval\", \"normal\")\nprint(file_path)\nnormal_signal, sr = load_sound_file(file_path)\nIPython.display.Audio(normal_signal, rate=sr) #code to listen to sound of wav-file","metadata":{"id":"AbV80hFsl8sz","outputId":"e209348d-d1c8-4e0d-8a52-ba03459d0954"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Machine 04 (05)\n","metadata":{"id":"5KD1Bjj3Y3Kg"}},{"cell_type":"code","source":"file_path = get_sound_sample(\"04\", 2)\nprint(file_path)\nnormal_signal, sr = load_sound_file(file_path)\nIPython.display.Audio(normal_signal, rate=sr) #code to listen to sound of wav-file","metadata":{"outputId":"88512f20-c173-4386-c5e3-d3c22a466de6","id":"CYJPkCgFY3Kl"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"file_path = get_sound_sample(\"04\", 6, \"test\", \"dev\", \"anomaly\")\nprint(file_path)\nnormal_signal, sr = load_sound_file(file_path)\nIPython.display.Audio(normal_signal, rate=sr) #code to listen to sound of wav-file","metadata":{"outputId":"0d587cf7-19e1-4b0f-d3e8-1ed21e5e8e64","id":"cAxcb5ZAY3Kn"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"file_path = get_sound_sample(\"05\", 0, \"train\", \"eval\", \"normal\")\nprint(file_path)\nnormal_signal, sr = load_sound_file(file_path)\nIPython.display.Audio(normal_signal, rate=sr) #code to listen to sound of wav-file","metadata":{"id":"1VuVsxQXh9NN","outputId":"a3561b8f-eed3-49a3-dcb8-df0805329be7"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Plot Machine Sounds (Wave and Mel)\n","metadata":{"id":"A7ERUszIY9Dz"}},{"cell_type":"markdown","source":"### Functions","metadata":{"id":"gyb3DkGcyKYT"}},{"cell_type":"code","source":"def plot_waves(normal, anomaly, sr, id):\n  fig = plt.figure(figsize=(24, 6))\n\n  plt.subplot(1, 3, 1)\n\n  librosa.display.waveplot(\n      normal,\n      sr=sr,\n      alpha=0.5,\n      color=colors[1],\n      linewidth=0.5,\n      label=f\"Machine #id_{id} - Normal Signal\",\n  )\n  plt.title(\"Normal Signal\")\n\n  plt.subplot(1, 3, 2)\n  librosa.display.waveplot(\n      anomaly,\n      sr=sr,\n      alpha=0.6,\n      color=colors[5],\n      linewidth=0.5,\n      label=f\"Machine #id_{id} - Abnormal Signal\",\n  )\n  plt.title(\"Abnormal Signal\")\n\n  plt.subplot(1, 3, 3)\n  librosa.display.waveplot(\n      anomaly,\n      sr=sr,\n      alpha=0.6,\n      color=colors[5],\n      linewidth=0.5,\n      label=\"Abnormal Signal\",\n  )\n  librosa.display.waveplot(\n      normal,\n      sr=sr,\n      alpha=0.5,\n      color=colors[1],\n      linewidth=0.5,\n      label=\"Normal Signal\",\n  )\n  plt.title(\"Both Signals\")\n\n  fig.suptitle(f\"Machine #id_{id} - 2D Representation of the Wave Forms\", fontsize=16)\n  plt.legend()\n  plt.show()","metadata":{"id":"AW9EdGxRvSMA"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def plot_mels(normal, anomaly, sr, n_mels=64, hop_length=512, n_fft=2048, power=2.0):\n  normal_mel_spectrogram = librosa.feature.melspectrogram(\n      normal, sr=sr, n_fft=n_fft, hop_length=hop_length, n_mels=n_mels\n  )\n  normal_log_mel_spectrogram = 20.0 / power * np.log10(normal_mel_spectrogram + sys.float_info.epsilon)\n\n  abnormal_mel_spectrogram = librosa.feature.melspectrogram(\n      anomaly, sr=sr, n_fft=n_fft, hop_length=hop_length, n_mels=n_mels\n  )\n  abnormal_log_mel_spectrogram = 20.0 / power * np.log10(abnormal_mel_spectrogram + sys.float_info.epsilon)\n\n  fig = plt.figure(figsize=(24, 6))\n\n  plt.subplot(1, 2, 1)\n  librosa.display.specshow(\n      normal_log_mel_spectrogram,\n      sr=sr,\n      hop_length=hop_length,\n      x_axis=\"time\",\n      y_axis=\"mel\",\n      cmap=\"viridis\",\n  )\n  plt.title(\"Machine #id_02 - Normal Signal\")\n  plt.xlabel(\"Time (s)\")\n  plt.ylabel(\"Frequency (Hz)\")\n  plt.colorbar(format=\"%+2.0f dB\")\n\n  plt.subplot(1, 2, 2)\n  librosa.display.specshow(\n      abnormal_log_mel_spectrogram,\n      sr=sr,\n      hop_length=hop_length,\n      x_axis=\"time\",\n      y_axis=\"mel\",\n      cmap=\"viridis\",\n  )\n  plt.title(\"Machine #id_02 - Abnormal Signal\")\n  plt.xlabel(\"Time (s)\")\n  plt.ylabel(\"Frequency (Hz)\")\n  plt.colorbar(format=\"%+2.0f dB\")\n\n  plt.show()\n\n  print(f\"The mel-spectrograms have a {normal_mel_spectrogram.shape} shape.\")","metadata":{"id":"b02hq1xbxeNo"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Machine 00 (01)","metadata":{"id":"0UUAXswlyN-r"}},{"cell_type":"code","source":"normal, sr =load_sound_file(get_sound_sample(\"00\", 0))\nanomaly, _ = load_sound_file(get_sound_sample(\"00\", 0, \"test\", \"dev\", \"anomaly\"))\nplot_waves(normal, anomaly, sr, \"00\")","metadata":{"id":"o-HMDnUQm_33","outputId":"e5361271-213c-429c-95e0-b4304cb110f9"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"normal, sr = load_sound_file(get_sound_sample(\"00\", 0))\nanomaly, _ = load_sound_file(get_sound_sample(\"00\", 0, \"test\", \"dev\", \"anomaly\"))\nplot_mels(normal, anomaly, sr)","metadata":{"id":"kpF44A-cx6iz","outputId":"bab92757-2a41-4166-853e-569205dfe6d0"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Machine 02 (03)","metadata":{"id":"WB97IQxByWty"}},{"cell_type":"code","source":"normal, sr = load_sound_file(get_sound_sample(\"02\", 0))\nanomaly, _ = load_sound_file(get_sound_sample(\"02\", 8, \"test\", \"dev\", \"anomaly\"))\nplot_waves(normal, anomaly, sr, \"02\")","metadata":{"id":"aAHD0X3AoaTg","outputId":"b62f3065-a88d-4e2c-fcf3-80ecc3db8577"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"normal, sr = load_sound_file(get_sound_sample(\"02\", 0))\nanomaly, _ = load_sound_file(get_sound_sample(\"02\", 0, \"test\", \"dev\", \"anomaly\"))\nplot_mels(normal, anomaly, sr)","metadata":{"id":"xUlO0rWzyhnD","outputId":"050b207f-832d-4286-8767-04c664527616"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Machine 04 (05)","metadata":{"id":"myNgqgOpycyv"}},{"cell_type":"code","source":"normal, sr = load_sound_file(get_sound_sample(\"04\", 0))\nanomaly, _ = load_sound_file(get_sound_sample(\"04\", 0, \"test\", \"dev\", \"anomaly\"))\nplot_waves(normal, anomaly, sr, \"04\")","metadata":{"id":"g7TI37sDrVjA","outputId":"4ae90e2b-9f14-4dc5-ac70-8c7ba4af2724"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"normal, sr = load_sound_file(get_sound_sample(\"04\", 0))\nanomaly, _ = load_sound_file(get_sound_sample(\"04\", 0, \"test\", \"dev\", \"anomaly\"))\nplot_mels(normal, anomaly)","metadata":{"id":"7YNuVoEUymqk","outputId":"47d8c201-cf5f-4ea6-8cf5-b1916333252e"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Feature Extraction","metadata":{"id":"h3VsRJT3Dkhi"}},{"cell_type":"markdown","source":"### RMS","metadata":{"id":"y2IBrtEIEdwa"}},{"cell_type":"code","source":"def RMS(y, sr, title):\n  # Get RMS value from each frame's magnitude value\n  S, phase = librosa.magphase(librosa.stft(y))\n  rms = librosa.feature.rms(S=S)\n  # Plot the RMS energy\n  fig, ax = plt.subplots(figsize=(15, 6), nrows=2, sharex=True)\n  times = librosa.times_like(rms)\n  ax[0].semilogy(times, rms[0], label='RMS Energy')\n  ax[0].set(xticks=[])\n  ax[0].legend()\n  ax[0].label_outer()\n  librosa.display.specshow(librosa.amplitude_to_db(S, ref=np.max),\n                          y_axis='log', x_axis='time', ax=ax[1])\n  ax[1].set(title=title)","metadata":{"id":"VPopCCxUEdQB"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# normal, sr = load_sound_file(get_sound_sample(\"00\", 0))\n# anomaly, _ = load_sound_file(get_sound_sample(\"00\", 0, \"test\", \"dev\", \"anomaly\"))\nnormal, sr = load_sound_file(get_sound_sample(\"02\", 0))\nanomaly, _ = load_sound_file(get_sound_sample(\"02\", 0, \"test\", \"dev\", \"anomaly\"))\nRMS(normal, sr, \"Normal Sound\")\nRMS(anomaly, sr, \"Abnormal Sound\")","metadata":{"id":"tR40Wg_xEJSr","outputId":"d3f992d1-8e3c-42bb-8c45-ad4a7f70a9d3"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Zero Crossing Rate","metadata":{"id":"ECUH4AuAF8YS"}},{"cell_type":"code","source":"def zero_crossing_rate(y, sr, title=\"Plot\"):\n  zcrs = librosa.feature.zero_crossing_rate(y)\n  print(f\"Zero crossing rate: {sum(librosa.zero_crossings(y))}\")\n  return sum(librosa.zero_crossings(y))\n  #plt.figure(figsize=(15, 3))\n  #plt.plot(zcrs[0])\n  #plt.title(title)","metadata":{"id":"IuVqU5ZgGW52"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# normal, sr = load_sound_file(get_sound_sample(\"00\", 0))\n# anomaly, _ = load_sound_file(get_sound_sample(\"00\", 0, \"test\", \"dev\", \"anomaly\"))\nnormal, sr = load_sound_file(get_sound_sample(\"02\", 0))\nanomaly, _ = load_sound_file(get_sound_sample(\"02\", 0, \"test\", \"dev\", \"anomaly\"))\nzero_crossing_rate(normal, sr, \"Normal\")\nzero_crossing_rate(anomaly, sr, \"Abnormal\")","metadata":{"id":"nlZLoB5KGjAo","outputId":"adf0db3f-d701-42c0-f7df-8bba2c8a9859"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Chroma","metadata":{"id":"vgmEsNohJS4g"}},{"cell_type":"code","source":"def chroma(x, sr, title=\"Title\"):\n  hop_length = 512\n  chromagram = librosa.feature.chroma_stft(x, sr=sr, hop_length=hop_length)\n  fig, ax = plt.subplots(figsize=(15, 3))\n  plt.title(title)\n  img = librosa.display.specshow(chromagram, x_axis='time', y_axis='chroma', hop_length=hop_length, cmap='coolwarm')\n  fig.colorbar(img, ax=ax)","metadata":{"id":"zJ28We2UJXHD"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# normal, sr = load_sound_file(get_sound_sample(\"00\", 0))\n# anomaly, _ = load_sound_file(get_sound_sample(\"00\", 0, \"test\", \"dev\", \"anomaly\"))\nnormal, sr = load_sound_file(get_sound_sample(\"02\", 0))\nanomaly, _ = load_sound_file(get_sound_sample(\"02\", 0, \"test\", \"dev\", \"anomaly\"))\nchroma(normal, sr, \"Normal-ID_02\")\nchroma(anomaly, sr, \"Abnormal-ID_02\")","metadata":{"id":"X2XB9y2CJi4P","outputId":"31ab7b79-d830-4d13-befd-9ea29dcee7d7"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Tempogram","metadata":{"id":"jQ8Obh1zKNDa"}},{"cell_type":"code","source":"def tempogram(y, sr, title=\"tempogram\"):\n  hop_length = 512\n  # Compute local onset autocorrelation\n  oenv = librosa.onset.onset_strength(y=y, sr=sr, hop_length=hop_length)\n  times = librosa.times_like(oenv, sr=sr, hop_length=hop_length)\n  tempogram = librosa.feature.tempogram(onset_envelope=oenv, sr=sr,\n                                        hop_length=hop_length)\n  # Estimate the global tempo for display purposes\n  tempo = librosa.beat.tempo(onset_envelope=oenv, sr=sr,\n                            hop_length=hop_length)[0]\n  fig, ax = plt.subplots(figsize=(15, 3))\n  img = librosa.display.specshow(tempogram, x_axis='time', y_axis='chroma', hop_length=hop_length, cmap='coolwarm')\n  fig.colorbar(img, ax=ax)","metadata":{"id":"jif3WcSgKQGH"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"normal, sr = load_sound_file(get_sound_sample(\"00\", 0))\nanomaly, _ = load_sound_file(get_sound_sample(\"00\", 0, \"test\", \"dev\", \"anomaly\"))\ntempogram(normal, sr, \"Normal\")\ntempogram(anomaly, sr, \"Abnormal\")","metadata":{"id":"8ykhWxZmKXa9","outputId":"6923b16a-76c4-48d8-b661-7b522c55849d"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### MFCCs","metadata":{"id":"aqvZKs4tL8Ou"}},{"cell_type":"code","source":"def mfcc(y, sr, title=\"Title\"):\n  mfccs = librosa.feature.mfcc(y, sr=sr)\n  # Displaying  the MFCCs:\n  plt.figure(figsize=(15, 3))\n  librosa.display.specshow(mfccs, sr=sr, x_axis='time')","metadata":{"id":"qUtr_bj_L_78"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"normal, sr = load_sound_file(get_sound_sample(\"00\", 0))\nanomaly, _ = load_sound_file(get_sound_sample(\"00\", 0, \"test\", \"dev\", \"anomaly\"))\nmfcc(normal, sr, \"Normal\")\nmfcc(anomaly, sr, \"Abnormal\")","metadata":{"id":"-pV8k9jRMK0V","outputId":"e88d6e38-26ad-4504-b366-41f4ce5a90a9"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Network\n\nThe implementation of the Variational Auto-Encoder (VAE) model.","metadata":{"id":"vSD5gBEc7FAM"}},{"cell_type":"code","source":"class VAE(nn.Module):\n    \"\"\"Mostly borrowed from PyTorch example.\n    Thanks to https://github.com/pytorch/examples/blob/master/vae/main.py\n    \"\"\"\n\n    def __init__(self, device, x_dim=640, h_dim=400, z_dim=20):\n        super().__init__()\n        self.x_dim = x_dim\n\n        self.fc11 = nn.Linear(x_dim, h_dim)\n        self.fc12 = nn.Linear(h_dim, h_dim)\n        self.fc21 = nn.Linear(h_dim, z_dim)\n        self.fc22 = nn.Linear(h_dim, z_dim)\n        self.fc31 = nn.Linear(z_dim, h_dim)\n        self.fc32 = nn.Linear(h_dim, h_dim)\n        self.fc4 = nn.Linear(h_dim, x_dim)\n\n    def encode(self, x):\n        x = F.relu(self.fc11(x))\n        x = F.relu(self.fc12(x))\n        return self.fc21(x), self.fc22(x)\n\n    def reparameterize(self, mu, logvar):\n        std = torch.exp(0.5*logvar)\n        eps = torch.randn_like(std)\n        return mu + eps*std\n\n    def decode(self, z):\n        h = F.relu(self.fc31(z))\n        h = F.relu(self.fc32(h))\n        return torch.sigmoid(self.fc4(h))\n\n    def forward_all(self, x):\n        mu, logvar = self.encode(x.view(-1, self.x_dim))\n        z = self.reparameterize(mu, logvar)\n        return self.decode(z), z, mu, logvar\n\n    def forward(self, x):\n        yhat, _, _, _ = self.forward_all(x)\n        return yhat\n\n\ndef VAE_loss_function(recon_x, x, mu, logvar, reconst_loss='mse', a_RECONST=1., a_KLD=1., x_dim=640):\n    \"\"\"Loss function for VAE which consists of reconstruction and KL divergence losses.\n    Thanks to https://github.com/pytorch/examples/blob/master/vae/main.py\n\n    You can also balance weights for each loss, just to see what if KLD loss is stronger, etc.\n\n    Args:\n        reconst_loss: Reconstruction loss calculation: 'mse' or 'bce'\n        a_RECONST: Weight for reconstruction loss.\n        a_KLD: Weight for KLD loss.\n    \"\"\"\n\n    func = (F.mse_loss if reconst_loss == 'mse'\n            else F.binary_cross_entropy if reconst_loss == 'bce'\n            else 'Unknown reconst_loss')\n    RECONST = func(recon_x, x.view(-1, x_dim), reduction='sum')\n\n    # see Appendix B from VAE paper:\n    # Kingma and Welling. Auto-Encoding Variational Bayes. ICLR, 2014\n    # https://arxiv.org/abs/1312.6114\n    # 0.5 * sum(1 + log(sigma^2) - mu^2 - sigma^2)\n    KLD = -0.5 * torch.sum(1 + logvar - mu.pow(2) - logvar.exp())\n\n    return RECONST*a_RECONST + KLD*a_KLD\n","metadata":{"execution":{"iopub.status.busy":"2022-05-18T10:32:18.835088Z","iopub.execute_input":"2022-05-18T10:32:18.835342Z","iopub.status.idle":"2022-05-18T10:32:18.913107Z","shell.execute_reply.started":"2022-05-18T10:32:18.835309Z","shell.execute_reply":"2022-05-18T10:32:18.912448Z"},"id":"pEksqnZ47FAN","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\n\"\"\"\nA Convolutional Variational Autoencoder\n\"\"\"\nclass VAE(nn.Module):\n    def __init__(self, imgChannels=1, featureDim=32*128*313, zDim=256):\n        super(VAE, self).__init__()\n\n        # Initializing the 2 convolutional layers and 2 full-connected layers for the encoder\n        self.encConv1 = nn.Conv2d(imgChannels, 16, kernel_size=5, padding=2)\n        self.encConv2 = nn.Conv2d(16, 32, kernel_size=5, padding=2)\n        self.encFC1 = nn.Linear(featureDim, zDim)\n        self.encFC2 = nn.Linear(featureDim, zDim)\n\n        # Initializing the fully-connected layer and 2 convolutional layers for decoder\n        self.decFC1 = nn.Linear(zDim, featureDim)\n        self.decConv1 = nn.ConvTranspose2d(32, 16, kernel_size=5, padding=2)\n        self.decConv2 = nn.ConvTranspose2d(16, imgChannels, kernel_size=5, padding=2)\n\n    def encoder(self, x):\n\n        # Input is fed into 2 convolutional layers sequentially\n        # The output feature map are fed into 2 fully-connected layers to predict mean (mu) and variance (logVar)\n        # Mu and logVar are used for generating middle representation z and KL divergence loss\n        #print(\"first\",x.shape)\n        x = x.unsqueeze(1)\n        #print(\"second\",x.shape)\n        x = F.relu(self.encConv1(x))\n        #print(\"thirdq\",x.shape)\n        x = F.relu(self.encConv2(x))\n        #print(\"third\",x.shape)\n        x = x.view(-1, 32*128*313)\n        #print(\"fourth\", x.shape)\n        mu = self.encFC1(x)\n        logVar = self.encFC2(x)\n        return mu, logVar\n\n    def reparameterize(self, mu, logVar):\n\n        #Reparameterization takes in the input mu and logVar and sample the mu + std * eps\n        std = torch.exp(logVar/2)\n        eps = torch.randn_like(std)\n        return mu + std * eps\n\n    def decoder(self, z):\n\n        # z is fed back into a fully-connected layers and then into two transpose convolutional layers\n        # The generated output is the same size of the original input\n        #print(\"dec0\",z.shape)\n        x = F.relu(self.decFC1(z))\n        #print(\"dec1\",x.shape)\n        x = x.view(-1, 32, 128, 313)\n        #print(\"dec2\",x.shape)\n        x = F.relu(self.decConv1(x))\n        x = torch.sigmoid(self.decConv2(x))\n        #print(\"out\",x.shape)\n        return x\n\n    def forward_all(self, x):\n        mu, logVar = self.encoder(x)\n        z = self.reparameterize(mu, logVar)\n        out = self.decoder(z)\n        return out, z, mu, logVar\n\n    def forward(self, x):\n        yhat, _, _, _ = self.forward_all(x)\n        return yhat\n        # The entire pipeline of the VAE: encoder -> reparameterization -> decoder\n        # output, mu, and logVar are returned for loss computation\n        \n    \n    \ndef VAE_loss_function(recon_x, x, mu, logvar, reconst_loss='mse', a_RECONST=1., a_KLD=1., x_dim=640):\n    \"\"\"Loss function for VAE which consists of reconstruction and KL divergence losses.\n    Thanks to https://github.com/pytorch/examples/blob/master/vae/main.py\n\n    You can also balance weights for each loss, just to see what if KLD loss is stronger, etc.\n\n    Args:\n        reconst_loss: Reconstruction loss calculation: 'mse' or 'bce'\n        a_RECONST: Weight for reconstruction loss.\n        a_KLD: Weight for KLD loss.\n    \"\"\"\n\n    func = (F.mse_loss if reconst_loss == 'mse'\n            else F.binary_cross_entropy if reconst_loss == 'bce'\n            else 'Unknown reconst_loss')\n    #print(\"recon:\",recon_x.shape,\"x\",x.shape )\n    recon_x = torch.squeeze(recon_x,1)\n    #print(\"recon:\",recon_x.shape,\"x\",x.shape )\n    RECONST = func(recon_x, x, reduction='sum')\n\n    # see Appendix B from VAE paper:\n    # Kingma and Welling. Auto-Encoding Variational Bayes. ICLR, 2014\n    # https://arxiv.org/abs/1312.6114\n    # 0.5 * sum(1 + log(sigma^2) - mu^2 - sigma^2)\n    KLD = -0.5 * torch.sum(1 + logvar - mu.pow(2) - logvar.exp())\n\n    return RECONST*a_RECONST + KLD*a_KLD","metadata":{"execution":{"iopub.status.busy":"2022-05-18T11:18:06.003762Z","iopub.execute_input":"2022-05-18T11:18:06.004022Z","iopub.status.idle":"2022-05-18T11:18:06.082786Z","shell.execute_reply.started":"2022-05-18T11:18:06.003992Z","shell.execute_reply":"2022-05-18T11:18:06.081913Z"},"id":"j0o7wE027FAO","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Parameters","metadata":{"execution":{"iopub.status.busy":"2022-05-02T08:38:36.395212Z","iopub.execute_input":"2022-05-02T08:38:36.395652Z","iopub.status.idle":"2022-05-02T08:38:36.422764Z","shell.execute_reply.started":"2022-05-02T08:38:36.395533Z","shell.execute_reply":"2022-05-02T08:38:36.422138Z"},"id":"f1IESJ6n7FAP"}},{"cell_type":"code","source":"params = {\n# inout directory\n\"dev_directory\" : \"data/dev_data/dev_data\",\n\"eval_directory\" : \"data/eval_data/eval_data\",\n\"model_directory\": \"./model\",\n\"result_directory\": \"./result\",\n\"result_file\": \"result.csv\",\n\"max_fpr\" : 0.1,\n\"mode\" : True, # mode=True for development dataset, mode=False for evaluation dataset\n\n# preprocessing for mel-spectrogram\n\"feature\": {\n\"n_mels\": 128,\n\"frames\" : 5,\n\"n_fft\": 1024,\n\"hop_length\": 512,\n\"power\": 2.0},\n\n# training\n\"fit\":{\n\"lr\": 0.01,\n\"b1\": 0.9,\n\"b2\": 0.999,\n\"weight_decay\": 0.0,\n\"epochs\" : 50,\n\"batch_size\" : 32,\n\"shuffle\" : True,\n\"validation_split\" : 0.1,\n\"verbose\" : 1},\n    \n# model architecture\n\"VAE\":{\n\"x_dim\": 640,\n\"h_dim\": 400,\n\"z_dim\": 20}\n    \n}\nparams = EasyDict(params)\n\n# create working directory\nensure_folder(params.model_directory)\n\n# test directories\ndirs = com.select_dirs(param=params, mode=params.mode)\nprint(dirs)\n# fix random seeds\ndeterministic_everything(2020, pytorch=True)\n\n# PyTorch device\ndevice = torch.device('cuda' if torch.cuda.is_available() else 'cpu')","metadata":{"execution":{"iopub.status.busy":"2022-05-18T10:32:18.994389Z","iopub.execute_input":"2022-05-18T10:32:18.99497Z","iopub.status.idle":"2022-05-18T10:32:19.069358Z","shell.execute_reply.started":"2022-05-18T10:32:18.994933Z","shell.execute_reply":"2022-05-18T10:32:19.068531Z"},"id":"HPJVb4Qf7FAP","outputId":"b483cbca-8ccb-41c2-b312-792833681bcf","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Training","metadata":{"id":"9ak3Q12V7FAQ"}},{"cell_type":"code","source":"class Task2Dataset(torch.utils.data.Dataset):\n    \"\"\"PyTorch dataset class for task2. Caching to a file supported.\n\n    Args:\n        n_mels, frames, n_fft, hop_length, power, transform: Audio conversion settings.\n        normalize: Normalize data value range from [-90, 24] to [0, 1] for VAE, False by default.\n        cache_to: Cache filename or None by default, use this for your iterative development.\n    \"\"\"\n\n    def __init__(self, files, n_mels, frames, n_fft, hop_length, power, transform,\n                 normalize=False, cache_to=None):\n        self.transform = transform\n        self.files = files\n        self.n_mels, self.frames, self.n_fft = n_mels, frames, n_fft\n        self.hop_length, self.power = hop_length, power\n        self.normalize = normalize\n\n    def __len__(self):\n        return len(self.files)\n\n    def __getitem__(self, index):\n        x, _ = get_log_mel_spectrogram(self.files[index],\n                                 n_mels=self.n_mels,\n                                 n_fft=self.n_fft,\n                                 hop_length=self.hop_length,\n                                 power=self.power)\n        if self.normalize:\n            x = pytorch_common.normalize_0to1(x)\n        x = self.transform(x)\n        return x.permute(1, 0, 2)\n\n    # def __init__(self, files, n_mels, frames, n_fft, hop_length, power, transform,\n    #              normalize=False, cache_to=None):\n    #     self.transform = transform\n    #     self.files = files\n    #     self.n_mels, self.frames, self.n_fft = n_mels, frames, n_fft\n    #     self.hop_length, self.power = hop_length, power\n    #     # load cache or convert all the data for the first time\n    #     if cache_to is not None and Path(cache_to).exists():\n    #         com.logger.info(f'Loading cached {Path(cache_to).name}')\n    #         self.X = np.load(cache_to)\n    #     else:\n    #         self.X = []\n    #         for filename in files:\n    #             img, _ = get_log_mel_spectrogram(filename,\n    #                              n_mels=self.n_mels,\n    #                              n_fft=self.n_fft,\n    #                              hop_length=self.hop_length,\n    #                              power=self.power)\n    #             self.X.append(img)\n    #         self.X = np.array(self.X)\n    #         if cache_to is not None:\n    #             np.save(cache_to, self.X)\n    #         # self.X = com.list_to_vector_array(self.files,\n    #         #                  n_mels=self.n_mels,\n    #         #                  frames=self.frames,\n    #         #                  n_fft=self.n_fft,\n    #         #                  hop_length=self.hop_length,\n    #         #                  power=self.power)\n    #         # if cache_to is not None:\n    #         #     np.save(cache_to, self.X)\n\n    #     if normalize:\n    #         self.X = pytorch_common.normalize_0to1(self.X)\n\n    # def __len__(self):\n    #     return len(self.X)\n\n    # def __getitem__(self, index):\n    #     x = self.X[index]\n    #     x = self.transform(x)\n    #     return x.permute(1, 0, 2) #x, x\n\n\n# VAE Training class\nclass Task2VAELightning(pl.LightningModule):\n    \"\"\"Task2 PyTorch Lightning class, for training only.\"\"\"\n\n    def __init__(self, device, model, params, files, normalize=False):\n        super().__init__()\n        self.params = params\n        self.normalize = normalize\n        self.model = model\n        self.mseloss = torch.nn.MSELoss()\n        # split data files\n        if files is not None:\n            n_val = int(params.fit.validation_split * len(files))\n            self.val_files = random.sample(files, n_val)\n            self.train_files = [f for f in files if f not in self.val_files]\n\n    def forward(self, x):\n        return self.model(x)\n    \n    def training_step(self, batch, batch_nb):\n        x, y = batch[0], batch[1]\n        y_hat, z, mu, logvar = self.model.forward_all(x)\n        loss = VAE_loss_function(recon_x=y_hat, x=x, mu=mu, logvar=logvar,\n                                 reconst_loss='mse',\n                                 a_RECONST=1.,\n                                 a_KLD=.01)\n        tensorboard_logs = {'train_loss': loss}\n        return {'loss': loss, 'log': tensorboard_logs}\n\n    def validation_step(self, batch, batch_nb):\n        x, y = batch[0], batch[1]\n        y_hat = self.forward(x)[0]\n        #print(y_hat)\n        return {'val_loss': self.mseloss(y_hat, y)}\n\n    def validation_epoch_end(self, outputs):\n        avg_loss = torch.stack([x['val_loss'] for x in outputs]).mean()\n        tensorboard_logs = {'val_loss': avg_loss}\n        return {'avg_val_loss': avg_loss, 'log': tensorboard_logs}\n\n    def configure_optimizers(self):\n        return torch.optim.Adam(self.parameters(), lr=self.params.fit.lr,\n                                betas=(self.params.fit.b1, self.params.fit.b2),\n                                weight_decay=self.params.fit.weight_decay)\n\n    def _get_dl(self, for_what):\n        files = self.train_files if for_what == 'train' else self.val_files\n        cache_file = f'{self.params.model_directory}/__cache_{str(files[0]).split(\"/\")[-3]}_{for_what}.npy'\n        ds = Task2Dataset(files,\n                          n_mels=self.params.feature.n_mels,\n                          frames=self.params.feature.frames,\n                          n_fft=self.params.feature.n_fft,\n                          hop_length=self.params.feature.hop_length,\n                          power=self.params.feature.power,\n                          transform=ToTensor1ch(device=device),\n                          normalize=self.normalize,\n                          cache_to=cache_file)\n        print(\"BATCH_SIXE\",self.params.fit.batch_size)\n        return torch.utils.data.DataLoader(ds, batch_size=self.params.fit.batch_size,\n                          shuffle=(self.params.fit.shuffle if for_what == 'train' else False))\n\n    def train_dataloader(self):\n        return self._get_dl('train')\n\n    def val_dataloader(self):\n        return self._get_dl('val')","metadata":{"execution":{"iopub.status.busy":"2022-05-18T11:07:06.002833Z","iopub.execute_input":"2022-05-18T11:07:06.003172Z","iopub.status.idle":"2022-05-18T11:07:06.096637Z","shell.execute_reply.started":"2022-05-18T11:07:06.003138Z","shell.execute_reply":"2022-05-18T11:07:06.095769Z"},"id":"k4ePsbsl7FAR","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#!pip install wandb\n#import wandb\n#wandb.init()","metadata":{"id":"XoOIRw3QpJoP"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import gc\ndel variables\ngc.collect()","metadata":{"id":"L4UaF7A-k8dg","outputId":"26caa05b-6cb9-4656-a77e-538f6e52d451"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch\ntorch.cuda.empty_cache()","metadata":{"id":"F3KdMefyldQ0"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"torch.cuda.memory_summary(device=None, abbreviated=False)","metadata":{"id":"-nQfwWbuluzv","outputId":"96099802-ca72-4089-aaf9-fb659bb0a6e1"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# train models\n\ndef train():\n    for target_dir in dirs:\n        target = str(target_dir).split('/')[-1]\n        print(f'==== Start training [{target}] with {torch.cuda.device_count()} GPU(s). ====')\n\n        files = com.file_list_generator(target_dir)\n\n        model = VAE().to(device)\n        #summary(device, model)\n        task2 = Task2VAELightning(device, model, params, files, normalize=True)\n        trainer = pl.Trainer(max_epochs=params.fit.epochs,\n                             gpus=torch.cuda.device_count())\n        trainer.fit(task2)\n\n        model_file = f'{params.model_directory}/model_{target}.pth'\n        torch.save(task2.model.state_dict(), model_file)\n        print(f'saved {model_file}.\\n')\n        \ntrain()","metadata":{"execution":{"iopub.status.busy":"2022-05-18T11:07:08.468888Z","iopub.execute_input":"2022-05-18T11:07:08.469157Z","iopub.status.idle":"2022-05-18T11:07:28.186836Z","shell.execute_reply.started":"2022-05-18T11:07:08.469129Z","shell.execute_reply":"2022-05-18T11:07:28.185812Z"},"id":"UI6Wo2lx7FAS","outputId":"5ce83c3d-bdf7-4a9f-b994-cd679d1ba02d","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Optuna Tuning","metadata":{"id":"lIC_edKR6Our"}},{"cell_type":"code","source":"!pip install optuna","metadata":{"id":"ddEC7xJYErEo"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from sklearn.model_selection import train_test_split\nimport optuna\n\ndef objective(trial):\n\n    # objective_params = {\n    #           'learning_rate': trial.suggest_loguniform('learning_rate', 1e-5, 1e-1),\n    #           #'optimizer': trial.suggest_categorical(\"optimizer\", [\"Adam\", \"RMSprop\", \"SGD\"]),\n    #           'z_unit': trial.suggest_int(\"n_unit\", 4, 40),\n    #           'h_unit': trial.suggest_int(\"h_unit\", 200, 500)\n    #           }\n    params = {\n      # inout directory\n      \"dev_directory\" : \"data/dev_data/dev_data\",\n      \"eval_directory\" : \"data/eval_data/eval_data\",\n      \"model_directory\": \"./model\",\n      \"result_directory\": \"./result\",\n      \"result_file\": \"result.csv\",\n      \"max_fpr\" : 0.1,\n      \"mode\" : True, # mode=True for development dataset, mode=False for evaluation dataset\n\n      # preprocessing for mel-spectrogram\n      \"feature\": {\n      \"n_mels\": 128,\n      \"frames\" : 5,\n      \"n_fft\": 1024,\n      \"hop_length\": 512,\n      \"power\": 2.0},\n\n      # training\n      \"fit\":{\n      \"lr\": trial.suggest_loguniform('learning_rate', 1e-5, 1e-1),\n      \"b1\": 0.9,\n      \"b2\": 0.999,\n      \"weight_decay\": 0.0,\n      \"epochs\" : 3,\n      \"batch_size\" : trial.suggest_int(\"h_unit\", 200, 1000),\n      \"shuffle\" : True,\n      \"validation_split\" : 0.1,\n      \"verbose\" : 1},\n          \n      # model architecture\n      \"VAE\":{\n      \"x_dim\": 640,\n      \"h_dim\": trial.suggest_int(\"h_unit\", 200, 500), #400\n      \"z_dim\": trial.suggest_int(\"n_unit\", 4, 40) #20\n      }\n          \n    }\n    to_tensor = pytorch_common.ToTensor1ch()\n    device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n    print(\"DEVICE\", device)\n    params = EasyDict(params)\n\n\n\n    # dir_eval = '/content/data/eval_data/eval_data/slider'\n    # files = com.file_list_generator(dir_eval)\n    # print(\"FILES\", len(files), files)\n    # dir_eval = '/content/data/eval_data/eval_data/slider'\n    # test_files, y_true = test_file_list_generator(dir_eval, \"\", dir_name=\"train\", mode=True)\n    # test_files = sorted(test_files)\n    # print(\"OTHER\", test_files)\n    dir_dev = '/content/data/dev_data/dev_data/slider'\n    anomaly_files , anomaly_y = test_file_list_generator(dir_dev, \"\", dir_name=\"test\", prefix_normal=\"anomaly\", mode=True)\n    d = {\"filename\": anomaly_files, \"y\": anomaly_y}\n    anomaly_df = pd.DataFrame(data=d)\n    anomaly_df = anomaly_df.sample(frac=0.2)\n    dir_eval = '/content/data/eval_data/eval_data/slider'\n    test_files, test_y = test_file_list_generator(dir_eval, \"\", dir_name=\"train\", mode=True)\n    d = {\"filename\": test_files, \"y\": test_y}\n    normal_df = pd.DataFrame(data=d)\n    normal_df = normal_df.sample(frac=0.5)\n    concat = pd.concat([normal_df, anomaly_df])\n    concat = concat.sample(frac=1)\n    files = list(np.array(concat.filename))\n    y = list(np.array(concat.y))\n\n\n    X_train, X_test, y_train, y_test = train_test_split(files, y, test_size=0.33, random_state=42)\n\n    model = VAE(device, x_dim=params.VAE.x_dim, h_dim=params.VAE.h_dim, z_dim=params.VAE.z_dim).to(device)\n    summary(device, model)\n    task2 = Task2VAELightning(device, model, params, X_train, normalize=True)\n    trainer = pl.Trainer(max_epochs=params.fit.epochs,\n                          gpus=torch.cuda.device_count())\n    trainer.fit(task2)\n\n\n    performance = []\n    y_pred = [0. for k in X_test]\n    for file_idx, file_path in tqdm(enumerate(X_test), total=len(X_test)):\n        try:\n            data = com.file_to_vector_array(file_path,\n                                            n_mels=params.feature.n_mels,\n                                            frames=params.feature.frames,\n                                            n_fft=params.feature.n_fft,\n                                            hop_length=params.feature.hop_length,\n                                            power=params.feature.power)\n            data = pytorch_common.normalize_0to1(data)\n            with torch.no_grad():\n                print(\"TO TENSOR:\", to_tensor(data))\n                yhat = model(to_tensor(data)).cpu().detach().numpy().reshape(data.shape)\n                errors = numpy.mean(numpy.square(data - yhat), axis=1)\n            y_pred[file_idx] = numpy.mean(errors)\n            #anomaly_score_list.append([os.path.basename(file_path), y_pred[file_idx]])\n        except:\n            com.logger.error(\"file broken!!: {}\".format(file_path))\n            sys.exit(-1)\n            \n        auc = metrics.roc_auc_score(y_true, y_pred)\n        #p_auc = metrics.roc_auc_score(y_true, y_pred, max_fpr=params.max_fpr)\n        performance.append(auc)\n\n    # calculate averages for AUCs and pAUCs\n    averaged_performance = numpy.mean(numpy.array(performance, dtype=float), axis=0)\n    return averaged_performance\n\nstudy = optuna.create_study(direction=\"maximize\", sampler=optuna.samplers.TPESampler())\nstudy.optimize(objective, n_trials=30)","metadata":{"id":"9pHhm3wtEprY"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Testing on Development dataset","metadata":{"id":"K2IP38F27FAT"}},{"cell_type":"code","source":"def test():\n    # make output result directory\n    os.makedirs(params.result_directory, exist_ok=True)\n\n    # load base directory\n    dirs = com.select_dirs(param=params, mode=params.mode)\n\n    # initialize lines in csv for AUC and pAUC\n    csv_lines = []\n\n    # PyTorch version specific...\n    to_tensor = pytorch_common.ToTensor1ch()\n    device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n\n    # loop of the base directory\n    for idx, target_dir in enumerate(dirs):\n        print(\"\\n===========================\")\n        print(\"[{idx}/{total}] {dirname}\".format(dirname=target_dir, idx=idx+1, total=len(dirs)))\n        machine_type = os.path.split(target_dir)[1]\n\n        print(\"============== MODEL LOAD ==============\")\n        # set model path\n        model_file = \"{model}/model_{machine_type}.pth\".format(model=params.model_directory,\n                                                               machine_type=machine_type)\n\n        # load model file\n        if not os.path.exists(model_file):\n            com.logger.error(\"{} model not found \".format(machine_type))\n            sys.exit(-1)\n        com.logger.info(\"loading model: {}\".format(model_file))\n        model = VAE(device, x_dim=params.VAE.x_dim, h_dim=params.VAE.h_dim, z_dim=params.VAE.z_dim).to(device)\n        pytorch_common.load_weights(model, model_file)\n        pytorch_common.summary(device, model)\n        model.eval()\n\n        if params.mode:\n            # results by type\n            csv_lines.append([machine_type])\n            csv_lines.append([\"id\", \"AUC\", \"pAUC\"])\n            performance = []\n\n        machine_id_list = get_machine_id_list_for_test(target_dir)\n\n        for id_str in machine_id_list:\n            # load test file\n            test_files, y_true = test_file_list_generator(target_dir, id_str, mode=params.mode)\n\n            # setup anomaly score file path\n            anomaly_score_csv = \"{result}/anomaly_score_{machine_type}_{id_str}.csv\".format(\n                                                                                     result=params.result_directory,\n                                                                                     machine_type=machine_type,\n                                                                                     id_str=id_str)\n            anomaly_score_list = []\n\n            print(\"\\n============== BEGIN TEST FOR A MACHINE ID ==============\")\n            y_pred = [0. for k in test_files]\n            for file_idx, file_path in tqdm(enumerate(test_files), total=len(test_files)):\n                try:\n                    data = com.file_to_vector_array(file_path,\n                                                    n_mels=params.feature.n_mels,\n                                                    frames=params.feature.frames,\n                                                    n_fft=params.feature.n_fft,\n                                                    hop_length=params.feature.hop_length,\n                                                    power=params.feature.power)\n                    data = pytorch_common.normalize_0to1(data)\n                    with torch.no_grad():\n                        yhat = model(to_tensor(data)).cpu().detach().numpy().reshape(data.shape)\n                        errors = numpy.mean(numpy.square(data - yhat), axis=1)\n                    y_pred[file_idx] = numpy.mean(errors)\n                    anomaly_score_list.append([os.path.basename(file_path), y_pred[file_idx]])\n                except:\n                    com.logger.error(\"file broken!!: {}\".format(file_path))\n                    sys.exit(-1)\n\n            # save anomaly score\n            save_csv(save_file_path=anomaly_score_csv, save_data=anomaly_score_list)\n            com.logger.info(\"anomaly score result ->  {}\".format(anomaly_score_csv))\n\n            if params.mode:\n                # append AUC and pAUC to lists\n                auc = metrics.roc_auc_score(y_true, y_pred)\n                p_auc = metrics.roc_auc_score(y_true, y_pred, max_fpr=params.max_fpr)\n                csv_lines.append([id_str.split(\"_\", 1)[1], auc, p_auc])\n                performance.append([auc, p_auc])\n                com.logger.info(\"AUC : {}\".format(auc))\n                com.logger.info(\"pAUC : {}\".format(p_auc))\n\n            print(\"\\n============ END OF TEST FOR A MACHINE ID ============\")\n\n        if params.mode:\n            # calculate averages for AUCs and pAUCs\n            averaged_performance = numpy.mean(numpy.array(performance, dtype=float), axis=0)\n            csv_lines.append([\"Average\"] + list(averaged_performance))\n            csv_lines.append([])\n\n    if params.mode:\n        # output results\n        result_path = \"{result}/{file_name}\".format(result=params.result_directory, file_name=params.result_file)\n        com.logger.info(\"AUC and pAUC results -> {}\".format(result_path))\n        save_csv(save_file_path=result_path, save_data=csv_lines)\n\ntest()","metadata":{"execution":{"iopub.status.busy":"2022-05-18T10:32:19.276074Z","iopub.status.idle":"2022-05-18T10:32:19.276429Z","shell.execute_reply.started":"2022-05-18T10:32:19.276265Z","shell.execute_reply":"2022-05-18T10:32:19.276289Z"},"id":"ggFvBxpU7FAT","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def upto_6digits(cell):\n    if not cell[0].isdigit(): return cell\n    return f'{float(cell):.6f}'\n\nif params.mode:\n    with open('./result/result.csv') as f:\n        for l in f.readlines():\n            l = l.strip() #replace('\\n', '')\n            if ',' not in l:\n                print(l)\n                continue\n            ls = l.split(',')\n            print(f'{ls[0]}\\t\\t{upto_6digits(ls[1])}\\t\\t{upto_6digits(ls[2])}')","metadata":{"execution":{"iopub.status.busy":"2022-05-18T10:32:19.278426Z","iopub.status.idle":"2022-05-18T10:32:19.278854Z","shell.execute_reply.started":"2022-05-18T10:32:19.278629Z","shell.execute_reply":"2022-05-18T10:32:19.278653Z"},"id":"hc2xBKOm7FAV","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Testing on the Evaluation dataset and generating submission file","metadata":{"id":"Zja054ey7FAW"}},{"cell_type":"code","source":"# re-training on evaluation dataset\nparams.mode = False\n# train() # due to the memory restriction, restart the kernel and train on only evaluation dataset","metadata":{"execution":{"iopub.status.busy":"2022-05-18T10:32:19.280207Z","iopub.status.idle":"2022-05-18T10:32:19.28063Z","shell.execute_reply.started":"2022-05-18T10:32:19.280394Z","shell.execute_reply":"2022-05-18T10:32:19.280416Z"},"id":"ettWKut17FAW","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test()","metadata":{"execution":{"iopub.status.busy":"2022-05-18T10:32:19.28194Z","iopub.status.idle":"2022-05-18T10:32:19.282357Z","shell.execute_reply.started":"2022-05-18T10:32:19.282125Z","shell.execute_reply":"2022-05-18T10:32:19.282147Z"},"id":"Ix6zODhx7FAW","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\n\ndf1 = pd.read_csv('./result/anomaly_score_slider_id_01.csv', delimiter=',', header=None)\ndf3 = pd.read_csv('./result/anomaly_score_slider_id_03.csv', delimiter=',', header=None)\ndf5 = pd.read_csv('./result/anomaly_score_slider_id_05.csv', delimiter=',', header=None)\n\ndfs = [df1, df3, df5]\neval_df = pd.concat(dfs)\neval_df = eval_df.rename(columns={0: \"file_name\", 1: \"anomaly_score\"})\n\neval_df.to_csv('./result/baseline_submission.csv',index = False)\n","metadata":{"execution":{"iopub.status.busy":"2022-05-18T10:32:19.283809Z","iopub.status.idle":"2022-05-18T10:32:19.284229Z","shell.execute_reply.started":"2022-05-18T10:32:19.283993Z","shell.execute_reply":"2022-05-18T10:32:19.284017Z"},"id":"ba8SWjuV7FAX","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"eval_df.head()","metadata":{"execution":{"iopub.status.busy":"2022-05-18T10:32:19.285592Z","iopub.status.idle":"2022-05-18T10:32:19.286004Z","shell.execute_reply.started":"2022-05-18T10:32:19.28578Z","shell.execute_reply":"2022-05-18T10:32:19.285803Z"},"id":"G60rRBH77FAX","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# **FOLLOWING IS THE CODE FOR THE SELF SUPERVISED LEARNING ARCHITECTURE**\n\n**Since most of the code is rewritten we figured out it was best to just joine the whole thing in the same notebook.**","metadata":{"id":"68PEXMHk88eH"}},{"cell_type":"markdown","source":"# Self Supervised Learning Architecture\n","metadata":{"id":"DgyxFXj3QKep"}},{"cell_type":"code","source":"resnet50 = torchvision.models.resnet50()\nmobnetv2 = torchvision.models.mobilenet_v2()","metadata":{"id":"wkrzEZ-dQJeq"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"resnet50.conv1 = torch.nn.Conv2d(1, 64, kernel_size=(7, 7), stride=(2, 2), padding=(3, 3), bias=False)\nresnet50.fc = torch.nn.Linear(in_features=2048, out_features=3, bias=True)\ntorchsummary.summary(resnet50.to(\"cuda\"), (1, 128, 128))","metadata":{"id":"ovxs0TskZjde","outputId":"a363eb4e-5d2b-4c46-e50c-8f8e5a1ca299"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"mobnetv2.features[0][0] = torch.nn.Conv2d(1, 32, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)\nmobnetv2.classifier[1] = torch.nn.Linear(in_features=1280, out_features=3, bias=True)\ntorchsummary.summary(mobnetv2.to(\"cuda\"), (1, 128, 128))","metadata":{"id":"uHpsMF3jZgTU","outputId":"25e3f859-d5f3-4098-a2af-566c7c9ee730"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Training","metadata":{"id":"VaPQS25g82hK"}},{"cell_type":"code","source":"class Task2Dataset(torch.utils.data.Dataset):\n    \"\"\"PyTorch dataset class for task2. Caching to a file supported.\n\n    Args:\n        n_mels, frames, n_fft, hop_length, power, transform: Audio conversion settings.\n        normalize: Normalize data value range from [-90, 24] to [0, 1] for VAE, False by default.\n        cache_to: Cache filename or None by default, use this for your iterative development.\n    \"\"\"\n\n    def __init__(self, files, n_mels, frames, n_fft, hop_length, power, transform,\n                 normalize=False, cache_to=None):\n        self.transform = transform\n        self.files = files\n        self.n_mels, self.frames, self.n_fft = n_mels, frames, n_fft\n        self.hop_length, self.power = hop_length, power\n        self.normalize = normalize\n        self.mapping = {1: 0, 3: 1, 5: 2}\n\n    def __len__(self):\n        return len(self.files)\n\n    def __getitem__(self, index):\n        x, _ = get_log_mel_spectrogram(self.files[index],\n                                 n_mels=self.n_mels,\n                                 n_fft=self.n_fft,\n                                 hop_length=self.hop_length,\n                                 power=self.power)\n        if self.normalize:\n            x = pytorch_common.normalize_0to1(x)\n        if self.transform:\n          x = self.transform(x)\n          trs = torchvision.transforms.RandomCrop((128, 128))\n          x = trs(x)\n\n        label = self.mapping[int(self.files[index].split(\"_\")[4][1])]\n        \n          \n        return x, label\n\n\n# VAE Training class\nclass Task2VAELightning(pl.LightningModule):\n    \"\"\"Task2 PyTorch Lightning class, for training only.\"\"\"\n\n    def __init__(self, device, model, params, files, normalize=False):\n        super().__init__()\n        self.params = params\n        self.normalize = normalize\n        self.model = model\n        self.cel = torch.nn.CrossEntropyLoss()\n        # split data files\n        if files is not None:\n            n_val = int(params.fit.validation_split * len(files))\n            self.val_files = random.sample(files, n_val)\n            self.train_files = [f for f in files if f not in self.val_files]\n\n    def forward(self, x):\n        return self.model.forward(x)\n    \n    def training_step(self, batch, batch_nb):\n        x, y = batch\n        x = x.to(device=device)\n        y = y.to(device=device)\n        y_hat= self.model.forward(x)\n        loss = self.cel(y_hat, y)\n        tensorboard_logs = {'train_loss': loss}\n        return {'loss': loss, 'log': tensorboard_logs}\n\n    def validation_step(self, batch, batch_nb):\n        x, y = batch\n        x = x.to(device=device)\n        y = y.to(device=device)\n        y_hat = self.forward(x)\n        return {'val_loss': self.cel(y_hat, y)}\n\n    def validation_epoch_end(self, outputs):\n        avg_loss = torch.stack([x['val_loss'] for x in outputs]).mean()\n        tensorboard_logs = {'val_loss': avg_loss}\n        return {'avg_val_loss': avg_loss, 'log': tensorboard_logs}\n\n    def configure_optimizers(self):\n        optim = torch.optim.Adam(self.parameters(), lr=self.params.fit.lr,\n                                betas=(self.params.fit.b1, self.params.fit.b2),\n                                weight_decay=self.params.fit.weight_decay)\n        return optim\n\n    def _get_dl(self, for_what):\n        files = self.train_files if for_what == 'train' else self.val_files\n        cache_file = f'{self.params.model_directory}/__cache_{str(files[0]).split(\"/\")[-3]}_{for_what}.npy'\n        ds = Task2Dataset(files,\n                          n_mels=self.params.feature.n_mels,\n                          frames=self.params.feature.frames,\n                          n_fft=self.params.feature.n_fft,\n                          hop_length=self.params.feature.hop_length,\n                          power=self.params.feature.power,\n                          transform=pytorch_common.ToTensor1ch(device=self.device, image=True),\n                          normalize=self.normalize,\n                          cache_to=cache_file)\n        return torch.utils.data.DataLoader(ds, batch_size=self.params.fit.batch_size,\n                          shuffle=(self.params.fit.shuffle if for_what == 'train' else False))\n\n    def train_dataloader(self):\n        return self._get_dl('train')\n\n    def val_dataloader(self):\n        return self._get_dl('val')\n    \n    def get_ds(self, for_what):\n        files = self.train_files if for_what == 'train' else self.val_files\n        ds = Task2Dataset(files,\n                          n_mels=self.params.feature.n_mels,\n                          frames=self.params.feature.frames,\n                          n_fft=self.params.feature.n_fft,\n                          hop_length=self.params.feature.hop_length,\n                          power=self.params.feature.power,\n                          transform=pytorch_common.ToTensor1ch(device=self.device, image=True),\n                          normalize=self.normalize,\n                          cache_to=None)\n        return ds\n\n\n  \ntarget = str(dir_eval).split('/')[-1]\nprint(f'==== Start training [{target}] with {torch.cuda.device_count()} GPU(s). ====')\n\nfiles = com.file_list_generator(dir_eval)\n#add_files = com.file_list_generator(dir_eval)\n#files.extend(add_files)\nprint(files)\n\nmodel = resnet50.to(device)\ntorchsummary.summary(model, (1, 128, 128))\ntask2 = Task2VAELightning(device, model, params, files, normalize=True)\nds = task2.get_ds(\"train\")\nx, label = ds[0]\nprint(x.shape)\nprint(label)\nplt.imshow(x.squeeze().cpu())","metadata":{"execution":{"iopub.status.busy":"2022-05-18T11:07:06.002833Z","iopub.execute_input":"2022-05-18T11:07:06.003172Z","iopub.status.idle":"2022-05-18T11:07:06.096637Z","shell.execute_reply.started":"2022-05-18T11:07:06.003138Z","shell.execute_reply":"2022-05-18T11:07:06.095769Z"},"outputId":"b55a43ff-a365-43bd-aa4e-9d3949a7e3b5","id":"xVXvIBit82hL","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch\ntorch.cuda.empty_cache()","metadata":{"id":"uUIrkqi182hL"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!nvidia-smi","metadata":{"id":"1PyuhWydpgz5","outputId":"713ed301-fad3-4be7-939d-e91433177bcf"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# train models\n\ndef train():\n      target = str(dir_eval).split('/')[-1]\n      print(f'==== Start training [{target}] with {torch.cuda.device_count()} GPU(s). ====')\n\n      files = com.file_list_generator(dir_eval)\n      #add_files = com.file_list_generator(dir_eval)\n      #files.extend(add_files)\n\n      model = resnet50.to(device)\n      torchsummary.summary(model, (1, 128, 128))\n      task2 = Task2VAELightning(device, model, params, files, normalize=True)\n      trainer = pl.Trainer(max_epochs=params.fit.epochs,\n                            gpus=torch.cuda.device_count(), log_every_n_steps=5)\n      trainer.fit(task2)\n\n      model_file = f'{params.model_directory}/model_{target}.pth'\n      torch.save(task2.model.state_dict(), model_file)\n      print(f'saved {model_file}.\\n')\n        \ntrain()","metadata":{"execution":{"iopub.status.busy":"2022-05-18T11:07:08.468888Z","iopub.execute_input":"2022-05-18T11:07:08.469157Z","iopub.status.idle":"2022-05-18T11:07:28.186836Z","shell.execute_reply.started":"2022-05-18T11:07:08.469129Z","shell.execute_reply":"2022-05-18T11:07:28.185812Z"},"outputId":"23988fb3-ad76-4c2e-d2a8-0c115d9b51b2","id":"q7gNvvFw82hM","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def test_file_list_generator(target_dir,\n                             id_name, mode,\n                             dir_name=\"test\",\n                             prefix_normal=\"normal\",\n                             prefix_anomaly=\"anomaly\",\n                             ext=\"wav\"):\n    \"\"\"\n    target_dir : str\n        base directory path of the dev_data or eval_data\n    id_name : str\n        id of wav file in <<test_dir_name>> directory\n    dir_name : str (default=\"test\")\n        directory containing test data\n    prefix_normal : str (default=\"normal\")\n        normal directory name\n    prefix_anomaly : str (default=\"anomaly\")\n        anomaly directory name\n    ext : str (default=\"wav\")\n        file extension of audio files\n\n    return :\n        if the mode is \"development\":\n            test_files : list [ str ]\n                file list for test\n            test_labels : list [ boolean ]\n                label info. list for test\n                * normal/anomaly = 0/1\n        if the mode is \"evaluation\":\n            test_files : list [ str ]\n                file list for test\n    \"\"\"\n    com.logger.info(\"target_dir : {}\".format(Path(target_dir+\"_\"+id_name).name))\n\n    # development\n    if mode:\n        normal_files = sorted(\n            glob.glob(\"{dir}/{dir_name}/{prefix_normal}_{id_name}*.{ext}\".format(dir=target_dir,\n                                                                                 dir_name=dir_name,\n                                                                                 prefix_normal=prefix_normal,\n                                                                                 id_name=id_name,\n                                                                                 ext=ext)))\n        normal_labels = np.zeros(len(normal_files))\n        anomaly_files = sorted(\n            glob.glob(\"{dir}/{dir_name}/{prefix_anomaly}_{id_name}*.{ext}\".format(dir=target_dir,\n                                                                                  dir_name=dir_name,\n                                                                                  prefix_anomaly=prefix_anomaly,\n                                                                                  id_name=id_name,\n                                                                                  ext=ext)))\n        anomaly_labels = np.ones(len(anomaly_files))\n        files = np.concatenate((normal_files, anomaly_files), axis=0)\n        labels = np.concatenate((normal_labels, anomaly_labels), axis=0)\n        com.logger.info(\"test_file  num : {num}\".format(num=len(files)))\n        if len(files) == 0:\n            com.logger.exception(\"no_wav_file!!\")\n        print(\"\\n========================================\")\n\n    # evaluation\n    else:\n        files = sorted(\n            glob.glob(\"{dir}/{dir_name}/*{id_name}*.{ext}\".format(dir=target_dir,\n                                                                  dir_name=dir_name,\n                                                                  id_name=id_name,\n                                                                  ext=ext)))\n        labels = None\n        com.logger.info(\"test_file  num : {num}\".format(num=len(files)))\n        if len(files) == 0:\n            com.logger.exception(\"no_wav_file!!\")\n        print(\"\\n=========================================\")\n\n    return files, labels","metadata":{"id":"Q33jLtk23fmi"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def save_csv(save_file_path,\n             save_data):\n    with open(save_file_path, \"w\", newline=\"\") as f:\n        writer = csv.writer(f, lineterminator='\\n')\n        writer.writerows(save_data)\n\n\ndef get_machine_id_list_for_test(target_dir,\n                                 dir_name=\"test\",\n                                 ext=\"wav\"):\n    \"\"\"\n    target_dir : str\n        base directory path of \"dev_data\" or \"eval_data\"\n    test_dir_name : str (default=\"test\")\n        directory containing test data\n    ext : str (default=\"wav)\n        file extension of audio files\n\n    return :\n        machine_id_list : list [ str ]\n            list of machine IDs extracted from the names of test files\n    \"\"\"\n    # create test files\n    dir_path = os.path.abspath(\"{dir}/{dir_name}/*.{ext}\".format(dir=target_dir, dir_name=dir_name, ext=ext))\n    file_paths = sorted(glob.glob(dir_path))\n    # extract id\n    machine_id_list = sorted(list(set(itertools.chain.from_iterable(\n        [re.findall('id_[0-9][0-9]', ext_id) for ext_id in file_paths]))))\n    return machine_id_list","metadata":{"id":"8Kn6COQJ3hUA"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Testing on Development dataset","metadata":{"id":"ycACwfbn82hO"}},{"cell_type":"code","source":"def test():\n    # make output result directory\n    os.makedirs(params.result_directory, exist_ok=True)\n\n    # load base directory\n    dirs = com.select_dirs(param=params, mode=params.mode)\n\n    # initialize lines in csv for AUC and pAUC\n    csv_lines = []\n\n    # PyTorch version specific...\n    to_tensor = pytorch_common.ToTensor1ch()\n    device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n\n    soft = torch.nn.Softmax()\n\n    # loop of the base directory\n    for idx, target_dir in enumerate(dirs):\n        print(\"\\n===========================\")\n        print(\"[{idx}/{total}] {dirname}\".format(dirname=target_dir, idx=idx+1, total=len(dirs)))\n        machine_type = os.path.split(target_dir)[1]\n\n        print(\"============== MODEL LOAD ==============\")\n        # set model path\n        model_file = \"{model}/model_{machine_type}.pth\".format(model=params.model_directory,\n                                                               machine_type=machine_type)\n\n        # load model file\n        if not os.path.exists(model_file):\n            com.logger.error(\"{} model not found \".format(machine_type))\n            sys.exit(-1)\n        com.logger.info(\"loading model: {}\".format(model_file))\n        model = resnet50.to(device)\n        pytorch_common.load_weights(model, model_file)\n        torchsummary.summary(model, (1, 128, 128))\n        model.eval()\n\n        if params.mode:\n            # results by type\n            csv_lines.append([machine_type])\n            csv_lines.append([\"id\", \"AUC\", \"pAUC\"])\n            performance = []\n\n        machine_id_list = get_machine_id_list_for_test(target_dir)\n\n        for id_str in machine_id_list:\n            # load test file\n            test_files, y_true = test_file_list_generator(target_dir, id_str, mode=params.mode)\n\n            # setup anomaly score file path\n            anomaly_score_csv = \"{result}/anomaly_score_{machine_type}_{id_str}.csv\".format(\n                                                                                     result=params.result_directory,\n                                                                                     machine_type=machine_type,\n                                                                                     id_str=id_str)\n            anomaly_score_list = []\n\n            print(\"\\n============== BEGIN TEST FOR A MACHINE ID ==============\")\n            y_pred = [0. for k in test_files]\n            for file_idx, file_path in tqdm(enumerate(test_files), total=len(test_files)):\n                data = imgc.file_to_vector_array_2d(file_path,\n                                                n_mels=params.feature.n_mels,\n                                                n_fft=params.feature.n_fft,\n                                                hop_length=params.feature.hop_length,\n                                                power=params.feature.power)\n                data = pytorch_common.normalize_0to1(data)\n                trs = torchvision.transforms.RandomCrop((128, 128))\n                data = trs(to_tensor(data))\n                with torch.no_grad():\n                    yhat = soft(model(data))\n                    if file_idx in [0, 500]:\n                        for i in range(2):\n                            plt.imshow(data[i].squeeze().cpu())\n                            print(yhat)\n                            plt.show()\n                y_pred[file_idx] = (1 - torch.max(yhat)).cpu().detach().numpy()\n                anomaly_score_list.append([os.path.basename(file_path), y_pred[file_idx]])\n\n            # save anomaly score\n            #anomaly_score_list = [[elem[0], 0] if elem[1] < 0.0005 else [elem[0], 1] for elem in anomaly_score_list]\n            #y_pred = [0 if elem < 0.0005 else 1 for elem in y_pred]\n            #values = [elem[1] for elem in anomaly_score_list]\n            #plt.hist(values)\n            #plt.show()\n            save_csv(save_file_path=anomaly_score_csv, save_data=anomaly_score_list)\n            com.logger.info(\"anomaly score result ->  {}\".format(anomaly_score_csv))\n\n            if params.mode:\n                # append AUC and pAUC to lists\n                auc = metrics.roc_auc_score(y_true, y_pred)\n                p_auc = metrics.roc_auc_score(y_true, y_pred, max_fpr=params.max_fpr)\n                csv_lines.append([id_str.split(\"_\", 1)[1], auc, p_auc])\n                performance.append([auc, p_auc])\n                com.logger.info(\"AUC : {}\".format(auc))\n                com.logger.info(\"pAUC : {}\".format(p_auc))\n\n            print(\"\\n============ END OF TEST FOR A MACHINE ID ============\")\n\n        if params.mode:\n            # calculate averages for AUCs and pAUCs\n            averaged_performance = numpy.mean(numpy.array(performance, dtype=float), axis=0)\n            csv_lines.append([\"Average\"] + list(averaged_performance))\n            csv_lines.append([])\n\n    if params.mode:\n        # output results\n        result_path = \"{result}/{file_name}\".format(result=params.result_directory, file_name=params.result_file)\n        com.logger.info(\"AUC and pAUC results -> {}\".format(result_path))\n        save_csv(save_file_path=result_path, save_data=csv_lines)\n\nparams.mode = True\ntest()","metadata":{"execution":{"iopub.status.busy":"2022-05-18T10:32:19.276074Z","iopub.status.idle":"2022-05-18T10:32:19.276429Z","shell.execute_reply.started":"2022-05-18T10:32:19.276265Z","shell.execute_reply":"2022-05-18T10:32:19.276289Z"},"outputId":"27b795da-d1c6-4f9f-c85f-d55c6b7816c8","id":"X_qF3UMn82hP","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def upto_6digits(cell):\n    if not cell[0].isdigit(): return cell\n    return f'{float(cell):.6f}'\n\nif params.mode:\n    with open('./result/result.csv') as f:\n        for l in f.readlines():\n            l = l.strip() #replace('\\n', '')\n            if ',' not in l:\n                print(l)\n                continue\n            ls = l.split(',')\n            print(f'{ls[0]}\\t\\t{upto_6digits(ls[1])}\\t\\t{upto_6digits(ls[2])}')","metadata":{"execution":{"iopub.status.busy":"2022-05-18T10:32:19.278426Z","iopub.status.idle":"2022-05-18T10:32:19.278854Z","shell.execute_reply.started":"2022-05-18T10:32:19.278629Z","shell.execute_reply":"2022-05-18T10:32:19.278653Z"},"outputId":"20c4abba-a590-4dfe-c6e9-94fc4fe0f856","id":"LEcdbq9082hP","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Testing on the Evaluation dataset and generating submission file","metadata":{"id":"vGvlp1_J82hQ"}},{"cell_type":"code","source":"# re-training on evaluation dataset\nparams.mode = False\n#train() # due to the memory restriction, restart the kernel and train on only evaluation dataset","metadata":{"execution":{"iopub.status.busy":"2022-05-18T10:32:19.280207Z","iopub.status.idle":"2022-05-18T10:32:19.28063Z","shell.execute_reply.started":"2022-05-18T10:32:19.280394Z","shell.execute_reply":"2022-05-18T10:32:19.280416Z"},"id":"GyvqDDNm82hQ","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test()","metadata":{"execution":{"iopub.status.busy":"2022-05-18T10:32:19.28194Z","iopub.status.idle":"2022-05-18T10:32:19.282357Z","shell.execute_reply.started":"2022-05-18T10:32:19.282125Z","shell.execute_reply":"2022-05-18T10:32:19.282147Z"},"outputId":"962a6052-3447-4f64-ab81-3481d1583535","id":"M3T-kwDr82hQ","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\n\ndf1 = pd.read_csv('./result/anomaly_score_slider_id_01.csv', delimiter=',', header=None)\ndf3 = pd.read_csv('./result/anomaly_score_slider_id_03.csv', delimiter=',', header=None)\ndf5 = pd.read_csv('./result/anomaly_score_slider_id_05.csv', delimiter=',', header=None)\n\ndfs = [df1, df3, df5]\neval_df = pd.concat(dfs)\neval_df = eval_df.rename(columns={0: \"file_name\", 1: \"anomaly_score\"})\n\neval_df.to_csv('./result/baseline_submission_resnet50.csv',index = False)\n","metadata":{"execution":{"iopub.status.busy":"2022-05-18T10:32:19.283809Z","iopub.status.idle":"2022-05-18T10:32:19.284229Z","shell.execute_reply.started":"2022-05-18T10:32:19.283993Z","shell.execute_reply":"2022-05-18T10:32:19.284017Z"},"id":"-6jiCwYn82hR","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"eval_df.head()","metadata":{"execution":{"iopub.status.busy":"2022-05-18T10:32:19.285592Z","iopub.status.idle":"2022-05-18T10:32:19.286004Z","shell.execute_reply.started":"2022-05-18T10:32:19.28578Z","shell.execute_reply":"2022-05-18T10:32:19.285803Z"},"outputId":"76ececa6-dd63-463b-d3c5-df9ef389b2a3","id":"RwLisQZs82hR","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# **FOLLOWING IS THE CODE FOR THE THREE MODEL ARCHITECTURE**\n\n**Since most of the code is rewritten we figured out it was best to just joine the whole thing in the same notebook.**","metadata":{"id":"Zyk89LEJ_aA_"}},{"cell_type":"markdown","source":"# Network\n\nThe implementation of the Variational Auto-Encoder (VAE) model.","metadata":{"id":"337095b6"}},{"cell_type":"code","source":"class VAE(nn.Module):\n    \"\"\"Mostly borrowed from PyTorch example.\n    Thanks to https://github.com/pytorch/examples/blob/master/vae/main.py\n    \"\"\"\n\n    def __init__(self, device, x_dim=640, h_dim=400, z_dim=20):\n        super().__init__()\n        self.x_dim = x_dim\n\n        self.fc11 = nn.Linear(x_dim, h_dim)\n        self.fc12 = nn.Linear(h_dim, h_dim)\n        self.fc21 = nn.Linear(h_dim, z_dim)\n        self.fc22 = nn.Linear(h_dim, z_dim)\n        self.fc31 = nn.Linear(z_dim, h_dim)\n        self.fc32 = nn.Linear(h_dim, h_dim)\n        self.fc4 = nn.Linear(h_dim, x_dim)\n\n    def encode(self, x):\n        x = F.relu(self.fc11(x))\n        x = F.relu(self.fc12(x))\n        return self.fc21(x), self.fc22(x)\n\n    def reparameterize(self, mu, logvar):\n        std = torch.exp(0.5*logvar)\n        eps = torch.randn_like(std)\n        return mu + eps*std\n\n    def decode(self, z):\n        h = F.relu(self.fc31(z))\n        h = F.relu(self.fc32(h))\n        return torch.sigmoid(self.fc4(h))\n\n    def forward_all(self, x):\n        mu, logvar = self.encode(x.view(-1, self.x_dim))\n        z = self.reparameterize(mu, logvar)\n        return self.decode(z), z, mu, logvar\n\n    def forward(self, x):\n        yhat, _, _, _ = self.forward_all(x)\n        return yhat\n\n\ndef VAE_loss_function(recon_x, x, mu, logvar, reconst_loss='mse', a_RECONST=1., a_KLD=1., x_dim=640):\n    \"\"\"Loss function for VAE which consists of reconstruction and KL divergence losses.\n    Thanks to https://github.com/pytorch/examples/blob/master/vae/main.py\n\n    You can also balance weights for each loss, just to see what if KLD loss is stronger, etc.\n\n    Args:\n        reconst_loss: Reconstruction loss calculation: 'mse' or 'bce'\n        a_RECONST: Weight for reconstruction loss.\n        a_KLD: Weight for KLD loss.\n    \"\"\"\n\n    func = (F.mse_loss if reconst_loss == 'mse'\n            else F.binary_cross_entropy if reconst_loss == 'bce'\n            else 'Unknown reconst_loss')\n    RECONST = func(recon_x, x.view(-1, x_dim), reduction='sum')\n\n    # see Appendix B from VAE paper:\n    # Kingma and Welling. Auto-Encoding Variational Bayes. ICLR, 2014\n    # https://arxiv.org/abs/1312.6114\n    # 0.5 * sum(1 + log(sigma^2) - mu^2 - sigma^2)\n    KLD = -0.5 * torch.sum(1 + logvar - mu.pow(2) - logvar.exp())\n\n    return RECONST*a_RECONST + KLD*a_KLD\n","metadata":{"id":"1777edad"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Parameters","metadata":{"id":"1cd29151"}},{"cell_type":"code","source":"params = {\n# inout directory\n\"dev_directory\" : \"data/dev_data/dev_data\",\n\"eval_directory\" : \"data/eval_data/eval_data\",\n\"model_directory\": \"./model\",\n\"result_directory\": \"./result\",\n\"result_file\": \"result.csv\",\n\"max_fpr\" : 0.1,\n\"mode\" : True, # mode=True for development dataset, mode=False for evaluation dataset\n\n# preprocessing for mel-spectrogram\n\"feature\": {\n\"n_mels\": 128,\n\"frames\" : 5,\n\"n_fft\": 1024,\n\"hop_length\": 512,\n\"power\": 2.0},\n\n# training\n\"fit\":{\n\"lr\": 0.001,\n\"b1\": 0.9,\n\"b2\": 0.999,\n\"weight_decay\": 0.0,\n\"epochs\" : 70,\n\"batch_size\" : 1000,\n\"shuffle\" : True,\n\"validation_split\" : 0.1,\n\"verbose\" : 1},\n    \n# model architecture\n\"VAE\":{\n\"x_dim\": 640,\n\"h_dim\": 400,\n\"z_dim\": 20}\n    \n}\nparams = EasyDict(params)\n\n# create working directory\nensure_folder(params.model_directory)\n\n# test directories\ndirs = com.select_dirs(param=params, mode=params.mode)\n\n# fix random seeds\ndeterministic_everything(2020, pytorch=True)\n\n# PyTorch device\ndevice = torch.device('cuda' if torch.cuda.is_available() else 'cpu')","metadata":{"id":"406dc38f","outputId":"6d84e813-c071-4f4f-fb1d-56cebab7cf57"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Training","metadata":{"id":"dd1f9487"}},{"cell_type":"code","source":"class Task2Dataset(torch.utils.data.Dataset):\n    \"\"\"PyTorch dataset class for task2. Caching to a file supported.\n\n    Args:\n        n_mels, frames, n_fft, hop_length, power, transform: Audio conversion settings.\n        normalize: Normalize data value range from [-90, 24] to [0, 1] for VAE, False by default.\n        cache_to: Cache filename or None by default, use this for your iterative development.\n    \"\"\"\n\n    def __init__(self, files, n_mels, frames, n_fft, hop_length, power, transform,\n                 normalize=False, cache_to=None):\n        self.transform = transform\n        self.files = files\n        self.n_mels, self.frames, self.n_fft = n_mels, frames, n_fft\n        self.hop_length, self.power = hop_length, power\n        # load cache or convert all the data for the first time\n        if cache_to is not None and Path(cache_to).exists():\n            com.logger.info(f'Loading cached {Path(cache_to).name}')\n            self.X = np.load(cache_to)\n        else:\n            self.X = com.list_to_vector_array(self.files,\n                             n_mels=self.n_mels,\n                             frames=self.frames,\n                             n_fft=self.n_fft,\n                             hop_length=self.hop_length,\n                             power=self.power)\n            if cache_to is not None:\n                np.save(cache_to, self.X)\n\n        if normalize:\n            self.X = normalize_0to1(self.X)\n\n    def __len__(self):\n        return len(self.X)\n\n    def __getitem__(self, index):\n        x = self.X[index]\n        x = self.transform(x)\n        return x, x\n\n\n# VAE Training class\nclass Task2VAELightning(pl.LightningModule):\n    \"\"\"Task2 PyTorch Lightning class, for training only.\"\"\"\n\n    def __init__(self, device, model, params, files, normalize=False):\n        super().__init__()\n        self.params = params\n        self.normalize = normalize\n        self.model = model\n        self.mseloss = torch.nn.MSELoss()\n        # split data files\n        if files is not None:\n            n_val = int(params.fit.validation_split * len(files))\n            self.val_files = random.sample(files, n_val)\n            self.train_files = [f for f in files if f not in self.val_files]\n\n    def forward(self, x):\n        return self.model(x)\n    \n    def training_step(self, batch, batch_nb):\n        x, y = batch\n        y_hat, z, mu, logvar = self.model.forward_all(x)\n        loss = VAE_loss_function(recon_x=y_hat, x=x, mu=mu, logvar=logvar,\n                                 reconst_loss='mse',\n                                 a_RECONST=1.,\n                                 a_KLD=.01)\n        tensorboard_logs = {'train_loss': loss}\n        return {'loss': loss, 'log': tensorboard_logs}\n\n    def validation_step(self, batch, batch_nb):\n        x, y = batch\n        y_hat = self.forward(x)\n        return {'val_loss': self.mseloss(y_hat, y)}\n\n    def validation_epoch_end(self, outputs):\n        avg_loss = torch.stack([x['val_loss'] for x in outputs]).mean()\n        tensorboard_logs = {'val_loss': avg_loss}\n        return {'avg_val_loss': avg_loss, 'log': tensorboard_logs}\n\n    def configure_optimizers(self):\n        return torch.optim.Adam(self.parameters(), lr=self.params.fit.lr,\n                                betas=(self.params.fit.b1, self.params.fit.b2),\n                                weight_decay=self.params.fit.weight_decay)\n\n    def _get_dl(self, for_what):\n        files = self.train_files if for_what == 'train' else self.val_files\n        cache_file = f'{self.params.model_directory}/__cache_{str(files[0]).split(\"/\")[-3]}_{for_what}.npy'\n        ds = Task2Dataset(files,\n                          n_mels=self.params.feature.n_mels,\n                          frames=self.params.feature.frames,\n                          n_fft=self.params.feature.n_fft,\n                          hop_length=self.params.feature.hop_length,\n                          power=self.params.feature.power,\n                          transform=ToTensor1ch(device=device),\n                          normalize=self.normalize,\n                          cache_to=cache_file)\n        return torch.utils.data.DataLoader(ds, batch_size=self.params.fit.batch_size,\n                          shuffle=(self.params.fit.shuffle if for_what == 'train' else False))\n\n    def train_dataloader(self):\n        return self._get_dl('train')\n\n    def val_dataloader(self):\n        return self._get_dl('val')","metadata":{"id":"303ee9a1"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# train models\n\ndef train():\n    print(dirs)\n    for target_dir in dirs:\n        target = str(target_dir).split('/')[-1]\n        print(f'==== Start training [{target}] with {torch.cuda.device_count()} GPU(s). ====')\n        #files = com.file_list_generator(target_dir)\n        dir_eval = '/content/data/eval_data/eval_data/slider'\n        files = com.file_list_generator(dir_eval)\n        files00 = [x for x in files if \"id_01\" in x]\n        files02 = [x for x in files if \"id_03\" in x]\n        files04 = [x for x in files if \"id_05\" in x]\n\n        print(files00)\n        print(files02)\n        print(files04)\n\n        model00 = VAE(device, x_dim=params.VAE.x_dim, h_dim=params.VAE.h_dim, z_dim=params.VAE.z_dim).to(device)\n        summary(device, model00)\n        task200 = Task2VAELightning(device, model00, params, files00, normalize=True)\n        trainer00 = pl.Trainer(max_epochs=params.fit.epochs,\n                             gpus=torch.cuda.device_count())\n        trainer00.fit(task200)\n\n        model_file = f'{params.model_directory}/model_00.pth'\n        torch.save(task200.model.state_dict(), model_file)\n        print(f'saved {model_file}.\\n')\n        \n        model02 = VAE(device, x_dim=params.VAE.x_dim, h_dim=params.VAE.h_dim, z_dim=params.VAE.z_dim).to(device)\n        summary(device, model02)\n        task202 = Task2VAELightning(device, model02, params, files02, normalize=True)\n        trainer02 = pl.Trainer(max_epochs=params.fit.epochs,\n                             gpus=torch.cuda.device_count())\n        trainer02.fit(task202)\n\n        model_file = f'{params.model_directory}/model_02.pth'\n        torch.save(task202.model.state_dict(), model_file)\n        print(f'saved {model_file}.\\n')\n\n        model04 = VAE(device, x_dim=params.VAE.x_dim, h_dim=params.VAE.h_dim, z_dim=params.VAE.z_dim).to(device)\n        summary(device, model04)\n        task2 = Task2VAELightning(device, model04, params, files04, normalize=True)\n        trainer = pl.Trainer(max_epochs=params.fit.epochs,\n                             gpus=torch.cuda.device_count())\n        trainer.fit(task2)\n\n        model_file = f'{params.model_directory}/model_04.pth'\n        torch.save(task2.model.state_dict(), model_file)\n        print(f'saved {model_file}.\\n')\n        \ntrain()","metadata":{"id":"6309ed77","outputId":"815825ea-584b-49bf-a7a0-074c5980fc1d"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# model_file = f'{params.model_directory}/model_04.pth'\n# torch.save(task2.model.state_dict(), model_file)\n\n# model_file = f'{params.model_directory}/model_02.pth'\n# torch.save(task202.model.state_dict(), model_file)\n           \n# model_file = f'{params.model_directory}/model_00.pth'\n# torch.save(task200.model.state_dict(), model_file)","metadata":{"id":"JgqJFxGB0cK4"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Testing on Development dataset","metadata":{"id":"f2bdddbd"}},{"cell_type":"code","source":"def test():\n    # make output result directory\n    os.makedirs(params.result_directory, exist_ok=True)\n\n    # load base directory\n    dirs = com.select_dirs(param=params, mode=params.mode)\n    target_dir = dirs[0]\n    print(\"TARGET DIR\", target_dir, dirs) \n    # initialize lines in csv for AUC and pAUC\n    csv_lines = []\n\n    # PyTorch version specific...\n    to_tensor = pytorch_common.ToTensor1ch()\n    device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n\n    # loop of the base directory\n    for model_id in [\"00\", \"02\", \"04\"]:\n        print(\"\\n===========================\")\n        #print(\"[{idx}/{total}] {dirname}\".format(dirname=target_dir, idx=idx+1, total=len(dirs)))\n        machine_type = os.path.split(target_dir)[1]\n\n        print(\"============== MODEL LOAD ==============\")\n        # set model path\n        model_file = \"{model}/model_{machine_type}.pth\".format(model=params.model_directory,\n                                                               machine_type=model_id)\n\n        # load model file\n        if not os.path.exists(model_file):\n            com.logger.error(\"{} model not found \".format(machine_type))\n            sys.exit(-1)\n        com.logger.info(\"loading model: {}\".format(model_file))\n        model = VAE(device, x_dim=params.VAE.x_dim, h_dim=params.VAE.h_dim, z_dim=params.VAE.z_dim).to(device)\n        pytorch_common.load_weights(model, model_file)\n        pytorch_common.summary(device, model)\n        model.eval()\n\n        if params.mode:\n            # results by type\n            csv_lines.append([machine_type])\n            csv_lines.append([\"id\", \"AUC\", \"pAUC\"])\n            performance = []\n\n        machine_id_list = get_machine_id_list_for_test(target_dir)\n\n        for id_str in machine_id_list:\n            # load test file\n            test_files, y_true = test_file_list_generator(target_dir, id_str, mode=params.mode)\n\n            # setup anomaly score file path\n            anomaly_score_csv = \"{result}/anomaly_score_{machine_type}_{id_str}_{model}.csv\".format(\n                                                                                     result=params.result_directory,\n                                                                                     machine_type=machine_type,\n                                                                                     id_str=id_str,\n                                                                                     model=model_id)\n            anomaly_score_list = []\n\n            print(\"\\n============== BEGIN TEST FOR A MACHINE ID ==============\")\n            y_pred = [0. for k in test_files]\n            for file_idx, file_path in tqdm(enumerate(test_files), total=len(test_files)):\n                try:\n                    data = com.file_to_vector_array(file_path,\n                                                    n_mels=params.feature.n_mels,\n                                                    frames=params.feature.frames,\n                                                    n_fft=params.feature.n_fft,\n                                                    hop_length=params.feature.hop_length,\n                                                    power=params.feature.power)\n                    data = pytorch_common.normalize_0to1(data)\n                    with torch.no_grad():\n                        yhat = model(to_tensor(data)).cpu().detach().numpy().reshape(data.shape)\n                        errors = numpy.mean(numpy.square(data - yhat), axis=1)\n                    y_pred[file_idx] = numpy.mean(errors)\n                    anomaly_score_list.append([os.path.basename(file_path), y_pred[file_idx]])\n                except:\n                    com.logger.error(\"file broken!!: {}\".format(file_path))\n                    sys.exit(-1)\n\n            # save anomaly score\n            save_csv(save_file_path=anomaly_score_csv, save_data=anomaly_score_list)\n            com.logger.info(\"anomaly score result ->  {}\".format(anomaly_score_csv))\n\n            if params.mode:\n                # append AUC and pAUC to lists\n                auc = metrics.roc_auc_score(y_true, y_pred)\n                p_auc = metrics.roc_auc_score(y_true, y_pred, max_fpr=params.max_fpr)\n                csv_lines.append([id_str.split(\"_\", 1)[1], auc, p_auc])\n                performance.append([auc, p_auc])\n                com.logger.info(\"AUC : {}\".format(auc))\n                com.logger.info(\"pAUC : {}\".format(p_auc))\n\n            print(\"\\n============ END OF TEST FOR A MACHINE ID ============\")\n\n        if params.mode:\n            # calculate averages for AUCs and pAUCs\n            averaged_performance = numpy.mean(numpy.array(performance, dtype=float), axis=0)\n            csv_lines.append([\"Average\"] + list(averaged_performance))\n            csv_lines.append([])\n\n    if params.mode:\n        # output results\n        result_path = \"{result}/{file_name}\".format(result=params.result_directory, file_name=params.result_file)\n        com.logger.info(\"AUC and pAUC results -> {}\".format(result_path))\n        save_csv(save_file_path=result_path, save_data=csv_lines)\n\ntest()","metadata":{"id":"AOdipIxEeM75","outputId":"37e46b5d-887f-43e0-9044-5d65bc3b1878"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from pytorch_common import test_file_list_generator\ndef test():\n    # make output result directory\n    os.makedirs(params.result_directory, exist_ok=True)\n\n    # load base directory\n    dirs = com.select_dirs(param=params, mode=params.mode)\n    target_dir = dirs[0]\n    print(\"TARGET DIR\", target_dir)\n\n    # initialize lines in csv for AUC and pAUC\n    csv_lines = []\n\n    # PyTorch version specific...\n    to_tensor = pytorch_common.ToTensor1ch()\n    device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n    machine_list = []\n    if params.mode:\n      machine_list = [\"00\", \"02\", \"04\"]\n    else:\n      machine_list = [\"01\", \"03\", \"05\"]\n\n    # loop of the base directory\n    for machine, model in zip(machine_list, [\"00\", \"02\", \"04\"]):\n        print(\"\\n===========================\")\n        #print(\"[{idx}/{total}] {dirname}\".format(dirname=target_dir, idx=idx+1, total=len(dirs)))\n        #machine_type = os.path.split(target_dir)[1]\n\n        print(\"============== MODEL LOAD ==============\")\n        # set model path\n        model_file = \"{model}/model_{machine_type}.pth\".format(model=params.model_directory,\n                                                               machine_type=model)\n\n        # load model file\n        if not os.path.exists(model_file):\n            com.logger.error(\"{} model not found \".format(machine))\n            sys.exit(-1)\n        com.logger.info(\"loading model: {}\".format(model_file))\n        model = VAE(device, x_dim=params.VAE.x_dim, h_dim=params.VAE.h_dim, z_dim=params.VAE.z_dim).to(device)\n        pytorch_common.load_weights(model, model_file)\n        pytorch_common.summary(device, model)\n        model.eval()\n\n        if params.mode:\n            # results by machine_model\n            csv_lines.append([machine])\n            csv_lines.append([\"id\", \"AUC\", \"pAUC\"])\n            performance = []\n\n        # machine_id_list = get_machine_id_list_for_test(target_dir)\n        # print(\"MACHINEIDLIST:\", machine_id_list)\n\n        # load test file\n        print(\"TARGET DIR\", target_dir, machine, params.mode)\n        machine_id = \"id_\" + machine\n        test_files, y_true = test_file_list_generator(target_dir, machine_id, mode=params.mode)\n        \n        print(\"TEST_FILES\",test_files)\n        print(\"TRUE\", y_true)\n        # setup anomaly score file path\n        anomaly_score_csv = \"{result}/anomaly_score_{machine_type}.csv\".format(\n                                                                                  result=params.result_directory,\n                                                                                  machine_type=machine)\n        anomaly_score_list = []\n\n        print(\"\\n============== BEGIN TEST FOR A MACHINE ID ==============\")\n        y_pred = [0. for k in test_files]\n        for file_idx, file_path in tqdm(enumerate(test_files), total=len(test_files)):\n            try:\n                data = com.file_to_vector_array(file_path,\n                                                n_mels=params.feature.n_mels,\n                                                frames=params.feature.frames,\n                                                n_fft=params.feature.n_fft,\n                                                hop_length=params.feature.hop_length,\n                                                power=params.feature.power)\n                data = pytorch_common.normalize_0to1(data)\n                with torch.no_grad():\n                    yhat = model(to_tensor(data)).cpu().detach().numpy().reshape(data.shape)\n                    errors = numpy.mean(numpy.square(data - yhat), axis=1)\n                y_pred[file_idx] = numpy.mean(errors)\n                anomaly_score_list.append([os.path.basename(file_path), y_pred[file_idx]])\n            except:\n                com.logger.error(\"file broken!!: {}\".format(file_path))\n                sys.exit(-1)\n\n        # save anomaly score\n        save_csv(save_file_path=anomaly_score_csv, save_data=anomaly_score_list)\n        com.logger.info(\"anomaly score result ->  {}\".format(anomaly_score_csv))\n\n        if params.mode:\n            # append AUC and pAUC to lists\n            auc = metrics.roc_auc_score(y_true, y_pred)\n            p_auc = metrics.roc_auc_score(y_true, y_pred, max_fpr=params.max_fpr)\n            csv_lines.append([machine, auc, p_auc])\n            performance.append([auc, p_auc])\n            com.logger.info(\"AUC : {}\".format(auc))\n            com.logger.info(\"pAUC : {}\".format(p_auc))\n\n        print(\"\\n============ END OF TEST FOR A MACHINE ID ============\")\n\n        if params.mode:\n            # calculate averages for AUCs and pAUCs\n            averaged_performance = numpy.mean(numpy.array(performance, dtype=float), axis=0)\n            csv_lines.append([\"Average\"] + list(averaged_performance))\n            csv_lines.append([])\n\n    if params.mode:\n        # output results\n        result_path = \"{result}/{file_name}\".format(result=params.result_directory, file_name=params.result_file)\n        com.logger.info(\"AUC and pAUC results -> {}\".format(result_path))\n        save_csv(save_file_path=result_path, save_data=csv_lines)\n\n#test()","metadata":{"id":"51195050"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def upto_6digits(cell):\n    if not cell[0].isdigit(): return cell\n    return f'{float(cell):.6f}'\n\nif params.mode:\n    with open('./result/result.csv') as f:\n        for l in f.readlines():\n            l = l.strip() #replace('\\n', '')\n            if ',' not in l:\n                print(l)\n                continue\n            ls = l.split(',')\n            print(f'{ls[0]}\\t\\t{upto_6digits(ls[1])}\\t\\t{upto_6digits(ls[2])}')","metadata":{"id":"703101ac"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Testing on the Evaluation dataset and generating submission file","metadata":{"id":"1ede6261"}},{"cell_type":"code","source":"# re-training on evaluation dataset\nparams.mode = False\n# train() # due to the memory restriction, restart the kernel and train on only evaluation dataset","metadata":{"id":"9c50ce3c"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test()","metadata":{"id":"33110615","outputId":"2b60fd57-84a0-4f2b-9385-61ceaec71fe5"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\n\n# df1_00 = pd.read_csv('./result/anomaly_score_slider_id_01_00.csv', delimiter=',', header=None)\n# df3_00 = pd.read_csv('./result/anomaly_score_slider_id_03_00.csv', delimiter=',', header=None)\n# df5_00 = pd.read_csv('./result/anomaly_score_slider_id_05_00.csv', delimiter=',', header=None)\n# df1_02 = pd.read_csv('./result/anomaly_score_slider_id_01_02.csv', delimiter=',', header=None)\n# df3_02 = pd.read_csv('./result/anomaly_score_slider_id_03_02.csv', delimiter=',', header=None)\n# df5_02 = pd.read_csv('./result/anomaly_score_slider_id_05_02.csv', delimiter=',', header=None)\n# df1_04 = pd.read_csv('./result/anomaly_score_slider_id_01_04.csv', delimiter=',', header=None)\n# df3_04 = pd.read_csv('./result/anomaly_score_slider_id_03_04.csv', delimiter=',', header=None)\n# df5_04 = pd.read_csv('./result/anomaly_score_slider_id_05_04.csv', delimiter=',', header=None)\n\n\n# dfs_00 = [df1_00, df3_00, df5_00]\n# dfs_02 = [df1_02, df3_02, df5_02]\n# dfs_04 = [df1_04, df3_04, df5_04]\n\n# eval_df_00 = pd.concat(dfs_00)\n# eval_df_02 = pd.concat(dfs_02)\n# eval_df_04 = pd.concat(dfs_04)\n# final_df = pd.concat([eval_df_00.iloc[:, :], eval_df_02.iloc[:, 1], eval_df_04.iloc[:, 1]], axis=1)\n# final_df[\"avg\"] = final_df[1].mean(axis=1)\n# print(final_df.head())\n# print(len(final_df))\n# eval_df_02 = pd.concat(dfs_02)\n# eval_df_04 = pd.concat(dfs_04)\n\n# eval_df = pd.concat((eval_df_00, eval_df_02, eval_df_04))\n# final_df\n# #eval_df\n# ##print(eval_df)\n# #grouper = eval_df.groupby(eval_df[0])\n# #grouper\n# # eval_df[1] = eval_df[1].mean()\n# # print(\"Etter\",eval_df.head())\n# eval_df = final_df[[0,\"avg\"]]\n# eval_df = eval_df.rename(columns={0: \"file_name\", \"avg\": \"anomaly_score\"})\n\n\ndf1 = pd.read_csv('./result/anomaly_score_01.csv', delimiter=',', header=None)\ndf3 = pd.read_csv('./result/anomaly_score_03.csv', delimiter=',', header=None)\ndf5 = pd.read_csv('./result/anomaly_score_05.csv', delimiter=',', header=None)\n\ndfs = [df1, df3, df5]\neval_df = pd.concat(dfs)\neval_df = eval_df.rename(columns={0: \"file_name\", 1: \"anomaly_score\"})\n\neval_df.to_csv('./result/submission_eval_train.csv',index = False)\n\n","metadata":{"id":"fc393998"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"eval_df.head()","metadata":{"id":"803dd433","outputId":"3f33f5ae-0f0d-4a0f-8dc3-fb073aa6d807"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from google.colab import files\nfiles.download('./result/baseline_submission_gg.csv') ","metadata":{"id":"xp6HOScDZiMe"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# **FOLLOWING IS THE CODE FOR THE CNN Auto Encoder**\n\n**Since most of the code is rewritten we figured out it was best to just joine the whole thing in the same notebook.**","metadata":{"id":"6ukgimqmA32N"}},{"cell_type":"markdown","source":"# Network\n\nThe implementation of the Variational Auto-Encoder (VAE) model.","metadata":{"id":"3F6yL4l1BZTS"}},{"cell_type":"code","source":"class CNNAutoEncoder(nn.Module):\n    \"\"\"\n    Thanks to http://dl-kento.hatenablog.com/entry/2018/02/22/200811#Convolutional-AutoEncoder\n    \"\"\"\n\n    def  __init__(self, z_dim=40):\n        super().__init__()\n\n        # define the network\n        # encoder\n        self.conv1 = nn.Sequential(nn.ZeroPad2d((1,2,1,2)),\n                              nn.Conv2d(1, 32, kernel_size=5, stride=2),\n                              nn.ReLU())\n        self.conv2 = nn.Sequential(nn.ZeroPad2d((1,2,1,2)),\n                              nn.Conv2d(32, 64, kernel_size=5, stride=2),\n                              nn.ReLU(), nn.Dropout(0.2))\n        self.conv3 = nn.Sequential(nn.Conv2d(64, 128, kernel_size=3, stride=2, padding=0),\n                              nn.ReLU(), nn.Dropout(0.3))\n        self.conv4 = nn.Sequential(nn.Conv2d(128, 256, kernel_size=3, stride=2, padding=0),\n                              nn.ReLU(), nn.Dropout(0.3))\n        self.fc1 = nn.Conv2d(256, z_dim, kernel_size=3)\n\n        # decoder\n        self.fc2 = nn.Sequential(nn.ConvTranspose2d(z_dim, 256, kernel_size=3),\n                            nn.ReLU(), nn.Dropout(0.3))\n        self.conv4d = nn.Sequential(nn.ConvTranspose2d(256, 128, kernel_size=3, stride=2, padding=0),\n                               nn.ReLU(), nn.Dropout(0.3))\n        self.conv3d = nn.Sequential(nn.ConvTranspose2d(128, 64, kernel_size=3, stride=2, padding=0),\n                               nn.ReLU(), nn.Dropout(0.2))\n        self.conv2d = nn.Sequential(nn.ConvTranspose2d(64, 32, kernel_size=5, stride=2),\n                               nn.ReLU())\n        self.conv1d = nn.ConvTranspose2d(32, 1, kernel_size=5, stride=2)\n\n    def forward(self, x):\n        encoded = self.fc1(self.conv4(self.conv3(self.conv2(self.conv1(x)))))\n\n        decoded = self.fc2(encoded)\n        decoded = self.conv4d(decoded)\n        decoded = self.conv3d(decoded)\n        decoded = self.conv2d(decoded)[:,:,1:-1,1:-1]\n        decoded = self.conv1d(decoded)[:,:,0:-1,0:-1]\n        decoded = nn.Sigmoid()(decoded)\n\n        return decoded","metadata":{"execution":{"iopub.status.busy":"2022-05-18T10:32:18.835088Z","iopub.execute_input":"2022-05-18T10:32:18.835342Z","iopub.status.idle":"2022-05-18T10:32:18.913107Z","shell.execute_reply.started":"2022-05-18T10:32:18.835309Z","shell.execute_reply":"2022-05-18T10:32:18.912448Z"},"id":"HdOiMZYfBZTh","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\n\"\"\"\nA Convolutional Variational Autoencoder\n\"\"\"\nclass VAE(nn.Module):\n    def __init__(self, imgChannels=1, featureDim=32*32*64, zDim=256):\n        super(VAE, self).__init__()\n\n        # Initializing the 2 convolutional layers and 2 full-connected layers for the encoder\n        self.encConv1 = nn.Conv2d(imgChannels, 16, kernel_size=5, padding=2)\n        self.maxpool = nn.MaxPool2d(2, 2)\n        self.encConv2 = nn.Conv2d(16, 32, kernel_size=5, padding=2)\n        self.encFC1 = nn.Linear(featureDim, zDim)\n        self.encFC2 = nn.Linear(featureDim, zDim)\n\n        # Initializing the fully-connected layer and 2 convolutional layers for decoder\n        self.decFC1 = nn.Linear(zDim, featureDim)\n        self.upsample = nn.Upsample(scale_factor=2, mode='bilinear', align_corners=True)\n        self.decConv1 = nn.ConvTranspose2d(32, 16, kernel_size=5, padding=2)\n        self.decConv2 = nn.ConvTranspose2d(16, imgChannels, kernel_size=5, padding=2)\n\n    def encoder(self, x):\n\n        # Input is fed into 2 convolutional layers sequentially\n        # The output feature map are fed into 2 fully-connected layers to predict mean (mu) and variance (logVar)\n        # Mu and logVar are used for generating middle representation z and KL divergence loss\n        #print(\"first\",x.shape)\n        #print(\"second\",x.shape)\n        x = self.maxpool(F.relu(self.encConv1(x)))\n        #print(\"thirdq\",x.shape)\n        x = self.maxpool(F.relu(self.encConv2(x)))\n        #print(\"third\",x.shape)\n        x = x.view(-1, 32*32*64)\n        #print(\"fourth\", x.shape)\n        mu = self.encFC1(x)\n        logVar = self.encFC2(x)\n        return mu, logVar\n\n    def reparameterize(self, mu, logVar):\n\n        #Reparameterization takes in the input mu and logVar and sample the mu + std * eps\n        std = torch.exp(logVar/2)\n        eps = torch.randn_like(std)\n        return mu + std * eps\n\n    def decoder(self, z):\n\n        # z is fed back into a fully-connected layers and then into two transpose convolutional layers\n        # The generated output is the same size of the original input\n        #print(\"dec0\",z.shape)\n        x = F.relu(self.decFC1(z))\n        #print(\"dec1\",x.shape)\n        x = self.upsample(x.view(-1, 32, 32, 64))\n        #print(\"dec2\",x.shape)\n        x = self.upsample(F.relu(self.decConv1(x)))\n        x = torch.sigmoid(self.decConv2(x))\n        #print(\"out\",x.shape)\n        return x\n\n    def forward_all(self, x):\n        mu, logVar = self.encoder(x)\n        z = self.reparameterize(mu, logVar)\n        out = self.decoder(z)\n        return out, z, mu, logVar\n\n    def forward(self, x):\n        yhat, _, _, _ = self.forward_all(x)\n        return yhat\n        # The entire pipeline of the VAE: encoder -> reparameterization -> decoder\n        # output, mu, and logVar are returned for loss computation\n        \n    \n    \ndef VAE_loss_function(recon_x, x, mu, logvar, reconst_loss='mse', a_RECONST=1., a_KLD=1., x_dim=640):\n    \"\"\"Loss function for VAE which consists of reconstruction and KL divergence losses.\n    Thanks to https://github.com/pytorch/examples/blob/master/vae/main.py\n\n    You can also balance weights for each loss, just to see what if KLD loss is stronger, etc.\n\n    Args:\n        reconst_loss: Reconstruction loss calculation: 'mse' or 'bce'\n        a_RECONST: Weight for reconstruction loss.\n        a_KLD: Weight for KLD loss.\n    \"\"\"\n\n    func = (F.mse_loss if reconst_loss == 'mse'\n            else F.binary_cross_entropy if reconst_loss == 'bce'\n            else 'Unknown reconst_loss')\n    #print(\"recon:\",recon_x.shape,\"x\",x.shape )\n    recon_x = torch.squeeze(recon_x,1)\n    #print(\"recon:\",recon_x.shape,\"x\",x.shape )\n    RECONST = func(recon_x, x, reduction='sum')\n\n    # see Appendix B from VAE paper:\n    # Kingma and Welling. Auto-Encoding Variational Bayes. ICLR, 2014\n    # https://arxiv.org/abs/1312.6114\n    # 0.5 * sum(1 + log(sigma^2) - mu^2 - sigma^2)\n    KLD = -0.5 * torch.sum(1 + logvar - mu.pow(2) - logvar.exp())\n\n    return RECONST*a_RECONST + KLD*a_KLD","metadata":{"execution":{"iopub.status.busy":"2022-05-18T11:18:06.003762Z","iopub.execute_input":"2022-05-18T11:18:06.004022Z","iopub.status.idle":"2022-05-18T11:18:06.082786Z","shell.execute_reply.started":"2022-05-18T11:18:06.003992Z","shell.execute_reply":"2022-05-18T11:18:06.081913Z"},"id":"VAWwj9bGBZTi","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Parameters","metadata":{"execution":{"iopub.status.busy":"2022-05-02T08:38:36.395212Z","iopub.execute_input":"2022-05-02T08:38:36.395652Z","iopub.status.idle":"2022-05-02T08:38:36.422764Z","shell.execute_reply.started":"2022-05-02T08:38:36.395533Z","shell.execute_reply":"2022-05-02T08:38:36.422138Z"},"id":"bc5YmefYBZTj"}},{"cell_type":"code","source":"params = {\n# inout directory\n\"dev_directory\" : \"data/dev_data/dev_data\",\n\"eval_directory\" : \"data/eval_data/eval_data\",\n\"model_directory\": \"./model\",\n\"result_directory\": \"./result\",\n\"result_file\": \"result.csv\",\n\"max_fpr\" : 0.1,\n\"mode\" : True, # mode=True for development dataset, mode=False for evaluation dataset\n\n# preprocessing for mel-spectrogram\n\"feature\": {\n\"n_mels\": 256,\n\"frames\" : 5,\n\"n_fft\": 1024,\n\"hop_length\": 512,\n\"power\": 2.0},\n\n# training\n\"fit\":{\n\"lr\": 0.001,\n\"b1\": 0.9,\n\"b2\": 0.999,\n\"weight_decay\": 0.0,\n\"epochs\" : 100,\n\"batch_size\" : 256,\n\"shuffle\" : True,\n\"validation_split\" : 0.1,\n\"verbose\" : 1},\n    \n# model architecture\n\"VAE\":{\n\"x_dim\": 640,\n\"h_dim\": 400,\n\"z_dim\": 20}\n    \n}\nparams = EasyDict(params)\n\n# create working directory\nensure_folder(params.model_directory)\n\n# test directories\ndirs = com.select_dirs(param=params, mode=params.mode)\nprint(dirs)\n# fix random seeds\ndeterministic_everything(2020, pytorch=True)\n\n# PyTorch device\ndevice = torch.device('cuda' if torch.cuda.is_available() else 'cpu')","metadata":{"execution":{"iopub.status.busy":"2022-05-18T10:32:18.994389Z","iopub.execute_input":"2022-05-18T10:32:18.99497Z","iopub.status.idle":"2022-05-18T10:32:19.069358Z","shell.execute_reply.started":"2022-05-18T10:32:18.994933Z","shell.execute_reply":"2022-05-18T10:32:19.068531Z"},"outputId":"bc511341-e7ba-4886-d324-5b79d3499d72","id":"1sdptKdGBZTk","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Training","metadata":{"id":"J6mx5FX4BZTl"}},{"cell_type":"code","source":"class Task2Dataset(torch.utils.data.Dataset):\n    \"\"\"PyTorch dataset class for task2. Caching to a file supported.\n\n    Args:\n        n_mels, frames, n_fft, hop_length, power, transform: Audio conversion settings.\n        normalize: Normalize data value range from [-90, 24] to [0, 1] for VAE, False by default.\n        cache_to: Cache filename or None by default, use this for your iterative development.\n    \"\"\"\n\n    def __init__(self, files, n_mels, frames, n_fft, hop_length, power, transform,\n                 normalize=False, cache_to=None):\n        self.transform = transform\n        self.files = files\n        self.n_mels, self.frames, self.n_fft = n_mels, frames, n_fft\n        self.hop_length, self.power = hop_length, power\n        self.normalize = normalize\n\n    def __len__(self):\n        return len(self.files)\n\n    def __getitem__(self, index):\n        x, _ = get_log_mel_spectrogram(self.files[index],\n                                 n_mels=self.n_mels,\n                                 n_fft=self.n_fft,\n                                 hop_length=self.hop_length,\n                                 power=self.power)\n        if self.normalize:\n            x = pytorch_common.normalize_0to1(x)\n        if self.transform:\n          x = self.transform(x)\n          trs = torchvision.transforms.RandomCrop((256, 256))\n          x = trs(x)\n        return x, x\n\n\n# VAE Training class\nclass Task2VAELightning(pl.LightningModule):\n    \"\"\"Task2 PyTorch Lightning class, for training only.\"\"\"\n\n    def __init__(self, device, model, params, files, normalize=False):\n        super().__init__()\n        self.params = params\n        self.normalize = normalize\n        self.model = model\n        self.mseloss = torch.nn.MSELoss()\n        # split data files\n        if files is not None:\n            n_val = int(params.fit.validation_split * len(files))\n            self.val_files = random.sample(files, n_val)\n            self.train_files = [f for f in files if f not in self.val_files]\n\n    def forward(self, x):\n        return self.model.forward(x)\n    \n    def training_step(self, batch, batch_nb):\n        x, y = batch\n        x = x.to(device=device)\n        y = y.to(device=device)\n        y_hat= self.model.forward(x)\n        loss = self.mseloss(y_hat, x)\n        tensorboard_logs = {'train_loss': loss}\n        return {'loss': loss, 'log': tensorboard_logs}\n\n    def validation_step(self, batch, batch_nb):\n        x, y = batch\n        x = x.to(device=device)\n        y = y.to(device=device)\n        y_hat = self.forward(x)\n        return {'val_loss': self.mseloss(y_hat, y)}\n\n    def validation_epoch_end(self, outputs):\n        avg_loss = torch.stack([x['val_loss'] for x in outputs]).mean()\n        tensorboard_logs = {'val_loss': avg_loss}\n        return {'avg_val_loss': avg_loss, 'log': tensorboard_logs}\n\n    def configure_optimizers(self):\n        optim = torch.optim.Adam(self.parameters(), lr=self.params.fit.lr,\n                                betas=(self.params.fit.b1, self.params.fit.b2),\n                                weight_decay=self.params.fit.weight_decay)\n        return optim\n\n    def _get_dl(self, for_what):\n        files = self.train_files if for_what == 'train' else self.val_files\n        cache_file = f'{self.params.model_directory}/__cache_{str(files[0]).split(\"/\")[-3]}_{for_what}.npy'\n        ds = Task2Dataset(files,\n                          n_mels=self.params.feature.n_mels,\n                          frames=self.params.feature.frames,\n                          n_fft=self.params.feature.n_fft,\n                          hop_length=self.params.feature.hop_length,\n                          power=self.params.feature.power,\n                          transform=ToTensor1ch(device=self.device, image=True),\n                          normalize=self.normalize,\n                          cache_to=cache_file)\n        return torch.utils.data.DataLoader(ds, batch_size=self.params.fit.batch_size,\n                          shuffle=(self.params.fit.shuffle if for_what == 'train' else False))\n\n    def train_dataloader(self):\n        return self._get_dl('train')\n\n    def val_dataloader(self):\n        return self._get_dl('val')\n    \n    def get_ds(self, for_what):\n        files = self.train_files if for_what == 'train' else self.val_files\n        ds = Task2Dataset(files,\n                          n_mels=self.params.feature.n_mels,\n                          frames=self.params.feature.frames,\n                          n_fft=self.params.feature.n_fft,\n                          hop_length=self.params.feature.hop_length,\n                          power=self.params.feature.power,\n                          transform=ToTensor1ch(device=self.device, image=True),\n                          normalize=self.normalize,\n                          cache_to=None)\n        return ds\n\n\nfor target_dir in dirs:      \n    target = str(target_dir).split('/')[-1]\n    print(f'==== Start training [{target}] with {torch.cuda.device_count()} GPU(s). ====')\n\n    files = com.file_list_generator(target_dir)\n\n    model = CNNAutoEncoder().to(device)\n    torchsummary.summary(model, (1, 128, 128))\n    task2 = Task2VAELightning(device, model, params, files, normalize=True)\n\n    dataset = task2.get_ds('train')\n    print(dataset[0][0])\n    plt.imshow(dataset[100][0].squeeze(0).cpu())\n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2022-05-18T11:07:06.002833Z","iopub.execute_input":"2022-05-18T11:07:06.003172Z","iopub.status.idle":"2022-05-18T11:07:06.096637Z","shell.execute_reply.started":"2022-05-18T11:07:06.003138Z","shell.execute_reply":"2022-05-18T11:07:06.095769Z"},"outputId":"ddc76256-ccfb-48fa-9ec2-a8c817726f55","id":"rNNtyWvXBZTl","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch\ntorch.cuda.empty_cache()","metadata":{"id":"33IXGNWgBZTm"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!nvidia-smi","metadata":{"outputId":"42504c5d-485c-4772-bc76-59ea2c186bd2","id":"jh8JNqCJBZTm"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# train models\n\ndef train():\n    for target_dir in dirs:\n        target = str(target_dir).split('/')[-1]\n        print(f'==== Start training [{target}] with {torch.cuda.device_count()} GPU(s). ====')\n\n        files = com.file_list_generator(target_dir)\n\n        model = CNNAutoEncoder().to(device)\n        torchsummary.summary(model, (1, 128, 313))\n        task2 = Task2VAELightning(device, model, params, files, normalize=True)\n        pytorch_common.show_some_predictions(task2.train_dataloader(), task2.model, 0, 3, image=True)\n        plt.show()\n        trainer = pl.Trainer(max_epochs=params.fit.epochs,\n                             gpus=torch.cuda.device_count(), log_every_n_steps=3)\n        trainer.fit(task2)\n\n        model_file = f'{params.model_directory}/model_{target}.pth'\n        torch.save(task2.model.state_dict(), model_file)\n        print(f'saved {model_file}.\\n')\n        \ntrain()","metadata":{"execution":{"iopub.status.busy":"2022-05-18T11:07:08.468888Z","iopub.execute_input":"2022-05-18T11:07:08.469157Z","iopub.status.idle":"2022-05-18T11:07:28.186836Z","shell.execute_reply.started":"2022-05-18T11:07:08.469129Z","shell.execute_reply":"2022-05-18T11:07:28.185812Z"},"outputId":"da011a22-d666-4b4b-a5cc-08005196d00c","id":"vYSVfPaZBZTo","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def test_file_list_generator(target_dir,\n                             id_name, mode,\n                             dir_name=\"test\",\n                             prefix_normal=\"normal\",\n                             prefix_anomaly=\"anomaly\",\n                             ext=\"wav\"):\n    \"\"\"\n    target_dir : str\n        base directory path of the dev_data or eval_data\n    id_name : str\n        id of wav file in <<test_dir_name>> directory\n    dir_name : str (default=\"test\")\n        directory containing test data\n    prefix_normal : str (default=\"normal\")\n        normal directory name\n    prefix_anomaly : str (default=\"anomaly\")\n        anomaly directory name\n    ext : str (default=\"wav\")\n        file extension of audio files\n\n    return :\n        if the mode is \"development\":\n            test_files : list [ str ]\n                file list for test\n            test_labels : list [ boolean ]\n                label info. list for test\n                * normal/anomaly = 0/1\n        if the mode is \"evaluation\":\n            test_files : list [ str ]\n                file list for test\n    \"\"\"\n    com.logger.info(\"target_dir : {}\".format(Path(target_dir+\"_\"+id_name).name))\n\n    # development\n    if mode:\n        normal_files = sorted(\n            glob.glob(\"{dir}/{dir_name}/{prefix_normal}_{id_name}*.{ext}\".format(dir=target_dir,\n                                                                                 dir_name=dir_name,\n                                                                                 prefix_normal=prefix_normal,\n                                                                                 id_name=id_name,\n                                                                                 ext=ext)))\n        normal_labels = np.zeros(len(normal_files))\n        anomaly_files = sorted(\n            glob.glob(\"{dir}/{dir_name}/{prefix_anomaly}_{id_name}*.{ext}\".format(dir=target_dir,\n                                                                                  dir_name=dir_name,\n                                                                                  prefix_anomaly=prefix_anomaly,\n                                                                                  id_name=id_name,\n                                                                                  ext=ext)))\n        anomaly_labels = np.ones(len(anomaly_files))\n        files = np.concatenate((normal_files, anomaly_files), axis=0)\n        labels = np.concatenate((normal_labels, anomaly_labels), axis=0)\n        com.logger.info(\"test_file  num : {num}\".format(num=len(files)))\n        if len(files) == 0:\n            com.logger.exception(\"no_wav_file!!\")\n        print(\"\\n========================================\")\n\n    # evaluation\n    else:\n        files = sorted(\n            glob.glob(\"{dir}/{dir_name}/*{id_name}*.{ext}\".format(dir=target_dir,\n                                                                  dir_name=dir_name,\n                                                                  id_name=id_name,\n                                                                  ext=ext)))\n        labels = None\n        com.logger.info(\"test_file  num : {num}\".format(num=len(files)))\n        if len(files) == 0:\n            com.logger.exception(\"no_wav_file!!\")\n        print(\"\\n=========================================\")\n\n    return files, labels","metadata":{"id":"5illG4dTBZTz"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def save_csv(save_file_path,\n             save_data):\n    with open(save_file_path, \"w\", newline=\"\") as f:\n        writer = csv.writer(f, lineterminator='\\n')\n        writer.writerows(save_data)\n\n\ndef get_machine_id_list_for_test(target_dir,\n                                 dir_name=\"test\",\n                                 ext=\"wav\"):\n    \"\"\"\n    target_dir : str\n        base directory path of \"dev_data\" or \"eval_data\"\n    test_dir_name : str (default=\"test\")\n        directory containing test data\n    ext : str (default=\"wav)\n        file extension of audio files\n\n    return :\n        machine_id_list : list [ str ]\n            list of machine IDs extracted from the names of test files\n    \"\"\"\n    # create test files\n    dir_path = os.path.abspath(\"{dir}/{dir_name}/*.{ext}\".format(dir=target_dir, dir_name=dir_name, ext=ext))\n    file_paths = sorted(glob.glob(dir_path))\n    # extract id\n    machine_id_list = sorted(list(set(itertools.chain.from_iterable(\n        [re.findall('id_[0-9][0-9]', ext_id) for ext_id in file_paths]))))\n    return machine_id_list","metadata":{"id":"a4aFJJjEBZT0"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for idx, target_dir in enumerate(dirs):\n  print(\"\\n===========================\")\n  print(\"[{idx}/{total}] {dirname}\".format(dirname=target_dir, idx=idx+1, total=len(dirs)))\n  machine_type = os.path.split(target_dir)[1]\n  model = CNNAutoEncoder().to(device)\n  model_file = \"{model}/model_{machine_type}.pth\".format(model=params.model_directory,\n                                                        machine_type=machine_type)\n  pytorch_common.load_weights(model, model_file)\n  task2 = Task2VAELightning(device, model, params, files, normalize=True)\n  pytorch_common.show_some_predictions(task2.train_dataloader(), task2.model, 0, 3, image=True)","metadata":{"id":"FdVWKq2E3mTu","outputId":"e28b277e-f493-439e-cd77-164f0f8039c0"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Testing on Development dataset","metadata":{"id":"OxREkQLrBZT2"}},{"cell_type":"code","source":"def test():\n    # make output result directory\n    os.makedirs(params.result_directory, exist_ok=True)\n\n    # load base directory\n    dirs = com.select_dirs(param=params, mode=params.mode)\n\n    # initialize lines in csv for AUC and pAUC\n    csv_lines = []\n\n    # PyTorch version specific...\n    to_tensor = pytorch_common.ToTensor1ch()\n    device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n\n    # loop of the base directory\n    for idx, target_dir in enumerate(dirs):\n        print(\"\\n===========================\")\n        print(\"[{idx}/{total}] {dirname}\".format(dirname=target_dir, idx=idx+1, total=len(dirs)))\n        machine_type = os.path.split(target_dir)[1]\n\n        print(\"============== MODEL LOAD ==============\")\n        # set model path\n        model_file = \"{model}/model_{machine_type}.pth\".format(model=params.model_directory,\n                                                               machine_type=machine_type)\n\n        # load model file\n        if not os.path.exists(model_file):\n            com.logger.error(\"{} model not found \".format(machine_type))\n            sys.exit(-1)\n        com.logger.info(\"loading model: {}\".format(model_file))\n        model = CNNAutoEncoder().to(device)\n        pytorch_common.load_weights(model, model_file)\n        torchsummary.summary(model, (1, 256, 256))\n        model.eval()\n\n        if params.mode:\n            # results by type\n            csv_lines.append([machine_type])\n            csv_lines.append([\"id\", \"AUC\", \"pAUC\"])\n            performance = []\n\n        machine_id_list = get_machine_id_list_for_test(target_dir)\n\n        for id_str in machine_id_list:\n            # load test file\n            test_files, y_true = test_file_list_generator(target_dir, id_str, mode=params.mode)\n\n            # setup anomaly score file path\n            anomaly_score_csv = \"{result}/anomaly_score_{machine_type}_{id_str}.csv\".format(\n                                                                                     result=params.result_directory,\n                                                                                     machine_type=machine_type,\n                                                                                     id_str=id_str)\n            anomaly_score_list = []\n\n            print(\"\\n============== BEGIN TEST FOR A MACHINE ID ==============\")\n            y_pred = [0. for k in test_files]\n            for file_idx, file_path in tqdm(enumerate(test_files), total=len(test_files)):\n                data = imgc.file_to_vector_array_2d(file_path,\n                                                n_mels=params.feature.n_mels,\n                                                n_fft=params.feature.n_fft,\n                                                hop_length=params.feature.hop_length,\n                                                power=params.feature.power)\n                data = pytorch_common.normalize_0to1(data)\n                trs = torchvision.transforms.RandomCrop((256, 256))\n                data = trs(to_tensor(data))\n                with torch.no_grad():\n                    yhat = model(data).cpu().detach().numpy().reshape(data.shape)\n                    data = data.cpu().detach().numpy()\n                    errors = np.mean(np.square(data - yhat), axis=1)\n                    if file_idx in [0, 500]:\n                        for i in range(2):\n                            fig, axs = plt.subplots(1, 2)\n                            axs[0].imshow(data[i].squeeze())\n                            axs[1].imshow(yhat[i].squeeze())\n                            plt.show()\n                y_pred[file_idx] = np.mean(errors)\n                anomaly_score_list.append([os.path.basename(file_path), y_pred[file_idx]])\n\n            # save anomaly score\n            #anomaly_score_list = [[elem[0], 0] if elem[1] < 0.0005 else [elem[0], 1] for elem in anomaly_score_list]\n            #y_pred = [0 if elem < 0.0005 else 1 for elem in y_pred]\n            #values = [elem[1] for elem in anomaly_score_list]\n            #plt.hist(values)\n            #plt.show()\n            save_csv(save_file_path=anomaly_score_csv, save_data=anomaly_score_list)\n            com.logger.info(\"anomaly score result ->  {}\".format(anomaly_score_csv))\n\n            if params.mode:\n                # append AUC and pAUC to lists\n                auc = metrics.roc_auc_score(y_true, y_pred)\n                p_auc = metrics.roc_auc_score(y_true, y_pred, max_fpr=params.max_fpr)\n                csv_lines.append([id_str.split(\"_\", 1)[1], auc, p_auc])\n                performance.append([auc, p_auc])\n                com.logger.info(\"AUC : {}\".format(auc))\n                com.logger.info(\"pAUC : {}\".format(p_auc))\n\n            print(\"\\n============ END OF TEST FOR A MACHINE ID ============\")\n\n        if params.mode:\n            # calculate averages for AUCs and pAUCs\n            averaged_performance = numpy.mean(numpy.array(performance, dtype=float), axis=0)\n            csv_lines.append([\"Average\"] + list(averaged_performance))\n            csv_lines.append([])\n\n    if params.mode:\n        # output results\n        result_path = \"{result}/{file_name}\".format(result=params.result_directory, file_name=params.result_file)\n        com.logger.info(\"AUC and pAUC results -> {}\".format(result_path))\n        save_csv(save_file_path=result_path, save_data=csv_lines)\n\nparams.mode = True\ntest()","metadata":{"execution":{"iopub.status.busy":"2022-05-18T10:32:19.276074Z","iopub.status.idle":"2022-05-18T10:32:19.276429Z","shell.execute_reply.started":"2022-05-18T10:32:19.276265Z","shell.execute_reply":"2022-05-18T10:32:19.276289Z"},"outputId":"dd901755-99d0-40a2-83eb-4b9386d5111d","id":"CBtWlipeBZT3","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def upto_6digits(cell):\n    if not cell[0].isdigit(): return cell\n    return f'{float(cell):.6f}'\n\nif params.mode:\n    with open('./result/result.csv') as f:\n        for l in f.readlines():\n            l = l.strip() #replace('\\n', '')\n            if ',' not in l:\n                print(l)\n                continue\n            ls = l.split(',')\n            print(f'{ls[0]}\\t\\t{upto_6digits(ls[1])}\\t\\t{upto_6digits(ls[2])}')","metadata":{"execution":{"iopub.status.busy":"2022-05-18T10:32:19.278426Z","iopub.status.idle":"2022-05-18T10:32:19.278854Z","shell.execute_reply.started":"2022-05-18T10:32:19.278629Z","shell.execute_reply":"2022-05-18T10:32:19.278653Z"},"outputId":"5c47b0ea-8714-4442-8ea7-b02fe5bed56c","id":"TSkIObv1BZT5","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Testing on the Evaluation dataset and generating submission file","metadata":{"id":"y9X0-ZxbBZT6"}},{"cell_type":"code","source":"# re-training on evaluation dataset\nparams.mode = False\n#train() # due to the memory restriction, restart the kernel and train on only evaluation dataset","metadata":{"execution":{"iopub.status.busy":"2022-05-18T10:32:19.280207Z","iopub.status.idle":"2022-05-18T10:32:19.28063Z","shell.execute_reply.started":"2022-05-18T10:32:19.280394Z","shell.execute_reply":"2022-05-18T10:32:19.280416Z"},"id":"tLj4dEuVBZT7","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test()","metadata":{"execution":{"iopub.status.busy":"2022-05-18T10:32:19.28194Z","iopub.status.idle":"2022-05-18T10:32:19.282357Z","shell.execute_reply.started":"2022-05-18T10:32:19.282125Z","shell.execute_reply":"2022-05-18T10:32:19.282147Z"},"outputId":"40d133ac-7032-4480-c681-3c965c52c22f","id":"G0W-cmgmBZT7","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\n\ndf1 = pd.read_csv('./result/anomaly_score_slider_id_01.csv', delimiter=',', header=None)\ndf3 = pd.read_csv('./result/anomaly_score_slider_id_03.csv', delimiter=',', header=None)\ndf5 = pd.read_csv('./result/anomaly_score_slider_id_05.csv', delimiter=',', header=None)\n\ndfs = [df1, df3, df5]\neval_df = pd.concat(dfs)\neval_df = eval_df.rename(columns={0: \"file_name\", 1: \"anomaly_score\"})\n\neval_df.to_csv('./result/baseline_submission.csv',index = False)\n","metadata":{"execution":{"iopub.status.busy":"2022-05-18T10:32:19.283809Z","iopub.status.idle":"2022-05-18T10:32:19.284229Z","shell.execute_reply.started":"2022-05-18T10:32:19.283993Z","shell.execute_reply":"2022-05-18T10:32:19.284017Z"},"id":"baHa3720BZT8","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"eval_df.head()","metadata":{"execution":{"iopub.status.busy":"2022-05-18T10:32:19.285592Z","iopub.status.idle":"2022-05-18T10:32:19.286004Z","shell.execute_reply.started":"2022-05-18T10:32:19.28578Z","shell.execute_reply":"2022-05-18T10:32:19.285803Z"},"outputId":"75396d01-7af7-4782-ffde-eeb400f7f95e","id":"mQGTSkgBBZT9","trusted":true},"execution_count":null,"outputs":[]}]}