{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.14","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"tpu1vmV38","dataSources":[{"sourceId":7327,"databundleVersionId":861871,"sourceType":"competition"}],"dockerImageVersionId":30732,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"launch time : 3rd, July  ","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"![image.png](attachment:e54f5ccd-3fdb-41c1-b6a5-cabc33840785.png)","metadata":{},"attachments":{"e54f5ccd-3fdb-41c1-b6a5-cabc33840785.png":{"image/png":"iVBORw0KGgoAAAANSUhEUgAAA3kAAABTCAIAAACtTVlPAAAgAElEQVR4Ae2d/U9bV5rH99/ob7ZkiR8sRUo02jYSM4rqKtMQQWjHo0SgGQiboGXr7qKmHZiw4y1TyGRrNEBQoUyGLknQuDCEpMOECQoKpEwgMgKCAiEB4zgGHGrsuObF2DdNWJ1z7rk+1y8JJHYDybey0su9556Xz7ng733O8zznX9bxHwiAAAiAAAiAAAiAAAikhsC/RFU7ZXfiAwIgAAIgAAIgAAIgAAJJIRCtNUNhCR8QAAEQAAEQAAEQAAEQSAoBaE1oaxAAARAAARAAARAAgVQRgNZMFdmkvAqgEhAAARAAARAAARDY1gSgNaE1QQAEQAAEQAAEQAAEUkUAWjNVZLf1Kwg6DwIgAAIgAAIgAAJJIQCtCa0JAiAAAiAAAiAAAiCQKgLQmqkim5RXAVQCAiAAAiAAAiAAAtuaALQmtCYIgAAIgAAIgAAIgECqCEBrporstn4FQedBAARAAARAAARAICkEoDWhNUEABEAABEAABEAABFJFAFozVWST8iqASkAABEAABEAABEBgWxOA1oTWBAEQAAEQAAEQAAEQSBUBaM1Ukd3WryDoPAiAAAiAAAiAAAgkhQC0JrQmCIAACIAACIAACIBAqghAa6aKbFJeBVAJCIAACIAACIAACGxrAtCa0JogAAIgAAIgAAIgAAKpIgCtmSqy2/oVBJ0HARAAARAAARAAgaQQgNaE1gQBEAABEAABEAABEEgVAWjNVJFNyqsAKgEBEAABEAABEACBbU0AWhNaEwRAAARAAARAAARAIFUEoDVTRXZbv4Kg8yAAAiAAAiAAAiCQFALQmttSawYWfYHgC/X8xWtIyvOHSkAABEAABEAABF5tAtCaL6TYNvNw+G40W05amm8svmiLc20FaVrdjvL+QPg5q3rxGjYz8OfsJJoAARAAARAAARB4BQhAa/5oSsjdkqfTaAta7r9oi56/l+zQ6jPqx577+XvxGp67adwIAiAAAiAAAiDwWhH4cbXm2orH5/M4b10dGhiwP/D4fIG1FxVe22e2kqY1t8+QX5/JxUhBAARAAARAAATiE/hRtOayc6D7VMmJd3b8Zucb0Z83f3qitK57eHY5fv+SqavmL32cmZlRcmluvr+hODcjM/Nodf9cUArd5z9WdEz4STfsHcUZmZmHmu4orQe+tWRkZmaU93josrXnZsdJWkNGZlFZM62EnLc1ZGZmZJZ0zvOx2BrJXfU2Wg/Xmg53X33xoczMjNzihl43b4Ld23jDf6e9ooi0ftxKOrM4Jv9Y3NjHq537pkSoVgoF3X3N5qOk6cxDxZb2mz5eZ8JL0TWEpciIcotPdox5uDMoK/nxN26PrdmUm5mRmWuqV8bLhyku5QudOXq8uU804t7vbzpOhkYqsXSMMl8CR4eJoGgc5S2GlvpPkjKV3S/sbBDhIPYQxyAAAiAAAiAAAj8igRRrzdUHV78++q/R+jJWce584zc/O/x137QvnnxJFo771jytTnOo2GTQ7di1U6PVabQ6Q4WlTK/bsfutNPpjmukSUZPTzdlanSa9blRuern7OCls+obIuMBApUGr0+jfyi4uPmog9aQVdMyRkrZyUomwSj5QSVqpELVmrsm0V7Nrbwa9UaPV51kdVBKxe4tMJn3arp28M5bybF3a7rd20L5pDHVMkM1ZCyLVBh0tBXqNVrfDUGQqNv5Er9No9560LZM6E19S1RCW5jqKaBM7DZmZhl1kpGkFVjsVf6zkIVOxQav/yW4Zmkwpdl6WbDUZpDNkgBkUqT6z4SadU4c1j/Rtp6Gw2GSklwyWG0tSKOxoytZptHtqWLGwFLhiJjWwiYhtAmdAAARAAARAAAS2FYEUak3PUOPh41Gy8s2f/v7QLyr45/cxls7SX1cNPUiVOYppTe2e8l5q+RtvJIJS+dFBlai2oJ2YD5kAymyapDopaCsnOsncTbSRdKOCqLHyb5ksXu6ryDWVN1ID3ka0ZkTGeb5lmtXcR6pl9+rymqn0XOwpIy3yH/395ek6jVZ/0kYaVSlFWUBb7eyxm7QeLTSf7BgjYUOJL6lqWOqnbRU0TbPByuL1aAehJJdMN3czq+p0M9HrMiVGIPKvvdlIdGpxB7EWhyVPb2U6V42yZj3HhLU0ca7o6HFL+02iidml9Drmfrrc9zuiVsuuULm8rX6XUvXcAgIIgAAIgAAIbGcCKdKaK+MXPxBWzN/8Rd3/XbztDKxGdIn8xby6Mn278091h8TCOW23njvC+mnf97LWrLwhTxiTd8qPjpZDEaskE0DZTPkNVKZpdWm/k+O+b1iIGDIca+6bdHuo+uSNbkRr6ssHFAisRaYgo+7lC+58DbqvnApceq+s/5i5dL6DiD+98WTHmH1Brc8SX1LV8C01vh7viTBnZ6hlUVWScFNR4gNnI2KXuECnkAMLPg/t1VwbscWmGS3tww4PdVSI3MvmJbN5gthiqazXM/2tgMIBCIAACIAACIDAdiWQCq25Mtz2a0U77vh91T8ebIDOg4Gq/32Te3O++Yu/DEekT7K0/DO0plreLXQc1eo0eda5sDRavUej1Zf1ciXnt9Vky6vJbPG65lvmdhmlF6VQnDV0YYVdMZESBRl1r7ozqpLc1igvzUv2tmK6dE7EKFnZZ46eFFqiS6KCFI9l/cdA0bHHXI3uWEQyRg9BPelBR7tJdlQgonO3scx6h0+xr71Ip9EaiWF1uC5dkPVC5erakvVIoB4QAAEQAAEQAIEUE0i+1py9ErFo7v+qz7PxSPO1B1ebFQPnm//e7Uyy1NiU1gwzAVTQcn+sJl2n0VfeUIJX6JQE5u/cuGxtOJ5LPR33UnfDKL0ohZiBUOWvKZr9fJ0mxVoZdW+0pJMX7mPtmuz5CC7bh/vbmytN1F1S5U8Z75KoID3fFBORWt4foW2zEIfRTWtNCkqb2+JIrAv9jtHejqby4gziIaBn/q9ktb2jiDgMWN2jdUTWC6bfxFWl+BcjQgMNgQAIgAAIgAAIvACBZGvNuc5/L5V9NPeffQ7b5MrA2fdk62bpB62upEqNzWlNiYmwo+WVGVpderWSzNI30dvTUt8xylfP2ep2ntUdCt9pyqQOoN8yC+hyX/keIuNUWlOXrYS3yx6ixZ0k4Po5tWbAYevraG64wuPZHdZDxJ+SOAY85ZKoNXkgVGUfX9qmdlwdc6BUlSTPWbQI9kyOTcgB47KrZWSAkzTE6pDVHl622/rbmxu7uUuA/VyuQEYKLV4yEXVbbEqnIVlqWQ/ZBwIgAAIgAAIgsH0JJFdr+v7xhbwOvqO6fXrjFk1RLK85W6t5JV90sxxDyeG7Sa0ZWuopYwHg2j01w4rqlRWVobCxvbe/21qZTUx0dP03LI3W7ZUXsmmIenY2iZVRa809BsPO7BLLSYv5EI34NlhsdCn5ObWmrBT1xnJrT19vR0Mh6YDsWsqi6eNdUivI5RsV9K6M4pNWa1OJkRg19cWdC2TI6pIxWpN6smr0FtkFlgebHzquDFCf10Z0sBw2ZKxsudzf19F41EDsmhG3hLAc6a9RyXqFOQ5AAARAAARAAAS2K4Gkas3bjftZeqPS0n+8SHLEQJ9ZNo7ur7uVPLKb1ZphWVYKyY9oZ/x3Wo4b5TxExPWwoMHGU1r67zTJXon6jJJL9jhr6AUt47aTLDGQlpaRbXjPqzXD0ty3dXm7aaYhoox3Zh/vYOmKiFJMcClaQQbdfdXMGYCs6e/INnfydfDoklF2zfHGDL0ujVgu5WkKjFs/lken0+gzP1acMkkTBRG/0l3Gsg45Jp29SAR6zTTTUyT5UXJeMHjHUBsIgAAIgAAIgMBLIZBErbly9SvZHplzcWqTg1kZv1hafCXioDn9t1+zlfQdXw3wCJLkic4N6w/qPqjLUFa9xRuDy54FX3RINSsQXA48axU4sOhTx7C/8Oj8Ps+CL367T7kUOyLuG7DRGVziIVNiVaTFeOfDEolMX4x/aaMtig3hGARAAARSRyDom7jcXFZIdso4ery5e5KbFZ7a4tyVxpMWC/n8XfVGHQq6b1gtdFOMBLXdt7XUs405isqae7h7Ev92EDpzqLiyqdcR/Qd/8U63vK9HvNuf2ufX6M/vfVuLRd5O5aTVxjL0PWv4y6NtdEItlqYB1TPgmeyR9yjJLY5TG52ycrrzy6FiS8sA93ZT5kLpTGZRWX3HKF1OVHVGKRC3fqWeLX+QPK25NlwlGyM/urg5o6aSIOlnEbm52FksZ4CvvPojbCkUM09zwz19HRa6Pq6KHFc9BDF34SoIgAAIgMArQoBvh0FcoeSPsvsG13+x3wILl0w0O7LgQEULL/SXEd8h8aOqLTBgoUGTQgF9QdMkfzMPOtqLIvlPWD07iiKrWCHZhUl1+9MiNWN7/hqckbdiEWfBUHmDxyokfG5v1pENXOiHxmaw2V+eaC5gG69EplWsLd6UGX7Xr3gGxpvxzJMDfMaVjWN406QVsf5tNV/J05q3G99h6tDSPrsJBIrQJBFFQjiR7x9fsBijN6vGEv9Wb6KhTVXCImDIkvTRNvWLaapa3FT3UBgEQAAEQCC1BCaaqMO9dm9Zx525+3faf0fd8bUs60iippe7jyseTYqzvhRSPLIM5vZJt2fB0VfBKmexoVJoyUY37NClFTSP3vd57o810Q3hlO3iPH8vobLGWN7r8Cy4R60lVP1wr/fgHboBm05D65+b7JB1Ld9tLqGKeq2+0fzyJilpBXU3pn32gTq6m51OlbklFojCNkprsogIrT6vzmZf8M0NW0lsq1YOq41EO2j3ll12eBZ89stmNmU8AcudBvrukW6ykhmf7j9ppE9OdrPsk/Z8vY3t/9Y4kzStOXvlA7bq/U7brQ0/1omEJvk1nr54iFV4uDtlOwklngOyxr2Q7GXuxM1tmFiiP3A4DwIgAAIgkDwC8nZxQhKSIEvrpkvjuY1j/24HvqWbpaVXlh+jZrBISUd3NVmEjazA+ns+ptpFTvHGMs1pi9qVVVSW45nngGNp7zSRTTfY3hkkVRzpBgvTFMNYaa5ipJAT50gOPxAgs3R7qp2lY76m7efoptB5leVktxcOPCx5bFbqKXFJCVeYaKRvIzRdYCjsbi+g0jOSxIbl6pbzCcob+2mFNIgswIOmkRGkauSR2EhvxfFuqeOkac2E0tDZ2Tq6Em/MTxOaJOfitVLZZfMvw/FuT97flJhnC82BAAiAAAi81gQmmzOIFpR3BmYo2KZxGrbJWewXh99WzjJsXFmWpWFEa0Z/Yclb+OpLaM47vvGHtrJP8fXniVAO8a19VdMRvNNAUuzpmJFsoimTLLAqKUFI32wn6VJ+/HiD2M6/+md4tpOCjjllsGx3vafsiix7JhibJh0teSqtqZoOsumdo4kWMNTfoZfk1VFx+uRpEmdZ6UlYClwuIZOYXjdKTj5Xb4Xaorv3si8lTWsOnJXTalaNCr9UznaabvO9qmi5+QyhSTCNVjGt+cZZaE0B6ct+YrbaE4z+gAAIgEDyCbBd37Qqf31uGFN2Nhb/Mi/fsNDkcXR338Ra09aQmZlhIJ6XO7LNLePcOU9Ok6LP48rSfo77AsYTrPLVdDkvstycbFFjveKeYPFuTz6ubfDFFBcIywATsVaqybjbqSeDoW6M55aOU3Lum5KMzEySZUX/Vl51vxJsdKOCrokbKvtYBMtiP30ViWyFrWqLX+UPwHP0Vnwat9xx8rWmeVCxYj64WKtsOynKzfhCczW4tuh9ODu/4Lg3Oz3jnLI7707fG5mcuDg2s+h9uBpcU03MNniyt9xkAyAIgAAIgMCGCGxWa7LwEX1BO92x4ilas5yHeqi36pXzHNN9j6kY1RuzqeWSZ2hWvlCWJ5qYDN1bzuNIoDU3MKebVm+eb4qJj6zBcoOkZ5FvF2KD5BnhbyAkwMNQWNc3z2dKidbSv8XEqJxyW/0CQ3o+38P8a9MKrDxl4aZ7uwECvGMvQz4lTWtOdx2N414ZmDrDE7O/8RsmN+MIzdXgmnthcXrm/oLHu7yyKj169OTJk/X19SdPnkiPHi2vrC54vNMz990Li1CcW/x5QvdAAARA4FUgIDtQCu50YUne8Ey1VE2/v3n4iCJEEmtN+fve01upjhSRQkF3X31xNtnjg0kWtUemrA+WR+vodhvaiNAMhaV4i/vy7WkW26swHUmQR7IDpeDzKoWC/Uz6sz1HVKDk0Jw9XNAn1JryXUt3WtThXKGwFBjvKC94K43k4TaWWe941B6Z8o2OSx/TICFBaBJpy9w9N9rbJPBJrRJNmtYMDFbKS97NA6oJU8vNkkZht3S6ieVDf8DucHl9/sePH68n/u/x48den9/ucD30B1T1b3nE6C0IgAAIgMA2I8A2ztXqjnYo+RR9nSbisaehq+Sq4cgr4PQqN1uSkuRDV+FZPmZVCmS14Sq2gBwbJGxvEfT10T3eNHpVZhwS3vBNMW0rEkcib/zLHTpVvX1dvzRZwmziEKk4xd6sSydzJEBW4MiG7bhzSp0oaOJqVbroKFs4KyAkVGL7P6uen2kri4VXpa+ifdhcb5Vub9WDpGnNkKv9MMt5ZG4cjhqtSm6qdktf9PkdztlgcC2xyFRdCQbXHM7ZRZ8fvzkgAAIgAAIgkDICvvYiqjN4RkMlNaOsPv2O7ubGduZw+UytyQN9DBX9HiZ0ppvzqBhNJ76AkrIlcl7jGCkQdHezFEtK0qKgo/MYDXPWG2uGuZen8lUrC1OdoYJteqysyAvqUyn82h7w2Pw8K01lqORP5epzzmZtaOYOl8/Smjweq6Blmtm2fX3le6jil/NYyQXSzZ3UrcJzs5nKSj3PeSQFhutoDm+d4dglvnQuGBef1duUPflCH5L3qCRPa4anzlQwHRlvY0m13GR5NB/6Aw7nbFiSVHLyh8D00N/O/PGPVeTz5697Jlwh1fWwJDmcs7Bubq/nDL0FARAAgW1GQPG327U3I3OvvC9xdvMEFYuy2Ulf2Rdvr7XYNfTR+kw577f+LRYbRHQJ9+8MhSW7lQcDyQZRnUZYKBecAtWWNh76o9y+wyDHHmm0uuy4m94lT0BsswkNKxJc/5OMzAx5b2d92RWq3bklW4wcFwYYs4a+cOlj4vBAPjsMNDaIHhssTO5LITkvgWq+hIVyOSyJ1SD8q4SjPbW3220Sk6g1pcjGkn/ui7OxJJebTGiuBtfsDpfaohma/uun77PJ2/Xz/VlZ+9mjoN99+NSA54eI4gzSe+G7KfwapORFBPWDAAiAwOtMIDBu/ThDyc2u/4mpeYIviXr+XrJDq0sTE+gIX/+xWjMUXp7oqMyT9Y3ilCn+6V6esJqpvyZRJ2m7CxpsyvK99EytSeq3lkR2HtK/ZWq+E+eLWOjk6zizQXdfda782qDVaXYZy6/wfSODYw1krveetMWYjQm0GK1JYnr6G4qNSm3qYC86s/P9NdRfk0rJndnHhX2ews/UmtSFN1Fvt9s8JlNrhgJ9Znmbyv2VQ0o0uvC7FJhq7R5mT797YdHr80f04w+B63/4uUar3//btnGPYMlcnb1+6lfkV/rIuenVSHGvz+9eWHwdf1W22xOGOQIBEACBbU1A3tqDq8zIWPxxRYnwlRf3zzV144veylwoSZqLbUsoEOlA7MlYv8/YMjiTiFJwORDPSv004CSz5jLZ+eUpU0YLPGXGN1S/ytn3Wc/Y1pvipGpNstnPr+UIodIPWl0JcawG16Zn7ovBQNPNv9Rof15yaTYiJ4Wj0N1zh/W6tP/uVUTo48ePp2fuw7T5jGd06z1w6DAIgAAIgAAIgMBrRSDJWjO0NnXmhBz988anVQO++HJz0ftwweONiMkHbYe1uveb7ZEznu6SrKw/jUROhAb+8FPtnsohRW2uL3i8i96Hr8lsLfn8S0roXFwFGVzxfh+f9rZHtOz3Lr+iQ4s7lTgJAiAAAiAAAq8QgWRrzbAUcrG9gqji/PR/LjrjqITZ+YXllciK+Hj9Ho3+0+sRGbm+TtVn5VBEa66vBy5+oNP8Z3eAn1teWZ2dX9iskPLe6qz9r9z8nNwPS08PJra8brZasby701zZ+Z14Jur42cIx6glznT9W3rsUdVL4cclWn78vK/9g/QgJYFzx+uI5MAjlo/oT/8f5zkpzp3uzd4nlhRpGvsw9NyyFwv5r5n05pyfjtyjeKx77ei2m8y/UE7E2HIMACIAACIAACPyIBFKgNcNSYOovdGtKZuD82eGvB2bVdinHvVnp0SMuGme/ztFpPhvgP9L/x9Ga6y7rrzTaP1znQULSo0eOe7ObUi3ONtO7/1Zz7bbL6/E7B0+XHsg9dzOOFN5UnbGF3W2mY22u2PP8jOtCkenCZmTu+Kn8JiLUEn5GqgyWK1xfus4fK0qGMnvxeoQaRqoMtYO0/67JKU/CgSQa4/gpo+UqH2BiDolux3kQAAEQAAEQAIGXRSAlWpMMxtlZ8ilfTCd5N3+W88Wp1uu3pn0+z7I0PeNkOwNRXTlSqdUd/qsnVmuW9IimzvX1oT9otEe+fiAXfPLkyfSMcxPgvu+17Ku4Ji7rD9cbP+n2Mu0SdI20nW6ormm9POPlq9XOLuvIvGvwTE3Dl53jHinkut5aXdNw5rpbLjDT0zLknacnWQFalUpruoYufFnTUH322l2WE9Q/0vL5sQNZx07UNHTNyJ2PLqOWYsGh2r2fD/IuheYnu87UNFSfvjAoy1lnV435V4bC0pqGliGvZ6j1hMl4wGSprum5S+sJ+qcun22orjnXNsS7LZFx3Zvs+rKm1RaTqVQeY7fzlkqzeu92k7F/eX5EUMnuW52xJzklVQ2K1vTarKxRr83ac9s/3nmajMUmmIHjTURosObdqqENzvXGa3ZfO936T7npqU6Fxsr4+fprdvUsQOCCAAiAAAiAAAg8F4GUac2wFApMtTYe2sESvKv/nbI7BWVJtGaOVR0VFLKfOaLX6I+cuSvIzQGV1lxfX5+yb0ZrDtakn7geX68EXRdMuZUtQ07X5LXqwvyqIbZgPVKVlf9J/bXbM+PWUuOvCs0nOqfsk12fGY2naPbd8FDtgcIPzadH7K6pyzWFByoGqZCNaM17548dNLcOzrhvd9YezG2wrYTCK05bZ21Obu3F64O3qcqJU0atcu6ezVdWkF3nj+0rbLg86XaNXfjEaO4iNXhvXz/3kaH0q+uDNtfS966Ri5/n53zede361AJZsx6pyi2s7p5yzYyc/iiL1zNSlZVTaG69fH3kntpYeLM+x0g67Lx5vrbQaOT20aXBmnxqD6bGYFMXlZvu87KR2H3TajaW9pDmpFCCGhStqcBxt5lyDpqbKByLMat2kPZEmIiuE7n51fJEhObPHztQP76xR/yZNUem+KbysjHWdMCQzhwVgkO1+yoGX1Xn140xjP9rgntBAARAAARAYPMEUqk1aW8CroE/1UUrzrvT9wS7pufiEZ1GiDGXZehqtNycbs7S6P84zFXqZu2a7jbTh9b4S9tLVyve/UxxiJxpzc9vpWYtopD+yZTfUO2eimtMf0SWhodq93zUxTRWWHK25Be2EFMll1Mrg58ZI2vft07nyzZUcQ09URlBbg7WpAsmvSXFG+GfnyvnFSVHJEKke1LIbi38qFM23Ib918qymqjPgDAuoaHwyrXyffJKd1gKDddzrTnTmh8Z5tJls/ELKrWDK0q40uAJtkSeqAZJ6SGHQygp0+HtKmV1Ll2tyJF1vBQKTp7LKe2RF9yHavfUjMQ830v2oRF7tGk2Uc1xpjg41nSATuvds4VV9U3GGuLwerPe+FTvWOgwEAABEAABEACBjRNIudaUu7LsHO79S92fP/pFxXv/+pudI5MTgr/muqvllxrtf1x8yFWk8v8fZr8+otfs/2I8tL7+g/3M+7q0TwcUO+dm/TWXrlQo4iwKkCKA2HlFGCkHobCgdSJibqg25+yUIoC4KOS1uS4U7cs6SOKQyOdg1tuymVDUmonKCBKQV0v75ndePltbWkgqPLBPGY7QT7XWHKxJ32eUO5CTm7NPdppUlVf6HxY7JtYzVLtnXw4bRU5u/nu8Xd/MtTOfmwtz8w/mZsk1J6ohvtaMeLXyMbrbTG8f4MRycrP2Ko6tAv9Ih1cGP9v39onrUVFTnD9lKNQcaS4c6c9IFZHX7jaT5Yp/pMrYdFOa+io34vwaaUuYEZwEARAAARAAARDYMIEfS2uqOxQVh77+sPu/9LqffhbRkYraXP/B46KenK6/HknT/rxuInJl03HoLroOqzg+hqWQ/XxpebebWiIVG1soLA2e2NdgI9pC0GSC1hG1pmBsW7pS8XY18SnkWsd1oajwwr1YjSIKskRlhLuEpX/vZXNOebeThZlzFaXup6gRpZBwryivhXEJDRGtKXT4nvVDWRwP1e4RHEblqfT3lBktXTMsGxGvMFENEZIcjkKJdoCPRTRJih0OBa/HtWuqyvBnTGmCXE1QszLFxJL6RW/PJ9SAOlhT+FXvhSLFmCrCwTEIgAAIgAAIgMDzEHg5WjM6v+b6uqfjSJpW/379SICHmUdE5fq662+/fUere+ePI4pRc339OfJrroxUG3M+65ZDZDyTraZ9zOWRrDUba0ZY2NC988e4ux6XUFJCu+aerNp/0jVc4mi4j8VKK1qHrKrz/D5Lg6ct1klqgfuuy5R77pY8WwnKCHM5f/7Yv1mdVEiJUmz8lDG+XXP+/LGc01NMUrNwKLYMHXR1/W8NS/MkjEtoiLoB5HBf1anT+emy1iTmQ8tleanaef7zhmuukChMg2NNRtli6mzJj1fDRrUmmYh83nnf0Lly6zjzGbhn/ZBDiKsvxZMKf1FrJpri0Pe9lgNZsrfA970WozEn4nWggiM2gWMQAAEQAAEQAIENEng5WjN236D19XXXX/+D7EW5/7dnhmYDLPlmKOCx99Yd2Z2m1e//rFfcEv059w0Kfjd4qvDdPftyDma9vYE2BOoAAARVSURBVC/f0sbEH5EUzi5z/gGy3Jx1oPDcsKyrBE2WyK5prq3OpyvaWR+eHmOLuRGtE3T1mHOz3svNzzFmHTT3cBun9+rn+fuyCr9iXo/xywjzN9Oazy1tvqGGg1lkOftgfkOVOb7WDH937UTuuwfyWTqnpeHTHx7IiuqhMC61nAq6uj7JIh1+L7/y8vlaHhsU8o2dK8wi/gAHs7IKT49TUU4Chiix/Pya2jKe0ihBDUqLChzlgIyUWx/Ficg5kFvZJfvXertK87/iYfvcfikgUo3imTWLUxwiXqoGXrm/5xODuNSeqAmcBwEQAAEQAAEQ2CCBl6M1yUJz1H7o1IwZmGgzv7+L7lKvU/5N232krl+dEWl9/QX3Q1+Km+08uOL1qOOynyFruABdfuqmPhvZ0eepZdxtplIhOfymU8GHpc3d8n2C4cTu35OIWKIansEzIhmXVBPxXddHcrTWBh/rhMUSdXjDHUtYM2oAARAAARAAARCIR+Clac3V4Jrd4QoG18S1cnYc8tiH+weu08+4U1w2l8sG6b1bYDN0rjXjkU2mKAmOnSs9K68mp7qtrVf/0q2z5i948qOt171kTjRGBwIgAAIgAAKvHIGXpjVDYemhP+BwzoYlKVZuPuVMWJIcztmH/sAW+I7/buraJM8oFLHJbYGOoTMgAAIgAAIgAAIgsCUIvEytGQpLiz6/wzkb17oZV24Gg2sO5+yiLzqlIuQdCIAACIAACIAACIDAFiTwkrUms27aHS6vz//48eO4+pKdfPz4sdfntztcW8OiuSVeFLbg84QugQAIgAAIgAAIgIBI4OVrzVBYWg2uuRcWp2fuL3i8yyur0qNHbFehJ0+eSI8eLa+sLni80zP33QuLW8BHEyoTBEAABEAABEAABEBgowS2hNZk4nc1uLbofTg7v+C4Nzs945yyO6dnnI57s7PzC4veh1CZ4isCjkEABEAABEAABEBgWxDYQlpzW/BCJ0EABEAABEAABEAABDZOAFpzoxbgjTNFSRAAARAAARAAARAAAUYAWhNaEwRAAARAAARAAARAIFUEoDVTRRZvMyAAAiAAAiAAAiAAAtCa0JogAAIgAAIgAAIgAAKpIgCtmSqyeI8BARAAARAAARAAARCA1oTWBAEQAAEQAAEQAAEQSBUBaM1UkcV7DAiAAAiAAAiAAAiAALQmtCYIgAAIgAAIgAAIgECqCEBrpoos3mNAAARAAARAAARAAASgNaE1QQAEQAAEQAAEQAAEUkUAWjNVZPEeAwIgAAIgAAIgAAIgAK0JrQkCIAACIAACIAACIJAqAtCaqSKL9xgQAAEQAAEQAAEQAAFoTWhNEAABEAABEACBV4rAWigcCktroTA7UNQeOyP+qxRTTrLCyo2xlSi14WCDBKA1X6nfrg3OOoqBAAiAAAiAwCtDQJGJ7CC4FloLhdm/7CAUloJrIfGMUoadF6+K9ypCM5F4fWUYpnQg/w8Of2+eP37M7wAAAABJRU5ErkJggg=="}}},{"cell_type":"markdown","source":"![image.png](attachment:801ac296-d840-49ee-a0b7-8ba63160ebe7.png)","metadata":{},"attachments":{"801ac296-d840-49ee-a0b7-8ba63160ebe7.png":{"image/png":"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"}}},{"cell_type":"code","source":"0709的成绩:0.43920,0.43920 最优成绩 0.40107 这个成绩相当于 46%的位置(507/1232 )\n\n0712 经验总结：\n1 本次数据集是ImgaeNet的子集,应该用在数据集训练好的模型。\n1 cosin优化器的T_max参数调整和epochs一样,这样可以把正确率\n2 采用模型是 models.resnet50.\n3 在原模型最后一层加入nn.Linear()和sofmtmax()将极大降低模型正确率。\n4 衡量模型的最重要的指标是trainloss和validloss,随着epcoh loss会降低,但是会降低到一个点位无法前进。\n5 最初的版本是train和valid都采用一个august算法,后来调整为valid和test为一套augustment,感觉效果不明显。\n6 Fine tune 对提升准确率确实有帮助。\n7 所谓调参,无论是lr,epoch,优化器等等对于结果的影响都是很微小的,主要的还是模型的选择,数据样本的多样性等等。\n8 简单模型如  models.resnet18带来的准去率非常低,0.10+\n9 一度怀疑是训练集和验证集的分布不一样,所以random.shuffle()整体打乱训练集合,但是效果有限。\n10 对本例来说,lr设置为e-4是比较好的,lr太大或者太小效果都不好。","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"##########################################\n####library\n###########################################\nimport numpy as np\nimport pandas as pd\nimport itertools\nimport torchvision\n\nimport os\nimport numpy as np\nfrom tqdm import tqdm\nimport random\nimport glob\nimport matplotlib.pyplot as plt\nimport torch.nn.functional as F\n\nfrom torchvision import models\nfrom PIL import Image\nimport torch\nimport math\nfrom torch import nn\nimport torch.nn as nn\nfrom torch.optim.lr_scheduler import CosineAnnealingLR\nfrom torch.utils.data import DataLoader,Dataset,Subset\nimport torchvision.transforms as transforms\nfrom sklearn.model_selection import train_test_split","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#########################################################\n#### Split train and validation from dataset \n###########################################################\n\n\nroot_dir = '/kaggle/input/dog-breed-identification/'\n# Read data labels\ndf = pd.read_csv(root_dir+'labels.csv')\nlen(df)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df.head()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train, valid = train_test_split(df, test_size = 0.2, stratify = df[\"breed\"])\ntrain.head()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train = pd.DataFrame(train)\ntrain.to_csv(\"train_split.csv\",index = False)\nvalid = pd.DataFrame(valid)\nvalid.to_csv(\"valid_split.csv\",index = False)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"####################################################################\n##  transform_train   operation \n####################################################################\ntransform_train = torchvision.transforms.Compose([\n    transforms.Resize(256),\n    \n    transforms.CenterCrop(224),\n    transforms.RandomHorizontalFlip(p=0.5),\n    transforms.RandomResizedCrop(\n    (200, 200), scale=(0.8, 1.0), ratio=(0.5, 2)),\n    \n    # 随机更改亮度，对比度和饱和度\n    torchvision.transforms.ColorJitter(brightness=0.4,\n                                       contrast=0.4,\n                                       saturation=0.4),\n    # 添加随机噪声\n    torchvision.transforms.ToTensor(),\n    # 标准化图像的每个通道\n    torchvision.transforms.Normalize([0.485, 0.456, 0.406],\n                                     [0.229, 0.224, 0.225])])\n\ntransform_valid_test = trans_test = transforms.Compose([\n                transforms.Resize(256), \n                transforms.CenterCrop(224),\n                transforms.ToTensor(),\n                transforms.Normalize(mean=[0.485, 0.456, 0.406], \n                                     std=[0.229, 0.224, 0.225])\n                                    ])","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"###############################################\n## define labe-index pair \n############################################\n\nsample_submiss = pd.read_csv(\"../input/dog-breed-identification/labels.csv\")\nlabels= sorted(list(set(sample_submiss.iloc[:,1])))\n\nn_labels=len(labels)\nlabel2idx =dict(zip(labels,range(n_labels)))\nidx2label={v:k for (k,v) in label2idx.items()}","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"len(labels)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#############################################################\n# Define customized-dataset 1/2\n#############################################################\n\nclass DogSet(Dataset):\n    \n    def __init__(self,csv_path,img_path,mode,transform):\n        \n        self.csv_file = pd.read_csv(csv_path)\n        self.mode = mode        \n        self.img_path =  img_path\n        self.transform = transform\n    \n        if mode=='train'or mode=='valid':\n            self.transform = transform_train\n        else:\n            self.transform  = transform_valid_test\n            \n    def __len__(self):\n        \n        return  len(self.csv_file)\n    \n    def __getitem__(self,index):\n        \n        if self.mode =='train' or  self.mode=='valid':\n        \n            img =os.path.join(self.img_path + self.csv_file.iloc[index]['id']+'.jpg')\n            img = Image.open(img)\n            img = self.transform(img)\n            \n            label = label2idx[self.csv_file.iloc[index]['breed']]\n            label = torch.tensor(label)\n            \n            return img,label\n        \n        else:\n            \n            img = os.path.join(self.img_path + self.csv_file.iloc[index]['id']+'.jpg')\n            id = self.csv_file.iloc[index]['id'] \n            img = Image.open(img)\n            img = self.transform(img)\n            return id,img\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#try a test \n\ndogset=DogSet(csv_path='./train_split.csv',img_path='../input/dog-breed-identification/train/',\n                mode='train',transform=transform_valid_test)\n\ntrainloader=DataLoader(dataset=dogset,batch_size=64,shuffle=False)\ni= 1\nfor batch in trainloader:\n    X,y = batch\n    print(X.shape)\n    print(y)\n    break","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#################################################################\n## define dataloader ,validloader and testloader\n##################################################################\n\n\ncsv_path='../input/dog-breed-identification/labels.csv'\nsplit_train='./train_split.csv'  # train after splitting\nsplit_valid='./valid_split.csv'  # valid.csv after splitting \n\ntrain_img='../input/dog-breed-identification/train/'\nvalid_img='../input/dog-breed-identification/train/'\n\ntrainset=DogSet(csv_path,mode='train',img_path = train_img, transform=transform_train)\nvalidset=DogSet(csv_path,mode='valid',img_path = valid_img, transform= transform_valid_test)\n\ntrain_loader = DataLoader(dataset = trainset, batch_size = 32, shuffle=True,num_workers=4)\nvalid_loader = DataLoader(dataset = validset, batch_size = 32, shuffle=False,num_workers=4)\n\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_device():\n    \n    return 'cuda' if torch.cuda.is_available() else 'cpu'\n\ndevice = get_device()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"####################################################################\n### define models.resnet152 and Fine-tune  resnet152->resnet50 ->models.resnet18\n###################################################################\n\n# def resnet50(numclasses):\n    \n#     model = models.resnet50(pretrained=True)\n    \n#     for param in model.parameters():    \n#         param.requires_grad = False\n    \n#     model.fc = torch.nn.Sequential(\n#         nn.Linear(2048,numclasses),\n#         nn.ReLU(),\n#         nn.Linear(512,numclasses),\n#         nn.Softmax(dim=1),\n#         )\n    \n    return model","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def resnet50(numclasses):\n    finetune_net = nn.Sequential()\n    finetune_net.features = models.resnet50(pretrained=True)\n    # 定义一个新的输出网络，共有120个输出类别\n    finetune_net.output_new = nn.Sequential(nn.Linear(1000, 256),\n                                            nn.ReLU(),\n                                            nn.Linear(256, numclasses))\n#     nn.init.xavier_normal_(layer_1.weight) \n    # 将模型参数分配给用于计算的CPU或GPU\n    finetune_net = finetune_net.to(device)\n    # 冻结参数\n    for param in finetune_net.features.parameters():\n        param.requires_grad = False\n    return finetune_net","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#########################################################################\n## traing function\n#########################################################################\ndef train(model,num_epochs,trainloader,validloader,learning_rate,weight_decay):\n    \n    optimizer = torch.optim.AdamW(model.parameters(),lr=learning_rate,weight_decay= weight_decay)\n    \n    scheduler = CosineAnnealingLR(optimizer,T_max= num_epochs) #T_max指的是经过多少迭代完成一个T的更新，这里就是每个epoch迭代一次。\n    train_loss_function = nn.CrossEntropyLoss()\n    valid_loss_function = nn.CrossEntropyLoss()\n    \n    best_val_acc = 0.7\n\n    for epoch in range(0,num_epochs):\n        model.train()\n        print(\"#########################\")\n        print(f'Starting epoch {epoch}')\n        print(\"#########################\")\n         \n        train_losses = []\n        train_accs = []\n         # Iterate the training set by batches\n\n        for batch in tqdm(trainloader):\n        # Move images and labels to GPU\n            imgs, labels = batch\n            imgs = imgs.to(device)\n            labels = labels.to(device)\n            # Forward the data\n            logits = model(imgs)\n            # Calculate loss\n            loss = train_loss_function(logits,labels)\n                \n            optimizer.zero_grad()\n            # Compute gradients for parameters\n            loss.backward()\n            # Update the parameters with computed gradients\n            optimizer.step()\n            # Compute the accuracy for current batch.\n    #             print(\"logits.argmax(dim=-1):\",logits.argmax(dim=-1).shape)\n    #             print(\"labels shape:\",labels.shape)\n            acc = (logits.argmax(dim=-1) == labels).float().mean()\n            # Record the loss and accuracy.\n            train_accs.append(acc)\n            train_losses.append(loss.item())\n\n        print(\"第%d个epoch的学习率：%f\" % (epoch,optimizer.param_groups[0]['lr']))\n        scheduler.step()\n        # The average loss and accuracy of the training set is the average of the recorded values.\n        train_loss = sum(train_losses) / len(train_losses)\n        train_acc = sum(train_accs) / len(train_accs)\n            \n        print(f\"[ Train | {epoch :03d}/{num_epochs:03d} ] loss = {train_loss:.5f}, \\\n              acc = {train_acc:.5f}\")\n\n        print('Training process has finished. Now Starting Validation ')\n\n        # Start Validation\n\n        model.eval()\n        valid_losses = []\n        valid_accs = []\n\n        for batch in tqdm(valid_loader):\n            imgs, labels = batch\n            # 不需要梯度验证.\n            # Using  torch.no_grad()  accelerates the forward process.\n            with torch.no_grad():\n                logits = model(imgs.to(device))\n                # 我们仍然可以计算损失（但不能计算梯度）。\n                loss = valid_loss_function(logits, labels.to(device))\n                \n                # 计算当前批次的精度。\n                acc = (logits.argmax(dim=-1) == labels.to(device)).float().mean()\n                # 记录损失和准确性\n                valid_losses.append(loss.item())\n                valid_accs.append(acc)\n        # 整个验证集的平均损失和准确度是记录值的平均值\n        valid_loss = sum(valid_losses) / len(valid_losses)\n        valid_acc = sum(valid_accs) / len(valid_accs)\n\n        # 打印信息.\n        print(f\"the epoch {epoch} validation dataset  loss = {valid_loss:.5f},\\\n              acc = {valid_acc:.5f}\")\n        \n        if valid_acc > best_val_acc:\n            best_val_acc= valid_acc\n            model_path = f'./model-epoch-{epoch}.pth'\n            torch.save(model.state_dict(),model_path)\n            print(f\"save model at {model_path}\")\n    \n    return model_path ,train_losses,valid_losses\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def xavier(m):\n    if type(m) == nn.Linear:\n        nn.init.xavier_uniform_(m.weight)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"###################################################### \n## performing  training \n#####################################################\nmodel = resnet50(120)\nmodel.apply(xavier)\n\nmodel = model.to(device)\nnum_epochs = 35  #original is 15\nlearning_rate = 3e-4 # oringial lr =1e-4;2e-4, 5e-4, 2e-4*\nweight_decay = 1e-3       # oringal value  1e-3\ntraining_result =train(model,num_epochs,train_loader,valid_loader,learning_rate,weight_decay)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.plot(np.arange(len(x)), x, label='train loss')\nplt.plot(np.arange(len(y)), y, label='val loss')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"##########################################################\n####plot loss-curve \n##########################################################\ntrain_losses,val_losses= training_result[1],training_result[2]\nplt.plot(np.arange(len(train_losses)), train_losses, label='train loss')\nplt.plot(np.arange(len(val_losses)), val_losses, label='val loss')\nplt.legend()\nplt.savefig('losses.png')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"training_result[0]","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"################################################\n####  Predicaton \n################################################","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submis_path = '../input/dog-breed-identification/sample_submission.csv'\nimg_path = '../input/dog-breed-identification/test/'\n\nmode='test'\n\ntestset= DogSet(csv_path = submis_path,img_path=img_path,mode=mode,transform= transform_valid_test)\ntest_loader = DataLoader(dataset=testset,batch_size=32,shuffle=True,num_workers=4)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.load_state_dict(torch.load(\"./model-epoch-24.pth\"))\nmodel.eval()\n\nwith torch.no_grad():\n\n    dfs = []\n    df = pd.DataFrame(columns=['id']+ columns)\n    \n    for batch in tqdm(test_loader):\n        \n        id,img= batch\n        input=input.to(device)\n        img = model(input)\n        \n        output = F.softmax(img,dim=1)\n        \n        output=output.cpu().numpy()\n        df[colnames]=output\n        df['id']=id\n        dfs.append(df)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dfs_agg=pd.concat(dfs)\ndfs_agg.head()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"len(dfs_agg)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from IPython.display import FileLink\nFileLink('./ids.csv')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from IPython.display import FileLink\nFileLink('./dfs_agg.csv')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"***************************************************************************************************","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from IPython.display import FileLink\nFileLink('./mysubmission0710_v2.csv')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}