Co może pójść nie tak z Data Science? Zbieranie danych

Co może pójść nie tak z Data Science? Zbieranie danych
Dziś istnieje mnóstwo kursów z zakresu Data Science i wiadomo, że najwięcej pieniędzy w Data Science można zarobić sprzedając kursy z tego zakresu (po co kopać, skoro można sprzedawać łopaty?). Głównym minusem tych kursów jest to, że nie mają one nic wspólnego z prawdziwą pracą: nikt nie dostarczy ci czystych, przetworzonych danych w odpowiednim formacie. Kiedy kończysz kursy i zaczynasz rozwiązywać prawdziwe zadania — pojawia się wiele niuansów.

Dlatego zaczynamy serię notatek "Co może pójść nie tak z Data Science", opartych na prawdziwych wydarzeniach, które miały miejsce z moim udziałem, moich przyjaciół i kolegów. Będziemy analizować na prawdziwych przykładach typowe problemy z Data Science: jak to tak naprawdę wygląda. Dziś zaczniemy od zadania zbierania danych.

I pierwsze, o co potykają się ludzie, zaczynając pracę z rzeczywistymi danymi — to własnie zbieranie tych odpowiednich materiałów. Kluczowa myśl tego artykułu:

Systematycznie niedoceniamy czasu, zasobów i wysiłków na zbieranie, oczyszczanie i przygotowywanie danych.

A przede wszystkim omówimy, co zrobić, aby tego uniknąć.

Według różnych szacunków, oczyszczanie, transformacja, przetwarzanie danych, inżynieria cech itd. zajmują 80-90% czasu, podczas gdy analiza 10-20%, podczas gdy praktycznie cały materiał szkoleniowy koncentruje się wyłącznie na analizie.

Przeanalizujmy prostą sytuację analityczną w trzech wariantach i zobaczmy, jakie mogą być "okoliczności łagodzące".

Dla przykładu znów rozważymy podobne wariacje zadania zbierania danych i porównania społeczności dla:

  1. Dwóch subreddits Reddit
  2. Dwóch sekcji Habr
  3. Dwóch grup w Odnoklassniki

Hipotetyczne podejście w teorii

Otwórz stronę i przeczytaj przykłady, jeśli wszystko jest jasne, zaplanuj kilka godzin na czytanie, kilka godzin na kodowanie według przykładów i debugowanie. Dodaj kilka godzin na zbieranie. Dolicz kilka godzin zapasu (pomnóż przez dwa i dodaj N godzin).

Kluczowym punktem jest to, że ocena czasowa opiera się na przypuszczeniach i domysłach dotyczących tego, ile to zajmie czasu.

Rozpocząć analizę czasu należy od oszacowania następujących parametrów dla hipotetycznego zadania opisanego powyżej:

  • Jaki jest rozmiar danych i ile w rzeczywistości trzeba zebrać (*patrz poniżej*).
  • Ile czasu zajmuje zebranie jednego wpisu i ile trzeba czekać, zanim można zebrać drugi.
  • Zaprojektuj kod, który zachowuje stan i rozpoczyna restart, gdy (a nie jeśli) wszystko zawiedzie.
  • Rozstrzygnij, czy potrzebujemy autoryzacji i zaplanuj czas na uzyskanie dostępu przez API.
  • Zdeklaruj liczbę błędów jako funkcję złożoności danych — oceniaj w oparciu o konkretne zadanie: struktura, ile przekształceń, co i jak ekstraktujemy.
  • Zaplanuj błędy sieciowe i problemy związane z nietypowym zachowaniem projektu.
  • Oceń, czy potrzebne funkcje są w dokumentacji, a jeśli nie, to jak i ile potrzeba na obejście problemu.

Najważniejsze jest to, że aby ocenić czas — musisz faktycznie poświęcić czas i wysiłek na 'wywiad bojowy' — tylko wtedy twoje planowanie będzie adekwatne. Dlatego, niezależnie od tego, jak bardzo będą cię naciskać, by powiedzieć 'ile czasu potrzeba na zebranie danych' — daj sobie czas na wstępną analizę i uzasadniaj, jak bardzo czas będzie się różnić w zależności od rzeczywistych parametrów zadania.

