{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":70203,"databundleVersionId":8068726,"sourceType":"competition"}],"dockerImageVersionId":30698,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import pandas as pd\ntrain_path = '/kaggle/input/birdclef-2024/train_audio/'\ndf = pd.read_csv('/kaggle/input/birdclef-2024/train_metadata.csv')\nfilenames = df.filename\nlabeled_ogg_files = [train_path + f for f in filenames]\n\nimport glob\nunlabeled_ogg_files = glob.glob('/kaggle/input/birdclef-2024/unlabeled_soundscapes/*')","metadata":{"execution":{"iopub.status.busy":"2024-04-28T18:32:39.214535Z","iopub.execute_input":"2024-04-28T18:32:39.215813Z","iopub.status.idle":"2024-04-28T18:32:40.803805Z","shell.execute_reply.started":"2024-04-28T18:32:39.215748Z","shell.execute_reply":"2024-04-28T18:32:40.802659Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torchaudio\nfrom tqdm import tqdm\nfrom joblib import Parallel, delayed\nimport os\nimport torch\n\n\nDEVICE = 'cuda' if torch.cuda.is_available() else 'cpu'\nSAMPLE_RATE = 32_000\nWINDOW = SAMPLE_RATE * 5\n\n\ncompute_melspec = torchaudio.transforms.MelSpectrogram(\n    sample_rate=SAMPLE_RATE,\n    n_mels=128,\n    n_fft=1920,\n    hop_length=640,\n    center=False,\n).to(DEVICE)\npower_to_db = torchaudio.transforms.AmplitudeToDB(\n    stype=\"power\",\n    top_db=80.0,\n).to(DEVICE)\n\n\ndef get_spec(audio, config):\n    audio = audio.to(DEVICE)\n    if config['normalize_audio']:\n        audio = (audio - audio.mean()) / audio.std()\n    if len(audio) < WINDOW:\n        audio = torch.concat([audio, torch.zeros(WINDOW - len(audio), device=DEVICE)])\n    spec = compute_melspec(audio) if config['melspec'] else compute_spec(audio)\n    if config['to_db']:\n        spec = power_to_db(spec)\n    if config['quantize']:\n        spec_min = spec.min()\n        spec = (255 * (spec - spec_min) / (spec.max() - spec_min)).round()\n    if config['quantize_norm']:\n        spec = spec / 255 - 0.5\n    if config['normalize']:\n        spec = (spec - spec.mean()) / spec.std()\n    return spec\n\n\ndef get_file_data(filename, config):\n    #info = torchaudio.info(filename)\n    #audio = torchaudio.load(filename)[0][0]\n    audio = torchaudio.load(filename, num_frames=WINDOW)[0][0]\n    return {\n        #'info': info,\n        'first5s': get_spec(audio[:WINDOW], config),\n        #'last5s': get_audio_stats(audio[-WINDOW:]),\n    }\n\n\ndef get_stats(ogg_files, config):\n    stats = Parallel(n_jobs=os.cpu_count())(\n        delayed(get_file_data)(filename, config) \n        for filename in tqdm(ogg_files)\n    )\n    specs = torch.stack([s['first5s'] for s in stats])\n    mean = specs.mean([0, 2])\n    std = specs.std([0, 2])\n    specs = specs.permute(0, 2, 1).reshape(-1, specs.shape[1])\n    return torch.stack([\n        specs.max(0).values,\n        specs.min(0).values,\n        mean,\n        std,\n        specs.median(0).values,\n    ]).to('cpu')","metadata":{"execution":{"iopub.status.busy":"2024-04-28T18:32:40.813846Z","iopub.execute_input":"2024-04-28T18:32:40.814148Z","iopub.status.idle":"2024-04-28T18:32:45.557593Z","shell.execute_reply.started":"2024-04-28T18:32:40.814119Z","shell.execute_reply":"2024-04-28T18:32:45.556613Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import plotly.graph_objects as go\n\n\ndef add_stats(fig, name, color, stats):\n    freq_bins = list(range(stats.shape[1]))\n    stats = dict(zip(['max', 'min', 'mean', 'std', 'median'], stats))\n    color_str = ','.join([str(s) for s in color])\n\n    fig.add_trace(go.Scatter(\n        name=f'{name}_mean_std',\n        x=freq_bins,\n        y=stats['mean'],\n        error_y={'array': stats['std']},\n        mode='markers',\n        marker_color=f'rgba({color_str}, .8)'\n    ))\n\n    fig.add_trace(go.Scatter(\n        name=f'{name}_median_min_max',\n        x=freq_bins,\n        y=stats['median'],\n        error_y={\n            'array': stats['max'] - stats['median'],\n            'arrayminus': stats['median'] - stats['min'],\n        },\n        mode='markers',\n        marker_color=f'rgba({color_str}, .3)'\n    ))","metadata":{"execution":{"iopub.status.busy":"2024-04-28T18:32:45.559013Z","iopub.execute_input":"2024-04-28T18:32:45.559694Z","iopub.status.idle":"2024-04-28T18:32:45.582377Z","shell.execute_reply.started":"2024-04-28T18:32:45.559652Z","shell.execute_reply":"2024-04-28T18:32:45.581213Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"default_config = {\n    'normalize_audio': False,\n    'melspec': True,\n    'to_db': True,\n    'quantize': False,\n    'quantize_norm': False,\n    'normalize': False,\n}\n\nspec_stats_unlabeled = get_stats(unlabeled_ogg_files, default_config)\nspec_stats_labeled = get_stats(labeled_ogg_files, default_config)\n    \nfig = go.Figure()\nfig.update_layout(\n    title = \"Frequency statistics for labeled train data and unlabeled soundscapes\",\n    xaxis_title=dict(text='Mel filterback'),\n    yaxis_title=dict(text='Decibels')\n)\nadd_stats(fig, 'unlabeled', [0, 0, 255], spec_stats_unlabeled)\nadd_stats(fig, 'labeled', [255, 0, 0], spec_stats_labeled)\nfig.show()","metadata":{"execution":{"iopub.status.busy":"2024-04-28T18:32:45.583746Z","iopub.execute_input":"2024-04-28T18:32:45.584115Z","iopub.status.idle":"2024-04-28T18:32:59.830046Z","shell.execute_reply.started":"2024-04-28T18:32:45.584074Z","shell.execute_reply":"2024-04-28T18:32:59.828933Z"},"trusted":true},"execution_count":null,"outputs":[]}]}