Jak pracować z programującymi nieprogramistami

Jacek Bzdak

Magalena Wójcik

Kim jesteśmy?

Jacek:

Jestem jedyną osobą identyfikującą się jako programista w zespole Data Scientistek/ów, więc chcąc nie chcąc (głównie chcąc) odpowiadam za wszystkie rzeczy związane z jakością projektu i wdrożeniami. Wcześniej pracowałem w fizyce jądrowej z naukowcami i elektronikami.

 

Przez parę lat uczyłem studentów fizyki rozsądnych praktyk programistycznych.

Kim jesteśmy?

Magda:

Przez lata kodowałam rzeczy webowe, ale odkrylam moje powołanie, kiedy zobaczyłam przedmiot "Narzędzia sztucznej inteligencji". Od tego czasu robię głównie Data Science, co znaczy, że skupiam się na zjawiskach i prawidłowościach w danych, a mniej na jakości kodu.

 

Jacek umiarkowanie mnie lubi ze względu na tę jakość.

Po co ta prezentacja?

Prezentację kierujemy do programistów i tech leadów, którzy nieuchronnie spotkają się w pracy z Data Scientistami (albo innymi specjalistami domenowymi). Mamy nadzieję ułatwić zorganizowanie takiej współpracy i uniknięcie konfliktów.

Disclaimer

  1. Podane niżej pomysły sprawdzają się w "młodym" zespole w consultingowym startupie, który realizuje dużo małych projektów i ciągle rekrutuje;
  2. Relatywnie rzadko robimy projekty Big Data, większość z nich da się zrobić na jednej maszynie (nawet jeśli jest to “duża” instancja);
  3. Jeśli masz terabajty danych i od lat tworzysz produkt możliwe, że rozwiązania te mogą nie być optymalne;

Plan prezentacji

  1. Skąd podział na "programistów" i "nieprogramistów" i dlaczego jest ważny?
  2. Kim jest Data Scientistka?
  3. Jak wyglądają projekty z zakresu DS?
  4. Problemy (i ich rozwiązania) na linii Data Scientist - programista
  5. Doświadczenia z pracą z elektronikami.
  6. Konkulzja: Jak pracować z programującymi nieprogramistami.

Programista vs nieprogramista

Przyjęliśmy rozróżnienie:

  • Programista to osoba, której głównym przedmiotem zainteresowania jest pisanie i dbanie o kod,
  • Nieprogramista co prawda pisze kod, ale jest głównie zainteresowany innymi tematami, np. wyniki modelu Machine Learningowego albo działanie urządzenia elektronicznego.

 

Bad programmers worry about the code. Good programmers worry about data structures and their relationships.

- Linus Torvalds

Data Scientists worry about subject matter,
spurious correlations and data leakages.

- Magdalena Wójcik

Dlaczego ten podział jest przydatny

Kim jest Data Scientistka?

Data Scientistka to taka programistka, która jest też statystyczką i analityczką w jednym.

 

Do jej zadań należy modelowanie problemów, projektowanie ekperymentów, implementacja i interpretacja wyników.

Przebieg projektu Data Science

  1. Rozmowa z klientem, zebranie wymagań i potrzeb, określenie jaki cel biznesowy ma osiągnąć model Machine Learningowy (ML),
  2. Analiza i czyszczenie danych, co może zająć nawet 90% czasu całego projektu. W ramach tego kroku powstają tzw. Transformery czyli skrypty przygotowujące dane do postaci odpowiedniej dla modelu ML,
  3. Trenowanie modelu ML (dopasowanie modelu do danych, wynikiem jest wytrenowany model),
  4. Interpretacja wyników modelu ML,
  5. Przekazanie wyników do klienta. Wynik może być gotowym produktem, mikroserwisem Data Science, jak i raportem/prezentacją.

Wyniki projektu Data Science

Dla programisty najważniejszy jest działający kod.

  • Kiedy poprosisz programistę o wyniki pracy dostaniesz PR z kodem.

Dla Data Scientistki/ty najważniejsze są dane i wyniki działania modelu, który może produkować je parę dni.

  • DS może czasem (zupełnie naturalnie i intuicyjnie) wysłać CSV.

