Cosa può andare storto con la scienza dei dati? Raccolta dati

Cosa può andare storto con la scienza dei dati? Raccolta dati
Oggi ci sono 100500 corsi di Data Science ed è noto da tempo che la maggior parte dei soldi in Data Science si possono guadagnare attraverso i corsi di Data Science (perché scavare quando si possono vendere pale?). Lo svantaggio principale di questi corsi è che non hanno nulla a che fare con il lavoro vero e proprio: nessuno ti fornirà dati puliti ed elaborati nel formato richiesto. E quando si esce dal corso e si inizia a risolvere un problema reale, emergono tante sfumature.

Pertanto, stiamo iniziando una serie di appunti “Cosa può andare storto con la scienza dei dati”, basati su eventi reali accaduti a me, ai miei compagni e colleghi. Analizzeremo i compiti tipici della Data Science utilizzando esempi reali: come ciò avviene realmente. Iniziamo oggi con l'attività di raccolta dati.

E la prima cosa in cui le persone inciampano quando iniziano a lavorare con dati reali è proprio la raccolta dei dati che sono più rilevanti per noi. Il messaggio chiave di questo articolo:

Sottovalutiamo sistematicamente il tempo, le risorse e gli sforzi necessari per raccogliere, pulire e preparare i dati.

E, soprattutto, discuteremo su cosa fare per evitarlo.

Secondo varie stime, la pulizia, la trasformazione, l'elaborazione dei dati, l'ingegneria delle funzionalità, ecc. richiedono l'80-90% del tempo e l'analisi il 10-20%, mentre quasi tutto il materiale didattico si concentra esclusivamente sull'analisi.

Consideriamo come esempio tipico un semplice problema analitico in tre versioni e vediamo quali sono le “circostanze aggravanti”.

E come esempio, ancora una volta, prenderemo in considerazione variazioni simili del compito di raccogliere dati e confrontare le comunità per:

  1. Due subreddit di Reddit
  2. Due sezioni di Habr
  3. Due gruppi di Odnoklassniki

Approccio condizionale in teoria

Apri il sito e leggi gli esempi, se è chiaro dedica qualche ora alla lettura, qualche ora al codice utilizzando gli esempi e al debug. Aggiungi qualche ora per la raccolta. Metti qualche ora in riserva (moltiplica per due e aggiungi N ore).

Punto chiave: le stime dei tempi si basano su ipotesi e congetture sul tempo necessario.

È necessario iniziare l’analisi temporale stimando i seguenti parametri per il problema condizionale sopra descritto:

  • Qual è la dimensione dei dati e quanti di essi devono essere raccolti fisicamente (*vedi sotto*).
  • Qual è il tempo di ritiro di un record e quanto tempo devi aspettare prima di poter ritirare il secondo?
  • Considera la possibilità di scrivere codice che salvi lo stato e avvii un riavvio quando (non se) tutto fallisce.
  • Scopri se abbiamo bisogno dell'autorizzazione e imposta l'ora per ottenere l'accesso tramite l'API.
  • Imposta il numero di errori in funzione della complessità dei dati: valuta per un'attività specifica: struttura, quante trasformazioni, cosa e come estrarre.
  • Correggi errori di rete e problemi con comportamenti di progetto non standard.
  • Valutare se le funzioni richieste sono presenti nella documentazione e, in caso contrario, come e quanto è necessario per una soluzione alternativa.

La cosa più importante è che per stimare il tempo - in realtà è necessario dedicare tempo e sforzi alla "ricognizione in vigore" - solo allora la tua pianificazione sarà adeguata. Pertanto, non importa quanto sei spinto a dire "quanto tempo ci vuole per raccogliere i dati", prenditi del tempo per un'analisi preliminare e argomenta quanto il tempo varierà a seconda dei parametri reali del problema.

E ora dimostreremo esempi specifici in cui tali parametri cambieranno.

Punto chiave: la stima si basa su un'analisi dei fattori chiave che influenzano la portata e la complessità del lavoro.

La stima basata su ipotesi è un buon approccio quando gli elementi funzionali sono sufficientemente piccoli e non ci sono molti fattori che possono influenzare in modo significativo la progettazione del problema. Ma nel caso di una serie di problemi di Data Science, tali fattori diventano estremamente numerosi e tale approccio diventa inadeguato.

Confronto delle comunità Reddit

Cominciamo con il caso più semplice (come si scoprirà più avanti). In generale, ad essere completamente onesti, abbiamo un caso quasi ideale, controlliamo la nostra lista di controllo della complessità:

  • Esiste un'API ordinata, chiara e documentata.
  • È estremamente semplice e, cosa più importante, il token viene ottenuto automaticamente.
  • C'è involucro di pitone - con molti esempi.
  • Una comunità che analizza e raccoglie dati su Reddit (anche nei video di YouTube che spiegano come utilizzare il wrapper Python) per esempio.
  • I metodi di cui abbiamo bisogno molto probabilmente esistono nell'API. Inoltre il codice appare compatto e pulito, di seguito è riportato un esempio di funzione che raccoglie commenti su un post.

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

