Was kann bei Data Science schiefgehen? Datensammlung

Was kann bei Data Science schiefgehen? Datensammlung
Heute gibt es 100500 Data-Science-Kurse und es ist schon lange bekannt, dass das meiste Geld in Data Science mit Data-Science-Kursen verdient werden kann (warum graben, wenn man Schaufeln verkaufen kann?). Der Hauptnachteil dieser Kurse besteht darin, dass sie nichts mit echter Arbeit zu tun haben: Niemand wird Ihnen saubere, aufbereitete Daten im erforderlichen Format zur Verfügung stellen. Und wenn man den Kurs verlässt und beginnt, ein echtes Problem zu lösen, tauchen viele Nuancen auf.

Aus diesem Grund beginnen wir mit einer Reihe von Notizen zum Thema „Was kann bei Data Science schiefgehen“, basierend auf realen Ereignissen, die mir, meinen Kameraden und Kollegen widerfahren sind. Wir analysieren typische Data Science-Aufgaben anhand realer Beispiele: Wie das tatsächlich geschieht. Beginnen wir heute mit der Datenerfassungsaufgabe.

Und das erste, worüber die Leute stolpern, wenn sie anfangen, mit echten Daten zu arbeiten, ist, dass sie tatsächlich die Daten sammeln, die für uns am relevantesten sind. Die Kernaussage dieses Artikels:

Wir unterschätzen systematisch den Zeit-, Ressourcen- und Arbeitsaufwand, der zum Sammeln, Bereinigen und Aufbereiten von Daten erforderlich ist.

Und vor allem besprechen wir, was zu tun ist, um dies zu verhindern.

Verschiedenen Schätzungen zufolge beanspruchen Bereinigung, Transformation, Datenverarbeitung, Feature Engineering usw. 80–90 % der Zeit und die Analyse 10–20 %, während sich fast alle Lehrmaterialien ausschließlich auf die Analyse konzentrieren.

Schauen wir uns als typisches Beispiel ein einfaches analytisches Problem in drei Versionen an und sehen wir uns an, was „erschwerende Umstände“ sind.

Und als Beispiel betrachten wir wiederum ähnliche Variationen der Aufgabe, Daten zu sammeln und Communities zu vergleichen für:

  1. Zwei Reddit-Subreddits
  2. Zwei Abschnitte von Habr
  3. Zwei Gruppen von Odnoklassniki

Bedingter Ansatz in der Theorie

Öffnen Sie die Site und lesen Sie die Beispiele. Wenn es klar ist, nehmen Sie sich ein paar Stunden Zeit zum Lesen, ein paar Stunden für den Code anhand der Beispiele und das Debuggen. Rechnen Sie mit der Abholung einige Stunden ein. Fügen Sie ein paar Stunden Reserve hinzu (multiplizieren Sie es mit zwei und addieren Sie N Stunden).

Kernpunkt: Zeitschätzungen basieren auf Annahmen und Vermutungen darüber, wie lange es dauern wird.

Es ist notwendig, die Zeitanalyse mit der Schätzung der folgenden Parameter für das oben beschriebene bedingte Problem zu beginnen:

  • Wie groß sind die Daten und wie viel davon muss physisch erfasst werden (*siehe unten*).
  • Wie lange dauert die Abholung für einen Datensatz und wie lange müssen Sie warten, bis Sie den zweiten abholen können?
  • Erwägen Sie das Schreiben von Code, der den Status speichert und einen Neustart startet, wenn (nicht wenn) alles fehlschlägt.
  • Finden Sie heraus, ob wir eine Autorisierung benötigen, und legen Sie den Zeitpunkt für den Zugriff über die API fest.
  • Legen Sie die Anzahl der Fehler als Funktion der Datenkomplexität fest – bewerten Sie sie für eine bestimmte Aufgabe: Struktur, wie viele Transformationen, was und wie extrahiert werden soll.
  • Beheben Sie Netzwerkfehler und Probleme mit nicht standardmäßigem Projektverhalten.
  • Bewerten Sie, ob die erforderlichen Funktionen in der Dokumentation enthalten sind und wenn nicht, wie und wie viel für eine Problemumgehung erforderlich ist.

