{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":91844,"databundleVersionId":11361821,"sourceType":"competition"},{"sourceId":11006697,"sourceType":"datasetVersion","datasetId":6852193},{"sourceId":11007574,"sourceType":"datasetVersion","datasetId":6852834},{"sourceId":11048751,"sourceType":"datasetVersion","datasetId":6869450},{"sourceId":11049372,"sourceType":"datasetVersion","datasetId":6883149},{"sourceId":11053663,"sourceType":"datasetVersion","datasetId":6886569},{"sourceId":11060723,"sourceType":"datasetVersion","datasetId":6891568},{"sourceId":11075449,"sourceType":"datasetVersion","datasetId":6902504},{"sourceId":11151956,"sourceType":"datasetVersion","datasetId":6957736},{"sourceId":11166743,"sourceType":"datasetVersion","datasetId":6873009},{"sourceId":227215399,"sourceType":"kernelVersion"},{"sourceId":227215575,"sourceType":"kernelVersion"},{"sourceId":227579048,"sourceType":"kernelVersion"}],"dockerImageVersionId":30918,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"### [Inspiration](https://www.kaggle.com/code/vyacheslavbolotin/inspiration/)\n\n<br/>\n\nNotebook is set to run **v.121**; &nbsp; Running it, you will get LB=**0.805**\n\nAn attempt will be made - not to select weights logically and \"manually\", but to use the [**rankdata**() function from the **scipy** scientific library](https://www.kaggle.com/code/cdeotte/xgboost-starter-ensemble-lb-0-935-wow) as in the [PS-S5E3-Rainfall](https://www.kaggle.com/competitions/playground-series-s5e3/code) competition. In case of success, work on this notebook will be suspended for some time. An exception may be the appearance of public works of our colleagues, similar in the structure of execution to the works of Japanese and Turkish experts, namely solution.**6** and solution.**11**, or a top presentation such as solution.**16** without links to private datasets or notebooks.\n\n\n### [BirdCLEF+ 2025](https://www.kaggle.com/competitions/birdclef-2025/leaderboard) | [Ensemble of solutions](https://www.kaggle.com/code/vyacheslavbolotin/birdclef-2025-ensemble-of-solutions/)\n   \n| &nbsp;| &nbsp; | &nbsp; | &nbsp; | &nbsp; | &nbsp; | &nbsp; |\n| - | :-: | :-: | - | :-: | -: | -: |\n| 1. | [0.485](https://www.kaggle.com/code/stefankahl/birdclef-2025-sample-submission) | v4 | [BirdCLEF+ 2025 Sample Submission](https://www.kaggle.com/code/stefankahl/birdclef-2025-sample-submission) | expert | [Stefan Kahl](https://www.kaggle.com/stefankahl) | Germany |\n| 10 | [0.490](https://www.kaggle.com/code/carlolepelaars/birdclef-2025-simple-submission) | v1 | [BirdCLEF+ 2025: Simple Submission](https://www.kaggle.com/code/carlolepelaars/birdclef-2025-simple-submission) | master | [Carlo Lepelaars](https://www.kaggle.com/carlolepelaars) | Netherlands |\n| 2. | [0.513](https://www.kaggle.com/code/rahuljiwane/notebook-bird-rahul-jiwane) | v2 | [Notebook Bird: Rahul Jiwane](https://www.kaggle.com/code/rahuljiwane/notebook-bird-rahul-jiwane) | contributor | [Rahul Jiwane](https://www.kaggle.com/rahuljiwane) | World|\n| 3. | [EDA](https://www.kaggle.com/code/mpwolke/birdclef-2025-el-silencio-natural-reserve) | v3 | [BirdClef 2025: El Silencio Natural Reserve](https://www.kaggle.com/code/mpwolke/birdclef-2025-el-silencio-natural-reserve) | grandmaster | [Marília Prata](https://www.kaggle.com/mpwolke) | Brazil |\n| 4. | [0.515](https://www.kaggle.com/code/kumarandatascientist/lb-0-515-sample-submission) | v6 | [LB 0.515 Sample submission](https://www.kaggle.com/code/kumarandatascientist/lb-0-515-sample-submission) | expert | [Kumaran K](https://www.kaggle.com/kumarandatascientist) | India |\n| 15. | [0.801](https://www.kaggle.com/code/kumarandatascientist/lb-0-801-efficientnet-b0-pytorch-pipeline) | v2 | [EfficientNet B0 Pytorch - **upgrade copy** - **solutions**.(**11**,**14**)](https://www.kaggle.com/code/kumarandatascientist/lb-0-801-efficientnet-b0-pytorch-pipeline) | expert | [Kumaran K](https://www.kaggle.com/kumarandatascientist) | India |\n| 5. | [0.500](https://www.kaggle.com/code/jocelyndumlao/birdclef-2025-mfcc-feature-roc-auc-analysis) | v1 | [BirdCLEF 2025: MFCC Feature & ROC-AUC Analysis](https://www.kaggle.com/code/jocelyndumlao/birdclef-2025-mfcc-feature-roc-auc-analysis) | master | [Jocelyn Dumlao](https://www.kaggle.com/jocelyndumlao) | Philippines |\n| 5b. | [0.531](https://www.kaggle.com/code/jocelyndumlao/birdclef-2025-inference-w-simplecnn-spectrogram) | v5 | [BirdCLEF 2025: Inference w/SimpleCNN Spectrogram](https://www.kaggle.com/code/jocelyndumlao/birdclef-2025-inference-w-simplecnn-spectrogram) | master | [Jocelyn Dumlao](https://www.kaggle.com/jocelyndumlao) | Philippines |\n| 8. | [0.682](https://www.kaggle.com/code/agcsdedf/birdclef-2025-base-submit) | v4 | [BirdCLEF 2025 Base Submit](https://www.kaggle.com/code/agcsdedf/birdclef-2025-base-submit) &nbsp; | contributor | [agcsdedf](https://www.kaggle.com/agcsdedf) | World |\n| 9  | [0.552](https://www.kaggle.com/code/kadircandrisolu/pytorch-inference-birdclef2025-baseline) | v3 | [[Pytorch, Inference] BirdCLEF2025 Baseline](https://www.kaggle.com/code/kadircandrisolu/pytorch-inference-birdclef2025-baseline) | contributor | [Kadircan İdrisoğlu](https://www.kaggle.com/kadircandrisolu) | World |\n| 6. | [0.631](https://www.kaggle.com/code/myso1987/birdclef2025-3-submit-baseline-5s) | v2 | [BirdCLEF2025-3 Submit-baseline 5s](https://www.kaggle.com/code/myso1987/birdclef2025-3-submit-baseline-5s) | expert | [MYSO](https://www.kaggle.com/myso1987) | Japan |\n| **6**.2 | [train](https://www.kaggle.com/code/myso1987/birdclef2025-2-train-baseline-5s) | v2 | [BirdCLEF2025-2 **Train**-baseline 5s](https://www.kaggle.com/code/myso1987/birdclef2025-2-train-baseline-5s) | expert | [MYSO](https://www.kaggle.com/myso1987) | Japan |\n| b.3 | [crop](https://www.kaggle.com/code/myso1987/birdclef2025-1-crop-audio-5s) | v2 | [BirdCLEF2025-1 Crop audio 5s](https://www.kaggle.com/code/myso1987/birdclef2025-1-crop-audio-5s) | expert | [MYSO](https://www.kaggle.com/myso1987) | Japan |\n| 11 | [0.761](https://www.kaggle.com/code/kadircandrisolu/efficientnet-b0-pytorch-inference-birdclef-25/notebook) | v1 | [EfficientNet B0 Pytorch [Inference] . BirdCLEF'25](https://www.kaggle.com/code/kadircandrisolu/efficientnet-b0-pytorch-inference-birdclef-25/notebook) | expert | [Kadircan İdrisoğlu](https://www.kaggle.com/kadircandrisolu) | Turkey |\n| **11**.2 | [train](https://www.kaggle.com/code/kadircandrisolu/efficientnet-b0-pytorch-train-birdclef-25) | v6 | [EfficientNet B0 Pytorch [**Train**] &nbsp; &nbsp; &nbsp; &nbsp;. BirdCLEF'25](https://www.kaggle.com/code/kadircandrisolu/efficientnet-b0-pytorch-train-birdclef-25) | expert | [Kadircan İdrisoğlu](https://www.kaggle.com/kadircandrisolu) | Turkey |\n| 11.3 | [mels](https://www.kaggle.com/code/kadircandrisolu/transforming-audio-to-mel-spec-birdclef-25) | v1 | [Transforming Audio-to-Mel Spec. &nbsp;&nbsp;. BirdCLEF'25](https://www.kaggle.com/code/kadircandrisolu/transforming-audio-to-mel-spec-birdclef-25) | expert | [Kadircan İdrisoğlu](https://www.kaggle.com/kadircandrisolu) | Turkey |\n| 12 | [0.723](https://www.kaggle.com/code/agcsdedf/birdclef-2025-openvino-inf) | v1 | [BirdCLEF-2025 OpenVINO Inf](https://www.kaggle.com/code/agcsdedf/birdclef-2025-openvino-inf) | contributor | [agcsdedf](https://www.kaggle.com/agcsdedf) | China |\n| 13 | [mels](https://) | v1 | [Bird CLEF+ 2025 . iAudio + 2 different mel-spectrograms](https://) | grandmaster | [invisible](https://www.kaggle.com/vyacheslavbolotin/code) | Russia |\n| 14 | [0.793](https://www.kaggle.com/code/salmanahmedtamu/labels-tta-efficientnet-b0-pytorch-inference) | v2 | [EfficientNet B0 Pytorch, Labels TTA, [Inference]](https://www.kaggle.com/code/salmanahmedtamu/labels-tta-efficientnet-b0-pytorch-inference) | expert | [Salman Ahmed](https://www.kaggle.com/salmanahmedtamu) | Dubai, U.A.E. |\n| **16** | [no data]((https://www.kaggle.com/code/liverpool786/fork-of-lb-0-804-ensemble-of-solutions) | [*v2*](https://www.kaggle.com/code/liverpool786/fork-of-lb-0-804-ensemble-of-solutions) | [**Upgrade model**](https://www.kaggle.com/datasets/liverpool786/lbmore-newtrain) -> [**lbmore-newtrain**](https://www.kaggle.com/datasets/liverpool786/lbmore-newtrain), of solution.14 | contributor | [InkWhisper](https://www.kaggle.com/liverpool786) | China |","metadata":{}},{"cell_type":"markdown","source":"|  |  LB | v | solutions | lbs | weights | time |\n| - | :-: | :-: | :-: | :-: | :-: | :-: |\n| 34 | [0.700](https://www.kaggle.com/code/vyacheslavbolotin/birdclef-2025-ensemble-of-solutions?scriptVersionId=228241815) | v65 | [6](https://www.kaggle.com/code/myso1987/birdclef2025-3-submit-baseline-5s) + [8](https://www.kaggle.com/code/agcsdedf/birdclef-2025-base-submit) + [5](https://www.kaggle.com/code/jocelyndumlao/birdclef-2025-mfcc-feature-roc-auc-analysis) | (0.631 + 0.682 + 0.500) | &nbsp; [ 0.70 + 0.17 + 0.13 ]() |< 30m|\n| 35 | [0.699](https://www.kaggle.com/code/vyacheslavbolotin/birdclef-2025-ensemble-of-solutions?scriptVersionId=228280463) | v67 | [6](https://www.kaggle.com/code/myso1987/birdclef2025-3-submit-baseline-5s) + [12](https://www.kaggle.com/code/agcsdedf/birdclef-2025-openvino-inf) + [5](https://www.kaggle.com/code/jocelyndumlao/birdclef-2025-mfcc-feature-roc-auc-analysis) | (0.631 + 0.723 + 0.500) | &nbsp; [ 0.70 + 0.17 + 0.13 ]() |< 30m|\n| 36 | [0.728](https://www.kaggle.com/code/vyacheslavbolotin/birdclef-2025-ensemble-of-solutions?scriptVersionId=228812279) | v69 | [6](https://www.kaggle.com/code/myso1987/birdclef2025-3-submit-baseline-5s) + [11](https://www.kaggle.com/code/kadircandrisolu/efficientnet-b0-pytorch-inference-birdclef-25/notebook) + [5](https://www.kaggle.com/code/jocelyndumlao/birdclef-2025-mfcc-feature-roc-auc-analysis) | (0.631 + 0.761 + 0.500) | &nbsp; [ 0.70 + 0.17 + 0.13 ]() |< 30m|\n| 37 | [0.742](https://www.kaggle.com/code/vyacheslavbolotin/birdclef-2025-ensemble-of-solutions?scriptVersionId=228819450) | v71 | &nbsp; [6](https://www.kaggle.com/code/myso1987/birdclef2025-3-submit-baseline-5s) + [11](https://www.kaggle.com/code/kadircandrisolu/efficientnet-b0-pytorch-inference-birdclef-25/notebook) + [5b](https://www.kaggle.com/code/jocelyndumlao/birdclef-2025-inference-w-simplecnn-spectrogram) | (0.631 + 0.761 + 0.532) | &nbsp; [ 0.17 + 0.70 + 0.13 ]() |< 30m|\n| 41 | [0.795](https://www.kaggle.com/code/vyacheslavbolotin/birdclef-2025-ensemble-of-solutions?scriptVersionId=228975249) | v77 | [11](https://www.kaggle.com/code/kadircandrisolu/efficientnet-b0-pytorch-inference-birdclef-25/notebook) + [14](https://www.kaggle.com/code/salmanahmedtamu/labels-tta-efficientnet-b0-pytorch-inference) | (0.761 + 0.793) | &nbsp; [ 0.50 + 0.50 ]() |< 1h|\n| 42 | [0.796](https://www.kaggle.com/code/vyacheslavbolotin/birdclef-2025-ensemble-of-solutions?scriptVersionId=228986961) | v78 | [11](https://www.kaggle.com/code/kadircandrisolu/efficientnet-b0-pytorch-inference-birdclef-25/notebook) + [14](https://www.kaggle.com/code/salmanahmedtamu/labels-tta-efficientnet-b0-pytorch-inference) | (0.761 + 0.793) | &nbsp; [ 0.30 + 0.70 ]() |< 1h|\n| 54 | [0.796](https://www.kaggle.com/code/vyacheslavbolotin/birdclef-2025-ensemble-of-solutions?scriptVersionId=229339696) | v105 | [11](https://www.kaggle.com/code/kadircandrisolu/efficientnet-b0-pytorch-inference-birdclef-25/notebook) + [15](https://www.kaggle.com/code/kumarandatascientist/lb-0-801-efficientnet-b0-pytorch-pipeline) | (0.761 + 0.801) | &nbsp; [ 0.30 + 0.70 ]() |< 1h|\n| 44 | [0.783](https://www.kaggle.com/code/vyacheslavbolotin/birdclef-2025-ensemble-of-solutions?scriptVersionId=229041861) | v82 | &nbsp; [5](https://www.kaggle.com/code/jocelyndumlao/birdclef-2025-mfcc-feature-roc-auc-analysis) + [11](https://www.kaggle.com/code/kadircandrisolu/efficientnet-b0-pytorch-inference-birdclef-25/notebook) + [14](https://www.kaggle.com/code/salmanahmedtamu/labels-tta-efficientnet-b0-pytorch-inference) + [5b](https://www.kaggle.com/code/jocelyndumlao/birdclef-2025-inference-w-simplecnn-spectrogram) | &nbsp; (0.500 + 0.761 + 0.793 + 0.532) | &nbsp; [ 0.04 + 0.38 + 0.54 + 0.04 ]() |< 78m|\n| 50 | [0.797](https://www.kaggle.com/code/vyacheslavbolotin/birdclef-2025-ensemble-of-solutions?scriptVersionId=229203837) | v100 | &nbsp; &nbsp; &nbsp; &nbsp; [11](https://www.kaggle.com/code/kadircandrisolu/efficientnet-b0-pytorch-inference-birdclef-25/notebook) + [14](https://www.kaggle.com/code/salmanahmedtamu/labels-tta-efficientnet-b0-pytorch-inference) + [12](https://www.kaggle.com/code/agcsdedf/birdclef-2025-openvino-inf) |(0.761 + 0.793 + 0.723) |[ 0.295 + 0.695 + 0.010 ]() | < 1h |\n| 53 | [0.801](https://www.kaggle.com/code/vyacheslavbolotin/birdclef-2025-ensemble-of-solutions?scriptVersionId=229329546) | v104 | &nbsp; &nbsp; &nbsp; &nbsp; [11](https://www.kaggle.com/code/kadircandrisolu/efficientnet-b0-pytorch-inference-birdclef-25/notebook) + [15](https://www.kaggle.com/code/kumarandatascientist/lb-0-801-efficientnet-b0-pytorch-pipeline) + [12](https://www.kaggle.com/code/agcsdedf/birdclef-2025-openvino-inf) |(0.761 + 0.801 + 0.723) |[ 0.295 + 0.695 + 0.010 ]() | < 74m |\n| 55  | [0.801](https://www.kaggle.com/code/vyacheslavbolotin/birdclef-2025-ensemble-of-solutions?scriptVersionId=229342251) | v**107** | [14](https://www.kaggle.com/code/salmanahmedtamu/labels-tta-efficientnet-b0-pytorch-inference) + [15](https://www.kaggle.com/code/kumarandatascientist/lb-0-801-efficientnet-b0-pytorch-pipeline) | (0.793 + 0.801) | &nbsp; [ 0.495 + 0.505 ]() |< 1h|\n| 51 | [0.797](https://www.kaggle.com/code/vyacheslavbolotin/birdclef-2025-ensemble-of-solutions?scriptVersionId=229369309) | v109 | &nbsp; [6](https://www.kaggle.com/code/myso1987/birdclef2025-3-submit-baseline-5s) + [11](https://www.kaggle.com/code/kadircandrisolu/efficientnet-b0-pytorch-inference-birdclef-25/notebook)  + [14](https://www.kaggle.com/code/salmanahmedtamu/labels-tta-efficientnet-b0-pytorch-inference) + [12](https://www.kaggle.com/code/agcsdedf/birdclef-2025-openvino-inf)|(0.631 + 0.761 + 0.793 + 0.723) |[ 0.005  + 0.290 + 0.695 + 0.010]() | < 77m |\n| 52 | [0.798](https://www.kaggle.com/code/vyacheslavbolotin/birdclef-2025-ensemble-of-solutions?scriptVersionId=229370421) | v111 | &nbsp; [6](https://www.kaggle.com/code/myso1987/birdclef2025-3-submit-baseline-5s) + [11](https://www.kaggle.com/code/kadircandrisolu/efficientnet-b0-pytorch-inference-birdclef-25/notebook)  + [14](https://www.kaggle.com/code/salmanahmedtamu/labels-tta-efficientnet-b0-pytorch-inference) + [15](https://www.kaggle.com/code/kumarandatascientist/lb-0-801-efficientnet-b0-pytorch-pipeline)|(0.631 + 0.761 + 0.793 + 0.801) |[ 0.010  + 0.061 + 0.455 + 0.474]() | < 90m |\n| 56 | [0.801](https://www.kaggle.com/code/vyacheslavbolotin/birdclef-2025-ensemble-of-solutions?scriptVersionId=229523478) | v114 | &nbsp; [6](https://www.kaggle.com/code/myso1987/birdclef2025-3-submit-baseline-5s) + [5 &nbsp; ](https://www.kaggle.com/code/jocelyndumlao/birdclef-2025-mfcc-feature-roc-auc-analysis)  + [14](https://www.kaggle.com/code/salmanahmedtamu/labels-tta-efficientnet-b0-pytorch-inference) + [15](https://www.kaggle.com/code/kumarandatascientist/lb-0-801-efficientnet-b0-pytorch-pipeline)|(0.631 + 0.505 + 0.793 + 0.801) |[ 0.0050  + 0.0001 + 0.4854 + 0.5095]() | < 60m |\n| 57 | [0.804](https://www.kaggle.com/code/vyacheslavbolotin/birdclef-2025-ensemble-of-solutions?scriptVersionId=229541832) | v117 | &nbsp; [6](https://www.kaggle.com/code/myso1987/birdclef2025-3-submit-baseline-5s) + [5 &nbsp; ](https://www.kaggle.com/code/jocelyndumlao/birdclef-2025-mfcc-feature-roc-auc-analysis)  + [16](https://www.kaggle.com/datasets/liverpool786/lbmore-newtrain) + [15](https://www.kaggle.com/code/kumarandatascientist/lb-0-801-efficientnet-b0-pytorch-pipeline)|(0.631 + 0.505 + no.dt + 0.801) |[ 0.0050  + 0.0001 + 0.4854 + 0.5095]() | < 90m |\n| 58 | [t.out](https://www.kaggle.com/code/vyacheslavbolotin/birdclef-2025-ensemble-of-solutions?scriptVersionId=229564418) | v119 | &nbsp; [6](https://www.kaggle.com/code/myso1987/birdclef2025-3-submit-baseline-5s) + [5 &nbsp; ](https://www.kaggle.com/code/jocelyndumlao/birdclef-2025-mfcc-feature-roc-auc-analysis)  + [16](https://www.kaggle.com/datasets/liverpool786/lbmore-newtrain) + [15](https://www.kaggle.com/code/kumarandatascientist/lb-0-801-efficientnet-b0-pytorch-pipeline)|(0.631 + 0.505 + no.dt + 0.801) |[ 0.0050  + 0.0001 + 0.5095 + 0.4854]() | > 90m |\n| 59 | [**0.805**](https://www.kaggle.com/code/vyacheslavbolotin/birdclef-2025-ensemble-of-solutions?scriptVersionId=229596114) | v121 | &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;[16](https://www.kaggle.com/datasets/liverpool786/lbmore-newtrain) + [15](https://www.kaggle.com/code/kumarandatascientist/lb-0-801-efficientnet-b0-pytorch-pipeline)|( no data + 0.801 ) |[ 0.50 + 0.50 ]() | < 74m |\n| 60 | [?]() | ? | &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;[**16**](https://www.kaggle.com/datasets/liverpool786/lbmore-newtrain) + [**16**](https://www.kaggle.com/code/kumarandatascientist/lb-0-801-efficientnet-b0-pytorch-pipeline)|( no data + 0.801 ) |[ 0.50 + 0.50 ]() | ? |\n| 61 | [0.804](Cool stuff! Thanks for sharing! Good luck with the tournament!) | v128 | &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;[16](https://www.kaggle.com/datasets/liverpool786/lbmore-newtrain) + [15](https://www.kaggle.com/code/kumarandatascientist/lb-0-801-efficientnet-b0-pytorch-pipeline)|( no data + 0.801 ) |[ 0.30 + 0.70 ]() | < 77m |\n| 62 | [0.805](https://www.kaggle.com/code/vyacheslavbolotin/birdclef-2025-ensemble-of-solutions?scriptVersionId=229710065) | v129 | &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;[16](https://www.kaggle.com/datasets/liverpool786/lbmore-newtrain) + [15](https://www.kaggle.com/code/kumarandatascientist/lb-0-801-efficientnet-b0-pytorch-pipeline)|( no data + 0.801 ) |[ 0.70 + 0.30 ]() | < 74m |\n\n\nv.104 < v.114 < v.107\nv.128 < v.117\nv.129 < v.121","metadata":{"_kg_hide-input":false,"_kg_hide-output":true}},{"cell_type":"code","source":"OPTION = {'N':'59',  # LB=0.805\n  'SOLUTIONs': [\n       {f'SOLUTION':'SOLUTION_16',f'FILE_SUBM':'subm_16.csv',f'WEIGHT':0.50,f'LB':'n.d.'},\n       {f'SOLUTION':'SOLUTION_15',f'FILE_SUBM':'subm_15.csv',f'WEIGHT':0.50,f'LB': 0.801},\n    ]\n}\n# OPTION = {'N':'70', skipy.stats.rankdata..\n\nexSOLUTIONS         = True;\nexEDA               = not exSOLUTIONS","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-07T13:36:18.768753Z","iopub.execute_input":"2025-04-07T13:36:18.769114Z","iopub.status.idle":"2025-04-07T13:36:18.774560Z","shell.execute_reply.started":"2025-04-07T13:36:18.769079Z","shell.execute_reply":"2025-04-07T13:36:18.773338Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"archive friendly intersections\n\n|  |  LB | v | solutions | lbs | weights | time |\n| - | :-: | :-: | :-: | :-: | :-: | :-: |\n| 34 | [0.700](https://www.kaggle.com/code/vyacheslavbolotin/birdclef-2025-ensemble-of-solutions?scriptVersionId=228241815) | v65 | [6](https://www.kaggle.com/code/myso1987/birdclef2025-3-submit-baseline-5s) + [8](https://www.kaggle.com/code/agcsdedf/birdclef-2025-base-submit) + [5](https://www.kaggle.com/code/jocelyndumlao/birdclef-2025-mfcc-feature-roc-auc-analysis) | (0.631 + 0.682 + 0.500) | &nbsp; [ 0.70 + 0.17 + 0.13 ]() |< 30m|\n| 35 | [0.699](https://www.kaggle.com/code/vyacheslavbolotin/birdclef-2025-ensemble-of-solutions?scriptVersionId=228280463) | v67 | [6](https://www.kaggle.com/code/myso1987/birdclef2025-3-submit-baseline-5s) + [12](https://www.kaggle.com/code/agcsdedf/birdclef-2025-openvino-inf) + [5](https://www.kaggle.com/code/jocelyndumlao/birdclef-2025-mfcc-feature-roc-auc-analysis) | (0.631 + 0.723 + 0.500) | &nbsp; [ 0.70 + 0.17 + 0.13 ]() |< 30m|\n| 36 | [0.728](https://www.kaggle.com/code/vyacheslavbolotin/birdclef-2025-ensemble-of-solutions?scriptVersionId=228812279) | v69 | [6](https://www.kaggle.com/code/myso1987/birdclef2025-3-submit-baseline-5s) + [11](https://www.kaggle.com/code/kadircandrisolu/efficientnet-b0-pytorch-inference-birdclef-25/notebook) + [5](https://www.kaggle.com/code/jocelyndumlao/birdclef-2025-mfcc-feature-roc-auc-analysis) | (0.631 + 0.761 + 0.500) | &nbsp; [ 0.70 + 0.17 + 0.13 ]() |< 30m|\n| 37 | [0.742](https://www.kaggle.com/code/vyacheslavbolotin/birdclef-2025-ensemble-of-solutions?scriptVersionId=228819450) | v71 | [6](https://www.kaggle.com/code/myso1987/birdclef2025-3-submit-baseline-5s)+[11](https://www.kaggle.com/code/kadircandrisolu/efficientnet-b0-pytorch-inference-birdclef-25/notebook)+[5b](https://www.kaggle.com/code/jocelyndumlao/birdclef-2025-inference-w-simplecnn-spectrogram) | (0.631 + 0.761 + 0.532) | &nbsp; [ 0.17 + 0.70 + 0.13 ]() |< 30m|\n| 38 | [0.700](https://www.kaggle.com/code/vyacheslavbolotin/birdclef-2025-ensemble-of-solutions?scriptVersionId=228824959) | v72 | [6](https://www.kaggle.com/code/myso1987/birdclef2025-3-submit-baseline-5s)+[11](https://www.kaggle.com/code/kadircandrisolu/efficientnet-b0-pytorch-inference-birdclef-25/notebook)+[5b](https://www.kaggle.com/code/jocelyndumlao/birdclef-2025-inference-w-simplecnn-spectrogram) | (0.631 + 0.761 + 0.532) | &nbsp; [ 0.70 + 0.17 + 0.13 ]() |< 30m|\n| 39 | [0.738](https://www.kaggle.com/code/salmanahmedtamu/labels-tta-efficientnet-b0-pytorch-inference) | v74 | [5b](https://www.kaggle.com/code/jocelyndumlao/birdclef-2025-inference-w-simplecnn-spectrogram)+[6](https://www.kaggle.com/code/myso1987/birdclef2025-3-submit-baseline-5s)+[11](https://www.kaggle.com/code/kadircandrisolu/efficientnet-b0-pytorch-inference-birdclef-25/notebook) | (0.532 + 0.631 + 0.761) | &nbsp; [ 0.05 + 0.10 + 0.85 ]() |< 30m|\n| 41 | [0.795](https://www.kaggle.com/code/vyacheslavbolotin/birdclef-2025-ensemble-of-solutions?scriptVersionId=228975249) | v77 | [11](https://www.kaggle.com/code/kadircandrisolu/efficientnet-b0-pytorch-inference-birdclef-25/notebook) + [14](https://www.kaggle.com/code/salmanahmedtamu/labels-tta-efficientnet-b0-pytorch-inference) | (0.761 + 0.793) | &nbsp; [ 0.50 + 0.50 ]() |< 1h|\n| 40 | [0.796](https://www.kaggle.com/code/vyacheslavbolotin/birdclef-2025-ensemble-of-solutions?scriptVersionId=228847640) | v76 | [11](https://www.kaggle.com/code/kadircandrisolu/efficientnet-b0-pytorch-inference-birdclef-25/notebook) + [14](https://www.kaggle.com/code/salmanahmedtamu/labels-tta-efficientnet-b0-pytorch-inference) | (0.761 + 0.793) | &nbsp; [ 0.40 + 0.60 ]() |< 1h|\n| **42** | [0.796](https://www.kaggle.com/code/vyacheslavbolotin/birdclef-2025-ensemble-of-solutions?scriptVersionId=228986961) | v**78** | [11](https://www.kaggle.com/code/kadircandrisolu/efficientnet-b0-pytorch-inference-birdclef-25/notebook) + [14](https://www.kaggle.com/code/salmanahmedtamu/labels-tta-efficientnet-b0-pytorch-inference) | (0.761 + 0.793) | &nbsp; [ 0.30 + 0.70 ]() |< 1h|\n| 43 | [0.796](https://www.kaggle.com/code/vyacheslavbolotin/birdclef-2025-ensemble-of-solutions?scriptVersionId=229001393) | v80 | [11](https://www.kaggle.com/code/kadircandrisolu/efficientnet-b0-pytorch-inference-birdclef-25/notebook) + [14](https://www.kaggle.com/code/salmanahmedtamu/labels-tta-efficientnet-b0-pytorch-inference) | (0.761 + 0.793) | &nbsp; [ 0.20 + 0.80 ]() |< 1h|\n| 44 | [0.783](https://www.kaggle.com/code/vyacheslavbolotin/birdclef-2025-ensemble-of-solutions?scriptVersionId=229041861) | v82 | &nbsp; [5](https://www.kaggle.com/code/jocelyndumlao/birdclef-2025-mfcc-feature-roc-auc-analysis) + [11](https://www.kaggle.com/code/kadircandrisolu/efficientnet-b0-pytorch-inference-birdclef-25/notebook) + [14](https://www.kaggle.com/code/salmanahmedtamu/labels-tta-efficientnet-b0-pytorch-inference) + [5b](https://www.kaggle.com/code/jocelyndumlao/birdclef-2025-inference-w-simplecnn-spectrogram) | &nbsp; (0.500 + 0.761 + 0.793 + 0.532) | &nbsp; [ 0.04 + 0.38 + 0.54 + 0.04 ]() |< 78m|\n| 45 | [0.744](https://www.kaggle.com/code/vyacheslavbolotin/birdclef-2025-ensemble-of-solutions?scriptVersionId=229055507) | v84 | [6](https://www.kaggle.com/code/myso1987/birdclef2025-3-submit-baseline-5s) + [11](https://www.kaggle.com/code/kadircandrisolu/efficientnet-b0-pytorch-inference-birdclef-25/notebook) + [14](https://www.kaggle.com/code/salmanahmedtamu/labels-tta-efficientnet-b0-pytorch-inference) + [8](https://www.kaggle.com/code/agcsdedf/birdclef-2025-base-submit) | &nbsp; (0.631 + 0.761 + 0.793 + 0.682) | &nbsp; [ 0.04 + 0.38 + 0.54 + 0.04 ]() |< 78m|\n| 46 | [0.749](https://www.kaggle.com/code/vyacheslavbolotin/birdclef-2025-ensemble-of-solutions?scriptVersionId=229151580) | v91 | [6](https://www.kaggle.com/code/myso1987/birdclef2025-3-submit-baseline-5s) + [11](https://www.kaggle.com/code/kadircandrisolu/efficientnet-b0-pytorch-inference-birdclef-25/notebook) + [14](https://www.kaggle.com/code/salmanahmedtamu/labels-tta-efficientnet-b0-pytorch-inference) + [8](https://www.kaggle.com/code/agcsdedf/birdclef-2025-base-submit) | &nbsp; (0.631 + 0.761 + 0.793 + 0.682) | &nbsp; [ 0.04 + 0.25 + 0.65 + 0.03]() |< 90m|\n| 47 | [0.759](https://www.kaggle.com/code/vyacheslavbolotin/birdclef-2025-ensemble-of-solutions?scriptVersionId=229174230) | v93 | [11](https://www.kaggle.com/code/kadircandrisolu/efficientnet-b0-pytorch-inference-birdclef-25/notebook)+[14](https://www.kaggle.com/code/salmanahmedtamu/labels-tta-efficientnet-b0-pytorch-inference)+[6](https://www.kaggle.com/code/myso1987/birdclef2025-3-submit-baseline-5s)+[8](https://www.kaggle.com/code/agcsdedf/birdclef-2025-base-submit)+[5b](https://www.kaggle.com/code/jocelyndumlao/birdclef-2025-inference-w-simplecnn-spectrogram)+[5](https://www.kaggle.com/code/jocelyndumlao/birdclef-2025-mfcc-feature-roc-auc-analysis)+[12](https://www.kaggle.com/code/agcsdedf/birdclef-2025-openvino-inf) |(0.761 0.793 0.631 0.682 0.532 0.500 0.723) |[ 0.272 0.674 0.015 0.013 0.004 0.03 0.19 ]() | < 90m |\n| 48 | [0.767](https://www.kaggle.com/code/vyacheslavbolotin/birdclef-2025-ensemble-of-solutions?scriptVersionId=229191597) | v98 | [11](https://www.kaggle.com/code/kadircandrisolu/efficientnet-b0-pytorch-inference-birdclef-25/notebook)+[14](https://www.kaggle.com/code/salmanahmedtamu/labels-tta-efficientnet-b0-pytorch-inference)+[6](https://www.kaggle.com/code/myso1987/birdclef2025-3-submit-baseline-5s)+[8](https://www.kaggle.com/code/agcsdedf/birdclef-2025-base-submit)+[5b](https://www.kaggle.com/code/jocelyndumlao/birdclef-2025-inference-w-simplecnn-spectrogram)+[5](https://www.kaggle.com/code/jocelyndumlao/birdclef-2025-mfcc-feature-roc-auc-analysis)+[12](https://www.kaggle.com/code/agcsdedf/birdclef-2025-openvino-inf) |(0.761 0.793 0.631 0.682 0.532 0.500 0.723) |[ 0.290 0.685 0.005 0.005 0.005 0.005 0.005 ]() | < 90m |\n| 49 | [0.767](https://www.kaggle.com/code/vyacheslavbolotin/birdclef-2025-ensemble-of-solutions?scriptVersionId=229189946) | v96 | [11](https://www.kaggle.com/code/kadircandrisolu/efficientnet-b0-pytorch-inference-birdclef-25/notebook)+[14](https://www.kaggle.com/code/salmanahmedtamu/labels-tta-efficientnet-b0-pytorch-inference)+[6](https://www.kaggle.com/code/myso1987/birdclef2025-3-submit-baseline-5s)+[8](https://www.kaggle.com/code/agcsdedf/birdclef-2025-base-submit)+[5b](https://www.kaggle.com/code/jocelyndumlao/birdclef-2025-inference-w-simplecnn-spectrogram)+[5](https://www.kaggle.com/code/jocelyndumlao/birdclef-2025-mfcc-feature-roc-auc-analysis)|(0.761 0.793 0.631 0.682 0.532 0.500) |[ 0.300 0.700 0.005 0.005 0.005 0.005 0.005 ]() | < 90m |\n| | | | | | | |\n| **50** | [0.797](https://www.kaggle.com/code/vyacheslavbolotin/birdclef-2025-ensemble-of-solutions?scriptVersionId=229203837) | v**100** | [11](https://www.kaggle.com/code/kadircandrisolu/efficientnet-b0-pytorch-inference-birdclef-25/notebook) + [14](https://www.kaggle.com/code/salmanahmedtamu/labels-tta-efficientnet-b0-pytorch-inference) + [12](https://www.kaggle.com/code/agcsdedf/birdclef-2025-openvino-inf) |(0.761 + 0.793 + 0.723) |[ 0.295 + 0.695 + 0.010 ]() | < 1h |\n\nv76 < v80 < v78, \n\n|  |  LB | v | solutions | lbs | weights | accelerator |lead time|\n| - | :-: | :-: | :-: | :-: | :-: | :-: | :-: |\n| 1 | [0.513](https://www.kaggle.com/code/vyacheslavbolotin/birdclef-2025-ensemble-of-solutions?scriptVersionId=227092444) | v1 | [1](https://www.kaggle.com/code/stefankahl/birdclef-2025-sample-submission) + [2](https://www.kaggle.com/code/rahuljiwane/notebook-bird-rahul-jiwane) | (0.485 + 0.513) | &nbsp; [ 0.50 + 0.50 ]() | CPU | 18 sec |\n| 2 | [0.513](https://www.kaggle.com/code/vyacheslavbolotin/birdclef-2025-ensemble-of-solutions?scriptVersionId=227092533) | v2 | [1](https://www.kaggle.com/code/stefankahl/birdclef-2025-sample-submission) + [2](https://www.kaggle.com/code/rahuljiwane/notebook-bird-rahul-jiwane) | (0.485 + 0.513) | &nbsp; [ 0.50 + 0.50 ]() | CPU | 17 sec |\n| 3 | [0.513](https://www.kaggle.com/code/vyacheslavbolotin/birdclef-2025-ensemble-of-solutions?scriptVersionId=227097944) | v6 | [1](https://www.kaggle.com/code/stefankahl/birdclef-2025-sample-submission) + [2](https://www.kaggle.com/code/rahuljiwane/notebook-bird-rahul-jiwane) | (0.485 + 0.513) | &nbsp; [ (0.25 + 0.25) ]() | CPU | 19 sec |\n| 4 | [0.513](https://www.kaggle.com/code/vyacheslavbolotin/birdclef-2025-ensemble-of-solutions?scriptVersionId=227098666) | v7 | [1](https://www.kaggle.com/code/stefankahl/birdclef-2025-sample-submission) + [2](https://www.kaggle.com/code/rahuljiwane/notebook-bird-rahul-jiwane) | (0.485 + 0.513) | &nbsp; [ (0.74 + 0.74) ]() | CPU | 18 sec |\n| 5 | [0.515](https://www.kaggle.com/code/vyacheslavbolotin/birdclef-2025-ensemble-of-solutions?scriptVersionId=227126389) | v10 | [2](https://www.kaggle.com/code/rahuljiwane/notebook-bird-rahul-jiwane) + [4](https://www.kaggle.com/code/kumarandatascientist/lb-0-515-sample-submission) | (0.513 + 0.515) | &nbsp; [ 0.50 + 0.50 ]() | CPU | 19 sec |\n| 6.1 | [0.515](https://www.kaggle.com/code/vyacheslavbolotin/birdclef-2025-ensemble-of-solutions?scriptVersionId=227184621) | v12 | [5](https://www.kaggle.com/code/jocelyndumlao/birdclef-2025-mfcc-feature-roc-auc-analysis) + [4](https://www.kaggle.com/code/kumarandatascientist/lb-0-515-sample-submission) | (0.500 + 0.515) | &nbsp; [ 0.50 + 0.50 ]() | CPU | 2m 23sec |\n| 6.2 | [0.631](https://www.kaggle.com/code/vyacheslavbolotin/birdclef-2025-ensemble-of-solutions?scriptVersionId=227292641) | v17 | [5](https://www.kaggle.com/code/jocelyndumlao/birdclef-2025-mfcc-feature-roc-auc-analysis) + [6](https://www.kaggle.com/code/myso1987/birdclef2025-3-submit-baseline-5s) | (0.500 + 0.631) | &nbsp; [ 0.50 + 0.50 ]() | CPU | 2m 53sec |\n| 7.1 | [0.569](https://www.kaggle.com/code/vyacheslavbolotin/birdclef-2025-ensemble-of-solutions?scriptVersionId=227295613) | v19 | [4](https://www.kaggle.com/code/kumarandatascientist/lb-0-515-sample-submission) + [6](https://www.kaggle.com/code/myso1987/birdclef2025-3-submit-baseline-5s) | (0.515 + 0.631) | &nbsp; [ 0.50 + 0.50 ]() | CPU | 30 sec |\n| 8 | [0.635](https://www.kaggle.com/code/vyacheslavbolotin/birdclef-2025-ensemble-of-solutions?scriptVersionId=227299776) | v22 | [4](https://www.kaggle.com/code/kumarandatascientist/lb-0-515-sample-submission) + [5](https://www.kaggle.com/code/jocelyndumlao/birdclef-2025-mfcc-feature-roc-auc-analysis) + [6](https://www.kaggle.com/code/myso1987/birdclef2025-3-submit-baseline-5s) | (0.515 + 0.500 + 0.631) | &nbsp; [ 0.01 + 0.14 + 0.85 ]() | CPU | 2m 41sec |\n| 9 | [0.631](https://www.kaggle.com/code/vyacheslavbolotin/birdclef-2025-ensemble-of-solutions?scriptVersionId=227303753) | v24 | [5](https://www.kaggle.com/code/jocelyndumlao/birdclef-2025-mfcc-feature-roc-auc-analysis) + [6](https://www.kaggle.com/code/myso1987/birdclef2025-3-submit-baseline-5s) | (0.500 + 0.631) | &nbsp; [ 0.09 + 0.91 ]() | CPU | 2m 47sec |\n| 10 | [0.631](https://www.kaggle.com/code/vyacheslavbolotin/birdclef-2025-ensemble-of-solutions?scriptVersionId=227390697) | v25 | [5](https://www.kaggle.com/code/jocelyndumlao/birdclef-2025-mfcc-feature-roc-auc-analysis) + [6](https://www.kaggle.com/code/myso1987/birdclef2025-3-submit-baseline-5s) | (0.500 + 0.631) | &nbsp; [ 0.21 + 0.79 ]() | CPU | 2m 40sec |\n| 18 | [0.626](https://www.kaggle.com/code/vyacheslavbolotin/birdclef-2025-ensemble-of-solutions?scriptVersionId=227662232) | v37 | [6](https://www.kaggle.com/code/myso1987/birdclef2025-3-submit-baseline-5s) + [9](https://www.kaggle.com/code/kadircandrisolu/pytorch-inference-birdclef2025-baseline) | (0.631 + 0.552) | &nbsp; [ 0.70 + 0.30 ]() | CPU | < 1h |\n| 19 | [0.695](https://www.kaggle.com/code/vyacheslavbolotin/birdclef-2025-ensemble-of-solutions?scriptVersionId=227672990) | v42 | [6](https://www.kaggle.com/code/myso1987/birdclef2025-3-submit-baseline-5s) + [8](https://www.kaggle.com/code/agcsdedf/birdclef-2025-base-submit) + [9](https://www.kaggle.com/code/kadircandrisolu/pytorch-inference-birdclef2025-baseline) | (0.631 + 0.682 + 0.552) | &nbsp; [ 0.45 + 0.54 + 0.01 ]() | CPU | < 1h |\n| 20 | [0.696](https://www.kaggle.com/code/vyacheslavbolotin/birdclef-2025-ensemble-of-solutions?scriptVersionId=227666177) | v40 | [6](https://www.kaggle.com/code/myso1987/birdclef2025-3-submit-baseline-5s) + [8](https://www.kaggle.com/code/agcsdedf/birdclef-2025-base-submit) | (0.631 + 0.682) | &nbsp; [ 0.50 + 0.50 ]() | CPU | < 1h |\n| 21 | [0.697](https://www.kaggle.com/code/vyacheslavbolotin/birdclef-2025-ensemble-of-solutions?scriptVersionId=227884787) | v48 | [6](https://www.kaggle.com/code/myso1987/birdclef2025-3-submit-baseline-5s) + [8](https://www.kaggle.com/code/agcsdedf/birdclef-2025-base-submit) + [5](https://www.kaggle.com/code/jocelyndumlao/birdclef-2025-mfcc-feature-roc-auc-analysis) | (0.631 + 0.682 + 0.500) | &nbsp; [ 0.54 + 0.45 + 0.01 ]() | CPU | < 1h | \n| 22 | [0.695](https://www.kaggle.com/code/vyacheslavbolotin/birdclef-2025-ensemble-of-solutions?scriptVersionId=227890897) | v49 | [6](https://www.kaggle.com/code/myso1987/birdclef2025-3-submit-baseline-5s) + [8](https://www.kaggle.com/code/agcsdedf/birdclef-2025-base-submit) + [5](https://www.kaggle.com/code/jocelyndumlao/birdclef-2025-mfcc-feature-roc-auc-analysis) | (0.631 + 0.682 + 0.500) | &nbsp; [ 0.45 + 0.54 + 0.01 ]() | CPU | < 1h |\n| 23 | [0.697](https://www.kaggle.com/code/vyacheslavbolotin/birdclef-2025-ensemble-of-solutions?scriptVersionId=227902104) | v51 | [6](https://www.kaggle.com/code/myso1987/birdclef2025-3-submit-baseline-5s) + [8](https://www.kaggle.com/code/agcsdedf/birdclef-2025-base-submit) + [9](https://www.kaggle.com/code/kadircandrisolu/pytorch-inference-birdclef2025-baseline) + [5](https://www.kaggle.com/code/jocelyndumlao/birdclef-2025-mfcc-feature-roc-auc-analysis) | (0.631 + 0.682 + 0.552 + 0.500) | &nbsp; [ 0.54 + 0.42 + 0.02 + 0.02 ]() | CPU | < 1h |\n| 24 | [0.697](https://www.kaggle.com/code/vyacheslavbolotin/birdclef-2025-ensemble-of-solutions?scriptVersionId=227969415) | v54 | [6](https://www.kaggle.com/code/myso1987/birdclef2025-3-submit-baseline-5s) + [8](https://www.kaggle.com/code/agcsdedf/birdclef-2025-base-submit) + [5](https://www.kaggle.com/code/jocelyndumlao/birdclef-2025-mfcc-feature-roc-auc-analysis) | (0.631 + 0.682 + 0.500) | &nbsp; [ 0.54 + 0.41 + 0.05 ]() | CPU | 3m 20sec |\n| 25 | [0.697](https://www.kaggle.com/code/vyacheslavbolotin/birdclef-2025-ensemble-of-solutions?scriptVersionId=227973687) | v55 | [6](https://www.kaggle.com/code/myso1987/birdclef2025-3-submit-baseline-5s) + [8](https://www.kaggle.com/code/agcsdedf/birdclef-2025-base-submit) + [5](https://www.kaggle.com/code/jocelyndumlao/birdclef-2025-mfcc-feature-roc-auc-analysis) | (0.631 + 0.682 + 0.500) | &nbsp; [ 0.52 + 0.41 + 0.07 ]() | CPU | 3m 31sec |\n| 26 | [0.698](https://www.kaggle.com/code/vyacheslavbolotin/birdclef-2025-ensemble-of-solutions?scriptVersionId=228084723) | v56 | [6](https://www.kaggle.com/code/myso1987/birdclef2025-3-submit-baseline-5s) + [8](https://www.kaggle.com/code/agcsdedf/birdclef-2025-base-submit) + [5](https://www.kaggle.com/code/jocelyndumlao/birdclef-2025-mfcc-feature-roc-auc-analysis) | (0.631 + 0.682 + 0.500) | &nbsp; [ 0.55 + 0.39 + 0.06 ]() | CPU | 3m 7sec |\n| 27 | [0.698](https://www.kaggle.com/code/vyacheslavbolotin/birdclef-2025-ensemble-of-solutions?scriptVersionId=228128213) | v58 | [6](https://www.kaggle.com/code/myso1987/birdclef2025-3-submit-baseline-5s) + [8](https://www.kaggle.com/code/agcsdedf/birdclef-2025-base-submit) + [5](https://www.kaggle.com/code/jocelyndumlao/birdclef-2025-mfcc-feature-roc-auc-analysis) | (0.631 + 0.682 + 0.500) | &nbsp; [ 0.55 + 0.38 + 0.07 ]() | CPU | 3m 17sec |\n| 29 | [0.698](https://www.kaggle.com/code/vyacheslavbolotin/birdclef-2025-ensemble-of-solutions?scriptVersionId=228134306) | v59 | [6](https://www.kaggle.com/code/myso1987/birdclef2025-3-submit-baseline-5s) + [8](https://www.kaggle.com/code/agcsdedf/birdclef-2025-base-submit) + [5](https://www.kaggle.com/code/jocelyndumlao/birdclef-2025-mfcc-feature-roc-auc-analysis) | (0.631 + 0.682 + 0.500) | &nbsp; [ 0.55 + 0.37 + 0.08 ]() | CPU | 3m 21sec |\n| 30 | [0.698](https://www.kaggle.com/code/vyacheslavbolotin/birdclef-2025-ensemble-of-solutions?scriptVersionId=228142762) | v60 | [6](https://www.kaggle.com/code/myso1987/birdclef2025-3-submit-baseline-5s) + [8](https://www.kaggle.com/code/agcsdedf/birdclef-2025-base-submit) + [5](https://www.kaggle.com/code/jocelyndumlao/birdclef-2025-mfcc-feature-roc-auc-analysis) | (0.631 + 0.682 + 0.500) | &nbsp; [ 0.55 + 0.34 + 0.11 ]() | CPU | 3m 5sec |\n| 31 | [0.698](https://www.kaggle.com/code/vyacheslavbolotin/birdclef-2025-ensemble-of-solutions?scriptVersionId=228166784) | v61 | [6](https://www.kaggle.com/code/myso1987/birdclef2025-3-submit-baseline-5s) + [8](https://www.kaggle.com/code/agcsdedf/birdclef-2025-base-submit) + [5](https://www.kaggle.com/code/jocelyndumlao/birdclef-2025-mfcc-feature-roc-auc-analysis) | (0.631 + 0.682 + 0.500) | &nbsp; [ 0.57 + 0.30 + 0.13 ]() | CPU | 3m 16sec |\n| 32 | [0.699](https://www.kaggle.com/code/vyacheslavbolotin/birdclef-2025-ensemble-of-solutions?scriptVersionId=228193564) | v62 | [6](https://www.kaggle.com/code/myso1987/birdclef2025-3-submit-baseline-5s) + [8](https://www.kaggle.com/code/agcsdedf/birdclef-2025-base-submit) + [5](https://www.kaggle.com/code/jocelyndumlao/birdclef-2025-mfcc-feature-roc-auc-analysis) | (0.631 + 0.682 + 0.500) | &nbsp; [ 0.60 + 0.27 + 0.13 ]() | CPU | 3m 20sec |\n| 33 | [0.699](https://www.kaggle.com/code/vyacheslavbolotin/birdclef-2025-ensemble-of-solutions?scriptVersionId=228212265) | v64 | [6](https://www.kaggle.com/code/myso1987/birdclef2025-3-submit-baseline-5s) + [8](https://www.kaggle.com/code/agcsdedf/birdclef-2025-base-submit) + [5](https://www.kaggle.com/code/jocelyndumlao/birdclef-2025-mfcc-feature-roc-auc-analysis) | (0.631 + 0.682 + 0.500) | &nbsp; [ 0.64 + 0.23 + 0.13 ]() | CPU | 3m 10sec |\n| 34 | [0.700](https://www.kaggle.com/code/vyacheslavbolotin/birdclef-2025-ensemble-of-solutions?scriptVersionId=228241815) | v65 | [6](https://www.kaggle.com/code/myso1987/birdclef2025-3-submit-baseline-5s) + [8](https://www.kaggle.com/code/agcsdedf/birdclef-2025-base-submit) + [5](https://www.kaggle.com/code/jocelyndumlao/birdclef-2025-mfcc-feature-roc-auc-analysis) | (0.631 + 0.682 + 0.500) | &nbsp; [ 0.70 + 0.17 + 0.13 ]() | CPU | 3m 22sec |\n| 35 | [0.699](https://www.kaggle.com/code/vyacheslavbolotin/birdclef-2025-ensemble-of-solutions?scriptVersionId=228280463) | v67 | [6](https://www.kaggle.com/code/myso1987/birdclef2025-3-submit-baseline-5s) + [12](https://www.kaggle.com/code/agcsdedf/birdclef-2025-openvino-inf) + [5](https://www.kaggle.com/code/jocelyndumlao/birdclef-2025-mfcc-feature-roc-auc-analysis) | (0.631 + 0.723 + 0.500) | &nbsp; [ 0.70 + 0.17 + 0.13 ]() | CPU | 3m 51sec |\n| 36 | [0.728](https://www.kaggle.com/code/vyacheslavbolotin/birdclef-2025-ensemble-of-solutions?scriptVersionId=228812279) | v69 | [6](https://www.kaggle.com/code/myso1987/birdclef2025-3-submit-baseline-5s) + [11](https://www.kaggle.com/code/kadircandrisolu/efficientnet-b0-pytorch-inference-birdclef-25/notebook) + [5](https://www.kaggle.com/code/jocelyndumlao/birdclef-2025-inference-w-simplecnn-spectrogram) | (0.631 + 0.761 + 0.500) | &nbsp; [ 0.70 + 0.17 + 0.13 ]() | CPU | < 30 min|\n| | | | | | | |\n| 52 | [?]() | ? |  &nbsp; &nbsp; &nbsp; &nbsp; [6](https://www.kaggle.com/code/myso1987/birdclef2025-3-submit-baseline-5s) + [11](https://www.kaggle.com/code/kadircandrisolu/efficientnet-b0-pytorch-inference-birdclef-25/notebook) + [14](https://www.kaggle.com/code/salmanahmedtamu/labels-tta-efficientnet-b0-pytorch-inference) + [12](https://www.kaggle.com/code/agcsdedf/birdclef-2025-openvino-inf) + [8](https://www.kaggle.com/code/agcsdedf/birdclef-2025-base-submit)|(0.631 + 0.761 + 0.793 + 0.723 + 0.682) |[ 0.005 + 0.285 + 0.690 + 0.010 + 0.005]() | ? |\n|  | [?]() | ? |  &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [6](https://www.kaggle.com/code/myso1987/birdclef2025-3-submit-baseline-5s) + [11](https://www.kaggle.com/code/kadircandrisolu/efficientnet-b0-pytorch-inference-birdclef-25/notebook) + [14](https://www.kaggle.com/code/salmanahmedtamu/labels-tta-efficientnet-b0-pytorch-inference) + [12](https://www.kaggle.com/code/agcsdedf/birdclef-2025-openvino-inf) + [15](https://www.kaggle.com/code/kumarandatascientist/lb-0-801-efficientnet-b0-pytorch-pipeline)|(0.631 + 0.761 + 0.793 + 0.723 + 0.801) |[ 0.005 + 0.285 + 0.285 + 0.010 + 0.405]() | ? |\n\nv.48 < v.51 < v.54 < v.56 < v.58 < v.59 < v.60 < v.61 < v.62 < v.64\n\nv.55 < v.51","metadata":{"_kg_hide-input":true,"_kg_hide-output":true}},{"cell_type":"code","source":"if exEDA:\n    OPTION = 'EDA'\n    WEIGHTS            = []\n    FILES_SUBM         = []\n    ENSEMBLE_SOLUTIONS = ['SOLUTION_3']","metadata":{"trusted":true,"_kg_hide-input":true,"_kg_hide-output":true,"jupyter":{"source_hidden":true},"execution":{"iopub.status.busy":"2025-04-07T13:36:18.776155Z","iopub.execute_input":"2025-04-07T13:36:18.776602Z","iopub.status.idle":"2025-04-07T13:36:18.798082Z","shell.execute_reply.started":"2025-04-07T13:36:18.776564Z","shell.execute_reply":"2025-04-07T13:36:18.796862Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"if type(OPTION) == dict:\n\n    def from_dict(OPTION):\n        OP = OPTION['N']\n        LB  = [e['LB']        for e in OPTION['SOLUTIONs']]\n        ES  = [e['SOLUTION']  for e in OPTION['SOLUTIONs']]\n        FS  = [e['FILE_SUBM'] for e in OPTION['SOLUTIONs']]\n        WTS = [e['WEIGHT']    for e in OPTION['SOLUTIONs']]\n        return OP, LB, ES, FS, WTS \n\n    OPTION, LB, ENSEMBLE_SOLUTIONS, FILES_SUBM, WEIGHTS = from_dict(OPTION)\n\n\nimport time\n\n\ncell_Start_time = time.time()\n\n\ndef begin(solution_name):\n    global cell_Start_time; cell_Start_time = time.time()\n    print(solution_name)\n\n\ndef end():\n    global cell_Start_time;\n    print(\"cell time:\", round(time.time() - cell_Start_time, 1))\n\n\ndef Geographic_():\n    import os\n    import re\n    import pandas as pd\n    import plotly.graph_objects as go\n    from scipy.interpolate import interp1d\n    import plotly.io as pio\n    import plotly.graph_objects as go\n    \n    pio.renderers.default = 'iframe'\n\n    # Define Paths \n    INPUT_PATH = './' \n    TRAIN_AUDIO_PATH = './'  \n    \n    # Load the training metadata\n    train_meta = pd.read_csv(os.path.join(INPUT_PATH, '/kaggle/input/birdclef-2025/train.csv'))\n        \n        \n    # Data Preprocessing\n    def preprocess_train_meta(df):\n        \"\"\"Preprocesses the training metadata.\"\"\"\n        df['secondary_labels'] = df['secondary_labels'].apply(lambda x: re.findall(r\"'(\\w+)'\", x))\n        df['len_sec_labels'] = df['secondary_labels'].map(len)\n        df['file_path'] = df.apply(lambda row: os.path.join(TRAIN_AUDIO_PATH, row['filename']), axis=1)\n        return df\n\n\n    train_meta = preprocess_train_meta(train_meta)\n    \n    # Data aggregation and preparation\n    train_meta_grouped = train_meta.groupby(['primary_label', 'latitude', 'longitude']).count().reset_index()[\n        ['primary_label', 'scientific_name', 'latitude', 'longitude']].rename(columns={'scientific_name': 'count'})\n    \n        \n    df = train_meta.merge(train_meta_grouped, on=['primary_label', 'latitude', 'longitude'], how='left').dropna(\n        subset=['count'])\n    df['count'] = df['count'].astype('int')\n    \n    values_list = df['count'].values.tolist()\n\n    # Radius scaling using interpolation\n    interpolation = interp1d([1, max(values_list)], [3, 20])  # Adjust range [min_radius, max_radius] as needed\n    radius = interpolation(values_list)\n    \n    # Color scale selection (using Plotly's built-in options for better aesthetics)\n    color_scale = \"Rainbow\"  # \"Hot\", \"Viridis\", \"Plasma\", \"Cividis\", \"Rainbow\"\n        \n    # Densitymapbox plot with enhanced aesthetics\n    fig = go.Figure(go.Densitymapbox(\n        lat=df['latitude'],\n        lon=df['longitude'],\n        z=df['count'],\n        radius=radius,\n        colorscale=color_scale,  # Use chosen colorscale\n        zmin=min(df['count']),  # Explicitly set zmin and zmax for consistent color mapping\n        zmax=max(df['count']),\n        opacity=0.7,  # Adjust opacity for better visualization\n        colorbar=dict(title=\"Observation Count\")  # Add a title to the colorbar\n    ))\n    \n    # Map layout customization\n    fig.update_layout(\n        title=\"Geographic Distribution of Primary Labels, by Philipino master Jocelyn Dumlao, solution.5\",  # Adding a descriptive title\n        title_x=0.5,  # Center the title\n        mapbox_style=\"carto-positron\",  # Choose a suitable basemap style: 'open-street-map', 'carto-positron', 'stamen-terrain', 'white-bg'\n        height=800,\n        mapbox={\n            'center': {'lat': df['latitude'].mean(), 'lon': df['longitude'].mean()},  # Center on the data\n            'zoom': 2,  # Adjust initial zoom level\n            'accesstoken': \"pk.eyJ1IjoiZXJpY21mYXJsaW5nIiwiYSI6ImNqOHB2eTMxOTAza2EzMm1xeDFiaG9zNnoifQ.xLWC_nwyxG2WbNlWr33oIA\"\n        },\n        margin={\"r\": 0, \"t\": 50, \"l\": 0, \"b\": 0},  # Adjust margins for better appearance\n        template=\"plotly_white\"  # Use a clean template\n    )\n\n    fig.show()","metadata":{"trusted":true,"_kg_hide-input":true,"_kg_hide-output":true,"jupyter":{"source_hidden":true},"execution":{"iopub.status.busy":"2025-04-07T13:36:18.799377Z","iopub.execute_input":"2025-04-07T13:36:18.799681Z","iopub.status.idle":"2025-04-07T13:36:18.820793Z","shell.execute_reply.started":"2025-04-07T13:36:18.799654Z","shell.execute_reply":"2025-04-07T13:36:18.819677Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## [Stefan Kahl](https://www.kaggle.com/stefankahl)\n### 1. [BirdCLEF+ 2025 Sample Submission](https://www.kaggle.com/code/stefankahl/birdclef-2025-sample-submission)","metadata":{}},{"cell_type":"code","source":"solution = 'SOLUTION_1'\n\nif  solution in ENSEMBLE_SOLUTIONS:\n                                    \n    begin(solution)\n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 0')\n    \n    \n    # BirdCLEF+ 2025 Sample Submission\n    # \n    # This is a quick run through the submission process. Test data is hidden, so we can't access it before submission. In order to make a valid submission, here's what we'll do:\n    # \n    # 1. Make sure we predict for all 206 classes in the train data\n    # 2. Load a list of test soundscapes\n    # 3. Process each soundscape\n    #      - load audio\n    #      - split into 5-second chunks\n    #      - run model inference for each chunk\n    #      - save predictions\n    # 4. Make submission csv file\n    # 5. Submit\n    # \n    # Ok, so here we go.\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1')\n    \n    \n    import os\n    import librosa\n    import numpy as np\n    import pandas as pd\n    \n    # Set seed\n    np.random.seed(42)\n    \n    # Class labels from train audio\n    class_labels = sorted(os.listdir('/kaggle/input/birdclef-2025/train_audio/'))\n    \n    # List of test soundscapes (only visible during submission)\n    test_soundscape_path = '/kaggle/input/birdclef-2025/test_soundscapes/'\n    test_soundscapes = [os.path.join(test_soundscape_path, afile) for afile in sorted(os.listdir(test_soundscape_path)) if afile.endswith('.ogg')]\n    \n    # Open each soundscape and make predictions for 5-second segments\n    # Use pandas df with 'row_id' plus class labels as columns\n    predictions = pd.DataFrame(columns=['row_id'] + class_labels)\n    for soundscape in test_soundscapes:\n    \n        # Load audio\n        sig, rate = librosa.load(path=soundscape, sr=None)\n    \n        # Split into 5-second chunks\n        chunks = []\n        for i in range(0, len(sig), rate*5):\n            chunk = sig[i:i+rate*5]\n            chunks.append(chunk)\n            \n        # Make predictions for each chunk\n        for i, chunk in enumerate(chunks):\n            \n            # Get row id  (soundscape id + end time of 5s chunk)      \n            row_id = os.path.basename(soundscape).split('.')[0] + f'_{i * 5 + 5}'\n            \n            # Make prediction (let's use random scores for now)\n            # scores = model.predict...\n            scores = np.random.rand(len(class_labels))\n            \n            # Append to predictions as new row\n            new_row = pd.DataFrame([[row_id] + list(scores)], columns=['row_id'] + class_labels)\n            predictions = pd.concat([predictions, new_row], axis=0, ignore_index=True)\n            \n    # Save prediction as csv\n    predictions.to_csv('subm_1.csv', index=False)\n    predictions.head()\n            \n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2')\n    \n    \n    # In order to make a submission, we need to:\n    # - disable internet for this notebook (Settings --> Turn off internet)\n    # - make sure the notebook runs without errors and a submission file gets created\n    # - submit to competition (panel on the right)\n    # - wait for the notebook to finish (this may take a while, remember there's a 90min time limit)\n    # \n    # If all goes well, we should see our submission scores \n    \n    \n    end()","metadata":{"trusted":true,"_kg_hide-input":true,"_kg_hide-output":true,"jupyter":{"source_hidden":true},"execution":{"iopub.status.busy":"2025-04-07T13:36:18.822108Z","iopub.execute_input":"2025-04-07T13:36:18.822484Z","iopub.status.idle":"2025-04-07T13:36:18.845118Z","shell.execute_reply.started":"2025-04-07T13:36:18.822449Z","shell.execute_reply":"2025-04-07T13:36:18.843951Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## [Carlo Lepelaars](https://www.kaggle.com/carlolepelaars)\n### 10. [BirdCLEF+ 2025: Simple Submission](https://www.kaggle.com/code/carlolepelaars/birdclef-2025-simple-submission)","metadata":{}},{"cell_type":"code","source":"solution = 'SOLUTION_10'\n\nif  solution in ENSEMBLE_SOLUTIONS:\n                                                        \n    begin(solution)\n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 0')\n    \n    \n    # BirdCLEF+ 2025: Simple Submission\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1')\n    \n    \n    # ![](https://www.kaggle.com/competitions/91844/images/header)\n    # \n    # This notebook shows a simple way to setup an inference pipeline for the \n    # [BirdCLEF+ 2025 competition](https://www.kaggle.com/competitions/birdclef-2025). \n    # \n    # Credits to [Stefan Kahl](https://www.kaggle.com/stefankahl) who set up \n    # [one of the first sample submission notebooks](https://www.kaggle.com/code/stefankahl/birdclef-2025-sample-submission). \n    # \n    # I simplified the process and optimized the loading/chunking process with [numpy](https://numpy.org/) \n    # and [soundfile](https://github.com/bastibe/python-soundfile). \n    # It can be helpful to first think about the problem yourself and then check out both approaches.\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2')\n    \n    \n    # Dependencies\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 3')\n    \n    \n    # All these dependencies are included in the standard Kaggle Notebooks environment.\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 4')\n    \n    \n    import numpy as np\n    import pandas as pd\n    from glob import glob\n    import soundfile as sf\n    from pathlib import Path\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 5')\n    \n    \n    # Get Paths and Labels\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 6')\n    \n    \n    # From the [competition description](https://www.kaggle.com/competitions/birdclef-2025/data) \n    # we know that the data is resampled to 32kHz, so we use a sample rate of `32_000`. \n    # A submission requires us to submit in 5 second chunks, so we chunk on `32000 * 5 = 160,000` samples.\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 7')\n    \n    \n    BASE_PATH = \"/kaggle/input/birdclef-2025/\"\n    TAXONOMY_PATH = f\"{BASE_PATH}taxonomy.csv\"\n    TEST_SCAPES_PATH = f\"{BASE_PATH}test_soundscapes/\"\n    SR, CHUNK_SEC = 32_000, 5\n    FIVE_SEC_SR = SR * CHUNK_SEC\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 8')\n    \n    \n    # We retrieve the labels from the taxonomy file.\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 9')\n    \n    \n    t = pd.read_csv(TAXONOMY_PATH)\n    class_labels = list(t['primary_label'])\n    class_labels[:5], class_labels[-5:]\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 10')\n    \n    \n    # `TEST_SCAPES_PATH` is populated during submission of the notebook.\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 11')\n    \n    \n    # Populated during submission of notebook\n    scape_paths = glob(TEST_SCAPES_PATH + \"*.ogg\")\n    scape_paths\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 12')\n    \n    \n    # Helper functions\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 13')\n    \n    \n    # Loading of audio is done efficiently using `soundfile`. `np.array_split` is an efficient way to split data into chunks.\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 14')\n    \n    \n    def load_audio(path) -> np.array:\n        with sf.SoundFile(path) as f: audio = f.read()\n        return audio\n    \n    def get_chunks(path) -> list[np.array]:\n        \"\"\" Create 5 second chunks (1D arrays) from audio file. \"\"\"\n        audio = load_audio(path)\n        return np.array_split(audio, np.ceil(audio.shape[0] / FIVE_SEC_SR))\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 15')\n    \n    \n    # Inference\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 16')\n    \n    \n    # We make a prediction for each chunk within each soundscape.\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 17')\n    \n    \n    cols = [\"row_id\"] + class_labels\n    rows = []\n    for path in scape_paths:\n        for i, chunk in enumerate(get_chunks(path), start=1):\n            row_id = f\"{Path(path).stem}_{i * CHUNK_SEC}\"\n            # Place your inference function here (Random predictions as placeholder)\n            #########################################\n            pred = np.random.rand(len(class_labels))\n            #########################################\n            rows.append([row_id] + pred.tolist())\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 18')\n    \n    \n    # We make sure that the final file contains `row_id` and the `206` class labels. Be careful if you have shuffled the order of your class labels in training.\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 19')\n    \n    \n    preds = pd.DataFrame(rows, columns=cols)\n    preds.head(2)\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 20')\n    \n    \n    # Submission\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 21')\n    \n    \n    preds.to_csv(\"subm_10.csv\", index=False)\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 22')\n    \n    \n    # **That's it! Hope this helps you to get started with the competition!**\n    # \n    # **If you like this Kaggle kernel, consider giving an upvote and leaving a comment. Your feedback is very welcome! I will try to implement your suggestions in this kernel.**\n    \n    \n    end()","metadata":{"trusted":true,"_kg_hide-input":true,"_kg_hide-output":true,"jupyter":{"source_hidden":true},"execution":{"iopub.status.busy":"2025-04-07T13:36:18.967544Z","iopub.execute_input":"2025-04-07T13:36:18.968091Z","iopub.status.idle":"2025-04-07T13:36:18.985692Z","shell.execute_reply.started":"2025-04-07T13:36:18.968048Z","shell.execute_reply":"2025-04-07T13:36:18.984290Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## [Rahul Jiwane](https://www.kaggle.com/rahuljiwane)\n### 2. [Notebook Bird: Rahul Jiwane](https://www.kaggle.com/code/rahuljiwane/notebook-bird-rahul-jiwane)","metadata":{}},{"cell_type":"code","source":"solution = 'SOLUTION_2'\n\nif  solution in ENSEMBLE_SOLUTIONS:\n                                    \n    begin(solution)\n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 0')\n    \n    \n    # This Python 3 environment comes with many helpful analytics libraries installed\n    # It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n    # For example, here's several helpful packages to load\n    \n    import numpy as np # linear algebra\n    import pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n    \n    # Input data files are available in the read-only \"../input/\" directory\n    # For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n    \n    import os\n    #for dirname, _, filenames in os.walk('/kaggle/input'):\n        #for filename in filenames:\n            #print(os.path.join(dirname, filename))\n    \n    # You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n    # You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1')\n    \n    \n    import os\n    import librosa\n    import numpy as np\n    import pandas as pd\n\n    \n    # Set seed\n    np.random.seed(2)\n    \n    # Class labels from train audio\n    class_labels = sorted(os.listdir('/kaggle/input/birdclef-2025/train_audio/'))\n    \n    # List of test soundscapes (only visible during submission)\n    test_soundscape_path = '/kaggle/input/birdclef-2025/test_soundscapes/'\n    test_soundscapes = [os.path.join(test_soundscape_path, afile) for afile in sorted(os.listdir(test_soundscape_path)) if afile.endswith('.ogg')]\n    \n    # Open each soundscape and make predictions for 5-second segments\n    # Use pandas df with 'row_id' plus class labels as columns\n    predictions = pd.DataFrame(columns=['row_id'] + class_labels)\n    for soundscape in test_soundscapes:\n    \n        # Load audio\n        sig, rate = librosa.load(path=soundscape, sr=None)\n    \n        # Split into 5-second chunks\n        chunks = []\n        for i in range(0, len(sig), rate*5):\n            chunk = sig[i:i+rate*5]\n            chunks.append(chunk)\n            \n        # Make predictions for each chunk\n        for i, chunk in enumerate(chunks):\n            \n            # Get row id  (soundscape id + end time of 5s chunk)      \n            row_id = os.path.basename(soundscape).split('.')[0] + f'_{i * 5 + 5}'\n            \n            # Make prediction (let's use random scores for now)\n            # scores = model.predict...\n            scores = np.random.rand(len(class_labels))\n            \n            # Append to predictions as new row\n            new_row = pd.DataFrame([[row_id] + list(scores)], columns=['row_id'] + class_labels)\n            predictions = pd.concat([predictions, new_row], axis=0, ignore_index=True)\n            \n    # Save prediction as csv\n    predictions.to_csv('subm_2.csv', index=False)\n    display(predictions.head())\n    \n    \n    end()","metadata":{"trusted":true,"_kg_hide-input":true,"_kg_hide-output":true,"jupyter":{"source_hidden":true},"execution":{"iopub.status.busy":"2025-04-07T13:36:18.987176Z","iopub.execute_input":"2025-04-07T13:36:18.987596Z","iopub.status.idle":"2025-04-07T13:36:19.009111Z","shell.execute_reply.started":"2025-04-07T13:36:18.987555Z","shell.execute_reply":"2025-04-07T13:36:19.008095Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## [Marília Prata](https://www.kaggle.com/mpwolke)\n### 3. [BirdClef 2025: El Silencio Natural Reserve](https://www.kaggle.com/code/mpwolke/birdclef-2025-el-silencio-natural-reserve)","metadata":{}},{"cell_type":"code","source":"solution = 'SOLUTION_3'\n\nif  solution in ENSEMBLE_SOLUTIONS:\n                                \n    begin(solution)\n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 0')\n    \n    \n    # Published on March 10, 2025. By Prata, Marília (mpwolke)\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1')\n    \n    \n    # This Python 3 environment comes with many helpful analytics libraries installed\n    # It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n    # For example, here's several helpful packages to load\n    \n    import numpy as np # linear algebra\n    import pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n    import matplotlib.pyplot as plt\n    import seaborn as sns\n    import plotly.graph_objs as go\n    import plotly.offline as py\n    import plotly.express as px\n    \n    #Ignore warnings\n    import warnings\n    warnings.filterwarnings('ignore')\n    \n    # Input data files are available in the read-only \"../input/\" directory\n    # For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n    \n    import os\n    for dirname, _, filenames in os.walk('/kaggle/input'):\n        for filename in filenames:\n            print(os.path.join(dirname, filename))\n    \n    # You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n    # You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2')\n    \n    \n    # Dataset Description\n    # \n    # \"Your challenge in this competition is to identify which species (birds, amphibians, mammals, insects) are calling in recordings made in **El Silencio Natural Reserve, Colombia**. This is an important task for scientists who monitor animal populations for conservation purposes. More accurate solutions could enable more comprehensive monitoring.\"\n    # \n    # https://www.kaggle.com/competitions/birdclef-2025/data\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 3')\n    \n    \n    # ![](https://image2.slideserve.com/5206482/colombia-middle-magdalena-valley-properties-l.jpg)SlideServe\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 4')\n    \n    \n    # Competition Citation:\n    # \n    # @misc{birdclef-2025,\n    # \n    #     author = {Holger Klinck and Juan Sebastián Cañas and Maggie Demkin and Sohier Dane and Stefan Kahl and Tom Denton},\n    #     \n    #     title = {BirdCLEF+ 2025},\n    #     \n    #     year = {2025},\n    #     howpublished = {\\url{https://kaggle.com/competitions/birdclef-2025}},\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 5')\n    \n    \n    #By Paulo Junqueira https://www.kaggle.com/code/paulojunqueira/pew-pew-overview-birdclef-2023/notebook\n    \n    import re\n    import librosa\n    import librosa.display\n    \n    import IPython.display as ipd\n    from urllib.request import urlopen\n    from datetime import datetime, timedelta\n    \n    import plotly.graph_objects as go\n    from scipy.interpolate import interp1d \n    from bs4 import BeautifulSoup as bs\n    import librosa\n    import librosa.display\n    import IPython.display as ipd\n    # import noisereduce as nr\n    \n    from tqdm.notebook import tqdm\n    # Pytorch\n    import torch\n    import torchaudio\n    import requests\n    from PIL import Image\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 6')\n    \n    \n    # metadata csv file\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 7')\n    \n    \n    meta = pd.read_csv('../input/birdclef-2025/train.csv')\n    meta['secondary_labels'] = meta['secondary_labels'].apply(lambda x: re.findall(r\"'(\\w+)'\", x))\n    meta['len_sec_labels'] = meta['secondary_labels'].map(len)\n    meta.head(2)\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 8')\n    \n    \n    # The Middle Magdalena Valley\n    # \n    # \n    # **The silence, natural reserve, and research station.**\n    # \n    # \n    # \"Let’s save the forests and wetlands of the Middle Magdalena Valley.\"\n    # \n    # \"Biodiverse Colombia Foundation has been working in the Middle Magdalena Valley since 2006 on conservation projects for three threatened species: the gray tamarin (Saguinus leucopus), the river turtle (Podocnemis lewyana), both endemic to this area, and the brown spider monkey (Ateles fusciceps).\"\n    # \n    # https://www.fundacionbiodiversa.org/fundacion2024/information/\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 9')\n    \n    \n    #By Paulo Junqueira https://www.kaggle.com/code/paulojunqueira/pew-pew-overview-birdclef-2023/notebook\n    \n    #Two lines Required to Plot Plotly\n    import plotly.io as pio\n    pio.renderers.default = 'iframe'\n    \n    \n    df_plot = meta.groupby(['primary_label','latitude', 'longitude']).count().reset_index()[['primary_label','scientific_name','latitude', 'longitude']].rename(columns = {'scientific_name':'count'})\n    meta_2 = meta.merge(df_plot, on = ['primary_label','latitude', 'longitude'], how = 'left').dropna(subset = ['count'])\n    meta_2['count'] = meta_2['count'].astype('int')\n    \n    values_list = meta_2['count'].values.tolist()\n    \n    interpolation = interp1d([1, max(values_list)], [3,20])\n    radius = interpolation(values_list)\n    fig = go.Figure(go.Densitymapbox(lat =meta_2['latitude'],lon = meta_2['longitude'], radius = radius,z = meta_2['count']))\n    \n    fig.update_layout(mapbox_style=\"open-street-map\",height = 800,\n                      mapbox = {\n                              'center': {'lat': 0, \n                              'lon': 0},\n                          'zoom':0\n                      })\n    fig.show()\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 10')\n    \n    \n    ## Protection of the last forest remnants and wetlands: an urgent need.\n    # \n    # \"Humid tropical rainforests, Earth's most biodiverse and ancient ecosystems, are vital for climate regulation and water resource protection. However, rainforests face severe threats. In **Colombia**, a megadiverse country, **the lowlands of the Magdalena Valley** are a biodiversity hotspot and home to many endangered species. Over 70% of the Magdalena Valley lowland rainforests are replaced by vast pastures for cattle ranching, and **illegal logging is common in forest fragment remnants.** The protection of the last forest remnants and wetlands is an urgent need.\"\n    # \n    # https://www.kaggle.com/competitions/birdclef-2025/overview\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 11')\n    \n    \n    #By Ben Jenkins https://www.kaggle.com/code/benjenkins96/identify-eastern-african-bird-species-by-sound\n    \n    # Set up a figure with subplots\n    fig, axs = plt.subplots(2, 2, figsize=(12, 8))\n    \n    # Plot a histogram of the latitude values\n    meta['latitude'].hist(bins=50, ax=axs[0, 0])\n    axs[0, 0].set_title('Distribution of Latitude', color='red')\n    axs[0, 0].set_xlabel('Latitude', color='red')\n    axs[0, 0].set_ylabel('Count', color='red')\n    # Plot a histogram of the longitude values\n    meta['longitude'].hist(bins=50, ax=axs[0, 1])\n    axs[0, 1].set_title('Distribution of Longitude', color='red')\n    axs[0, 1].set_xlabel('Longitude', color='red')\n    axs[0, 1].set_ylabel('Count', color='red')\n    \n    # Plot a scatterplot of the latitude and longitude values\n    meta.plot.scatter(x='longitude', y='latitude', alpha=0.1, ax=axs[1, 0])\n    axs[1, 0].set_title('Geographic Distribution of Recordings', color='red')\n    axs[1, 0].set_xlabel('Longitude', color='red')\n    axs[1, 0].set_ylabel('Latitude', color='red')\n    \n    # Print the top 10 authors with the most recordings\n    meta['author'].value_counts().nlargest(10).plot.barh(ax=axs[1, 1])\n    axs[1, 1].set_title('Top 10 Authors with the Most Recordings', color='red')\n    axs[1, 1].set_xlabel('Count', color='red')\n    axs[1, 1].set_ylabel('Author', color='red')\n    \n    # Adjust the layout of the subplots\n    plt.tight_layout()\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 12')\n    \n    \n    ## Most Recordings contributor: Jayrson Araujo de Oliveira  \n    # \n    # \"Professor passionate for Biology, especially Birds. He said, he is just beginning to learn about ornithology and intend to advance in my knowledge to the limit, especially recognition of songs' bird. The vast majority of the songs I put on this site are also on wikiaves.com.br.\"\n    # \n    # https://xeno-canto.org/contributor/LXKLWEDKEM\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 13')\n    \n    \n    # Taxonomy csv file\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 14')\n    \n    \n    taxonomy = pd.read_csv(\"/kaggle/input/birdclef-2025/taxonomy.csv\")\n    pd.set_option('display.max_columns', None)\n    taxonomy.head()\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 15')\n    \n    \n    ## Magdalena Valley animals Class Names\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 16')\n    \n    \n    ax = taxonomy['class_name'].value_counts()[:20].plot.barh(figsize=(16, 8), color='green')\n    ax.set_title('Colombian Animals Class names', size=18, color='orange')\n    ax.set_ylabel('class_name', size=10)\n    ax.set_xlabel('Count', size=10);\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 17')\n    \n    \n    # Groupby forest animals by Scientific name and Class names\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 18')\n    \n    \n    taxonomy.groupby(['scientific_name','class_name']).size().reset_index(name='count')\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 19')\n    \n    \n    ## Colombian Forest Animals by Class names\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 20')\n    \n    \n    #Eunji Goo https://www.kaggle.com/code/quantum09/is-it-going-to-rain\n    \n    class_proportion = taxonomy['class_name'].value_counts()/taxonomy['class_name'].value_counts().sum()\n    colormap = plt.cm.tab10(range(0, len(class_proportion)))\n    labels = class_proportion.index\n    values = class_proportion.values\n    \n    bars = plt.barh(labels, values)\n    \n    #plt.xlabel(\"Frequency\") #Não alterou nada\n    \n    #plt.legend(title='Forest Animals Class names' , bbox_to_anchor=(1.0, 1), loc='lower right')#HORRÌVEL!\n    \n    bar_plot = class_proportion.plot.barh(color=colormap)\n    \n    # Add titles, labels, invert y-axis\n    \n    bar_plot.set_title(\"Colombian Forest Animals by Class names\")\n    bar_plot.set_ylabel(\"Class Names\")\n    \n    total = values.sum()\n    for bar, count in zip(bars, values):\n        width = bar.get_width()\n        pct = count / total * 100\n        plt.text(width, bar.get_y() + bar.get_height()/2,\n                 f\"{count}\\n({pct:.1f}%)\",\n                 ha='left', va='center')\n    \n    #Invert the axis to have the descending order\n    bar_plot.invert_yaxis()\n    plt.show(bar_plot)\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 21')\n    \n    \n    # Let's try to hear a sample of EL Silencio Natural Reserve.\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 22')\n    \n    \n    #Code by Sayantan Mazumdar https://www.kaggle.com/swaralipibose/converting-audio-to-spectogram-noise-image-data/notebook\n    \n    !pip install soundfile -q\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 23')\n    \n    \n    #Code by Sayantan Mazumdar https://www.kaggle.com/swaralipibose/converting-audio-to-spectogram-noise-image-data/notebook\n    \n    !pip install noisereduce\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 24')\n    \n    \n    ## Convert Audio to Frequency\n    # \n    # It's freezing the page, therefore I commented the snippet.\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 25')\n    \n    \n    #Code by Sayantan Mazumdar https://www.kaggle.com/swaralipibose/converting-audio-to-spectogram-noise-image-data/notebook\n    \n    #Convert Audio to Frequency\n    \n    #import soundfile as sf\n    #freq,rate=sf.read('../input/birdclef-2025/train_audio/1139490/CSA36389.ogg')\n    #import plotly.express as px\n    #import numpy as np\n    #px.line(x=np.array(list(range(len(freq)))),y=freq)\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 26')\n    \n    \n    ## Display ogg Audio\n    # \n    # That's a description of the recordings, not an expected animal.  \n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 27')\n    \n    \n    #Code by Sayantan Mazumdar https://www.kaggle.com/swaralipibose/converting-audio-to-spectogram-noise-image-data/notebook\n    \n    import IPython\n    IPython.display.Audio(\"../input/birdclef-2025/train_audio/1139490/CSA36389.ogg\")\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 28')\n    \n    \n    #  El Silencio Natural Reserve\n    # \n    # \"Established in 2012, El Silencio Natural Reserve protects 5,407 acres of tropical lowland forests and wetlands. Home to diverse wildlife, including 295 birds, 34 amphibians, 69 mammals, 50 reptiles, and nearly 500 plant species, El Silencio is a **model for regional conservation and sustainability**.\"\n    # \n    # https://www.kaggle.com/competitions/birdclef-2025/overview\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 29')\n    \n    \n    # ![](https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSc_4VFSnT2fXRYvJkvJ_ksANI5b8eMT9ma3w&s)\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 30')\n    \n    \n    #Acknowledgements:\n    # \n    # Paulo Junqueira https://www.kaggle.com/code/paulojunqueira/pew-pew-overview-birdclef-2023/notebook\n    # \n    # Ben Jenkins https://www.kaggle.com/code/benjenkins96/identify-eastern-african-bird-species-by-sound\n    # \n    # Sayantan Mazumdar https://www.kaggle.com/swaralipibose/converting-audio-to-spectogram-noise-image-data/notebook\n    # \n    # Eunji Goo https://www.kaggle.com/code/quantum09/is-it-going-to-rain\n    # \n    # Marília Prata https://www.kaggle.com/code/mpwolke/birdclef-2024-western-ghats-species/notebook\n    \n    \n    end()","metadata":{"trusted":true,"_kg_hide-input":true,"_kg_hide-output":true,"jupyter":{"source_hidden":true},"execution":{"iopub.status.busy":"2025-04-07T13:36:19.011025Z","iopub.execute_input":"2025-04-07T13:36:19.011405Z","iopub.status.idle":"2025-04-07T13:36:19.142886Z","shell.execute_reply.started":"2025-04-07T13:36:19.011364Z","shell.execute_reply":"2025-04-07T13:36:19.141478Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## [Kumaran K](https://www.kaggle.com/kumarandatascientist)\n### 4. [LB 0.515 Sample submission](https://www.kaggle.com/code/kumarandatascientist/lb-0-515-sample-submission)\n### 15. [EfficientNet B0 Pytorch - this is an upgrade copy - Solutions.(**11**,**14**)](https://www.kaggle.com/code/kumarandatascientist/lb-0-801-efficientnet-b0-pytorch-pipeline)","metadata":{}},{"cell_type":"code","source":"solution = 'SOLUTION_4'\n\nif  solution in ENSEMBLE_SOLUTIONS:\n                                    \n    begin(solution)\n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 0')\n    \n    \n    # BirdCLEF+ 2025 Sample Submission\n    # \n    # This is a quick run through the submission process. Test data is hidden, so we can't access it before submission. In order to make a valid submission, here's what we'll do:\n    # \n    # 1. Make sure we predict for all 206 classes in the train data\n    # 2. Load a list of test soundscapes\n    # 3. Process each soundscape\n    #      - load audio\n    #      - split into 5-second chunks\n    #      - run model inference for each chunk\n    #      - save predictions\n    # 4. Make submission csv file\n    # 5. Submit\n    # \n    # Ok, so here we go.\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1')\n    \n    \n    import os\n    import librosa\n    import numpy as np\n    import pandas as pd\n    \n    # Set seed\n    np.random.seed(2)\n    \n    # Class labels from train audio\n    class_labels = sorted(os.listdir('/kaggle/input/birdclef-2025/train_audio/'))\n    \n    # List of test soundscapes (only visible during submission)\n    test_soundscape_path = '/kaggle/input/birdclef-2025/test_soundscapes/'\n    test_soundscapes = [os.path.join(test_soundscape_path, afile) for afile in sorted(os.listdir(test_soundscape_path)) if afile.endswith('.ogg')]\n    \n    # Open each soundscape and make predictions for 5-second segments\n    # Use pandas df with 'row_id' plus class labels as columns\n    predictions = pd.DataFrame(columns=['row_id'] + class_labels)\n    for soundscape in test_soundscapes:\n    \n        # Load audio\n        sig, rate = librosa.load(path=soundscape, sr=None)\n    \n        # Split into 5-second chunks\n        chunks = []\n        for i in range(0, len(sig), rate*5):\n            chunk = sig[i:i+rate*5]\n            chunks.append(chunk)\n            \n        # Make predictions for each chunk\n        for i, chunk in enumerate(chunks):\n            \n            # Get row id  (soundscape id + end time of 5s chunk)      \n            row_id = os.path.basename(soundscape).split('.')[0] + f'_{i * 5 + 5}'\n            \n            # Make prediction (let's use random scores for now)\n            # scores = model.predict...\n            scores = np.random.rand(len(class_labels))\n            \n            # Append to predictions as new row\n            new_row = pd.DataFrame([[row_id] + list(scores)], columns=['row_id'] + class_labels)\n            predictions = pd.concat([predictions, new_row], axis=0, ignore_index=True)\n            \n    # Save prediction as csv\n    predictions.to_csv('subm_4.csv', index=False)\n    predictions.head()\n            \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2')\n    \n    \n    # In order to make a submission, we need to:\n    # - disable internet for this notebook (Settings --> Turn off internet)\n    # - make sure the notebook runs without errors and a submission file gets created\n    # - submit to competition (panel on the right)\n    # - wait for the notebook to finish (this may take a while, remember there's a 90min time limit)\n    # \n    # If all goes well, we should see our submission scores \n    \n    end()","metadata":{"trusted":true,"_kg_hide-input":true,"_kg_hide-output":true,"jupyter":{"source_hidden":true},"execution":{"iopub.status.busy":"2025-04-07T13:36:19.175947Z","iopub.execute_input":"2025-04-07T13:36:19.176415Z","iopub.status.idle":"2025-04-07T13:36:19.186475Z","shell.execute_reply.started":"2025-04-07T13:36:19.176373Z","shell.execute_reply":"2025-04-07T13:36:19.185358Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"solution = 'SOLUTION_15'\n\nif  solution in ENSEMBLE_SOLUTIONS:\n                                        \n    begin(solution)\n\n    # what changed ?\n    # \n    #  HOP_LENGTH = 16\n    #  N_MELS     = 148\n    #  FMIN       = 20\n    #  FMAX       = 16000\n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 0')\n    \n    \n    # This notebook is exact copy of the notebook mentioned below but with TTA on Predictions\n    # \n    # - [Copied from Notebook](https://www.kaggle.com/code/kumarandatascientist/lb-0-784-efficientnet-b0-pytorch-inference)  \n    \n\n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1')\n    \n    \n    import os\n    import gc\n    import warnings\n    import logging\n    import time\n    import math\n    import cv2\n    from pathlib import Path\n    \n    import numpy as np\n    import pandas as pd\n    import librosa\n    import torch\n    import torch.nn as nn\n    import torch.nn.functional as F\n    import timm\n    from tqdm.auto import tqdm\n\n    # Suppress warnings and limit logging output\n    warnings.filterwarnings(\"ignore\")\n    logging.basicConfig(level=logging.ERROR)\n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2')\n    \n    \n    class CFG:\n     \n        test_soundscapes = '/kaggle/input/birdclef-2025/test_soundscapes'\n        submission_csv = '/kaggle/input/birdclef-2025/sample_submission.csv'\n        taxonomy_csv = '/kaggle/input/birdclef-2025/taxonomy.csv'\n        model_path = '/kaggle/input/birdclef-2025-efficientnet-b0'  \n        \n        # Audio parameters\n        FS = 32000  \n        WINDOW_SIZE = 5  \n        \n        # Mel spectrogram parameters\n        N_FFT = 1034\n        HOP_LENGTH =     64\n        N_MELS     =    136\n        FMIN       =     20\n        FMAX       = 16000\n        TARGET_SHAPE = (256, 256)\n        \n        model_name = 'efficientnet_b0'\n        in_channels = 1\n        device = 'cpu'  \n        \n        # Inference parameters\n        batch_size = 16\n        use_tta = False  \n        tta_count = 3   \n        threshold = 0.7\n        \n        use_specific_folds = False  # If False, use all found models\n        folds = [0, 1]  # Used only if use_specific_folds is True\n        \n        debug = False\n        debug_count = 3\n    \n    cfg = CFG()\n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 3')\n    \n    print(f\"Using device: {cfg.device}\")\n    print(f\"Loading taxonomy data...\")\n    taxonomy_df = pd.read_csv(cfg.taxonomy_csv)\n    species_ids = taxonomy_df['primary_label'].tolist()\n    num_classes = len(species_ids)\n    print(f\"Number of classes: {num_classes}\")\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 4')\n    \n    \n    class BirdCLEFModel(nn.Module):\n        def __init__(self, cfg, num_classes):\n            super().__init__()\n            self.cfg = cfg\n            \n            self.backbone = timm.create_model(\n                cfg.model_name,\n                pretrained=False,  \n                in_chans=cfg.in_channels,\n                drop_rate=0.0,    \n                drop_path_rate=0.0\n            )\n            \n            if 'efficientnet' in cfg.model_name:\n                backbone_out = self.backbone.classifier.in_features\n                self.backbone.classifier = nn.Identity()\n            elif 'resnet' in cfg.model_name:\n                backbone_out = self.backbone.fc.in_features\n                self.backbone.fc = nn.Identity()\n            else:\n                backbone_out = self.backbone.get_classifier().in_features\n                self.backbone.reset_classifier(0, '')\n            \n            self.pooling = nn.AdaptiveAvgPool2d(1)\n            self.feat_dim = backbone_out\n            self.classifier = nn.Linear(backbone_out, num_classes)\n            \n        def forward(self, x):\n            features = self.backbone(x)\n            \n            if isinstance(features, dict):\n                features = features['features']\n                \n            if len(features.shape) == 4:\n                features = self.pooling(features)\n                features = features.view(features.size(0), -1)\n            \n            logits = self.classifier(features)\n            return logits\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 5')\n    \n    \n    def audio2melspec(audio_data, cfg):\n        \"\"\"Convert audio data to mel spectrogram\"\"\"\n        if np.isnan(audio_data).any():\n            mean_signal = np.nanmean(audio_data)\n            audio_data = np.nan_to_num(audio_data, nan=mean_signal)\n    \n        mel_spec = librosa.feature.melspectrogram(\n            y=audio_data,\n            sr=cfg.FS,\n            n_fft=cfg.N_FFT,\n            hop_length=cfg.HOP_LENGTH,\n            n_mels=cfg.N_MELS,\n            fmin=cfg.FMIN,\n            fmax=cfg.FMAX,\n            power=2.0\n        )\n    \n        mel_spec_db = librosa.power_to_db(mel_spec, ref=np.max)\n        mel_spec_norm = (mel_spec_db - mel_spec_db.min()) / (mel_spec_db.max() - mel_spec_db.min() + 1e-8)\n        \n        return mel_spec_norm\n    \n    def process_audio_segment(audio_data, cfg):\n        \"\"\"Process audio segment to get mel spectrogram\"\"\"\n        if len(audio_data) < cfg.FS * cfg.WINDOW_SIZE:\n            audio_data = np.pad(audio_data, \n                              (0, cfg.FS * cfg.WINDOW_SIZE - len(audio_data)), \n                              mode='constant')\n        \n        mel_spec = audio2melspec(audio_data, cfg)\n        \n        # Resize if needed\n        if mel_spec.shape != cfg.TARGET_SHAPE:\n            mel_spec = cv2.resize(mel_spec, cfg.TARGET_SHAPE, interpolation=cv2.INTER_LINEAR)\n            \n        return mel_spec.astype(np.float32)\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 6')\n    \n    \n    def find_model_files(cfg):\n        \"\"\"\n        Find all .pth model files in the specified model directory\n        \"\"\"\n        model_files = []\n        \n        model_dir = Path(cfg.model_path)\n        \n        for path in model_dir.glob('**/*.pth'):\n            model_files.append(str(path))\n        \n        return model_files\n    \n    def load_models(cfg, num_classes):\n        \"\"\"\n        Load all found model files and prepare them for ensemble\n        \"\"\"\n        models = []\n        \n        model_files = find_model_files(cfg)\n        \n        if not model_files:\n            print(f\"Warning: No model files found under {cfg.model_path}!\")\n            return models\n        \n        print(f\"Found a total of {len(model_files)} model files.\")\n        \n        if cfg.use_specific_folds:\n            filtered_files = []\n            for fold in cfg.folds:\n                fold_files = [f for f in model_files if f\"fold{fold}\" in f]\n                filtered_files.extend(fold_files)\n            model_files = filtered_files\n            print(f\"Using {len(model_files)} model files for the specified folds ({cfg.folds}).\")\n        \n        for model_path in model_files:\n            try:\n                print(f\"Loading model: {model_path}\")\n                checkpoint = torch.load(model_path, map_location=torch.device(cfg.device))\n                \n                model = BirdCLEFModel(cfg, num_classes)\n                model.load_state_dict(checkpoint['model_state_dict'])\n                model = model.to(cfg.device)\n                model.eval()\n                \n                models.append(model)\n            except Exception as e:\n                print(f\"Error loading model {model_path}: {e}\")\n        \n        return models\n    \n    def predict_on_spectrogram(audio_path, models, cfg, species_ids):\n        \"\"\"Process a single audio file and predict species presence for each 5-second segment\"\"\"\n        predictions = []\n        row_ids = []\n        soundscape_id = Path(audio_path).stem\n        \n        try:\n            print(f\"Processing {soundscape_id}\")\n            audio_data, _ = librosa.load(audio_path, sr=cfg.FS)\n            \n            total_segments = int(len(audio_data) / (cfg.FS * cfg.WINDOW_SIZE))\n            \n            for segment_idx in range(total_segments):\n                start_sample = segment_idx * cfg.FS * cfg.WINDOW_SIZE\n                end_sample = start_sample + cfg.FS * cfg.WINDOW_SIZE\n                segment_audio = audio_data[start_sample:end_sample]\n                \n                end_time_sec = (segment_idx + 1) * cfg.WINDOW_SIZE\n                row_id = f\"{soundscape_id}_{end_time_sec}\"\n                row_ids.append(row_id)\n    \n                if cfg.use_tta:\n                    all_preds = []\n                    \n                    for tta_idx in range(cfg.tta_count):\n                        mel_spec = process_audio_segment(segment_audio, cfg)\n                        mel_spec = apply_tta(mel_spec, tta_idx)\n    \n                        mel_spec = torch.tensor(mel_spec, dtype=torch.float32).unsqueeze(0).unsqueeze(0)\n                        mel_spec = mel_spec.to(cfg.device)\n    \n                        if len(models) == 1:\n                            with torch.no_grad():\n                                outputs = models[0](mel_spec)\n                                probs = torch.sigmoid(outputs).cpu().numpy().squeeze()\n                                all_preds.append(probs)\n                        else:\n                            segment_preds = []\n                            for model in models:\n                                with torch.no_grad():\n                                    outputs = model(mel_spec)\n                                    probs = torch.sigmoid(outputs).cpu().numpy().squeeze()\n                                    segment_preds.append(probs)\n                            \n                            avg_preds = np.mean(segment_preds, axis=0)\n                            all_preds.append(avg_preds)\n    \n                    final_preds = np.mean(all_preds, axis=0)\n                else:\n                    mel_spec = process_audio_segment(segment_audio, cfg)\n                    \n                    mel_spec = torch.tensor(mel_spec, dtype=torch.float32).unsqueeze(0).unsqueeze(0)\n                    mel_spec = mel_spec.to(cfg.device)\n                    \n                    if len(models) == 1:\n                        with torch.no_grad():\n                            outputs = models[0](mel_spec)\n                            final_preds = torch.sigmoid(outputs).cpu().numpy().squeeze()\n                    else:\n                        segment_preds = []\n                        for model in models:\n                            with torch.no_grad():\n                                outputs = model(mel_spec)\n                                probs = torch.sigmoid(outputs).cpu().numpy().squeeze()\n                                segment_preds.append(probs)\n    \n                        final_preds = np.mean(segment_preds, axis=0)\n                        \n                predictions.append(final_preds)\n                \n        except Exception as e:\n            print(f\"Error processing {audio_path}: {e}\")\n        \n        return row_ids, predictions\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 7')\n    \n    \n    def apply_tta(spec, tta_idx):\n        \"\"\"Apply test-time augmentation\"\"\"\n        if tta_idx == 0:\n            # Original spectrogram\n            return spec\n        elif tta_idx == 1:\n            # Time shift (horizontal flip)\n            return np.flip(spec, axis=1)\n        elif tta_idx == 2:\n            # Frequency shift (vertical flip)\n            return np.flip(spec, axis=0)\n        else:\n            return spec\n    \n    def run_inference(cfg, models, species_ids):\n        \"\"\"Run inference on all test soundscapes\"\"\"\n        test_files = list(Path(cfg.test_soundscapes).glob('*.ogg'))\n        \n        if cfg.debug:\n            print(f\"Debug mode enabled, using only {cfg.debug_count} files\")\n            test_files = test_files[:cfg.debug_count]\n        \n        print(f\"Found {len(test_files)} test soundscapes\")\n    \n        all_row_ids = []\n        all_predictions = []\n    \n        for audio_path in tqdm(test_files):\n            row_ids, predictions = predict_on_spectrogram(str(audio_path), models, cfg, species_ids)\n            all_row_ids.extend(row_ids)\n            all_predictions.extend(predictions)\n        \n        return all_row_ids, all_predictions\n    \n    def create_submission(row_ids, predictions, species_ids, cfg):\n        \"\"\"Create submission dataframe\"\"\"\n        print(\"Creating submission dataframe...\")\n    \n        submission_dict = {'row_id': row_ids}\n        \n        for i, species in enumerate(species_ids):\n            submission_dict[species] = [pred[i] for pred in predictions]\n    \n        submission_df = pd.DataFrame(submission_dict)\n    \n        submission_df.set_index('row_id', inplace=True)\n    \n        sample_sub = pd.read_csv(cfg.submission_csv, index_col='row_id')\n    \n        missing_cols = set(sample_sub.columns) - set(submission_df.columns)\n        if missing_cols:\n            print(f\"Warning: Missing {len(missing_cols)} species columns in submission\")\n            for col in missing_cols:\n                submission_df[col] = 0.0\n    \n        submission_df = submission_df[sample_sub.columns]\n    \n        submission_df = submission_df.reset_index()\n        \n        return submission_df\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 8')\n    \n    \n    def main():\n        start_time = time.time()\n        print(\"Starting BirdCLEF-2025 inference...\")\n        print(f\"TTA enabled: {cfg.use_tta} (variations: {cfg.tta_count if cfg.use_tta else 0})\")\n    \n        models = load_models(cfg, num_classes)\n        \n        if not models:\n            print(\"No models found! Please check model paths.\")\n            return\n        \n        print(f\"Model usage: {'Single model' if len(models) == 1 else f'Ensemble of {len(models)} models'}\")\n    \n        row_ids, predictions = run_inference(cfg, models, species_ids)\n    \n        submission_df = create_submission(row_ids, predictions, species_ids, cfg)\n    \n        submission_path = 'submission.csv'\n        submission_df.to_csv(submission_path, index=False)\n        print(f\"Submission saved to {submission_path}\")\n        \n        end_time = time.time()\n        print(f\"Inference completed in {(end_time - start_time)/60:.2f} minutes\")\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 9')\n    \n    \n    if __name__ == \"__main__\":\n        main()\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 10')\n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 11')\n    \n    \n    sub = pd.read_csv('submission.csv')\n    cols = sub.columns[1:]\n    groups = sub['row_id'].str.rsplit('_', n=1).str[0]\n    groups = groups.values\n    for group in np.unique(groups):\n        sub_group = sub[group == groups]\n        predictions = sub_group[cols].values\n        new_predictions = predictions.copy()\n        for i in range(1, predictions.shape[0]-1):\n            new_predictions[i] = (predictions[i-1] * 0.2) + (predictions[i] * 0.6) + (predictions[i+1] * 0.2)\n        new_predictions[0] = (predictions[0] * 0.8) + (predictions[1] * 0.2)\n        new_predictions[-1] = (predictions[-1] * 0.8) + (predictions[-2] * 0.2)\n        sub_group[cols] = new_predictions\n        sub[group == groups] = sub_group\n    sub.to_csv(\"subm_15.csv\", index=False)\n    \n    end()","metadata":{"trusted":true,"_kg_hide-input":true,"_kg_hide-output":true,"execution":{"iopub.status.busy":"2025-04-07T13:36:19.188060Z","iopub.execute_input":"2025-04-07T13:36:19.188358Z","iopub.status.idle":"2025-04-07T13:36:36.331963Z","shell.execute_reply.started":"2025-04-07T13:36:19.188325Z","shell.execute_reply":"2025-04-07T13:36:36.330995Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## [Jocelyn Dumlao](https://www.kaggle.com/jocelyndumlao)\n### 5. &nbsp; [BirdCLEF 2025: MFCC Feature & ROC-AUC Analysis](https://www.kaggle.com/code/jocelyndumlao/birdclef-2025-mfcc-feature-roc-auc-analysis)\n### 5b. [BirdCLEF 2025: Inference w/SimpleCNN Spectrogram](https://www.kaggle.com/code/jocelyndumlao/birdclef-2025-inference-w-simplecnn-spectrogram)","metadata":{}},{"cell_type":"code","source":"solution = 'SOLUTION_5'\n\nif  solution in ENSEMBLE_SOLUTIONS:\n                                        \n    begin(solution)\n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 0')\n    \n    \n    # <div style=\"display: flex; justify-content: space-between; align-items: flex-start;\">\n    #     <div style=\"text-align: left;\">\n    #         <p style=\"color:#FFD700; font-size: 15px; font-weight: bold; margin-bottom: 1px; text-align: left;\">Published on  March 12, 2025</p>\n    #         <h4 style=\"color:#4B0082; font-weight: bold; text-align: left; margin-top: 6px;\">Author: Jocelyn C. Dumlao</h4>\n    #         <p style=\"font-size: 17px; line-height: 1.7; color: #333; text-align: center; margin-top: 20px;\"></p>\n    #         <a href=\"https://www.linkedin.com/in/jocelyn-dumlao-168921a8/\" target=\"_blank\" style=\"display: inline-block; background-color: #003f88; color: #fff; text-decoration: none; padding: 5px 10px; border-radius: 10px; margin: 15px;\">LinkedIn</a>\n    #         <a href=\"https://github.com/jcdumlao14\" target=\"_blank\" style=\"display: inline-block; background-color: transparent; color: #059c99; text-decoration: none; padding: 5px 10px; border-radius: 10px; margin: 15px; border: 2px solid #007bff;\">GitHub</a>\n    #         <a href=\"https://www.youtube.com/@CogniCraftedMinds\" target=\"_blank\" style=\"display: inline-block; background-color: #ff0054; color: #fff; text-decoration: none; padding: 5px 10px; border-radius: 10px; margin: 15px;\">YouTube</a>\n    #         <a href=\"https://www.kaggle.com/jocelyndumlao\" target=\"_blank\" style=\"display: inline-block; background-color: #3a86ff; color: #fff; text-decoration: none; padding: 5px 10px; border-radius: 10px; margin: 15px;\">Kaggle</a>\n    #     </div>\n    # </div>\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1')\n    \n    \n    # <center>\n    #   <img src=\"https://www.kaggle.com/competitions/91844/images/header\" alt=\"image\"width=\"40%\">\n    # </center>\n    # \n    # [Image Source](https://www.kaggle.com/competitions/birdclef-2025)\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2')\n    \n    \n    # <p style=\"padding:10px;background-color:#e6d498;margin:0;color:#102d02;font-family:newtimeroman;font-size:100%;text-align:center;border-radius:12px;font-weight:300;border: 6px solid #f2102e; box-shadow: 0 0 10px #f2102e;\">Introduction</p>\n    # \n    # *Biodiversity monitoring is essential for conservation, but traditional surveys are expensive and time-consuming. This competition leverages passive acoustic monitoring (PAM) and machine learning to identify species based on their sounds, enabling large-scale, cost-effective biodiversity assessments. Participants will develop models to classify under-studied species with limited labeled data, contributing to conservation efforts in Colombia’s Magdalena Valley. The region, a biodiversity hotspot, faces deforestation threats, making effective monitoring crucial. Fundación Biodiversa Colombia leads efforts to protect and restore these ecosystems, with El Silencio Natural Reserve serving as a key conservation site.*\n    # \n    # ***Overall Goal:** The code aims to build a simple bird sound classifier for the BirdCLEF competition. It involves data loading, exploration, feature extraction, model training, evaluation, and submission file creation.*\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 3')\n    \n    \n    # <p style=\"padding:10px;background-color:#e6d498;margin:0;color:#102d02;font-family:newtimeroman;font-size:100%;text-align:center;border-radius:12px;font-weight:300;border: 6px solid #f2102e; box-shadow: 0 0 10px #f2102e;\">Import Libraries</p>\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 4')\n    \n    \n    import os\n    import re\n    import numpy as np\n    import pandas as pd\n    import matplotlib.pyplot as plt\n    import seaborn as sns\n    import librosa\n    import librosa.display\n    import IPython.display as ipd\n    import soundfile as sf\n    from sklearn.metrics import roc_auc_score, roc_curve\n    from sklearn.preprocessing import MultiLabelBinarizer\n    from sklearn.model_selection import train_test_split\n    from sklearn.ensemble import RandomForestClassifier\n    \n    import warnings\n    warnings.filterwarnings(\"ignore\")\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 5')\n    \n    \n    # <p style=\"padding:10px;background-color:#e6d498;margin:0;color:#102d02;font-family:newtimeroman;font-size:100%;text-align:center;border-radius:12px;font-weight:300;border: 6px solid #f2102e; box-shadow: 0 0 10px #f2102e;\">Load Data</p>\n    # \n    # - Load Data: Read CSV files (metadata, taxonomy, submission).\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 6')\n    \n    \n    # Define paths\n    INPUT_PATH = '/kaggle/input/birdclef-2025/'\n    TRAIN_AUDIO_PATH = os.path.join(INPUT_PATH, 'train_audio')\n    TEST_SOUNDSCAPES_PATH = os.path.join(INPUT_PATH, 'test_soundscapes')\n    TRAIN_SOUNDSCAPES_PATH = os.path.join(INPUT_PATH, 'train_soundscapes')\n    \n    # Load data\n    taxonomy = pd.read_csv(os.path.join(INPUT_PATH, 'taxonomy.csv'))\n    train_meta = pd.read_csv(os.path.join(INPUT_PATH, 'train.csv'))\n    sample_submission = pd.read_csv(os.path.join(INPUT_PATH, 'sample_submission.csv'))\n    recording_locations = pd.read_csv(os.path.join(INPUT_PATH, 'recording_location.txt'))\n    \n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 7')\n    \n    \n    # <p style=\"padding:10px;background-color:#e6d498;margin:0;color:#102d02;font-family:newtimeroman;font-size:100%;text-align:center;border-radius:12px;font-weight:300;border: 6px solid #f2102e; box-shadow: 0 0 10px #f2102e;\">Data Preprocessing</p>\n    # \n    # - Cleans and prepares the training metadata. Specifically, it extracts secondary labels and constructs file paths for audio files.\n    # - The `preprocess_train_meta` function uses regular expressions (`re.findall`) to extract secondary labels from strings and `os.path.join` to create full file paths.\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 8')\n    \n    \n    # Data Preprocessing\n    def preprocess_train_meta(df):\n        \"\"\"Preprocesses the training metadata.\"\"\"\n        df['secondary_labels'] = df['secondary_labels'].apply(lambda x: re.findall(r\"'(\\w+)'\", x))\n        df['len_sec_labels'] = df['secondary_labels'].map(len)\n        df['file_path'] = df.apply(lambda row: os.path.join(TRAIN_AUDIO_PATH, row['filename']), axis=1)\n        return df\n    \n    train_meta = preprocess_train_meta(train_meta)\n    \n    print(\"Train Meta Shape:\", train_meta.shape)\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 9')\n    \n    \n    print(\"Train Meta Head:\")\n    train_meta.head().style.background_gradient(cmap='YlOrBr')\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 10')\n    \n    \n    print(\"Taxonomy Head:\")\n    taxonomy.head().style.background_gradient(cmap='plasma')\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 11')\n    \n    \n    print(\"Recording Locations Head:\")\n    recording_locations.head().style.background_gradient(cmap='plasma')\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 12')\n    \n    \n    # <p style=\"padding:10px;background-color:#e6d498;margin:0;color:#102d02;font-family:newtimeroman;font-size:100%;text-align:center;border-radius:12px;font-weight:300;border: 6px solid #f2102e; box-shadow: 0 0 10px #f2102e;\">Visualization</p>\n    # \n    # **Audio Visualization:**\n    # - Visualizes audio waveforms and spectrograms to get a sense of the data.\n    # - The `visualize_audio` function uses `librosa.load` to load audio, `librosa.display.waveshow` to plot waveforms, and `librosa.display.specshow` to plot spectrograms. It displays these plots using `matplotlib.pyplot`.\n    # \n    # **Soundscapes Visualization:**\n    # - Visualizes soundscape audio files similarly to individual training examples.\n    # - The `visualize_soundscape` function mirrors `visualize_audio` but operates on soundscape files. `get_available_soundscapes` is used to locate soundscape files.\n    # \n    # **Recording Location Map:**\n    # - Creates an interactive map showing the geographic locations of the audio recordings.\n    # - Uses the `folium` library to create a map centered on the average latitude and longitude of the recordings. It adds markers to the map for each recording location.\n    # \n    # **Taxonomy Visualization:**\n    # - Visualizes the distribution of different categories within the taxonomy (e.g., class names, common names).\n    # - The `plot_taxonomy_distribution` function uses `pandas.value_counts` to count the occurrences of each category and `seaborn.barplot` to create a bar plot of the top N categories.\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 13')\n    \n    \n    # Audio Visualization (Train Data Examples)\n    def visualize_audio(file_paths, titles):\n        \"\"\"Visualizes audio waveforms and spectrograms.\"\"\"\n        plt.figure(figsize=(15, 4 * len(file_paths)))\n        for i, file_path in enumerate(file_paths):\n            try:\n                y, sr = librosa.load(file_path)\n                plt.subplot(len(file_paths), 2, 2 * i + 1)\n                librosa.display.waveshow(y, sr=sr)\n                plt.title(f'Waveform: {titles[i]}')\n    \n                plt.subplot(len(file_paths), 2, 2 * i + 2)\n                D = librosa.stft(y)\n                S_db = librosa.amplitude_to_db(np.abs(D), ref=np.max)\n                librosa.display.specshow(S_db, sr=sr, x_axis='time', y_axis='log')\n                plt.title(f'Spectrogram: {titles[i]}')\n            except Exception as e:\n                print(f\"Error processing {file_path}: {e}\")\n        plt.tight_layout()\n        plt.show()\n    \n    # Select 4 audio examples\n    audio_examples = train_meta.sample(4)\n    file_paths = audio_examples['file_path'].tolist()\n    titles = audio_examples['primary_label'].tolist()\n    \n    print(\"\\nVisualizing Train Audio Examples:\")\n    visualize_audio(file_paths, titles)\n    \n    # Soundscapes Visualization\n    def visualize_soundscape(file_paths, titles):\n        \"\"\"Visualizes soundscape audio waveforms and spectrograms.\"\"\"\n        plt.figure(figsize=(15, 4 * len(file_paths)))\n        for i, file_path in enumerate(file_paths):\n            try:\n                y, sr = librosa.load(file_path)\n                plt.subplot(len(file_paths), 2, 2 * i + 1)\n                librosa.display.waveshow(y, sr=sr)\n                plt.title(f'Soundscape Waveform: {titles[i]}')\n    \n                plt.subplot(len(file_paths), 2, 2 * i + 2)\n                D = librosa.stft(y)\n                S_db = librosa.amplitude_to_db(np.abs(D), ref=np.max)\n                librosa.display.specshow(S_db, sr=sr, x_axis='time', y_axis='log')\n                plt.title(f'Soundscape Spectrogram: {titles[i]}')\n            except Exception as e:\n                print(f\"Error processing {file_path}: {e}\")\n        plt.tight_layout()\n        plt.show()\n    \n    # Select 4 diverse soundscape examples\n    def get_available_soundscapes(soundscapes_path):\n        \"\"\"Returns a list of available soundscape files.\"\"\"\n        try:\n            soundscape_files = [f for f in os.listdir(soundscapes_path) if f.endswith('.ogg')]\n            soundscape_files = [os.path.join(soundscapes_path, f) for f in soundscape_files]\n            return soundscape_files\n        except FileNotFoundError:\n            print(f\"Error: The directory {soundscapes_path} was not found.\")\n            return []\n        except Exception as e:\n            print(f\"Error listing soundscape files: {e}\")\n            return []\n    \n    available_soundscapes = get_available_soundscapes(TRAIN_SOUNDSCAPES_PATH)\n    \n    if len(available_soundscapes) >= 4:\n        soundscape_files = available_soundscapes[:4]  # Select the first 4\n        soundscape_titles = [f'Soundscape {i+1}' for i in range(4)]\n    \n        print(\"\\nVisualizing Soundscapes:\")\n        visualize_soundscape(soundscape_files, soundscape_titles)\n    else:\n        print(\"\\nNot enough soundscapes available to visualize 4 examples.\")\n    \n    # Recording Location Map\n    import folium\n    \n    def create_location_map(train_meta, n_samples=200):\n        \"\"\"Creates an interactive map of recording locations using Folium.\"\"\"\n        location_df = train_meta[['latitude', 'longitude']].dropna().sample(n_samples)\n        latitudes = location_df['latitude'].values.tolist()\n        longitudes = location_df['longitude'].values.tolist()\n    \n        # Calculate the average location to center the map\n        avg_lat = sum(latitudes) / len(latitudes)\n        avg_lon = sum(longitudes) / len(longitudes)\n    \n        # Create the map\n        m = folium.Map(location=[avg_lat, avg_lon], zoom_start=6)\n    \n        # Add markers for each location\n        for lat, lon in zip(latitudes, longitudes):\n            folium.CircleMarker(location=[lat, lon], radius=5, color='blue', fill=True, fill_color='blue').add_to(m)\n    \n        return m\n    \n    print(\"\\nCreating Recording Location Map:\")\n    map_obj = create_location_map(train_meta)\n    map_obj  # Display the map\n    \n    # Taxonomy Visualization\n    def plot_taxonomy_distribution(taxonomy, column_name, top_n=10):\n        \"\"\"Plots the distribution of taxonomy categories.\"\"\"\n        plt.figure(figsize=(12, 6))\n        counts = taxonomy[column_name].value_counts().nlargest(top_n)\n        sns.barplot(x=counts.index, y=counts.values, palette='viridis')\n        plt.title(f'Top {top_n} {column_name} Distribution')\n        plt.xlabel(column_name)\n        plt.ylabel('Frequency')\n        plt.xticks(rotation=45, ha='right')\n        plt.tight_layout()\n        plt.show()\n    \n    print(\"\\nVisualizing Taxonomy Distributions:\")\n    plot_taxonomy_distribution(taxonomy, 'class_name')\n    plot_taxonomy_distribution(taxonomy, 'common_name')\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 14')\n    \n    \n    # <p style=\"padding:10px;background-color:#e6d498;margin:0;color:#102d02;font-family:newtimeroman;font-size:100%;text-align:center;border-radius:12px;font-weight:300;border: 6px solid #f2102e; box-shadow: 0 0 10px #f2102e;\">Feature Extraction</p>\n    # \n    # - Extracts Mel-Frequency Cepstral Coefficients (MFCCs) from audio files, \n    #   which are a common audio feature used in machine learning.\n    # \n    # - The `extract_mfcc` function uses `librosa.load` to load audio, `librosa.feature.mfcc` \n    #   to compute MFCCs, and `numpy.mean` to average the MFCCs over time.\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 15')\n    \n    \n    # Feature Extraction (Simple MFCC)\n    def extract_mfcc(file_path, sr=22050, n_mfcc=20):\n        \"\"\"Extracts MFCC features from an audio file.\"\"\"\n        try:\n            y, sr = librosa.load(file_path, sr=sr)\n            mfccs = librosa.feature.mfcc(y=y, sr=sr, n_mfcc=n_mfcc)\n            mfccs_processed = np.mean(mfccs.T, axis=0)  # Average across time\n        except Exception as e:\n            # Comment out this line to suppress error messages\n            # print(f\"Error processing {file_path}: {e}\")\n            return None\n        return mfccs_processed\n    \n    # Example MFCC extraction\n    example_file = train_meta['file_path'].iloc[0]\n    mfccs = extract_mfcc(example_file)\n    print(\"\\nMFCC Features Example:\", mfccs)\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 16')\n    \n    \n    # <p style=\"padding:10px;background-color:#e6d498;margin:0;color:#102d02;font-family:newtimeroman;font-size:100%;text-align:center;border-radius:12px;font-weight:300;border: 6px solid #f2102e; box-shadow: 0 0 10px #f2102e;\">Model Training</p>\n    # \n    # - Trains a Random Forest Classifier to predict bird species based on MFCC features.\n    #   - The `train_model` function extracts MFCCs for a subset of the training data.\n    #   - Splits the data into training and testing sets using `train_test_split`.\n    #   - Creates a `RandomForestClassifier` and trains it using model.fit.\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 17')\n    \n    \n    # Model Training (Simple RandomForest)\n    def train_model(train_meta, n_samples=500, n_mfcc=20):\n        \"\"\"Trains a RandomForestClassifier model.\"\"\"\n        # Sample a subset of data for faster training\n        train_subset = train_meta.sample(n_samples, random_state=42)\n    \n        # Extract MFCC features\n        features = []\n        labels = []\n        for index, row in train_subset.iterrows():\n            mfccs = extract_mfcc(row['file_path'], n_mfcc=n_mfcc)\n            if mfccs is not None:\n                features.append(mfccs)\n                labels.append(row['primary_label'])\n    \n        X = np.array(features)\n        y = np.array(labels)\n    \n        # Train/Test split\n        X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)\n    \n        # Train a simple RandomForestClassifier\n        model = RandomForestClassifier(n_estimators=100, random_state=42)  # Adjust hyperparameters\n        model.fit(X_train, y_train)\n    \n        return model, X_test, y_test, y_train\n    \n    model, X_test, y_test, y_train = train_model(train_meta)\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 18')\n    \n    \n    # <p style=\"padding:10px;background-color:#e6d498;margin:0;color:#102d02;font-family:newtimeroman;font-size:100%;text-align:center;border-radius:12px;font-weight:300;border: 6px solid #f2102e; box-shadow: 0 0 10px #f2102e;\">Macro-averaged ROC-AUC Evaluation</p>\n    # \n    # - Evaluates the model using macro-averaged ROC-AUC, which is suitable for multi-class classification problems.\n    #    - The `evaluate_model` function predicts probabilities for each class using `model.predict_proba`.\n    #    - Binarizes the true labels using `MultiLabelBinarizer` to convert them into a one-vs-all format.\n    #    - Calculates the ROC-AUC score for each class using `roc_auc_score` and plots the ROC curves.\n    #    - Computes the macro-averaged ROC-AUC score by averaging the ROC-AUC scores for all classes, \n    #      handling potential `ValueError` and `IndexError` exceptions.\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 19')\n    \n    \n    # Macro-averaged ROC-AUC Evaluation\n    def evaluate_model(model, X_test, y_test, labels, y_train):\n        \"\"\"Evaluates the model using macro-averaged ROC-AUC.\"\"\"\n    \n        # Get predictions\n        y_pred_proba = model.predict_proba(X_test)\n    \n        # Binarize the true labels (fitting on both train and test labels to ensure all classes are present)\n        mlb = MultiLabelBinarizer(classes=labels)\n        mlb.fit([[label] for label in np.concatenate([y_train, y_test])])\n        y_test_bin = mlb.transform([[label] for label in y_test])\n    \n        # Calculate ROC AUC for each class\n        roc_auc_scores = []\n        fprs, tprs, thresholds = [], [], []  # Store ROC curve data\n    \n        for i, label in enumerate(labels):\n            try:\n                # Get the index of the label in the MultiLabelBinarizer's classes_\n                label_index = list(mlb.classes_).index(label)\n    \n                # Check if there's only one class present in the true labels\n                if len(np.unique(y_test_bin[:, label_index])) <= 1:\n                    raise ValueError(f\"Only one class present in y_true for label {label}. ROC AUC score is not defined in that case.\")\n    \n                # Calculate ROC AUC\n                roc_auc = roc_auc_score(y_test_bin[:, label_index], y_pred_proba[:, list(mlb.classes_).index(label)])\n                roc_auc_scores.append(roc_auc)\n    \n                # Calculate ROC curve\n                fpr, tpr, threshold = roc_curve(y_test_bin[:, label_index], y_pred_proba[:, list(mlb.classes_).index(label)])\n                fprs.append(fpr)\n                tprs.append(tpr)\n                thresholds.append(threshold)\n    \n            except ValueError as e:\n                #Remove this line if you want to see the error messages\n                #print(f\"ValueError for label {label}: {e}\")  # Added error message\n                roc_auc_scores.append(np.nan)\n                fprs.append(None)\n                tprs.append(None)\n                thresholds.append(None)\n    \n            except IndexError as e:\n                #Remove this line if you want to see the error messages\n                #print(f\"IndexError for label {label}: {e}\")\n                roc_auc_scores.append(np.nan)\n                fprs.append(None)\n                tprs.append(None)\n                thresholds.append(None)\n    \n        # Calculate the macro-averaged ROC AUC, ignoring NaN values\n        macro_roc_auc = np.nanmean(roc_auc_scores)\n        print(f\"Macro-Averaged ROC AUC: {macro_roc_auc:.4f}\")\n    \n        # Plot ROC curves\n        plt.figure(figsize=(8, 6))\n        for i, label in enumerate(labels):\n            if fprs[i] is not None and tprs[i] is not None:\n                plt.plot(fprs[i], tprs[i], label=f'{label} (AUC = {roc_auc_scores[i]:.2f})')\n        plt.plot([0, 1], [0, 1], 'k--', label='Random')\n        plt.xlabel('False Positive Rate')\n        plt.ylabel('True Positive Rate')\n        plt.title('ROC Curves for Each Class')\n        plt.legend(loc='lower right')\n        plt.show()\n    \n        return macro_roc_auc\n    \n    # Prepare labels for MultiLabelBinarizer\n    labels = train_meta['primary_label'].unique()\n    \n    # Evaluate the model\n    macro_roc_auc = evaluate_model(model, X_test, y_test, labels, y_train)\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 20')\n    \n    \n    # <p style=\"padding:10px;background-color:#e6d498;margin:0;color:#102d02;font-family:newtimeroman;font-size:100%;text-align:center;border-radius:12px;font-weight:300;border: 6px solid #f2102e; box-shadow: 0 0 10px #f2102e;\">Prediction and Submission</p>\n    # \n    # - Predicts bird presence in the test soundscapes and creates a submission file in the required format.\n    # - The `predict_and_submit` function iterates through the sample submission file.\n    # - For each soundscape, it extracts MFCC features.\n    # - Uses the trained model to predict the probabilities of each bird species being present.\n    # - Creates a Pandas DataFrame in the correct format for submission and saves it to a CSV file. It also handles `KeyError` exceptions that might arise if certain `row_id` values are missing.\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 21')\n    \n    \n    # Prediction and Submission\n    def predict_and_submit(model, sample_submission, train_meta, labels, n_mfcc=20):\n        \"\"\"Predicts bird presence and creates a submission file.\"\"\"\n        predictions = {}  # Store predictions\n    \n        for index, row in sample_submission.iterrows():\n            try:\n                audio_path = os.path.join(TEST_SOUNDSCAPES_PATH, row['file_id'] + '.ogg')\n                mfccs = extract_mfcc(audio_path, n_mfcc=n_mfcc)\n    \n                if mfccs is None:\n                    # Handle missing or corrupted audio files\n                    prediction_values = [0] * len(labels)\n                else:\n                    # Get the predicted probabilities for each class\n                    prediction_values = model.predict_proba(mfccs.reshape(1, -1))[0]  # Predict probabilities\n    \n                # Create a dictionary mapping labels to prediction probabilities\n                label_predictions = dict(zip(labels, prediction_values))\n                predictions[row['row_id']] = label_predictions\n    \n            except KeyError as e:\n                print(f\"KeyError in predict_and_submit: {e}. Skipping row {row['row_id']}\")\n                # Create a dictionary with default probabilities for all labels\n                label_predictions = {label: 0.0 for label in labels}\n                predictions[row['row_id']] = label_predictions\n    \n        # Create submission DataFrame\n        submission_data = []\n        for row_id, label_predictions in predictions.items():\n            row_data = {'row_id': row_id}\n            row_data.update(label_predictions)\n            submission_data.append(row_data)\n    \n        submission_df = pd.DataFrame(submission_data)\n        submission_df = submission_df.set_index('row_id')\n    \n        # Ensure that the order of columns in the submission matches the sample_submission\n        cols = sample_submission.columns[1:]\n        submission_df = submission_df[cols]\n    \n        submission_df.to_csv('subm_5.csv')\n        print(\"Submission file created successfully!\")\n        return submission_df\n    \n    # Predict and submit\n    submission_df = predict_and_submit(model, sample_submission, train_meta, labels)\n    \n    print(\"\\nSubmission File Head:\")\n    print(submission_df.head())\n    \n    # Print the head of the created submission file\n    submission = pd.read_csv('subm_5.csv')\n    print(\"Submission File Head:\")\n    print(submission.head())\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 22')\n\n\n    Geographic_()\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 23')\n    \n    \n    end()","metadata":{"trusted":true,"_kg_hide-input":true,"_kg_hide-output":true,"jupyter":{"source_hidden":true},"execution":{"iopub.status.busy":"2025-04-07T13:36:36.334020Z","iopub.execute_input":"2025-04-07T13:36:36.334300Z","iopub.status.idle":"2025-04-07T13:36:36.376284Z","shell.execute_reply.started":"2025-04-07T13:36:36.334275Z","shell.execute_reply":"2025-04-07T13:36:36.375162Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"solution = 'SOLUTION_5b'\n\nif  solution in ENSEMBLE_SOLUTIONS:\n                                            \n    begin(solution)\n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 0')\n    \n    \n    # <div style=\"display: flex; justify-content: space-between; align-items: flex-start;\">\n    #     <div style=\"text-align: left;\">\n    #         <p style=\"color:#FFD700; font-size: 15px; font-weight: bold; margin-bottom: 1px; text-align: left;\">Published on  March 17, 2025</p>\n    #         <h4 style=\"color:#4B0082; font-weight: bold; text-align: left; margin-top: 6px;\">Author: Jocelyn C. Dumlao</h4>\n    #         <p style=\"font-size: 17px; line-height: 1.7; color: #333; text-align: center; margin-top: 20px;\"></p>\n    #         <a href=\"https://www.linkedin.com/in/jocelyn-dumlao-168921a8/\" target=\"_blank\" style=\"display: inline-block; background-color: #003f88; color: #fff; text-decoration: none; padding: 5px 10px; border-radius: 10px; margin: 15px;\">LinkedIn</a>\n    #         <a href=\"https://github.com/jcdumlao14\" target=\"_blank\" style=\"display: inline-block; background-color: transparent; color: #059c99; text-decoration: none; padding: 5px 10px; border-radius: 10px; margin: 15px; border: 2px solid #007bff;\">GitHub</a>\n    #         <a href=\"https://www.youtube.com/@CogniCraftedMinds\" target=\"_blank\" style=\"display: inline-block; background-color: #ff0054; color: #fff; text-decoration: none; padding: 5px 10px; border-radius: 10px; margin: 15px;\">YouTube</a>\n    #         <a href=\"https://www.kaggle.com/jocelyndumlao\" target=\"_blank\" style=\"display: inline-block; background-color: #3a86ff; color: #fff; text-decoration: none; padding: 5px 10px; border-radius: 10px; margin: 15px;\">Kaggle</a>\n    #     </div>\n    # </div>\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1')\n    \n    \n    # <p style=\"padding:10px;background-color:#ffdf5b;font-family:newtimeroman;font-size:100%;\n    #    text-align:center;border-radius:12px;font-weight:300;border: 6px outset #f2102e;\">\n    #    BirdCLEF 2025: Inference with SimpleCNN Spectrogram Model</p>\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2')\n    \n    \n    # <p style=\"padding:10px;background-color:#ffdf5b;font-family:newtimeroman;font-size:100%;\n    #    text-align:center;border-radius:12px;font-weight:300;border: 6px outset #f2102e;\">\n    #    Setup and Imports</p>\n    \n    # - This section prepares the environment by loading necessary tools and defining key data locations.\n    # - It starts by importing the required libraries for deep learning, audio processing, \n    #   and data manipulation. Then, it sets up the paths to the data files used in the project. \n    #   Crucially, it loads the sample submission to get the list of bird species being predicted \n    #   and maps them to numerical indices. Finally, a debug mode is configured to allow for easier \n    #   testing with a smaller amount of data.\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 3')\n    \n    \n    import torch\n    import torch.nn as nn\n    import torch.nn.functional as F\n    \n    import os\n    import librosa\n    import numpy as np\n    import pandas as pd\n    \n    import gc\n    import dataclasses\n    from concurrent.futures import ThreadPoolExecutor\n    from typing import Optional, Callable, Tuple, List\n    import traceback  # Import traceback module\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 4')\n    \n    \n    # Define file paths \n    test_data = \"/kaggle/input/birdclef-2025/test_soundscapes\"\n    submission = \"/kaggle/input/birdclef-2025/sample_submission.csv\"\n    train_csv = \"/kaggle/input/birdclef-2025/train.csv\"\n    taxonomy_csv = \"/kaggle/input/birdclef-2025/taxonomy.csv\"\n    \n    transform: Optional[Callable] = None  # Type hint for transform\n    audio_transform: Optional[Callable] = None # Type hint for audio_transform\n    \n    @dataclasses.dataclass\n    class AudioParam:\n        SR: int = 32_000  # Sample rate\n        NFFT: int = 2048  # Number of FFT points\n        NMEL: int = 128   # Number of Mel bands\n        FMAX: int = 16_000 # Maximum frequency\n        FMIN: int = 20   # Minimum frequency\n        HOP_LENGTH: int = NFFT // 4  # Hop length\n    \n    audio_param = AudioParam()\n    \n    # Load submission CSV to get class names\n    try:\n        sub_csv = pd.read_csv(submission)\n        idx2cls = sub_csv.columns.drop(\"row_id\").tolist()  # List of bird species (class names)\n        cls2idx = {c: i for i, c in enumerate(idx2cls)} # Class name to index mapping\n    except FileNotFoundError as e:\n        print(f\"Error: sample_submission.csv not found! {e}\")\n        idx2cls = [] # Provide a default for testing, but the code will likely fail\n        cls2idx = {}\n    \n    \n    DEBUG = True # Enable Debugging\n    file_names = [os.path.join(test_data, fp) for fp in os.listdir(test_data) if fp.endswith(\".ogg\")]\n    \n    # Use a single file for debugging.  This makes the matrix dimension calculations easier.\n    if len(file_names) == 0:\n        file_names = [\n            \"/kaggle/input/birdclef-2025/train_soundscapes/H02_20230420_074000.ogg\",\n        ]\n        DEBUG = True\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 5')\n    \n    \n    # <p style=\"padding:10px;background-color:#ffdf5b;font-family:newtimeroman;font-size:100%;text-align:center;border-radius:12px;font-weight:300;border: 6px outset #f2102e;\">SimpleCNN Model Definition</p>\n    # - The SimpleCNN class defines a basic convolutional neural network for processing audio spectrograms. It consists of two convolutional layers with ReLU activation and max pooling, followed by a flattening layer and a dynamically sized linear (fully connected) layer. The model learns to extract features from the spectrogram and predict the presence of different bird species. The size of the final linear layer is dynamically adjusted based on the input size, making it flexible for different spectrogram dimensions.\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 6')\n    \n    \n    #  a simpler, randomly initialized CNN model\n    class SimpleCNN(nn.Module):\n        def __init__(self, num_classes: int = 1):\n            super().__init__()\n            self.conv1 = nn.Conv2d(1, 16, kernel_size=3, padding=1)\n            self.relu1 = nn.ReLU()\n            self.pool1 = nn.MaxPool2d(kernel_size=2, stride=2)\n            self.conv2 = nn.Conv2d(16, 32, kernel_size=3, padding=1)\n            self.relu2 = nn.ReLU()\n            self.pool2 = nn.MaxPool2d(kernel_size=2, stride=2)\n            self.flatten = nn.Flatten()\n    \n            # Calculate the input size to the linear layer dynamically\n            self._to_linear = None  # Placeholder, will be calculated during the first forward pass\n            self.fc1 = nn.Linear(1, num_classes)  # Placeholder Linear layer\n    \n        def forward(self, x: torch.Tensor) -> torch.Tensor:\n            try:\n                x = self.pool1(self.relu1(self.conv1(x)))\n                x = self.pool2(self.relu2(self.conv2(x)))\n                x = self.flatten(x)\n    \n                # Dynamically determine the input size of the linear layer\n                if self._to_linear is None:\n                    self._to_linear = x.shape[1]\n                    if self._to_linear == 0:\n                       print(\"Error: self._to_linear is zero!\")\n                       #Handle this better - e.g., skip or set a min size\n                       return torch.zeros((1, len(idx2cls)))  # or a zero tensor of the right size\n                    self.fc1 = nn.Linear(self._to_linear, len(idx2cls))  # Update the linear layer\n                x = self.fc1(x)\n                return x\n            except Exception as e:\n                print(f\"Error in SimpleCNN.forward: {e}\")\n                return torch.zeros((1, len(idx2cls)))\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 7')\n    \n    \n    # <p style=\"padding:10px;background-color:#ffdf5b;font-family:newtimeroman;font-size:100%;\n    #    text-align:center;border-radius:12px;font-weight:300;border: 6px outset #f2102e;\">\n    #    Audio Processing Pipeline</p>\n        \n    # - This section defines how raw audio is transformed into a format suitable for the CNN.\n    # - It takes a raw audio waveform as input and converts it into a Mel spectrogram.\n    #   This spectrogram representation highlights the frequencies present in the audio \n    #   in a way that is perceptually relevant. The spectrogram is then normalized to a \n    #   specific range, and a \"channel\" dimension is added to meet the input requirements \n    #   of the neural network.\n\n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 8')\n    \n    \n    # Instantiate the SimpleCNN model.\n    model = SimpleCNN(num_classes=len(idx2cls))\n    model.eval() # Set the model to evaluation mode.\n    \n    def pipeline(x: np.ndarray) -> np.ndarray:\n        \"\"\"\n        Converts audio data to a mel spectrogram and then to a dB scale.\n        \"\"\"\n        try:\n            mels = librosa.feature.melspectrogram(\n                y=x,\n                sr=audio_param.SR,\n                n_fft=audio_param.NFFT,\n                n_mels=audio_param.NMEL,\n                fmax=audio_param.FMAX,\n                fmin=audio_param.FMIN,\n                hop_length=audio_param.HOP_LENGTH,\n            )\n            db_map = librosa.power_to_db(mels, ref=np.max)\n            db_map = (db_map + 80) / (80 + 1e-6)  # Normalize to [0, 1] - Added small constant\n            if np.isnan(db_map).any():\n                print(\"Warning: NaN values detected in db_map!\")\n                db_map = np.nan_to_num(db_map) #Replace with 0\n    \n            return db_map[None, :, :]  # Add a channel dimension (1, height, width)\n        except Exception as e:\n            print(f\"Error in pipeline: {e}\")\n            return np.zeros((1, audio_param.NMEL, 1)) # return a zero array\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 9')\n    \n    \n    # <p style=\"padding:10px;background-color:#ffdf5b;font-family:newtimeroman;\n    #    font-size:100%;text-align:center;border-radius:12px;font-weight:300;\n    #    border: 6px outset #f2102e;\">Prediction Function</p>\n    \n    # - This section defines the core prediction process for a single audio file.\n    # - It loads an audio file, divides it into 5-second segments, and \n    #   then processes each segment individually. It applies optional audio and \n    #   image augmentations to improve robustness. The processed segment (the Mel spectrogram) \n    #   is then passed to the neural network to generate a prediction. \n    #   The function also creates unique identifiers for each segment and stores the prediction \n    #   results along with these identifiers.\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 10')\n    \n    \n    @torch.no_grad()\n    def predict(fp: str) -> Tuple[np.ndarray, List[str]]:\n        \"\"\"\n        Predicts bird calls in a given audio file.\n    \n        Args:\n            fp (str): File path of the audio file.\n    \n        Returns:\n            Tuple[np.ndarray, List[str]]: Tuple containing the model output and the list of row IDs.\n        \"\"\"\n        try:\n            x, _ = librosa.load(fp, sr=audio_param.SR)  # Load the audio file.\n    \n            if x.size == 0:\n                print(f\"Warning: Audio file {fp} is empty!\")\n                return np.array([]), [] #return empty arrays\n        except Exception as e:\n            print(f\"Error loading file {fp}: {e}\")\n            return np.array([]), []\n    \n        # Number of 5-second segments\n        num_segments = int(np.floor(len(x) / audio_param.SR / 5))\n        all_outs = []\n        all_row_ids = []\n        for i in range(num_segments):\n            start = i * audio_param.SR * 5\n            end = (i + 1) * audio_param.SR * 5\n            segment = x[start:end]\n    \n    \n            if audio_transform is not None:\n                try:\n                    segment = audio_transform(sample=segment, sample_rate=audio_param.SR) #Apply audio transform\n                except Exception as e:\n                    print(f\"Audio Transform Failed {e}\")\n    \n            try:\n                segment = pipeline(segment)  #Convert waveform to mel spectrogram.\n            except Exception as e:\n                print(f\"Pipeline failed {e}\")\n                continue\n    \n            if transform is not None:\n                try:\n                    segment = transform(image=segment)[\"image\"] #Apply image transform.\n                except Exception as e:\n                    print(f\"Transform failed {e}\")\n                    continue\n    \n            try:\n                segment = torch.from_numpy(segment).float().unsqueeze(0)  # Convert to tensor and add batch dimension.\n                out = model(segment).sigmoid().detach().cpu().numpy() # Get the model output.\n                all_outs.append(out[0])\n    \n                fp_name = os.path.basename(fp).split(\".\")[0] #Extract the base filename.\n                row_id = f\"{fp_name}_{(i + 1) * 5}\" #Create row IDs.  Correct the slice name\n                all_row_ids.append(row_id)\n            except Exception as e:\n                print(f\"Error during processing of segment {i} in {fp}: {e}  {traceback.format_exc()}\") #Print trace\n    \n        return np.array(all_outs), all_row_ids # return all values\n    \n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 11')\n    \n    \n    # <p style=\"padding:10px;background-color:#ffdf5b;font-family:newtimeroman;font-size:100%;text-align:center;border-radius:12px;font-weight:300;border: 6px outset #f2102e;\">Prediction Loop and Submission File</p>\n    # - This section orchestrates the prediction process for multiple audio files and creates the final submission file.\n    # - It initializes data structures to store the prediction results. It then uses parallel processing to speed up the prediction process across multiple audio files. The prediction results and identifiers are collected, reshaped, and combined into a Pandas DataFrame. Finally, this DataFrame is saved to a CSV file in the format required for submission. A small sample of the DataFrame is displayed for verification.\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 12')\n    \n    \n    row_id = []\n    matrix = []\n    \n    #Using a ThreadPoolExecutor to parallelize the predictions\n    with ThreadPoolExecutor(max_workers=4) as executor:\n        for fp_idx, (fp) in enumerate(file_names): #Enumerate so you know the file index\n            try:\n                out, rid = predict(fp)\n                if len(rid) > 0:  # Only extend if there are valid results\n                    row_id.extend(rid)  # Changed append to extend to unpack the list of strings\n                    matrix.extend(out)  # Append the output, which should have shape (num_classes,)\n                else:\n                    print(f\"Warning: No predictions generated for file: {fp}\")\n            except Exception as e:\n                print(f\"Failed to run predict for file {fp} {e}\") #Major problem.\n            gc.collect() #Collect after each file\n            print(f\"Finished {fp_idx+1}/{len(file_names)}\") #Track progress\n    \n    try:\n        matrix = np.array(matrix).reshape(-1, len(idx2cls))  # Reshape to (num_segments, num_classes)\n        row_id = np.array(row_id).reshape(-1, 1)  # Ensure row_id is a 2D array\n        matrix = np.hstack([row_id, matrix])  # Now both arrays have the same dimensions\n    \n        # Create a Pandas DataFrame from the results.\n        sub = pd.DataFrame(matrix, columns=[\"row_id\", *idx2cls])\n        sub.to_csv('subm_5b.csv', index=False)\n    \n        print(sub.head())\n    except Exception as e:\n        print(f\"Error creating submission file {e}\") #Most likely problem.\n    \n    print(\"Finished!\") #If you see this, then great!\n    gc.collect()\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 13')\n    \n    \n    end()","metadata":{"trusted":true,"_kg_hide-input":true,"_kg_hide-output":true,"jupyter":{"source_hidden":true},"execution":{"iopub.status.busy":"2025-04-07T13:36:36.378071Z","iopub.execute_input":"2025-04-07T13:36:36.378467Z","iopub.status.idle":"2025-04-07T13:36:36.408641Z","shell.execute_reply.started":"2025-04-07T13:36:36.378429Z","shell.execute_reply":"2025-04-07T13:36:36.407561Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## [MYSO](https://www.kaggle.com/myso1987)\n### 6. &nbsp; [BirdCLEF.2025-3 Submit-baseline 5s](https://www.kaggle.com/code/myso1987/birdclef2025-3-submit-baseline-5s)\n### 6.2 [BirdCLEF2025-2 Train-baseline 5s](https://www.kaggle.com/code/myso1987/birdclef2025-2-train-baseline-5s)\n### b.3 [BirdCLEF2025-1 Crop audio 5s](https://www.kaggle.com/code/myso1987/birdclef2025-1-crop-audio-5s)","metadata":{}},{"cell_type":"code","source":"solution = 'SOLUTION_6'\n\nif  solution in ENSEMBLE_SOLUTIONS:\n                                            \n    begin(solution)\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 0')\n    \n    \n    # * Training Notebook [here.](https://www.kaggle.com/code/myso1987/birdclef2025-2-train-baseline-5s)\n    # * Dataset  Creation [here](https://www.kaggle.com/code/myso1987/birdclef2025-1-crop-audio-5s)\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1')\n    \n    \n    import os\n    import gc\n    import time\n    import pandas as pd\n    import torch\n    import torch.nn as nn\n    from torchvision import models\n    import torchaudio\n    import torchaudio.transforms as AT\n    from contextlib import contextmanager\n    import concurrent.futures\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2')\n    \n    \n    test_audio_dir = '../input/birdclef-2025/test_soundscapes/'\n    file_list = [f for f in sorted(os.listdir(test_audio_dir))]\n    file_list = [file.split('.')[0] for file in file_list if file.endswith('.ogg')]\n    \n    debug = False\n    \n    if len(file_list) == 0:\n        debug = True\n        debug_st_num = 5\n        debug_num = 8\n        test_audio_dir = '../input/birdclef-2025/train_soundscapes/'\n        file_list = [f for f in sorted(os.listdir(test_audio_dir))]\n        file_list = [file.split('.')[0] for file in file_list if file.endswith('.ogg')]\n        file_list = file_list[debug_st_num:debug_st_num+debug_num]\n    \n    print('Debug mode:', debug)\n    print('Number of test soundscapes:', len(file_list))\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 3')\n    \n    \n    wav_sec = 5\n    sample_rate = 32000\n    min_segment = sample_rate*wav_sec\n    \n    class_labels = sorted(os.listdir('../input/birdclef-2025/train_audio/'))\n    \n    n_fft=1024\n    win_length=1024\n    hop_length=512\n    f_min=20\n    f_max=15000\n    n_mels=128\n    \n    mel_spectrogram = AT.MelSpectrogram(\n        sample_rate=sample_rate,\n        n_fft=n_fft,\n        win_length=win_length,\n        hop_length=hop_length,\n        center=True,\n        f_min=f_min,\n        f_max=f_max,\n        pad_mode=\"reflect\",\n        power=2.0,\n        norm='slaney',\n        n_mels=n_mels,\n        mel_scale=\"htk\",\n        # normalized=True\n    )\n    \n    def normalize_std(spec, eps=1e-23):\n        mean = torch.mean(spec)\n        std = torch.std(spec)\n        return torch.where(std == 0, spec-mean, (spec - mean) / (std+eps))\n    \n    def audio_to_mel(filepath=None):\n        waveform, sample_rate = torchaudio.load(filepath,backend=\"soundfile\")\n        len_wav = waveform.shape[1]\n        waveform = waveform[0,:].reshape(1, len_wav) # stereo->mono mono->mono\n        waveform = waveform / torch.max(torch.abs(waveform))\n        waveform = waveform + 1.5849e-05*(torch.rand(1, len_wav)-0.5) \n        PREDS = []\n        for i in range(12):\n            waveform2 = waveform[:,i*sample_rate*5:i*sample_rate*5+sample_rate*5]\n            melspec = mel_spectrogram(waveform2)\n            melspec = torch.log10(melspec)\n            melspec = normalize_std(melspec)\n            melspec = torch.unsqueeze(melspec, dim=0)\n            \n            PREDS.append(melspec)\n        return torch.vstack(PREDS)\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 4')\n    \n    \n    class Model_resnet34(nn.Module):\n        def __init__(self, pretrained=False):\n            super().__init__()\n    \n            # Use timm\n            model = models.resnet34(pretrained=pretrained)\n    \n            num_ftrs = model.fc.in_features\n            model.fc = nn.Linear(num_ftrs, len(class_labels))\n            self.model = model\n    \n        def forward(self, x):\n            x = torch.cat((x,x,x),1)\n            x = self.model(x)\n            return x\n    \n    model = Model_resnet34(pretrained=False)\n    model.load_state_dict(torch.load('/kaggle/input/birdclef-2025-models/baseline.pth', weights_only=True, map_location=torch.device('cpu')))\n    model.eval();\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 5')\n    \n    \n    def prediction(afile):    \n        global pred\n        path = test_audio_dir + afile + '.ogg'\n        with torch.inference_mode():\n            sig = audio_to_mel(path)\n            print()\n            outputs = model(sig)\n            outputs = torch.softmax(outputs,dim=1).detach().cpu().numpy()\n            chunks = [[] for i in range(12)]\n            for i in range(len(chunks)):        \n                chunk_end_time = (i + 1) * 5\n                row_id = afile + '_' + str(chunk_end_time)\n                pred['row_id'].append(row_id)\n                bird_no = 0\n                for bird in class_labels:         \n                    pred[bird].append(outputs[i,bird_no])\n                    bird_no += 1\n            gc.collect()\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 6')\n    \n    \n    pred = {'row_id': []}\n    for species_code in class_labels:\n        pred[species_code] = []\n        \n    start = time.time()\n    with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:\n        _ = list(executor.map(prediction, file_list))\n    end_t = time.time()\n    \n    if debug == True:\n        print(700*(end_t - start)/60/debug_num)\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 7')\n    \n    \n    results = pd.DataFrame(pred, columns = ['row_id'] + class_labels) \n        \n    results.to_csv(\"subm_6.csv\", index=False)    \n    \n    if debug:\n        display(results.head())\n    \n    \n    end()","metadata":{"trusted":true,"_kg_hide-input":true,"_kg_hide-output":true,"execution":{"iopub.status.busy":"2025-04-07T13:36:36.409796Z","iopub.execute_input":"2025-04-07T13:36:36.410154Z","iopub.status.idle":"2025-04-07T13:36:36.435685Z","shell.execute_reply.started":"2025-04-07T13:36:36.410126Z","shell.execute_reply":"2025-04-07T13:36:36.434623Z"},"jupyter":{"source_hidden":true}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"solution = 'SOLUTION_6.2'\n\nif  solution in ENSEMBLE_SOLUTIONS:\n                                                \n    begin(solution)\n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 0')\n    \n    \n    # * Inference Notebook [here.]\n    #   (https://www.kaggle.com/code/myso1987/birdclef2025-3-submit-baseline-5s)\n        \n    # * Dataset Creation [here]\n    #   (https://www.kaggle.com/code/myso1987/birdclef2025-1-crop-audio-5s)\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1')\n    \n    \n    ## Import\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2')\n    \n    \n    import sys\n    sys.path.append('/kaggle/usr/lib/kaggle_metric_utilities')\n    sys.path.append('/kaggle/usr/lib/birdclef-roc-auc')\n    import os\n    import random\n    import numpy as np\n    import pandas as pd\n    import matplotlib.pyplot as plt\n    from sklearn.model_selection import train_test_split\n    from tqdm import tqdm\n    \n    import torch\n    import torch.optim as optim\n    import torch.nn as nn\n    from torch.utils.data import DataLoader, Dataset\n    import torchaudio\n    import torchaudio.transforms as AT\n    from torchvision import models\n    \n    from metric import score\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 3')\n    \n    \n    ## Config\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 4')\n    \n    \n    wav_sec = 5\n    sample_rate = 32000\n    min_segment = sample_rate*wav_sec\n    \n    epochs = 8\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 5')\n    \n    \n    root_path = \"../input/birdclef-2025/\" \n    input_path = '/kaggle/input/birdclef-2025-train-data/train_raw5/'\n    \n    class_labels = sorted(os.listdir('../input/birdclef-2025/train_audio/'))\n    \n    train_meta = pd.read_csv(root_path + 'train.csv')\n    display(train_meta.head())\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 6')\n    \n    \n    ## Utilities\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 7')\n    \n    \n    def plot_spectrogram(specgram, title=None, ylabel=\"freq_bin\"):\n        fig, axs = plt.subplots(1, 1)\n        axs.set_title(title or \"Spectrogram (db)\")\n        axs.set_ylabel(ylabel)\n        axs.set_xlabel(\"frame\")\n        im = axs.imshow((specgram), origin=\"lower\", aspect=\"auto\")\n        fig.colorbar(im, ax=axs)\n        plt.show(block=False)\n    \n    def cal_score(label, pred):\n        label = np.concatenate(label)\n        pred = np.concatenate(pred)\n    \n        label_df = pd.DataFrame(label>0.5, columns=class_labels)\n        pred_df = pd.DataFrame(pred, columns=class_labels)\n        label_df['id'] = np.arange(len(label_df))\n        pred_df['id'] = np.arange(len(pred_df))\n    \n        return score(label_df, pred_df, row_id_column_name='id')\n    \n    device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 8')\n    \n    \n    ## Dataset\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 9')\n    \n    \n    n_fft=1024\n    win_length=1024\n    hop_length=512\n    f_min=20\n    f_max=15000\n    n_mels=128\n    \n    mel_spectrogram = AT.MelSpectrogram(\n        sample_rate=sample_rate,\n        n_fft=n_fft,\n        win_length=win_length,\n        hop_length=hop_length,\n        center=True,\n        f_min=f_min,\n        f_max=f_max,\n        pad_mode=\"reflect\",\n        power=2.0,\n        norm='slaney',\n        n_mels=n_mels,\n        mel_scale=\"htk\",\n        # normalized=True\n    )\n    \n    class BirdclefDataset(Dataset):\n        def __init__(self, df, mode='train'):\n            self.df = df\n            self.mode = mode\n    \n        def normalize_std(self, spec, eps=1e-23):\n            mean = torch.mean(spec)\n            std = torch.std(spec)\n            return torch.where(std == 0, spec-mean, (spec - mean) / (std+eps))\n                    \n        def __getitem__(self, index):\n            sig, _ = torchaudio.load(uri=input_path+self.df.iloc[index].filename,backend=\"soundfile\")\n            sig = sig / torch.max(torch.abs(sig))\n            sig = sig + 1.5849e-05*(torch.rand(1, min_segment)-0.5) \n            melspec = mel_spectrogram(sig)\n            melspec = torch.log(melspec)\n            melspec = self.normalize_std(melspec)\n    \n            target = self.df.iloc[index].primary_label\n            y = np.array([1 if item == target else 0 for item in class_labels])\n            \n            return melspec, y\n        \n        def __len__(self):\n            return len(self.df)\n            \n    temp_dataset = BirdclefDataset(train_meta, mode='train')\n    temp_loader = DataLoader(temp_dataset, batch_size=24, shuffle=False, num_workers=1,drop_last=True)\n    for X, y in temp_loader:\n        break\n        \n    plot_spectrogram(X[0,0,:,:])    \n    del temp_dataset, temp_loader, X, y\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 10')\n    \n    \n    ## Model\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 11')\n    \n    \n    class Model_resnet34(nn.Module):\n        def __init__(self, pretrained=False):\n            super().__init__()\n            model = models.resnet34(pretrained=pretrained)\n            num_ftrs = model.fc.in_features\n            model.fc = nn.Linear(num_ftrs, len(class_labels))\n            self.model = model\n    \n        def forward(self, x):\n            x = torch.cat((x,x,x),1)\n            x = self.model(x)\n            return x\n    \n    model = Model_resnet34(pretrained=True)\n    model = model.to(device)\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 12')\n    \n    \n    ## Train\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 13')\n    \n    \n    train_df, val_df = train_test_split(train_meta, test_size=0.2, random_state=42)\n    \n    train_dataset = BirdclefDataset(train_df, mode='train')\n    train_loader = DataLoader(train_dataset, batch_size=24, shuffle=True, num_workers=2,drop_last=True)\n    \n    val_dataset = BirdclefDataset(val_df, mode='val')\n    val_loader = DataLoader(val_dataset, batch_size=24, shuffle=False, num_workers=1,drop_last=True)\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 14')\n    \n    \n    criterion = nn.CrossEntropyLoss()\n    optimizer = optim.Adam(model.parameters(), lr=0.001)\n    \n    for epoch in range(epochs):\n        model.train()\n        pred_train = []\n        label_train = []\n        running_loss = 0.0\n        for melspecs, labels in tqdm(train_loader):\n            melspecs, labels = melspecs.to(device), labels.to(device)\n            optimizer.zero_grad()\n            outputs = model(melspecs)\n            loss = criterion(outputs, labels.to(torch.float32))\n            loss.backward()\n            optimizer.step()\n            running_loss += loss.item()\n            pred_train.append(torch.softmax(outputs,dim=1).detach().cpu().numpy())\n            label_train.append(labels.detach().cpu().numpy())\n    \n        pred_val = []\n        label_val = []\n        running_loss_val = 0.0\n        model.eval()\n        with torch.no_grad():\n            for melspecs, labels in val_loader:\n                melspecs, labels = melspecs.to(device), labels.to(device)\n                outputs = model(melspecs)\n                loss = criterion(outputs, labels.to(torch.float32))\n                running_loss_val += loss.item()\n                pred_val.append(torch.softmax(outputs,dim=1).detach().cpu().numpy())\n                label_val.append(labels.detach().cpu().numpy())\n        \n        auc_train_val = cal_score(label_train, pred_train)\n        auc_val = cal_score(label_val, pred_val)\n        print(f\"Epoch {epoch+1}/{epochs}, Loss: {running_loss/len(train_loader):.4f}, Loss_val: {running_loss_val/len(train_loader):.4f}\")\n        print(f\"Auc: {auc_train_val:.2f}% Auc_val: {auc_val:.2f}%\")\n    \n    torch.save(model.state_dict(), \"baseline.pth\")\n    \n    \n    end()","metadata":{"trusted":true,"_kg_hide-input":true,"_kg_hide-output":true,"jupyter":{"source_hidden":true},"execution":{"iopub.status.busy":"2025-04-07T13:36:36.436702Z","iopub.execute_input":"2025-04-07T13:36:36.437060Z","iopub.status.idle":"2025-04-07T13:36:36.472191Z","shell.execute_reply.started":"2025-04-07T13:36:36.437023Z","shell.execute_reply":"2025-04-07T13:36:36.471042Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"solution = 'SOLUTION_b.3'\n\nif  solution in ENSEMBLE_SOLUTIONS:\n                                                \n    begin(solution)\n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 0')\n    \n    \n    # * Training Notebook [here.]\n    #   (https://www.kaggle.com/code/myso1987/birdclef2025-2-train-baseline-5s)\n        \n    # * Inference Notebook [here.]\n    #   (https://www.kaggle.com/code/myso1987/birdclef2025-3-submit-baseline-5s)\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1')\n    \n    \n    import os\n    import pandas as pd\n    import numpy as np\n    import torch\n    import torchaudio\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2')\n    \n    \n    wav_sec = 5\n    sample_rate = 32000\n    min_segment = sample_rate*wav_sec\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 3')\n    \n    \n    root_path = \"../input/birdclef-2025/\"\n    input_path = root_path + '/train_audio/'\n    out_path = \"./train_raw\" + str(wav_sec) +\"/\"\n    backend='soundfile'\n    \n    try:\n        os.mkdir(out_path)\n    except FileExistsError:\n        pass\n    \n    train_meta = pd.read_csv(root_path + 'train.csv')\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 4')\n    \n    \n    def crop_and_save(index):\n        sig, _ = torchaudio.load(input_path+train_meta.iloc[index].filename, backend=backend)\n        \n        if sig.shape[1]<=min_segment:\n            sig = torch.concat([sig, torch.zeros(1,min_segment-sig.shape[1])], dim=1)\n    \n        dir_path = out_path + train_meta.iloc[index].filename.split('/')[0] + '/'\n        if not os.path.exists(dir_path):\n            os.mkdir(dir_path)\n        \n        tmp_savename = out_path + train_meta.iloc[index].filename\n        torchaudio.save(uri=tmp_savename, src=sig[:,:min_segment], sample_rate=sample_rate, backend=backend)\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 5')\n    \n    \n    for index in range(len(train_meta)):\n        crop_and_save(index)\n    \n    \n    end()","metadata":{"trusted":true,"_kg_hide-input":true,"_kg_hide-output":true,"jupyter":{"source_hidden":true},"execution":{"iopub.status.busy":"2025-04-07T13:36:36.473354Z","iopub.execute_input":"2025-04-07T13:36:36.473776Z","iopub.status.idle":"2025-04-07T13:36:36.495344Z","shell.execute_reply.started":"2025-04-07T13:36:36.473734Z","shell.execute_reply":"2025-04-07T13:36:36.494345Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## [agcsdedf](https://www.kaggle.com/agcsdedf)\n### 8. &nbsp; [BirdCLEF 2025 Base Submit](https://www.kaggle.com/code/agcsdedf/birdclef-2025-base-submit)\n### 12. [BirdCLEF-2025 OpenVINO Inf](https://www.kaggle.com/code/agcsdedf/birdclef-2025-openvino-inf)","metadata":{}},{"cell_type":"code","source":"solution = 'SOLUTION_8'\n\nif  solution in ENSEMBLE_SOLUTIONS:\n                                                \n    begin(solution)\n\n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 0')\n    \n    \n    import torch\n    import torch.nn as nn\n    import torch.nn.functional as F\n    \n    import os\n    import timm\n    import librosa\n    import numpy as np\n    import pandas as pd\n    \n    # import random\n    # import albumentations as A\n    # # import audiomentations as Audio\n    # from albumentations.pytorch import ToTensorV2\n    \n    import gc\n    import dataclasses\n    from concurrent.futures import ThreadPoolExecutor\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1')\n    \n    \n    test_data_path = \"/kaggle/input/birdclef-2025/test_soundscapes\"\n    submission_path = \"/kaggle/input/birdclef-2025/sample_submission.csv\"\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2')\n    \n    \n    transform = None\n    audio_transform = None\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 3')\n    \n    \n    @dataclasses.dataclass\n    class AudioParam:\n        SR: int=32_000\n        NFFT: int=2048\n        NMEL: int=128\n        FMAX: int=16_000\n        FMIN: int=20\n        HOP_LENGTH: int=NFFT // 4\n    \n    audio_param = AudioParam()\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 4')\n    \n    \n    sub_csv = pd.read_csv(submission_path)\n    idx2cls = sub_csv.columns.drop(\"row_id\").tolist()\n    cls2idx = {c: i for i, c in enumerate(idx2cls)}\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 5')\n    \n    \n    DEBUG = False\n    file_names = [os.path.join(test_data_path, fp) for fp in os.listdir(test_data_path) if fp.endswith(\".ogg\")]\n    if len(file_names) == 0:\n        file_names = [\n            \"/kaggle/input/birdclef-2025/train_soundscapes/H02_20230420_074000.ogg\",\n            \"/kaggle/input/birdclef-2025/train_soundscapes/H02_20230420_112000.ogg\",\n            \"/kaggle/input/birdclef-2025/train_soundscapes/H02_20230420_164000.ogg\",\n        ]\n        DEBUG = True\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 6')\n    \n    \n    class EfficientNetV2(nn.Module):\n        def __init__(self, num_classes=1, pretrained=False, dropout=.0):\n            super().__init__()\n            self.backbone = timm.create_model(\n                \"timm/tf_efficientnetv2_m.in21k\",\n                in_chans=1,\n                pretrained=pretrained,\n                features_only=True,\n                drop_rate=dropout,\n                drop_path_rate=dropout,\n            )\n    \n            self.head = nn.Sequential(\n                nn.Conv2d(512, num_classes, 1),\n                nn.AdaptiveAvgPool2d(1),\n                nn.Flatten(1),\n            )\n    \n        def forward(self, x):\n            x = self.backbone(x)[-1]\n            x = self.head(x)\n    \n            return x\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 7')\n    \n    \n    class EfficientNetB3(nn.Module):\n        def __init__(self, num_classes=1):\n            super().__init__()\n            self.backbone = timm.create_model(\n                \"efficientnet_b3.ra2_in1k\",\n                pretrained=False, \n                features_only=True, \n            )\n            self.backbone.conv_stem = nn.Conv2d(1, 40, 3, stride=2, padding=1, bias=False)\n            self.head = nn.Sequential(\n                nn.Conv2d(384, num_classes, 1),\n                nn.AdaptiveAvgPool2d(1),\n                nn.Flatten(1),\n            )\n    \n        def forward(self, x):\n            x = self.backbone(x)[-1]\n            x = self.head(x)\n    \n            return x\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 8')\n    \n    \n    # model = EfficientNetB3(len(idx2cls))\n    # model.load_state_dict(\n    #     torch.load(\n    #         \"/kaggle/input/birdclef-2025-base-trainer/EfficientB3_last\",\n    #         map_location=\"cpu\",\n    #         weights_only=True,\n    #     )\n    # )\n    \n    model = EfficientNetV2(len(idx2cls))\n    model.load_state_dict(\n        torch.load(\n            \"/kaggle/input/birdclef-2025-base-trainer/EfficientV2_last\",\n            map_location=\"cpu\",\n            weights_only=True,\n        )\n    )\n    \n    model.eval();\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 9')\n    \n    \n    def pipeline(x):\n        mels = librosa.feature.melspectrogram(\n            y=x,\n            sr=audio_param.SR,\n            n_fft=audio_param.NFFT,\n            n_mels=audio_param.NMEL,\n            fmax=audio_param.FMAX,\n            fmin=audio_param.FMIN,\n            hop_length=audio_param.HOP_LENGTH,\n        )\n    \n        # db_map = pcen(mels).astype(np.float32)\n    \n        db_map = librosa.power_to_db(mels, ref=np.max)\n        db_map = (db_map + 80) / 80\n    \n        return db_map[:, None]\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 10')\n    \n    \n    @torch.no_grad()\n    def predict(fp):\n        x, _ = librosa.load(fp, sr=audio_param.SR)\n        x = x.reshape(-1, audio_param.SR*5)\n        if audio_transform is not None:\n            x = audio_transform(sample=x, sample_rate=audio_param.SR)\n    \n        x = pipeline(x)\n    \n        if transform is not None:\n            x = transform(image=x)[\"image\"]\n    \n        x = torch.from_numpy(x)\n    \n        out = model(x).sigmoid().detach().numpy()\n        fp_name = os.path.basename(fp).split(\".\")[0]\n        row_id = [f\"{fp_name}_{(i+1)*5}\" for i in range(0, out.shape[0])]\n    \n        return out, row_id\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 11')\n    \n    \n    row_id = []\n    matrix = []\n    with ThreadPoolExecutor(max_workers=4) as executor:\n        for out, rid in executor.map(predict, file_names):\n            row_id += rid\n            matrix.append(out)\n    matrix = np.concatenate(matrix)\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 12')\n    \n    \n    matrix = np.concatenate([np.array(row_id).reshape(-1, 1), matrix], axis=1)\n    sub_csv = pd.DataFrame(matrix, columns=[\"row_id\", *idx2cls])\n    sub_csv.to_csv('subm_8.csv', index=False)\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 13')\n    \n    \n    sub_csv.head()","metadata":{"trusted":true,"_kg_hide-input":true,"_kg_hide-output":true,"execution":{"iopub.status.busy":"2025-04-07T13:36:36.498223Z","iopub.execute_input":"2025-04-07T13:36:36.498563Z","iopub.status.idle":"2025-04-07T13:36:36.520122Z","shell.execute_reply.started":"2025-04-07T13:36:36.498531Z","shell.execute_reply":"2025-04-07T13:36:36.519126Z"},"jupyter":{"source_hidden":true}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"solution = 'SOLUTION_12'\n\nif  solution in ENSEMBLE_SOLUTIONS:\n                                                    \n    begin(solution)\n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 0')\n\n        \n    # Pytorch2OpenVINO：\n    \n    # - - - - Start - - - -\n    # model = resnet34()\n    # model.eval()\n    \n    # openvino_model = openvino.convert_model(model, example_input=torch.randn(1, 1, 128, 320))\n    \n    # openvino_model.reshape([-1, 1, 128, 320])\n    # openvino.save_model(openvino_model, \"resnet34.xml\")\n    \n    # - - - - End - - - -\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1')\n    \n    \n    # %%capture\n    \n    !pip install -U openvino-telemetry  --no-index --find-links /kaggle/input/pip-hub\n    !pip install -U openvino  --no-index --find-links /kaggle/input/pip-hub\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2')\n    \n    \n    import torch\n    import torch.nn as nn\n    import torch.nn.functional as F\n    \n    import os\n    import timm\n    import librosa\n    import numpy as np\n    import pandas as pd\n    \n    # import random\n    import albumentations as A\n    # # import audiomentations as Audio\n    # from albumentations.pytorch import ToTensorV2\n    \n    import gc\n    import dataclasses\n    from concurrent.futures import ThreadPoolExecutor\n    \n    import scipy\n    import openvino\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 3')\n    \n    \n    test_data_path = \"/kaggle/input/birdclef-2025/test_soundscapes\"\n    submission_path = \"/kaggle/input/birdclef-2025/sample_submission.csv\"\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 4')\n    \n    \n    transform = A.Compose([\n        A.Resize(128, 320),\n        # ToTensorV2(),\n    ])\n    audio_transform = None\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 5')\n    \n    \n    @dataclasses.dataclass\n    class AudioParam:\n        SR: int=32_000\n        NFFT: int=2048\n        NMEL: int=128\n        FMAX: int=16_000\n        FMIN: int=20\n        HOP_LENGTH: int=NFFT // 4\n    \n    audio_param = AudioParam()\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 6')\n    \n    \n    sub_csv = pd.read_csv(submission_path)\n    idx2cls = sub_csv.columns.drop(\"row_id\").tolist()\n    cls2idx = {c: i for i, c in enumerate(idx2cls)}\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 7')\n    \n    \n    DEBUG = False\n    file_names = [os.path.join(test_data_path, fp) for fp in os.listdir(test_data_path) if fp.endswith(\".ogg\")]\n    if len(file_names) == 0:\n        file_names = [\n            \"/kaggle/input/birdclef-2025/train_soundscapes/H02_20230420_074000.ogg\",\n            \"/kaggle/input/birdclef-2025/train_soundscapes/H02_20230420_112000.ogg\",\n            \"/kaggle/input/birdclef-2025/train_soundscapes/H02_20230420_164000.ogg\",\n            \"/kaggle/input/birdclef-2025/train_soundscapes/H02_20230422_021500.ogg\",\n        ]\n        DEBUG = True\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 8')\n    \n    \n    def pipeline(x):\n        if audio_transform is not None:\n            x = audio_transform(sample=x, sample_rate=audio_param.SR)\n        \n        mels = librosa.feature.melspectrogram(\n            y=x,\n            sr=audio_param.SR,\n            n_fft=audio_param.NFFT,\n            n_mels=audio_param.NMEL,\n            fmax=audio_param.FMAX,\n            fmin=audio_param.FMIN,\n            hop_length=audio_param.HOP_LENGTH,\n        )\n    \n        # db_map = pcen(mels).astype(np.float32)\n    \n        x = librosa.power_to_db(mels, ref=np.max)\n        x = (x + 80) / 80\n    \n        if transform is not None:\n            x = np.stack([transform(image=img)[\"image\"] for img in x])\n    \n        return x[:, None]\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 9')\n    \n    \n    def predict(fps):\n        ie = openvino.Core()\n        model = ie.read_model(model=\"/kaggle/input/efficientnetb3-openvino-ir/EfficientNetB3.xml\")\n        compiled_model  = ie.compile_model(model=model, device_name=\"CPU\")\n    \n        input_layer = next(iter(compiled_model.inputs))\n        output_layer = next(iter(compiled_model.outputs))\n    \n        row_ids = []\n        outputs = []\n        for fp in fps:\n            x, _ = librosa.load(fp, sr=audio_param.SR)\n            x = x.reshape(-1, audio_param.SR*5)\n        \n            x = pipeline(x).astype(np.float32)\n            output = compiled_model({input_layer: x})\n            out = output[output_layer]\n            out = scipy.special.softmax(out, axis=1)\n            outputs.append(out)\n        \n            fp_name = os.path.basename(fp).split(\".\")[0]\n            row_ids += [f\"{fp_name}_{(i+1)*5}\" for i in range(0, out.shape[0])]\n    \n        del x, out, ie, model, compiled_model\n        gc.collect()\n    \n        return np.concatenate(outputs, axis=0), row_ids\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 10')\n    \n    \n    fold = len(file_names) // 4\n    file_names = [\n        file_names[0:fold],\n        file_names[fold:fold*2],\n        file_names[fold*2:fold*3],\n        file_names[fold*3:],\n    ]\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 11')\n    \n    \n    row_id = []\n    matrix = []\n    with ThreadPoolExecutor(max_workers=4) as executor:\n        for out, rid in executor.map(predict, file_names):\n            row_id += rid\n            matrix.append(out)\n    matrix = np.concatenate(matrix)\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 12')\n    \n    \n    matrix = np.concatenate([np.array(row_id).reshape(-1, 1), matrix], axis=1)\n    sub_csv = pd.DataFrame(matrix, columns=[\"row_id\", *idx2cls])\n    sub_csv.to_csv('subm_12.csv', index=False)\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 13')\n    \n    \n    sub_csv.head()\n    \n    \n    end()","metadata":{"trusted":true,"jupyter":{"source_hidden":true},"_kg_hide-input":true,"_kg_hide-output":true,"execution":{"iopub.status.busy":"2025-04-07T13:36:36.521932Z","iopub.execute_input":"2025-04-07T13:36:36.522325Z","iopub.status.idle":"2025-04-07T13:36:36.558031Z","shell.execute_reply.started":"2025-04-07T13:36:36.522285Z","shell.execute_reply":"2025-04-07T13:36:36.556808Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## [Kadircan İdrisoğlu](https://www.kaggle.com/kadircandrisolu)\n### 9. [[Pytorch, Training] BirdCLEF2025 Baseline](https://www.kaggle.com/code/kadircandrisolu/pytorch-training-birdclef2025-baseline), v5\n### 9. [[Pytorch, Inference] BirdCLEF2025 Baseline](https://www.kaggle.com/code/kadircandrisolu/pytorch-inference-birdclef2025-baseline)","metadata":{}},{"cell_type":"code","source":"solution = 'SOLUTION_9_Trainer'\n\nif  solution in ENSEMBLE_SOLUTIONS:\n                                                        \n    begin(solution)\n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 0')\n    \n    \n    # About this notebook\n    # In this notebook, I will show the way to train the model used here: [this training notebook](https://www.kaggle.com/code/kadircandrisolu/pytorch-inference-birdclef2025-baseline?scriptVersionId=227612872) \n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1')\n    \n    \n    # Libraries\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2')\n    \n    \n    # Basic imports\n    import os\n    import logging\n    import random\n    import gc\n    import time\n    import warnings\n    from pathlib import Path\n    \n    # Data processing\n    import numpy as np\n    import pandas as pd\n    from sklearn.model_selection import StratifiedKFold\n    from sklearn.metrics import roc_auc_score\n    \n    # Audio processing\n    import librosa\n    import soundfile as sf\n    \n    # PyTorch\n    import torch\n    import torch.nn as nn\n    import torch.nn.functional as F\n    import torch.optim as optim\n    from torch.optim import lr_scheduler\n    from torch.utils.data import Dataset, DataLoader\n    \n    # Visualization\n    import matplotlib.pyplot as plt\n    import seaborn as sns\n    from tqdm.auto import tqdm\n    \n    # Model architecture\n    import timm\n    \n    # Ignore warnings\n    warnings.filterwarnings(\"ignore\")\n    logging.basicConfig(level=logging.ERROR)\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 3')\n    \n    \n    # Configuration\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 4')\n    \n    \n    class CFG:\n        \n        seed = 42\n        debug = True  \n        apex = False\n        print_freq = 100\n        num_workers = 2\n        \n        # Paths\n        train_datadir = '/kaggle/input/birdclef-2025/train_audio'\n        train_csv = '/kaggle/input/birdclef-2025/train.csv'\n        test_soundscapes = '/kaggle/input/birdclef-2025/test_soundscapes'\n        submission_csv = '/kaggle/input/birdclef-2025/sample_submission.csv'\n        taxonomy_csv = '/kaggle/input/birdclef-2025/taxonomy.csv'\n        \n        # Model Settings\n        model_name = 'efficientnet_b0'  \n        pretrained = True\n        in_channels = 1  \n        \n        # Audio Settings\n        sample_rate = 32000  # Competition audio is 32kHz\n        duration = 5  # 5-second clips for prediction\n        melspec_parameters = {\n            'n_mels': 128,\n            'fmin': 20,\n            'fmax': 16000,\n        }\n        \n        # Training Settings\n        device = 'cuda' if torch.cuda.is_available() else 'cpu'\n        epochs = 20  \n        batch_size = 32  \n        criterion = 'BCEWithLogitsLoss'\n        \n        # Cross-validation\n        n_fold = 5\n        selected_folds = [0, 1, 2, 3, 4]  \n        \n        # Optimizer\n        optimizer = 'Adam'\n        lr = 1e-3\n        weight_decay = 1e-6\n        \n        # Scheduler\n        scheduler = 'CosineAnnealingLR'\n        min_lr = 1e-6\n        T_max = epochs\n        \n        # Augmentations\n        aug_prob = 0.5  \n        mixup_alpha = 0.4  \n        \n        # Debug settings \n        def update_debug_settings(self):\n            if self.debug:\n                self.epochs = 2\n                self.selected_folds = [0, 1]  \n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 5')\n    \n    \n    cfg = CFG()\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 6')\n    \n    \n    # Utilities\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 7')\n    \n    \n    def set_seed(seed=42):\n        \"\"\"\n        Set seed for reproducibility\n        \"\"\"\n        random.seed(seed)\n        os.environ[\"PYTHONHASHSEED\"] = str(seed)\n        np.random.seed(seed)\n        torch.manual_seed(seed)\n        torch.cuda.manual_seed(seed)\n        torch.cuda.manual_seed_all(seed)\n        torch.backends.cudnn.deterministic = True\n        torch.backends.cudnn.benchmark = False\n    \n    set_seed(cfg.seed)\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 8')\n    \n    \n    # Dataset Preparation and Data Augmentations\n    # We'll convert audio to mel spectrograms and apply random augmentations with 50% probability each - including time stretching, pitch shifting, and volume adjustments. This randomized approach creates diverse training samples from the same audio files\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 9')\n    \n    \n    class BirdCLEFDataset(Dataset):\n        def __init__(self, df, cfg, mode=\"train\"):\n            self.df = df\n            self.cfg = cfg\n            self.mode = mode\n            \n            taxonomy_df = pd.read_csv(self.cfg.taxonomy_csv)\n            self.species_ids = taxonomy_df['primary_label'].tolist()\n            self.num_classes = len(self.species_ids)\n            self.label_to_idx = {label: idx for idx, label in enumerate(self.species_ids)}\n            \n            if cfg.debug:\n                self.df = self.df.sample(min(1000, len(self.df)), random_state=cfg.seed).reset_index(drop=True)\n        \n        def __len__(self):\n            return len(self.df)\n        \n        def __getitem__(self, idx):\n            row = self.df.iloc[idx]\n            audio_path = os.path.join(self.cfg.train_datadir, row['filename'])\n            audio, sr = self.load_audio_file(audio_path)\n            \n            if self.mode == \"train\" and random.random() < self.cfg.aug_prob:\n                audio = self.apply_audio_augmentations(audio)\n            \n            melspec = self.audio_to_melspec(audio, sr)\n            \n            target = self.encode_label(row['primary_label'])\n            \n            if 'secondary_labels' in row and row['secondary_labels'] not in [[''], None, np.nan]:\n                if isinstance(row['secondary_labels'], str):\n                    secondary_labels = eval(row['secondary_labels'])\n                else:\n                    secondary_labels = row['secondary_labels']\n                \n                for label in secondary_labels:\n                    if label in self.label_to_idx:\n                        target[self.label_to_idx[label]] = 1.0\n            \n            return {\n                'melspec': torch.tensor(melspec, dtype=torch.float32),\n                'target': torch.tensor(target, dtype=torch.float32),\n                'filename': row['filename']\n            }\n        \n        def load_audio_file(self, file_path):\n            \"\"\"Load and preprocess audio file\"\"\"\n            audio, sr = sf.read(file_path)\n            \n            if len(audio.shape) > 1:\n                audio = audio.mean(axis=1)\n            \n            if sr != self.cfg.sample_rate:\n                audio = librosa.resample(audio, orig_sr=sr, target_sr=self.cfg.sample_rate)\n                sr = self.cfg.sample_rate\n                \n            target_length = int(self.cfg.duration * self.cfg.sample_rate)\n            \n            if len(audio) < target_length:\n                padding = target_length - len(audio)\n                audio = np.pad(audio, (0, padding), mode='constant')\n            elif len(audio) > target_length:\n                if self.mode == \"train\":\n                    start = random.randint(0, len(audio) - target_length)\n                else:\n                    start = (len(audio) - target_length) // 2\n                audio = audio[start:start + target_length]\n            \n            return audio, sr\n        \n        def audio_to_melspec(self, audio, sr):\n            \"\"\"Convert audio to mel spectrogram\"\"\"\n            melspec = librosa.feature.melspectrogram(\n                y=audio,\n                sr=sr,\n                n_fft=2048,\n                hop_length=512,\n                n_mels=self.cfg.melspec_parameters['n_mels'],\n                fmin=self.cfg.melspec_parameters['fmin'],\n                fmax=self.cfg.melspec_parameters['fmax']\n            )\n            \n            melspec = librosa.power_to_db(melspec)\n            \n            melspec = (melspec - melspec.min()) / (melspec.max() - melspec.min() + 1e-8)\n            \n            melspec = melspec[np.newaxis, :, :]\n            \n            return melspec\n        \n        def apply_audio_augmentations(self, audio):\n            \n            # Time stretching\n            if random.random() < 0.5:\n                stretch_factor = random.uniform(0.8, 1.2)\n                audio = librosa.effects.time_stretch(audio, rate=stretch_factor)\n            \n            # Pitch shifting\n            if random.random() < 0.5:\n                pitch_shift = random.randint(-3, 3)\n                audio = librosa.effects.pitch_shift(\n                    audio, \n                    sr=self.cfg.sample_rate, \n                    n_steps=pitch_shift\n                )\n            \n            # Volume adjustment\n            if random.random() < 0.5:\n                gain = random.uniform(0.8, 1.2)\n                audio = audio * gain\n                \n            audio = np.clip(audio, -1, 1)\n            \n            return audio\n        \n        def encode_label(self, label):\n    \n            target = np.zeros(self.num_classes)\n            if label in self.label_to_idx:\n                target[self.label_to_idx[label]] = 1.0\n            return target\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 10')\n    \n    \n    # Model Definition\n    # I'm using an EfficientNet backbone and I've added mixup training which blends samples together during training. This reduces overfitting and makes our model more robust.\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 11')\n    \n    \n    class BirdCLEFModel(nn.Module):\n        def __init__(self, cfg):\n            super().__init__()\n            self.cfg = cfg\n            \n            taxonomy_df = pd.read_csv(cfg.taxonomy_csv)\n            cfg.num_classes = len(taxonomy_df)\n            \n            self.backbone = timm.create_model(\n                cfg.model_name,\n                pretrained=cfg.pretrained,\n                in_chans=cfg.in_channels,\n                drop_rate=0.2,\n                drop_path_rate=0.2\n            )\n            \n            if 'efficientnet' in cfg.model_name:\n                backbone_out = self.backbone.classifier.in_features\n                self.backbone.classifier = nn.Identity()\n            elif 'resnet' in cfg.model_name:\n                backbone_out = self.backbone.fc.in_features\n                self.backbone.fc = nn.Identity()\n            else:\n                backbone_out = self.backbone.get_classifier().in_features\n                self.backbone.reset_classifier(0, '')\n            \n            self.pooling = nn.AdaptiveAvgPool2d(1)\n                \n            self.feat_dim = backbone_out\n            \n            self.classifier = nn.Linear(backbone_out, cfg.num_classes)\n            \n            self.mixup_enabled = hasattr(cfg, 'mixup_alpha') and cfg.mixup_alpha > 0\n            if self.mixup_enabled:\n                self.mixup_alpha = cfg.mixup_alpha\n                \n        def forward(self, x, targets=None):\n        \n            if self.training and self.mixup_enabled and targets is not None:\n                mixed_x, targets_a, targets_b, lam = self.mixup_data(x, targets)\n                x = mixed_x\n            else:\n                targets_a, targets_b, lam = None, None, None\n            \n            features = self.backbone(x)\n            \n            if isinstance(features, dict):\n                features = features['features']\n                \n            if len(features.shape) == 4:\n                features = self.pooling(features)\n                features = features.view(features.size(0), -1)\n            \n            logits = self.classifier(features)\n            \n            if self.training and self.mixup_enabled and targets is not None:\n                loss = self.mixup_criterion(F.binary_cross_entropy_with_logits, \n                                           logits, targets_a, targets_b, lam)\n                return logits, loss\n                \n            return logits\n        \n        def mixup_data(self, x, targets):\n            \"\"\"Applies mixup to the data batch\"\"\"\n            batch_size = x.size(0)\n            \n            # Sample lambda from beta distribution\n            lam = np.random.beta(self.mixup_alpha, self.mixup_alpha)\n            \n            # Random permutation of batch indices\n            indices = torch.randperm(batch_size).to(x.device)\n            \n            # Mix data and targets\n            mixed_x = lam * x + (1 - lam) * x[indices]\n            \n            return mixed_x, targets, targets[indices], lam\n        \n        def mixup_criterion(self, criterion, pred, y_a, y_b, lam):\n            \"\"\"Applies mixup to the loss function\"\"\"\n            return lam * criterion(pred, y_a) + (1 - lam) * criterion(pred, y_b)\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 12')\n    \n    \n    # Training Utilities\n    # Setting up our optimization strategy with Adam optimizer and cosine scheduling. The custom collate function handles different audio lengths in batches.\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 13')\n    \n    \n    def get_optimizer(model, cfg):\n      \n        if cfg.optimizer == 'Adam':\n            optimizer = optim.Adam(\n                model.parameters(),\n                lr=cfg.lr,\n                weight_decay=cfg.weight_decay\n            )\n        elif cfg.optimizer == 'AdamW':\n            optimizer = optim.AdamW(\n                model.parameters(),\n                lr=cfg.lr,\n                weight_decay=cfg.weight_decay\n            )\n        elif cfg.optimizer == 'SGD':\n            optimizer = optim.SGD(\n                model.parameters(),\n                lr=cfg.lr,\n                momentum=0.9,\n                weight_decay=cfg.weight_decay\n            )\n        else:\n            raise NotImplementedError(f\"Optimizer {cfg.optimizer} not implemented\")\n            \n        return optimizer\n    \n    def get_scheduler(optimizer, cfg):\n       \n        if cfg.scheduler == 'CosineAnnealingLR':\n            scheduler = lr_scheduler.CosineAnnealingLR(\n                optimizer,\n                T_max=cfg.T_max,\n                eta_min=cfg.min_lr\n            )\n        elif cfg.scheduler == 'ReduceLROnPlateau':\n            scheduler = lr_scheduler.ReduceLROnPlateau(\n                optimizer,\n                mode='min',\n                factor=0.5,\n                patience=2,\n                min_lr=cfg.min_lr,\n                verbose=True\n            )\n        elif cfg.scheduler == 'StepLR':\n            scheduler = lr_scheduler.StepLR(\n                optimizer,\n                step_size=cfg.epochs // 3,\n                gamma=0.5\n            )\n        elif cfg.scheduler == 'OneCycleLR':\n            scheduler = None  \n        else:\n            scheduler = None\n            \n        return scheduler\n    \n    def get_criterion(cfg):\n     \n        if cfg.criterion == 'BCEWithLogitsLoss':\n            criterion = nn.BCEWithLogitsLoss()\n        else:\n            raise NotImplementedError(f\"Criterion {cfg.criterion} not implemented\")\n            \n        return criterion\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 14')\n    \n    \n    def collate_fn(batch):\n        \"\"\"Custom collate function to handle different sized spectrograms\"\"\"\n        batch = [item for item in batch if item is not None]\n        if len(batch) == 0:\n            return {}\n            \n        result = {key: [] for key in batch[0].keys()}\n        \n        for item in batch:\n            for key, value in item.items():\n                result[key].append(value)\n        \n        for key in result:\n            if key == 'target' and isinstance(result[key][0], torch.Tensor):\n                result[key] = torch.stack(result[key])\n            elif key == 'melspec' and isinstance(result[key][0], torch.Tensor):\n                shapes = [t.shape for t in result[key]]\n                if len(set(str(s) for s in shapes)) == 1:\n                    result[key] = torch.stack(result[key])\n        \n        return result\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 15')\n    \n    \n    # Training loop\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 16')\n    \n    \n    def train_one_epoch(model, loader, optimizer, criterion, device, scheduler=None):\n        \n        model.train()\n        losses = []\n        all_targets = []\n        all_outputs = []\n        \n        pbar = tqdm(enumerate(loader), total=len(loader), desc=\"Training\")\n        \n        for step, batch in pbar:\n        \n            if isinstance(batch['melspec'], list):\n                batch_outputs = []\n                batch_losses = []\n                \n                for i in range(len(batch['melspec'])):\n                    inputs = batch['melspec'][i].unsqueeze(0).to(device)\n                    target = batch['target'][i].unsqueeze(0).to(device)\n                    \n                    optimizer.zero_grad()\n                    output = model(inputs)\n                    loss = criterion(output, target)\n                    loss.backward()\n                    \n                    batch_outputs.append(output.detach().cpu())\n                    batch_losses.append(loss.item())\n                \n                optimizer.step()\n                outputs = torch.cat(batch_outputs, dim=0).numpy()\n                loss = np.mean(batch_losses)\n                targets = batch['target'].numpy()\n                \n            else:\n                inputs = batch['melspec'].to(device)\n                targets = batch['target'].to(device)\n                \n                optimizer.zero_grad()\n                outputs = model(inputs)\n                \n                if isinstance(outputs, tuple):\n                    outputs, loss = outputs  \n                else:\n                    loss = criterion(outputs, targets)\n                    \n                loss.backward()\n                optimizer.step()\n                \n                outputs = outputs.detach().cpu().numpy()\n                targets = targets.detach().cpu().numpy()\n            \n            if scheduler is not None and isinstance(scheduler, lr_scheduler.OneCycleLR):\n                scheduler.step()\n                \n            all_outputs.append(outputs)\n            all_targets.append(targets)\n            losses.append(loss if isinstance(loss, float) else loss.item())\n            \n            pbar.set_postfix({\n                'train_loss': np.mean(losses[-10:]) if losses else 0,\n                'lr': optimizer.param_groups[0]['lr']\n            })\n        \n        all_outputs = np.concatenate(all_outputs)\n        all_targets = np.concatenate(all_targets)\n        auc = calculate_auc(all_targets, all_outputs)\n        avg_loss = np.mean(losses)\n        \n        return avg_loss, auc\n    \n    def validate(model, loader, criterion, device):\n       \n        model.eval()\n        losses = []\n        all_targets = []\n        all_outputs = []\n        \n        with torch.no_grad():\n            for batch in tqdm(loader, desc=\"Validation\"):\n                if isinstance(batch['melspec'], list):\n                    batch_outputs = []\n                    batch_losses = []\n                    \n                    for i in range(len(batch['melspec'])):\n                        inputs = batch['melspec'][i].unsqueeze(0).to(device)\n                        target = batch['target'][i].unsqueeze(0).to(device)\n                        \n                        output = model(inputs)\n                        loss = criterion(output, target)\n                        \n                        batch_outputs.append(output.detach().cpu())\n                        batch_losses.append(loss.item())\n                    \n                    outputs = torch.cat(batch_outputs, dim=0).numpy()\n                    loss = np.mean(batch_losses)\n                    targets = batch['target'].numpy()\n                    \n                else:\n                    inputs = batch['melspec'].to(device)\n                    targets = batch['target'].to(device)\n                    \n                    outputs = model(inputs)\n                    loss = criterion(outputs, targets)\n                    \n                    outputs = outputs.detach().cpu().numpy()\n                    targets = targets.detach().cpu().numpy()\n                \n                all_outputs.append(outputs)\n                all_targets.append(targets)\n                losses.append(loss if isinstance(loss, float) else loss.item())\n        \n        all_outputs = np.concatenate(all_outputs)\n        all_targets = np.concatenate(all_targets)\n        \n        auc = calculate_auc(all_targets, all_outputs)\n        avg_loss = np.mean(losses)\n        \n        return avg_loss, auc\n    \n    def calculate_auc(targets, outputs):\n      \n        num_classes = targets.shape[1]\n        aucs = []\n        \n        probs = 1 / (1 + np.exp(-outputs))\n        \n        for i in range(num_classes):\n            \n            if np.sum(targets[:, i]) > 0:\n                class_auc = roc_auc_score(targets[:, i], probs[:, i])\n                aucs.append(class_auc)\n        \n        return np.mean(aucs) if aucs else 0.0\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 17')\n    \n    \n    # Training!\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 18')\n    \n    \n    def run_training(df, cfg):\n    \n        taxonomy_df = pd.read_csv(cfg.taxonomy_csv)\n        species_ids = taxonomy_df['primary_label'].tolist()\n        cfg.num_classes = len(species_ids)\n        \n        if cfg.debug:\n            cfg.update_debug_settings()\n            \n        skf = StratifiedKFold(n_splits=cfg.n_fold, shuffle=True, random_state=cfg.seed)\n        \n        best_scores = []\n        \n        for fold, (train_idx, val_idx) in enumerate(skf.split(df, df['primary_label'])):\n            if fold not in cfg.selected_folds:\n                continue\n                \n            print(f'\\n{\"=\"*30} Fold {fold} {\"=\"*30}')\n            \n            train_df = df.iloc[train_idx].reset_index(drop=True)\n            val_df = df.iloc[val_idx].reset_index(drop=True)\n            \n            print(f'Training set: {len(train_df)} samples')\n            print(f'Validation set: {len(val_df)} samples')\n            \n            train_dataset = BirdCLEFDataset(train_df, cfg, mode='train')\n            val_dataset = BirdCLEFDataset(val_df, cfg, mode='valid')\n            \n            train_loader = DataLoader(\n                train_dataset, \n                batch_size=cfg.batch_size, \n                shuffle=True, \n                num_workers=cfg.num_workers,\n                collate_fn=collate_fn,\n                drop_last=True\n            )\n            \n            val_loader = DataLoader(\n                val_dataset, \n                batch_size=cfg.batch_size, \n                shuffle=False, \n                num_workers=cfg.num_workers,\n                collate_fn=collate_fn\n            )\n            \n            model = BirdCLEFModel(cfg).to(cfg.device)\n            optimizer = get_optimizer(model, cfg)\n            criterion = get_criterion(cfg)\n            \n            if cfg.scheduler == 'OneCycleLR':\n                scheduler = lr_scheduler.OneCycleLR(\n                    optimizer,\n                    max_lr=cfg.lr,\n                    steps_per_epoch=len(train_loader),\n                    epochs=cfg.epochs,\n                    pct_start=0.1\n                )\n            else:\n                scheduler = get_scheduler(optimizer, cfg)\n            \n            best_auc = 0\n            best_epoch = 0\n            \n            for epoch in range(cfg.epochs):\n                print(f\"\\nEpoch {epoch+1}/{cfg.epochs}\")\n                \n                train_loss, train_auc = train_one_epoch(\n                    model, \n                    train_loader, \n                    optimizer, \n                    criterion, \n                    cfg.device,\n                    scheduler if isinstance(scheduler, lr_scheduler.OneCycleLR) else None\n                )\n                \n                val_loss, val_auc = validate(model, val_loader, criterion, cfg.device)\n    \n                if scheduler is not None and not isinstance(scheduler, lr_scheduler.OneCycleLR):\n                    if isinstance(scheduler, lr_scheduler.ReduceLROnPlateau):\n                        scheduler.step(val_loss)\n                    else:\n                        scheduler.step()\n    \n                print(f\"Train Loss: {train_loss:.4f}, Train AUC: {train_auc:.4f}\")\n                print(f\"Val Loss: {val_loss:.4f}, Val AUC: {val_auc:.4f}\")\n                \n                if val_auc > best_auc:\n                    best_auc = val_auc\n                    best_epoch = epoch + 1\n                    print(f\"New best AUC: {best_auc:.4f} at epoch {best_epoch}\")\n    \n                    torch.save({\n                        'model_state_dict': model.state_dict(),\n                        'optimizer_state_dict': optimizer.state_dict(),\n                        'scheduler_state_dict': scheduler.state_dict() if scheduler else None,\n                        'epoch': epoch,\n                        'val_auc': val_auc,\n                        'train_auc': train_auc,\n                        'cfg': cfg\n                    }, f\"model_fold{fold}.pth\")\n            \n            best_scores.append(best_auc)\n            print(f\"\\nBest AUC for fold {fold}: {best_auc:.4f} at epoch {best_epoch}\")\n            \n            # Clear memory\n            del model, optimizer, scheduler, train_loader, val_loader\n            torch.cuda.empty_cache()\n            gc.collect()\n        \n     \n        print(\"\\n\" + \"=\"*60)\n        print(\"Cross-Validation Results:\")\n        for fold, score in enumerate(best_scores):\n            print(f\"Fold {fold}: {score:.4f}\")\n        print(f\"Mean AUC: {np.mean(best_scores):.4f}\")\n        print(\"=\"*60)\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 19')\n    \n    \n    if __name__ == \"__main__\":\n       \n        print(\"Loading data...\")\n        train_df = pd.read_csv(cfg.train_csv)\n        taxonomy_df = pd.read_csv(cfg.taxonomy_csv)\n        \n        print(\"\\nStarting training...\")\n        run_training(train_df, cfg)\n        \n        print(\"\\nTraining complete!\")\n    \n    \n    end()","metadata":{"trusted":true,"jupyter":{"source_hidden":true},"_kg_hide-input":true,"_kg_hide-output":true,"execution":{"iopub.status.busy":"2025-04-07T13:36:36.559201Z","iopub.execute_input":"2025-04-07T13:36:36.559499Z","iopub.status.idle":"2025-04-07T13:36:36.836512Z","shell.execute_reply.started":"2025-04-07T13:36:36.559473Z","shell.execute_reply":"2025-04-07T13:36:36.835338Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"solution = 'SOLUTION_9'\n\nif  solution in ENSEMBLE_SOLUTIONS:\n                                                        \n    begin(solution)\n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 0')\n    \n    \n    # About this notebook\n    # The models used in this notebook were trained using [this training notebook](https://www.kaggle.com/code/kadircandrisolu/pytorch-training-birdclef2025-baseline/notebook?scriptVersionId=227610458) in debug mode. For better performance, you can set debug mode to False and experiment with different configuration parameters.\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1')\n    \n    \n    # Basic imports\n    import os\n    import logging\n    import gc\n    import time\n    from tqdm.auto import tqdm\n    import warnings\n    from pathlib import Path\n    import pickle\n    from typing import Dict, List, Tuple, Optional, Union\n    \n    # Data processing\n    import numpy as np\n    import pandas as pd\n    \n    # Audio processing\n    import librosa\n    import soundfile as sf\n    \n    # PyTorch\n    import torch\n    import torch.nn as nn\n    import torch.nn.functional as F\n    from torch.utils.data import Dataset, DataLoader\n    \n    # Model architecture\n    import timm\n    \n    # Ignore warnings\n    warnings.filterwarnings(\"ignore\")\n    logging.basicConfig(level=logging.ERROR)\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2')\n    \n    \n    class CFG:\n       \n        seed = 42\n        num_workers = 2\n        batch_size = 16  \n        \n        # Paths\n        model_dir = '/kaggle/input/birdclef2025_baseline_models/pytorch/default/1/'  # Directory where trained models are stored\n        test_soundscapes = '/kaggle/input/birdclef-2025/test_soundscapes/'\n        sample_submission_path = '/kaggle/input/birdclef-2025/sample_submission.csv'\n        taxonomy_path = '/kaggle/input/birdclef-2025/taxonomy.csv'\n        output_path = 'subm_9.csv' \n        \n        # Model Settings\n        model_name = 'efficientnet_b0'  \n        pretrained = False  \n        in_channels = 1 \n        \n        # Audio Settings\n        sample_rate = 32000  # Competition audio is 32kHz\n        duration = 5  # 5-second clips for prediction\n        melspec_parameters = {\n            'n_mels': 128,\n            'fmin': 20,\n            'fmax': 16000,\n        }\n        \n        # Inference Settings\n        device = 'cpu'  \n        use_ensemble = True \n        tta = False \n        folds_to_use = [0, 1]  \n        verbose = False \n        \n        # Time management\n        max_soundscapes_per_batch = 50  \n        time_limit = 85\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 3')\n    \n    \n    cfg = CFG()\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 4')\n    \n    \n    def set_seed(seed=42):\n        \n        np.random.seed(seed)\n        torch.manual_seed(seed)\n        torch.cuda.manual_seed(seed)\n        torch.backends.cudnn.deterministic = True\n        torch.backends.cudnn.benchmark = False\n        os.environ['PYTHONHASHSEED'] = str(seed)\n    \n    set_seed(cfg.seed)\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 5')\n    \n    \n    class BirdCLEFModel(nn.Module):\n        def __init__(self, cfg, num_classes):\n            super().__init__()\n            self.cfg = cfg\n            \n            self.backbone = timm.create_model(\n                cfg.model_name,\n                pretrained=cfg.pretrained,\n                in_chans=cfg.in_channels,\n                drop_rate=0.2,\n                drop_path_rate=0.2\n            )\n            \n            if 'efficientnet' in cfg.model_name:\n                backbone_out = self.backbone.classifier.in_features\n                self.backbone.classifier = nn.Identity()\n            elif 'resnet' in cfg.model_name:\n                backbone_out = self.backbone.fc.in_features\n                self.backbone.fc = nn.Identity()\n            else:\n                backbone_out = self.backbone.get_classifier().in_features\n                self.backbone.reset_classifier(0, '')\n            \n            self.pooling = nn.AdaptiveAvgPool2d(1)\n                \n            self.feat_dim = backbone_out\n            \n            self.classifier = nn.Linear(backbone_out, num_classes)\n                \n        def forward(self, x):\n            \n            features = self.backbone(x)\n            \n            if isinstance(features, dict): \n                features = features['features']\n                \n            if len(features.shape) == 4:  \n                features = self.pooling(features)\n                features = features.view(features.size(0), -1)\n            \n            logits = self.classifier(features)\n            \n            return logits\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 6')\n    \n    \n    class BirdCLEFInferenceDataset(Dataset):\n        def __init__(self, submission_df, soundscape_ids, cfg):\n    \n            self.submission_df = submission_df\n            self.cfg = cfg\n            \n            self.rows = self.submission_df[\n                self.submission_df['row_id'].str.split('_').str[1].isin(soundscape_ids)\n            ].copy()\n            \n            self.segments = []\n            for row_id in self.rows['row_id']:\n                parts = row_id.split('_')\n                soundscape_id = parts[1]\n                end_time = int(parts[2])\n                \n                self.segments.append({\n                    'soundscape_id': soundscape_id,\n                    'end_time': end_time,\n                    'row_id': row_id\n                })\n        \n        def __len__(self):\n            return len(self.segments)\n        \n        def __getitem__(self, idx):\n            segment = self.segments[idx]\n            soundscape_id = segment['soundscape_id']\n            end_time = segment['end_time']\n            start_time = end_time - 5  \n            \n            audio_path = os.path.join(self.cfg.test_soundscapes, f'soundscape_{soundscape_id}.ogg')\n            \n            try:\n                audio, sr = self.load_audio_segment(audio_path, start_time, end_time)\n                \n                melspec = self.audio_to_melspec(audio, sr)\n                \n                return {\n                    'melspec': torch.tensor(melspec, dtype=torch.float32),\n                    'row_id': segment['row_id']\n                }\n                \n            except Exception as e:\n                if self.cfg.verbose:\n                    print(f\"Error processing {audio_path} at segment {start_time}-{end_time}: {e}\")\n                \n                empty_melspec = np.zeros((1, self.cfg.melspec_parameters['n_mels'], \n                                         int(self.cfg.duration * self.cfg.sample_rate / 512 + 1)))\n                return {\n                    'melspec': torch.tensor(empty_melspec, dtype=torch.float32),\n                    'row_id': segment['row_id']\n                }\n        \n        def load_audio_segment(self, audio_path, start_time, end_time):\n        \n            start_sample = start_time * self.cfg.sample_rate\n            end_sample = end_time * self.cfg.sample_rate\n            \n            info = sf.info(audio_path)\n            frames_to_read = end_sample - start_sample\n            \n            audio, sr = sf.read(audio_path, start=start_sample, frames=frames_to_read)\n            \n            if len(audio.shape) > 1:\n                audio = audio.mean(axis=1)\n            \n            if sr != self.cfg.sample_rate:\n                audio = librosa.resample(audio, orig_sr=sr, target_sr=self.cfg.sample_rate)\n            \n            return audio, self.cfg.sample_rate\n        \n        def audio_to_melspec(self, audio, sr):\n     \n            melspec = librosa.feature.melspectrogram(\n                y=audio,\n                sr=sr,\n                n_fft=2048,\n                hop_length=512,\n                n_mels=self.cfg.melspec_parameters['n_mels'],\n                fmin=self.cfg.melspec_parameters['fmin'],\n                fmax=self.cfg.melspec_parameters['fmax']\n            )\n            \n            melspec = librosa.power_to_db(melspec)\n            \n            melspec = (melspec - melspec.min()) / (melspec.max() - melspec.min() + 1e-8)\n            \n            melspec = melspec[np.newaxis, :, :]\n            \n            return melspec\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 7')\n    \n    \n    def collate_fn(batch):\n    \n        batch = [item for item in batch if item is not None]\n        if len(batch) == 0:\n            return {}\n            \n        result = {key: [] for key in batch[0].keys()}\n        \n        for item in batch:\n            for key, value in item.items():\n                result[key].append(value)\n        \n        for key in result:\n            if key == 'row_id':\n                pass\n            elif key == 'melspec' and isinstance(result[key][0], torch.Tensor):\n                shapes = [t.shape for t in result[key]]\n                if len(set(str(s) for s in shapes)) == 1:  # All shapes are the same\n                    result[key] = torch.stack(result[key])\n        \n        return result\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 8')\n    \n    \n    # Inference Functions\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 9')\n    \n    \n    def load_trained_model(fold, cfg, num_classes):\n    \n        model = BirdCLEFModel(cfg, num_classes).to(cfg.device)\n        \n        try:\n            model_path = os.path.join(cfg.model_dir, f\"model_fold{fold}.pth\")\n            \n            if os.path.exists(model_path):\n                checkpoint = torch.load(model_path, map_location=cfg.device)\n                \n                if 'model_state_dict' in checkpoint:\n                    model.load_state_dict(checkpoint['model_state_dict'])\n                else:\n                    model.load_state_dict(checkpoint)\n                    \n                print(f\"Loaded model weights from fold {fold}\")\n                return model\n            else:\n                print(f\"Model weights for fold {fold} not found at {model_path}\")\n                return None\n                \n        except Exception as e:\n            print(f\"Error loading model for fold {fold}: {e}\")\n            return None\n    \n    def run_inference(models, submission_df, cfg):\n    \n        import sys\n        import os\n        from contextlib import contextmanager\n        \n        @contextmanager\n        def suppress_stderr():\n            old_stderr = sys.stderr\n            if not cfg.verbose:\n                sys.stderr = open(os.devnull, 'w')\n            try:\n                yield\n            finally:\n                if not cfg.verbose:\n                    sys.stderr.close()\n                sys.stderr = old_stderr\n    \n        start_time = time.time()\n        \n        results_df = submission_df.copy()\n        species_columns = [col for col in submission_df.columns if col != 'row_id']\n        \n        all_soundscape_ids = submission_df['row_id'].str.split('_').str[1].unique()\n        total_soundscapes = len(all_soundscape_ids)\n        \n        print(f\"Running inference on {total_soundscapes} soundscapes...\")\n        \n        for i in range(0, total_soundscapes, cfg.max_soundscapes_per_batch):\n            elapsed_minutes = (time.time() - start_time) / 60\n            if cfg.time_limit and elapsed_minutes > cfg.time_limit:\n                print(f\"Time limit reached ({elapsed_minutes:.2f} minutes). Stopping inference.\")\n                break\n                \n            batch_ids = all_soundscape_ids[i:i+cfg.max_soundscapes_per_batch]\n            print(f\"Processing batch {i//cfg.max_soundscapes_per_batch + 1}: {len(batch_ids)} soundscapes\")\n            \n            dataset = BirdCLEFInferenceDataset(submission_df, batch_ids, cfg)\n            \n            with suppress_stderr():\n                dataloader = DataLoader(\n                    dataset, \n                    batch_size=cfg.batch_size,\n                    shuffle=False,\n                    num_workers=cfg.num_workers,\n                    collate_fn=collate_fn\n                )\n                \n                batch_results = {}\n                \n                for batch in tqdm(dataloader, desc=\"Inference\"):\n                    if not batch: \n                        continue\n                        \n                    row_ids = batch['row_id']\n                    melspecs = batch['melspec']\n                    \n                    if isinstance(melspecs, list):\n                        for i, (melspec, row_id) in enumerate(zip(melspecs, row_ids)):\n                            melspec = melspec.unsqueeze(0).to(cfg.device)\n         \n                            model_preds = []\n                            for model in models:\n                                with torch.no_grad():\n                                    pred = torch.sigmoid(model(melspec)).cpu().numpy().squeeze()\n                                    model_preds.append(pred)\n                            \n                            avg_pred = np.mean(model_preds, axis=0)\n    \n                            batch_results[row_id] = avg_pred\n                    else:\n                        melspecs = melspecs.to(cfg.device)\n                        \n                        model_preds = []\n                        for model in models:\n                            with torch.no_grad():\n                                pred = torch.sigmoid(model(melspecs)).cpu().numpy()\n                                model_preds.append(pred)\n                        \n                        avg_pred = np.mean(model_preds, axis=0)\n                        \n                        for i, row_id in enumerate(row_ids):\n                            batch_results[row_id] = avg_pred[i]\n            \n            for row_id, preds in batch_results.items():\n                idx = results_df[results_df['row_id'] == row_id].index[0]\n                results_df.loc[idx, species_columns] = preds\n                \n            # Clear memory\n            del dataset, dataloader, batch_results\n            gc.collect()\n        \n        elapsed_minutes = (time.time() - start_time) / 60\n        print(f\"Inference completed in {elapsed_minutes:.2f} minutes\")\n        \n        return results_df\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 10')\n    \n    \n    def main():\n        import warnings\n        warnings.filterwarnings(\"ignore\")\n        \n        from contextlib import redirect_stderr\n        import os\n        import sys\n        \n        null_file = open(os.devnull, 'w') if not cfg.verbose else sys.stderr\n        \n        with redirect_stderr(null_file):\n            start_time = time.time()\n            \n            taxonomy_df = pd.read_csv(cfg.taxonomy_path)\n            num_classes = len(taxonomy_df)\n            print(f\"Number of classes: {num_classes}\")\n            \n            print(\"Loading submission template...\")\n            submission_df = pd.read_csv(cfg.sample_submission_path)\n            print(f\"Submission template shape: {submission_df.shape}\")\n    \n            print(\"\\n\" + \"=\"*60)\n            \n            print(\"Loading trained models...\")\n            models = []\n            for fold in cfg.folds_to_use:\n                model = load_trained_model(fold, cfg, num_classes)\n                if model is not None:\n                    models.append(model)\n            if len(models) == 0:\n                print(\"No models were loaded successfully. Exiting.\")\n                return\n            print(f\"Loaded {len(models)} models for inference.\")\n            \n            for model in models:\n                model.eval()\n    \n            print(\"\\n\" + \"=\"*60)\n            \n            print(\"Running inference...\")\n            results_df = run_inference(models, submission_df, cfg)\n            \n            results_df.to_csv(cfg.output_path, index=False)\n            \n            elapsed_minutes = (time.time() - start_time) / 60\n            print(f\"Inference completed in {elapsed_minutes:.2f} minutes\")\n            print(\"Submission saved\")\n        \n        # if not cfg.verbose:\n        #     null_file.close()\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 11')\n    \n    \n    if __name__ == \"__main__\":\n        main()\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 12')\n    \n    \n    end()","metadata":{"trusted":true,"_kg_hide-input":true,"execution":{"iopub.status.busy":"2025-04-07T13:36:36.837812Z","iopub.execute_input":"2025-04-07T13:36:36.838201Z","iopub.status.idle":"2025-04-07T13:36:36.880677Z","shell.execute_reply.started":"2025-04-07T13:36:36.838169Z","shell.execute_reply":"2025-04-07T13:36:36.879595Z"},"_kg_hide-output":true,"jupyter":{"source_hidden":true}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# [Kadircan İdrisoğlu](https://www.kaggle.com/kadircandrisolu)\n### 11. &nbsp; [EfficientNet B0 Pytorch [Inference]  . BirdCLEF'25](https://www.kaggle.com/code/kadircandrisolu/efficientnet-b0-pytorch-inference-birdclef-25/notebook)\n### 11.2 [EfficientNet B0 Pytorch [Train] &nbsp; &nbsp; &nbsp; &nbsp;. BirdCLEF'25](https://www.kaggle.com/code/kadircandrisolu/efficientnet-b0-pytorch-train-birdclef-25)\n### 11.3 [Transforming Audio-to-Mel Spec. &nbsp; . BirdCLEF'25](https://www.kaggle.com/code/kadircandrisolu/transforming-audio-to-mel-spec-birdclef-25)","metadata":{}},{"cell_type":"code","source":"solution = 'SOLUTION_11'\n\nif  solution in ENSEMBLE_SOLUTIONS:\n                                                            \n    begin(solution)\n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 0')\n\n\n    # **BirdCLEF 2025 Inference Notebook**\n    # This notebook runs inference on BirdCLEF 2025 test soundscapes and generates a submission file. \n    # It supports both single model inference and ensemble inference with multiple models. \n    # You can find the pre-processing and training processes in the following notebooks:\n    \n    # - [Transforming Audio-to-Mel Spec. | BirdCLEF'25]\n    #   (https://www.kaggle.com/code/kadircandrisolu/transforming-audio-to-mel-spec-birdclef-25) \n\n    # - [EfficientNet B0 Pytorch [Train] | BirdCLEF'25]\n    #   (https://www.kaggle.com/code/kadircandrisolu/efficientnet-b0-pytorch-train-birdclef-25)\n    \n    # **Features**\n    # - Audio Preprocessing\n    # - Test-Time Augmentation (TTA)\n    \n    \n    import os\n    import gc\n    import warnings\n    import logging\n    import time\n    import math\n    import cv2\n    from pathlib import Path\n    \n    import numpy as np\n    import pandas as pd\n    import librosa\n    import torch\n    import torch.nn as nn\n    import torch.nn.functional as F\n    import timm\n    from tqdm.auto import tqdm\n    \n    warnings.filterwarnings(\"ignore\")\n    logging.basicConfig(level=logging.ERROR)\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1')\n    \n    \n    class CFG:\n     \n        test_soundscapes = '/kaggle/input/birdclef-2025/test_soundscapes'\n        submission_csv = '/kaggle/input/birdclef-2025/sample_submission.csv'\n        taxonomy_csv = '/kaggle/input/birdclef-2025/taxonomy.csv'\n        model_path = '/kaggle/input/birdclef25-effnetb0-starter-weight'  \n        \n        # Audio parameters\n        FS = 32000  # Sample rate\n        WINDOW_SIZE = 5  # Size of each prediction window in seconds\n        \n        # Mel spectrogram parameters\n        N_FFT = 1024\n        HOP_LENGTH =   512\n        N_MELS     =   128\n        FMIN       =    50\n        FMAX       = 14000\n        TARGET_SHAPE = (256, 256)\n        \n        # Model parameters\n        model_name = 'efficientnet_b0'\n        in_channels = 1\n        device = 'cpu'  # Force CPU as per competition requirements\n        \n        # Inference parameters\n        batch_size = 16\n        use_tta = False  # Whether to use test-time augmentation\n        tta_count = 3   # Number of TTA variations if use_tta is True\n        threshold = 0.5\n        \n        # Ensemble - automatically find model files instead of specifying folds\n        use_specific_folds = False  # If False, use all found models\n        folds = [0, 1]  # Used only if use_specific_folds is True\n        \n        # Flag for debugging with a subset of soundscapes\n        debug = False\n        debug_count = 3\n    \n    cfg = CFG()\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2')\n    \n    \n    print(f\"Using device: {cfg.device}\")\n    print(f\"Loading taxonomy data...\")\n    taxonomy_df = pd.read_csv(cfg.taxonomy_csv)\n    species_ids = taxonomy_df['primary_label'].tolist()\n    num_classes = len(species_ids)\n    print(f\"Number of classes: {num_classes}\")\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 3')\n    \n    \n    class BirdCLEFModel(nn.Module):\n        def __init__(self, cfg, num_classes):\n            super().__init__()\n            self.cfg = cfg\n            \n            self.backbone = timm.create_model(\n                cfg.model_name,\n                pretrained=False,  # No need for pretrained weights during inference\n                in_chans=cfg.in_channels,\n                drop_rate=0.0,     # Disable dropout for inference\n                drop_path_rate=0.0\n            )\n            \n            if 'efficientnet' in cfg.model_name:\n                backbone_out = self.backbone.classifier.in_features\n                self.backbone.classifier = nn.Identity()\n            elif 'resnet' in cfg.model_name:\n                backbone_out = self.backbone.fc.in_features\n                self.backbone.fc = nn.Identity()\n            else:\n                backbone_out = self.backbone.get_classifier().in_features\n                self.backbone.reset_classifier(0, '')\n            \n            self.pooling = nn.AdaptiveAvgPool2d(1)\n            self.feat_dim = backbone_out\n            self.classifier = nn.Linear(backbone_out, num_classes)\n            \n        def forward(self, x):\n            features = self.backbone(x)\n            \n            if isinstance(features, dict):\n                features = features['features']\n                \n            if len(features.shape) == 4:\n                features = self.pooling(features)\n                features = features.view(features.size(0), -1)\n            \n            logits = self.classifier(features)\n            return logits\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 4')\n    \n    \n    def audio2melspec(audio_data, cfg):\n        \"\"\"Convert audio data to mel spectrogram\"\"\"\n        if np.isnan(audio_data).any():\n            mean_signal = np.nanmean(audio_data)\n            audio_data = np.nan_to_num(audio_data, nan=mean_signal)\n    \n        mel_spec = librosa.feature.melspectrogram(\n            y=audio_data,\n            sr=cfg.FS,\n            n_fft=cfg.N_FFT,\n            hop_length=cfg.HOP_LENGTH,\n            n_mels=cfg.N_MELS,\n            fmin=cfg.FMIN,\n            fmax=cfg.FMAX,\n            power=2.0\n        )\n    \n        mel_spec_db = librosa.power_to_db(mel_spec, ref=np.max)\n        mel_spec_norm = (mel_spec_db - mel_spec_db.min()) / (mel_spec_db.max() - mel_spec_db.min() + 1e-8)\n        \n        return mel_spec_norm\n    \n    def process_audio_segment(audio_data, cfg):\n        \"\"\"Process audio segment to get mel spectrogram\"\"\"\n        if len(audio_data) < cfg.FS * cfg.WINDOW_SIZE:\n            # Pad if segment is shorter than window size\n            audio_data = np.pad(audio_data, \n                              (0, cfg.FS * cfg.WINDOW_SIZE - len(audio_data)), \n                              mode='constant')\n        \n        mel_spec = audio2melspec(audio_data, cfg)\n        \n        # Resize if needed\n        if mel_spec.shape != cfg.TARGET_SHAPE:\n            mel_spec = cv2.resize(mel_spec, cfg.TARGET_SHAPE, interpolation=cv2.INTER_LINEAR)\n            \n        return mel_spec.astype(np.float32)\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 5')\n    \n    \n    def find_model_files(cfg):\n        \"\"\"\n        Find all .pth model files in the specified model directory\n        \"\"\"\n        model_files = []\n        \n        # Convert the model directory to a Path object\n        model_dir = Path(cfg.model_path)\n        \n        # Find all .pth files, checking all subdirectories\n        for path in model_dir.glob('**/*.pth'):\n            model_files.append(str(path))\n        \n        return model_files\n    \n    def load_models(cfg, num_classes):\n        \"\"\"\n        Load all found model files and prepare them for ensemble\n        \"\"\"\n        models = []\n        \n        # Find model files\n        model_files = find_model_files(cfg)\n        \n        if not model_files:\n            print(f\"Warning: No model files found under {cfg.model_path}!\")\n            return models\n        \n        print(f\"Found a total of {len(model_files)} model files.\")\n        \n        # If specific folds are requested, use only those folds\n        if cfg.use_specific_folds:\n            filtered_files = []\n            for fold in cfg.folds:\n                fold_files = [f for f in model_files if f\"fold{fold}\" in f]\n                filtered_files.extend(fold_files)\n            model_files = filtered_files\n            print(f\"Using {len(model_files)} model files for the specified folds ({cfg.folds}).\")\n        \n        # Load each model file\n        for model_path in model_files:\n            try:\n                print(f\"Loading model: {model_path}\")\n                checkpoint = torch.load(model_path, map_location=torch.device(cfg.device))\n                \n                model = BirdCLEFModel(cfg, num_classes)\n                model.load_state_dict(checkpoint['model_state_dict'])\n                model = model.to(cfg.device)\n                model.eval()\n                \n                models.append(model)\n            except Exception as e:\n                print(f\"Error loading model {model_path}: {e}\")\n        \n        return models\n    \n    def predict_on_spectrogram(audio_path, models, cfg, species_ids):\n        \"\"\"Process a single audio file and predict species presence for each 5-second segment\"\"\"\n        predictions = []\n        row_ids = []\n        soundscape_id = Path(audio_path).stem\n        \n        try:\n            print(f\"Processing {soundscape_id}\")\n            audio_data, _ = librosa.load(audio_path, sr=cfg.FS)\n            \n            # Calculate total number of complete 5-second segments\n            total_segments = int(len(audio_data) / (cfg.FS * cfg.WINDOW_SIZE))\n            \n            for segment_idx in range(total_segments):\n                # Extract current 5-second segment\n                start_sample = segment_idx * cfg.FS * cfg.WINDOW_SIZE\n                end_sample = start_sample + cfg.FS * cfg.WINDOW_SIZE\n                segment_audio = audio_data[start_sample:end_sample]\n                \n                # Calculate end time in seconds for row_id\n                end_time_sec = (segment_idx + 1) * cfg.WINDOW_SIZE\n                row_id = f\"{soundscape_id}_{end_time_sec}\"\n                row_ids.append(row_id)\n                \n                # Process the audio segment and get mel spectrogram\n                if cfg.use_tta:\n                    # Use test-time augmentation\n                    all_preds = []\n                    \n                    for tta_idx in range(cfg.tta_count):\n                        mel_spec = process_audio_segment(segment_audio, cfg)\n                        mel_spec = apply_tta(mel_spec, tta_idx)\n                        \n                        # Convert to tensor and add batch and channel dimensions\n                        mel_spec = torch.tensor(mel_spec, dtype=torch.float32).unsqueeze(0).unsqueeze(0)\n                        mel_spec = mel_spec.to(cfg.device)\n                        \n                        # Handle single model case without ensemble\n                        if len(models) == 1:\n                            with torch.no_grad():\n                                outputs = models[0](mel_spec)\n                                probs = torch.sigmoid(outputs).cpu().numpy().squeeze()\n                                all_preds.append(probs)\n                        else:\n                            # Get predictions from each model for ensemble\n                            segment_preds = []\n                            for model in models:\n                                with torch.no_grad():\n                                    outputs = model(mel_spec)\n                                    probs = torch.sigmoid(outputs).cpu().numpy().squeeze()\n                                    segment_preds.append(probs)\n                            \n                            # Average predictions from all models\n                            avg_preds = np.mean(segment_preds, axis=0)\n                            all_preds.append(avg_preds)\n                    \n                    # Average TTA predictions\n                    final_preds = np.mean(all_preds, axis=0)\n                else:\n                    # No TTA - just use the original spectrogram\n                    mel_spec = process_audio_segment(segment_audio, cfg)\n                    \n                    # Convert to tensor and add batch and channel dimensions\n                    mel_spec = torch.tensor(mel_spec, dtype=torch.float32).unsqueeze(0).unsqueeze(0)\n                    mel_spec = mel_spec.to(cfg.device)\n                    \n                    # Handle single model case without ensemble\n                    if len(models) == 1:\n                        with torch.no_grad():\n                            outputs = models[0](mel_spec)\n                            final_preds = torch.sigmoid(outputs).cpu().numpy().squeeze()\n                    else:\n                        # Get predictions from each model for ensemble\n                        segment_preds = []\n                        for model in models:\n                            with torch.no_grad():\n                                outputs = model(mel_spec)\n                                probs = torch.sigmoid(outputs).cpu().numpy().squeeze()\n                                segment_preds.append(probs)\n                        \n                        # Average predictions from all models\n                        final_preds = np.mean(segment_preds, axis=0)\n                        \n                predictions.append(final_preds)\n                \n        except Exception as e:\n            print(f\"Error processing {audio_path}: {e}\")\n        \n        return row_ids, predictions\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 6')\n    \n    \n    def apply_tta(spec, tta_idx):\n        \"\"\"Apply test-time augmentation\"\"\"\n        if tta_idx == 0:\n            # Original spectrogram\n            return spec\n        elif tta_idx == 1:\n            # Time shift (horizontal flip)\n            return np.flip(spec, axis=1)\n        elif tta_idx == 2:\n            # Frequency shift (vertical flip)\n            return np.flip(spec, axis=0)\n        else:\n            return spec\n    \n    def run_inference(cfg, models, species_ids):\n        \"\"\"Run inference on all test soundscapes\"\"\"\n        # Get list of test soundscapes\n        test_files = list(Path(cfg.test_soundscapes).glob('*.ogg'))\n        \n        if cfg.debug:\n            print(f\"Debug mode enabled, using only {cfg.debug_count} files\")\n            test_files = test_files[:cfg.debug_count]\n        \n        print(f\"Found {len(test_files)} test soundscapes\")\n        \n        # Initialize lists for predictions\n        all_row_ids = []\n        all_predictions = []\n        \n        # Process each soundscape\n        for audio_path in tqdm(test_files):\n            row_ids, predictions = predict_on_spectrogram(str(audio_path), models, cfg, species_ids)\n            all_row_ids.extend(row_ids)\n            all_predictions.extend(predictions)\n        \n        return all_row_ids, all_predictions\n    \n    def create_submission(row_ids, predictions, species_ids, cfg):\n        \"\"\"Create submission dataframe\"\"\"\n        print(\"Creating submission dataframe...\")\n        \n        # Create dictionary with row_ids\n        submission_dict = {'row_id': row_ids}\n        \n        # Add predictions for each species\n        for i, species in enumerate(species_ids):\n            submission_dict[species] = [pred[i] for pred in predictions]\n        \n        # Create dataframe\n        submission_df = pd.DataFrame(submission_dict)\n        \n        # Set row_id as index\n        submission_df.set_index('row_id', inplace=True)\n        \n        # Verify the submission format against sample submission\n        sample_sub = pd.read_csv(cfg.submission_csv, index_col='row_id')\n        \n        # Check if all species columns are present\n        missing_cols = set(sample_sub.columns) - set(submission_df.columns)\n        if missing_cols:\n            print(f\"Warning: Missing {len(missing_cols)} species columns in submission\")\n            # Add missing columns with zeros\n            for col in missing_cols:\n                submission_df[col] = 0.0\n        \n        # Ensure columns are in the same order as sample submission\n        submission_df = submission_df[sample_sub.columns]\n        \n        # Reset the index to include row_id as a column\n        submission_df = submission_df.reset_index()\n        \n        return submission_df\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 7')\n    \n    \n    def main():\n        start_time = time.time()\n        print(\"Starting BirdCLEF-2025 inference...\")\n        print(f\"TTA enabled: {cfg.use_tta} (variations: {cfg.tta_count if cfg.use_tta else 0})\")\n        \n        # Load models for ensemble\n        models = load_models(cfg, num_classes)\n        \n        if not models:\n            print(\"No models found! Please check model paths.\")\n            return\n        \n        print(f\"Model usage: {'Single model' if len(models) == 1 else f'Ensemble of {len(models)} models'}\")\n        \n        # Run inference on test soundscapes\n        row_ids, predictions = run_inference(cfg, models, species_ids)\n        \n        # Create submission dataframe\n        submission_df = create_submission(row_ids, predictions, species_ids, cfg)\n        \n        # Save submission file\n        submission_path = 'subm_11.csv'\n        submission_df.to_csv(submission_path, index=False)\n        print(f\"Submission saved to {submission_path}\")\n        \n        end_time = time.time()\n        print(f\"Inference completed in {(end_time - start_time)/60:.2f} minutes\")\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 8')\n    \n    \n    if __name__ == \"__main__\":\n        main()\n    \n    \n    end()","metadata":{"trusted":true,"_kg_hide-input":true,"_kg_hide-output":true,"jupyter":{"source_hidden":true},"execution":{"iopub.status.busy":"2025-04-07T13:36:36.881833Z","iopub.execute_input":"2025-04-07T13:36:36.882164Z","iopub.status.idle":"2025-04-07T13:36:36.922838Z","shell.execute_reply.started":"2025-04-07T13:36:36.882138Z","shell.execute_reply":"2025-04-07T13:36:36.921944Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"solution = 'SOLUTION_11.2'\n\nif  solution in ENSEMBLE_SOLUTIONS:\n                                                            \n    begin(solution)\n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 0')\n    \n    \n    # **BirdCLEF 2025 Training Notebook**\n    # \n    # This is a baseline training pipeline for BirdCLEF 2025 using EfficientNetB0 with PyTorch and Timm(for pretrained EffNet). You can check inference and preprocessing notebooks in the following links: \n    # \n    # - [EfficientNet B0 Pytorch [Inference] | BirdCLEF'25](https://www.kaggle.com/code/kadircandrisolu/efficientnet-b0-pytorch-inference-birdclef-25)\n    # \n    #   \n    # - [Transforming Audio-to-Mel Spec. | BirdCLEF'25](https://www.kaggle.com/code/kadircandrisolu/transforming-audio-to-mel-spec-birdclef-25)  \n    # \n    # Note that by default this notebook is in Debug Mode, so it will only train the model with 2 epochs, but the [weight](https://www.kaggle.com/datasets/kadircandrisolu/birdclef25-effnetb0-starter-weight) I used in the inference notebook was obtained after 10 epochs of training.\n    # \n    # **Features**\n    # * Implement with Pytorch and Timm\n    # * Flexible audio processing with both pre-computed and on-the-fly mel spectrograms\n    # * Stratified 5-fold cross-validation with ensemble capability\n    # * Mixup training for improved generalization\n    # * Spectrogram augmentations (time/frequency masking, brightness adjustment)\n    # * AdamW optimizer with Cosine Annealing LR scheduling\n    # * Debug mode for quick experimentation with smaller datasets\n    # \n    # **Pre-computed Spectrograms**\n    # For faster training, you can use pre-computed mel spectrograms from [this dataset](https://www.kaggle.com/datasets/kadircandrisolu/birdclef25-mel-spectrograms) by setting `LOAD_DATA = True`\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1')\n    \n    \n    # Libraries\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2')\n    \n    \n    import os\n    import logging\n    import random\n    import gc\n    import time\n    import cv2\n    import math\n    import warnings\n    from pathlib import Path\n    \n    import numpy as np\n    import pandas as pd\n    from sklearn.model_selection import StratifiedKFold\n    from sklearn.metrics import roc_auc_score\n    import librosa\n    \n    import torch\n    import torch.nn as nn\n    import torch.nn.functional as F\n    import torch.optim as optim\n    from torch.optim import lr_scheduler\n    from torch.utils.data import Dataset, DataLoader\n    \n    import matplotlib.pyplot as plt\n    import seaborn as sns\n    from tqdm.auto import tqdm\n    \n    import timm\n    \n    warnings.filterwarnings(\"ignore\")\n    logging.basicConfig(level=logging.ERROR)\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 3')\n    \n    \n    # Configuration\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 4')\n    \n    \n    class CFG:\n        \n        seed = 42\n        debug = True  \n        apex = False\n        print_freq = 100\n        num_workers = 2\n        \n        OUTPUT_DIR = '/kaggle/working/'\n    \n        train_datadir = '/kaggle/input/birdclef-2025/train_audio'\n        train_csv = '/kaggle/input/birdclef-2025/train.csv'\n        test_soundscapes = '/kaggle/input/birdclef-2025/test_soundscapes'\n        submission_csv = '/kaggle/input/birdclef-2025/sample_submission.csv'\n        taxonomy_csv = '/kaggle/input/birdclef-2025/taxonomy.csv'\n    \n        spectrogram_npy = '/kaggle/input/birdclef25-mel-spectrograms/birdclef2025_melspec_5sec_256_256.npy'\n     \n        model_name = 'efficientnet_b0'  \n        pretrained = True\n        in_channels = 1\n    \n        LOAD_DATA = True  \n        FS = 32000\n        TARGET_DURATION = 5.0\n        TARGET_SHAPE = (256, 256)\n        \n        N_FFT = 1024\n        HOP_LENGTH = 512\n        N_MELS = 128\n        FMIN = 50\n        FMAX = 14000\n        \n        device = 'cuda' if torch.cuda.is_available() else 'cpu'\n        epochs = 10  \n        batch_size = 32  \n        criterion = 'BCEWithLogitsLoss'\n    \n        n_fold = 5\n        selected_folds = [0, 1, 2, 3, 4]   \n    \n        optimizer = 'AdamW'\n        lr = 5e-4 \n        weight_decay = 1e-5\n      \n        scheduler = 'CosineAnnealingLR'\n        min_lr = 1e-6\n        T_max = epochs\n    \n        aug_prob = 0.5  \n        mixup_alpha = 0.5  \n        \n        def update_debug_settings(self):\n            if self.debug:\n                self.epochs = 2\n                self.selected_folds = [0]\n    \n    cfg = CFG()\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 5')\n    \n    \n    # Utilities\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 6')\n    \n    \n    def set_seed(seed=42):\n        \"\"\"\n        Set seed for reproducibility\n        \"\"\"\n        random.seed(seed)\n        os.environ[\"PYTHONHASHSEED\"] = str(seed)\n        np.random.seed(seed)\n        torch.manual_seed(seed)\n        torch.cuda.manual_seed(seed)\n        torch.cuda.manual_seed_all(seed)\n        torch.backends.cudnn.deterministic = True\n        torch.backends.cudnn.benchmark = False\n    \n    set_seed(cfg.seed)\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 7')\n    \n    \n    # Pre-processing\n    # These functions handle the transformation of audio files to mel spectrograms for model input, with flexibility controlled by the `LOAD_DATA` parameter. The process involves either loading pre-computed spectrograms from this [dataset](https://www.kaggle.com/datasets/kadircandrisolu/birdclef25-mel-spectrograms) (when `LOAD_DATA=True`) or dynamically generating them (when `LOAD_DATA=False`), transforming audio data into spectrogram representations, and preparing it for the neural network.\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 8')\n    \n    \n    def audio2melspec(audio_data, cfg):\n        \"\"\"Convert audio data to mel spectrogram\"\"\"\n        if np.isnan(audio_data).any():\n            mean_signal = np.nanmean(audio_data)\n            audio_data = np.nan_to_num(audio_data, nan=mean_signal)\n    \n        mel_spec = librosa.feature.melspectrogram(\n            y=audio_data,\n            sr=cfg.FS,\n            n_fft=cfg.N_FFT,\n            hop_length=cfg.HOP_LENGTH,\n            n_mels=cfg.N_MELS,\n            fmin=cfg.FMIN,\n            fmax=cfg.FMAX,\n            power=2.0\n        )\n    \n        mel_spec_db = librosa.power_to_db(mel_spec, ref=np.max)\n        mel_spec_norm = (mel_spec_db - mel_spec_db.min()) / (mel_spec_db.max() - mel_spec_db.min() + 1e-8)\n        \n        return mel_spec_norm\n    \n    def process_audio_file(audio_path, cfg):\n        \"\"\"Process a single audio file to get the mel spectrogram\"\"\"\n        try:\n            audio_data, _ = librosa.load(audio_path, sr=cfg.FS)\n    \n            target_samples = int(cfg.TARGET_DURATION * cfg.FS)\n    \n            if len(audio_data) < target_samples:\n                n_copy = math.ceil(target_samples / len(audio_data))\n                if n_copy > 1:\n                    audio_data = np.concatenate([audio_data] * n_copy)\n    \n            # Extract center 5 seconds\n            start_idx = max(0, int(len(audio_data) / 2 - target_samples / 2))\n            end_idx = min(len(audio_data), start_idx + target_samples)\n            center_audio = audio_data[start_idx:end_idx]\n    \n            if len(center_audio) < target_samples:\n                center_audio = np.pad(center_audio, \n                                     (0, target_samples - len(center_audio)), \n                                     mode='constant')\n    \n            mel_spec = audio2melspec(center_audio, cfg)\n            \n            if mel_spec.shape != cfg.TARGET_SHAPE:\n                mel_spec = cv2.resize(mel_spec, cfg.TARGET_SHAPE, interpolation=cv2.INTER_LINEAR)\n    \n            return mel_spec.astype(np.float32)\n            \n        except Exception as e:\n            print(f\"Error processing {audio_path}: {e}\")\n            return None\n    \n    def generate_spectrograms(df, cfg):\n        \"\"\"Generate spectrograms from audio files\"\"\"\n        print(\"Generating mel spectrograms from audio files...\")\n        start_time = time.time()\n    \n        all_bird_data = {}\n        errors = []\n    \n        for i, row in tqdm(df.iterrows(), total=len(df)):\n            if cfg.debug and i >= 1000:\n                break\n            \n            try:\n                samplename = row['samplename']\n                filepath = row['filepath']\n                \n                mel_spec = process_audio_file(filepath, cfg)\n                \n                if mel_spec is not None:\n                    all_bird_data[samplename] = mel_spec\n                \n            except Exception as e:\n                print(f\"Error processing {row.filepath}: {e}\")\n                errors.append((row.filepath, str(e)))\n    \n        end_time = time.time()\n        print(f\"Processing completed in {end_time - start_time:.2f} seconds\")\n        print(f\"Successfully processed {len(all_bird_data)} files out of {len(df)}\")\n        print(f\"Failed to process {len(errors)} files\")\n        \n        return all_bird_data\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 9')\n    \n    \n    # Dataset Preparation and Data Augmentations\n    # We'll convert audio to mel spectrograms and apply random augmentations with 50% probability each - including time stretching, pitch shifting, and volume adjustments. This randomized approach creates diverse training samples from the same audio files\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 10')\n    \n    \n    class BirdCLEFDatasetFromNPY(Dataset):\n        def __init__(self, df, cfg, spectrograms=None, mode=\"train\"):\n            self.df = df\n            self.cfg = cfg\n            self.mode = mode\n    \n            self.spectrograms = spectrograms\n            \n            taxonomy_df = pd.read_csv(self.cfg.taxonomy_csv)\n            self.species_ids = taxonomy_df['primary_label'].tolist()\n            self.num_classes = len(self.species_ids)\n            self.label_to_idx = {label: idx for idx, label in enumerate(self.species_ids)}\n    \n            if 'filepath' not in self.df.columns:\n                self.df['filepath'] = self.cfg.train_datadir + '/' + self.df.filename\n            \n            if 'samplename' not in self.df.columns:\n                self.df['samplename'] = self.df.filename.map(lambda x: x.split('/')[0] + '-' + x.split('/')[-1].split('.')[0])\n    \n            sample_names = set(self.df['samplename'])\n            if self.spectrograms:\n                found_samples = sum(1 for name in sample_names if name in self.spectrograms)\n                print(f\"Found {found_samples} matching spectrograms for {mode} dataset out of {len(self.df)} samples\")\n            \n            if cfg.debug:\n                self.df = self.df.sample(min(1000, len(self.df)), random_state=cfg.seed).reset_index(drop=True)\n        \n        def __len__(self):\n            return len(self.df)\n        \n        def __getitem__(self, idx):\n            row = self.df.iloc[idx]\n            samplename = row['samplename']\n            spec = None\n    \n            if self.spectrograms and samplename in self.spectrograms:\n                spec = self.spectrograms[samplename]\n            elif not self.cfg.LOAD_DATA:\n                spec = process_audio_file(row['filepath'], self.cfg)\n    \n            if spec is None:\n                spec = np.zeros(self.cfg.TARGET_SHAPE, dtype=np.float32)\n                if self.mode == \"train\":  # Only print warning during training\n                    print(f\"Warning: Spectrogram for {samplename} not found and could not be generated\")\n    \n            spec = torch.tensor(spec, dtype=torch.float32).unsqueeze(0)  # Add channel dimension\n    \n            if self.mode == \"train\" and random.random() < self.cfg.aug_prob:\n                spec = self.apply_spec_augmentations(spec)\n            \n            target = self.encode_label(row['primary_label'])\n            \n            if 'secondary_labels' in row and row['secondary_labels'] not in [[''], None, np.nan]:\n                if isinstance(row['secondary_labels'], str):\n                    secondary_labels = eval(row['secondary_labels'])\n                else:\n                    secondary_labels = row['secondary_labels']\n                \n                for label in secondary_labels:\n                    if label in self.label_to_idx:\n                        target[self.label_to_idx[label]] = 1.0\n            \n            return {\n                'melspec': spec, \n                'target': torch.tensor(target, dtype=torch.float32),\n                'filename': row['filename']\n            }\n        \n        def apply_spec_augmentations(self, spec):\n            \"\"\"Apply augmentations to spectrogram\"\"\"\n        \n            # Time masking (horizontal stripes)\n            if random.random() < 0.5:\n                num_masks = random.randint(1, 3)\n                for _ in range(num_masks):\n                    width = random.randint(5, 20)\n                    start = random.randint(0, spec.shape[2] - width)\n                    spec[0, :, start:start+width] = 0\n            \n            # Frequency masking (vertical stripes)\n            if random.random() < 0.5:\n                num_masks = random.randint(1, 3)\n                for _ in range(num_masks):\n                    height = random.randint(5, 20)\n                    start = random.randint(0, spec.shape[1] - height)\n                    spec[0, start:start+height, :] = 0\n            \n            # Random brightness/contrast\n            if random.random() < 0.5:\n                gain = random.uniform(0.8, 1.2)\n                bias = random.uniform(-0.1, 0.1)\n                spec = spec * gain + bias\n                spec = torch.clamp(spec, 0, 1) \n                \n            return spec\n        \n        def encode_label(self, label):\n            \"\"\"Encode label to one-hot vector\"\"\"\n            target = np.zeros(self.num_classes)\n            if label in self.label_to_idx:\n                target[self.label_to_idx[label]] = 1.0\n            return target\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 11')\n    \n    \n    def collate_fn(batch):\n        \"\"\"Custom collate function to handle different sized spectrograms\"\"\"\n        batch = [item for item in batch if item is not None]\n        if len(batch) == 0:\n            return {}\n            \n        result = {key: [] for key in batch[0].keys()}\n        \n        for item in batch:\n            for key, value in item.items():\n                result[key].append(value)\n        \n        for key in result:\n            if key == 'target' and isinstance(result[key][0], torch.Tensor):\n                result[key] = torch.stack(result[key])\n            elif key == 'melspec' and isinstance(result[key][0], torch.Tensor):\n                shapes = [t.shape for t in result[key]]\n                if len(set(str(s) for s in shapes)) == 1:\n                    result[key] = torch.stack(result[key])\n        \n        return result\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 12')\n    \n    \n    # Model Definition\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 13')\n    \n    \n    class BirdCLEFModel(nn.Module):\n        def __init__(self, cfg):\n            super().__init__()\n            self.cfg = cfg\n            \n            taxonomy_df = pd.read_csv(cfg.taxonomy_csv)\n            cfg.num_classes = len(taxonomy_df)\n            \n            self.backbone = timm.create_model(\n                cfg.model_name,\n                pretrained=cfg.pretrained,\n                in_chans=cfg.in_channels,\n                drop_rate=0.2,\n                drop_path_rate=0.2\n            )\n            \n            if 'efficientnet' in cfg.model_name:\n                backbone_out = self.backbone.classifier.in_features\n                self.backbone.classifier = nn.Identity()\n            elif 'resnet' in cfg.model_name:\n                backbone_out = self.backbone.fc.in_features\n                self.backbone.fc = nn.Identity()\n            else:\n                backbone_out = self.backbone.get_classifier().in_features\n                self.backbone.reset_classifier(0, '')\n            \n            self.pooling = nn.AdaptiveAvgPool2d(1)\n                \n            self.feat_dim = backbone_out\n            \n            self.classifier = nn.Linear(backbone_out, cfg.num_classes)\n            \n            self.mixup_enabled = hasattr(cfg, 'mixup_alpha') and cfg.mixup_alpha > 0\n            if self.mixup_enabled:\n                self.mixup_alpha = cfg.mixup_alpha\n                \n        def forward(self, x, targets=None):\n        \n            if self.training and self.mixup_enabled and targets is not None:\n                mixed_x, targets_a, targets_b, lam = self.mixup_data(x, targets)\n                x = mixed_x\n            else:\n                targets_a, targets_b, lam = None, None, None\n            \n            features = self.backbone(x)\n            \n            if isinstance(features, dict):\n                features = features['features']\n                \n            if len(features.shape) == 4:\n                features = self.pooling(features)\n                features = features.view(features.size(0), -1)\n            \n            logits = self.classifier(features)\n            \n            if self.training and self.mixup_enabled and targets is not None:\n                loss = self.mixup_criterion(F.binary_cross_entropy_with_logits, \n                                           logits, targets_a, targets_b, lam)\n                return logits, loss\n                \n            return logits\n        \n        def mixup_data(self, x, targets):\n            \"\"\"Applies mixup to the data batch\"\"\"\n            batch_size = x.size(0)\n    \n            lam = np.random.beta(self.mixup_alpha, self.mixup_alpha)\n    \n            indices = torch.randperm(batch_size).to(x.device)\n    \n            mixed_x = lam * x + (1 - lam) * x[indices]\n            \n            return mixed_x, targets, targets[indices], lam\n        \n        def mixup_criterion(self, criterion, pred, y_a, y_b, lam):\n            \"\"\"Applies mixup to the loss function\"\"\"\n            return lam * criterion(pred, y_a) + (1 - lam) * criterion(pred, y_b)\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 14')\n    \n    \n    # Training Utilities\n    # We are configuring our optimization strategy with the AdamW optimizer, cosine scheduling, and the BCEWithLogitsLoss criterion.\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 15')\n    \n    \n    def get_optimizer(model, cfg):\n      \n        if cfg.optimizer == 'Adam':\n            optimizer = optim.Adam(\n                model.parameters(),\n                lr=cfg.lr,\n                weight_decay=cfg.weight_decay\n            )\n        elif cfg.optimizer == 'AdamW':\n            optimizer = optim.AdamW(\n                model.parameters(),\n                lr=cfg.lr,\n                weight_decay=cfg.weight_decay\n            )\n        elif cfg.optimizer == 'SGD':\n            optimizer = optim.SGD(\n                model.parameters(),\n                lr=cfg.lr,\n                momentum=0.9,\n                weight_decay=cfg.weight_decay\n            )\n        else:\n            raise NotImplementedError(f\"Optimizer {cfg.optimizer} not implemented\")\n            \n        return optimizer\n    \n    def get_scheduler(optimizer, cfg):\n       \n        if cfg.scheduler == 'CosineAnnealingLR':\n            scheduler = lr_scheduler.CosineAnnealingLR(\n                optimizer,\n                T_max=cfg.T_max,\n                eta_min=cfg.min_lr\n            )\n        elif cfg.scheduler == 'ReduceLROnPlateau':\n            scheduler = lr_scheduler.ReduceLROnPlateau(\n                optimizer,\n                mode='min',\n                factor=0.5,\n                patience=2,\n                min_lr=cfg.min_lr,\n                verbose=True\n            )\n        elif cfg.scheduler == 'StepLR':\n            scheduler = lr_scheduler.StepLR(\n                optimizer,\n                step_size=cfg.epochs // 3,\n                gamma=0.5\n            )\n        elif cfg.scheduler == 'OneCycleLR':\n            scheduler = None  \n        else:\n            scheduler = None\n            \n        return scheduler\n    \n    def get_criterion(cfg):\n     \n        if cfg.criterion == 'BCEWithLogitsLoss':\n            criterion = nn.BCEWithLogitsLoss()\n        else:\n            raise NotImplementedError(f\"Criterion {cfg.criterion} not implemented\")\n            \n        return criterion\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 16')\n    \n    \n    # Training Loop\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 17')\n    \n    \n    def train_one_epoch(model, loader, optimizer, criterion, device, scheduler=None):\n        \n        model.train()\n        losses = []\n        all_targets = []\n        all_outputs = []\n        \n        pbar = tqdm(enumerate(loader), total=len(loader), desc=\"Training\")\n        \n        for step, batch in pbar:\n        \n            if isinstance(batch['melspec'], list):\n                batch_outputs = []\n                batch_losses = []\n                \n                for i in range(len(batch['melspec'])):\n                    inputs = batch['melspec'][i].unsqueeze(0).to(device)\n                    target = batch['target'][i].unsqueeze(0).to(device)\n                    \n                    optimizer.zero_grad()\n                    output = model(inputs)\n                    loss = criterion(output, target)\n                    loss.backward()\n                    \n                    batch_outputs.append(output.detach().cpu())\n                    batch_losses.append(loss.item())\n                \n                optimizer.step()\n                outputs = torch.cat(batch_outputs, dim=0).numpy()\n                loss = np.mean(batch_losses)\n                targets = batch['target'].numpy()\n                \n            else:\n                inputs = batch['melspec'].to(device)\n                targets = batch['target'].to(device)\n                \n                optimizer.zero_grad()\n                outputs = model(inputs)\n                \n                if isinstance(outputs, tuple):\n                    outputs, loss = outputs  \n                else:\n                    loss = criterion(outputs, targets)\n                    \n                loss.backward()\n                optimizer.step()\n                \n                outputs = outputs.detach().cpu().numpy()\n                targets = targets.detach().cpu().numpy()\n            \n            if scheduler is not None and isinstance(scheduler, lr_scheduler.OneCycleLR):\n                scheduler.step()\n                \n            all_outputs.append(outputs)\n            all_targets.append(targets)\n            losses.append(loss if isinstance(loss, float) else loss.item())\n            \n            pbar.set_postfix({\n                'train_loss': np.mean(losses[-10:]) if losses else 0,\n                'lr': optimizer.param_groups[0]['lr']\n            })\n        \n        all_outputs = np.concatenate(all_outputs)\n        all_targets = np.concatenate(all_targets)\n        auc = calculate_auc(all_targets, all_outputs)\n        avg_loss = np.mean(losses)\n        \n        return avg_loss, auc\n    \n    def validate(model, loader, criterion, device):\n       \n        model.eval()\n        losses = []\n        all_targets = []\n        all_outputs = []\n        \n        with torch.no_grad():\n            for batch in tqdm(loader, desc=\"Validation\"):\n                if isinstance(batch['melspec'], list):\n                    batch_outputs = []\n                    batch_losses = []\n                    \n                    for i in range(len(batch['melspec'])):\n                        inputs = batch['melspec'][i].unsqueeze(0).to(device)\n                        target = batch['target'][i].unsqueeze(0).to(device)\n                        \n                        output = model(inputs)\n                        loss = criterion(output, target)\n                        \n                        batch_outputs.append(output.detach().cpu())\n                        batch_losses.append(loss.item())\n                    \n                    outputs = torch.cat(batch_outputs, dim=0).numpy()\n                    loss = np.mean(batch_losses)\n                    targets = batch['target'].numpy()\n                    \n                else:\n                    inputs = batch['melspec'].to(device)\n                    targets = batch['target'].to(device)\n                    \n                    outputs = model(inputs)\n                    loss = criterion(outputs, targets)\n                    \n                    outputs = outputs.detach().cpu().numpy()\n                    targets = targets.detach().cpu().numpy()\n                \n                all_outputs.append(outputs)\n                all_targets.append(targets)\n                losses.append(loss if isinstance(loss, float) else loss.item())\n        \n        all_outputs = np.concatenate(all_outputs)\n        all_targets = np.concatenate(all_targets)\n        \n        auc = calculate_auc(all_targets, all_outputs)\n        avg_loss = np.mean(losses)\n        \n        return avg_loss, auc\n    \n    def calculate_auc(targets, outputs):\n      \n        num_classes = targets.shape[1]\n        aucs = []\n        \n        probs = 1 / (1 + np.exp(-outputs))\n        \n        for i in range(num_classes):\n            \n            if np.sum(targets[:, i]) > 0:\n                class_auc = roc_auc_score(targets[:, i], probs[:, i])\n                aucs.append(class_auc)\n        \n        return np.mean(aucs) if aucs else 0.0\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 18')\n    \n    \n    # Training!\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 19')\n    \n    \n    def run_training(df, cfg):\n        \"\"\"Training function that can either use pre-computed spectrograms or generate them on-the-fly\"\"\"\n    \n        taxonomy_df = pd.read_csv(cfg.taxonomy_csv)\n        species_ids = taxonomy_df['primary_label'].tolist()\n        cfg.num_classes = len(species_ids)\n        \n        if cfg.debug:\n            cfg.update_debug_settings()\n    \n        spectrograms = None\n        if cfg.LOAD_DATA:\n            print(\"Loading pre-computed mel spectrograms from NPY file...\")\n            try:\n                spectrograms = np.load(cfg.spectrogram_npy, allow_pickle=True).item()\n                print(f\"Loaded {len(spectrograms)} pre-computed mel spectrograms\")\n            except Exception as e:\n                print(f\"Error loading pre-computed spectrograms: {e}\")\n                print(\"Will generate spectrograms on-the-fly instead.\")\n                cfg.LOAD_DATA = False\n        \n        if not cfg.LOAD_DATA:\n            print(\"Will generate spectrograms on-the-fly during training.\")\n            if 'filepath' not in df.columns:\n                df['filepath'] = cfg.train_datadir + '/' + df.filename\n            if 'samplename' not in df.columns:\n                df['samplename'] = df.filename.map(lambda x: x.split('/')[0] + '-' + x.split('/')[-1].split('.')[0])\n            \n        skf = StratifiedKFold(n_splits=cfg.n_fold, shuffle=True, random_state=cfg.seed)\n        \n        best_scores = []\n        \n        for fold, (train_idx, val_idx) in enumerate(skf.split(df, df['primary_label'])):\n            if fold not in cfg.selected_folds:\n                continue\n                \n            print(f'\\n{\"=\"*30} Fold {fold} {\"=\"*30}')\n            \n            train_df = df.iloc[train_idx].reset_index(drop=True)\n            val_df = df.iloc[val_idx].reset_index(drop=True)\n            \n            print(f'Training set: {len(train_df)} samples')\n            print(f'Validation set: {len(val_df)} samples')\n            \n            train_dataset = BirdCLEFDatasetFromNPY(train_df, cfg, spectrograms=spectrograms, mode='train')\n            val_dataset = BirdCLEFDatasetFromNPY(val_df, cfg, spectrograms=spectrograms, mode='valid')\n            \n            train_loader = DataLoader(\n                train_dataset, \n                batch_size=cfg.batch_size, \n                shuffle=True, \n                num_workers=cfg.num_workers,\n                pin_memory=True,\n                collate_fn=collate_fn,\n                drop_last=True\n            )\n            \n            val_loader = DataLoader(\n                val_dataset, \n                batch_size=cfg.batch_size, \n                shuffle=False, \n                num_workers=cfg.num_workers,\n                pin_memory=True,\n                collate_fn=collate_fn\n            )\n            \n            model = BirdCLEFModel(cfg).to(cfg.device)\n            optimizer = get_optimizer(model, cfg)\n            criterion = get_criterion(cfg)\n            \n            if cfg.scheduler == 'OneCycleLR':\n                scheduler = lr_scheduler.OneCycleLR(\n                    optimizer,\n                    max_lr=cfg.lr,\n                    steps_per_epoch=len(train_loader),\n                    epochs=cfg.epochs,\n                    pct_start=0.1\n                )\n            else:\n                scheduler = get_scheduler(optimizer, cfg)\n            \n            best_auc = 0\n            best_epoch = 0\n            \n            for epoch in range(cfg.epochs):\n                print(f\"\\nEpoch {epoch+1}/{cfg.epochs}\")\n                \n                train_loss, train_auc = train_one_epoch(\n                    model, \n                    train_loader, \n                    optimizer, \n                    criterion, \n                    cfg.device,\n                    scheduler if isinstance(scheduler, lr_scheduler.OneCycleLR) else None\n                )\n                \n                val_loss, val_auc = validate(model, val_loader, criterion, cfg.device)\n    \n                if scheduler is not None and not isinstance(scheduler, lr_scheduler.OneCycleLR):\n                    if isinstance(scheduler, lr_scheduler.ReduceLROnPlateau):\n                        scheduler.step(val_loss)\n                    else:\n                        scheduler.step()\n    \n                print(f\"Train Loss: {train_loss:.4f}, Train AUC: {train_auc:.4f}\")\n                print(f\"Val Loss: {val_loss:.4f}, Val AUC: {val_auc:.4f}\")\n                \n                if val_auc > best_auc:\n                    best_auc = val_auc\n                    best_epoch = epoch + 1\n                    print(f\"New best AUC: {best_auc:.4f} at epoch {best_epoch}\")\n    \n                    torch.save({\n                        'model_state_dict': model.state_dict(),\n                        'optimizer_state_dict': optimizer.state_dict(),\n                        'scheduler_state_dict': scheduler.state_dict() if scheduler else None,\n                        'epoch': epoch,\n                        'val_auc': val_auc,\n                        'train_auc': train_auc,\n                        'cfg': cfg\n                    }, f\"model_fold{fold}.pth\")\n            \n            best_scores.append(best_auc)\n            print(f\"\\nBest AUC for fold {fold}: {best_auc:.4f} at epoch {best_epoch}\")\n            \n            # Clear memory\n            del model, optimizer, scheduler, train_loader, val_loader\n            torch.cuda.empty_cache()\n            gc.collect()\n        \n        print(\"\\n\" + \"=\"*60)\n        print(\"Cross-Validation Results:\")\n        for fold, score in enumerate(best_scores):\n            print(f\"Fold {cfg.selected_folds[fold]}: {score:.4f}\")\n        print(f\"Mean AUC: {np.mean(best_scores):.4f}\")\n        print(\"=\"*60)\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 20')\n    \n    \n    if __name__ == \"__main__\":\n        import time\n        \n        print(\"\\nLoading training data...\")\n        train_df = pd.read_csv(cfg.train_csv)\n        taxonomy_df = pd.read_csv(cfg.taxonomy_csv)\n    \n        print(\"\\nStarting training...\")\n        print(f\"LOAD_DATA is set to {cfg.LOAD_DATA}\")\n        if cfg.LOAD_DATA:\n            print(\"Using pre-computed mel spectrograms from NPY file\")\n        else:\n            print(\"Will generate spectrograms on-the-fly during training\")\n        \n        run_training(train_df, cfg)\n        \n        print(\"\\nTraining complete!\")\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 21')\n    \n    \n    end()","metadata":{"trusted":true,"_kg_hide-input":true,"_kg_hide-output":true,"jupyter":{"source_hidden":true},"execution":{"iopub.status.busy":"2025-04-07T13:36:36.924292Z","iopub.execute_input":"2025-04-07T13:36:36.924597Z","iopub.status.idle":"2025-04-07T13:36:37.000957Z","shell.execute_reply.started":"2025-04-07T13:36:36.924561Z","shell.execute_reply":"2025-04-07T13:36:36.999673Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"solution = 'SOLUTION_11.3'\n\nif  solution in ENSEMBLE_SOLUTIONS:\n                                                            \n    begin(solution)\n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 0')\n    \n    \n    # **BirdCLEF 2025 Data Preprocessing Notebook**\n    # This notebook demonstrates how we can transform audio data into mel-spectrogram data. \n    # This transformation is essential for training 2D Convolutional Neural Networks (CNNs) on audio data,\n    # as it converts the one-dimensional audio signals into two-dimensional image-like representations.\n    # I run this public notebook in debug mode(only a few sample processing). \n    # You can find the fully preprocessed mel spectrogram training dataset here --> \n    # [BirdCLEF'25 | Mel Spectrograms](https://www.kaggle.com/datasets/kadircandrisolu/birdclef25-mel-spectrograms).\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1')\n    \n    \n    import os\n    import cv2\n    import math\n    import time\n    import librosa\n    import pandas as pd\n    import numpy as np\n    from tqdm.notebook import tqdm\n    \n    import torch\n    import warnings\n    warnings.filterwarnings(\"ignore\")\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2')\n    \n    \n    class Config:\n     \n        DEBUG_MODE = True\n        \n        OUTPUT_DIR = '/kaggle/working/'\n        DATA_ROOT = '/kaggle/input/birdclef-2025'\n        FS = 32000\n        \n        # Mel spectrogram parameters\n        N_FFT = 1024\n        HOP_LENGTH = 512\n        N_MELS = 128\n        FMIN = 50\n        FMAX = 14000\n        \n        TARGET_DURATION = 5.0\n        TARGET_SHAPE = (256, 256)  \n        \n        N_MAX = 50 if DEBUG_MODE else None  \n    \n    config = Config()\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 3')\n    \n    \n    print(f\"Debug mode: {'ON' if config.DEBUG_MODE else 'OFF'}\")\n    print(f\"Max samples to process: {config.N_MAX if config.N_MAX is not None else 'ALL'}\")\n    \n    print(\"Loading taxonomy data...\")\n    taxonomy_df = pd.read_csv(f'{config.DATA_ROOT}/taxonomy.csv')\n    species_class_map = dict(zip(taxonomy_df['primary_label'], taxonomy_df['class_name']))\n    \n    print(\"Loading training metadata...\")\n    train_df = pd.read_csv(f'{config.DATA_ROOT}/train.csv')\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 4')\n    \n    \n    label_list = sorted(train_df['primary_label'].unique())\n    label_id_list = list(range(len(label_list)))\n    label2id = dict(zip(label_list, label_id_list))\n    id2label = dict(zip(label_id_list, label_list))\n    \n    print(f'Found {len(label_list)} unique species')\n    working_df = train_df[['primary_label', 'rating', 'filename']].copy()\n    working_df['target'] = working_df.primary_label.map(label2id)\n    working_df['filepath'] = config.DATA_ROOT + '/train_audio/' + working_df.filename\n    working_df['samplename'] = working_df.filename.map(lambda x: x.split('/')[0] + '-' + x.split('/')[-1].split('.')[0])\n    working_df['class'] = working_df.primary_label.map(lambda x: species_class_map.get(x, 'Unknown'))\n    total_samples = min(len(working_df), config.N_MAX or len(working_df))\n    print(f'Total samples to process: {total_samples} out of {len(working_df)} available')\n    print(f'Samples by class:')\n    print(working_df['class'].value_counts())\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 5')\n    \n    \n    def audio2melspec(audio_data):\n        if np.isnan(audio_data).any():\n            mean_signal = np.nanmean(audio_data)\n            audio_data = np.nan_to_num(audio_data, nan=mean_signal)\n    \n        mel_spec = librosa.feature.melspectrogram(\n            y=audio_data,\n            sr=config.FS,\n            n_fft=config.N_FFT,\n            hop_length=config.HOP_LENGTH,\n            n_mels=config.N_MELS,\n            fmin=config.FMIN,\n            fmax=config.FMAX,\n            power=2.0\n        )\n    \n        mel_spec_db = librosa.power_to_db(mel_spec, ref=np.max)\n        mel_spec_norm = (mel_spec_db - mel_spec_db.min()) / (mel_spec_db.max() - mel_spec_db.min() + 1e-8)\n        \n        return mel_spec_norm\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 6')\n    \n    \n    print(\"Starting audio processing...\")\n    print(f\"{'DEBUG MODE - Processing only 50 samples' if config.DEBUG_MODE else 'FULL MODE - Processing all samples'}\")\n    start_time = time.time()\n    \n    all_bird_data = {}\n    errors = []\n    \n    for i, row in tqdm(working_df.iterrows(), total=total_samples):\n        if config.N_MAX is not None and i >= config.N_MAX:\n            break\n        \n        try:\n            audio_data, _ = librosa.load(row.filepath, sr=config.FS)\n    \n            target_samples = int(config.TARGET_DURATION * config.FS)\n    \n            if len(audio_data) < target_samples:\n                n_copy = math.ceil(target_samples / len(audio_data))\n                if n_copy > 1:\n                    audio_data = np.concatenate([audio_data] * n_copy)\n    \n            start_idx = max(0, int(len(audio_data) / 2 - target_samples / 2))\n            end_idx = min(len(audio_data), start_idx + target_samples)\n            center_audio = audio_data[start_idx:end_idx]\n    \n            if len(center_audio) < target_samples:\n                center_audio = np.pad(center_audio, \n                                     (0, target_samples - len(center_audio)), \n                                     mode='constant')\n    \n            mel_spec = audio2melspec(center_audio)\n    \n            if mel_spec.shape != config.TARGET_SHAPE:\n                mel_spec = cv2.resize(mel_spec, config.TARGET_SHAPE, interpolation=cv2.INTER_LINEAR)\n    \n            all_bird_data[row.samplename] = mel_spec.astype(np.float32)\n            \n        except Exception as e:\n            print(f\"Error processing {row.filepath}: {e}\")\n            errors.append((row.filepath, str(e)))\n    \n    end_time = time.time()\n    print(f\"Processing completed in {end_time - start_time:.2f} seconds\")\n    print(f\"Successfully processed {len(all_bird_data)} files out of {total_samples} total\")\n    print(f\"Failed to process {len(errors)} files\")\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 7')\n    \n    \n    import matplotlib.pyplot as plt\n    \n    samples = []\n    displayed_classes = set()\n    \n    max_samples = min(4, len(all_bird_data))\n    \n    for i, row in working_df.iterrows():\n        if i >= (config.N_MAX or len(working_df)):\n            break\n            \n        if row['samplename'] in all_bird_data:\n            if config.DEBUG_MODE:\n                if row['class'] not in displayed_classes:\n                    samples.append((row['samplename'], row['class'], row['primary_label']))\n                    displayed_classes.add(row['class'])\n            else:\n                if row['class'] not in displayed_classes:\n                    samples.append((row['samplename'], row['class'], row['primary_label']))\n                    displayed_classes.add(row['class'])\n            \n            if len(samples) >= max_samples:  \n                break\n    \n    if samples:\n        plt.figure(figsize=(16, 12))\n        \n        for i, (samplename, class_name, species) in enumerate(samples):\n            plt.subplot(2, 2, i+1)\n            plt.imshow(all_bird_data[samplename], aspect='auto', origin='lower', cmap='viridis')\n            plt.title(f\"{class_name}: {species}\")\n            plt.colorbar(format='%+2.0f dB')\n        \n        plt.tight_layout()\n        debug_note = \"debug_\" if config.DEBUG_MODE else \"\"\n        plt.savefig(f'{debug_note}melspec_examples.png')\n        plt.show()\n    \n    \n    end()","metadata":{"trusted":true,"_kg_hide-input":true,"_kg_hide-output":true,"jupyter":{"source_hidden":true},"execution":{"iopub.status.busy":"2025-04-07T13:36:37.001962Z","iopub.execute_input":"2025-04-07T13:36:37.002226Z","iopub.status.idle":"2025-04-07T13:36:37.026461Z","shell.execute_reply.started":"2025-04-07T13:36:37.002203Z","shell.execute_reply":"2025-04-07T13:36:37.024986Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## [Salman Ahmed](https://www.kaggle.com/salmanahmedtamu)\n### 14. [EfficientNet B0 Pytorch, Labels TTA, [Inference]](https://www.kaggle.com/code/salmanahmedtamu/labels-tta-efficientnet-b0-pytorch-inference)","metadata":{}},{"cell_type":"code","source":"solution = 'SOLUTION_14'\n\nif  solution in ENSEMBLE_SOLUTIONS:\n                                                                \n    begin(solution)\n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 0')\n    \n    \n    # This notebook is exact copy of the notebook mentioned below but with TTA on Predictions\n    # \n    # - [Copied from Notebook](https://www.kaggle.com/code/kumarandatascientist/lb-0-784-efficientnet-b0-pytorch-inference)  \n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1')\n    \n    \n    import os\n    import gc\n    import warnings\n    import logging\n    import time\n    import math\n    import cv2\n    from pathlib import Path\n    \n    import numpy as np\n    import pandas as pd\n    import librosa\n    import torch\n    import torch.nn as nn\n    import torch.nn.functional as F\n    import timm\n    from tqdm.auto import tqdm\n    \n    warnings.filterwarnings(\"ignore\")\n    logging.basicConfig(level=logging.ERROR)\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2')\n    \n    \n    class CFG:\n     \n        test_soundscapes = '/kaggle/input/birdclef-2025/test_soundscapes'\n        submission_csv = '/kaggle/input/birdclef-2025/sample_submission.csv'\n        taxonomy_csv = '/kaggle/input/birdclef-2025/taxonomy.csv'\n        model_path = '/kaggle/input/birdclef-2025-efficientnet-b0'  \n        \n        # Audio parameters\n        FS = 32000  \n        WINDOW_SIZE = 5  \n        \n        # Mel spectrogram parameters\n        N_FFT = 1024\n        HOP_LENGTH = 512\n        N_MELS = 148\n        FMIN = 50\n        FMAX = 14000\n        TARGET_SHAPE = (256, 256)\n        \n        model_name = 'efficientnet_b0'\n        in_channels = 1\n        device = 'cpu'  \n        \n        # Inference parameters\n        batch_size = 16\n        use_tta = False  \n        tta_count = 3   \n        threshold = 0.5\n        \n        use_specific_folds = False  # If False, use all found models\n        folds = [0, 1]  # Used only if use_specific_folds is True\n        \n        debug = False\n        debug_count = 3\n    \n    cfg = CFG()\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 3')\n    \n    \n    print(f\"Using device: {cfg.device}\")\n    print(f\"Loading taxonomy data...\")\n    taxonomy_df = pd.read_csv(cfg.taxonomy_csv)\n    species_ids = taxonomy_df['primary_label'].tolist()\n    num_classes = len(species_ids)\n    print(f\"Number of classes: {num_classes}\")\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 4')\n    \n    \n    class BirdCLEFModel(nn.Module):\n        def __init__(self, cfg, num_classes):\n            super().__init__()\n            self.cfg = cfg\n            \n            self.backbone = timm.create_model(\n                cfg.model_name,\n                pretrained=False,  \n                in_chans=cfg.in_channels,\n                drop_rate=0.0,    \n                drop_path_rate=0.0\n            )\n            \n            if 'efficientnet' in cfg.model_name:\n                backbone_out = self.backbone.classifier.in_features\n                self.backbone.classifier = nn.Identity()\n            elif 'resnet' in cfg.model_name:\n                backbone_out = self.backbone.fc.in_features\n                self.backbone.fc = nn.Identity()\n            else:\n                backbone_out = self.backbone.get_classifier().in_features\n                self.backbone.reset_classifier(0, '')\n            \n            self.pooling = nn.AdaptiveAvgPool2d(1)\n            self.feat_dim = backbone_out\n            self.classifier = nn.Linear(backbone_out, num_classes)\n            \n        def forward(self, x):\n            features = self.backbone(x)\n            \n            if isinstance(features, dict):\n                features = features['features']\n                \n            if len(features.shape) == 4:\n                features = self.pooling(features)\n                features = features.view(features.size(0), -1)\n            \n            logits = self.classifier(features)\n            return logits\n\n        \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 5')\n    \n    \n    def audio2melspec(audio_data, cfg):\n        \"\"\"Convert audio data to mel spectrogram\"\"\"\n        if np.isnan(audio_data).any():\n            mean_signal = np.nanmean(audio_data)\n            audio_data = np.nan_to_num(audio_data, nan=mean_signal)\n    \n        mel_spec = librosa.feature.melspectrogram(\n            y=audio_data,\n            sr=cfg.FS,\n            n_fft=cfg.N_FFT,\n            hop_length=cfg.HOP_LENGTH,\n            n_mels=cfg.N_MELS,\n            fmin=cfg.FMIN,\n            fmax=cfg.FMAX,\n            power=2.0\n        )\n    \n        mel_spec_db = librosa.power_to_db(mel_spec, ref=np.max)\n        mel_spec_norm = (mel_spec_db - mel_spec_db.min()) / (mel_spec_db.max() - mel_spec_db.min() + 1e-8)\n        \n        return mel_spec_norm\n    \n    def process_audio_segment(audio_data, cfg):\n        \"\"\"Process audio segment to get mel spectrogram\"\"\"\n        if len(audio_data) < cfg.FS * cfg.WINDOW_SIZE:\n            audio_data = np.pad(audio_data, \n                              (0, cfg.FS * cfg.WINDOW_SIZE - len(audio_data)), \n                              mode='constant')\n        \n        mel_spec = audio2melspec(audio_data, cfg)\n        \n        # Resize if needed\n        if mel_spec.shape != cfg.TARGET_SHAPE:\n            mel_spec = cv2.resize(mel_spec, cfg.TARGET_SHAPE, interpolation=cv2.INTER_LINEAR)\n            \n        return mel_spec.astype(np.float32)\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 6')\n    \n    \n    def find_model_files(cfg):\n        \"\"\"\n        Find all .pth model files in the specified model directory\n        \"\"\"\n        model_files = []\n        \n        model_dir = Path(cfg.model_path)\n        \n        for path in model_dir.glob('**/*.pth'):\n            model_files.append(str(path))\n        \n        return model_files\n    \n    def load_models(cfg, num_classes):\n        \"\"\"\n        Load all found model files and prepare them for ensemble\n        \"\"\"\n        models = []\n        \n        model_files = find_model_files(cfg)\n        \n        if not model_files:\n            print(f\"Warning: No model files found under {cfg.model_path}!\")\n            return models\n        \n        print(f\"Found a total of {len(model_files)} model files.\")\n        \n        if cfg.use_specific_folds:\n            filtered_files = []\n            for fold in cfg.folds:\n                fold_files = [f for f in model_files if f\"fold{fold}\" in f]\n                filtered_files.extend(fold_files)\n            model_files = filtered_files\n            print(f\"Using {len(model_files)} model files for the specified folds ({cfg.folds}).\")\n        \n        for model_path in model_files:\n            try:\n                print(f\"Loading model: {model_path}\")\n                checkpoint = torch.load(model_path, map_location=torch.device(cfg.device))\n                \n                model = BirdCLEFModel(cfg, num_classes)\n                model.load_state_dict(checkpoint['model_state_dict'])\n                model = model.to(cfg.device)\n                model.eval()\n                \n                models.append(model)\n            except Exception as e:\n                print(f\"Error loading model {model_path}: {e}\")\n        \n        return models\n    \n    def predict_on_spectrogram(audio_path, models, cfg, species_ids):\n        \"\"\"Process a single audio file and predict species presence for each 5-second segment\"\"\"\n        predictions = []\n        row_ids = []\n        soundscape_id = Path(audio_path).stem\n        \n        try:\n            print(f\"Processing {soundscape_id}\")\n            audio_data, _ = librosa.load(audio_path, sr=cfg.FS)\n            \n            total_segments = int(len(audio_data) / (cfg.FS * cfg.WINDOW_SIZE))\n            \n            for segment_idx in range(total_segments):\n                start_sample = segment_idx * cfg.FS * cfg.WINDOW_SIZE\n                end_sample = start_sample + cfg.FS * cfg.WINDOW_SIZE\n                segment_audio = audio_data[start_sample:end_sample]\n                \n                end_time_sec = (segment_idx + 1) * cfg.WINDOW_SIZE\n                row_id = f\"{soundscape_id}_{end_time_sec}\"\n                row_ids.append(row_id)\n    \n                if cfg.use_tta:\n                    all_preds = []\n                    \n                    for tta_idx in range(cfg.tta_count):\n                        mel_spec = process_audio_segment(segment_audio, cfg)\n                        mel_spec = apply_tta(mel_spec, tta_idx)\n    \n                        mel_spec = torch.tensor(mel_spec, dtype=torch.float32).unsqueeze(0).unsqueeze(0)\n                        mel_spec = mel_spec.to(cfg.device)\n    \n                        if len(models) == 1:\n                            with torch.no_grad():\n                                outputs = models[0](mel_spec)\n                                probs = torch.sigmoid(outputs).cpu().numpy().squeeze()\n                                all_preds.append(probs)\n                        else:\n                            segment_preds = []\n                            for model in models:\n                                with torch.no_grad():\n                                    outputs = model(mel_spec)\n                                    probs = torch.sigmoid(outputs).cpu().numpy().squeeze()\n                                    segment_preds.append(probs)\n                            \n                            avg_preds = np.mean(segment_preds, axis=0)\n                            all_preds.append(avg_preds)\n    \n                    final_preds = np.mean(all_preds, axis=0)\n                else:\n                    mel_spec = process_audio_segment(segment_audio, cfg)\n                    \n                    mel_spec = torch.tensor(mel_spec, dtype=torch.float32).unsqueeze(0).unsqueeze(0)\n                    mel_spec = mel_spec.to(cfg.device)\n                    \n                    if len(models) == 1:\n                        with torch.no_grad():\n                            outputs = models[0](mel_spec)\n                            final_preds = torch.sigmoid(outputs).cpu().numpy().squeeze()\n                    else:\n                        segment_preds = []\n                        for model in models:\n                            with torch.no_grad():\n                                outputs = model(mel_spec)\n                                probs = torch.sigmoid(outputs).cpu().numpy().squeeze()\n                                segment_preds.append(probs)\n    \n                        final_preds = np.mean(segment_preds, axis=0)\n                        \n                predictions.append(final_preds)\n                \n        except Exception as e:\n            print(f\"Error processing {audio_path}: {e}\")\n        \n        return row_ids, predictions\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 7')\n    \n    \n    def apply_tta(spec, tta_idx):\n        \"\"\"Apply test-time augmentation\"\"\"\n        if tta_idx == 0:\n            # Original spectrogram\n            return spec\n        elif tta_idx == 1:\n            # Time shift (horizontal flip)\n            return np.flip(spec, axis=1)\n        elif tta_idx == 2:\n            # Frequency shift (vertical flip)\n            return np.flip(spec, axis=0)\n        else:\n            return spec\n    \n    def run_inference(cfg, models, species_ids):\n        \"\"\"Run inference on all test soundscapes\"\"\"\n        test_files = list(Path(cfg.test_soundscapes).glob('*.ogg'))\n        \n        if cfg.debug:\n            print(f\"Debug mode enabled, using only {cfg.debug_count} files\")\n            test_files = test_files[:cfg.debug_count]\n        \n        print(f\"Found {len(test_files)} test soundscapes\")\n    \n        all_row_ids = []\n        all_predictions = []\n    \n        for audio_path in tqdm(test_files):\n            row_ids, predictions = predict_on_spectrogram(str(audio_path), models, cfg, species_ids)\n            all_row_ids.extend(row_ids)\n            all_predictions.extend(predictions)\n        \n        return all_row_ids, all_predictions\n    \n    def create_submission(row_ids, predictions, species_ids, cfg):\n        \"\"\"Create submission dataframe\"\"\"\n        print(\"Creating submission dataframe...\")\n    \n        submission_dict = {'row_id': row_ids}\n        \n        for i, species in enumerate(species_ids):\n            submission_dict[species] = [pred[i] for pred in predictions]\n    \n        submission_df = pd.DataFrame(submission_dict)\n    \n        submission_df.set_index('row_id', inplace=True)\n    \n        sample_sub = pd.read_csv(cfg.submission_csv, index_col='row_id')\n    \n        missing_cols = set(sample_sub.columns) - set(submission_df.columns)\n        if missing_cols:\n            print(f\"Warning: Missing {len(missing_cols)} species columns in submission\")\n            for col in missing_cols:\n                submission_df[col] = 0.0\n    \n        submission_df = submission_df[sample_sub.columns]\n    \n        submission_df = submission_df.reset_index()\n        \n        return submission_df\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 8')\n    \n    \n    def main():\n        start_time = time.time()\n        print(\"Starting BirdCLEF-2025 inference...\")\n        print(f\"TTA enabled: {cfg.use_tta} (variations: {cfg.tta_count if cfg.use_tta else 0})\")\n    \n        models = load_models(cfg, num_classes)\n        \n        if not models:\n            print(\"No models found! Please check model paths.\")\n            return\n        \n        print(f\"Model usage: {'Single model' if len(models) == 1 else f'Ensemble of {len(models)} models'}\")\n    \n        row_ids, predictions = run_inference(cfg, models, species_ids)\n    \n        submission_df = create_submission(row_ids, predictions, species_ids, cfg)\n    \n        submission_path = 'submission.csv'\n        submission_df.to_csv(submission_path, index=False)\n        print(f\"Submission saved to {submission_path}\")\n        \n        end_time = time.time()\n        print(f\"Inference completed in {(end_time - start_time)/60:.2f} minutes\")\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 9')\n    \n    \n    if __name__ == \"__main__\":\n        main()\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 10')\n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 11')\n    \n    \n    sub = pd.read_csv('submission.csv')\n    \n    cols = sub.columns[1:]\n    groups = sub['row_id'].str.rsplit('_', n=1).str[0]\n    groups = groups.values\n        \n    for group in np.unique(groups):\n        sub_group = sub[group == groups]\n        predictions = sub_group[cols].values\n        new_predictions = predictions.copy()\n        for i in range(1, predictions.shape[0]-1):\n            new_predictions[i] = (predictions[i-1] * 0.2) + (predictions[i] * 0.6) + (predictions[i+1] * 0.2)\n        new_predictions[0] = (predictions[0] * 0.8) + (predictions[1] * 0.2)\n        new_predictions[-1] = (predictions[-1] * 0.8) + (predictions[-2] * 0.2)\n        sub_group[cols] = new_predictions\n        sub[group == groups] = sub_group\n        \n    sub.to_csv(\"subm_14.csv\", index=False)\n    \n    \n    end()","metadata":{"trusted":true,"_kg_hide-input":true,"_kg_hide-output":true,"jupyter":{"source_hidden":true},"execution":{"iopub.status.busy":"2025-04-07T13:36:37.027573Z","iopub.execute_input":"2025-04-07T13:36:37.027926Z","iopub.status.idle":"2025-04-07T13:36:37.069562Z","shell.execute_reply.started":"2025-04-07T13:36:37.027893Z","shell.execute_reply":"2025-04-07T13:36:37.068205Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## [InkWhisper](https://www.kaggle.com/liverpool786)\n### 16. [Upgrade model](https://www.kaggle.com/datasets/liverpool786/lbmore-newtrain) -> [EfficientNet B0 Pytorch, Labels TTA, [Inference]](https://www.kaggle.com/code/salmanahmedtamu/labels-tta-efficientnet-b0-pytorch-inference)","metadata":{}},{"cell_type":"code","source":"solution = 'SOLUTION_16'\n\nif  solution in ENSEMBLE_SOLUTIONS:\n                                                                \n    begin(solution)\n\n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ u')\n\n\n    # The model was trained and fine-tuned using an A100 GPU, achieving improved performance.\n    # (The new model has replaced the model from \"14. EfficientNet B0 PyTorch, Labels TTA, [Inference]\".)\n    # *(The new model named /kaggle/input/lbmore-newtrain)*\n\n\n    # Credits to invisible for the ensemble solution. Original notebook: \n    # https://www.kaggle.com/code/vyacheslavbolotin/birdclef-2025-ensemble-of-solutions/notebook\n    \n    \n    # Your vote directly fuels our progress - if this model helped your workflow,                     \n    # please ⭐ support with an upvote! ⭐ Every vote gets us closer to breakthrough solutions ⭐. \n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 0')\n    \n    \n    # This notebook is exact copy of the notebook mentioned below but with TTA on Predictions\n    # \n    # - [Copied from Notebook](https://www.kaggle.com/code/kumarandatascientist/lb-0-784-efficientnet-b0-pytorch-inference)  \n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1')\n    \n    \n    import os\n    import gc\n    import warnings\n    import logging\n    import time\n    import math\n    import cv2\n    from pathlib import Path\n    \n    import numpy as np\n    import pandas as pd\n    import librosa\n    import torch\n    import torch.nn as nn\n    import torch.nn.functional as F\n    import timm\n    from tqdm.auto import tqdm\n    \n    warnings.filterwarnings(\"ignore\")\n    logging.basicConfig(level=logging.ERROR)\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2')\n    \n    \n    class CFG:\n     \n        test_soundscapes = '/kaggle/input/birdclef-2025/test_soundscapes'\n        submission_csv = '/kaggle/input/birdclef-2025/sample_submission.csv'\n        taxonomy_csv = '/kaggle/input/birdclef-2025/taxonomy.csv'\n        model_path = '/kaggle/input/lbmore-newtrain'  \n        \n        # Audio parameters\n        FS = 32000  \n        WINDOW_SIZE = 5  \n        \n        # Mel spectrogram parameters\n        N_FFT = 1024\n        HOP_LENGTH = 512\n        N_MELS = 148\n        FMIN = 50\n        FMAX = 14000\n        TARGET_SHAPE = (256, 256)\n        \n        model_name = 'efficientnet_b0'\n        in_channels = 1\n        device = 'cpu'  \n        \n        # Inference parameters\n        batch_size = 16\n        use_tta = False  \n        tta_count = 3   \n        threshold = 0.5\n        \n        use_specific_folds = False  # If False, use all found models\n        folds = [0, 1]  # Used only if use_specific_folds is True\n        \n        debug = False\n        debug_count = 3\n    \n    cfg = CFG()\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 3')\n    \n    \n    print(f\"Using device: {cfg.device}\")\n    print(f\"Loading taxonomy data...\")\n    taxonomy_df = pd.read_csv(cfg.taxonomy_csv)\n    species_ids = taxonomy_df['primary_label'].tolist()\n    num_classes = len(species_ids)\n    print(f\"Number of classes: {num_classes}\")\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 4')\n    \n    \n    class BirdCLEFModel(nn.Module):\n        def __init__(self, cfg, num_classes):\n            super().__init__()\n            self.cfg = cfg\n            \n            self.backbone = timm.create_model(\n                cfg.model_name,\n                pretrained=False,  \n                in_chans=cfg.in_channels,\n                drop_rate=0.0,    \n                drop_path_rate=0.0\n            )\n            \n            if 'efficientnet' in cfg.model_name:\n                backbone_out = self.backbone.classifier.in_features\n                self.backbone.classifier = nn.Identity()\n            elif 'resnet' in cfg.model_name:\n                backbone_out = self.backbone.fc.in_features\n                self.backbone.fc = nn.Identity()\n            else:\n                backbone_out = self.backbone.get_classifier().in_features\n                self.backbone.reset_classifier(0, '')\n            \n            self.pooling = nn.AdaptiveAvgPool2d(1)\n            self.feat_dim = backbone_out\n            self.classifier = nn.Linear(backbone_out, num_classes)\n            \n        def forward(self, x):\n            features = self.backbone(x)\n            \n            if isinstance(features, dict):\n                features = features['features']\n                \n            if len(features.shape) == 4:\n                features = self.pooling(features)\n                features = features.view(features.size(0), -1)\n            \n            logits = self.classifier(features)\n            return logits\n\n        \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 5')\n    \n    \n    def audio2melspec(audio_data, cfg):\n        \"\"\"Convert audio data to mel spectrogram\"\"\"\n        if np.isnan(audio_data).any():\n            mean_signal = np.nanmean(audio_data)\n            audio_data = np.nan_to_num(audio_data, nan=mean_signal)\n    \n        mel_spec = librosa.feature.melspectrogram(\n            y=audio_data,\n            sr=cfg.FS,\n            n_fft=cfg.N_FFT,\n            hop_length=cfg.HOP_LENGTH,\n            n_mels=cfg.N_MELS,\n            fmin=cfg.FMIN,\n            fmax=cfg.FMAX,\n            power=2.0\n        )\n    \n        mel_spec_db = librosa.power_to_db(mel_spec, ref=np.max)\n        mel_spec_norm = (mel_spec_db - mel_spec_db.min()) / (mel_spec_db.max() - mel_spec_db.min() + 1e-8)\n        \n        return mel_spec_norm\n    \n    def process_audio_segment(audio_data, cfg):\n        \"\"\"Process audio segment to get mel spectrogram\"\"\"\n        if len(audio_data) < cfg.FS * cfg.WINDOW_SIZE:\n            audio_data = np.pad(audio_data, \n                              (0, cfg.FS * cfg.WINDOW_SIZE - len(audio_data)), \n                              mode='constant')\n        \n        mel_spec = audio2melspec(audio_data, cfg)\n        \n        # Resize if needed\n        if mel_spec.shape != cfg.TARGET_SHAPE:\n            mel_spec = cv2.resize(mel_spec, cfg.TARGET_SHAPE, interpolation=cv2.INTER_LINEAR)\n            \n        return mel_spec.astype(np.float32)\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 6')\n    \n    \n    def find_model_files(cfg):\n        \"\"\"\n        Find all .pth model files in the specified model directory\n        \"\"\"\n        model_files = []\n        \n        model_dir = Path(cfg.model_path)\n        \n        for path in model_dir.glob('**/*.pth'):\n            model_files.append(str(path))\n        \n        return model_files\n    \n    def load_models(cfg, num_classes):\n        \"\"\"\n        Load all found model files and prepare them for ensemble\n        \"\"\"\n        models = []\n        \n        model_files = find_model_files(cfg)\n        \n        if not model_files:\n            print(f\"Warning: No model files found under {cfg.model_path}!\")\n            return models\n        \n        print(f\"Found a total of {len(model_files)} model files.\")\n        \n        if cfg.use_specific_folds:\n            filtered_files = []\n            for fold in cfg.folds:\n                fold_files = [f for f in model_files if f\"fold{fold}\" in f]\n                filtered_files.extend(fold_files)\n            model_files = filtered_files\n            print(f\"Using {len(model_files)} model files for the specified folds ({cfg.folds}).\")\n        \n        for model_path in model_files:\n            try:\n                print(f\"Loading model: {model_path}\")\n                checkpoint = torch.load(model_path, map_location=torch.device(cfg.device))\n                \n                model = BirdCLEFModel(cfg, num_classes)\n                model.load_state_dict(checkpoint['model_state_dict'])\n                model = model.to(cfg.device)\n                model.eval()\n                \n                models.append(model)\n            except Exception as e:\n                print(f\"Error loading model {model_path}: {e}\")\n        \n        return models\n    \n    def predict_on_spectrogram(audio_path, models, cfg, species_ids):\n        \"\"\"Process a single audio file and predict species presence for each 5-second segment\"\"\"\n        predictions = []\n        row_ids = []\n        soundscape_id = Path(audio_path).stem\n        \n        try:\n            print(f\"Processing {soundscape_id}\")\n            audio_data, _ = librosa.load(audio_path, sr=cfg.FS)\n            \n            total_segments = int(len(audio_data) / (cfg.FS * cfg.WINDOW_SIZE))\n            \n            for segment_idx in range(total_segments):\n                start_sample = segment_idx * cfg.FS * cfg.WINDOW_SIZE\n                end_sample = start_sample + cfg.FS * cfg.WINDOW_SIZE\n                segment_audio = audio_data[start_sample:end_sample]\n                \n                end_time_sec = (segment_idx + 1) * cfg.WINDOW_SIZE\n                row_id = f\"{soundscape_id}_{end_time_sec}\"\n                row_ids.append(row_id)\n    \n                if cfg.use_tta:\n                    all_preds = []\n                    \n                    for tta_idx in range(cfg.tta_count):\n                        mel_spec = process_audio_segment(segment_audio, cfg)\n                        mel_spec = apply_tta(mel_spec, tta_idx)\n    \n                        mel_spec = torch.tensor(mel_spec, dtype=torch.float32).unsqueeze(0).unsqueeze(0)\n                        mel_spec = mel_spec.to(cfg.device)\n    \n                        if len(models) == 1:\n                            with torch.no_grad():\n                                outputs = models[0](mel_spec)\n                                probs = torch.sigmoid(outputs).cpu().numpy().squeeze()\n                                all_preds.append(probs)\n                        else:\n                            segment_preds = []\n                            for model in models:\n                                with torch.no_grad():\n                                    outputs = model(mel_spec)\n                                    probs = torch.sigmoid(outputs).cpu().numpy().squeeze()\n                                    segment_preds.append(probs)\n                            \n                            avg_preds = np.mean(segment_preds, axis=0)\n                            all_preds.append(avg_preds)\n    \n                    final_preds = np.mean(all_preds, axis=0)\n                else:\n                    mel_spec = process_audio_segment(segment_audio, cfg)\n                    \n                    mel_spec = torch.tensor(mel_spec, dtype=torch.float32).unsqueeze(0).unsqueeze(0)\n                    mel_spec = mel_spec.to(cfg.device)\n                    \n                    if len(models) == 1:\n                        with torch.no_grad():\n                            outputs = models[0](mel_spec)\n                            final_preds = torch.sigmoid(outputs).cpu().numpy().squeeze()\n                    else:\n                        segment_preds = []\n                        for model in models:\n                            with torch.no_grad():\n                                outputs = model(mel_spec)\n                                probs = torch.sigmoid(outputs).cpu().numpy().squeeze()\n                                segment_preds.append(probs)\n    \n                        final_preds = np.mean(segment_preds, axis=0)\n                        \n                predictions.append(final_preds)\n                \n        except Exception as e:\n            print(f\"Error processing {audio_path}: {e}\")\n        \n        return row_ids, predictions\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 7')\n    \n    \n    def apply_tta(spec, tta_idx):\n        \"\"\"Apply test-time augmentation\"\"\"\n        if tta_idx == 0:\n            # Original spectrogram\n            return spec\n        elif tta_idx == 1:\n            # Time shift (horizontal flip)\n            return np.flip(spec, axis=1)\n        elif tta_idx == 2:\n            # Frequency shift (vertical flip)\n            return np.flip(spec, axis=0)\n        else:\n            return spec\n    \n    def run_inference(cfg, models, species_ids):\n        \"\"\"Run inference on all test soundscapes\"\"\"\n        test_files = list(Path(cfg.test_soundscapes).glob('*.ogg'))\n        \n        if cfg.debug:\n            print(f\"Debug mode enabled, using only {cfg.debug_count} files\")\n            test_files = test_files[:cfg.debug_count]\n        \n        print(f\"Found {len(test_files)} test soundscapes\")\n    \n        all_row_ids = []\n        all_predictions = []\n    \n        for audio_path in tqdm(test_files):\n            row_ids, predictions = predict_on_spectrogram(str(audio_path), models, cfg, species_ids)\n            all_row_ids.extend(row_ids)\n            all_predictions.extend(predictions)\n        \n        return all_row_ids, all_predictions\n    \n    def create_submission(row_ids, predictions, species_ids, cfg):\n        \"\"\"Create submission dataframe\"\"\"\n        print(\"Creating submission dataframe...\")\n    \n        submission_dict = {'row_id': row_ids}\n        \n        for i, species in enumerate(species_ids):\n            submission_dict[species] = [pred[i] for pred in predictions]\n    \n        submission_df = pd.DataFrame(submission_dict)\n    \n        submission_df.set_index('row_id', inplace=True)\n    \n        sample_sub = pd.read_csv(cfg.submission_csv, index_col='row_id')\n    \n        missing_cols = set(sample_sub.columns) - set(submission_df.columns)\n        if missing_cols:\n            print(f\"Warning: Missing {len(missing_cols)} species columns in submission\")\n            for col in missing_cols:\n                submission_df[col] = 0.0\n    \n        submission_df = submission_df[sample_sub.columns]\n    \n        submission_df = submission_df.reset_index()\n        \n        return submission_df\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 8')\n    \n    \n    def main():\n        start_time = time.time()\n        print(\"Starting BirdCLEF-2025 inference...\")\n        print(f\"TTA enabled: {cfg.use_tta} (variations: {cfg.tta_count if cfg.use_tta else 0})\")\n    \n        models = load_models(cfg, num_classes)\n        \n        if not models:\n            print(\"No models found! Please check model paths.\")\n            return\n        \n        print(f\"Model usage: {'Single model' if len(models) == 1 else f'Ensemble of {len(models)} models'}\")\n    \n        row_ids, predictions = run_inference(cfg, models, species_ids)\n    \n        submission_df = create_submission(row_ids, predictions, species_ids, cfg)\n    \n        submission_path = 'subm_16.csv'\n        submission_df.to_csv(submission_path, index=False)\n        print(f\"Submission saved to {submission_path}\")\n        \n        end_time = time.time()\n        print(f\"Inference completed in {(end_time - start_time)/60:.2f} minutes\")\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 9')\n    \n    \n    if __name__ == \"__main__\":\n        main()\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 10')\n\n    \n    # main()\n\n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 11')\n    \n    \n    sub = pd.read_csv('subm_16.csv')\n    \n    cols = sub.columns[1:]\n    groups = sub['row_id'].str.rsplit('_', n=1).str[0]\n    groups = groups.values\n        \n    for group in np.unique(groups):\n        sub_group = sub[group == groups]\n        predictions = sub_group[cols].values\n        new_predictions = predictions.copy()\n        for i in range(1, predictions.shape[0]-1):\n            new_predictions[i] = (predictions[i-1] * 0.2) + (predictions[i] * 0.6) + (predictions[i+1] * 0.2)\n        new_predictions[0] = (predictions[0] * 0.8) + (predictions[1] * 0.2)\n        new_predictions[-1] = (predictions[-1] * 0.8) + (predictions[-2] * 0.2)\n        sub_group[cols] = new_predictions\n        sub[group == groups] = sub_group\n        \n    sub.to_csv(\"subm_16.csv\", index=False)\n    \n    \n    end()","metadata":{"trusted":true,"_kg_hide-input":true,"_kg_hide-output":true,"execution":{"iopub.status.busy":"2025-04-07T13:36:37.070988Z","iopub.execute_input":"2025-04-07T13:36:37.071473Z","iopub.status.idle":"2025-04-07T13:36:40.346887Z","shell.execute_reply.started":"2025-04-07T13:36:37.071425Z","shell.execute_reply":"2025-04-07T13:36:40.345908Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# 📜\n\nimport os\n\n\ndef ensN(lbs        = LB,\n         solution   = ENSEMBLE_SOLUTIONS,\n         wts        = WEIGHTS,\n         files_subm = FILES_SUBM,\n         option     = OPTION):\n    def f_ensemble(df,cols,wts):\n        return sum([df[cols[i]]*wts[i] for i in range(len(wts))])\n    soluts = [solut.replace(\"SOLUTION_\",\"\") for solut in solution]\n    print(f'Ensemble: {soluts},   LB: {lbs},   weights: {wts}')\n    list_TARGETs = sorted(os.listdir('/kaggle/input/birdclef-2025/train_audio/'))\n    list_list_TARGETs = [[f'{TARGET} {i}' for TARGET in list_TARGETs] for i in range(len(solution))]\n    list_df_subms     = [pd.read_csv(file_subm) for file_subm in files_subm]\n    for i in range(len(list_df_subms)):\n        list_df_subms[i] = list_df_subms[i].rename(columns={\n                TARGET : f'{TARGET} {i}' for TARGET in list_TARGETs})\n    dfs = pd.merge(list_df_subms[0], list_df_subms[1], on=['row_id'])\n    for i in range(2,len(files_subm)): \n        dfs = pd.merge(dfs,list_df_subms[i],on=['row_id'])\n    matrix_cols = [[f'{TARGET} {i}' for i in range(len(files_subm))] for TARGET in list_TARGETs]\n    for i in range(len(matrix_cols)):\n        dfs[list_TARGETs[i]] = dfs.apply(lambda x:f_ensemble(x,matrix_cols[i],wts), axis=1)\n    for one_list in list_list_TARGETs:\n        for TARGET in one_list: del dfs[TARGET]\n    return dfs\n\n\ndef ens2(lbs        = LB,\n         solution   = ENSEMBLE_SOLUTIONS,\n         wts        = WEIGHTS,\n         files_subm = FILES_SUBM,\n         option     = OPTION):\n    soluts = [solut.replace(\"SOLUTION_\",\"\") for solut in solution]\n    print(f'Ensemble: {soluts},   LB: {lbs},   weights: {wts}')\n    list_TARGETs = sorted(os.listdir('/kaggle/input/birdclef-2025/train_audio/'))\n    list_targets_0 = [f'{TARGET} 0' for TARGET in list_TARGETs]\n    list_targets_1 = [f'{TARGET} 1' for TARGET in list_TARGETs]\n    df0 = pd.read_csv(files_subm[0])\n    df1 = pd.read_csv(files_subm[1])\n    df0 = df0.rename(columns={TARGET : f'{TARGET} 0' for TARGET in list_TARGETs})\n    df1 = df1.rename(columns={TARGET : f'{TARGET} 1' for TARGET in list_TARGETs})\n    dfs = pd.merge(df0,df1,on=['row_id'])\n    for i in range(len(list_TARGETs)):\n        dfs[list_TARGETs[i]] = dfs[list_targets_0[i]]*wts[0] + wts[1]*dfs[list_targets_1[i]]          \n    for col0,col1 in zip(list_targets_0, list_targets_1):\n        del dfs[col0]\n        del dfs[col1] \n    return dfs\n\n\ndef ens4(lbs        = LB,\n         solution   = ENSEMBLE_SOLUTIONS,\n         wts        = WEIGHTS,\n         files_subm = FILES_SUBM,\n         option     = OPTION):\n\n    soluts = [solut.replace(\"SOLUTION_\",\"\") for solut in solution]\n\n    print(f'Ensemble: {soluts},   LB: {lbs},   weights: {wts}\\n')\n    \n    list_TARGETs = sorted(os.listdir('/kaggle/input/birdclef-2025/train_audio/'))\n\n    list_targets_0 = [f'{TARGET} 0' for TARGET in list_TARGETs]\n    list_targets_1 = [f'{TARGET} 1' for TARGET in list_TARGETs]\n    list_targets_2 = [f'{TARGET} 2' for TARGET in list_TARGETs]\n    list_targets_3 = [f'{TARGET} 3' for TARGET in list_TARGETs]\n\n    df0 = pd.read_csv(files_subm[0])\n    df1 = pd.read_csv(files_subm[1])\n    df2 = pd.read_csv(files_subm[2])\n    df3 = pd.read_csv(files_subm[3])\n\n    df0 = df0.rename(columns={TARGET : f'{TARGET} 0' for TARGET in list_TARGETs})\n    df1 = df1.rename(columns={TARGET : f'{TARGET} 1' for TARGET in list_TARGETs})\n    df2 = df2.rename(columns={TARGET : f'{TARGET} 2' for TARGET in list_TARGETs})\n    df3 = df3.rename(columns={TARGET : f'{TARGET} 3' for TARGET in list_TARGETs})\n\n    dfs = pd.merge(df0,df1,on=['row_id'])\n    dfs = pd.merge(dfs,df2,on=['row_id'])\n    dfs = pd.merge(dfs,df3,on=['row_id'])\n\n    for i in range(len(list_TARGETs)):\n        dfs[list_TARGETs[i]] =\\\n                dfs[list_targets_0[i]]*wts[0] +\\\n                dfs[list_targets_1[i]]*wts[1] +\\\n                dfs[list_targets_2[i]]*wts[2] +\\\n                dfs[list_targets_3[i]]*wts[3]\n                 \n    for col0,col1,col2,col3 in zip(list_targets_0, list_targets_1, list_targets_2, list_targets_3):\n        del dfs[col0]\n        del dfs[col1]\n        del dfs[col2]\n        del dfs[col3]\n\n    return dfs\n\n\nensemble = ensN \n\nif len(ENSEMBLE_SOLUTIONS)==2: ensemble = ens2\nif len(ENSEMBLE_SOLUTIONS)==4: ensemble = ens4\n\n\nif exEDA:\n\n    if 'SOLUTION_3' in ENSEMBLE_SOLUTIONS:\n        import IPython\n        print('a small piece of code taken from solution.3 by Prata, Marília \\n')\n        IPython.display(IPython.display.Audio(\"../input/birdclef-2025/train_audio/1139490/CSA36389.ogg\"))\n\n\nimport warnings; warnings.filterwarnings(\"ignore\")\n\n\ndef world_cloud():\n    \n    from wordcloud import WordCloud\n    import matplotlib.pyplot as plt\n\n    path_DS         = '/kaggle/input/birdclef-2025-ensemble-of-solution'\n    \n    path_Solut_1    = path_DS + '/SOLUTION_1__'    + 'Stefan_Kahl'      + '__BirdCLEF_2025_Sample_Submission.py'\n    path_Solut_10   = path_DS + '/SOLUTION_10__'   + 'Carlo_Lepelaars'  + '__BirdCLEF_2025_Simple_Submission.py'\n    path_Solut_3    = path_DS + '/SOLUTION_3__'    + 'Marilia_Prata'    + '__BirdClef_2025_El_Silencio_Natural_Reserve.py'\n    \n    path_Solut_5    = path_DS + '/SOLUTION_5__'    + 'Jocelyn_Dumlao'   + '__BirdCLEF_2025_MFCC_Feature_and_ROC_AUC_Analysis.py'\n    path_Solut_5b   = path_DS + '/SOLUTION_5b__'   + 'Jocelyn_Dumlao'   + '__BirdCLEF_2025_Inference_w_SimpleCNN_Spectrogram.py'\n    path_Solut_15   = path_DS + '/SOLUTION_15__'   + 'Kumaran'          + '__EfficientNet_B0_Pytorch_upgrade_copy_Solutions_11_14.py'\n    \n    path_Solut_8    = path_DS + '/SOLUTION_8__'    + 'agcsdedf'         + '__BirdCLEF_2025_Base_Submit.py'\n    path_Solut_12   = path_DS + '/SOLUTION_12__'   + 'agcsdedf'         + '__BirdCLEF_2025_OpenVINO_Inf.py'\n    path_Solut_14   = path_DS + '/SOLUTION_14__'   + 'Salman_Ahmed'     + '__Labels_TTA_EfficientNet_B0_Pytorch_Inference.py'\n    \n    path_Solut_6    = path_DS + '/SOLUTION_6__'    + 'MYSO'             + '__BirdCLEF_2025_3_Submit_baseline_5s.py'\n    path_Solut_6_2  = path_DS + '/SOLUTION_6_2__'  + 'MYSO'             + '__BirdCLEF_2025_2_Train_baseline_5s.py'\n    path_Solut_b_3  = path_DS + '/SOLUTION_6_3__'  + 'MYSO__BirdCLEF2025_1_Crop_audio_5s.py'\n    \n    path_Solut_11   = path_DS + '/SOLUTION_11__'   + 'Kadircan_drisolu' + '__EfficientNet_B0_Pytorch_Inference_BirdCLEF_25.py'\n    path_Solut_11_2 = path_DS + '/SOLUTION_11_2__' + 'Kadircan_drisolu' + '__EfficientNet_B0_Pytorch_Train_BirdCLEF_25.py'\n    path_Solut_11_3 = path_DS + '/SOLUTION_11_3__' + 'Kadircan_drisolu__Transforming_Audio_to_Mel_Spec_BirdCLEF_25.py'\n    \n    ps_to_Soluts  = [\n        path_Solut_1,\n        path_Solut_10,\n        path_Solut_3, \n        \n        path_Solut_5, \n        path_Solut_5b,\n        path_Solut_15,\n        \n        path_Solut_8,\n        path_Solut_12,\n        path_Solut_14,\n    ]\n    ps_to_Soluts_2  = [\n        path_Solut_b_3,\n        path_Solut_6_2,\n        path_Solut_6,\n        \n        path_Solut_11_3,\n        path_Solut_11_2,\n        path_Solut_11,\n    ]\n\n    title_Soluts  = [\n        \"SOLUTION_1\",\n        \"SOLUTION_10\",\n        \"SOLUTION_3\",\n        \"SOLUTION_5\",\n        \"SOLUTION_5b\",\n        \"SOLUTION_15 - upgrade copy (11,14)\",\n        \"SOLUTION_8\",\n        \"SOLUTION_12\",\n        \"SOLUTION_14\",\n    ]\n    title_Soluts_2  = [\n        \"SOLUTION_b_3   -1-   [Crop audio]\",\n        \"SOLUTION_6_2   -2-   [Train]\",\n        \"SOLUTION_6   -3-   [Inference]\",\n        \n        \"SOLUTION_11_3   -1-   [Transforming Audio-to-Mel Spec]\",\n        \"SOLUTION_11_2   -2-   [Train]\",\n        \"SOLUTION_11   -3-   [Inference]\",\n    ]\n\n    def del_some_words_from(data):\n        clr_data = data.replace('print',\"\").replace('cell',\"\").replace('cfg',\"\").replace('self',\"\").replace('kaggle',\"\").replace('submission',\"\").replace('import',\"\")\n        return clr_data\n\n    # read SOLUTION from Dataset and transport to Worldcloud\n    \n    def read_for_Worldcloud(path):\n        with open(path) as f: \n            data = f.read()\n            f.close()\n        clr_data = del_some_words_from(data)\n        return WordCloud(background_color='gainsboro').generate(clr_data) # \"floralwhite\"\n\n    def read_for_Worldcloud_2(path):\n        with open(path) as f: \n            data = f.read()\n            f.close()\n        clr_data = del_some_words_from(data)\n        return WordCloud(background_color='lightsteelblue').generate(clr_data)\n\n    \n    wc_from_Soluts   = [{\"path\":read_for_Worldcloud(p),   \"title\":t} for p,t in zip(ps_to_Soluts,  title_Soluts)]\n\n    wc_from_Soluts_2 = [{\"path\":read_for_Worldcloud_2(p), \"title\":t} for p,t in zip(ps_to_Soluts_2,title_Soluts_2)]\n\n    \n    fig, (ax1,ax10,ax3) = plt.subplots(ncols=3,figsize=(12,6))\n    axs = [ax1,ax10,ax3]\n    for i in range(3): \n        axs[i].imshow(wc_from_Soluts[i]['path'])\n        axs[i].axis(\"off\")\n        axs[i].set_title(wc_from_Soluts[i]['title'],fontsize=10)\n    plt.tight_layout()\n    plt.show()\n    #-----------\n    fig, (ax5,ax5b,ax15) = plt.subplots(ncols=3,figsize=(12,6))\n    axs = [ax1,ax10,ax3, ax5,ax5b,ax15]\n    for i in range(3,6,1): \n        axs[i].imshow(wc_from_Soluts[i]['path'])\n        axs[i].axis(\"off\")\n        axs[i].set_title(wc_from_Soluts[i]['title'],fontsize=10)\n    plt.tight_layout()\n    plt.show()\n    #-----------\n    fig, (ax8,ax12,ax14) = plt.subplots(ncols=3,figsize=(12,6))\n    axs = [ax1,ax10,ax5, ax5,ax5b,ax15, ax8,ax12,ax14]\n    for i in range(6,9,1): \n        axs[i].imshow(wc_from_Soluts[i]['path'])\n        axs[i].axis(\"off\")\n        axs[i].set_title(wc_from_Soluts[i]['title'],fontsize=10)\n    plt.tight_layout()\n    plt.show()\n    #-----------\n    fig, (axb_3,ax6_2,ax6) = plt.subplots(ncols=3,figsize=(12,6))\n    axs = [axb_3,ax6_2,ax6]\n    for i in range(3): \n        axs[i].imshow(wc_from_Soluts_2[i]['path'])\n        axs[i].axis(\"off\")\n        axs[i].set_title(wc_from_Soluts_2[i]['title'],fontsize=10)\n    plt.tight_layout()\n    plt.show()\n    #-----------\n    fig, (ax11_3,ax11_2,ax11) = plt.subplots(ncols=3,figsize=(12,6))\n    axs = [axb_3,ax6_2,ax6, ax11_3,ax11_2,ax11]\n    for i in range(3,6,1): \n        axs[i].imshow(wc_from_Soluts_2[i]['path'])\n        axs[i].axis(\"off\")\n        axs[i].set_title(wc_from_Soluts_2[i]['title'],fontsize=10)\n    plt.tight_layout()\n    plt.show()","metadata":{"trusted":true,"_kg_hide-input":true,"_kg_hide-output":true,"execution":{"iopub.status.busy":"2025-04-07T13:36:40.347988Z","iopub.execute_input":"2025-04-07T13:36:40.348351Z","iopub.status.idle":"2025-04-07T13:36:40.381964Z","shell.execute_reply.started":"2025-04-07T13:36:40.348325Z","shell.execute_reply":"2025-04-07T13:36:40.380759Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"if exSOLUTIONS:\n\n    subm = ensemble()\n    subm.to_csv('submission.csv', index=False)\n\n    Geographic_(), world_cloud()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-07T13:36:40.383254Z","iopub.execute_input":"2025-04-07T13:36:40.383764Z","iopub.status.idle":"2025-04-07T13:36:51.244159Z","shell.execute_reply.started":"2025-04-07T13:36:40.383716Z","shell.execute_reply":"2025-04-07T13:36:51.242996Z"}},"outputs":[],"execution_count":null}]}