Sztandarowe problemy
w projektach Data Science
 

i jakie znaleźliśmy rozwiązania

API - zrozumiałe dla obu stron

Problem:

Bezproblemowa współpraca między częścią "data-science" a "programistyczną" (api, webaplikacja). 

Rozwiązanie:

Ustalone API zrozumiałe dla wszystkich, przejrzane przez wszystkich i wszyscy uważają, że jest dobre i zdatne do użytku.

Praktyka:

Po pierwszej implementacji trzeba je zmienić, i to jest OK. 

API - zrozumiałe dla obu stron

@dataclasses.dataclass(frozen=True)
class DetectorResultInstance:
    """Bazowa klasa na wiersz wyniku działania detektora."""
    product_id: int
    reported_value: float
    correct_value: typing.Optional[float]
    # ... 15 innych kolumn (potrzeby biznesowe)


class IDetector:
    """Międzymordzie dla szablonów detektorów."""

    @abc.abstractmethod
    def execute(
        self, detector_input: DetectorInput, context: DetectorContext
    ) -> typing.Iterator[DetectorResultInstance]:
        """
        Uruchamia detektor i zwraca jego wyniki. Operacja ta może trwać
        długo i jest wykonywana asynchronicznie w kolejce zadań.
        """
        raise NotImplementedError

Przeglądy kodu

Problem:

Przeglądy kodu mogą być uważane przez Data Scientistów/ki za niepotrzebne (o kod się nie liczy, liczą się dane) i być stresujące/irytujące.

 

Symptomy:

Czas przez jaki wiszą otwarte PR generuje problemy w projekcie (tj. nagminnie ludzie zaczynają branchować się od swoich PR)

Przeglądy kodu

Rozwiązanie:

Dbamy, żeby przeglądy kodu nie były okazją do gate keepingu, raczej do poprawy firmowych praktyk.

Nasza procedura przeglądania kodu:

  • Znajdź kilka rzeczy, których poprawa zmieni najwięcej,
  • Przekonaj osobę zgłaszającą kod do tego, że proponowane poprawki pomogą, albo: daj się przekonać, że nie ma sensu tego robić, bo nie będzie istotnej zmiany,
  • Potraktujcie poprawę kodu jako wspólną odpowiedzialność.

"Silo mentality"

Problem:

Sytuacja, kiedy dwa zespoły (u nas Data Science i Development) pracują zupełnie niezależnie, nie dzielą się informacjami i współpracują wyłącznie na podstawie formalnych procedur.

Rozwiązanie:

Wymuszamy komunikację i naukę przez wspólną pracę nad projektami, zawsze z udziałem programistów i DS.

Wdrożenia

Problem:

Wdrożenie aplikacji wykorzystującej model ML dla klienta zwykle leży daleko poza kompetencjami Data Scientista.

Razem z modelem często trzeba wdrożyć też wiele bibliotek w konkretnych wersjach, od których zależą modele ML. Wytrenowane modele są z reguły plikami w nieprzezroczystym formacie i często nie są łatwo portowalne między wersjami biblioteki.

 

Wdrożenia

Rozwiązanie:

Wytrenowane modele i zależności pakujemy do dockera, to gwarantuje że wersje się nie rozjadą. 


Do zarządzania zależnościami używamy pip-tools.

Pip-tools

$ cat requirements.in
Flask


$ pip-compile requirements.in

$ cat requirements.txt 
click==6.7                # via flask
flask==0.12.2
itsdangerous==0.24        # via flask
jinja2==2.9.6             # via flask
markupsafe==1.0           # via jinja2
werkzeug==0.12.2          # via flask

Jupyter notebook

Problem:

Do analiz i eksperymentów Data Scientiści korzystają z notebooków, które wewnętrznie są plikami JSON z zserializowanymi wykresami i wynikami obliczeń.

 

Nie nadają się do wdrożeń, przechowywania w repo, diffowania.

Code review

Jupyter notebook

Rozwiązanie:

Korzystamy z biblioteki jupytext, która równolegle z zapisem pliku ipynb zapisuje też py.

W repo przechowujemy tylko pliki py, chyba, że mamy w notatniku ważne wyniki obliczeń.

Code review

Kod eksperymentalny

Problem:

W projektach Data Science powstaje sporo kodu eksperymentalnego.

Przed startem projektu nie wiadomo:

  • Co dokładnie klient ma w danych,
  • Co wpływa na wynik, na co zwracać uwagę,
  • Jaki model będzie najlepszy do tego problemu.

Pierwsza faza projektu zaczyna się od EDA (Eksploracyjna Analiza Danych).

Choć często prototypy nie ograniczają się od EDA.

 

Kod eksperymentalny

Rozwiązanie:

  • Większość prototypowego kodu trafia do repozytorium,
  • Wiemy że ma on niższy standard,
  • Generalnie prototypy trzymamy w notebookach jupytera,
  • Kod pythona (pliki *.py) zawierają kod produkcyjny.

 

Testowanie kodu

Problem:

Programista chce przetestować 100% projektu. Data Scientist wie, że to nie ma sensu. Przykładowo, modele najczęściej przychodzą zaimplementowane w bibliotekach i ekstremalnie rzadko są źródłem błędów.

 

Rozwiązanie:

Warto testować:

  • Proces przetwarzania danych (Transformery),
  • Warto zrobić "smoke testy" całego projektu.

 

Praca na instancjach

Problem:

Modele i dane często zajmują dziesiątki GB i nie mieszczą się na lokalnych maszynach. Data Scientiści mogą jednocześnie nie czuć się na tyle komfortowo z Linuxem, żeby pracować wygodnie na zdalnej instancji.

 

Rozwiązanie:

  1. Nie pracowanie na instancjach. Wygenerowanie małego datasetu, który mieści się w RAMie lokalnie.
  2. Zapakowanie pojektu do dockera i stawianie środowiska przez docker-compose up.

Jak pracować z elektronikami

Elektronicy myślą głównie tym jakie urządzenie wyprodukują, ile będzie kosztować w produkcji i jak spełnić wszystkie wymogi stawiane urządzeniu.
- Daniel Kowalski

Protokół komunikacji to API

  • Urządzenia mogą mieć specyficzne wymogi; 
    • Czasem to maksymalny rozmiar ramki;
    • Czasem to maksymalny pobór mocy; 
    • Czasem maksymalny rozmiar kodu wykonywalnego;
    • ...
    • Trzeba słuchać! 
  • Warto myśleć o rozszerzalności protokołu, ale ważne jest żeby działał dobrze tu i teraz;
  • Koniecznie trzeba wersjonować protokół; 
  • Trudno jest zrobić go dobrze za pierwszym razem;

Przykład problematycznego protokołu (w projekcie)

  • Firma wybrała MODBUS TCP do kontaktu z czujnikami;
  • Modbus jest bardzo przyjemnym i fajnym protokołem; 
  • Natomiast zakłada istnienie mastera który odpytuje urządzenia;  
  • Z wyboru protokołu wynika że urządzenie działające na GSM miało otwarte gniazdo TCP do serwera non stop;
  • Urządzenie działało na baterii;

Wszystko co możliwe należy zaimplementować poza urządzeniem

  • Wszystko co się da należy zaimplementować po stronie "programistycznej" (web-serwis, kontroler);
  • Update centralnego systemu jest tańszy i łatwiejszy niż update firmware sprzętu zakopanego pod ziemią;
    • Tworzenie tej części też jest IMO tańsze; 
  • Warto pamiętać że nie wszystko da się tak wyeksportować;

Jak pracować z programującymi nie programistami

  1. Należy trzy razy posłuchać, a dopiero później zacząć działać; 
  2. Za nieintuicyjnymi rozwiązaniami z reguły stoją dobre argumenty;
  3. Patrz punkt 1;
  4. Przy odrobinie dobrej woli z obu stron można spotkać się po środku;

Q & A

Jak pracować

By Magdalena Wójcik

Jak pracować

PyCon PL 2019

  • 1,709