Das Wichtigste ist, dass Sie zur Schätzung der Zeit – Sie müssen tatsächlich Zeit und Mühe in die „Aufklärung im Einsatz“ investieren – nur dann eine angemessene Planung ist. Unabhängig davon, wie sehr Sie gefragt werden, wie lange die Datenerfassung dauert, nehmen Sie sich daher etwas Zeit für eine vorläufige Analyse und argumentieren Sie, wie stark die Zeit je nach den tatsächlichen Parametern der Aufgabe variieren wird.

Und jetzt zeigen wir konkrete Beispiele, wo sich solche Parameter ändern werden.

Kernpunkt: Die Schätzung basiert auf einer Analyse der Schlüsselfaktoren, die den Umfang und die Komplexität der Arbeit beeinflussen.

Eine auf Schätzungen basierende Schätzung ist ein guter Ansatz, wenn die Funktionselemente klein genug sind und es nicht viele Faktoren gibt, die die Gestaltung des Problems wesentlich beeinflussen können. Bei einer Reihe von Data-Science-Problemen werden solche Faktoren jedoch extrem zahlreich und ein solcher Ansatz wird unzureichend.

Vergleich der Reddit-Communitys

Beginnen wir mit dem einfachsten Fall (wie sich später herausstellt). Um ganz ehrlich zu sein, haben wir im Allgemeinen einen nahezu idealen Fall. Schauen wir uns unsere Komplexitäts-Checkliste an:

  • Es gibt eine übersichtliche, klare und dokumentierte API.
  • Es ist äußerst einfach und das Wichtigste: Ein Token wird automatisch erhalten.
  • Es gibt Python-Wrapper - mit vielen Beispielen.
  • Eine Community, die Daten auf reddit analysiert und sammelt (sogar YouTube-Videos, in denen erklärt wird, wie man den Python-Wrapper verwendet) zum beispiel.
  • Die Methoden, die wir benötigen, sind höchstwahrscheinlich in der API vorhanden. Darüber hinaus sieht der Code kompakt und sauber aus. Unten finden Sie ein Beispiel für eine Funktion, die Kommentare zu einem Beitrag sammelt.

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()

Genommen von diese eine Auswahl praktischer Hilfsmittel zum Verpacken.

Auch wenn dies der beste Fall ist, lohnt es sich dennoch, eine Reihe wichtiger Faktoren aus dem wirklichen Leben zu berücksichtigen:

  • API-Grenzwerte – wir sind gezwungen, Daten stapelweise zu erfassen (Ruhezustand zwischen Anfragen usw.).
  • Erfassungszeit – für eine vollständige Analyse und einen Vergleich müssen Sie allein für den Spaziergang des Spiders durch den Subreddit viel Zeit einplanen.
  • Der Bot muss auf einem Server laufen – Sie können ihn nicht einfach auf Ihrem Laptop ausführen, ihn in Ihren Rucksack stecken und Ihrer Arbeit nachgehen. Also habe ich alles auf einem VPS ausgeführt. Mit dem Aktionscode habrahabr10 können Sie weitere 10 % der Kosten sparen.
  • Die physische Unzugänglichkeit einiger Daten (sie sind für Administratoren sichtbar oder zu schwer zu erfassen) – dies muss berücksichtigt werden; grundsätzlich können nicht alle Daten in angemessener Zeit erfasst werden.
  • Netzwerkfehler: Netzwerken ist eine Qual.
  • Dabei handelt es sich um lebendige, reale Daten – sie sind niemals rein.

Natürlich ist es notwendig, diese Nuancen in die Entwicklung einzubeziehen. Spezifische Stunden/Tage hängen von der Entwicklungserfahrung oder Erfahrung bei der Arbeit an ähnlichen Aufgaben ab. Wir sehen jedoch, dass es sich hier um eine rein technische Aufgabe handelt und keine zusätzlichen Körperbewegungen zur Lösung erforderlich sind – alles kann sehr gut beurteilt, geplant und erledigt werden.

Vergleich der Habr-Abschnitte

Kommen wir zu einem interessanteren und nicht trivialen Fall des Vergleichs von Threads und/oder Abschnitten von Habr.

Schauen wir uns unsere Komplexitäts-Checkliste an. Um jeden Punkt zu verstehen, müssen Sie sich ein wenig mit der Aufgabe selbst befassen und experimentieren.

  • Zuerst denkt man, dass es eine API gibt, aber das ist nicht der Fall. Ja, ja, Habr hat eine API, aber sie ist für Benutzer einfach nicht zugänglich (oder vielleicht funktioniert sie überhaupt nicht).
  • Dann fangen Sie einfach an, HTML zu analysieren – „Anfragen importieren“, was könnte schiefgehen?
  • Wie kann man überhaupt analysieren? Der einfachste und am häufigsten verwendete Ansatz besteht darin, über IDs zu iterieren. Beachten Sie, dass dies nicht der effizienteste ist und verschiedene Fälle behandeln muss – hier ist ein Beispiel für die Dichte realer IDs unter allen vorhandenen.

    Was kann bei Data Science schiefgehen? Datensammlung
    Genommen von diese artikel.

  • In HTML verpackte Rohdaten über dem Web sind mühsam. Sie möchten beispielsweise die Bewertung eines Artikels erfassen und speichern: Sie haben die Punktzahl aus dem HTML herausgerissen und beschlossen, sie zur weiteren Verarbeitung als Zahl zu speichern: 

    1) int(score) gibt einen Fehler aus: Da es bei Habré ein Minus gibt, wie zum Beispiel in der Zeile „–5“, ist dies ein Bindestrich, kein Minuszeichen (unerwartet, oder?), also bei Irgendwann musste ich den Parser mit solch einem schrecklichen Fix zum Leben erwecken.

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

    Möglicherweise gibt es überhaupt kein Datum, keine Plus- und Minuspunkte (wie wir oben in der Funktion check_date sehen, ist dies passiert).

    2) Unentdeckte Sonderzeichen – sie werden kommen, Sie müssen vorbereitet sein.

    3) Die Struktur ändert sich je nach Art des Beitrags.

    4) Alte Beiträge können eine **seltsame Struktur** haben.

  • Im Wesentlichen muss die Fehlerbehandlung gehandhabt werden und was passieren kann und was nicht, und Sie können nicht sicher vorhersagen, was schief gehen wird und wie die Struktur sonst aussehen könnte und was wo abfallen wird – Sie müssen nur versuchen, dies zu berücksichtigen die Fehler, die der Parser auslöst.
  • Dann wird Ihnen klar, dass Sie in mehreren Threads parsen müssen, andernfalls dauert das Parsen in einem Thread mehr als 30 Stunden (dies ist lediglich die Ausführungszeit eines bereits funktionierenden Single-Threaded-Parsers, der schläft und keinen Verboten unterliegt). IN diese Artikel, dies führte irgendwann zu einem ähnlichen Schema:

Was kann bei Data Science schiefgehen? Datensammlung

Gesamtcheckliste nach Komplexität:

  • Arbeiten mit dem Netzwerk und HTML-Parsing mit Iteration und Suche nach ID.
  • Dokumente heterogener Struktur.
  • Es gibt viele Stellen, an denen der Code leicht verloren gehen kann.
  • Es ist notwendig, || zu schreiben Code.
  • Die erforderliche Dokumentation, Codebeispiele und/oder Community fehlen.

Der geschätzte Zeitaufwand für diese Aufgabe wird drei- bis fünfmal höher sein als für das Sammeln von Daten auf Reddit.

Vergleich der Odnoklassniki-Gruppen

Kommen wir zum beschriebenen technisch interessantesten Fall. Für mich war es gerade deshalb interessant, weil es auf den ersten Blick recht trivial aussieht, es aber gar nicht so ist – sobald man mit einem Stock hineinsticht.

