diff --git a/data/2024-09-21-14-44-50.m4a b/data/2024-09-21-14-44-50.m4a new file mode 100644 index 0000000000000000000000000000000000000000..099b8669d3f8acb4bd4192d06bab7d090d14c5b9 Binary files /dev/null and b/data/2024-09-21-14-44-50.m4a differ diff --git a/data/2024-10-12-17-17-28.m4a b/data/2024-10-12-17-17-28.m4a new file mode 100644 index 0000000000000000000000000000000000000000..ac7dcf023a97b9aaf185693bb6f25f9b1b31e936 Binary files /dev/null and b/data/2024-10-12-17-17-28.m4a differ diff --git a/data/2024-10-12-17-18-41.m4a b/data/2024-10-12-17-18-41.m4a new file mode 100644 index 0000000000000000000000000000000000000000..da501075da9d932d8951f2fa32a3ff7ff84014a8 Binary files /dev/null and b/data/2024-10-12-17-18-41.m4a differ diff --git a/data/2024-10-12-17-21-09.m4a b/data/2024-10-12-17-21-09.m4a new file mode 100644 index 0000000000000000000000000000000000000000..4585aac64e27ac35263570a3c17634fdf5895d6b Binary files /dev/null and b/data/2024-10-12-17-21-09.m4a differ diff --git a/data/2024-10-12-17-21-31.m4a b/data/2024-10-12-17-21-31.m4a new file mode 100644 index 0000000000000000000000000000000000000000..83a4002d871bee376f5a9545c144593e329fa367 Binary files /dev/null and b/data/2024-10-12-17-21-31.m4a differ diff --git a/data/2024-10-12-17-21-51.m4a b/data/2024-10-12-17-21-51.m4a new file mode 100644 index 0000000000000000000000000000000000000000..99e924d084ec041ca1adfcaae2abea01ddb0471f Binary files /dev/null and b/data/2024-10-12-17-21-51.m4a differ diff --git a/data/2024-10-12-17-22-08.m4a b/data/2024-10-12-17-22-08.m4a new file mode 100644 index 0000000000000000000000000000000000000000..02a8560ba41c19a2290bb836d490d3632d5e71aa Binary files /dev/null and b/data/2024-10-12-17-22-08.m4a differ diff --git a/data/2024-10-12-17-22-20.m4a b/data/2024-10-12-17-22-20.m4a new file mode 100644 index 0000000000000000000000000000000000000000..351233678ff038aad0b71496bc34378fd649d8f9 Binary files /dev/null and b/data/2024-10-12-17-22-20.m4a differ diff --git a/data/2024-10-12-17-22-31.m4a b/data/2024-10-12-17-22-31.m4a new file mode 100644 index 0000000000000000000000000000000000000000..e200112bf3d71d4e6fd330a0eb8357d3163046db Binary files /dev/null and b/data/2024-10-12-17-22-31.m4a differ diff --git a/data/2024-10-12-17-26-23.m4a b/data/2024-10-12-17-26-23.m4a new file mode 100644 index 0000000000000000000000000000000000000000..05c7425d63c41e0f867777c1ba030793bb241587 Binary files /dev/null and b/data/2024-10-12-17-26-23.m4a differ diff --git a/data/2024-10-12-17-27-28.m4a b/data/2024-10-12-17-27-28.m4a new file mode 100644 index 0000000000000000000000000000000000000000..97a7eda66c1b2441b074ec5c0d90fb1972d713b8 Binary files /dev/null and b/data/2024-10-12-17-27-28.m4a differ diff --git a/data/2024-10-12-17-27-52.m4a b/data/2024-10-12-17-27-52.m4a new file mode 100644 index 0000000000000000000000000000000000000000..16f1694964c5e37cad623e050ee7c92ce6251986 Binary files /dev/null and b/data/2024-10-12-17-27-52.m4a differ diff --git a/data/2024-10-12-17-28-24.m4a b/data/2024-10-12-17-28-24.m4a new file mode 100644 index 0000000000000000000000000000000000000000..f716c1923dbe6cee18030519e4e99783b1651a1d Binary files /dev/null and b/data/2024-10-12-17-28-24.m4a differ diff --git a/data/2024-10-12-17-28-56.m4a b/data/2024-10-12-17-28-56.m4a new file mode 100644 index 0000000000000000000000000000000000000000..93cd8866a32a22b8122c5e99523bb0151e93f883 Binary files /dev/null and b/data/2024-10-12-17-28-56.m4a differ diff --git a/data/2024-10-12-17-29-33.m4a b/data/2024-10-12-17-29-33.m4a new file mode 100644 index 0000000000000000000000000000000000000000..fcbb9b4d24126b689030e67f45ed1923d8b601ba Binary files /dev/null and b/data/2024-10-12-17-29-33.m4a differ diff --git a/data/2024-10-12-17-30-50.m4a b/data/2024-10-12-17-30-50.m4a new file mode 100644 index 0000000000000000000000000000000000000000..df2aa404029551c03d354337bf815d0298b1bed8 Binary files /dev/null and b/data/2024-10-12-17-30-50.m4a differ diff --git a/data/2024-10-12-17-30-57.m4a b/data/2024-10-12-17-30-57.m4a new file mode 100644 index 0000000000000000000000000000000000000000..8eff7917d0499c4428d6a4bcdb96079218b9a8d1 Binary files /dev/null and b/data/2024-10-12-17-30-57.m4a differ diff --git a/data/2024-10-12-17-32-03.m4a b/data/2024-10-12-17-32-03.m4a new file mode 100644 index 0000000000000000000000000000000000000000..238bcad83ed7e1fcd20f2846194878a9f98ece8a Binary files /dev/null and b/data/2024-10-12-17-32-03.m4a differ diff --git a/data/2024-10-12-17-34-06.m4a b/data/2024-10-12-17-34-06.m4a new file mode 100644 index 0000000000000000000000000000000000000000..e2703869b8abc89d724c535af326085cc4bc3bca Binary files /dev/null and b/data/2024-10-12-17-34-06.m4a differ diff --git a/data/2024-10-12-17-35-14.m4a b/data/2024-10-12-17-35-14.m4a new file mode 100644 index 0000000000000000000000000000000000000000..d456cab719c158edd216c255bfb6f9668daee75b Binary files /dev/null and b/data/2024-10-12-17-35-14.m4a differ diff --git a/data/2024-10-12-17-36-20.m4a b/data/2024-10-12-17-36-20.m4a new file mode 100644 index 0000000000000000000000000000000000000000..ff7db36af05f8e4567d348b27b855aae0d773ae5 Binary files /dev/null and b/data/2024-10-12-17-36-20.m4a differ diff --git a/data/2024-10-12-17-37-30.m4a b/data/2024-10-12-17-37-30.m4a new file mode 100644 index 0000000000000000000000000000000000000000..27d547ddb60038d13a2bca61b3d1741a04d3b240 Binary files /dev/null and b/data/2024-10-12-17-37-30.m4a differ diff --git a/data/2024-10-12-17-38-17.m4a b/data/2024-10-12-17-38-17.m4a new file mode 100644 index 0000000000000000000000000000000000000000..0b9970cdfab83fc5db889e38e85291f506932474 Binary files /dev/null and b/data/2024-10-12-17-38-17.m4a differ diff --git a/data/2024-10-12-17-38-36.m4a b/data/2024-10-12-17-38-36.m4a new file mode 100644 index 0000000000000000000000000000000000000000..57df1dfeed88f5f81e876ce6b477bc6164a5b9f3 Binary files /dev/null and b/data/2024-10-12-17-38-36.m4a differ diff --git a/data/2024-10-12-17-39-00.m4a b/data/2024-10-12-17-39-00.m4a new file mode 100644 index 0000000000000000000000000000000000000000..207023a5c9e1f9b1b376b94c20a37d42d10df131 Binary files /dev/null and b/data/2024-10-12-17-39-00.m4a differ diff --git a/data/2024-10-12-17-41-38.m4a b/data/2024-10-12-17-41-38.m4a new file mode 100644 index 0000000000000000000000000000000000000000..eec263d87240b8ce21f9b69c6ad50867c0a3ed23 Binary files /dev/null and b/data/2024-10-12-17-41-38.m4a differ diff --git a/data/2024-10-12-17-42-24.m4a b/data/2024-10-12-17-42-24.m4a new file mode 100644 index 0000000000000000000000000000000000000000..6131cc93ef8ea96cc128d86d5311350f27cde594 Binary files /dev/null and b/data/2024-10-12-17-42-24.m4a differ diff --git a/data/2024-10-12-17-43-22.m4a b/data/2024-10-12-17-43-22.m4a new file mode 100644 index 0000000000000000000000000000000000000000..0e91f709b3b7618f12e59091c2a4ab42fa4faee3 Binary files /dev/null and b/data/2024-10-12-17-43-22.m4a differ diff --git a/data/2024-10-12-17-44-39.m4a b/data/2024-10-12-17-44-39.m4a new file mode 100644 index 0000000000000000000000000000000000000000..79890c38a38441ef4cf3fb23cab9c0282769e481 Binary files /dev/null and b/data/2024-10-12-17-44-39.m4a differ diff --git a/data/2024-10-12-17-45-00.m4a b/data/2024-10-12-17-45-00.m4a new file mode 100644 index 0000000000000000000000000000000000000000..2eb2b37084316e4afa0a6ced0dc07f059eab6a70 Binary files /dev/null and b/data/2024-10-12-17-45-00.m4a differ diff --git a/data/2024-10-12-17-46-43.m4a b/data/2024-10-12-17-46-43.m4a new file mode 100644 index 0000000000000000000000000000000000000000..35efc0a15a464de755e2f72c261ce0f65f18f3e9 Binary files /dev/null and b/data/2024-10-12-17-46-43.m4a differ diff --git a/data/2024-10-12-17-47-04.m4a b/data/2024-10-12-17-47-04.m4a new file mode 100644 index 0000000000000000000000000000000000000000..be01b42842b02eca76ba6ef483e5cefe5f294be4 Binary files /dev/null and b/data/2024-10-12-17-47-04.m4a differ diff --git a/data/2024-10-12-17-47-17.m4a b/data/2024-10-12-17-47-17.m4a new file mode 100644 index 0000000000000000000000000000000000000000..f08af9e1daed17510c5cd7f6caaacf8160266e6c Binary files /dev/null and b/data/2024-10-12-17-47-17.m4a differ diff --git a/data/processed_audio__audio1_audio1_0.wav b/data/processed_audio__audio1_audio1_0.wav new file mode 100644 index 0000000000000000000000000000000000000000..73607e0ff02beb33897e13408e12debeda2952aa Binary files /dev/null and b/data/processed_audio__audio1_audio1_0.wav differ diff --git a/data/processed_audio__audio1_audio1_1.wav b/data/processed_audio__audio1_audio1_1.wav new file mode 100644 index 0000000000000000000000000000000000000000..b0e2d0feb02074a95df8fdca688c169da7f6745d Binary files /dev/null and b/data/processed_audio__audio1_audio1_1.wav differ diff --git a/data/processed_audio__audio1_audio1_2.wav b/data/processed_audio__audio1_audio1_2.wav new file mode 100644 index 0000000000000000000000000000000000000000..eb316ac2cd436812c5d0fac6d9ce01ebd3ce305f Binary files /dev/null and b/data/processed_audio__audio1_audio1_2.wav differ diff --git a/data/processed_audio__audio1_audio1_3.wav b/data/processed_audio__audio1_audio1_3.wav new file mode 100644 index 0000000000000000000000000000000000000000..7e733f4a6c983c2951ba650f3ec7283570418bde Binary files /dev/null and b/data/processed_audio__audio1_audio1_3.wav differ diff --git a/data/processed_audio__audio1_audio1_4.wav b/data/processed_audio__audio1_audio1_4.wav new file mode 100644 index 0000000000000000000000000000000000000000..6364216ef3d16e836c729ce967b87ba0390575f1 Binary files /dev/null and b/data/processed_audio__audio1_audio1_4.wav differ diff --git a/data/processed_audio__audio1_audio1_5.wav b/data/processed_audio__audio1_audio1_5.wav new file mode 100644 index 0000000000000000000000000000000000000000..773b1b629632c7a3a8dea5e929ec50be033db5b9 Binary files /dev/null and b/data/processed_audio__audio1_audio1_5.wav differ diff --git a/data/processed_audio__audio1_audio1_6.wav b/data/processed_audio__audio1_audio1_6.wav new file mode 100644 index 0000000000000000000000000000000000000000..5db0d3125d486200d46d3aef48738fd5b23bc7f3 Binary files /dev/null and b/data/processed_audio__audio1_audio1_6.wav differ diff --git a/data/processed_audio__audio1_audio1_7.wav b/data/processed_audio__audio1_audio1_7.wav new file mode 100644 index 0000000000000000000000000000000000000000..324627467f36af2921db18226893e3c30c762739 Binary files /dev/null and b/data/processed_audio__audio1_audio1_7.wav differ diff --git a/data/processed_audio__audio1_audio1_8.wav b/data/processed_audio__audio1_audio1_8.wav new file mode 100644 index 0000000000000000000000000000000000000000..6fee57b6c9360b0d356a87ee4f6f4e0262c9f7b3 Binary files /dev/null and b/data/processed_audio__audio1_audio1_8.wav differ diff --git a/data/processed_audio__audio1_audio1_9.wav b/data/processed_audio__audio1_audio1_9.wav new file mode 100644 index 0000000000000000000000000000000000000000..1159bb6a3c20ae45ce2b1a8af539a1865117c0d4 Binary files /dev/null and b/data/processed_audio__audio1_audio1_9.wav differ diff --git a/data/processed_audio__audio2_audio2_0.wav b/data/processed_audio__audio2_audio2_0.wav new file mode 100644 index 0000000000000000000000000000000000000000..e6473194c8caec4a1c0065757a6245ee8ece3a81 Binary files /dev/null and b/data/processed_audio__audio2_audio2_0.wav differ diff --git a/data/processed_audio__audio2_audio2_1.wav b/data/processed_audio__audio2_audio2_1.wav new file mode 100644 index 0000000000000000000000000000000000000000..4d93481393f8ef45d5b0f70b10748e442a3b98b0 Binary files /dev/null and b/data/processed_audio__audio2_audio2_1.wav differ diff --git a/data/processed_audio__audio2_audio2_2.wav b/data/processed_audio__audio2_audio2_2.wav new file mode 100644 index 0000000000000000000000000000000000000000..24434e58d4d61c6f6c699c4f8e3084cc8364e339 Binary files /dev/null and b/data/processed_audio__audio2_audio2_2.wav differ diff --git a/data/processed_audio__audio2_audio2_3.wav b/data/processed_audio__audio2_audio2_3.wav new file mode 100644 index 0000000000000000000000000000000000000000..a9347c04ddbb8b8c2bf44090569865939a25269d Binary files /dev/null and b/data/processed_audio__audio2_audio2_3.wav differ diff --git a/data/processed_audio__audio2_audio2_4.wav b/data/processed_audio__audio2_audio2_4.wav new file mode 100644 index 0000000000000000000000000000000000000000..4a52fc89a344a806a4aa41cdba0355a1b440e5bb Binary files /dev/null and b/data/processed_audio__audio2_audio2_4.wav differ diff --git a/data/processed_audio__audio2_audio2_5.wav b/data/processed_audio__audio2_audio2_5.wav new file mode 100644 index 0000000000000000000000000000000000000000..60d775ce2ccf0d39ceab727b1eeaf2ae9fea48a5 Binary files /dev/null and b/data/processed_audio__audio2_audio2_5.wav differ diff --git a/data/processed_audio__audio2_audio2_6.wav b/data/processed_audio__audio2_audio2_6.wav new file mode 100644 index 0000000000000000000000000000000000000000..800a430a8d18db5af247aaff0b33c424f682cd72 Binary files /dev/null and b/data/processed_audio__audio2_audio2_6.wav differ diff --git a/data/processed_audio__audio2_audio2_7.wav b/data/processed_audio__audio2_audio2_7.wav new file mode 100644 index 0000000000000000000000000000000000000000..00e71417c1e9c3e1db6481bbd861ad90ce758bca Binary files /dev/null and b/data/processed_audio__audio2_audio2_7.wav differ diff --git a/data/processed_audio__audio2_audio2_8.wav b/data/processed_audio__audio2_audio2_8.wav new file mode 100644 index 0000000000000000000000000000000000000000..8477124d1fcb68977e54843809ff42688510ac78 Binary files /dev/null and b/data/processed_audio__audio2_audio2_8.wav differ diff --git a/data/processed_audio__audio2_audio2_9.wav b/data/processed_audio__audio2_audio2_9.wav new file mode 100644 index 0000000000000000000000000000000000000000..de1e5d186fabe7b56d7b2b807e928706c63f7739 Binary files /dev/null and b/data/processed_audio__audio2_audio2_9.wav differ diff --git a/data/processed_audio__audio3_audio3_0.wav b/data/processed_audio__audio3_audio3_0.wav new file mode 100644 index 0000000000000000000000000000000000000000..7e04fe6063bb5786ac0caf4b681aa037d8dbf7e0 Binary files /dev/null and b/data/processed_audio__audio3_audio3_0.wav differ diff --git a/data/processed_audio__audio3_audio3_1.wav b/data/processed_audio__audio3_audio3_1.wav new file mode 100644 index 0000000000000000000000000000000000000000..017b51e1a38e67cdbbf02492c631550b6b0fa628 Binary files /dev/null and b/data/processed_audio__audio3_audio3_1.wav differ diff --git a/data/processed_audio__audio3_audio3_2.wav b/data/processed_audio__audio3_audio3_2.wav new file mode 100644 index 0000000000000000000000000000000000000000..e8b186185f2710f77ffd1461d0c4ebaf44a6609c Binary files /dev/null and b/data/processed_audio__audio3_audio3_2.wav differ diff --git a/data/processed_audio__audio3_audio3_3.wav b/data/processed_audio__audio3_audio3_3.wav new file mode 100644 index 0000000000000000000000000000000000000000..b3ccfaf70036354dbd0f2779f8599c0849e87ced Binary files /dev/null and b/data/processed_audio__audio3_audio3_3.wav differ diff --git a/data/processed_audio__audio3_audio3_4.wav b/data/processed_audio__audio3_audio3_4.wav new file mode 100644 index 0000000000000000000000000000000000000000..e16d0d84d7bd8e951d7021534798c31ccf9aaf6c Binary files /dev/null and b/data/processed_audio__audio3_audio3_4.wav differ diff --git a/data/processed_audio__audio3_audio3_5.wav b/data/processed_audio__audio3_audio3_5.wav new file mode 100644 index 0000000000000000000000000000000000000000..945f666e4b29826dd77604f681ff3a6fb61ba1b7 Binary files /dev/null and b/data/processed_audio__audio3_audio3_5.wav differ diff --git a/data/processed_audio__audio3_audio3_6.wav b/data/processed_audio__audio3_audio3_6.wav new file mode 100644 index 0000000000000000000000000000000000000000..6b9f07e8dd2058199338f1c22a36196315c3acfe Binary files /dev/null and b/data/processed_audio__audio3_audio3_6.wav differ diff --git a/data/processed_audio__audio3_audio3_7.wav b/data/processed_audio__audio3_audio3_7.wav new file mode 100644 index 0000000000000000000000000000000000000000..19eb2a4e542c7a01f2eb31602911599b69792747 Binary files /dev/null and b/data/processed_audio__audio3_audio3_7.wav differ diff --git a/data/processed_audio__audio3_audio3_8.wav b/data/processed_audio__audio3_audio3_8.wav new file mode 100644 index 0000000000000000000000000000000000000000..32f8d3410a3f85887bfa294b7fcba027b0bfd204 Binary files /dev/null and b/data/processed_audio__audio3_audio3_8.wav differ diff --git a/data/processed_audio__audio3_audio3_9.wav b/data/processed_audio__audio3_audio3_9.wav new file mode 100644 index 0000000000000000000000000000000000000000..f3098e5179123312562c41f0971fe835836a188d Binary files /dev/null and b/data/processed_audio__audio3_audio3_9.wav differ diff --git a/data/processed_audio__audio3_audio4_0.wav b/data/processed_audio__audio3_audio4_0.wav new file mode 100644 index 0000000000000000000000000000000000000000..bb0bdf062ffac239121413d53dcc53e8a8c4b537 Binary files /dev/null and b/data/processed_audio__audio3_audio4_0.wav differ diff --git a/data/processed_audio__audio3_audio4_1.wav b/data/processed_audio__audio3_audio4_1.wav new file mode 100644 index 0000000000000000000000000000000000000000..90f48e741b5ff6d7798120a2406f0ce5b09d01a8 Binary files /dev/null and b/data/processed_audio__audio3_audio4_1.wav differ diff --git a/data/processed_audio__audio3_audio4_2.wav b/data/processed_audio__audio3_audio4_2.wav new file mode 100644 index 0000000000000000000000000000000000000000..2d631dde87b46f82ee9ba2b4e5437006b700c954 Binary files /dev/null and b/data/processed_audio__audio3_audio4_2.wav differ diff --git a/data/processed_audio__audio3_audio4_3.wav b/data/processed_audio__audio3_audio4_3.wav new file mode 100644 index 0000000000000000000000000000000000000000..f897e8364ea0f90bc775835f79998d8099ed8e94 Binary files /dev/null and b/data/processed_audio__audio3_audio4_3.wav differ diff --git a/data/processed_audio__audio3_audio4_4.wav b/data/processed_audio__audio3_audio4_4.wav new file mode 100644 index 0000000000000000000000000000000000000000..94fec7541564b9c46217196691b343c8aff28ee2 Binary files /dev/null and b/data/processed_audio__audio3_audio4_4.wav differ diff --git a/data/processed_audio__audio3_audio4_5.wav b/data/processed_audio__audio3_audio4_5.wav new file mode 100644 index 0000000000000000000000000000000000000000..7319ccc83d40993a7ccfe9320dfd09d59d132192 Binary files /dev/null and b/data/processed_audio__audio3_audio4_5.wav differ diff --git a/data/processed_audio__audio3_audio4_6.wav b/data/processed_audio__audio3_audio4_6.wav new file mode 100644 index 0000000000000000000000000000000000000000..c0cd55143723284076a1b5ca9ae3e01f3f074b99 Binary files /dev/null and b/data/processed_audio__audio3_audio4_6.wav differ diff --git a/data/processed_audio__audio3_audio4_7.wav b/data/processed_audio__audio3_audio4_7.wav new file mode 100644 index 0000000000000000000000000000000000000000..c4413ef5cdf833be2ded3231c64eaba1907658fd Binary files /dev/null and b/data/processed_audio__audio3_audio4_7.wav differ diff --git a/data/processed_audio__audio3_audio4_8.wav b/data/processed_audio__audio3_audio4_8.wav new file mode 100644 index 0000000000000000000000000000000000000000..e44d4bf43381273520b664829a59557fdad207a7 Binary files /dev/null and b/data/processed_audio__audio3_audio4_8.wav differ diff --git a/data/processed_audio__audio3_audio4_9.wav b/data/processed_audio__audio3_audio4_9.wav new file mode 100644 index 0000000000000000000000000000000000000000..cad17af0853cb7e13df56519d85d5f1ac7d18fff Binary files /dev/null and b/data/processed_audio__audio3_audio4_9.wav differ diff --git a/model_v1.pth b/model_v1.pth new file mode 100644 index 0000000000000000000000000000000000000000..faa7bd93e54c8efdea2f1da453d2d283202fcb00 --- /dev/null +++ b/model_v1.pth @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5f7a58c5149d6e0ffce92cd08d6dad74f9e6f2c667571eed883c2a92e86a4b9b +size 134923 diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..408f3b140a2ef9e1e895036dace37639fbcea426 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,51 @@ +appnope==0.1.4 +asttokens==2.4.1 +comm==0.2.2 +contourpy==1.3.0 +cycler==0.12.1 +debugpy==1.8.5 +decorator==5.1.1 +executing==2.1.0 +filelock==3.16.0 +fonttools==4.53.1 +fsspec==2024.9.0 +ipykernel==6.29.5 +ipython==8.27.0 +jedi==0.19.1 +Jinja2==3.1.4 +jupyter_client==8.6.2 +jupyter_core==5.7.2 +kiwisolver==1.4.7 +MarkupSafe==2.1.5 +matplotlib==3.9.2 +matplotlib-inline==0.1.7 +mpmath==1.3.0 +nest-asyncio==1.6.0 +networkx==3.3 +numpy==2.1.1 +packaging==24.1 +pandas==2.2.2 +parso==0.8.4 +pexpect==4.9.0 +pillow==10.4.0 +platformdirs==4.3.3 +prompt_toolkit==3.0.47 +psutil==6.0.0 +ptyprocess==0.7.0 +pure_eval==0.2.3 +pydub==0.25.1 +Pygments==2.18.0 +pyparsing==3.1.4 +python-dateutil==2.9.0.post0 +pytz==2024.2 +pyzmq==26.2.0 +six==1.16.0 +stack-data==0.6.3 +sympy==1.13.2 +torch==2.2.2 +torchaudio==2.2.2 +tornado==6.4.1 +traitlets==5.14.3 +typing_extensions==4.12.2 +tzdata==2024.1 +wcwidth==0.2.13 diff --git a/rnn_torchview b/rnn_torchview new file mode 100644 index 0000000000000000000000000000000000000000..455950d428e37ae78b94d119bb5a2b20c707151b --- /dev/null +++ b/rnn_torchview @@ -0,0 +1,72 @@ +strict digraph model { + graph [ordering=in rankdir=TB size="12.0,12.0"] + node [align=left fontname="Linux libertine" fontsize=10 height=0.2 margin=0 ranksep=0.1 shape=plaintext style=filled] + edge [fontsize=10] + 0 [label=< + + +
input-tensor
depth:0
(1, 10, 128)
> fillcolor=lightyellow] + 1 [label=< + + + + + + + + + + +
RNN
depth:1
input:(1, 10, 128)
output: (1, 10, 128), (1, 1, 128)
> fillcolor=darkseagreen1] + 2 [label=< + + + + + + + + + + +
Dropout
depth:1
input:(1, 10, 128)
output: (1, 10, 128)
> fillcolor=darkseagreen1] + 3 [label=< + + + + + + + + + + +
__getitem__
depth:1
input:(1, 10, 128)
output: (1, 128)
> fillcolor=aliceblue] + 4 [label=< + + + + + + + + + + +
Linear
depth:1
input:(1, 128)
output: (1, 1)
> fillcolor=darkseagreen1] + 5 [label=< + + +
output-tensor
depth:0
(1, 1)
> fillcolor=lightyellow] + 0 -> 1 + 1 -> 2 + 2 -> 3 + 3 -> 4 + 4 -> 5 +} diff --git a/rnn_torchview.png b/rnn_torchview.png new file mode 100644 index 0000000000000000000000000000000000000000..4d5242d600d6c69c8fb37cd560e2ea5d6d6151e8 Binary files /dev/null and b/rnn_torchview.png differ diff --git a/train_rnn.ipynb b/train_rnn.ipynb new file mode 100644 index 0000000000000000000000000000000000000000..c08b7547a6813ff1bded659a1d770594078c9f35 --- /dev/null +++ b/train_rnn.ipynb @@ -0,0 +1,816 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 71, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import torch\n", + "import torch.nn as nn\n", + "import torch.optim as optim\n", + "from torch.utils.data import Dataset, DataLoader\n", + "import torchaudio\n", + "import numpy as np\n", + "import pandas as pd\n", + "import torchaudio.transforms as transforms\n", + "from pydub import AudioSegment\n", + "import matplotlib.pyplot as plt\n", + "import IPython\n", + "%matplotlib inline\n", + "\n", + "device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")" + ] + }, + { + "cell_type": "code", + "execution_count": 72, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "execution_count": 72, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "IPython.display.Audio(\"./exp1/processed_audio/audio1/audio1_0.wav\")" + ] + }, + { + "cell_type": "code", + "execution_count": 73, + "metadata": {}, + "outputs": [], + "source": [ + "# df work\n", + "\n", + "# create df with file paths and time points\n", + "\n", + "# directories to get audio files from\n", + "audio_dirs = [\"./data\"]\n", + "\n", + "# create list of file paths and time points\n", + "file_paths = []\n", + "time_points = []\n", + "sample_rates = []\n", + "\n", + "for audio_dir in audio_dirs:\n", + " for file in os.listdir(audio_dir):\n", + " if file.endswith(\".wav\"):\n", + " file_paths.append(f\"{audio_dir}/{file}\")\n", + " elif file.endswith(\".m4a\"):\n", + " file_paths.append(f\"{audio_dir}/{file}\")\n", + "\n", + "# time point is length of audio file minus 1\n", + "for file_path in file_paths:\n", + " audio = AudioSegment.from_file(file_path)\n", + " time_points.append(audio.duration_seconds - 1)\n", + "\n", + "for file_path in file_paths:\n", + " audio = AudioSegment.from_file(file_path)\n", + " sample_rates.append(audio.frame_rate)\n", + "\n", + "\n", + "\n", + "# create df\n", + "df = pd.DataFrame({\"file_path\": file_paths, \"time_point\": time_points, \"sample_rate\": sample_rates})\n", + "\n", + "\n", + "# train test split\n", + "from sklearn.model_selection import train_test_split\n", + "\n", + "train_df, test_df = train_test_split(df, test_size=0.1, random_state=42)" + ] + }, + { + "cell_type": "code", + "execution_count": 74, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
file_pathtime_pointsample_rate
0./data/2024-10-12-17-22-31.m4a6.5528000
1./data/2024-10-12-17-47-04.m4a6.5528000
2./data/processed_audio__audio1_audio1_2.wav5.00048000
3./data/2024-10-12-17-29-33.m4a16.9208000
4./data/processed_audio__audio1_audio1_1.wav7.00048000
............
68./data/2024-10-12-17-46-43.m4a8.3448000
69./data/2024-10-12-17-28-24.m4a8.4728000
70./data/processed_audio__audio3_audio4_8.wav6.00048000
71./data/processed_audio__audio2_audio2_5.wav8.00048000
72./data/processed_audio__audio2_audio2_3.wav8.00048000
\n", + "

73 rows × 3 columns

\n", + "
" + ], + "text/plain": [ + " file_path time_point sample_rate\n", + "0 ./data/2024-10-12-17-22-31.m4a 6.552 8000\n", + "1 ./data/2024-10-12-17-47-04.m4a 6.552 8000\n", + "2 ./data/processed_audio__audio1_audio1_2.wav 5.000 48000\n", + "3 ./data/2024-10-12-17-29-33.m4a 16.920 8000\n", + "4 ./data/processed_audio__audio1_audio1_1.wav 7.000 48000\n", + ".. ... ... ...\n", + "68 ./data/2024-10-12-17-46-43.m4a 8.344 8000\n", + "69 ./data/2024-10-12-17-28-24.m4a 8.472 8000\n", + "70 ./data/processed_audio__audio3_audio4_8.wav 6.000 48000\n", + "71 ./data/processed_audio__audio2_audio2_5.wav 8.000 48000\n", + "72 ./data/processed_audio__audio2_audio2_3.wav 8.000 48000\n", + "\n", + "[73 rows x 3 columns]" + ] + }, + "execution_count": 74, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df" + ] + }, + { + "cell_type": "code", + "execution_count": 75, + "metadata": {}, + "outputs": [], + "source": [ + "class SlidingWindowAudioDataset(Dataset):\n", + " def __init__(self, df, sample_rate=16000, window_size=1, hop_length=0.1, n_fft=2048, n_mels=128):\n", + " self.df = df\n", + " self.sample_rate = sample_rate\n", + " self.window_size = window_size\n", + " self.hop_length = int(hop_length * sample_rate)\n", + " self.n_fft = n_fft\n", + " self.n_mels = n_mels\n", + " \n", + " def __len__(self):\n", + " return len(self.df)\n", + "\n", + " def __getitem__(self, idx):\n", + " file_path = self.df.iloc[idx]['file_path']\n", + " label_point_seconds = self.df.iloc[idx]['time_point']\n", + "\n", + " # Load audio file\n", + " waveform, sr = torchaudio.load(file_path)\n", + " \n", + " # Convert to mono if stereo\n", + " if waveform.shape[0] > 1:\n", + " waveform = waveform.mean(dim=0, keepdim=True)\n", + "\n", + " if sr != self.sample_rate:\n", + " resampler = torchaudio.transforms.Resample(sr, self.sample_rate)\n", + " waveform = resampler(waveform)\n", + "\n", + " \n", + " # Calculate mel spectrogram\n", + " mel_spectrogram = torchaudio.transforms.MelSpectrogram(\n", + " sample_rate=self.sample_rate,\n", + " n_fft=self.n_fft,\n", + " hop_length=self.hop_length,\n", + " n_mels=self.n_mels\n", + " )(waveform)\n", + " \n", + " # Apply sliding window\n", + " # Debugging information\n", + " # print(f\"File: {file_path}\")\n", + " # print(f\"Mel Spectrogram shape: {mel_spectrogram.shape}\")\n", + " # print(f\"Sample Rate: {self.sample_rate}\")\n", + " # print(f\"Hop Length: {self.hop_length}\")\n", + " # print(f\"Window Size: {self.window_size}\")\n", + " # print(f\"Waveform shape: {len(waveform[0])}\")\n", + " \n", + " # Calculate number of windows\n", + " total_duration = len(waveform[0]) / self.sample_rate\n", + " window_duration = self.window_size\n", + " hop_duration = self.hop_length / self.sample_rate\n", + " \n", + " num_windows = max(0, int((total_duration - window_duration) // hop_duration + 1))\n", + " \n", + " # print(f\"Total Duration: {total_duration:.2f} seconds\")\n", + " # print(f\"Window Duration: {window_duration} seconds\")\n", + " # print(f\"Hop Duration: {hop_duration:.2f} seconds\")\n", + " # print(f\"Calculated Num Windows: {num_windows}\")\n", + " \n", + " windows = []\n", + " labels = []\n", + " for i in range(num_windows):\n", + " start_time = i * self.hop_length / self.sample_rate\n", + " end_time = start_time + self.window_size\n", + " \n", + " window = mel_spectrogram[:, :, i:i+int(self.window_size * self.sample_rate / self.hop_length)]\n", + " # print(window.shape)\n", + "\n", + " # label point is 85%\n", + " # find middle of window and find the percentage based on the label point\n", + " middle = (start_time + end_time) / 2\n", + " # full time based on 85% mark\n", + " full_time = total_duration / (0.85 * 100) * 100\n", + " # label point\n", + " label = middle / full_time\n", + "\n", + " windows.append(window)\n", + " labels.append(label)\n", + "\n", + " # print(f\"Actual Num Windows: {len(windows)}\")\n", + " # print(\"---\")\n", + "\n", + " # print shape\n", + " # print(torch.stack(windows).shape)\n", + " # print(torch.tensor(labels).shape)\n", + " return torch.stack(windows), torch.tensor(labels)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 76, + "metadata": {}, + "outputs": [], + "source": [ + "class AudioRNN(nn.Module):\n", + " def __init__(self, input_size, hidden_size, output_size, dropout, num_layers=1):\n", + " super(AudioRNN, self).__init__()\n", + " self.rnn = nn.RNN(input_size, hidden_size, num_layers, batch_first=True)\n", + " self.fc = nn.Linear(hidden_size, output_size)\n", + " self.hidden_size = hidden_size\n", + " self.hidden_state = None\n", + " self.hidden_size = hidden_size\n", + " self.num_layers = num_layers\n", + " self.dropout = nn.Dropout(dropout)\n", + "\n", + " def reset_hidden_state(self):\n", + " self.hidden_state = torch.zeros(self.num_layers, 1, self.hidden_size).to(device)\n", + "\n", + " def forward(self, x):\n", + " out, _ = self.rnn(x, self.hidden_state)\n", + " out = self.dropout(out)\n", + " out = self.fc(out[:, -1, :])\n", + " return out" + ] + }, + { + "cell_type": "code", + "execution_count": 77, + "metadata": {}, + "outputs": [], + "source": [ + "def train(model, device, loader, test_loader, criterion, optimizer, epochs, patience=3):\n", + " best_acc = 0\n", + " patience_counter = 0\n", + " epoch_losses = []\n", + " for epoch in range(epochs):\n", + " model.train()\n", + " running_loss = 0.0\n", + " for batch_idx, (data, target) in enumerate(loader):\n", + " for i in range(data.size(1)):\n", + " # the label we want is only the index i of the target\n", + " target_batch = target[:, i].to(device).float()\n", + " # get the data for the index i\n", + " data_batch = data[:, i, :, :].to(device)\n", + "\n", + " model.reset_hidden_state()\n", + "\n", + " data_batch = data_batch.squeeze(1)\n", + " data_batch = data_batch.permute(0, 2, 1)\n", + "\n", + " optimizer.zero_grad()\n", + " output = model(data_batch)\n", + " output = output.squeeze(1)\n", + " \n", + " loss = criterion(output, target_batch)\n", + " loss.backward()\n", + " optimizer.step()\n", + " running_loss += loss.item()\n", + " \n", + " epoch_losses.append(running_loss/(batch_idx+1))\n", + " print(f'Epoch {epoch+1}/{epochs}, Loss: {running_loss/(batch_idx+1)}')\n", + " # Plotting the training loss\n", + " IPython.display.clear_output(wait=True)\n", + " plt.plot(epoch_losses, marker='o', linestyle='-', color='b')\n", + " plt.xlabel('Steps')\n", + " plt.ylabel('Loss')\n", + " plt.grid(True)\n", + " plt.show()\n", + "\n", + " print(f\"Epoch: {epoch}\")\n", + " print(\"test loss\")\n", + " test_acc = test(model, device, test_loader)\n", + "\n", + " if test_acc > best_acc:\n", + " best_acc = test_acc\n", + " patience_counter = 0\n", + " else:\n", + " patience_counter += 1\n", + "\n", + " if patience_counter > patience:\n", + " print(\"Early Stopping\")\n", + " break\n", + "\n", + " print(\"train loss\")\n", + " train_acc = test(model, device, loader)\n", + "\n", + "\n", + "def test(model, device, loader):\n", + " total_loss = 0\n", + " total_correct = 0\n", + " total_no = 0\n", + " leeway = 0.1\n", + " crit = torch.nn.MSELoss()\n", + " model.eval()\n", + " with torch.no_grad():\n", + " for data, target in loader:\n", + " for i in range(data.size(1)):\n", + " data_batch = data[:, i, :, :].to(device)\n", + " target_batch = target[:, i].to(device)\n", + "\n", + " # reset hidden state\n", + " model.reset_hidden_state()\n", + "\n", + " # drop x y dimension\n", + " data_batch = data_batch.squeeze(1)\n", + " # wrong dimension order swap y z\n", + " data_batch = data_batch.permute(0, 2, 1)\n", + " # feed to model\n", + " output = model(data_batch)\n", + " output = output.squeeze(1)\n", + "\n", + " if abs(output.item() - target_batch.item()) < leeway:\n", + " total_correct += 1\n", + " total_no += 1\n", + "\n", + " # get accuracy with the output and target float\n", + "\n", + " loss = crit(output, target_batch)\n", + " total_loss += loss.item()\n", + " \n", + " avg_loss = total_loss / total_no\n", + " print(f'Validation Loss: {avg_loss}')\n", + " print(f'Accuracy: {total_correct / total_no}')\n", + " return total_correct / total_no" + ] + }, + { + "cell_type": "code", + "execution_count": 78, + "metadata": {}, + "outputs": [], + "source": [ + "train_dataset = SlidingWindowAudioDataset(train_df, \n", + " sample_rate=16000)\n", + "\n", + "test_dataset = SlidingWindowAudioDataset(test_df,\n", + " sample_rate=16000) \n", + "\n", + "batch_size = 1\n", + "train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)\n", + "test_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=False)\n", + "\n", + "# Model configuration\n", + "input_dim = 128 # Number of mel frequency bins\n", + "hidden_dim = 128\n", + "output_dim = 1\n", + "num_layers = 1\n", + "dropout = 0.3\n", + "learning_rate = 0.00003\n", + "\n", + "model = AudioRNN(input_dim, hidden_dim, output_dim, dropout, num_layers).to(device)\n", + "\n", + "# self, input_size, hidden_size, output_size, num_layers=1\n", + "\n", + "criterion = nn.MSELoss()\n", + "\n", + "\n", + "optimizer = optim.Adam(model.parameters(), lr=learning_rate, weight_decay=0.0003)" + ] + }, + { + "cell_type": "code", + "execution_count": 79, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Validation Loss: 0.629760848049892\n", + "Accuracy: 0.07122145704965567\n" + ] + }, + { + "data": { + "text/plain": [ + "0.07122145704965567" + ] + }, + "execution_count": 79, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "test(model, device, test_loader)" + ] + }, + { + "cell_type": "code", + "execution_count": 80, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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DOTkqF0KIiIi7fMrkGnRogVWrlyJ48ePY82aNejevTsA4Pfff0dcXFxQC1hV/P678rSlpUD//gxmiIiIvPErkHnppZcwfvx4pKeno3379sjIyAAgW2fatGkT1AJWFf6s1jt6NDeQJCIi8sSvQGbAgAE4duwYfvjhB6xZs8Z+vEuXLpg1a1bQCleVZGYCiYm+nXPiBNeUISIi8sSvdWQAICkpCUlJSfZdsFNSUrgYngdGIzB3LjBwoG/ncbYTERGRe361yFitVkydOhXx8fFIS0tDWloa6tSpg7///e+wWq3BLmOVcf/9wL33+nYO15QhIiJyz68Wmeeffx4LFizA9OnTcccddwAAtm7dismTJ+Pq1av4xz/+EdRCViUTJgCrVytPzzEyRERE7vkVyHzwwQf497//bd/1GgBat26Nxo0b48knn2Qg40HHjr6l37wZ+N+kMCIiIqrEr66lCxcuoFWrVk7HW7VqhQtK1+GvprZt8y39t9+GphxERERVgV+BzM0334y3337b6fjbb7+N1q1bB1yoqszXwbs//cTuJSIiInf86lqaMWMG7rvvPqxfv96+hsz27dtx/PhxrPZlAEg15Ot6MkVFcgp2584hKQ4REZGu+dUic9ddd+H//b//h379+qGgoAAFBQXIzs7GL7/8go8++ijYZaxSOnYEDAbfzuEUbCIiItf8XkcmOTnZaVDvnj17sGDBAsyfPz/gglVV27YBQvh2DqdgExERueZXiwz5j60rREREwcNAJsz82XPJlw0niYiIqhMGMmGWmQmkpPg2ToZdS0RERK75NEYmOzvb4+sFBQWBlKVaMBqBN98EBgxQuyRERET651MgEx8f7/X1Bx98MKACVQfZ2cDnnwMjRgBK1g9k1xIREZFrPgUyCxcuDFU5qp3sbKBWLaBHD+9p2bVERETkGsfI6MDmzWqXgIiISJsYyKgoL09Zujff5DYFRERErjCQ0QHbNgVERETkiIGMinzZP+nkyZAVg4iISLcYyKioc2cgNlZZ2rNnQ1oUIiIiXWIgoyKjEXj0UWVp69cPbVmIiIj0iIGMyvr0UZYuKSm05SAiItIjBjIqUzobibOWiIiInDGQUZnS2UjvvRfachAREekRAxmd+L//Y6sMERFRZaoGMlu2bEHv3r2RnJwMg8GAlStXOrwuhMBLL72ERo0aISYmBl27dsWB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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Epoch: 30\n", + "test loss\n", + "Validation Loss: 0.011056410072496364\n", + "Accuracy: 0.7776368249365713\n", + "Early Stopping\n" + ] + } + ], + "source": [ + "train(model, device, train_loader, test_loader, criterion, optimizer, epochs=100)" + ] + }, + { + "cell_type": "code", + "execution_count": 81, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Validation Loss: 0.011056410072496364\n", + "Accuracy: 0.7776368249365713\n" + ] + }, + { + "data": { + "text/plain": [ + "0.7776368249365713" + ] + }, + "execution_count": 81, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "test(model, device, test_loader)" + ] + }, + { + "cell_type": "code", + "execution_count": 82, + "metadata": {}, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "model\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "input-tensor\n", + "depth:0\n", + "\n", + "(1, 10, 128)\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "RNN\n", + "depth:1\n", + "\n", + "input:\n", + "\n", + "(1, 10, 128) \n", + "\n", + "output: \n", + "\n", + "(1, 10, 128), (1, 1, 128) \n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "\n", + "Dropout\n", + "depth:1\n", + "\n", + "input:\n", + "\n", + "(1, 10, 128) \n", + "\n", + "output: \n", + "\n", + "(1, 10, 128) \n", + "\n", + "\n", + "\n", + "1->2\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "3\n", + "\n", + "\n", + "__getitem__\n", + "depth:1\n", + "\n", + "input:\n", + "\n", + "(1, 10, 128) \n", + "\n", + "output: \n", + "\n", + "(1, 128) \n", + "\n", + "\n", + "\n", + "2->3\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "4\n", + "\n", + "\n", + "Linear\n", + "depth:1\n", + "\n", + "input:\n", + "\n", + "(1, 128) \n", + "\n", + "output: \n", + "\n", + "(1, 1) \n", + "\n", + "\n", + "\n", + "3->4\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "5\n", + "\n", + "\n", + "output-tensor\n", + "depth:0\n", + "\n", + "(1, 1)\n", + "\n", + "\n", + "\n", + "4->5\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 82, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# from torchviz import make_dot\n", + "from torchview import draw_graph\n", + "import matplotlib.pyplot as plt\n", + "# Visualize the model\n", + "# x = torch.randn(1, 10, input_size)\n", + "# y = model(x)\n", + "# make_dot(y, params=dict(list(model.named_parameters()) + [('x', x)])).render(\"rnn_torchviz\", format=\"png\")\n", + "\n", + "# Display the generated graph\n", + "# img = plt.imread(\"rnn_torchviz.png\")\n", + "# plt.imshow(img)\n", + "# plt.axis('off')\n", + "\n", + "# Visualize the model\n", + "x = torch.randn(1, 10, input_dim).to(device)\n", + "y = model(x)\n", + "graph = draw_graph(model, input_size=(1, 10, input_dim), device=device)\n", + "graph.visual_graph.render(\"rnn_torchview\", format=\"png\")\n", + "graph.visual_graph\n", + "\n", + "# Display the generated graph\n", + "# img = plt.imread(\"rnn_torchview.png\")\n", + "# plt.imshow(img)\n", + "# plt.axis('off')\n", + "# plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 83, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "==========================================================================================\n", + "Layer (type:depth-idx) Output Shape Param #\n", + "==========================================================================================\n", + "AudioRNN [1, 1] --\n", + "├─RNN: 1-1 [1, 10, 128] 33,024\n", + "├─Dropout: 1-2 [1, 10, 128] --\n", + "├─Linear: 1-3 [1, 1] 129\n", + "==========================================================================================\n", + "Total params: 33,153\n", + "Trainable params: 33,153\n", + "Non-trainable params: 0\n", + "Total mult-adds (Units.MEGABYTES): 0.33\n", + "==========================================================================================\n", + "Input size (MB): 0.01\n", + "Forward/backward pass size (MB): 0.01\n", + "Params size (MB): 0.13\n", + "Estimated Total Size (MB): 0.15\n", + "==========================================================================================" + ] + }, + "execution_count": 83, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from torchinfo import summary\n", + "\n", + "summary(model, input_size=(1, 10, input_dim), device=device)" + ] + }, + { + "cell_type": "code", + "execution_count": 84, + "metadata": {}, + "outputs": [], + "source": [ + "# save model\n", + "# name is time\n", + "import time\n", + "torch.save(model.state_dict(), f\"./model_{time.time()}.pth\")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.6" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +}