File size: 93,018 Bytes
26e5b8d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "# TechTrident\n",
        "\n",
        "AI system detects defects/degradation (cracks, hotspots, soiling) using tabular performance data + images. ONNX export required. Public datasets only.\n",
        "\n",
        "Classes: ['Bird-drop', 'Clean', 'Dusty', 'Electrical-damage', 'Physical-Damage', 'Snow-Covered']\n",
        "\n",
        "Datasets: [PV Panel Defect Dataset](https://www.kaggle.com/datasets/alicjalena/pv-panel-defect-dataset) TechTrident | Wadla 4.0 Hackathon 2025\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "g77qbAOimwT8",
        "outputId": "d7630c7b-a22e-4796-8183-388d6441a587"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "\u001b[?25l   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m0.0/18.1 MB\u001b[0m \u001b[31m?\u001b[0m eta \u001b[36m-:--:--\u001b[0m\r\u001b[2K   \u001b[91m━━━\u001b[0m\u001b[90mβ•Ί\u001b[0m\u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m1.5/18.1 MB\u001b[0m \u001b[31m45.8 MB/s\u001b[0m eta \u001b[36m0:00:01\u001b[0m\r\u001b[2K   \u001b[91m━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[91mβ•Έ\u001b[0m\u001b[90m━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m8.6/18.1 MB\u001b[0m \u001b[31m126.2 MB/s\u001b[0m eta \u001b[36m0:00:01\u001b[0m\r\u001b[2K   \u001b[91m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[91mβ•Έ\u001b[0m\u001b[90m━\u001b[0m \u001b[32m17.4/18.1 MB\u001b[0m \u001b[31m242.1 MB/s\u001b[0m eta \u001b[36m0:00:01\u001b[0m\r\u001b[2K   \u001b[91m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[91mβ•Έ\u001b[0m \u001b[32m18.1/18.1 MB\u001b[0m \u001b[31m244.7 MB/s\u001b[0m eta \u001b[36m0:00:01\u001b[0m\r\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m18.1/18.1 MB\u001b[0m \u001b[31m115.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m17.4/17.4 MB\u001b[0m \u001b[31m119.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m46.0/46.0 kB\u001b[0m \u001b[31m4.2 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m86.8/86.8 kB\u001b[0m \u001b[31m7.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[?25h"
          ]
        }
      ],
      "source": [
        "!pip install -q torch torchvision torchaudio\n",
        "!pip install -q scikit-learn matplotlib seaborn\n",
        "!pip install -q onnx onnxruntime\n",
        "!pip install -q tqdm\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "GMkcprwXrbBX",
        "outputId": "0d33e958-6054-4215-e54d-de76432d6bbb"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Using Colab cache for faster access to the 'solarpanel' dataset.\n",
            "Path to dataset files: /kaggle/input/solarpanel\n"
          ]
        }
      ],
      "source": [
        "import kagglehub\n",
        "\n",
        "# Download latest version\n",
        "path = kagglehub.dataset_download(\"pkdarabi/solarpanel\")\n",
        "\n",
        "print(\"Path to dataset files:\", path)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "KKazlbdSros-",
        "outputId": "03cdf94e-b7d8-48b7-f7e5-ea4aef35a623"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Using Colab cache for faster access to the 'pv-panel-defect-dataset' dataset.\n",
            "Path to dataset files: /kaggle/input/pv-panel-defect-dataset\n"
          ]
        }
      ],
      "source": [
        "import kagglehub\n",
        "\n",
        "# Download latest version\n",
        "path = kagglehub.dataset_download(\"alicjalena/pv-panel-defect-dataset\")\n",
        "\n",
        "print(\"Path to dataset files:\", path)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "pFgkSY2Srjyg",
        "outputId": "3cef8f66-230b-46c8-925e-1a1c8d07e9ec"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Using Colab cache for faster access to the 'pvel-ad-electroluminescence-pv-defect-dataset' dataset.\n",
            "Path to dataset files: /kaggle/input/pvel-ad-electroluminescence-pv-defect-dataset\n"
          ]
        }
      ],
      "source": [
        "import kagglehub\n",
        "\n",
        "# Download latest version\n",
        "path = kagglehub.dataset_download(\"programmer3/pvel-ad-electroluminescence-pv-defect-dataset\")\n",
        "\n",
        "print(\"Path to dataset files:\", path)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "Wk-TX_1DsZtS",
        "outputId": "3728b24f-240e-41b4-ae21-3c56f2eecfe5"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "\n",
            "============================================================\n",
            "DATASET: RGB_SolarPanel\n",
            "PATH: /root/.cache/kagglehub/datasets/pkdarabi/solarpanel/versions/49\n",
            "============================================================\n",
            "\n",
            "============================================================\n",
            "DATASET: EL_PV_Defect\n",
            "PATH: /root/.cache/kagglehub/datasets/programmer3/pvel-ad-electroluminescence-pv-defect-dataset/versions/1\n",
            "============================================================\n",
            "\n",
            "============================================================\n",
            "DATASET: Thermal_PV\n",
            "PATH: /kaggle/input/pv-panel-defect-dataset\n",
            "============================================================\n",
            "ROOT: /kaggle/input/pv-panel-defect-dataset\n",
            "SUBFOLDERS: ['val', 'test', 'train']\n",
            "FILES COUNT: 0\n",
            "SAMPLE FILES: []\n"
          ]
        }
      ],
      "source": [
        "# STEP 3: Inspect each dataset structure (one by one)\n",
        "\n",
        "import os\n",
        "\n",
        "dataset_paths = {\n",
        "    \"RGB_SolarPanel\": \"/root/.cache/kagglehub/datasets/pkdarabi/solarpanel/versions/49\",\n",
        "    \"EL_PV_Defect\": \"/root/.cache/kagglehub/datasets/programmer3/pvel-ad-electroluminescence-pv-defect-dataset/versions/1\",\n",
        "    \"Thermal_PV\": \"/kaggle/input/pv-panel-defect-dataset\"\n",
        "}\n",
        "\n",
        "def inspect_dataset(name, path):\n",
        "    print(\"\\n\" + \"=\"*60)\n",
        "    print(f\"DATASET: {name}\")\n",
        "    print(f\"PATH: {path}\")\n",
        "    print(\"=\"*60)\n",
        "\n",
        "    for root, dirs, files in os.walk(path):\n",
        "        print(\"ROOT:\", root)\n",
        "        print(\"SUBFOLDERS:\", dirs)\n",
        "        print(\"FILES COUNT:\", len(files))\n",
        "        print(\"SAMPLE FILES:\", files[:5])\n",
        "        break\n",
        "\n",
        "for name, path in dataset_paths.items():\n",
        "    inspect_dataset(name, path)\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "7tHZWUP3s2ON",
        "outputId": "03518ec6-efa1-42c1-f590-1f935fd14f31"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "\n",
            "--- TRAIN ---\n",
            "Classes: ['Snow-Covered', 'Dusty', 'Electrical-damage', 'Clean', 'Bird-drop', 'Physical-Damage']\n",
            "\n",
            "--- VAL ---\n",
            "Classes: ['Snow-Covered', 'Dusty', 'Electrical-damage', 'Clean', 'Bird-drop', 'Physical-Damage']\n",
            "\n",
            "--- TEST ---\n",
            "Classes: ['Snow-Covered', 'Dusty', 'Electrical-damage', 'Clean', 'Bird-drop', 'Physical-Damage']\n"
          ]
        }
      ],
      "source": [
        "# STEP 4: Inspect class folders inside Thermal dataset\n",
        "\n",
        "import os\n",
        "\n",
        "thermal_path = \"/kaggle/input/pv-panel-defect-dataset\"\n",
        "\n",
        "for split in [\"train\", \"val\", \"test\"]:\n",
        "    split_path = os.path.join(thermal_path, split)\n",
        "    print(f\"\\n--- {split.upper()} ---\")\n",
        "    if os.path.exists(split_path):\n",
        "        print(\"Classes:\", os.listdir(split_path))\n",
        "    else:\n",
        "        print(\"❌ Split not found\")\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 7,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "WFpVI-6dtK6I",
        "outputId": "a1f6ab86-cf2a-4f8d-bc15-8169c7438b69"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Using device: cuda\n",
            "Class mapping: {'Bird-drop': 0, 'Clean': 1, 'Dusty': 2, 'Electrical-damage': 3, 'Physical-Damage': 4, 'Snow-Covered': 5}\n",
            "Train samples: 929\n",
            "Val samples: 550\n",
            "Test samples: 95\n"
          ]
        }
      ],
      "source": [
        "# STEP 5: DataLoader & Transforms\n",
        "\n",
        "import torch\n",
        "from torchvision import datasets, transforms\n",
        "from torch.utils.data import DataLoader\n",
        "\n",
        "DEVICE = \"cuda\" if torch.cuda.is_available() else \"cpu\"\n",
        "print(\"Using device:\", DEVICE)\n",
        "\n",
        "IMG_SIZE = 224\n",
        "BATCH_SIZE = 32\n",
        "\n",
        "# Transform (handles thermal / grayscale / RGB)\n",
        "train_transform = transforms.Compose([\n",
        "    transforms.Resize((IMG_SIZE, IMG_SIZE)),\n",
        "    transforms.Grayscale(num_output_channels=3),\n",
        "    transforms.RandomHorizontalFlip(),\n",
        "    transforms.ToTensor(),\n",
        "    transforms.Normalize(\n",
        "        mean=[0.485, 0.456, 0.406],\n",
        "        std=[0.229, 0.224, 0.225]\n",
        "    )\n",
        "])\n",
        "\n",
        "val_transform = transforms.Compose([\n",
        "    transforms.Resize((IMG_SIZE, IMG_SIZE)),\n",
        "    transforms.Grayscale(num_output_channels=3),\n",
        "    transforms.ToTensor(),\n",
        "    transforms.Normalize(\n",
        "        mean=[0.485, 0.456, 0.406],\n",
        "        std=[0.229, 0.224, 0.225]\n",
        "    )\n",
        "])\n",
        "\n",
        "DATASET_PATH = \"/kaggle/input/pv-panel-defect-dataset\"\n",
        "\n",
        "train_data = datasets.ImageFolder(\n",
        "    root=f\"{DATASET_PATH}/train\",\n",
        "    transform=train_transform\n",
        ")\n",
        "\n",
        "val_data = datasets.ImageFolder(\n",
        "    root=f\"{DATASET_PATH}/val\",\n",
        "    transform=val_transform\n",
        ")\n",
        "\n",
        "test_data = datasets.ImageFolder(\n",
        "    root=f\"{DATASET_PATH}/test\",\n",
        "    transform=val_transform\n",
        ")\n",
        "\n",
        "train_loader = DataLoader(train_data, batch_size=BATCH_SIZE, shuffle=True)\n",
        "val_loader = DataLoader(val_data, batch_size=BATCH_SIZE, shuffle=False)\n",
        "test_loader = DataLoader(test_data, batch_size=BATCH_SIZE, shuffle=False)\n",
        "\n",
        "print(\"Class mapping:\", train_data.class_to_idx)\n",
        "print(\"Train samples:\", len(train_data))\n",
        "print(\"Val samples:\", len(val_data))\n",
        "print(\"Test samples:\", len(test_data))\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 7,
      "metadata": {
        "id": "VBpWsVAPvQOm"
      },
      "outputs": [],
      "source": []
    },
    {
      "cell_type": "code",
      "execution_count": 9,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "R90aPddvtg3z",
        "outputId": "4b65372d-de96-4dc3-a733-327ddbafe519"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "\n",
            "Epoch [1/15]\n"
          ]
        },
        {
          "name": "stderr",
          "output_type": "stream",
          "text": [
            "100%|β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ| 30/30 [00:26<00:00,  1.13it/s]\n"
          ]
        },
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Train Loss: 46.1716, Train Acc: 49.52%\n",
            "Val Loss: 23.4326, Val Acc: 72.36%\n",
            "\n",
            "Epoch [2/15]\n"
          ]
        },
        {
          "name": "stderr",
          "output_type": "stream",
          "text": [
            "100%|β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ| 30/30 [00:24<00:00,  1.24it/s]\n"
          ]
        },
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Train Loss: 31.0843, Train Acc: 76.43%\n",
            "Val Loss: 13.2697, Val Acc: 82.00%\n",
            "\n",
            "Epoch [3/15]\n"
          ]
        },
        {
          "name": "stderr",
          "output_type": "stream",
          "text": [
            "100%|β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ| 30/30 [00:23<00:00,  1.25it/s]\n"
          ]
        },
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Train Loss: 20.2007, Train Acc: 84.82%\n",
            "Val Loss: 8.2944, Val Acc: 86.00%\n",
            "\n",
            "Epoch [4/15]\n"
          ]
        },
        {
          "name": "stderr",
          "output_type": "stream",
          "text": [
            "100%|β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ| 30/30 [00:24<00:00,  1.21it/s]\n"
          ]
        },
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Train Loss: 15.8832, Train Acc: 86.65%\n",
            "Val Loss: 5.8530, Val Acc: 89.45%\n",
            "\n",
            "Epoch [5/15]\n"
          ]
        },
        {
          "name": "stderr",
          "output_type": "stream",
          "text": [
            "100%|β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ| 30/30 [00:23<00:00,  1.25it/s]\n"
          ]
        },
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Train Loss: 11.4642, Train Acc: 91.07%\n",
            "Val Loss: 4.3735, Val Acc: 92.91%\n",
            "\n",
            "Epoch [6/15]\n"
          ]
        },
        {
          "name": "stderr",
          "output_type": "stream",
          "text": [
            "100%|β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ| 30/30 [00:24<00:00,  1.25it/s]\n"
          ]
        },
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Train Loss: 9.1711, Train Acc: 95.16%\n",
            "Val Loss: 3.6670, Val Acc: 94.00%\n",
            "\n",
            "Epoch [7/15]\n"
          ]
        },
        {
          "name": "stderr",
          "output_type": "stream",
          "text": [
            "100%|β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ| 30/30 [00:23<00:00,  1.26it/s]\n"
          ]
        },
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Train Loss: 7.1015, Train Acc: 95.59%\n",
            "Val Loss: 3.0334, Val Acc: 95.27%\n",
            "\n",
            "Epoch [8/15]\n"
          ]
        },
        {
          "name": "stderr",
          "output_type": "stream",
          "text": [
            "100%|β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ| 30/30 [00:23<00:00,  1.26it/s]\n"
          ]
        },
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Train Loss: 5.9129, Train Acc: 96.77%\n",
            "Val Loss: 2.7183, Val Acc: 95.82%\n",
            "\n",
            "Epoch [9/15]\n"
          ]
        },
        {
          "name": "stderr",
          "output_type": "stream",
          "text": [
            "100%|β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ| 30/30 [00:24<00:00,  1.25it/s]\n"
          ]
        },
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Train Loss: 4.7660, Train Acc: 98.17%\n",
            "Val Loss: 2.6371, Val Acc: 96.18%\n",
            "\n",
            "Epoch [10/15]\n"
          ]
        },
        {
          "name": "stderr",
          "output_type": "stream",
          "text": [
            "100%|β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ| 30/30 [00:23<00:00,  1.26it/s]\n"
          ]
        },
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Train Loss: 4.2479, Train Acc: 97.42%\n",
            "Val Loss: 2.5740, Val Acc: 96.18%\n",
            "\n",
            "Epoch [11/15]\n"
          ]
        },
        {
          "name": "stderr",
          "output_type": "stream",
          "text": [
            "100%|β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ| 30/30 [00:23<00:00,  1.26it/s]\n"
          ]
        },
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Train Loss: 3.4081, Train Acc: 99.03%\n",
            "Val Loss: 2.5000, Val Acc: 95.64%\n",
            "\n",
            "Epoch [12/15]\n"
          ]
        },
        {
          "name": "stderr",
          "output_type": "stream",
          "text": [
            "100%|β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ| 30/30 [00:23<00:00,  1.25it/s]\n"
          ]
        },
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Train Loss: 4.4313, Train Acc: 98.28%\n",
            "Val Loss: 2.3392, Val Acc: 96.36%\n",
            "\n",
            "Epoch [13/15]\n"
          ]
        },
        {
          "name": "stderr",
          "output_type": "stream",
          "text": [
            "100%|β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ| 30/30 [00:30<00:00,  1.02s/it]\n"
          ]
        },
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Train Loss: 3.8637, Train Acc: 98.17%\n",
            "Val Loss: 2.3700, Val Acc: 96.18%\n",
            "\n",
            "Epoch [14/15]\n"
          ]
        },
        {
          "name": "stderr",
          "output_type": "stream",
          "text": [
            "100%|β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ| 30/30 [00:23<00:00,  1.26it/s]\n"
          ]
        },
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Train Loss: 3.9151, Train Acc: 98.92%\n",
            "Val Loss: 2.4089, Val Acc: 96.36%\n",
            "\n",
            "Epoch [15/15]\n"
          ]
        },
        {
          "name": "stderr",
          "output_type": "stream",
          "text": [
            "100%|β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ| 30/30 [00:23<00:00,  1.25it/s]\n"
          ]
        },
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Train Loss: 3.1275, Train Acc: 98.82%\n",
            "Val Loss: 2.2238, Val Acc: 95.82%\n"
          ]
        }
      ],
      "source": [
        "# STEP 6: Build EfficientNet-B0 model & training loop\n",
        "\n",
        "import torch\n",
        "import torch.nn as nn\n",
        "import torch.optim as optim\n",
        "from torchvision import models\n",
        "from tqdm import tqdm\n",
        "\n",
        "NUM_CLASSES = 6\n",
        "EPOCHS = 15\n",
        "LR = 1e-4\n",
        "\n",
        "# Load pretrained EfficientNet-B0\n",
        "model = models.efficientnet_b0(pretrained=True)\n",
        "\n",
        "# Replace classifier\n",
        "in_features = model.classifier[1].in_features\n",
        "model.classifier[1] = nn.Linear(in_features, NUM_CLASSES)\n",
        "\n",
        "model = model.to(DEVICE)\n",
        "\n",
        "# Loss & optimizer\n",
        "criterion = nn.CrossEntropyLoss()\n",
        "optimizer = optim.Adam(model.parameters(), lr=LR)\n",
        "\n",
        "# Training & validation loop\n",
        "for epoch in range(EPOCHS):\n",
        "    print(f\"\\nEpoch [{epoch+1}/{EPOCHS}]\")\n",
        "\n",
        "    # ---- Training ----\n",
        "    model.train()\n",
        "    train_loss = 0\n",
        "    correct = 0\n",
        "    total = 0\n",
        "\n",
        "    for images, labels in tqdm(train_loader):\n",
        "        images, labels = images.to(DEVICE), labels.to(DEVICE)\n",
        "\n",
        "        optimizer.zero_grad()\n",
        "        outputs = model(images)\n",
        "        loss = criterion(outputs, labels)\n",
        "        loss.backward()\n",
        "        optimizer.step()\n",
        "\n",
        "        train_loss += loss.item()\n",
        "        _, predicted = torch.max(outputs, 1)\n",
        "        total += labels.size(0)\n",
        "        correct += (predicted == labels).sum().item()\n",
        "\n",
        "    train_acc = 100 * correct / total\n",
        "    print(f\"Train Loss: {train_loss:.4f}, Train Acc: {train_acc:.2f}%\")\n",
        "\n",
        "    # ---- Validation ----\n",
        "    model.eval()\n",
        "    val_loss = 0\n",
        "    correct = 0\n",
        "    total = 0\n",
        "\n",
        "    with torch.no_grad():\n",
        "        for images, labels in val_loader:\n",
        "            images, labels = images.to(DEVICE), labels.to(DEVICE)\n",
        "            outputs = model(images)\n",
        "            loss = criterion(outputs, labels)\n",
        "\n",
        "            val_loss += loss.item()\n",
        "            _, predicted = torch.max(outputs, 1)\n",
        "            total += labels.size(0)\n",
        "            correct += (predicted == labels).sum().item()\n",
        "\n",
        "    val_acc = 100 * correct / total\n",
        "    print(f\"Val Loss: {val_loss:.4f}, Val Acc: {val_acc:.2f}%\")\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 10,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 954
        },
        "id": "5XUQH8-ExIx6",
        "outputId": "e57ad2b3-8825-4f83-d3dc-f537c844b7c6"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "\n",
            "Classification Report:\n",
            "\n",
            "                   precision    recall  f1-score   support\n",
            "\n",
            "        Bird-drop       0.94      1.00      0.97        17\n",
            "            Clean       0.84      0.89      0.86        18\n",
            "            Dusty       0.93      0.81      0.87        16\n",
            "Electrical-damage       0.92      0.92      0.92        13\n",
            "  Physical-Damage       1.00      1.00      1.00        15\n",
            "     Snow-Covered       1.00      1.00      1.00        16\n",
            "\n",
            "         accuracy                           0.94        95\n",
            "        macro avg       0.94      0.94      0.94        95\n",
            "     weighted avg       0.94      0.94      0.94        95\n",
            "\n"
          ]
        },
        {
          "data": {
            "image/png": "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aGgIfX19fPzxx6hdu3aZ4jp16hTWrFmDWbNmyae13LJlCzw9PTFjxgwsXLiwTMcjImIFnoioHHXt2hXx8fHo3bs3Dh06hFGjRuGbb75BSkoKlixZgpUrV8r33bhxI+bMmYNLly5h3LhxOHXqFKZMmYJdu3apNCZzc3McOHAAenp6mDRpErZt24bg4GD4+fkVi71WrVrYvHkzRo0ahdWrV6Nt27Y4deoUjI2NSz1+hw4dEBoaCnNzc8ycOROLFy9G8+bNERkZWebktzxMnToV48ePx9GjRzF27FhER0fjjz/+QM2aNRX209LSwrZt26CpqYnhw4ejX79+OHPmTJnO9eLFCwwePBju7u6YNm2afH2bNm0wduxYLFmyBOfPn1fJdRFR5SGRleUuISIiIiIiEhQr8EREREREIsIEnoiIiIhIRJjAExERERGJCBN4IiIiIiIRYQJPRERERCQiTOCJiIiIiESECTwRERERkYjwSaykdnTdvxI6hArjyaVVQodARESVhI6AWWV55g65Mer3bykr8EREREREIsIKPBERERGJm6Ry1aSZwBMRERGRuEkkQkfwQVWurytERERERCLHCjwRERERiVsla6GpXFdLRERERCRyrMATERERkbixB56IiIiIiNQVK/BEREREJG7sgSciIiIiInXFCjwRERERiVsl64FnAk9ERERE4sYWGiIiIiIiUleswBMRERGRuFWyFhpW4ImIiIiIRIQVeCIiIiISN/bAExERERGRumIFnoiIiIjEjT3wRERERESkrliBJyIiIiJxYw88ERERERGpK1bgiYiIiEjc2ANPRERERCQiEo3yW8ooPDwcfn5+qF69OiQSCQ4ePFhsn4SEBHTt2hXGxsbQ19dH06ZNkZqaqvQ5mMATEREREalIdnY2GjZsiNWrV5e4PSkpCa1bt4azszPCwsIQHx+PGTNmQEdHR+lzsIWGiIiIiMRNjW5i9fX1ha+vb6nbp02bhs6dO2PhwoXydfb29mU6h/pcLRERERGRmsnLy8Pz588Vlry8vHc6VlFREf744w/UqVMH3t7esLS0xMcff1xim83bMIEnIiIiInHTkJTbEhwcDGNjY4UlODj4ncLMyMhAVlYWFixYAB8fHxw7dgw9evRAz549cebMGaWPwxYaIiIiIqJSTJkyBUFBQQrrpFLpOx2rqKgIANCtWzd8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v//eLQfgKvZFRBoKFfAiIhYUHR1NRkYG3t7eBAYG4un5//8d+Pr6ul1bXl7ODTfcwOuvv17nda688sp/9P52u/2Cv6e8vByA999/n9atW7ud8/Hx+Uc5RETMSAW8iIgF+fr6Eh4efl7Xdu3albfeeouAgAD8/f3PeM3VV1/N9u3bueWWWwCorq7mq6++omvXrme8PjIyEqfTyZYtW1wtNP/rz98A1NTUuNY6duyIj48PJSUlZ925j4iIIDs7223t888///u/pIiIiegmVhEROafhw4fTsmVLhgwZQl5eHvv27WPz5s0kJiZy8OBBACZPnswzzzzD2rVr+eGHH5gwYcI5Z7i3bduW+Ph4Ro0axdq1a12vuXLlSgBCQkKw2WysW7eOI0eOUF5ejsPhIDk5mUceeYTly5ezd+9e8vPzmTdvHsuXLwdg/Pjx7Nmzh0cffZTCwkLeeOMNXn755Uv9EYmIXFYq4EVE5JyaNGnCJ598QnBwMMOGDSMiIoLRo0dz6tQp1478lClTGDFiBPHx8fTs2ROHw8Htt99+ztfNyMjgjjvuYMKECXTo0IGxY8dy4sQJAFq3bs306dOZOnUqrVq1YtKkSQCkpaXx1FNPMWvWLCIiIoiJieH9998nNDQUgODgYFavXs3atWvp3LkzmZmZzJw58xJ+OiIil5+t9mx3GImIiIiISL2jHXgRERERERNRAS8iIiIiYiIq4EVERERETEQFvIiIiIiIiaiAFxERERExERXwIiIiIiImogJeRERERMREVMCLiIiIiJiICngRERERERNRAS8iIiIiYiIq4EVERERETEQFvIiIiIiIifwfGoZpHdZPaM4AAAAASUVORK5CYII=",
            "text/plain": [
              "<Figure size 800x600 with 2 Axes>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "# STEP 7: Test Evaluation Metrics\n",
        "\n",
        "import numpy as np\n",
        "from sklearn.metrics import classification_report, confusion_matrix\n",
        "import seaborn as sns\n",
        "import matplotlib.pyplot as plt\n",
        "\n",
        "model.eval()\n",
        "\n",
        "all_preds = []\n",
        "all_labels = []\n",
        "\n",
        "with torch.no_grad():\n",
        "    for images, labels in test_loader:\n",
        "        images = images.to(DEVICE)\n",
        "        outputs = model(images)\n",
        "        _, preds = torch.max(outputs, 1)\n",
        "\n",
        "        all_preds.extend(preds.cpu().numpy())\n",
        "        all_labels.extend(labels.numpy())\n",
        "\n",
        "# Classification report\n",
        "print(\"\\nClassification Report:\\n\")\n",
        "print(classification_report(all_labels, all_preds, target_names=train_data.classes))\n",
        "\n",
        "# Confusion Matrix\n",
        "cm = confusion_matrix(all_labels, all_preds)\n",
        "\n",
        "plt.figure(figsize=(8,6))\n",
        "sns.heatmap(cm, annot=True, fmt=\"d\",\n",
        "            xticklabels=train_data.classes,\n",
        "            yticklabels=train_data.classes,\n",
        "            cmap=\"Blues\")\n",
        "plt.xlabel(\"Predicted\")\n",
        "plt.ylabel(\"Actual\")\n",
        "plt.title(\"Confusion Matrix\")\n",
        "plt.show()\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 11,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "KMyAqFlhyVK7",
        "outputId": "c1d68f2a-d819-4cca-abbd-5143d875db73"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "\u001b[?25l   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m0.0/693.4 kB\u001b[0m \u001b[31m?\u001b[0m eta \u001b[36m-:--:--\u001b[0m\r\u001b[2K   \u001b[91m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[91mβ•Έ\u001b[0m \u001b[32m686.1/693.4 kB\u001b[0m \u001b[31m23.4 MB/s\u001b[0m eta \u001b[36m0:00:01\u001b[0m\r\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m693.4/693.4 kB\u001b[0m \u001b[31m16.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[?25h\u001b[?25l   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m0.0/133.1 kB\u001b[0m \u001b[31m?\u001b[0m eta \u001b[36m-:--:--\u001b[0m\r\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m133.1/133.1 kB\u001b[0m \u001b[31m13.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[?25h"
          ]
        }
      ],
      "source": [
        "# FIX: Install missing ONNX dependencies required by latest PyTorch\n",
        "\n",
        "!pip install -q onnxscript\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 12,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "r-kjCoenyb79",
        "outputId": "4acc6c11-5789-482d-e296-cfdf8fb72736"
      },
      "outputs": [
        {
          "name": "stderr",
          "output_type": "stream",
          "text": [
            "/tmp/ipython-input-3311461802.py:12: UserWarning: # 'dynamic_axes' is not recommended when dynamo=True, and may lead to 'torch._dynamo.exc.UserError: Constraints violated.' Supply the 'dynamic_shapes' argument instead if export is unsuccessful.\n",
            "  torch.onnx.export(\n",
            "W1218 21:15:42.026000 174 torch/onnx/_internal/exporter/_compat.py:114] Setting ONNX exporter to use operator set version 18 because the requested opset_version 11 is a lower version than we have implementations for. Automatic version conversion will be performed, which may not be successful at converting to the requested version. If version conversion is unsuccessful, the opset version of the exported model will be kept at 18. Please consider setting opset_version >=18 to leverage latest ONNX features\n"
          ]
        },
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "[torch.onnx] Obtain model graph for `EfficientNet([...]` with `torch.export.export(..., strict=False)`...\n",
            "[torch.onnx] Obtain model graph for `EfficientNet([...]` with `torch.export.export(..., strict=False)`... βœ…\n",
            "[torch.onnx] Run decomposition...\n"
          ]
        },
        {
          "name": "stderr",
          "output_type": "stream",
          "text": [
            "WARNING:onnxscript.version_converter:The model version conversion is not supported by the onnxscript version converter and fallback is enabled. The model will be converted using the onnx C API (target version: 11).\n"
          ]
        },
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "[torch.onnx] Run decomposition... βœ…\n",
            "[torch.onnx] Translate the graph into ONNX...\n",
            "[torch.onnx] Translate the graph into ONNX... βœ…\n"
          ]
        },
        {
          "name": "stderr",
          "output_type": "stream",
          "text": [
            "WARNING:onnxscript.version_converter:Failed to convert the model to the target version 11 using the ONNX C API. The model was not modified\n",
            "Traceback (most recent call last):\n",
            "  File \"/usr/local/lib/python3.12/dist-packages/onnxscript/version_converter/__init__.py\", line 127, in call\n",
            "    converted_proto = _c_api_utils.call_onnx_api(\n",
            "                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^\n",
            "  File \"/usr/local/lib/python3.12/dist-packages/onnxscript/version_converter/_c_api_utils.py\", line 65, in call_onnx_api\n",
            "    result = func(proto)\n",
            "             ^^^^^^^^^^^\n",
            "  File \"/usr/local/lib/python3.12/dist-packages/onnxscript/version_converter/__init__.py\", line 122, in _partial_convert_version\n",
            "    return onnx.version_converter.convert_version(\n",
            "           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n",
            "  File \"/usr/local/lib/python3.12/dist-packages/onnx/version_converter.py\", line 39, in convert_version\n",
            "    converted_model_str = C.convert_version(model_str, target_version)\n",
            "                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n",
            "RuntimeError: /github/workspace/onnx/version_converter/adapters/axes_input_to_attribute.h:65: adapt: Assertion `node->hasAttribute(kaxes)` failed: No initializer or constant input to node found\n"
          ]
        },
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Applied 98 of general pattern rewrite rules.\n",
            "βœ… ONNX model exported to: /content/solar_panel_defect_model.onnx\n"
          ]
        }
      ],
      "source": [
        "# STEP 8A: Export PyTorch model to ONNX\n",
        "\n",
        "import torch\n",
        "\n",
        "ONNX_PATH = \"/content/solar_panel_defect_model.onnx\"\n",
        "\n",
        "# Dummy input (batch size 1, 3-channel, 224x224)\n",
        "dummy_input = torch.randn(1, 3, 224, 224).to(DEVICE)\n",
        "\n",
        "model.eval()\n",
        "\n",
        "torch.onnx.export(\n",
        "    model,\n",
        "    dummy_input,\n",
        "    ONNX_PATH,\n",
        "    export_params=True,\n",
        "    opset_version=11,\n",
        "    do_constant_folding=True,\n",
        "    input_names=[\"input_image\"],\n",
        "    output_names=[\"class_scores\"],\n",
        "    dynamic_axes={\n",
        "        \"input_image\": {0: \"batch_size\"},\n",
        "        \"class_scores\": {0: \"batch_size\"}\n",
        "    }\n",
        ")\n",
        "\n",
        "print(\"βœ… ONNX model exported to:\", ONNX_PATH)\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 13,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "WPPp6_uVyroE",
        "outputId": "1542d5a3-f5ac-4138-b4b5-633b9e9032f5"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "ONNX output shape: (1, 6)\n",
            "Sample output: [[  993.0995    199.42247  -608.0232  -2058.3643  -4874.3457  -1554.5675 ]]\n"
          ]
        }
      ],
      "source": [
        "# STEP 8B: Verify ONNX model inference\n",
        "\n",
        "import onnxruntime as ort\n",
        "import numpy as np\n",
        "\n",
        "# Load ONNX model\n",
        "ort_session = ort.InferenceSession(ONNX_PATH)\n",
        "\n",
        "# Prepare dummy input\n",
        "dummy_np = np.random.randn(1, 3, 224, 224).astype(np.float32)\n",
        "\n",
        "# Run inference\n",
        "outputs = ort_session.run(\n",
        "    None,\n",
        "    {\"input_image\": dummy_np}\n",
        ")\n",
        "\n",
        "print(\"ONNX output shape:\", outputs[0].shape)\n",
        "print(\"Sample output:\", outputs[0])\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 14,
      "metadata": {
        "id": "Tj-Ynteqzf23"
      },
      "outputs": [],
      "source": [
        "# STEP G1: Install Gradio\n",
        "\n",
        "!pip install -q gradio onnxruntime pillow\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 15,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "PQzRiyU7z6WY",
        "outputId": "837b66a5-ad05-44cc-9e02-e5ff0db1eade"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "βœ… ONNX model loaded\n",
            "βœ… Inference pipeline ready\n"
          ]
        }
      ],
      "source": [
        "# STEP G2: Load ONNX model & preprocessing function\n",
        "\n",
        "import onnxruntime as ort\n",
        "import numpy as np\n",
        "from PIL import Image\n",
        "import torch\n",
        "from torchvision import transforms\n",
        "\n",
        "# Path to ONNX model\n",
        "ONNX_PATH = \"/content/solar_panel_defect_model.onnx\"\n",
        "\n",
        "# Load ONNX runtime session\n",
        "ort_session = ort.InferenceSession(ONNX_PATH, providers=[\"CPUExecutionProvider\"])\n",
        "\n",
        "print(\"βœ… ONNX model loaded\")\n",
        "\n",
        "# Class labels (VERY IMPORTANT: order must match training)\n",
        "CLASS_NAMES = [\n",
        "    'Bird-drop',\n",
        "    'Clean',\n",
        "    'Dusty',\n",
        "    'Electrical-damage',\n",
        "    'Physical-Damage',\n",
        "    'Snow-Covered'\n",
        "]\n",
        "\n",
        "# Same preprocessing as training\n",
        "IMG_SIZE = 224\n",
        "\n",
        "preprocess = transforms.Compose([\n",
        "    transforms.Resize((IMG_SIZE, IMG_SIZE)),\n",
        "    transforms.Grayscale(num_output_channels=3),\n",
        "    transforms.ToTensor(),\n",
        "    transforms.Normalize(\n",
        "        mean=[0.485, 0.456, 0.406],\n",
        "        std=[0.229, 0.224, 0.225]\n",
        "    )\n",
        "])\n",
        "\n",
        "def predict_image(pil_image):\n",
        "    \"\"\"\n",
        "    Input: PIL Image\n",
        "    Output: (predicted_class, confidence, full_probs_dict)\n",
        "    \"\"\"\n",
        "    img = preprocess(pil_image).unsqueeze(0).numpy().astype(np.float32)\n",
        "\n",
        "    # ONNX inference\n",
        "    outputs = ort_session.run(\n",
        "        None,\n",
        "        {\"input_image\": img}\n",
        "    )[0]\n",
        "\n",
        "    # Softmax\n",
        "    exp_scores = np.exp(outputs)\n",
        "    probs = exp_scores / np.sum(exp_scores, axis=1, keepdims=True)\n",
        "\n",
        "    probs = probs[0]\n",
        "    pred_idx = int(np.argmax(probs))\n",
        "\n",
        "    predicted_class = CLASS_NAMES[pred_idx]\n",
        "    confidence = float(probs[pred_idx])\n",
        "\n",
        "    prob_dict = {CLASS_NAMES[i]: float(probs[i]) for i in range(len(CLASS_NAMES))}\n",
        "\n",
        "    return predicted_class, confidence, prob_dict\n",
        "\n",
        "\n",
        "print(\"βœ… Inference pipeline ready\")\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 646
        },
        "id": "IHyiWnj_0EFQ",
        "outputId": "0a33d28f-97e8-4d98-d582-261a875c92f4"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "It looks like you are running Gradio on a hosted Jupyter notebook, which requires `share=True`. Automatically setting `share=True` (you can turn this off by setting `share=False` in `launch()` explicitly).\n",
            "\n",
            "Colab notebook detected. This cell will run indefinitely so that you can see errors and logs. To turn off, set debug=False in launch().\n",
            "* Running on public URL: https://d55396fb96ea5bc795.gradio.live\n",
            "\n",
            "This share link expires in 1 week. For free permanent hosting and GPU upgrades, run `gradio deploy` from the terminal in the working directory to deploy to Hugging Face Spaces (https://huggingface.co/spaces)\n"
          ]
        },
        {
          "data": {
            "text/html": [
              "<div><iframe src=\"https://d55396fb96ea5bc795.gradio.live\" width=\"100%\" height=\"500\" allow=\"autoplay; camera; microphone; clipboard-read; clipboard-write;\" frameborder=\"0\" allowfullscreen></iframe></div>"
            ],
            "text/plain": [
              "<IPython.core.display.HTML object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "# STEP G3: Gradio Interface\n",
        "\n",
        "import gradio as gr\n",
        "\n",
        "def gradio_predict(image):\n",
        "    pred_class, confidence, prob_dict = predict_image(image)\n",
        "\n",
        "    confidence_percent = f\"{confidence * 100:.2f}%\"\n",
        "\n",
        "    return pred_class, confidence_percent, prob_dict\n",
        "\n",
        "\n",
        "iface = gr.Interface(\n",
        "    fn=gradio_predict,\n",
        "    inputs=gr.Image(type=\"pil\", label=\"Upload Solar Panel Image (Thermal / IR / RGB)\"),\n",
        "    outputs=[\n",
        "        gr.Textbox(label=\"Predicted Defect Class\"),\n",
        "        gr.Textbox(label=\"Confidence\"),\n",
        "        gr.Label(label=\"All Class Probabilities\")\n",
        "    ],\n",
        "    title=\"AI-Powered Solar Panel Defect Detection\",\n",
        "    description=(\n",
        "        \"Upload any solar panel image (thermal, infrared, or RGB). \"\n",
        "        \"The AI model classifies defects such as soiling, electrical damage, \"\n",
        "        \"physical damage, snow coverage, or clean panels.\"\n",
        "    ),\n",
        "    examples=None\n",
        ")\n",
        "\n",
        "iface.launch(debug=True)\n"
      ]
    }
  ],
  "metadata": {
    "accelerator": "GPU",
    "colab": {
      "gpuType": "T4",
      "provenance": []
    },
    "kernelspec": {
      "display_name": "Python 3",
      "name": "python3"
    },
    "language_info": {
      "name": "python"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}