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

Cosa può andare storto con la Data Science? Raccolta dati
Attualmente ci sono 100.500 corsi di Data Science e si sa da tempo che si può guadagnare di più vendendo corsi di Data Science (perché scavare quando puoi vendere pale?). Il principale svantaggio di questi corsi è che non hanno nulla a che fare con il lavoro reale: nessuno ti darà dati grezzi e lavorati nel formato richiesto. E quando esci da un corso e inizi a risolvere un problema reale, emergono molte complicazioni.

Pertanto, iniziamo una serie di appunti intitolati "Cosa può andare storto con il Data Science", basati su eventi reali che sono accaduti a me, ai miei colleghi e compagni. Analizzeremo esempi concreti di compiti tipici in Data Science: come accade davvero. Iniziamo oggi con il compito di raccolta dati.

E il primo ostacolo che le persone incontrano iniziando a lavorare con dati reali è proprio la raccolta di questi dati rilevanti. 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 varie stime, la pulizia, la trasformazione, il data processing, l'ingegneria delle caratteristiche, ecc. occupano l'80-90% del tempo, mentre l'analisi solo il 10-20%, mentre praticamente tutto il materiale didattico si concentra esclusivamente sull'analisi.

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

E per esempio, esamineremo simili variazioni nel compito di raccolta dati e confronto delle comunità per:

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

Un approccio condizionale in teoria

Aprire il sito e leggere gli esempi, se è chiaro, dedicare alcune ore alla lettura, alcune ore al codice sugli esempi e al debug. Aggiungere alcune ore per la raccolta. Aggiungere ulteriori ore a disposizione (moltiplicare per due e aggiungere N ore).

Il punto chiave: la stima temporale si basa su ipotesi e congetture su quanto tempo richiederà.

Iniziare l'analisi del tempo deve partire dalla valutazione dei seguenti parametri per il compito condizionale descritto sopra:

  • Qual è la dimensione dei dati e quanto ne è necessario raccogliere fisicamente (*vedi sotto*).
  • Qual è il tempo di raccolta di una registrazione e quanto bisogna aspettare prima di poter raccogliere la seconda.
  • Implementare la scrittura del codice per mantenere lo stato e avviare un riavvio quando (e non se) tutto fallisce.
  • Chiarire se abbiamo bisogno di autorizzazione e predisporre il tempo necessario per l'accesso tramite API.
  • Considerare il numero di errori come funzione della complessità dei dati — valutare in base a un compito specifico: struttura, quante trasformazioni, cosa e come estraiamo.
  • Considerare gli errori di rete e i problemi con i comportamenti non standard del progetto.
  • Valutare se le funzioni necessarie sono nella documentazione e, in caso contrario, quanto tempo e come sarà necessario per una soluzione alternativa.

La cosa più importante per valutare il tempo — è necessario effettivamente spendere tempo e sforzi per un "recon" — solo allora la vostra pianificazione sarà adeguata. Pertanto, qualunque pressione ci sia nel dire "quanto tempo è necessario per raccogliere i dati" — prendetevi tempo per un'analisi preliminare e argomentate quanto il tempo varierà in base ai parametri reali del compito.

E ora presenteremo esempi concreti in cui questi parametri cambieranno.

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

Una valutazione basata su supposizioni è un buon approccio quando gli elementi funzionali sono piuttosto piccoli e ci sono pochi fattori che possono influenzare la struttura del compito. Tuttavia, nel caso di alcune attività di Data Science, i fattori possono diventare estremamente numerosi e questo approccio diventa inadeguato.

Comparazione delle comunità di Reddit

Iniziamo con il caso più semplice (come poi si rivelerà). In realtà, per essere onesti, ci troviamo di fronte a un caso praticamente ideale, verifichiamo la nostra checklist di complessità:

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

Estratto da questo elenco di utilità pratiche per l'incapsulamento.

