Cosa può andare storto con la Data Science? Raccolta dati

Cosa può andare storto con la Data Science? Raccolta dati
Oggi ci sono 100500 corsi di Data Science e è già noto che i corsi di Data Science sono il modo migliore per guadagnare nel campo: per quale motivo scavare quando puoi vendere pale? Il principale svantaggio di questi corsi è che non hanno nulla a che fare con il lavoro reale: nessuno ti fornirà dati puliti e lavorati nel formato corretto. E quando finisci il corso e inizi a affrontare un vero problema, emergono molte sfide.

Per questo motivo, iniziamo una serie di articoli "Cosa può andare storto con il Data Science", basati su eventi reali accaduti a me, ai miei amici e colleghi. Analizzeremo esempi concreti di compiti tipici di Data Science: come avviene realmente. Iniziamo oggi con la questione della raccolta dei dati.

E il primo ostacolo che incontrano le persone che iniziano a lavorare con dati reali è proprio la raccolta di questi dati pertinenti. 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 cosa fare per evitare che ciò accada.

Secondo diverse stime, la pulizia, la trasformazione, il data processing, il feature engineering ecc. occupano l'80-90% del tempo, mentre l'analisi il 10-20%, mentre praticamente tutto il materiale didattico si concentra esclusivamente sull'analisi.

Analizziamo come esempio tipico un semplice compito analitico in tre varianti e vediamo quali possono essere le "circostanze aggravanti".

E per esempio, considereremo nuovamente variazioni simili del problema di raccolta dei dati e confronteremo le comunità per:

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

Un approccio condizionale in teoria

Apri il sito e leggi gli esempi; se è chiaro, pianifica alcune ore per la lettura, alcune ore per il codice degli esempi e il debug. Aggiungi alcune ore per la raccolta. Aggiungi alcune ore di riserva (raddoppia e aggiungi N ore).

Il punto chiave: la stima temporale si basa su supposizioni e congetture su quanto tempo ci vorrà.

Inizia l'analisi del tempo stimando i seguenti parametri per il compito condizionale descritto sopra:

  • Qual è la dimensione dei dati e quanto fisicamente bisogna raccogliere (*vedi sotto*).
  • Quanto tempo ci vuole per raccogliere un'unità di dati e quanto bisogna aspettare prima di poter raccogliere la successiva.
  • Prevedere la scrittura del codice che mantiene lo stato e avvia il riavvio quando (e non se) tutto cade.
  • Capire se abbiamo bisogno di autenticazione e prevedere il tempo di accesso tramite API.
  • Prevedere il numero di errori come funzione della complessità dei dati — valutare in base a un compito specifico: struttura, quanti cambiamenti, cosa e come estraiamo.
  • Prevedere errori di rete e problemi con comportamenti non standard del progetto.
  • Valutare se le funzioni necessarie sono nella documentazione e, in caso contrario, quanto e come è necessario per una soluzione alternativa.

La cosa più importante per la valutazione del tempo è che è necessario investire realmente tempo e sforzi per una "ricognizione" — solo allora la tua pianificazione sarà adeguata. Quindi, per quanto tu possa essere spinto a dire "quanto tempo serve per raccogliere i dati" — prenditi del tempo per un'analisi preliminare e giustifica quanto il tempo varierà in base ai parametri reali del compito.

E adesso mostreremo esempi concreti in cui tali parametri cambieranno.

Punto chiave: la valutazione si basa sull'analisi dei fattori chiave che influenzano il volume e la complessità del lavoro.

La valutazione basata su congetture è un buon approccio quando gli elementi funzionali sono piuttosto piccoli e non ci sono molti fattori che possono influenzare in modo significativo la struttura del compito. Ma nel caso di diversi compiti di Data Science, tali fattori diventano estremamente numerosi e questo approccio diventa inadeguato.

Confronto delle comunità di Reddit

Iniziamo dal caso più semplice (come poi si dimostrerà). In realtà, se vogliamo essere completamente onesti, ci troviamo di fronte a un caso praticamente ideale, verifichiamo la nostra lista di controllo della complessità:

  • C'è un'API chiara, comprensibile e documentata.
  • Estremamente semplice e soprattutto, il token viene ottenuto automaticamente.
  • C'è wrapper python — con un sacco di esempi.
  • La comunità che si occupa di analisi e raccolta di dati su Reddit (fino a video su YouTube che spiegano come utilizzare il wrapper python) ad esempio, ecco.
  • I metodi di cui abbiamo bisogno probabilmente esistono nell'API. Inoltre, il codice appare compatto e pulito, qui sotto un esempio di una funzione che raccoglie i commenti a 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()

