[{"content":"Prolog Przyznaję bez bicia, trochę zbierałem się do napisania tego wpisu. Zmęczenie po hackathonach potrafi dać w kość, a opisanie tego, co udało nam się osiągnąć podczas tych 24 godzin, to nie lada wyzwanie, bo prób oraz wielorakich podejść było mnóstwo. Jednakże teraz, patrząc przez okno pociągu jadącego z Suwałk do Poznania, czuję, że wena przejmuje nade mną kontrolę, zupełnie jak aktualizacja Windowsa w randomowy wtorek o 12:40.\nWena weną, ale rzeczywistość, z którą musieliśmy się zmierzyć na miejscu, była zdecydowanie mniej poetycka. Wyobraź sobie tabelę mającą 64 miliony wierszy. Wiem, że to zadanie jest dosyć trudne, dlatego śpieszę z pomocą. 64 miliony wierszy zapisanych czcionką Times New Roman (font size 12) to około 1 300 000 stron A4 (estymacja by Gemini).\nCo więcej, wyobraź sobie, że czytasz te 1 300 000 stron A4, a następnie masz na ich podstawie przewidzieć obciążenie sieci elektrycznej dla jakiegoś urządzenia. Zgadza się - nie jest to najłatwiejsze zadanie, dlatego, jak dobrze wiemy, do tego typu wyzwań pierwsze co wyciągniemy, to drzewa decyzyjne. My również tak zrobiliśmy na początku! Jednak po kilku godzinach postanowiliśmy zrobić coś kompletnie innego i użyliśmy architektury, która z założenia miała służyć do przetwarzania tekstu, a w ostatnim czasie jest adaptowana do wielu innych dziedzin. Nie przedłużając, opowiem Wam, jak ten eksperyment przyniósł nam 1. miejsce na 45 drużyn i dlaczego czasami warto wyrzucić bezpieczną instrukcję przez okno.\nKrótki wstęp o formule hackathonu EnsembleAI Aby zrozumieć, jakie emocje towarzyszyły mi oraz zespołowi podczas tej zażartej walki, musimy zacząć od opisu formuły hackathonu, bo jest ona co najmniej nietypowa i zapewnia strzały dopaminy mocniejsze niż Reelsy z Instagrama. Każde z 4 zadań jest oceniane oddzielnie, a punktacja przydzielana jest na podstawie podesłanych rozwiązań, specyficznych dla każdego zadania. W przypadku zadania 3, którym się zajmowałem, był to na przykład plik CSV z predykcjami miesięcznego obciążenia sici elektrycznej dla konkretnego przedziału czasu. Przez taką organizację newralgiczną częścią hackathonu była strona z leaderboardem, gdzie mogliśmy podejrzeć ile punktów mamy w danym zadaniu. Rozwiązania można było przesyłać tylko co określony z góry czas, by między innymi uniknąć DDOS-owania serwerów. A więc, jak widać, po każdym kolejnym przesłaniu pliku następował pełen napięcia okres oczekiwania: czy i o ile nasze rozwiązanie poprawiło pozycję w rankingu. Ale może od początku: co, jak, gdzie i w ogóle po co? Wyzwanie przygotował dla nas jeden z partnerów hackathonu – Euros Energy, od którego dostaliśmy również dane. Zatem o co w ogóle chodziło? Brief z opisem problemu nakreślał nam szerszy kontekst: masowa elektryfikacja to absolutny kamień milowy transformacji energetycznej w Polsce. Jednak dla dystrybutorów prądu szybki wzrost liczby instalacji, w tym głównie pomp ciepła, stwarza ogromne wyzwania. Mówiąc krótko: precyzyjne prognozowanie zapotrzebowania na energię jest wręcz niezbędne, aby zapobiec przeciążeniom sieci i wynikającym z nich awariom.\nDane, jakie dostaliśmy Jak mówimy o uczeniu maszynowym i predykcjach, to wstyd nie zacząć od opisu danych, jakie otrzymaliśmy, a więc by nie siać niezadowolenia, zacznijmy:\nKażdy zespół miał do dyspozycji 3 główne zbiory:\nTrain: Październik 2024 – Kwiecień 2025 Validation: Maj 2025 – Czerwiec 2025 Test: Lipiec 2025 – Październik 2025 Na tym ostatnim zbiorze wykonywaliśmy predykcje przy każdym submission, ale tutaj pojawia się haczyk, który decydował o wszystkim. To był mechanizm znany z Kaggle: Public vs Private Leaderboard. Zbiór Test był niby jawny i każdy go miał, ale\u0026hellip; brakowało w nim naszego „y” (celu predykcji). Nie było więc mowy o douczeniu modelu czy sprawdzeniu wyniku na własną rękę.\nPrzez całe 24 godziny walczyliśmy „po omacku”, widząc na tablicy wyniki tylko dla wycinka tych danych. Jednak te punkty nie miały takiego znaczenia w końcowej klasyfikacji! Finalna ocena, która decydowała o podium, została przeliczona na pozostałej, całkowicie zatajonej części zbioru Test, której wyników nikt nie znał do samego końca. To sprawiło, że ostatnie minuty hackathonu to była czysta loteria emocjonalna, bo specyfika lata mogła być zgoła inna niż okresu jesienno-zimowego, na którym głównie trenowaliśmy.\nW praktyce ocenianie wyglądało tak:\nScore Months used Weights Leaderboard (visible) Validation only (May – Jun 2025) - Final score Validation + Test (May – Oct 2025) 2/6 valid + 4/6 test Ostatecznie w danych mieliśmy ok. 600 różnych sensorów, które nadsyłały nam logi w odstępach 5-minutowych w przedstawionych powyżej okresach, co dawało nam ok. 64 miliony wierszy (10.42 GB!) do analizy.\nCel Krótko i na temat: celem predykcji nie była chwilowa moc, a średnia miesięczna wartość wskaźnika obciążenia sieci (x2) dla każdego urządzenia. Przechodziliśmy więc z danych o wysokiej rozdzielczości (odczyty co 5 minut) na poziom agregatów miesięcznych. Na dole wrzucam dokładny i piękny wzór zawarty w opisie zadania:\nDla każdego urządzenia d i miesiąca prognozy m, należy przewidzieć średnią wartość x2 ze wszystkich 5-minutowych odczytów w danym miesiącu:\ntargetd,m = (1 / Nd,m) * \u0026sum; x2(d,m,i) A metryką oceny na live oraz ostatecznym leaderboardzie było MAE:\nMAE = (1 / n) * \u0026sum; | yi - ŷi | Także co, pora opisać nasze starania oraz drogę, która poprowadziła nas prościutko na 3 miejsce w całym hackathonie!\nFeature Engineering oraz Preprocessing danych Na samym starcie trzeba przyjrzeć się blisko danym oraz rozkładom i tak też zrobiłem, ale jeszcze przed tym, na samym końcu instrukcji dostarczonej przez organizatorów, mogliśmy znaleźć taką oto sekcję:\nW tamtym momencie pomyślałem, że koniecznie musimy od tego zacząć i dodać do każdego z sensorów informację, do jakiego dystrybutora energii należy. W końcu każdy team pewnie to zrobi, prawda? Prawda?? No finalnie okazało się, że nie :D i kto wie, może to nam dało te kilka punktów więcej?\nW danych mieliśmy takie informacje jak szerokość oraz długość geograficzna każdego sensora, a więc na tej podstawie postanowiłem zlokalizować każde urządzenie w konkretnym województwie, odpytując API GeoPy. Okazało się, że dane zostały zanonimizowane (?) albo były w nich błędy, bo niektóre lokalizacje były niepoprawnie umiejscowione i GeoPy nie mogło znaleźć odpowiedniego dopasowania. W takich wypadkach użyliśmy algorytmu KNN do znalezienia najbliższego urządzenia, które ma poprawne współrzędne. Później stworzona mapa przypisywała każde województwo do jednego z dystrybutorów energii takich jak PGE, Enea lub Tauron i tak oto mieliśmy pierwszy ciekawy feature.\nKolejnym ważnym aspektem jest agregacja danych. Było ich naprawdę mnóstwo, co mogło przytłoczyć niejeden model, więc decyzja padła na agregację godzinową. Zmniejszało to całkiem znacznie zbiór danych, eliminowało szum z zapisów prowadzonych co 5 minut, dawało przestrzeń na wykrycie schematów, a także było wartościową jednostką predykcyjną.\nOgólnie problem był dosyć ciekawy, bo na początku podchodziłem do tego zadania jak do predykcji szeregów czasowych. Jednak po głębszym zastanowieniu, tak naprawdę mamy tu najzwyklejszy problem regresji. Wiadomo, interwały są prowadzone co 5 minut, ale predykcja to predykcja MIESIĘCZNA! Przy takim rozmyciu szczegółów na rzecz skali makro, jakby to powiedział mój profesor z politechniki: musimy ewidentnie użyć jak najbardziej precyzyjnej siekiery, a nie skalpela. Co więcej, w miarę uniwersalnej siekiery, która będzie umiała powiązać ważne cechy jesienią, po czym zaaplikować je również latem.\nPierwsze podejście Jako pierwsze podejście zdecydowałem się na CatBoosta. Było trochę cech kategorycznych oraz liczbowych, więc postanowiłem, że drzewa boostingowe mogą się całkiem dobrze odnaleźć w tym świecie. Także na start wleciał właśnie CatBoost z następującymi hiperparametrami (wtedy jeszcze bez strojenia):\n1 2 3 4 5 6 7 8 9 CatBoostRegressor( iterations=800, learning_rate=0.05, depth=6, loss_function=\u0026#34;MAE\u0026#34;, cat_features=CATEGORICAL_FEATURES, random_seed=42, verbose=100, ) I jak to się mówi: benc! Siadło, a do tego grubo, bo nasz pierwszy model miał 0.0074 MAE. 0.0074!!! Kurczę, to naprawdę jest mało\u0026hellip; Szczególnie przy agregacji miesięcznej oraz przy takiej specyfice danych!\nPo tym nastąpiła salwa kolejnych faz inżynierii cech, błądzenia i eksploracji zbioru. Summa summarum inne zespoły również dobrały się do podobnych wyników, a ostatecznie nas przeskoczyły, więc jako ostatni krok użyliśmy Optuny do optymzalizacji hiperparametrów, by wycisnąć z CatBoosta, ile się dało. Otrzymaliśmy wynik MAE na poziomie 0.0044. Każda z kolejnych wersji to naprawdę była ciężka walka i nadal uważam, że zejście na samym drzewku do takiej wartości to było naprawdę osiągnięcie. Tym bardziej, trochę spoilerując, że jednak Transformer to architektura znacznie, ale to znacznie cięższa, więc nawet trudno porównać te dwa modele między sobą, bo stoją one na dwóch różnych końcach efektywności oraz wymagań obliczeniowych. Także finalnie i tak mogę uznać ten wynik za naprawdę dobry jak na naszą wiedzę oraz umiejętności.\nAutoboty do boju Kiedy porzuciliśmy nasze piękne drzewko? Po pierwsze wtedy, gdy naprawdę poczułem, że kolejne zmiany, próby oraz feature engineering nic nie zmieniają albo zmieniają na tyle mało, że nie jesteśmy w stanie skoczyć wyżej w rankingu. Po drugie: kiedy drużyna o nazwie \u0026ldquo;Transformers\u0026rdquo; nam nakopała, a tym samym, można powiedzieć, nas natchnęła\u0026hellip; Po krótkim researchu postanowiłem wyciągnąć naprawdę, ale to naprawdę ciężkie działa, a mianowicie Feature Tokenizer Transformer (FT-Transfomrmer). Jest to, można powiedzieć, w miarę świeża architektura, która zdobywa ostatnio coraz większą popularność podczas kagglowych zawodów.\nOgólny zamysł i sposób działania Feature Tokenizer Transformera Zawarty poniżej opis opiera się na pracy, która właśnie FT-Transformera wprowadziła. Oczywiście obrazki również pochodzą z tego samego źródła.\nOd początku. Jak wiemy w datasetach mamy głównie do czynienia z dwoma typami cech: nominalne, czyli takie jak kategorie, oraz numeryczne, przedstawiające konkretną wartość liczbową.\nTransformery zostały szeroko wykorzystane w przetwarzaniu języka naturalnego (NLP) w modelach generatywnych, takich jak GPT, czy koder-dekoder, takich jak T5. Jak więc zmusić naszą architekturę do przetwarzania tym razem nie konkretnych embeddingów stworzonych z tokenów, a właśnie kategorii i liczb jednocześnie?\nGłówny komponent: Feature Tokenizer I właśnie za to odpowiada nasz komponent Feature Tokenizer. Jest on taką perełką tego podejścia, a działa na dwa konkretne sposoby:\nCechy numeryczne: Tutaj sprawa jest względnie prosta \u0026ndash;\u0026gt; bierzemy naszą liczbę, mnożymy ją przez wyuczony wektor wag o długości naszego wyjściowego embeddingu, dodajemy bias i tak właśnie nasza wartość liczbowa rozciągnęła się, tworząc nam embedding o zadanej wielkości.\nCechy kategoryczne: I tutaj działa to dosyć podobnie jak przetwarzanie słów w NLP. Każda wartość cechy na początku jest transformowana do reprezentacji one-hot encoding, a następnie jest wymnażana przez macierz wag. Tak w skrócie matematycznie działa to po prostu jak wybieranie konkretnego wiersza z tej macierzy plus wiadomo bias.\nOne-hot encoding to zmiana reprezentacji danej wartości kategorycznej na ciąg binarny. Brzmi to dziwnie, ale jest naprawdę proste. Przykład: mamy cechę \u0026ldquo;Kolor\u0026rdquo; w datasecie motocykli. W naszym datasecie mamy dwa kolory – czerwony i czarny. Wrzucając to w wektor, możemy to zrobić tak: [Czerwony, Czarny], a więc na pierwszym miejscu mamy wartość czerwony, a na drugim wartość czarny. Reprezentacja one-hot encoding to tak jakby zapalanie lampek, więc jeśli mielibyśmy przedstawić, że motocykl jest czerwony, to byłoby to tak: [1,0], a czarny to [0,1].\nNastępnie wszystkie wartości naszych cech są połączone za pomocą konkatenacji w wielką macierz T. Dodatkowo na samą górę doklejany jest losowo zainicjowany wektor [CLS] o takiej samej długości. Dalej cała ta macierz jest przetwarzana i podana do naszego Transformera, tak więc T reprezentuje nam tak jakby jeden wiersz w naszej tabeli (oczywiście wliczając w to ten dodatkowy wektor [CLS]). Na dole wizualizacja, jak to się prezentuje:\nAle po co ten [CLS]? CLS to skrót od Classification, a głównym zadaniem tego wektora jest zbieranie informacji podczas przejścia przez całą sieć ze wszystkich warstw.\nDalej, jak widać, nasz wektor T z przetworzonymi cechami ląduje w Transformerze, przechodzi normalizację i następnie idzie do unitu Multi-Head Self-Attention. Dzięki tej warstwie model może wyłonić kontekst, jaki jest potrzebny do osiągnięcia wyniku najbardziej zbliżonego do ideału, a w naszym przypadku kontekst to inne kolumny tabeli, czyli wartości z macierzy T. I właśnie ten kontekst, między innymi, składuje nam wektor [CLS].\nA dlaczego ta uwaga jest „Multi-Head” ? Podobnie jak w modelach językowych jeden \u0026ldquo;head\u0026rdquo; może wyłapywać z tekstu gramatykę, a inna emocje, tak tutaj każda z głów szuka w naszym wierszu danych zupełnie innego kontekstu. Dzięki temu w tym samym czasie jedna „głowa” może śledzić tylko twarde zależności geograficzne (np. obciążenia do województwa/operatora), inna szuka ukrytych powiązań technicznych (model pompy vs obciążenie), a nasz token [CLS] dostaje na końcu pełny, wielowymiarowy obraz sytuacji zamiast jednej, uśrednionej papki.\nNa samym zaś końcu wyrzucamy wszystkie inne wiersze z macierzy T prócz naszego [CLS], który zawiera takie meritum czyli całą informację potrzebną do dalszego przetwarzania (w naszym zadaniu do przewidzenia konkretnego obciążenia) i dalej idzie to prosto do klasyfikacji/regresji.\nZastosowanie FT-Transformera w naszym zadaniu Ostateczny Feature Engineering W trakcie tych 24 godzin dużo testowałem z różnymi feature\u0026rsquo;ami, nieraz pytając LLMa, czy może on ma jakieś ciekawe pomysły. W sumie wylistuję tu to, co udało się dodać i co finalnie zostało wykorzystane do ostatecznego nauczenia naszego Transformera, ale też część z tych feature\u0026rsquo;ów została oczywiście użyta do wytrenowania CatBoosta.\ndeviceType, czyli typ urządzenia, który pomaga modelowi uchwycić różnice w charakterystyce pracy.\nx3 to dodatkowa cecha kategoryczna z danych wejściowych, która wnosi informację o typie krzywej grzewczej.\noperator, a mianowicie nazwa operatora dostawcy, pozwalająca modelowi uwzględnić różnice wynikające z warunków eksploatacji oraz polityk działania.\nvoivodeship to województwo, czyli kontekst geograficzny wpływający między innymi na klimat oraz sezonowość zachowania systemu.\ndevice_operator_combo, czyli połączenie urządzenia oraz operatora, które pozwala łapać interakcje specyficzne dla konkretnej pary.\nt1_mean-t13_mean oznacza średnią wartość sygnału t1-t13 w oknie czasu opisującą jego typowy poziom.\nt8_max wyznacza maksymalną wartość t8 opisującą skrajne piki oraz epizody wysokiego obciążenia.\nt8_std to odchylenie standardowe t8 mierzące zmienność sygnału.\nt7_max oznacza maksimum t7, które wskazuje na chwilowe ekstremalne stany systemu.\nt4_min to minimum t4 przydatne do wykrywania głębokich spadków.\ndelta_load jest zmianą obciążenia między punktami czasowymi pokazującą dynamikę pracy układu.\ndelta_source wyznacza zmianę po stronie źródła, która może odzwierciedlać przełączenia lub skoki warunków zasilania.\ncwu_demand to zapotrzebowanie na CWU, czyli sygnał popytu wpływający bezpośrednio na pracę systemu.\ndelta_temp_out_in oznacza różnicę temperatury wyjścia oraz wejścia opisującą transfer energii a także efektywność procesu.\ncwu_spike jest flagą nagłego wzrostu zapotrzebowania CWU pomocną przy modelowaniu krótkich i gwałtownych zdarzeń.\nhour_sin to sinus z godziny doby, który koduje cykliczność czasu bez sztucznego przeskoku między godziną 23:00 a 00:00.\nhour_cos stanowi cosinus z godziny doby uzupełniający powyższy sinus i pozwalający modelowi odtworzyć pełną fazę dobową.\nmonth_sin jest sinusem z miesiąca reprezentującym sezonowość roczną w sposób ciągły.\nmonth_cos to cosinus z miesiąca, który razem z sinusem miesiąca domyka cykliczną reprezentację pór roku.\nCo pod maską? Sieć, głowica i hiperparametry Teoria teorią, ale teraz pora przejść do tego, jak my te Transformerowe klocki zaadaptowaliśmy do naszego datasetu.\nTeoretycznie wspominałem, że liczby są prosto wymnażane przez wektor wag. Jednakże my poszliśmy o krok dalej, a co za tym idzie każda cecha numeryczna była przetwarzana jeszcze przed samym wejściem do Transformera przez małą sieć neuronową, a mianowicie MLP (Multi Layer Perceptron):\n1 2 3 4 5 nn.Sequential( nn.Linear(1, embed_dim // 2), nn.ReLU(), nn.Linear(embed_dim // 2, embed_dim), ) Zrobiliśmy to, bo nie wszystkie cechy mogą wpływać liniowo na wynik, dlatego dorzuciliśmy trochę tej nieliniowości jeszcze przed samym wejściem do Transformera.\nCechy kategoryczne były standardowo zamieniane na embeddingi zgodnie z poprzednim opisem. Jedyne co, to dodaliśmy też miejsce na OOV, czyli Out of Vocabulary, w razie gdyby na przykład konkretny operator czy deviceType był nieznany. To, co dalej się dzieje, to klasyczny Feature Tokenizer Transformer opisany wcześniej. Jeśli chodzi o hiperparametry, to zastosowaliśmy:\nEmbedding size: 64 Multi head attentions: 8 Transformer layers: 3 Dropout: 0.1 Po tym, jak nasze dane przejdą przez wszystkie warstwy Transformera, dochodzimy do finału, czyli tzw. głowicy regresyjnej. Tutaj sprawa jest prosta: wyciągamy z całej macierzy tylko ten jeden, konkretny wektor [CLS], o którym pisałem wcześniej. Dlaczego akurat jego? Bo dzięki mechanizmowi atencji to właśnie on \u0026ldquo;nasiąkł\u0026rdquo; informacjami ze wszystkich pozostałych kolumn i ma w sobie skondensowaną wiedzę o całym wierszu danych.\nResztę wektorów (tych odpowiadających za np. region) po prostu odcinamy, bo wykonały już swoją robotę. Nasz [CLS] trafia do ostatniej, malutkiej sieci neuronowej składającej się z warstwy normalizacji i aktywacji ReLU, która ostatecznie \u0026ldquo;zgniata\u0026rdquo; te wszystkie skomplikowane liczby do jednej, finalnej wartości.\nNa samym końcu dorzuciliśmy jeszcze twardy bezpiecznik. Skoro przewidujemy obciążenie energii, to ujemny wynik fizycznie nie ma sensu, więc ucięliśmy wszystkie wartości poniżej zera, pilnując, żeby model nie wypluwał bzdur.\nFaza treningu Kilka słów o tym, jak w ogóle podeszliśmy do uczenia naszego modelu. Starałem się to zrobić najbardziej optymalnie, by nie trenować bez sensu naszego Transformera oraz nie marnować tak ważnego na hackathonie czasu. Mieliśmy dwie główne fazy:\nFaza 1, czyli taki poligon doświadczalny Zamiast trenować na wszystkim, zrobiłem twarde cięcie w czasie na początku lutego. Model uczył się na danych sprzed tej daty, a następnie miał przewidywać przyszłość, czyli to, co działo się po 1 lutego. Dlaczego podział po dacie, a nie losowy? Bo w przypadku obciążenia sieci elektrycznej losowy podział spowodowałby wyciek danych, czyli model widziałby \u0026ldquo;przyszłość\u0026rdquo;, żeby przewidzieć \u0026ldquo;przeszłość\u0026rdquo;. W tej fazie dorzuciliśmy też Early Stopping, by model przerywał naukę, gdy przestanie się poprawiać. Oczywiście zapisywaliśmy wszystkie checkpointy. Dzięki tej fazie wiedzieliśmy, jakie jest nasze realne MAE, zanim w ogóle wysłaliśmy cokolwiek do organizatorów.\nFaza 2, czyli cała naprzód Gdy po wielu testach w Fazie 1 upewniliśmy się, że nasza architektura działa stabilnie, to przeszliśmy właśnie do Fazy 2 \u0026ndash;\u0026gt; więcej danych = lepszy model. Na sam koniec zdjęliśmy blokadę z 1 lutego i wrzuciliśmy do pieca absolutnie wszystkie dostępne dane treningowe z przeszłości. Tak potężnie nafeedowany oraz wyregulowany model wygenerował ostateczne predykcje, które trafiły do naszego finałowego pliku submission.\nMały tip na sam koniec Warto jeszcze wspomnieć, że sam Transformer uczył się przeskalowanej wartości wskaźnika x2, zrealizowanej za pomocą StandardScalera. Sieci neuronowe lubią na ogół normalizację, więc to też mogło dołożyć swoją cegiełkę do stabilniejszego i bardziej efektywnego uczenia naszego FT-Transformera. Przed samym zapisaniem przewidzianej wartości do pliku wynikowego była ona w odpowiedni sposób przeskalowana do oryginalnego przedziału wartości.\nTriumf Transformera Kiedy opadł kurz, siedzieliśmy sobie w stołówce, zajadając pyszny obiad rodem z tych u babci. Byliśmy już trochę pogodzeni z myślą, że na top 10 nie mamy co liczyć. Ale wiadomo ciekawość to pierwszy stopień do\u0026hellip; sprawdzenia wyników. Zagryzając kotleta, postanowiłem zerknąć na Final Score.\nA tu okazuje się, że nasza siekiera była nie tylko precyzyjna, ale i rozbiła bank. Z wynikiem 0.008158 wyprzedziliśmy drugie miejsce o niemal 100% (ich MAE było prawie dwukrotnie wyższe!). To był ten moment, w którym loteria emocjonalna zamieniła się w falę euforii. Jednak przeżuwanie kotleta musiało gwałtownie nabrać tempa \u0026ndash;\u0026gt; trzeba było biec dopracować pitcha.\nP.S. W temacie obiadu: organizatorzy, jeśli to czytacie – ten posiłek na każdej edycji jest jak dar od bogów. Nie zmieniajcie tego! Działa on jak balsam na żołądek zmaltretowany toną pizzy i litrami energetyków. Epilog Zatem, czemu to mogło zadziałać, a nawet teraz już można powiedzieć, że zadziałało? Po pierwsze, zderzyliśmy się z charakterystyką drzew decyzyjnych: nie są stworzone do problemów ekstrapolacji. Każde drzewo tworzy sztywne podziały, których uczy się w trakcie treningu. Ale co, jeśli latem model zobaczy wartości zupełnie spoza zbioru treningowego? Z tym problemem znacznie lepiej radzą sobie architektury typu Transformer, które uczą się ciągłych relacji i nie są ograniczone sztywnymi ramami.\nPo drugie cóż, wiadomo, że ciężko powiedzieć coś na 100%, bo jednak tak duże oraz złożone sieci neuronowe to taka czarna skrzynka. Na pewno każda z wymienionych wcześniej praktyk kształtowała po trochu końcowy wynik. Jednak gdybym miał już coś wytypować, co mogło mieć większy wpływ, to położyłbym nacisk na ten sławetny mechanizm Multi-Head Self-Attention.\nGłównym problemem oraz wyzwaniem w tych danych było wyciągnięcie uniwersalnej wiedzy z miesięcy jesienno-zimowych, kiedy pompa ciepła zazwyczaj działa na pełnych obrotach i przeniesienie jej na letnie obciążenie, kiedy to wykorzystanie pomp jest znacznie mniejsze. W FT-Transformerze mechanizm kontekstu mógł modelować, jak mocno dane cechy mają wpływ na wynik oraz jak bardzo konkretne atrybuty powinny być brane pod uwagę w szczególnych przypadkach. Dodatkowo jeszcze nasz nieliniowy MLP, który przetwarzał nasze wartości numeryczne, też mógł wzbogacić te cechy i nadać im konkretny wpływ na wynik. Jak wiemy, Transformery nieźle generalizują i wydaje mi się, że to właśnie ta cecha zagrała pierwsze skrzypce w tym zadaniu.\nNiemniej jednak trzeba oddać honory innym drużynom, które były tuż pod nami. Mimo iż druga drużyna miała wynik gorszy od naszego (niemal dwukrotnie!!), to chyba jako jedyni wyciągnęliśmy tak ciężkie działo jak Transformer do tego zadania. Inne drużyny korzystały z drzew regresyjnych takich jak LightGBM i biorąc pod uwagę różnicę w skomplikowaniu naszej oraz ich architektury, to wykonali oni naprawdę świetną robotę. Niemniej jednak to nam udało się wyjść na prowadzenie i z naszego rozwiązania możemy być dumni!\nTo co\u0026hellip; za rok? Kolejny EnsembleAI i kolejny raz świetnie się na nim bawiłem. Wielkie dzięki dla organizatorów za tak świetny event oraz dla mojej drużyny DNS, czyli Drużyny Nieobecnego Szymona, w składzie:\nJakub Hudziak Jakub Binkowski Maciej Kaszkowiak Maciej Mazur oraz oczywiście ja :D Daliśmy ognia chłopaki i mam nadzieję, że nie po raz ostatni! Chyba się już powtarzam, jednak mówię to za każdym razem szczerze. To co, do zobaczenia za rok?\n","date":"2026-04-07T16:00:00Z","image":"https://blog.huszcza.dev/p/ensemble-ai-2026/cover_hu0e514019a1e8ec17548c39a03053cd2b_1242696_120x120_fill_q75_box_smart1.jpeg","permalink":"https://blog.huszcza.dev/pl/p/ensemble-ai-2026/","title":"Transformery na wycince drzew - EnsembleAI 2026"},{"content":"Nuty a kod, czyli jak 13 lat kształcenia muzycznego sprawiło, że jestem lepszym devem i nie tylko Ostatnio uświadomiłem sobie, że coraz częściej nachodzi mnie myśl, że największą stopą zwrotu jakiej doświadczam, jest tytułowe 13 lat szkoły muzycznej. Co więcej, niesamowite jest to, jak ten zainwestowany czas ma wpływ na prawie KAŻDĄ dziedzinę mojego życia. Jednakże na start może słowo o tym, jak te kilkanaście lat wyglądało.\n13 lat w suwalskiej „muzycznej”, czyli mój fundament Na samym wstępie chciałbym oznajmić, że szczęśliwie przez cały czas swojej nauki miałem styczność z najlepszym dydaktykiem oraz\u0026hellip; przyjacielem, z którym mam kontakt do dziś. Nuczyciel trąbki, Pan Paweł Misiukiewicz, przez ponad dekadę wpajał we mnie nie tylko to, że powinienem znać liczbę krzyżyków i bemoli w każdej gamie (o zgrozo! D:), ale również jak być zdeterminowanym, odpowiedzialnym i na swój sposób dojrzałym znacznie wcześniej, niż wymagały tego wiek i okoliczności poza szkołą.\nNie dość, że nauczyciel wymagał ode mnie wyżej wymienionych cech, to skłamałbym, mówiąc, że tylko to było wyzwaniem. Grającym \u0026ldquo;drugie skrzypce\u0026rdquo; nauczycielem była sama trąbka. Uważam, że jest to najbardziej uniwersalny, pięknie brzmiący instrument i nie wymieniłbym go na żaden inny (jest najlepszy wiadomo), ale\u0026hellip; na swój sposób niewdzięczny. Kiedyś to przeklinałem, ale dziś widzę, że te wszystkie korzyści to efekt \u0026lsquo;brute force’, który ten instrument na mnie po prostu wymusił.\nPo pierwsze, grając na trąbce gramy na ustach, a więc na małym, ale jednak mięśniu, dlatego systematyczność to chyba najważniejsza rzecz (pomijam tu aspekty techniczne itd.). Zawsze mnie to denerwowało, że tacy pianiści może ćwiczą statystycznie dłużej, ale jak zrobią sobie tydzień przerwy w wakacje, to nie dzieje się żaden dramat. A trąbka? 3 dni wolnego == 10 dni wracania do formy – taki właśnie przelicznik przedstawił mi Pan Paweł i naprawdę tak jest.\nSystematyczność: 3 dni wolnego == 10 dni powrotu do formy I tak oto wyłania nam się pierwsza cecha, którą praktykowałem przez 13 lat i staram się ją trenować do dzisiaj, mimo iż czasu z trąbką spędzam znacznie mniej - Systematyczność. Wyznaczając sobie jakiś cel, stopniowe dążenie do jego osiągnęcia naprawdę nie sprawia mi problemu; jest to we mnie wgrane jak Arch Linux u typowego redditowca. Nie muszę chyba pisać, że czy to studia, czy praca, czy siłownia, czy COKOLWIEK wymaga w naszym życiu systematyczności. Takim oto sposobem udało mi się osiągnąć rzeczy zupełnie niezwiązane z muzyką – np. regularne treningi na siłowni, szlifowanie języka albo regualarne czytanie (wszystko oczywiście równolegle ze studiami i pracą). Wiem, że zaraz ktoś sobie pomyśli: \u0026ldquo;Ziomuś, tyle osób ćwiczy i nie potrzeba do tego kilkunastu lat szkoły muzycznej XD\u0026rdquo;. Oczywiście zgadzam się, aczkolwiek chodzi mi o tę naturalność – to, że jest to dla mnie zwykłe i, pokuszę się nawet o stwierdzenie, relatywnie proste.\nKolejna cecha trąbki jest również ściśle powiązana z tą pierwszą. Widzimy już szkic, że trąbka wymaga czasu i systematyczności, a więc również świetnego planowania. Jak miałbym wyznaczyć coś, co w sobie lubię, to jestem naprawdę dobrym planistą, bo kolejny raz (będę to mówił dosyć często w tym poście) przez 13 lat była to codzienność, a nawet wymóg, by zrobić krok dalej.\nEgzamin techniczny i „muzykowanie”, czyli planuj bo nie zdasz Egzaminy w szkole muzycznej składają się często z konkretnego programu. Dla każdego instrumentu wygląda to inaczej, ale na trąbce już na średnim poziomie, czyli na II stopniu, mamy dwa egzaminy. Jeden techniczny, gdzie gramy - jak sama nazwa mówi - rzeczy skupiające się na samej technice grania, sposobie wykonywania czy trudniejszych \u0026ldquo;nutach\u0026rdquo;: duże skoki, wymagające tempo czy testowanie wytrzymałości. Drugi egzamin skupiał się na wykonaniu dłuższego utworu z akompaniamentem, np. fortepianu. Ja miałem przyjemność grać zawsze z najlepszą oraz niezawodną Panią Danutą Long. Mam nadzieję, że ani Pan Paweł, ani Pani Danuta nie będą mi mieli za złe, że wymieniam ich z imienia i nazwiska, ale nie sposób nie mówić wprost, jak bardzo oraz konkretnie czyj wkład doceniam i co wpłynęło na to, że patrzę na zainwestowane lata pracy z uśmiechem.\nTen drugi egzamin skupiał się bardziej na graniu \u0026ldquo;muzyki\u0026rdquo;. To dosyć szerokie pojęcie, ale ogólnie mam tu na myśli wykonywanie utworu w poprawny, obiektywnie ładny oraz zgodny z intencjami kompozytora sposób. Do tego dochodziło zgrywanie się z akompaniamentem, więc wymagało to trochę innej, już bardziej zespołowej pracy, a nie tylko indywidualnej jak w przypadku pierwszego typu.\nZarysowałem mniej więcej wymagania - widać, że to nie jest żadne \u0026ldquo;hop-siup\u0026rdquo;. Egzamin to naprawdę wiele godzin spędzonych na ćwiczeniu solo z nutami czy z Panią akompaniatorką. I właśnie te regularne egzaminy oraz oczywiście różne inne koncerty z orkiestrą i nie tylko (miałem okazję grać w różnych zespołach, orkiestrze szkolnej, miejskiej oraz wielu pobocznych projektach, jak np. kolędowanie z suwalskimi siatkarzami).\nNa każdy z tych eventów był termin, zorganizowane próby i na każde z nich trzeba było się przygotować kawałek po kawałeczku, skupiając się na tym, co wychodzi nam najgorzej w danej chwili. Każdą etiudę, każdy utwór - dosłownie wszystko, co przechodziło \u0026ldquo;przez moje palce\u0026rdquo; miało swój cel: czy to wprawki skupiające się na technice, czy akurat te dwie linijki, które wychodziły mi najsłabiej. Proces był prosty: zawsze musiałem sobie podzielić materiał tak, żeby zdążyć z zapasem, a w trakcie realizacji planu określić, co idzie najgorzej i skupiać się właśnie na tych częściach.\nA i bym zapomniał: większa część egzaminów wymagała nauczenia się materiału na pamięć. Tutaj chyba nie muszę nic więcej mówić - bez pychy stwierdzam, że moja pamięć to żyleta i jedyne, co ją ogranicza, to czas, jaki mam na naukę oraz ile rzeczy realizuję naraz. Ostatnio przekonałem się, że nawet moja pamięć ma limity, ale to może przy okazji innego wpisu.\nI tak szczerze: to były rzeczy, które towarzyszyły mi od siedmiolatka do - jakby to powiedział Pan Paweł - \u0026ldquo;starego konia\u0026rdquo; (tłumaczenie: nieprecyzyjne określenie na kogoś, od kogo już można wymagać; wiek raczej nieokreślony, w tym wypadku około 20 lat). Czym one się różnią od moich dzisiejszych wymagań w pracy? Dostaję \u0026ldquo;ticket\u0026rdquo; na Jirze, muszę rozplanować, co trzeba w nim zrobić, co zrobię najpierw, wyznaczyć termin i zidentyfikować, co wymaga najwięcej pracy i mocnego przetestowania. Jak na to spojrzeć to praktycznie to samo, tylko domena inna.\nDebugowanie stresu: Jak nie dać się tremie? Łatwo sobie wyobrazić, że nie tylko samo planowanie było nieodłączną częścią egzaminów i wystąpień, ale również stres. Szczerze mogę przyznać, że raczej należę do tych, którzy stresują się bardziej niż inni, mimo iż prawie zawsze czuję się dobrze przygotowany do wydarzeń, które ten stres wywołują. Niemniej jednak to, że wymagało to ode mnie więcej wysiłku, poskutkowało tym, że bardzo dobrze siebie znam. Wiem też, że stres odczuwam praktycznie tylko przed wystąpieniami, a kiedy zaczynam działać – wszystko ze mnie ulatuje.\nStresowe sytuacje dotykają nas codziennie: na studiach przed oddaniem ważnego projektu, w pracy przy prezentacji przed całym zespołem. Ja bardzo dobrze siebie znam. Wiem, że przed muszę sobie zająć głowę i mam w zapasie kilka technik, które pomagają mi ten stres tolerować i nie pozwalać mu na dominację, a przede wszystkim na uczucie strachu czy wymuszanie rezygnacji z czegoś.\nLekcja pokory: Co się nie dogra, to się dowygląda W trakcie pisania tego wpisu uświadamiam sobie, że wszystko jest ze sobą bardzo połączone, a ja, ciągnąc ten sznurek powiązań, zauważam po raz kolejny, że z każdym pociągnięciem odkryję coś nowego. Porażki i oczekiwania to chyba moja największa bolączka. Za to czasem trochę nienawidziłem trąbki: jak psujesz i kiksujesz (trębaczowe określenie, np. nietrafienie w dźwięk), to wszyscy o tym wiedzą. To nie jest jakieś brzdąknięcie na skrzypcach (może tak nie jest, ale tak to sobie wyobrażam); trąbka ze swoją donośnością i wyniosłością ogłasza, że ten tutaj kolega właśnie popełnił błąd – tak, żeby wszyscy słyszeli.\nDo dzisiaj pamiętam koncert orkiestry oraz moje niezbyt udane wejście, o którym wiedzieli wszyscy (a może mi się tylko tak zdawało? Nigdy się tego nie dowiem). Pamiętam także komentarz dyrygenta, Pana Czarka (również serdecznie pozdrawiam - uważam, że dyscyplina i profesjonalizm zawsze były podstawą funkcjonowania dobrego zespołu i grając w tej orkiestrze, właśnie to dało się odczuć), że \u0026ldquo;Benek stawia wszystkim piwo\u0026rdquo;. Pamiętam również okropny występ kwartetu (albo kwintetu?) dętego, w którym grałem, który widziała całą sekcja dęta szkoły, bo KTOŚ zadbał o to, by go nagrać i zaprezetnować.\nTakże porażek było dosyć sporo. Wspomnę też, że trąbka wymaga naprawdę dużej pewności siebie. Jeśli będziemy grać cicho, unikać wyjścia przed szereg, to tylko spotęgujemy możliwość błędu. Dopiero na końcowym etapie mojego kształcenia rozliczyłem się ze sobą i postanowiłem po prostu grać, nie bać się i nie myśleć o tym, że jak popełnię błąd, to będzie on bardziej słyszalny.\nZbierając to wszystko: widać, że radzenie sobie z porażkami i \u0026ldquo;twarda psycha\u0026rdquo; - i tutaj mam na myśli pogodzenie się przede wszystkim ze sobą, z faktem, że właśnie popełniło się błąd, i powiedzenie sobie: \u0026ldquo;dobra, idźmy dalej, postaram się bardziej następnym razem\u0026rdquo; - było kluczowe. Co więcej, po takim \u0026ldquo;udanym inaczej\u0026rdquo; koncercie nie było dopuszczalne filmowe ucieknięcie ze sceny albo pokazanie wszystkim, jak bardzo mi smutno. Do dziś pamiętam ostatnią zagraną okropną nutę felernego dnia koncertu kwartetu: odłożenie trąbki od ust, powstanie z szerokim uśmiechem, ukłon i zejście ze sceny. I dopiero wtedy zrzucenie z siebie tych pozorów.\nNo cóż, jak to się mówi: co się nie dogra, to się dowygląda\u0026hellip; I w sumie nie chodzi tutaj o samą aparycję czy robienie dobrej miny do złej gry (dosłownie!). Chodzi bardziej o niepozwolenie sobie na słabość na scenie, na rozlecenie się w momencie, gdy piłka jest jeszcze w grze. Po prostu akceptacja stanu, ale zachowanie profesjonalizmu aż do samego końca, nawet jak poszło źle. Jak o tym piszę, to myślę o takim kapitanie, co idzie na dno ze swoim statkiem. Podobnie tutaj: nie dajemy sobie przestrzeni w tym konkretnym momencie na emocje, tylko trzymamy się w ryzach. Tak samo podchodzę do błędów dzisiaj: porażką nie jest popełnienie błędu, a niewyciągnięcie wniosków i popełnienie go drugi raz dokładnie w taki sam sposób.\nFinalnie może dorzucę jeszcze takie największe wyzwanie, które zwieńczy moją historię w szkole muzycznej - koncert dyplomowy. Nie wiem, czy dla kogoś to może być pierdoła, ale dla mnie to było dotychczas największe wydarzenie. Koncert dyplomowy to około godzinny, otwarty koncert solowy (piszę z perspektywy trębacza), na który zaprasza się bliskich i znajomych (więc jak popsuć, to na oczach tych, na których najbardziej Wam zależy). Miałem tę przyjemność - za co jestem wdzięczny Panu Pawłowi - dostać wolną rękę co do utworów. Trochę czasu spędziłem na researchu, ale finalnie wykonałem utwory, które bardzo mi się podobały, a praca nad nimi była czystą przyjemnością (Centennial Horizon oraz Sonata Jean Hubeau).\nSam ostatni rok bardzo dobrze wspominam, bo byłem wtedy już na I roku informatyki i jeździłem co dwa tygodnie z Poznania do Suwałk, by brać udział w próbach właśnie z Panem Pawłem. Ćwiczyliśmy głównie utwory dyplomowe i bardzo mi się to podobało, bo były to próby na dużej sali koncertowej i skupialiśmy się głównie na muzykowaniu - by wykonanie było po prostu tak dobre, na jakie mnie stać. I chyba wypalił mi ten koncert. Czemu chyba? Bo był to taki stres, że naprawdę mało z niego pamiętam, ale jedno wiem: dowiozłem i nie zawiodłem ani mojego nauczyciela, ani bliskich, a przede wszystkim siebie. Finalnie dyplom ukończyłem z oceną celującą i w mojej głowie widnieje to jako jedno z większych osiągnięć. Za każdym razem, gdy mam przed sobą duże, stresujące wydarzenie, przypominam sobie ten fakt: że ogromem pracy i setkami godzin dowiozłem coś znacznie cięższego i większego. A więc czemu miałbym nie dać rady teraz?\nI tak oto kończę ten przydługawy wpis. Nie pisałem tutaj o takich oczywistościach jak gra zespołowa, bo to wydaje mi się naturalne. Nie pisałem też, jak bardzo doceniam dzięki szkole muzykę, jej kunszt oraz jak dużo emocji we mnie wywołuje. Jak czasem łapie mnie za serducho widok składu orkiestry.\nCoda: Podziękowania dla tych którzy są ze mną do dziś Nie miałem okazji nigdy wcześniej podzielić się przemyśleniami ani co do szkoły, ani muzyki i całej tej historii. A więc z tego miejsca chciałbym podziękować:\nPanu Pawłowi – przyjacielowi, nauczycielowi nie tylko muzycznemu, ale i życiowemu; Pani Danusi Long – najlepszej akompaniatorce i sojuszniczce, gdy potrzebowałem adwokata u Pana Pawła; Panu Grzegorzowi – który angażował mnie w swoje ambitne projekty i wyjazdy (wspominam je do dziś!), mimo iż nie zawsze udało mi się idealnie wszystko dograć; Panu Czarkowi – dyrygentowi orkiestry (oraz sąsiadowi!), której z dumą byłem członkiem i czułem się tam jak profesjonalista; oraz wszystkim znajomym i przyjaciołom – niejeden koncert zagraliśmy, niejeden wyjazd zaliczyliśmy i przeżyliśmy razem wiele świetnych chwil. I jak to się mówi: last but not least – dziękuję rodzicom. To oni pchnęli mnie na I stopień, wozili setki kilometrów na zajęcia, cierpliwie czekali i przyjmowali na siebie niejedną informację o tym, że coś sknociłem. Jednak jeszcze bardziej dziękuję im za to, że NIE PCHNĘLI mnie na II stopień. Czuję, że to było najważniejsze - to była Moja decyzja (tak, przez duże „M”) i właśnie to przeświadczenie dawało mi największego kopa sprawczości.\nPatrzę na ten czas z sentymentem i nie powiem - staram się jakoś angażować w wolnym czasie w sferę artystyczną, czy to teatr czy sam grając sobie kolejny raz \u0026ldquo;Centennial Horizon\u0026rdquo; bo czuję, że jest ona moją bardzo dużą i nieodłączną częścią.\nSwojego wykonania nie mam, ale może jak ktoś byłby zainteresowany i chciał przesluchać mój repertuar to zachęcam udać się w tę pochłaniającą podróż: Dzięki za przeczytanie tego posta. Może i Ty zaczniesz uczyć się na czymś grać albo zachęcisz kogoś, kto się nad tym zastanawia? Do następnego!\n","date":"2026-02-07T10:00:00Z","image":"https://blog.huszcza.dev/p/music-vs-it/cover_hu617634170b26205250057699274c3efc_1252253_120x120_fill_box_smart1_3.png","permalink":"https://blog.huszcza.dev/pl/p/muzyka-a-it/","title":"Nuty a kod, czyli jak 13 lat kształcenia muzycznego sprawiło, że jestem lepszym devem i nie tylko"},{"content":"MLA-C01: Jak zdałem egzamin Machine Learning Engineer - Associate Początki Ostatnio udało mi się z sukcesem zdać pierwszy certyfikat związany z chmurą. Padło na AWS Machine Learning Engineer - Associate i szczerze powiem, że postanowienie, by zdawać akurat ten konkretny certyfikat, było dość szalonym wyborem :D. Czemu? Architekturę AWS-a znałem poprzednio na bardzo podstawowym poziomie. Nauczyłem się jej trochę podczas tworzenia mojej pracy inżynierskiej we współpracy z OLX. Miałem wtedy okazję skorzystać z takich serwisów jak Cognito, S3, Translate czy kilku modeli z Bedrocka. Nie wiedziałem dosłownie nic o pojęciach typu VPC czy IAM, co oczywiście jest dosyć naturalne, bo nie były mi najzwyczajniej potrzebne podczas rozwijania projektu.\nJednakże wracając, czemu akurat TEN certyfikat? Mianowicie w pracy ukazało się ogłoszenie, że można wziąć udział w kursie, którego ukończenie pozwoli otrzymać voucher na egzamin. W tamtym momencie miałem na uczelni przedmiot ściśle związany z takimi pojęciami jak MLOps (Machine Learning Operations), który pokazał mi, jak bardzo podoba mi się ta tematyka, a wręcz fascynuje (pozdrawiam Janka, naszego prowadzącego ;)). Takim oto właśnie sposobem nie zastanawiałem się długo, w kilka sekund wypełniłem formularz i finalnie znalazłem się na liście kursantów.\nUważam, że kurs był dosyć wartościowy. Nie pamiętam dokładnie, jaka tematyka była poruszana na części wykładowej, ale każde nasze spotkanie kończyło się labami, na których mogliśmy porobić i pobawić się między innymi SageMakerem (platforma do budowania, trenowania i wdrażania modeli). Uważam, że to było wartościowe pod względem na pewno praktycznym i wiadomo, przetwarzanie i uruchamianie modeli na SageMakerze jest dosyć drogie, więc nie miałem dużo okazji (okrągłe zero) wcześniej z niego skorzystać. Po kursie otrzymałem voucher i tutaj zaczęła się moja dosyć przydługa droga prowadząca do egzaminu.\nPrzygotowania Na wstępie chciałbym zaznaczyć, że pierwszy semestr specjalizacji Sztuczna Inteligencja uważam za jeden z najcięższych w czasie całych studiów: projektów było mnóstwo, egzaminy nie były najprostsze, a to wszystko przy akompaniamencie pracy na 3/4 etatu. Jednym słowem: jazda bez trzymanki. Dlatego też, kończąc kurs w kwietniu, postanowiłem przenieść datę egzaminu na czerwiec – wtedy jeszcze mi się wydawało, że ma to bardzo dużo sensu. Bez przedłużania skoczmy więc do czerwca.\nW czerwcu po zakończeniu sesji (bez poprawek) uświadomiłem sobie, że nie mam totalnie siły po pracy ( już na pełen etat) siadać jeszcze i kuć do egzaminu, więc przerzuciłem naukę na lipiec.\nNo i w lipcu wiadomo jak to wakacje… aa, mam Was ;) W lipcu naprawdę zacząłem przygotowania, a jak już mowa o przygotowaniach, to kończę z formą mojego kochanego pamiętniczka i przechodzę do bardziej merytorycznego tonu, by każdy, kto przyszedł tu po „mięcho”, czyli jak zdać egzamin MLA-C01, wiedział, jak mi się to udało.\nJak uczyłem się do egzaminu? Najważniejsze odkrycie i coś, co bardzo mi pomogło, to grupa AWSCertifications na Reddicie. W skrócie: jest to zagłębie ludzi, którzy zdają, zdali lub uczą się na swoje egzaminy z AWS-a. Można tam znaleźć dosłownie wszystko w tej tematyce, od notatek po porady jak odpowiadać na pytania i je analizować. Codziennie pokazują się tam nowe wpisy, więc polecam sobie poczytać doświadczenia wielu ludzi, którzy przeszli już tę samą drogę.\nPo przeczytaniu miałem pierwszy wniosek: trzeba zacząć od kursów Stephane\u0026rsquo;a Maareka na Udemy. Tak też zrobiłem i obejrzałem ok. 24h wykładów mówiących o całym przekroju egzaminu. Od przetwarzania danych po udostępnianie modeli na SageMakerze. Na początku starałem się robić własne notatki i na pewno byłoby to wartościowe, ale zaznaczę, że nie wiedziałem nic i wszystko, co słyszałem, było dla mnie nowe. Co więcej nie zajęłoby to 24h, a pewnie dwa razy tyle. Po kilku działach przerwałem i postanowiłem chłonąć wiedzę na bieżąco i zrozumieć najwięcej, jak się da. Także ten krok polecam każdemu, ja słuchałem tych wykładów nie tylko je uważnie oglądając, ale czasem przygotowując obiad i wydaje mi się, że even w takiej formie coś mi tam w głowie zostało.\nWarto zaznaczyć (to jest rzecz, którą wiem właśnie z Reddita), że niektóre działy, takie jak przetwarzanie danych, Stephane Maarek wziął z innych egzaminów, i to bardziej zaawansowanych. Czasem wiedza jest mocno szczegółowa, może nawet za bardzo jak na poziom Associate (mamy 4 główne poziomy egzaminów AWS, od najłatwiejszego do najtrudniejszego z największą ilością szczegółów: Practitioner, Associate, Specialty, Professional). Niemniej jednak po egzaminie uważam, że warto wiedzieć więcej niż mniej, bo niektóre pytania były naprawdę bardzo szczegółowe. Dodatkowo jest też segment o popularnych architekturach i omawiana jest architektura Transformer – to na pewno można pominąć i, jak ktoś się spieszy, to polecam. Jak nie, to zawsze warto poszerzyć horyzonty.\nPo wykładach wziąłem kolejny kurs od Stephane\u0026rsquo;a Maareka - Praktyczne egzaminy. Trzy pełne praktyczne egzaminy, które są naprawdę trudne. Świeżo po obejrzeniu wykładów osiągnąłem kolejno: 66%, 67% i 70%. A aby zdać egzamin, potrzebujemy 72%. Mimo że wyniki nie były najlepsze, to właśnie z tych praktycznych egzaminów dowiedziałem się i zapamiętałem najwięcej. Dlaczego? Bo chyba tak działam i mimo że nadal to były pytania ABC, to mają one dosyć praktyczny wydźwięk, a więc analizujemy, jakie rozwiązania są najlepsze dla danej „historyjki”, np.: firma A chce sobie wyhostować model, chce to zrobić najtaniej, ale musi zwrócić uwagę na to, że w ruchu w ich aplikacji są nagłe nieprzewidywalne skoki – czego muszą użyć? I z każdym kolejnym pytaniem analizujemy i dowiadujemy się, jakie rozwiązanie dostępne na AWS najlepiej do tego zastosować, jaką mają specyfikę i oczywiście cenę.\nPodobał mi się ten format i mimo że był z początku dosyć trudny, tak był znacznie lepszy dla mnie niż słuchanie suchych wykładów (aczkolwiek nadal polecam to zrobić). Rekomenduję też zwrócić uwagę na czysto Machine Learningowe aspekty: regularyzacja, overfitting, metryki czy nawet kwantyzacja lub fine-tuning, taki jak LoRa.\nPo przerobieniu testów nadal nie czułem się pewnie, a że uczenie się na błędach okazało się u mnie efektywne, postanowiłem poszukać kolejnych testów. I tutaj wchodzi Tutorials Dojo - fajne odświeżenie, ale testy znacznie prostsze niż na realnym egzaminie oraz testy Maareka. Było kilka ciekawych i nietuzinkowych pytań, ale uważam, że warto je zrobić w celu eksploracji wiedzy i poznania kolejnych przypadków użycia serwisów, niż dla realnego przygotowania do pytań na oryginalnym egzaminie.\nNiemniej jednak nadal bym je zrobił, tylko w innej kolejności.\nMoja rekomendowana kolejność:\nWykłady Maareka (jako solidna baza wiedzy) Pytania Tutorials Dojo (jako utrwalenie i eksploracja przypadków użycia) Egzaminy Maareka (jako finałowy boss i prawdziwy test bojowy) Ja po przerobieniu egzaminów od TD (Tutorials Dojo) wróciłem ponownie do egzaminów Maareka (od momentu, kiedy je robiłem, minęły około 2 miesiące, wiecie, urlop i takie sprawy\u0026hellip;) i na drugim podejściu uzyskałem kolejno: 81%, 86% i 81%. Podczas kolejnego podejścia do robienia tych egzaminów robiłem kompleksowe notatki, zarówno z pytań, w których popełniłem błędy, jak i również tych poprawnych, bo czasem czujemy odpowiedź, ale nie jesteśmy pewni - ją też warto przeanalizować, zrozumieć i uzyskać pewność w wyborze.\nPo powyższym zapisałem się na egzamin i do egzaminu przez te kilka dni czytałem tylko pełną prezentację Maareka oraz własne notatki. Na egzaminie miałem dodatkowe 30 minut akomodacji ze względu na to, że nie jestem native\u0026rsquo;em i nie powiem, dosyć się przydało. Podczas pierwszego obiegu po pytaniach nie marnowałem dużo czasu i zaznaczałem taką odpowiedź, jaką czułem i rozumiałem najbardziej, ale dzięki temu udało mi się w czasie zrobić 2 takie przebiegi. Drugi już na spokojnie, analizując mocno każde pytanie, co pozwoliło mi przemyśleć odpowiedzi i finalnie zmienić 7-8 z nich, bo odkryłem kilka słów-kluczy zarówno w odpowiedziach, jak i pytaniach. I tak oto ok. 11h po egzaminie dostałem wiadomość, że zdałem z wynikiem 818 i jestem z niego całkiem dumny (tak samo jak z odznaki, którą otrzymałem od AWS-a)\nSam egzamin podsumowałbym jednym słowem: tricky. Wiele odpowiedzi wydaje się poprawnych, ale ma jedno słówko, które totalnie zmienia ich sens. Tak samo było z pytaniami. A więc polecam zdekomponować sobie w głowie pytania na składowe, dowiedzieć się, jakie są dokładnie wymagania, co chcemy osiągnąć i na czym się skupić.\nLLM-y w procesie uczenia Myślę, że warto też wspomnieć, jak wykorzystywałem AI podczas uczenia. Na wcześniej wspomnianym reddicie jest na ten temat mnóstwo wątków, a jak to się mówi \u0026ldquo;rabini są niezgodni\u0026rdquo;.\nJak miałbym skrócić, jak używałem AI, byłoby to po prostu słowo: Dlaczego?\nJeśli w testach było jakieś wytłumaczenie, ale czułem, że to za mało, to właśnie z tym pytaniem szedłem do Gemini albo ChataGPT. Na początku jeszcze sprawdzałem, czy odpowiedzi zgadzają się z dokumentacją AWSa, ale po jakimś czasie przestałem, bo odpowiedzi były raz za razem poprawne. Uważam, że super jest wykorzystywać te narzędzia właśnie w ten sposób czyli do obrazowania, lepszego opisywania i wyjaśniania. Do pokazywania przypadków użycia albo dawania prostych przykładów.\nCo ważne, ani razu nie użyłem LLM-ów, żeby dały mi poprawną odpowiedź na pytanie. Wolałem sam zaznaczyć najbardziej logiczny wybór (jeśli nawet był zły) i dopiero później poprosić AI o wyjaśnienie. I taki sposób u mnie zadziałał rewelacyjnie.\nPolecam Benedykt Huszcza\nCo teraz? Wszystkim, którzy się uczą, życzę powodzenia! Dla tych, co nie zdali, mam nadzieję, że moja ścieżka pomoże Wam pokonać egzamin za drugim razem, a reszcie - dzięki za przeczytanie tego posta! W razie co piszcie na mojego maila lub sociale. Chętnie odpowiem na pytania oraz pomogę, jak umiem najlepiej. Na dole wrzucam sekcję dla osób, które chcą po prostu dowiedzieć się skrótowo, jak przebiegała moja nauka. Teraz, jak zawsze, pozostaje pytanie: co teraz zajmie mi głowę…?\nJak udało mi się zdać MLA-C01 (wersja TL;DR) Zacząłem od Reddita: Przejrzałem AWSCertifications. Super sprawa, żeby zobaczyć, jak inni się uczyli i jakie mają wskazówki. Wykłady Stephane Maarek (Udemy): Najpierw obejrzałem cały kurs (~24h). Na tym etapie głównie chłonąłem wiedzę, żeby zrozumieć ogólny obraz. Testy Tutorials Dojo: Przerobiłem je jako trzecie, ale polecam jako drugie. Były fajne, żeby poznać więcej przypadków użycia serwisów, ale czułem, że są prostsze niż realny egzamin. Testy Praktyczne Stephane Maarek (Udemy): To był dla mnie \u0026ldquo;finałowy boss\u0026rdquo; i najważniejszy etap. Te testy są naprawdę trudne (moje pierwsze wyniki to 66-70%) i to z nich nauczyłem się najwięcej. Klucz do sukcesu (u mnie): Podczas robienia testów robiłem bardzo szczegółowe notatki. Analizowałem nie tylko pytania, w których popełniłem błąd, ale także te, na które odpowiedziałem poprawnie (zwłaszcza jeśli było to \u0026ldquo;na czuja\u0026rdquo;). Chodziło o to, by naprawdę zrozumieć dlaczego dana opcja jest najlepsza. To pozwoliło mi zdobyć wiedzę, zapamiętać i zrozumieć sens. Rekomendowana kolejność: Wykłady Maareka -\u0026gt; Testy Tutorials Dojo -\u0026gt; Testy Maareka + robienie dogłębnych notatek. Przed egzaminem: Powtarzałem już tylko z własnych notatek i slajdów z kursu Maareka. Na egzaminie: Czytałem pytania bardzo uważnie. Są \u0026ldquo;tricky\u0026rdquo;. Rozbijałem je w głowie na wymagania, szukałem słów-kluczy i zrobiłem dwa obiegi przez wszystkie pytania. ","date":"2025-11-03T12:00:00Z","image":"https://blog.huszcza.dev/p/aws-mla-c01-en/cover_huda35e8d3581351945c7eae22c1f222ff_1066935_120x120_fill_box_smart1_3.png","permalink":"https://blog.huszcza.dev/pl/p/aws-mla-c01/","title":"MLA-C01, czyli jak zdałem egzamin Machine Learning Engineer - Associate"},{"content":"W dniach 14-16.03.25 razem z zespołem mieliśmy okazję wziąć udział w hackathonie w Krakowie. Uczestniczyliśmy już w poprzedniej edycji, więc jeśli chcecie dowiedzieć się więcej o tym wydarzeniu, serdecznie zapraszam do lektury wpisu Macieja. W skrócie – było to nasze pierwsze starcie z tworzeniem sieci neuronowych. Co więcej, uczyliśmy się wszystkiego na bieżąco, więc wyzwanie było naprawdę spore. Mimo wszystko udało nam się zająć 12 miejsce, co było dla nas duużym osiągnięciem! W tym roku poszło nam jeszcze lepiej – udało nam się wywalczyć 3 miejsce!\nPROLOG - przeddzień walk Założenie na ten hackathon mieliśmy proste: wiemy już więcej o AI i jeśli przyjdzie nam zmierzyć się z pisaniem sieci neuronowej, to jesteśmy na pewno lepiej przygotowani niż poprzednim razem.\nWspólnie z Jakubem Binkowskim mieliśmy również okazję przejść przedmiot Sieci neuronowe, co dało nam znacznie szerszy pogląd na przetwarzanie obrazów, techniki regularyzacji i sposoby zapobiegania przeuczenia modeli.\nW piątek postanowiliśmy też zapoznać się z materiałami przesłanymi przez organizatorów. Mimo że nie był to dla nas łatwy materiał, udało nam się przebrnąć przez kilka z nich i wyciągnąć coś wartościowego. Jak okazało się później, mogliśmy się po prostu porządnie zrelaksować\u0026hellip;\nPoczątek - intuicja ponad wszystko A więc lądujemy w sali na wystąpieniach otwierających i dostajemy kilka kluczowych informacji.\nPo pierwsze, dzięki współpracy organizatorów z Cyfronetem, każdy zespół miał do dyspozycji naprawdę potężne maszyny – i tutaj poczułem, że to solidnie przyspieszy naukę naszych modeli. Liczby i moc obliczeniowa zrobiły ogromne wrażenie, więc kolejny raz mogę zbić piątkę z organizatorami za świetny pomysł.\nNastępnie dowiedzieliśmy się, jakie będą zadania, i tutaj spotkało nas lekkie zaskoczenie. Okazało się, że każdy zespół musi wybrać jedną z dwóch ścieżek:\nPierwsza – składała się z czterech podzadań dotyczących uczenia adwersarzowego, kradzieży modeli i kilku innych tematów związanych z szeroko pojętym uczeniem maszynowym. Druga – zadanie polegało na nauce bota do gry stworzonej przez organizatorów. Boty miały grać między sobą, a zasady rankingu były proste: za remis drużyna dostaje 0.5 pkt, za wygraną 1 pkt, za przegraną – wiadomo\u0026hellip; smutne i okrągłe 0 pkt. Wow, nie wiedzieliśmy, że tak szybko dopadnie nas widmo decyzji, ale na szczęście mieliśmy na nią ponad 8 godzin, więc był czas na testy i ocenę, w którym zadaniu będziemy czuć się najlepiej. Po wykładach chwilę się rozluźniliśmy, podeszliśmy do kilku stanowisk – między innymi do JetBrainsów. Razem z Szymonem jesteśmy fanami ich IDE, więc była to naprawdę fajna gratka. Także od dzisiaj oficjalnie staję się ich chodzącą reklamą, ale co tam – naprawdę doceniam jakość ich rozwiązań. 😎\n3, 2, 1, start! - wyścig rozpoczęty! Na początku, przez lekkie niezrozumienie zasad, postanowiliśmy jak najszybciej wypuścić pierwszą wersję bota – byliśmy przekonani, że rating będzie naliczany co godzinę, a finalny ranking będzie sumą poszczególnych pojedynków z trawania całego hackathonu.\nWypuściliśmy więc coś prostego, ale obrazowo nazwanego – ICBM. Rakieta leciała prosto z naszej bazy do bazy przeciwnika. Gdy tylko mieliśmy zasoby, odpalaliśmy kolejną rakietę.\nI, ku naszemu zaskoczeniu, takie rozwiązanie dało całkiem niezłe efekty na samym początku – na tyle dobre, że poczuliśmy wiatr w żaglach i postanowiliśmy w pełni skupić się na tym zadaniu.\nOctoSpace – zasady gry w pigułce 🚀 W grze celem jest całkowita dominacja. Można wygrać na dwa sposoby – eliminując przeciwnika poprzez przejęcie jego planety lub zdobywając więcej punktów po 1000 turach (w końcowym etapie organizatorzy zwiększyli tury do 2000, bo było za dużo remisów). Plansza o wymiarach 100x100 jest początkowo pokryta mgłą, a eksploracja statkami odkrywa jej kolejne obszary.\nStatki pozwalają walczyć i zdobywać planety. Standardowa prędkość ruchu to 1 lub 2 pola na turę, jednak wchodząc w spowalniającą mgłę, statek porusza się trzykrotnie wolniej, a zderzając się z asteroidą, otrzymuje obrażenia. Statki mogą atakować na dystans do 8 pól, ale po każdym strzale z założenia miało następować 10-tur cooldownu, jednak odkryliśmy, że finalnie to nie było żadnego cooldown-u :D. Leczenie jednostek jest możliwe tylko na własnych planetach, gdzie odzyskują 1 HP na turę.\nAby powiększać flotę, potrzebujemy surowców, które zdobywamy kontrolując planety. Każda planeta składa się z 16 pól zasobów, a ilość pozyskanych surowców zależy od ich rodzaju i liczby kontrolowanych pól. Początkowa planeta ma wszystkie zasoby w równych proporcjach, ale inne planety mogą mieć ich nierównomierny podział.\nZdobywanie planet odbywa się poprzez wpadnięcie statku na planetę. Jeśli planeta jest nieprzejęta, przejmujemy ją natychmiast. W przypadku zajętej planety rozpoczyna się proces przejęcia, który trwa kilka tur. Jeśli planeta była w trakcie przejmowania przez przeciwnika, można zneutralizować jego postępy i odzyskać kontrolę.\nNasz plan Nie mieliśmy złudzeń – żaden z nas nigdy wcześniej nie tworzył modelu opartego na Reinforcement Learningu. Jedyne, co mieliśmy na ten temat, to zajęcia sprzed tygodnia, na których razem z Jakubem poznaliśmy podstawowe problemy i założenia RL. Nie porzuciliśmy od razu wizji stworzenia czegoś więcej niż heurystyk, ale od nich chcieliśmy zacząć. Wiedzieliśmy, że i tak będą nam potrzebne – choćby po to, żeby w razie czego móc trenować model przeciwko różnym strategiom.\nJednakże\u0026hellip; spoiler alert – dowiedzieliśmy się, że na maszynie testowej nie można korzystać z bardziej wysokopoziomowych narzędzi do RL. Możemy używać tylko czystego PyTorcha (only sad reactions).\nI tak oto przybiliśmy gwóźdź do trumny i zamiast walczyć z ograniczeniami, postanowiliśmy przerzucić wszystkie siły na stworzenie najmocniejszej heurystyki, na jaką nas stać.\nOd rakiety do floty - nasze pomysły Na starcie nasza heurystyka zawierała tylko jeden typ statku – ICBM. Jego zadaniem było czyste bombardowanie bazy przeciwnika. Proste, ale skuteczne – nawet bardziej niż skuteczne, bo przez pierwsze 12 godzin hackathonu zajmowaliśmy pierwsze miejsce w tabeliXD. To było dla nas spore zaskoczenie.\nICBMv2 - pierwsze ulepszenie Kolejnym krokiem była wersja ICBMv2, która miała zaimplementowany pathfinding, czyli lokalne znajdowanie najlepszej ścieżki, omijającej asteroidy i mgły spowalniające. W strategii bombardowania bazy przeciwnika było to kluczowe, bo każde spowolnienie naszej rakiety działało na naszą niekorzyść.\nDefender - pierwsza linia obrony Defender to nasza ostoja i pierwsza pomoc w systemie bezpieczeństwa. Jego zadanie było następujące:\nUstawić się pod odpowiednim kątem i razem z drugim defenderem tworzyć ogień krzyżowy, pokrywający większość ataków na naszą bazę.\nW razie kryzysu pełnił funkcję pierwszej pomocy – jeśli baza była atakowana, a nie mieliśmy wystarczających zasobów na nowy statek (stworzenie nowego statku w trakcie przejmowania zatrzymywało przejmowanie), defender leciał na ratunek i odbijał bazę.\nExplorer - zwiad i zbieranie zasobów Wiedzieliśmy, że zmasowany atak bez zasobów szybko się skończy, więc potrzebowaliśmy kogoś, kto nie tylko zdobywa surowce, ale i odkrywa mapę.\nExplorer korzystał z pathfindingu, ale\u0026hellip; nie udało nam się stworzyć idealnego algorytmu szukania ścieżki, więc zdarzało się, że się blokował. W finalnej wersji, jeśli utknął, zmieniał się w rakietę, dodatkowo zmieniając standardowy wektor ataku naszej strategii (standardowym wektorem była główna przekątna mapy). Btw. Jak widzę nagłą przemianę explorera w rakietę to mam przed oczami ten obraz:\nBackdoor - cichy zabójca Analizując naszą taktykę, zauważyliśmy, że jest wrażliwa na ataki z granic mapy. Idąc tym tropem, doszliśmy do wniosku, że przeciwnicy też mogą nie zabezpieczać się wystarczająco.\nTak powstał Backdoor – cichy zabójca, który po dotarciu za bazę przeciwnika i odczekaniu odpowiedniego czasu niespodziewanie ją atakował.\nW finalnym rozrachunku nie okazał się wystarczająco efektywny, by wprowadzić go do naszej strategii, a czas nie pozwalał nam również dokładnie przetestować jego wpływu. Jednakże jego sposób działania był na tyle komiczny, że muszę to pokazać XD.\nYour browser doesn't support HTML5 video. Here is a link to the video instead. Na nagraniu widać jak zielone backdoory gracza pierwszego skradają się na krańcu mapy, odczekują chwilę, a następnie razem atakują. Na przekątnej natomiast widać różowe statki gracza drugiego, czyli wersje ICBM naszych statków.\nSmażenie wrogów - dodatkowy atut rakiet Do tej pory nasze boty nie wykorzystywały strzelania, ale na końcowym etapie hackathonu je dodaliśmy – i to działało naprawdę dobrze.\nKażdy napotkany przeciwnik, póki był w naszym zasięgu, był kolokwialnie mówiąc grillowany 🔥. Jednak w naszej głównej taktyce, gdzie statki nie były statkami, a latającymi rakietami planeta → planeta, ta funkcjonalność niestety spowalniała je, co wpływało negatywnie na ich efektywność.\nPomysły, na które nie starczyło nam czasu Wariant Szymona - stackowanie rakiet i zmasowany atak Plan był prosty – gromadzimy rakiety, a potem wysyłamy je w jednym, miażdżącym ataku.\nBrzmi jak coś, co naprawdę mogłoby zadziałać, ale\u0026hellip; niestety nie starczyło nam czasu, żeby to przetestować :(\nKilka usprawnień w procesie tworzenia Bota Warto zaznaczyć, że nie samym kodem nasze rozwiązanie żyło.\nPonieważ przesyłany bot musiał zmieścić się w jednym pliku, a nasza struktura zawierała ich wiele, w tym wspólne funkcje dla różnych modułów, stworzyliśmy skrypt, który łączył plik utils.py z naszą wersją agenta (bota).\nKażdy agent miał swój własny folder i moduł. Proste, ale jakże skuteczne. Żeby porównać dwa rozwiązania, wystarczyło w skrypcie podać nazwy folderów, w których znajdowali się nasi agenci i\u0026hellip; cyk!. Dwa boty rozpoczynały batalię między sobą – za jednym kliknięciem Entera. Brzmi to bardzo prosto, ale uwierzcie mi, że sam pewnie nabiłem ponad sto odpaleń tego skryptu, a przy takiej liczbie każde dodatkowe kliknięcie ma znaczenie.\nCI/CD - automatyzacja wykrywająca błędy W trakcie hackathonu pojawiał się nie jeden błąd w grze (kodzie źródłowym), a organizatorzy naprawiali je na bieżąco. Wpływało to na kompatybilność naszych botów, więc dodanie automatyzacji pozwoliło nam sprawdzać, czy nasze konfiguracje nadal działają zgodnie z nową wersją gry. Dodatkowo mieliśmy w planach równoległe i automatyczne testowanie nowych botów, ale\u0026hellip; po raz kolejny nie starczyło nam na to czasu.\nFinał - triumf prostoty Nasza finalna heurystyka prezentowała się następująco:\n🔥 Rdzeń: rakiety ICBM Jeśli defenderzy są na miejscu i nie wypada tura na tworzenie Explorera, to bombardujemy przeciwnika ICBMv2. Dodatkowo na samym początku gry wypuszczamy dwie wersje rakiety v1 oraz v2.\n🚀 Wsparcie: Explorer Co jakiś czas do gry wchodził Explorer – jego głównym zadaniem było szukanie planet z zasobami.\nJeśli uległ zakleszczeniu, zmieniał się w rakietę ICBMv2, randomizował wektor ataku.\n🛡️ Bezpieczny mur: Dwójka Defenderów Bez większych zmian – jeśli baza jest atakowana i nie możemy jej obronić nowym statkiem, to Defender zmieniał się w medyka. W innym przypadku prowadził ciągły ogień krzyżowy, smażąc wszystko, co popadnie.\nI tak! Taka heurystyka dała nam 3. miejsce! 🏆\nMoże wydawać się trywialna, ale naprawdę przyniosła efekty. Jak widać, nie rzuciliśmy się na falę szczęścia, tylko w testach i ewaluacjach to podejście okazało się najefektywniejsze.\nA jeśli działa, to znaczy, że jest co najmniej dobre.\nGamechanger - wiedza prosto z kodu źródłowego Warto też zaznaczyć, że przez cały czas trwania hackathonu analizowaliśmy kod źródłowy gry. Dzięki temu poznaliśmy jej działanie od samych podstaw, dowiedzieliśmy się, że czasami zamiast strzelać, lepiej uciekać, a także odkryliśmy wiele innych sprytnych taktyk, które wykorzystaliśmy w naszym finalnym rozwiązaniu.\nEpilog Pisząc ten post, nadal czuję naprawdę dużą satysfakcję, ale przede wszystkim cieszę się z czasu spędzonego z drużyną. Naprawdę to świetne uczucie – walczyć ramię w ramię z kolejnymi przeciwnościami, mając u boku taką ekipę jak nasza. Co więcej, sam event, mimo drobnych potknięć, był nie tylko ambitny, ale też świetnie przemyślany.\nNa wielu hackathonach wybór zwycięzcy opiera się na subiektywnej opinii jury, a tutaj wygrywa matematyka – kto wyżej w rankingu, ten lepszy. I to jest coś, co naprawdę doceniam.\nMam wielką nadzieję, że za rok ponownie uda nam się wziąć udział w kolejnej edycji wydarzenia. Wiem, że następnym razem będziemy jeszcze mocniejsi i wierzę, że znów staniemy w szranki – zarówno ze swoimi słabościami, jak i z wieloma naprawdę utalentowanymi i ambitnymi deweloperami.\nPodziękowania Dzięki ekipo!\nMaciej Kaszkowiak, Jakub Binkowski, Maciej Mazur i Szymon Pasieczny – jak już mówiłem, dzięki wam hackathon to nie tylko kodzenie, ale też świetnie spędzony czas z dużą dozą śmiechu, żartów i tryhardu. Czyli mieszanka w idealnych proporcjach.\nDzięki Adamowi Mazurowi – przewodniczącemu koła \u0026ldquo;Ghost\u0026rdquo; na Politechnice Poznańskiej. Dzięki jego zaangażowaniu najprawdopodobniej otrzymamy finansowanie od uczelni, a to naprawdę dobre uczucie – mieć świadomość, że nasza uczelnia wspiera nas w tym, co robimy.\nDzięki organizatorom! – bez was nie byłoby tego eventu. Czuć, że wykonaliście kawał dobrej roboty – dużo rzeczy zostało poprawionych względem poprzedniej edycji i wiem, że ta tendencja będzie utrzymana.\nKto wie, może kiedyś hackathon odbędzie się na Politechnice Poznańskiej? 🤔\nDzięki za poświęcony czas na przeczytanie tego wpisu! Na dole wrzucam kilka fotek z wydarzenia, a jak dojdą jakieś nowe, to postaram się je uzupełnić!\n","date":"2025-03-18T16:00:00Z","image":"https://blog.huszcza.dev/p/cover_hubd3a1d1e4832aaa50c390556c17ca78a_2091579_120x120_fill_box_smart1_3.png","permalink":"https://blog.huszcza.dev/pl/p/ensemble-ai-2025/","title":"EnsembleAI 2025"},{"content":"Czym jest Benedykt-the-Dev? Benedykt-the-Dev to moja strona osobista, na której dzielę się portfolio, umiejętnościami oraz wpisami na blogu o moich doświadczeniach i zainteresowaniach. Do stworzenia tego projektu użyłem Next.js oraz kilku mniejszych bibliotek, o których opowiem za chwilę. Blog zbudowałem na Hugo, co pozwala na szybkie działanie i świetną optymalizację pod kątem SEO.\nNie mogę nie wspomnieć, że inspirację do tego projektu zaczerpnąłem od Macieja. Jego wpisy zawsze czytałem z ciekawością, co ostatecznie zmotywowało mnie do stworzenia własnej strony.\nSzczerze mówiąc, rok temu nie przypuszczałbym, że będę pisał wpis na bloga o swojej własnej stronie. Liczę na to, że za rok spojrzę na to z podobną refleksją – ale tym razem w kontekście czegoś zupełnie innego, o czym teraz nawet nie mam pojęcia.\nCo znajdziesz na stronie? Portfolio – Najważniejsze projekty z linkami do wpisów na blogu, moja ścieżka kariery, zainteresowania oraz możliwość kontaktu. Blog – Miejsce, w którym dzielę się przemyśleniami, poradnikami i doświadczeniami z mojego życia. Stack technologiczny Next.js – Framework frontendowy, który świetnie współpracuje z SEO oraz oferuje szybkie działanie dzięki renderowaniu po stronie serwera (SSR). W przyszłości ułatwi mi też wdrażanie nowych funkcji, np. formularza kontaktowego. Framer Motion – Moje pierwsze doświadczenie z tą biblioteką animacji. Bardzo intuicyjne rozwiązanie, które pozwala ograniczyć zbędny kod. React Typist – Użyłem tego narzędzia, żeby uzyskać efekt pisania na ekranie. Jest lekkie i proste w implementacji – dokładnie to, czego potrzebowałem. Tailwind CSS – Framework CSS typu utility-first, który umożliwia pisanie spójnych i nowoczesnych stylów bez potrzeby korzystania z dodatkowych plików CSS. Uwielbiam to rozwiązanie za możliwość pisania komponentów i stylów w jednym miejscu. Hugo – Blog oparty jest na Hugo, co gwarantuje szybkie ładowanie oraz dobrą optymalizację pod kątem SEO. Początkowo miałem ambitny plan, by napisać wszystko od podstaw, włącznie z backendem i CMS-em. Jednak ostatecznie postawiłem na Hugo, co pozwoliło mi szybciej zacząć publikować wpisy na blogu. Tutaj również inspirowałem się podejściem Macieja, który polecił to rozwiązanie. Co dalej? Ten projekt był świetną okazją do pokazania moich umiejętności oraz dzielenia się wiedzą z zakresu web developmentu, AI i innych tematów, które mnie interesują. Planuję rozbudować stronę o sekcję dotyczącą hobby czy wykształcenia.\nJednak nie oszukujmy się – najbliższe miesiące będą dość intensywne, bo za tydzień zaczynam nową pracę na 3/4 etatu oraz studia II stopnia ze specjalnością AI. Presja? Owszem, ale podobno to przywilej – więc zamierzam to wykorzystać na maksa. Na nudę na pewno nie będę narzekać!\nChcesz zobaczyć kod źródłowy albo dowiedzieć się więcej? Sprawdź repozytorium na GitHubie.\n","date":"2025-02-24T16:00:00Z","image":"https://blog.huszcza.dev/p/benedykt-the-dev/cover_hu5459c0360c2b0cb7a147d2df0eb350ca_2043236_120x120_fill_q75_box_smart1.jpg","permalink":"https://blog.huszcza.dev/pl/p/benedykt-the-dev/","title":"Benedykt-the-Dev – Portfolio i Blog Programistyczny"},{"content":"Nasza praca inżynierska – Czy to przyszłość marketingu? Projekt powstał w czteroosobowym zespole jako nasza praca inżynierska. Było to dla nas ogromne wyzwanie, ale jednocześnie niesamowita przygoda, która pozwoliła nam połączyć kreatywność z nowoczesną technologią.\nPisząc ten wpis, czuję dumę z tego, co udało nam się osiągnąć. Z drugiej strony – istnieją pewne ograniczenia, o których za chwilę opowiem. Zacznijmy jednak od tego, co udało nam się stworzyć i dlaczego jest to jedna z możliwych dróg rozwoju marketingu.\nO co chodzi z tą pracą inżynierską? Mówiąc krótko – wraz z OLX postawiliśmy stworzyć narzędzie, które pozwala firmom na szybkie i łatwe generowanie banerów reklamowych, bez potrzeby zatrudniania sztabu grafików. Wszystko dzięki wykorzystaniu algorytmów sztucznej inteligencji, które automatyzują proces projektowania.\nPomyślcie tylko – ile razy widzieliście powtarzalne, nudne reklamy, które przemijały bez echa? Albo ile firm rezygnuje z kampanii reklamowych z powodu braku budżetu na profesjonalnych grafików? Właśnie te problemy chcieliśmy rozwiązać, tworząc platformę do generowania banerów reklamowych.\nJak to działa? Bez wchodzenia w zbyt techniczne szczegóły – system korzysta z rozwiązań generatywnego AI, aby w oparciu o preferencje użytkownika tworzyć unikatowe i estetyczne banery. Użytkownik może wybrać jeden z trzech dostępnych typów banerów, dodać swoje logo, ustalić dominujące kolory, a nawet wygenerować chwytliwy slogan. Cały proces trwa dosłownie kilka minut!\nDlaczego nie mogę zdradzić wszystkiego\u0026hellip; jeszcze No i dochodzimy do najciekawszej (i trochę frustrującej) części. Na tym etapie nie mogę zagłębiać się w szczegóły techniczne i pokazać dokładnie, jak działa cały system. Dlaczego? Ano dlatego, że nie wiadomo jeszcze, co stanie się z prawami autorskimi. Projekt wzbudził zainteresowanie i\u0026hellip; nic więcej narazie nie mogę powiedzieć, bo wolę nie zapeszać.\nCo dalej? Nie jest to więc wpis bardzo szczegółowy, ale w przyszłości postaram się go rozszerzyć o techniczne detale. Chciałbym opowiedzieć o tym, jak udało nam się zintegrować AI z tak pozornie kreatywnym procesem jak projektowanie graficzne. Na razie muszę jednak uzbroić się w cierpliwość i poczekać, jak potoczą się sprawy z potencjalnym przejęciem projektu.\nJedno jest pewne – ta praca inżynierska była dla mnie wyzwaniem i jednocześnie dała przestrzeń do rozwoju i poznania nowych narzędzi. Niezależnie od tego, co przyniesie przyszłość, już teraz jestem dumny z tego, co udało nam się osiągnąć. A jeśli wszystko pójdzie po naszej myśli\u0026hellip; to kto wie, może kiedyś zobaczycie efekty naszej pracy na bannerach OLX?\n","date":"2025-02-24T12:00:00Z","image":"https://blog.huszcza.dev/p/ad-banner-generator/cover_hu5459c0360c2b0cb7a147d2df0eb350ca_697511_120x120_fill_q75_box_smart1.jpg","permalink":"https://blog.huszcza.dev/pl/p/ad-banner-generator/","title":"Praca inżynierska – Projekt tworzony wraz z OLX"},{"content":"Słowem wstępu Projekt został stworzony jako ocena cząstkowa z przedmiotu informatyka w medycynie. Nie licząc hackathonu (swoją drogą, polecam wpis Macieja na temat tego wydarzenia), było to moje pierwsze poważniejsze zetknięcie z bibliotekami takimi jak PyTorch czy OpenCV.\nPonieważ zadanie okazało się dość wymagające, zmusiło mnie to do szerokiego researchu na temat różnych metod przetwarzania obrazów. Sprawdzałem dosłownie wszystko – od najprostszych filtrów po bardziej zaawansowane techniki computer vision. Dzięki temu poznałem podstawowe metody używane w tej dziedzinie, co znacznie poszerzyło moje horyzonty.\nNie będę ukrywał – momentami bywało ciężko, zwłaszcza gdy szumy na obrazach niweczyły godziny pracy nad kodem. Mimo to, wizja wykorzystania technologii do analizy obrazów medycznych była dla mnie ogromną inspiracją i napędzała mnie do działania. Czasami frustrowałem się, gdy coś nie działało zgodnie z oczekiwaniami, ale satysfakcja z działającego rozwiązania zdecydowanie wynagrodziła wszystkie trudy.\nK-Nearest Neighbors (KNN) – Klasyfikacja naczyń krwionośnych Czym jest K-Nearest Neighbors? K-Nearest Neighbors (KNN) to jeden z najprostszych i najbardziej intuicyjnych algorytmów uczenia maszynowego. Jego działanie opiera się na założeniu, że podobne dane są blisko siebie w przestrzeni cech. W skrócie – jeśli chcesz wiedzieć, do jakiej klasy należy nowy punkt, sprawdź, do jakiej klasy należą jego najbliżsi sąsiedzi.\nW przypadku projektu Vessel Extraction KNN został użyty do:\nKlasyfikacji pikseli jako „naczynia krwionośne” lub „tło”, Analizy sąsiedztwa pikseli, co pozwalało na bardziej precyzyjne rozróżnienie naczyń od szumów. Undersampling – Jak poradziłem sobie z niezbalansowanymi danymi? Jakie były wyzwania? Nadmiar danych tła – Obszary bez naczyń krwionośnych (tło) dominowały na obrazach, co powodowało, że model uczył się głównie rozpoznawać tło, a nie naczynia.\nNiedobór danych naczyń krwionośnych – Piksele należące do naczyń krwionośnych stanowiły mniej niż 10% wszystkich danych, co powodowało, że model bardzo szybko przeuczał się.\nJak sobie z tym poradziłem? Postanowiłem zastosować undersampling – czyli celowe ograniczenie liczby danych tła, aby liczba pikseli naczyniowych i tła była bardziej zrównoważona. Brzmi prosto, ale wymagało to kilku przemyślanych kroków:\nWybór próbek tła:\nNie wyrzucałem danych tła losowo, bo mogło to prowadzić do utraty ważnych informacji o kontekście obrazu. Skupiłem się na reprezentatywnych próbkach, czyli takich, które znajdowały się blisko naczyń krwionośnych. Dzięki temu model miał lepszy kontekst do nauki. Redukcja liczby próbek tła:\nOstatecznie zredukowałem liczbę próbek tła o około 70%, co sprawiło, że stosunek danych naczyniowych do tła był bardziej zrównoważony. Ważne było, żeby nie przesadzić – musiałem zostawić wystarczająco dużo tła, żeby model nie zaczął go mylić z naczyniami. Zachowanie lokalnych wzorców:\nDzięki zastosowaniu wycinków 3x3 pikseli model nie stracił lokalnych wzorców, co poprawiło dokładność (accuracy). Jak działało KNN w tym projekcie? Ekstrakcja cech:\nKażdy piksel został opisany za pomocą wartości jasności oraz wartości sąsiednich pikseli. Dzięki temu model miał więcej informacji o lokalnym kontekście. Wybór liczby sąsiadów (k):\nNajważniejszym parametrem w KNN jest k – liczba najbliższych sąsiadów, których klasa będzie brana pod uwagę przy klasyfikacji. W projekcie przeprowadziłem walidację krzyżową, żeby znaleźć optymalną wartość k. Najlepsze wyniki osiągnąłem dla k = 5, co zapewniło równowagę między dokładnością a czułością. Klasyfikacja:\nDla każdego pikselu sprawdzane było, jakie klasy mają jego k najbliżsi sąsiedzi. Piksel zostawał przypisany do tej klasy, która miała najwięcej reprezentantów w sąsiedztwie. Wyniki i efekty Dokładność (accuracy): 89% – całkiem nieźle jak na prosty model bez głębokiego uczenia! Czułość (recall): 85% – dobrze wykrywał naczynia krwionośne, ale czasami mylił je z cienkimi liniami tła. Precyzja (precision): 91% – model dość skutecznie unikał fałszywych alarmów (błędnego oznaczania tła jako naczyń). Wiem, że efekt na pierwszy rzut oka nie powala i można się zastanawiać, jakim cudem udało się uzyskać tak dobre \u0026ldquo;cyferki\u0026rdquo; (czyli dokładność). Ale tu właśnie tkwi mały szkopuł, czyli narzucone wymaganie.\nChciałbym zaznaczyć, że do uczenia modelu wykorzystałem wycinki o rozmiarze 3x3 pikseli, ponieważ na tak małych fragmentach model łatwiej wykrywa lokalne wzorce charakterystyczne dla naczyń krwionośnych.\nCałkowity rozmiar obrazu to 512x512 pikseli, więc jeśli klasyfikator stwierdził, że dany wycinek to naczynie krwionośne, to te 9 pikseli (3x3) w rezultacie zostało w całości wypełnione na biało.\nZalety i wady KNN Zalety:\nProstota implementacji – KNN jest bardzo intuicyjny i łatwy do zrozumienia. Brak trenowania modelu – Cała „nauka” odbywa się w momencie klasyfikacji. Wady:\nWolne działanie dla dużych zbiorów danych – Każda klasyfikacja wymaga obliczenia odległości do wszystkich punktów treningowych. Czułość na nieistotne cechy – Wszystkie cechy mają taką samą wagę, co czasami może prowadzić do błędnych klasyfikacji. FastAi – Głębokie uczenie dla klasyfikacji naczyń krwionośnych Dlaczego FastAi? Po przetestowaniu klasycznego KNN postanowiłem pójść krok dalej i zastosować FastAi – framework oparty na PyTorch, który jest świetny do szybkiego prototypowania modeli głębokiego uczenia. FastAi oferuje:\nŁatwą integrację z gotowymi modelami (np. ResNet), Prosty w użyciu interfejs API, który przyspiesza przygotowanie danych i trenowanie modeli, Zaawansowane techniki optymalizacji (np. learning rate finder). Jak działało FastAi w projekcie? Przygotowanie danych:\nObrazy zostały podzielone na mniejsze fragmenty (patches), aby modele mogły łatwiej nauczyć się wzorców. Użyłem FastAi DataBlock API do zarządzania danymi i ich etykietowania. Klasyfikacja odbywała się na dwóch poziomach: Naczynia krwionośne, Tło. Model głębokiego uczenia:\nWybrałem ResNet34 – lekki, ale wystarczająco mocny model do rozpoznawania naczyń. Skorzystałem z transfer learningu, żeby model uczył się na podstawie gotowych wag (ImageNet), co przyspieszyło trening. Fine-tuning na ostatnich warstwach pozwolił dostosować model do specyficznego zadania rozpoznawania naczyń krwionośnych. Trenowanie i optymalizacja:\nTrenowałem model przy użyciu learning rate finder FastAi, co pomogło dobrać optymalny współczynnik uczenia. Augmentacja danych (rotacje, odbicia, zmiana jasności) pomogła zwiększyć różnorodność danych treningowych i poprawiła ogólną wydajność modelu. Wyniki i efekty Dokładność (accuracy): 92% – co jest wyraźną poprawą w porównaniu do KNN. Czułość (recall): 90% – model świetnie radził sobie z rozpoznawaniem naczyń nawet w trudniejszych przypadkach. Precyzja (precision): 94% – minimalna liczba fałszywych alarmów i bardzo precyzyjne wykrywanie naczyń. Zalety i wady FastAi Zalety:\nWysoka dokładność – Model głębokiego uczenia znacznie przewyższał KNN pod względem dokładności. Możliwość fine-tuningu – Dzięki transfer learningowi i fine-tuningowi model szybko dostosował się do specyfiki obrazów medycznych. Proste API – FastAi pozwala na szybkie eksperymentowanie z różnymi modelami i parametrami. Wady:\nWysokie wymagania sprzętowe – Modele głębokiego uczenia wymagają mocnego GPU do efektywnego treningu, sam korzsytałem z Kaggle do fine tuningu. Pierwszy krok w świecie uczenia maszynowego Muszę przyznać, że to mój pierwszy indywidualny projekt związany z uczeniem maszynowym i computer vision. Poznałem w praktyce działanie KNN oraz FastAi, zrozumiałem, jak potężne są techniki przetwarzania obrazu i jak radzić sobie z problemem niezbalansowanych danych za pomocą undersamplingu. Satysfakcja z wyniku przetwarzania była ogromna, jednakże sam projekt uświadomił mi również, że jestem dopiero na początku drogi.\nPomimo wielu błędów i frustracji, poczułem prawdziwą zajawkę na uczenie maszynowe. Kombinowanie z danymi, testowanie modeli i optymalizacja algorytmów okazały się czymś, co naprawdę mnie kręci. Wiem, że przede mną jeszcze mnóstwo nauki – zaawansowane architektury sieci neuronowych, optymalizacja hiperparametrów, wydajność na GPU – ale jestem na to gotowy.\nJeśli chcesz zobaczyć kod źródłowy albo dowiedzieć się więcej, zajrzyj do repozytorium na GitHubie. Może ten projekt zainspiruje Cię do rozpoczęcia własnej przygody z AI?\n","date":"2025-02-23T18:00:00Z","image":"https://blog.huszcza.dev/p/vessel-extraction/cover_hu5459c0360c2b0cb7a147d2df0eb350ca_4078906_120x120_fill_q75_box_smart1.jpg","permalink":"https://blog.huszcza.dev/pl/p/vessel-extraction/","title":"Vessel Extraction – Przetwarzanie Obrazów z Wykorzystaniem Pythona i OpenCV"},{"content":"Skąd wziął się pomysł? Pomysł na SpeedDatingMatcher zrodził się dzięki mojej siostrze Róży, która studiuje na Uniwersytecie Medycznym w Białymstoku. Co więcej, nie tylko studiuje – prowadzi również uczelniane pismo – Młody Medyk. Od dwóch lat jej organizacja studencka organizuje eventy speed datingowe. No i tutaj pojawił się problem – według relacji Róży nic nie okazuje się bardziej żmudne, okropne i jest bólem nie do zniesienia jak sprawdzenie preferencji kontaktu uczestników oraz wysyłanie do nich maili z informacją zwrotną. Jeśli dobrze pamiętam to podczas wypowiadania tych słów, uroniła nawet nie jedną, a dwie łzy, ale takie krokodyle nawyki nabyła już w dzieciństwie. Mimo wszystko jako brat-deweloper postanowiłem jej pomóc i wziąłem sprawy w swoje ręce.\nCzym jest SpeedDatingMatcher? SpeedDatingMatcher to system do zarządzania wydarzeniami speed datingowymi. Obsługuje rejestrację uczestników, dopasowywanie preferencji (kto chce się skontaktować z kim) oraz wysyłanie maili z kontaktami dzięki integracji z Brevo. Pierwsza wersja została wdrożona na Microsoft Azure, ale nie będę ukrywał – brak doświadczenia z SSR dał mi w kość. Skończyło się to większą frustracją, niż się spodziewałem, ale ostatecznie udało mi się aplikację uruchomić.\nW tegorocznej edycji (2025) postanowiłem podejść do tematu bardziej rozsądnie – nie tylko ze względu na moje doświadczenie z Azure, a również to finansowe, bo pakiet edukacyjnych stu dolarów całkowicie wykorzystałem na poprzednią edycję. Finalnie postawiłem na VPS z wykorzystaniem Dockera i nginx. Miałem też do dyspozycji serwer AWS EC2 Free Tier, ale wiedziałem, że wkrótce będę potrzebował serwera do tego bloga, więc od razu zdecydowałem się na VPS.\nJak to działa? Głównym celem aplikacji nie jest tylko wysyłanie maili, ale automatyczne dopasowywanie uczestników wydarzenia. Jak to działa? Jeśli uczestnik z numerem 3 chce skontaktować się z numerem 2 oraz 1, muszę sprawdzić, czy zarówno numer 2, jak i 1 również chcą kontaktu z numerem 3. Dopiero wtedy, gdy jest wzajemna chęć kontaktu, wysyłamy maila. Sytuację obrazuje poniższa grafika:\nAplikacja oferuje m.in.:\nZarządzanie wydarzeniami randkowymi – Kompleksowe zarządzanie uczestnikami i spotkaniami. Walidacja emaili – Sprawdzanie poprawności podanych adresów email. Integracja z Brevo – Automatyczne powiadomienia i przypomnienia dla uczestników. Dzięki wykorzystaniu Django, mogę łatwo zarządzać użytkownikami i ich danymi.\nStack technologiczny Django – Backend i zarządzanie bazą danych. Next.js – Szybki frontend z renderowaniem po stronie serwera. Brevo – Integracja do wysyłania e-maili. BeautifulSoup4 – Dynamiczna modyfikacja szablonów HTML w mailach. Microsoft Azure – Hosting aplikacji w chmurze (pierwsza wersja). Docker – Konteneryzacja aplikacji. Nginx – Reverse proxy na serwerze VPS. Czego się nauczyłem i co dalej? Szczerze mówiąc, był to pierwszy poważniejszy projekt, który zrealizowałem poza pracą. Gdybym powiedział, że planowanie architektury, dobór technologii oraz pisanie kodu nie sprawiło mi ogromnej frajdy, to bym skłamał. Ten projekt naprawdę rozbudził moją deweloperską pasję.\nMogłem przetestować swoje pomysły, a przy okazji nauczyć się dużo o SSR, Django i Azure. Nie było łatwo, ale każde wyzwanie było nową lekcją.\nProjekt współtworzyłem z Maćkiem, co pozwoliło mi zdobyć cenne doświadczenie w zarządzaniu zadaniami, współpracy zespołowej oraz Code Review.\nChcesz dowiedzieć się więcej? Sprawdź repozytorium na GitHubie.\n","date":"2025-02-23T17:00:00Z","image":"https://blog.huszcza.dev/p/speeddating-matcher/cover_hucb6842c766b35d342dbb95cacf542a9b_2241605_120x120_fill_box_smart1_3.png","permalink":"https://blog.huszcza.dev/pl/p/speeddating-matcher/","title":"SpeedDatingMatcher – Event Management z Django i Next.js"}]