Preso da questo una selezione di utili strumenti per il confezionamento.

Nonostante questo sia il caso migliore, vale comunque la pena prendere in considerazione una serie di fattori importanti della vita reale:

  • Limiti API: siamo costretti a prendere i dati in batch (sospensione tra le richieste, ecc.).
  • Tempo di raccolta: per un'analisi e un confronto completi, dovrai dedicare un tempo significativo solo affinché lo spider cammini attraverso il subreddit.
  • Il bot deve essere eseguito su un server: non puoi semplicemente eseguirlo sul tuo laptop, metterlo nello zaino e dedicarti ai tuoi affari. Quindi ho eseguito tutto su un VPS. Utilizzando il codice promozionale habrahabr10 puoi risparmiare un altro 10% del costo.
  • L'inaccessibilità fisica di alcuni dati (sono visibili agli amministratori o sono troppo difficili da raccogliere) - di questo bisogna tener conto; in linea di principio, non tutti i dati possono essere raccolti in tempo adeguato.
  • Errori di rete: la rete è una seccatura.
  • Si tratta di dati reali viventi: non sono mai puri.

Naturalmente, è necessario includere queste sfumature nello sviluppo. Ore/giorni specifici dipendono dall'esperienza di sviluppo o dall'esperienza di lavoro su compiti simili, tuttavia, vediamo che qui il compito è puramente ingegneristico e non richiede movimenti del corpo aggiuntivi per essere risolto: tutto può essere valutato, programmato e fatto molto bene.

Confronto delle sezioni Habr

Passiamo a un caso più interessante e non banale di confronto di thread e/o sezioni di Habr.

Controlliamo la nostra lista di controllo della complessità: qui, per comprendere ogni punto, dovrai approfondire un po' l'attività stessa e sperimentare.

  • All'inizio pensi che esista un'API, ma non esiste. Sì, sì, Habr ha un'API, ma semplicemente non è accessibile agli utenti (o forse non funziona affatto).
  • Quindi inizi ad analizzare l'HTML - "richieste di importazione", cosa potrebbe andare storto?
  • Come analizzare comunque? L'approccio più semplice e utilizzato più frequentemente è quello di ripetere gli ID, nota che non è il più efficiente e dovrà gestire casi diversi: ecco un esempio della densità di ID reali tra tutti quelli esistenti.

    Cosa può andare storto con la scienza dei dati? Raccolta dati
    Preso da questo articolo.

  • I dati grezzi racchiusi in HTML sul web sono una seccatura. Ad esempio, vuoi raccogliere e salvare la valutazione di un articolo: hai estratto il punteggio dall'html e hai deciso di salvarlo come numero per un'ulteriore elaborazione: 

    1) int(score) genera un errore: poiché su Habré c'è un segno meno, come, ad esempio, nella riga "–5" - questo è un trattino, non un segno meno (inaspettatamente, giusto?), quindi a ad un certo punto ho dovuto riportare in vita il parser con una soluzione così terribile.

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

    Potrebbero non esserci date, più e meno (come abbiamo visto sopra nella funzione check_date, questo è successo).

    2) Caratteri speciali senza escape: arriveranno, devi essere preparato.

    3) La struttura cambia a seconda della tipologia di incarico.

    4) I vecchi post potrebbero avere una **struttura strana**.

  • In sostanza, sarà necessario gestire la gestione degli errori e ciò che può o meno accadere e non è possibile prevedere con certezza cosa andrà storto e in che altro modo potrebbe essere la struttura e cosa cadrà e dove: dovrai solo provare a tenerne conto gli errori generati dal parser.
  • Quindi ti rendi conto che devi analizzare più thread, altrimenti l'analisi in uno richiederà più di 30 ore (questo è puramente il tempo di esecuzione di un parser a thread singolo già funzionante, che dorme e non rientra in alcun divieto). IN questo articolo, questo ha portato ad un certo punto a uno schema simile:

Cosa può andare storto con la scienza dei dati? Raccolta dati

Lista di controllo totale per complessità:

  • Lavorare con la rete e l'analisi html con iterazione e ricerca per ID.
  • Documenti di struttura eterogenea.
  • Ci sono molti posti in cui il codice può facilmente cadere.
  • È necessario scrivere || codice.
  • Mancano la documentazione necessaria, gli esempi di codice e/o la community.

Il tempo stimato per questa attività sarà 3-5 volte superiore rispetto alla raccolta dei dati da Reddit.

Confronto dei gruppi Odnoklassniki