Tratto da questo selezioni di utilità convenienti per il wrapping.

Nonostante siamo di fronte al miglior caso, è comunque importante considerare una serie di fattori significativi della vita reale:

  • Limiti API — dobbiamo raccogliere i dati a gruppi (fare delle pause tra le richieste, ecc.).
  • Tempo di raccolta — per un'analisi e un confronto completi, sarà necessario prevedere un tempo considerevole affinché il crawler possa passare attraverso il subreddit.
  • Il bot deve funzionare su un server — non puoi semplicemente avviarlo sul portatile, metterlo nello zaino e andare in giro. Per questo ho avviato tutto su VPS. Con il codice promozionale habrahabr10 puoi risparmiare un ulteriore 10%.
  • Inaccessibilità fisica di alcuni dati (visibili solo agli admin o raccolti in modo troppo complesso) — questo deve essere considerato, non tutti i dati possono essere raccolti in tempi ragionevoli.
  • Errori di rete: lavorare con la rete è una seccatura.
  • Questi sono dati reali — non sono mai puri.

Certo, è necessario tenere conto di questi aspetti durante lo sviluppo. I tempi specifici dipendono dall'esperienza di sviluppo o dall'esperienza su compiti simili; tuttavia, possiamo notare che qui la questione è puramente ingegneristica e non richiede ulteriori sforzi per la risoluzione: tutto può essere valutato bene, dettagliato e realizzato.

Confronto delle sezioni di Habr

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

Controlliamo la nostra lista di controllo della complessità: qui, per comprendere ogni punto, sarà necessario esplorare un po' il compito stesso e sperimentare.

  • Inizialmente pensi che esista un'API, ma non c'è. Sì, Habr ha un'API, ma è solo non disponibile per gli utenti (o potrebbe non funzionare affatto).
  • Poi inizi semplicemente a parsificare l'html — "import requests", cosa potrebbe andare storto?
  • E come si fa a parsificare? L'approccio più semplice e comunemente usato è iterare per ID, notiamo che non è il più efficiente e sarà necessario gestire vari casi — per esempio, la densità degli ID reali tra tutti gli esistenti.

    Cosa può andare storto con la Data Science? Raccolta dati
    Tratto da questo articoli.

  • I dati grezzi, incapsulati in HTML sulla rete, sono un problema. Ad esempio, vuoi raccogliere e salvare il punteggio di un articolo: hai estratto il punteggio dall'html e hai deciso di conservarlo come numero per ulteriore elaborazione: 

    1) int(score) genera un errore: poiché su Habr il meno, come in "–5", è un trattino corto, non un segno meno (inaspettato, vero?), quindi a un certo punto è stato necessario far funzionare il parser con una soluzione orribile del genere.

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

    Potrebbe non esserci affatto un valore di data, più o meno (come vediamo sopra nella funzione check_date, ed è successo).

    2) I caratteri speciali non scappati arriveranno, bisogna essere pronti.

    3) La struttura cambia a seconda del tipo di post.

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

  • In sostanza, la gestione degli errori e ciò che può o non può accadere dovrà essere gestita e non si può prevedere con certezza cosa andrà storto e come potrebbe essere la struttura e dove potrebbe andare in crisi - dovrai semplicemente provare e tenere conto degli errori che il parser lancia.
  • Poi capisci che devi effettuare il parsing in più thread altrimenti il parsing in uno solo richiederà più di 30 ore (questo è solo il tempo di esecuzione di un parser monothread che sta dormendo e non rischia ban). In questo un articolo, questo ha portato a un certo punto a uno schema simile:

Cosa può andare storto con la Data Science? Raccolta dati

In sintesi, la lista di controllo per la complessità:

  • Lavorare con la rete e fare parsing di html con iterazioni e iterazioni su ID.
  • Documenti di struttura eterogenea.
  • Molti luoghi in cui il codice può facilmente fallire.
  • È necessario scrivere || codice.
  • Manca la documentazione necessaria, esempi di codice e/o comunità.

Una valutazione condizionata del tempo per questo compito sarà da 3 a 5 volte superiore a quella per raccogliere dati da Reddit.

Confronto tra gruppi di Odnoklassniki