Teraz zaprezentujemy konkretne przykłady, w których te parametry będą się zmieniać.

Kluczowa kwestia: ocena opiera się na analizie kluczowych czynników wpływających na zakres i złożoność pracy.

Ocena oparta na domysłach — to dobre podejście, gdy funkcjonalne elementy są na tyle małe, że nie ma zbyt wielu czynników, które mogą w znaczący sposób wpłynąć na strukturę zadania. Ale w przypadku wielu zadań z zakresu Data Science takich czynników staje się niezwykle wiele i takie podejście staje się nieadekwatne.

Porównanie społeczności Reddit

Zacznijmy od najprostszego przypadku (jak się później okaże). Tak naprawdę, jeśli mamy być całkowicie szczery, mamy przed sobą praktycznie idealny przypadek, sprawdźmy naszą listę kontrolną złożoności:

  • Mamy schludne, jasne i udokumentowane API.
  • Bardzo prosto i co najważniejsze, token można automatycznie uzyskać.
  • Tak python wrapper — z mnóstwem przykładów.
  • Społeczność zajmująca się analizą i zbieraniem danych na Reddit (aż do filmów na YouTube wyjaśniających, jak używać python wrappera) oto na przykład.
  • Potrzebne nam metody prawdopodobnie istnieją w API. Co więcej, kod wygląda kompaktowo i czyściutko, poniżej przykład funkcji zbierającej komentarze do posta.

def get_comments(submission_id):
    reddit = Reddit(check_for_updates=False, user_agent=AGENT)
    submission = reddit.submission(id=submission_id)
    more_comments = submission.comments.replace_more()
    if more_comments:
        skipped_comments = sum(x.count for x in more_comments)
        logger.debug('Skipped %d MoreComments (%d comments)',
                     len(more_comments), skipped_comments)
    return submission.comments.list()

Zaczerpnięte z tego zbiór wygodnych narzędzi do obróbki.

Pomimo że mamy tutaj najlepszy możliwy przypadek, należy uwzględnić szereg ważnych czynników z życia codziennego:

  • Limity API — jesteśmy zmuszeni pobierać dane w partiach (czekać pomiędzy zapytaniami itd.).
  • Czas zbierania — aby przeprowadzić pełną analizę i porównanie, trzeba przewidzieć znaczny czas na to, by robot mógł przejść przez subreddita.
  • Bot musi działać na serwerze — nie możesz po prostu uruchomić go na laptopie, włożyć do plecaka i ruszyć w sprawy. Dlatego wszystko uruchomiłem na VPS. Z kodem promocyjnym habrahabr10 możesz zaoszczędzić jeszcze 10% kosztów.
  • Fizyczna niedostępność niektórych danych (są widoczne dla administratorów lub zbyt trudno je zbierać) — należy to uwzględnić, nie wszystkie dane da się zrealizować w rozsądnym czasie.
  • Błędy sieciowe: praca z siecią to ból.
  • To żywe, prawdziwe dane — nigdy nie są czyste.

Oczywiście, należy uwzględnić w rozwoju podane niuanse. Konkretne godziny/dni zależą od doświadczenia w programowaniu lub pracy nad podobnymi zadaniami, niemniej jednak widzimy, że zadanie to jest wyłącznie inżynieryjne i nie wymaga dodatkowych działań do rozwiązania — wszystko można dobrze oszacować, opisać i zrealizować.

Porównanie działów Habra

Przechodzimy do bardziej interesującego i nietypowego przypadku porównania strumieni i/lub działów Habra.