Passiamo al caso descritto più tecnicamente interessante. Per me è stato interessante proprio perché a prima vista sembra piuttosto banale, ma non risulta affatto essere così, non appena lo colpisci.

Iniziamo con la nostra lista di controllo delle difficoltà e notiamo che molti di essi si riveleranno molto più difficili di quanto sembri all'inizio:

  • C'è un'API, ma manca quasi completamente delle funzioni necessarie.
  • Per alcune funzioni è necessario richiedere l'accesso via mail, ovvero la concessione dell'accesso non è istantanea.
  • È terribilmente documentato (per cominciare, i termini russi e inglesi sono confusi ovunque e in modo del tutto incoerente - a volte devi solo indovinare cosa vogliono da te da qualche parte) e, inoltre, il design non è adatto per ottenere dati, ad esempio , la funzione di cui abbiamo bisogno.
  • Richiede una sessione nella documentazione, ma in realtà non la utilizza e non c'è modo di comprendere tutte le complessità delle modalità API se non curiosare e sperare che qualcosa funzioni.
  • Non ci sono esempi e nessuna comunità; l'unico punto di appoggio nella raccolta delle informazioni è un piccolo involucro in Python (senza molti esempi di utilizzo).
  • Il selenio sembra essere l’opzione più praticabile, poiché molti dei dati necessari sono bloccati.
    1) Cioè l'autorizzazione avviene tramite un utente fittizio (e la registrazione manualmente).

    2) Tuttavia, con Selenium non ci sono garanzie per un lavoro corretto e ripetibile (almeno nel caso di ok.ru di sicuro).

    3) Il sito web Ok.ru contiene errori JavaScript e talvolta si comporta in modo strano e incoerente.

    4) Devi fare l'impaginazione, caricare gli elementi, ecc...

    5) Gli errori API forniti dal wrapper dovranno essere gestiti in modo complicato, ad esempio in questo modo (un pezzo di codice sperimentale):

    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
    

    Il mio errore preferito è stato:

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

    6) In definitiva, Selenium + API sembra l'opzione più razionale.

  • È necessario salvare lo stato e riavviare il sistema, gestire molti errori, incluso il comportamento incoerente del sito - e questi errori sono abbastanza difficili da immaginare (a meno che non si scrivano parser professionalmente, ovviamente).

La stima del tempo condizionale per questa attività sarà 3-5 volte superiore rispetto a quella per la raccolta dei dati da Habr. Nonostante il fatto che nel caso di Habr utilizziamo un approccio frontale con l'analisi HTML, e nel caso di OK possiamo lavorare con l'API in punti critici.

risultati

Non importa quanto sia necessario stimare le scadenze “sul posto” (stiamo pianificando oggi!) di un voluminoso modulo di pipeline di elaborazione dati, il tempo di esecuzione non è quasi mai possibile stimare anche qualitativamente senza analizzare i parametri dell’attività.

Da un punto di vista leggermente più filosofico, le strategie di stima agili funzionano bene per compiti di ingegneria, ma i problemi che sono più sperimentali e, in un certo senso, “creativi” ed esplorativi, cioè meno prevedibili, hanno difficoltà, come negli esempi di argomenti simili, di cui abbiamo discusso qui.

Naturalmente, la raccolta dei dati è solo un ottimo esempio: di solito è un compito incredibilmente semplice e tecnicamente non complicato, e spesso il diavolo si nasconde nei dettagli. Ed è proprio su questo compito che possiamo mostrare l'intera gamma di possibili opzioni su cosa può andare storto e esattamente quanto tempo può durare il lavoro.

Se guardi le caratteristiche dell'attività senza ulteriori esperimenti, Reddit e OK sembrano simili: c'è un'API, un wrapper Python, ma in sostanza la differenza è enorme. A giudicare da questi parametri, il pars di Habr sembra più complicato di OK, ma in pratica è esattamente il contrario, e questo è esattamente ciò che può essere scoperto conducendo semplici esperimenti per analizzare i parametri del problema.

Secondo la mia esperienza, l'approccio più efficace è stimare approssimativamente il tempo necessario per l'analisi preliminare stessa e i primi semplici esperimenti, leggendo la documentazione: questi ti permetteranno di dare una stima accurata dell'intero lavoro. In termini della popolare metodologia agile, ti chiedo di creare un ticket per la “stima dei parametri del compito”, sulla base del quale posso dare una valutazione di ciò che può essere realizzato all'interno dello “sprint” e fornire una stima più accurata per ciascuno compito.

Pertanto, l’argomentazione più efficace sembra essere quella che mostri allo specialista “non tecnico” quanto tempo e risorse varieranno a seconda di parametri che devono ancora essere valutati.

Cosa può andare storto con la scienza dei dati? Raccolta dati

Fonte: habr.com

Aggiungi un commento