Passiamo al caso più tecnicamente interessante tra quelli descritti. Per me era interessante proprio perché, a prima vista, sembra piuttosto banale, ma non è affatto così - non appena ci dai un colpetto.

Inizieremo dalla nostra lista di controllo della complessità e notiamo che molti di essi si riveleranno molto più complicati di quanto non sembrino inizialmente:

  • L'API c'è, ma mancano quasi completamente le funzioni necessarie.
  • Per alcune funzioni bisogna richiedere l'accesso via email, quindi la concessione dell'accesso non è immediata.
  • È mal documentato (per cominciare, si mescolano termini russi e inglesi in modo assolutamente incoerente — a volte devi semplicemente indovinare cosa vogliono da te) e, inoltre, non è progettato per la raccolta dei 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 sottigliezze delle modalità API, se non provando e sperando che qualcosa funzioni.
  • Mancano esempi e comunità, l'unico punto di riferimento nella raccolta delle informazioni è un piccolo wrapper in Python (senza un gran numero di esempi di utilizzo).
  • La soluzione più funzionante sembra essere Selenium, dal momento che molti dei dati necessari sono bloccati.
    1) Cioè, l'autenticazione avviene tramite un utente fittizio (e registrazione manuale).

    2) Tuttavia, con Selenium non ci sono garanzie di funzionamento corretto e ripetibile (almeno nel caso di ok.ru, sicuramente).

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

    4) È necessario affrontare la paginazione, il caricamento di elementi, ecc.…

    5) Gli errori API restituiti dal wrapper dovranno essere gestiti in modo un po’ macchinoso, 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) Alla fine, la combinazione Selenium + API sembra la soluzione più razionale.

  • È necessario mantenere lo stato e riavviare il sistema, gestire molti errori, incluso il comportamento incoerente del sito — e queste sono situazioni abbastanza difficili da immaginare (a meno che non scrivi parser in modo professionale, ovviamente).

Una stima condizionale del tempo per questo compito sarà da 3 a 5 volte superiore rispetto alla raccolta di dati da Habr. Anche se nel caso di Habr utilizziamo un approccio diretto con l'analisi HTML, mentre nel caso di OK possiamo lavorare con l'API in punti critici.

Conclusioni

Anche se vi venisse chiesto di fornire una stima dei tempi "sul posto" (dobbiamo fare pianificazione oggi!), il tempo di esecuzione è praticamente impossibile da valutare anche qualitativamente senza un'analisi dei parametri del compito.

Se parliamo in modo un po' più filosofico, le strategie di stima in agile si adattano bene ai compiti ingegneristici, ma sorgono difficoltà con compiti più sperimentali e, in un certo senso, "creativi" e di ricerca, ovvero meno prevedibili, come negli esempi simili a quelli che abbiamo esaminato qui.

Certo, la raccolta dei dati è un esempio illuminante — di solito questo compito sembra incredibilmente semplice e tecnicamente non problematico, ed è proprio nei dettagli che spesso si nasconde il diavolo. E proprio su questo compito si riesce a dimostrare tutta la gamma di possibili varianti di ciò che può andare storto e quanto possa effettivamente prolungarsi il lavoro.

Se si esaminano rapidamente le caratteristiche del compito senza esperimenti aggiuntivi, Reddit e OK sembrano simili: c'è un'API, un wrapper python, ma in sostanza, la differenza è enorme. Se si giudica in base a questi parametri, il parsing di Habr sembra più complicato rispetto a OK — e nella pratica è esattamente il contrario, e questo si può scoprire effettuando semplici esperimenti di analisi dei parametri del compito.

Dal mio punto di vista, l'approccio più efficace è una stima approssimativa del tempo che occorrerà per l'analisi preliminare e i primi esperimenti semplici, la lettura della documentazione — sono questi a permettervi di fornire una stima precisa per l'intero lavoro. In termini di metodologia agile popolare — chiedo di aprirmi un ticket per "stima dei parametri del compito", sulla base del quale posso fornire una stima di ciò che è possibile realizzare nel contesto di uno "sprint" e fornire una stima più precisa per ciascun compito.

Pertanto, sembra più efficace un'argomentazione che mostri a un esperto "non tecnico" quanto possa variare il tempo e le risorse a seconda dei parametri che devono ancora essere valutati.

Cosa può andare storto con la Data Science? Raccolta dati

Fonte: habr.com

Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server 🔥 Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server | ProHoster