Sprawdzimy naszą listę kontrolną trudności — tutaj, aby zrozumieć każdy punkt, będzie trzeba nieco pogmerać w same zadanie i poeksperymentować.

  • Na początku myślisz, że jest API, ale go nie ma. Tak, tak, Habr ma API, ale jest ono niedostępne dla użytkowników (a może w ogóle nie działa).
  • Potem po prostu zaczynasz parsować html — „import requests”, co może pójść nie tak?
  • A jak w ogóle parsować? Najprostszym i najczęściej używanym podejściem jest iteracja po ID, co należy zauważyć, że nie jest najwydajniejsze i trzeba będzie poradzić sobie z różnymi przypadkami — dla przykładu gęstość rzeczywistych ID wśród wszystkich istniejących.

    Co może pójść nie tak z Data Science? Zbieranie danych
    Zaczerpnięte z tego artykułem.

  • Surowe dane owinięte w HTML w sieci to ból. Na przykład, chcesz zebrać i zapisać oceny artykułu: wyexploatowałeś score z HTML i postanowiłeś zapisać go jako liczbę do dalszego przetwarzania: 

    1) int(score) generuje błąd: ponieważ na Habrze minus, jak na przykład w wierszu „–5” — to jest krótkie myślnik, a nie znak minus (niespodzianka, prawda?), więc w pewnym momencie musiałem uruchomić parser z takim strasznym poprawką.

    try:
          score_txt = post.find(class_="score").text.replace(u"–","-").replace(u"+","+")
          score = int(score_txt)
          if check_date(date):
            post_score += score
    

    Daty, plusy i minusy mogą w ogóle nie występować (jak widzimy wyżej w funkcji check_date i takie przypadki miały miejsce).

    2) Nieescape'owane znaki specjalne — one się pojawią, trzeba być na to gotowym.

    3) Struktura zmienia się w zależności od typu posta.

    4) Stare posty mogą mieć **dziwną strukturę**.

  • W zasadzie obróbka błędów i tego, co może się zdarzyć lub nie, będzie musiała być obsługiwana, a nie można z całą pewnością przewidzieć, co pójdzie nie tak i jak może być inna struktura oraz co gdzie odpadnie — trzeba po prostu próbować i uwzględniać błędy, które zgłasza parser.
  • Potem zdajesz sobie sprawę, że trzeba parsować w kilku wątkach, bo parsowanie w jednym może zająć 30+ godzin (to czysto czas realizacji już działającego jednowątkowego parsera, który śpi i nie wpada w żadne bany). W tego artykułach, doprowadziło to w pewnym momencie do podobnego schematu:

Co może pójść nie tak z Data Science? Zbieranie danych

Podsumowując checklistę złożoności:

  • Praca z siecią i parsowaniem HTML z iteracją i перебором по ID.
  • Dokumenty o niejednorodnej strukturze.
  • Wiele miejsc, gdzie kod może łatwo upaść.
  • Trzeba pisać || kod.
  • Brak potrzebnej dokumentacji, przykładów kodu i/lub społeczności.

Szacunkowy czas na to zadanie będzie od 3 do 5 razy wyższy niż dla zbierania danych z Reddita.

Porównanie grup Odnoklassników

Przechodzimy do najciekawszego przypadku technicznego opisanego. Dla mnie był interesujący właśnie tym, że na pierwszy rzut oka wydaje się dość trywialny, ale taki nie jest — gdy tylko jak go dotkniesz patyczkiem.

Zacznijmy od naszej checklisty złożoności i zauważmy, że wiele z nich okaże się znacznie trudniejszych, niż wydaje się na początku:

  • API istnieje, ale prawie całkowicie brakuje potrzebnych funkcji.
  • Do niektórych funkcji trzeba prosić o dostęp mailem, to znaczy, że przyznanie dostępu nie jest natychmiastowe.
  • Jest fatalnie udokumentowany (zaczynając od tego, że wszechobecnie mieszają się rosyjskie i angielskie terminy, co jest całkowicie niespójne — czasami musisz po prostu zgadywać, czego od ciebie oczekują) i, co więcej, nie nadaje się projektowo do pozyskiwania danych, na przykład, potrzebna nam funkcja.
  • Wymaga sesji w dokumentacji, a w rzeczywistości jej nie używa — i nie ma żadnego sposobu, by zrozumieć wszystkie niuanse trybów API, poza nawigowaniem i nadzieją, że coś zadziała.
  • Brakuje przykładów i społeczności, jedynym punktem odniesienia w zbieraniu informacji jest mały wrapper w Pythonie (bez dużej liczby przykładów użycia).
  • Najbardziej funkcjonalna opcja wydaje się być Selenium, ponieważ wiele potrzebnych danych jest zamkniętych.
    1) To znaczy, że autoryzacja odbywa się przez fikcyjnego użytkownika (i rejestrację ręcznie).

    2) Jednakże z Selenium nie ma gwarancji poprawnej i powtarzalnej pracy (przynajmniej w przypadku ok.ru na pewno).

    3) Strona Ok.ru zawiera błędy JavaScript i czasami zachowuje się dziwnie i niespójnie.

    4) Należy zająć się paginacją, ładowaniem elementów itd…

    5) Błędy API, które zwraca wrapper, będą musiały być pokonywane w sposób prowizoryczny, na przykład tak (fragment eksperymentalnego kodu):

    def get_comments(args, context, discussions):
        pause = 1
        if args.extract_comments:
            all_comments = set()
    #ma to sens, aby śledzić już przetworzone dyskusje
            for discussion in tqdm(discussions): 
                try:
                    comments = get_comments_from_discussion_via_api(context, discussion)
                except odnoklassniki.api.OdnoklassnikiError as e:
                    if "NOT_FOUND" in str(e):
                        comments = set()
                    else:
                        print(e)
                        bp()
                        pass
                all_comments |= comments
                time.sleep(pause)
            return all_comments
    

    Mój ulubiony błąd to:

    OdnoklassnikiError("Error(code: 'None', description: 'HTTP error', method: 'discussions.getComments', params: …)")

    6) Ostatecznie opcja Selenium + API wydaje się być najbardziej rozsądnym wyborem.

  • Konserwacja stanu i ponowne uruchomienie systemu są niezbędne, przetwarzanie wielu błędów, w tym niespójnego zachowania strony — a te błędy są dość trudne do wyobrażenia (jeśli nie piszesz zawodowo parserów, oczywiście).