Beginnen wir mit unserer Schwierigkeits-Checkliste und beachten Sie, dass sich viele davon als viel schwieriger herausstellen werden, als sie zunächst aussehen:

  • Es gibt eine API, allerdings fehlen ihr die nötigen Funktionen fast vollständig.
  • Für bestimmte Funktionen müssen Sie den Zugriff per E-Mail anfordern, d. h. die Zugriffsgewährung erfolgt nicht sofort.
  • Es ist furchtbar dokumentiert (zunächst werden russische und englische Begriffe überall verwechselt, und zwar völlig inkonsistent – ​​manchmal muss man nur raten, was sie irgendwo von einem wollen) und außerdem ist das Design beispielsweise nicht für die Datenbeschaffung geeignet , die Funktion, die wir brauchen.
  • Erfordert eine Sitzung in der Dokumentation, nutzt sie aber nicht wirklich – und es gibt keine andere Möglichkeit, alle Feinheiten der API-Modi zu verstehen, als herumzustöbern und zu hoffen, dass etwas funktioniert.
  • Es gibt keine Beispiele und keine Community; der einzige Stützpunkt beim Sammeln von Informationen ist ein kleiner Verpackung in Python (ohne viele Anwendungsbeispiele).
  • Selen scheint die praktikableste Option zu sein, da viele der notwendigen Daten gesperrt sind.
    1) Das heißt, die Autorisierung erfolgt durch einen fiktiven Benutzer (und die Registrierung per Hand).

    2) Allerdings gibt es bei Selenium keine Garantien für korrekte und wiederholbare Arbeit (zumindest im Fall von ok.ru sicher).

    3) Die Website Ok.ru enthält JavaScript-Fehler und verhält sich manchmal seltsam und inkonsistent.

    4) Sie müssen eine Paginierung durchführen, Elemente laden usw.

    5) API-Fehler, die der Wrapper verursacht, müssen umständlich behandelt werden, zum Beispiel so (ein Stück experimenteller Code):

    def get_comments(args, context, discussions):
        pause = 1
        if args.extract_comments:
            all_comments = set()
    #makes sense to keep track of already processed discussions
            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
    

    Mein Lieblingsfehler war:

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

    6) Letztendlich scheint Selenium + API die rationalste Option zu sein.

  • Es ist notwendig, den Status zu speichern und das System neu zu starten, viele Fehler zu beheben, einschließlich inkonsistentem Verhalten der Site – und diese Fehler sind ziemlich schwer vorstellbar (es sei denn, Sie schreiben Parser natürlich professionell).

Die bedingte Zeitschätzung für diese Aufgabe wird drei- bis fünfmal höher sein als für die Datenerfassung von Habr. Trotz der Tatsache, dass wir im Fall von Habr einen frontalen Ansatz mit HTML-Parsing verwenden und im Fall von OK an kritischen Stellen mit der API arbeiten können.

Befund

Unabhängig davon, wie sehr Sie die Fristen „vor Ort“ (wir planen heute!) eines umfangreichen Datenverarbeitungs-Pipeline-Moduls abschätzen müssen, ist es fast nie möglich, die Ausführungszeit auch nur qualitativ abzuschätzen, ohne die Aufgabenparameter zu analysieren.

Etwas philosophischer ausgedrückt funktionieren agile Schätzstrategien gut für technische Aufgaben, aber Probleme, die experimenteller und in gewissem Sinne „kreativ“ und explorativ, also weniger vorhersehbar, sind, haben Schwierigkeiten, wie in den Beispielen ähnlicher Themen. worüber wir hier gesprochen haben.

Natürlich ist die Datenerhebung nur ein Paradebeispiel – es ist meist eine unglaublich einfache und technisch unkomplizierte Aufgabe, und der Teufel steckt oft im Detail. Und genau bei dieser Aufgabe können wir die ganze Bandbreite an Möglichkeiten aufzeigen, was schief gehen kann und wie lange die Arbeit genau dauern kann.

Wenn Sie sich die Eigenschaften der Aufgabe ohne zusätzliche Experimente ansehen, sehen Reddit und OK ähnlich aus: Es gibt eine API, einen Python-Wrapper, aber im Wesentlichen ist der Unterschied riesig. Nach diesen Parametern zu urteilen, sieht Habrs Pars komplizierter aus als OK – aber in der Praxis ist es genau das Gegenteil, und genau das kann man herausfinden, indem man einfache Experimente zur Analyse der Parameter des Problems durchführt.

Meiner Erfahrung nach ist es am effektivsten, den Zeitaufwand für die Voranalyse selbst und einfache erste Experimente grob abzuschätzen und die Dokumentation zu lesen – so können Sie eine genaue Schätzung für die gesamte Arbeit abgeben. In Anlehnung an die beliebte agile Methodik bitte ich Sie, ein Ticket zur „Schätzung der Aufgabenparameter“ zu erstellen, auf dessen Grundlage ich eine Einschätzung darüber abgeben kann, was innerhalb des „Sprints“ erreicht werden kann, und jeweils eine genauere Schätzung abgeben kann Aufgabe.

Daher scheint das wirksamste Argument eines zu sein, das einem „technisch nicht versierten“ Spezialisten zeigt, wie viel Zeit und Ressourcen abhängig von noch zu bewertenden Parametern variieren werden.

Was kann bei Data Science schiefgehen? Datensammlung

Source: habr.com

Kommentar hinzufügen