Nonostante siamo di fronte al miglior caso, ci sono ancora una serie di fattori importanti della vita reale da considerare:

  • Limiti API — siamo costretti a prendere i dati in batch (fare pause tra le richieste, ecc.).
  • Tempo di raccolta — per un'analisi completa e un confronto, sarà necessario prevedere un notevole tempo affinché il crawler possa esplorare il subreddit.
  • Il bot deve essere in esecuzione su un server — non puoi semplicemente avviarlo sul laptop, metterlo nello zaino e andare per affari. Per questo motivo, ho avviato tutto su un VPS. Con il codice promozionale habrahabr10 puoi risparmiare il 10% sul costo.
  • Inaccessibilità fisica di alcuni dati (visibili solo agli amministratori o troppo complessi da raccogliere) — questo deve essere considerato, non tutti i dati possono essere raccolti in un tempo ragionevole.
  • Errori di rete: lavorare con la rete è un problema.
  • Questi sono dati reali e vivi — non sono mai completamente puliti.

Certo, è fondamentale includere questi aspetti nello sviluppo. Le ore/giorni specifici dipendono dall'esperienza di sviluppo o da esperienze simili, tuttavia vediamo che qui la questione è puramente ingegneristica e non richiede ulteriori sforzi per essere risolta: possiamo valutare, pianificare e realizzare tutto molto bene.

Confronto delle sezioni di Habr

Passiamo a un caso più interessante e non triviale nel confronto dei flussi e/o delle sezioni di Habr.

Verifichiamo la nostra lista di controllo della difficoltà: qui, per comprendere ogni punto, dovremo toccare un po' la questione e fare qualche esperimento.

  • All'inizio si pensa che ci sia un API, ma non c'è. Sì, Habr ha un API, ma è solo inaccessibile per gli utenti (o potrebbe non funzionare affatto).
  • Poi si inizia semplicemente a fare parsing dell'html: "import requests", cosa potrebbe andare storto?
  • E come si fa a fare parsing? L'approccio più semplice e comunemente usato è iterare per ID, notando che non è il più efficace e bisognerà gestire casi diversi: ecco un esempio della densità degli ID reali tra tutti quelli esistenti.

    Cosa può andare storto con la Data Science? Raccolta dati
    Estratto da questo dell'articolo.

  • I dati grezzi avvolti in HTML attraverso la rete sono un mal di testa. Ad esempio, vuoi estrarre e conservare il punteggio di un articolo: estrai il punteggio dall'html e decidi di salvarlo come numero per ulteriori elaborazioni. 

    1) int(punteggio) genera un errore: su Habr, il meno, come nella stringa "–5", è un trattino corto e non un segno meno (inatteso, vero?), quindi a un certo punto è stato necessario riavviare il parser con un orrendo fix 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
    

    Le date, i più e i meno potrebbero non esserci affatto (come vediamo sopra nella funzione check_date, è successo).

    2) Caratteri speciali non escapati — essi arriveranno, bisogna essere pronti.

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

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

  • Fondamentalmente, dovrai gestire gli errori e ciò che può o non può accadere, e non puoi prevedere con certezza cosa potrebbe andare storto e quale potrebbe essere la struttura, e dove ci saranno problemi — dovrai semplicemente provare e considerare gli errori che il parser restituisce.
  • Poi capisci che è necessario effettuare il parsing in più thread, altrimenti il parsing in uno solo richiederà oltre 30 ore (questo è solo il tempo di esecuzione di un parser a thread singolo, che è inattivo e non incappa in alcun ban). In questo l'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 checklist per la complessità:

  • Lavorare con reti e parsare HTML con iterazione e navigazione per ID.
  • Documenti di struttura eterogenea.
  • Molti punti in cui il codice può facilmente andare in errore.
  • Necessità di scrivere || codice.
  • Manca la documentazione necessaria, esempi di codice e/o comunità.

La stima condizionale del tempo per questo compito sarà 3-5 volte superiore a quella per raccogliere dati da Reddit.

Confronto dei gruppi di Odnoklassniki