Szacunkowy czas realizacji zadania będzie 3-5 razy wyższy niż w przypadku zbierania danych z Habr. Mimo że w przypadku Habr stosujemy prosty sposób z parsowaniem HTML, w przypadku OK możemy w krytycznych miejscach pracować z API.

Wnioski

Choć może się wydawać, że na miejscu wymagana jest ocena czasów (planowanie jest dziś obowiązkowe!), ocena czasu realizacji rozbudowanego modułu pipeline'u przetwarzania danych prawie nigdy nie jest możliwa do przeprowadzenia nawet w sposób rzetelny bez analizy parametrów zadania.

Mówiąc nieco bardziej filozoficznie, strategie oceny w agile dobrze nadają się do zadań inżynieryjnych, jednak z zadaniami bardziej eksperymentalnymi i w pewnym sensie 'artystycznymi' oraz badawczymi, czyli mniej przewidywalnymi, pojawiają się trudności, jak w przykładach omówionych tutaj.

Oczywiście, zbieranie danych jest tylko wyraźnym przykładem — zazwyczaj to zadanie wydaje się niezwykle proste i technicznie nieskomplikowane, ale to właśnie w szczegółach często tkwi diabeł. I w tej kwestii można zaprezentować cały wachlarz potencjalnych problemów, które mogą wystąpić, oraz to, jak bardzo może wydłużyć się praca.

Jeśli pobieżnie przejrzeć cechy zadania bez dodatkowych eksperymentów, Reddit i OK wydają się podobne: obie mają API, wrapper w Pythonie, ale zasadniczo różnica jest ogromna. Jeśli ocenić te parametry, parser Habr wydaje się bardziej skomplikowany niż OK — a w praktyce jest dokładnie odwrotnie i to właśnie można ustalić, przeprowadzając proste eksperymenty dotyczące analizy parametrów zadania.

Z mojego doświadczenia najskuteczniejszym podejściem jest wstępna ocena czasu, który będzie potrzebny na sam wstępny analiz oraz proste pierwsze eksperymenty, czytanie dokumentacji — one pozwolą ci wydać dokładną ocenę dla całej pracy. W terminach popularnej metodologii agile — proszę o utworzenie zgłoszenia pod 'ocenę parametrów zadania', na podstawie którego mogę ocenić, co może być wykonane w ramach 'sprintu' i wydać dokładniejszą ocenę dla każdego zadania.

Dlatego najbardziej efektywnym argumentem wydaje się być pokazanie 'nietechnicznemu' specjaliście, jak bardzo czas i zasoby będą się różnić w zależności od parametrów, które jeszcze muszą być ocenione.

Co może pójść nie tak z Data Science? Zbieranie danych

Źródło: habr.com

Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS 🔥 Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS | ProHoster