Passiamo al caso tecnicamente più interessante tra quelli descritti. Per me è stato interessante proprio perché, a prima vista, sembra abbastanza banale, ma non lo è affatto—appena lo tocchi con un bastoncino.

Inizieremo con la nostra checklist di complessità e segnaleremo che molti di essi si riveleranno molto più complicati di quanto sembrino all'inizio:

  • L'API esiste, ma manca quasi completamente delle funzioni necessarie.
  • Alcune funzioni richiedono la richiesta di accesso via email, quindi l'accesso non è immediato.
  • È terribilmente documentato (iniziamo col dire che si mescolano termini russi e inglesi ovunque, in modo assolutamente incoerente — a volte bisogna semplicemente indovinare cosa vogliono da te) e, inoltre, non è adatto per ottenere i dati in modo efficiente, per esempio, la funzione di cui abbiamo bisogno.
  • Richiede una sessione nella documentazione, ma in realtà non la utilizza — e non c'è modo di districarsi tra le complessità dei vari modi API, se non provando e sperando che qualcosa funzioni.
  • Mancano esempi e una comunità, l'unico punto di riferimento per la raccolta di informazioni è un piccolo wrapper in Python (senza una grande quantità di esempi di utilizzo).
  • L'opzione più funzionale sembra essere Selenium, poiché molti dati necessari sono bloccati.
    1) Cioè, l'autenticazione avviene tramite un utente fittizio (e registrazione manuale).

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

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

    4) È necessario gestire la paginazione, il caricamento degli elementi, ecc…

    5) Gli errori API restituiti dal wrapper devono essere gestiti in modo artigianale, 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 era:

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

    6) Alla fine, la combinazione di Selenium + API sembra essere la soluzione più razionale.

  • È necessario mantenere lo stato e riavviare il sistema, gestire numerosi 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 condizionata del tempo per questo compito sarà da 3 a 5 volte superiore rispetto alla raccolta dei dati da Habr. Sebbene nel caso di Habr utilizziamo un approccio frontale con parsing HTML, nel caso di OK possiamo lavorare con l'API in modo critico.

Conclusioni

Anche se vi viene chiesta una stima dei tempi «sul posto» (dobbiamo pianificare oggi!), è praticamente impossibile valutare il tempo di esecuzione di un voluminoso modulo di pipeline per l'elaborazione dei dati, se non dopo aver analizzato i parametri del compito.

Se parliamo in modo un po' più filosofico, le strategie di stima in agile si adattano bene ai compiti ingegneristici, ma per compiti più sperimentali e, in un certo senso, «creativi» e di ricerca, ossia meno prevedibili, sorgono difficoltà, come negli esempi che abbiamo analizzato qui.

Sicuramente, la raccolta dei dati è un chiaro esempio illustrativo — di solito sembra un compito incredibilmente semplice e tecnicamente poco complicato, ma sono proprio nei dettagli che si nasconde il diavolo. Ed è proprio in questo compito che si può mostrare l'intero spettro delle possibili varianti di ciò che può andare storto e quanto effettivamente può allungarsi il lavoro.

Se si osservano rapidamente le caratteristiche del compito senza esperimenti aggiuntivi, Reddit e OK sembrano simili: c'è un'API e un wrapper Python, ma in sostanza la differenza è enorme. Se si giudica da questi parametri, il parsing di Habr sembra più complesso rispetto a OK — mentre in pratica è esattamente il contrario, e questo può essere scoperto eseguendo semplici esperimenti per analizzare i parametri del compito.

Dalla mia esperienza, l'approccio più efficace è una stima preliminare del tempo necessario per l'analisi iniziale, esperimenti semplici e la lettura della documentazione: sono queste attività che permettono di fornire una stima precisa per l'intero lavoro. In termini della metodologia agile popolare, chiedo di aprire un ticket per 'stimare i parametri del task', sulla base del quale posso valutare cosa è possibile realizzare nel corso di uno 'sprint' e fornire una stima più accurata per ogni attività.

Pertanto, sembra più efficace un argomento che mostri a un professionista 'non tecnico' quanto possono 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