Wat kan er misgaan bij Data Science? Gegevensverzameling

Wat kan er misgaan bij Data Science? Gegevensverzameling
Tegenwoordig zijn er 100500 Data Science-cursussen en het is al lang bekend dat het meeste geld in Data Science kan worden verdiend met Data Science-cursussen (waarom graven als je schoppen kunt verkopen?). Het grootste nadeel van deze cursussen is dat ze niets met echt werk te maken hebben: niemand zal je schone, verwerkte gegevens in het vereiste formaat geven. En als je de cursus verlaat en een echt probleem gaat oplossen, komen er veel nuances naar voren.

Daarom beginnen we met een reeks aantekeningen “Wat kan er misgaan met Data Science”, gebaseerd op echte gebeurtenissen die mij, mijn kameraden en collega’s zijn overkomen. We zullen typische Data Science-taken analyseren aan de hand van echte voorbeelden: hoe dit feitelijk gebeurt. Laten we vandaag beginnen met de taak voor het verzamelen van gegevens.

En het eerste waar mensen over struikelen als ze met echte data gaan werken, is het daadwerkelijk verzamelen van de data die voor ons het meest relevant zijn. De kernboodschap van dit artikel:

We onderschatten systematisch de tijd, middelen en moeite die nodig zijn om gegevens te verzamelen, op te schonen en voor te bereiden.

En het allerbelangrijkste: we zullen bespreken wat we moeten doen om dit te voorkomen.

Volgens verschillende schattingen nemen opschoning, transformatie, gegevensverwerking, feature-engineering, etc. 80-90% van de tijd in beslag, en analyse 10-20%, terwijl bijna al het onderwijsmateriaal uitsluitend op analyse is gericht.

Laten we als typisch voorbeeld een eenvoudig analytisch probleem in drie versies bekijken en zien wat “verzwarende omstandigheden” zijn.

En als voorbeeld zullen we opnieuw soortgelijke varianten van de taak van het verzamelen van gegevens en het vergelijken van gemeenschappen bekijken voor:

  1. Twee Reddit-subreddits
  2. Twee delen van Habr
  3. Twee groepen Odnoklassniki

Voorwaardelijke benadering in theorie

Open de site en lees de voorbeelden. Als het duidelijk is, reserveer dan een paar uur voor het lezen, een paar uur voor de code met behulp van de voorbeelden en het debuggen. Voeg een paar uur toe voor het verzamelen. Zet een paar uur reserve in (vermenigvuldig met twee en tel N uur op).

Belangrijk punt: Tijdschattingen zijn gebaseerd op aannames en giswerk over hoe lang het zal duren.

Het is noodzakelijk om de tijdanalyse te beginnen door de volgende parameters te schatten voor het hierboven beschreven voorwaardelijke probleem:

  • Wat is de omvang van de gegevens en hoeveel ervan moet fysiek worden verzameld (*zie hieronder*).
  • Wat is de ophaaltijd voor één record en hoe lang moet je wachten voordat je de tweede kunt ophalen?
  • Overweeg code te schrijven die de status opslaat en een herstart start wanneer (niet als) alles mislukt.
  • Zoek uit of we autorisatie nodig hebben en stel de tijd in voor het verkrijgen van toegang via de API.
  • Stel het aantal fouten in als functie van de complexiteit van de gegevens - evalueer voor een specifieke taak: structuur, hoeveel transformaties, wat en hoe te extraheren.
  • Repareer netwerkfouten en problemen met niet-standaard projectgedrag.
  • Beoordeel of de vereiste functies in de documentatie staan ​​en zo niet, hoe en hoeveel er nodig is voor een oplossing.

Het belangrijkste is dat om de tijd in te schatten - je eigenlijk tijd en moeite moet besteden aan "verkenningen die van kracht zijn" - alleen dan zal je planning adequaat zijn. Daarom, hoezeer u ook wordt gedwongen om te zeggen “hoe lang duurt het om gegevens te verzamelen” – koop uzelf wat tijd voor een voorlopige analyse en beargumenteer in hoeverre de tijd zal variëren, afhankelijk van de werkelijke parameters van de taak.

En nu zullen we specifieke voorbeelden demonstreren waarin dergelijke parameters zullen veranderen.

Kernpunt: De schatting is gebaseerd op een analyse van sleutelfactoren die van invloed zijn op de omvang en complexiteit van het werk.

Op gok gebaseerde schattingen zijn een goede aanpak als de functionele elementen klein genoeg zijn en er niet veel factoren zijn die het ontwerp van het probleem significant kunnen beïnvloeden. Maar in het geval van een aantal Data Science-problemen worden dergelijke factoren uiterst talrijk en wordt een dergelijke aanpak ontoereikend.

Vergelijking van Reddit-gemeenschappen

Laten we beginnen met het eenvoudigste geval (zoals later blijkt). Over het algemeen hebben we, om helemaal eerlijk te zijn, een bijna ideaal geval. Laten we onze complexiteitschecklist eens bekijken:

  • Er is een nette, duidelijke en gedocumenteerde API.
  • Het is uiterst eenvoudig en het allerbelangrijkste: er wordt automatisch een token verkregen.
  • Er is python omslag - met veel voorbeelden.
  • Een community die gegevens op reddit analyseert en verzamelt (zelfs YouTube-video's waarin wordt uitgelegd hoe je Python-wrapper gebruikt) hier is een voorbeeld.
  • De methoden die we nodig hebben, bestaan ​​hoogstwaarschijnlijk in de API. Bovendien ziet de code er compact en overzichtelijk uit; hieronder staat een voorbeeld van een functie die reacties op een bericht verzamelt.

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

Genomen van dit een selectie handige hulpprogramma's voor het inpakken.

Ondanks het feit dat dit het beste geval is, is het toch de moeite waard om rekening te houden met een aantal belangrijke factoren uit het echte leven:

  • API-limieten - we zijn gedwongen om gegevens in batches op te nemen (slaap tussen verzoeken, enz.).
  • Verzameltijd - voor een volledige analyse en vergelijking moet u een aanzienlijke hoeveelheid tijd reserveren, zodat de spin door de subreddit kan lopen.
  • De bot moet op een server draaien; u kunt hem niet zomaar op uw laptop laten draaien, in uw rugzak stoppen en uw gang gaan. Dus ik draaide alles op een VPS. Met de promotiecode habrahabr10 kunt u nog eens 10% op de kosten besparen.
  • De fysieke ontoegankelijkheid van sommige gegevens (ze zijn zichtbaar voor beheerders of zijn te moeilijk om te verzamelen) - hiermee moet rekening worden gehouden; in principe kunnen niet alle gegevens op tijd worden verzameld.
  • Netwerkfouten: Netwerken is lastig.
  • Dit zijn levende, echte gegevens - het is nooit puur.

Natuurlijk is het noodzakelijk om deze nuances in de ontwikkeling op te nemen. Specifieke uren/dagen zijn afhankelijk van ontwikkelingservaring of ervaring met het werken aan soortgelijke taken. We zien echter dat de taak hier puur technisch is en geen extra lichaamsbewegingen vereist om op te lossen - alles kan zeer goed worden beoordeeld, gepland en uitgevoerd.

Vergelijking van Habr-secties

Laten we verder gaan met een interessanter en niet-triviaal geval van het vergelijken van threads en/of secties van Habr.

Laten we onze checklist voor complexiteit eens bekijken. Om elk punt te begrijpen, moet je hier een beetje in de taak zelf duiken en experimenteren.

  • In eerste instantie denk je dat er een API is, maar die is er niet. Ja, ja, Habr heeft een API, maar deze is gewoon niet toegankelijk voor gebruikers (of misschien werkt deze helemaal niet).
  • Dan begin je gewoon met het parseren van html - “importverzoeken”, wat kan er misgaan?
  • Hoe dan ook te parseren? De eenvoudigste en meest gebruikte aanpak is het herhalen van ID's. Merk op dat dit niet de meest efficiënte is en verschillende gevallen zal moeten behandelen - hier is een voorbeeld van de dichtheid van echte ID's onder alle bestaande.

    Wat kan er misgaan bij Data Science? Gegevensverzameling
    Genomen van dit artikelen.

  • Ruwe gegevens verpakt in HTML op internet zijn lastig. U wilt bijvoorbeeld de beoordeling van een artikel verzamelen en opslaan: u hebt de score uit de html gehaald en besloten deze als getal op te slaan voor verdere verwerking: 

    1) int(score) levert een fout op: aangezien er op Habré een minteken staat, zoals bijvoorbeeld in de regel “–5” - dit is een en-streepje, geen minteken (onverwachts, toch?), dus bij op een gegeven moment moest ik de parser tot leven wekken met zo'n vreselijke oplossing.

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

    Het kan zijn dat er helemaal geen datum, plussen en minnen zijn (zoals we hierboven zien in de check_date-functie, is dit gebeurd).

    2) Niet-ontsnapte speciale karakters - ze zullen komen, je moet voorbereid zijn.

    3) De structuur verandert afhankelijk van het type post.

    4) Oude berichten kunnen een **rare structuur** hebben.

  • In wezen zal de foutafhandeling en wat er wel of niet zal gebeuren moeten worden afgehandeld en je kunt niet met zekerheid voorspellen wat er mis zal gaan en hoe anders de structuur zal zijn en wat waar zal wegvallen - je zult gewoon moeten proberen er rekening mee te houden de fouten die de parser genereert.
  • Dan realiseer je je dat je in meerdere threads moet parseren, anders duurt het parseren in één thread meer dan 30 uur (dit is puur de uitvoeringstijd van een reeds werkende single-threaded parser, die slaapt en niet onder een verbod valt). IN dit artikel leidde dit op een gegeven moment tot een soortgelijk plan:

Wat kan er misgaan bij Data Science? Gegevensverzameling

Totale checklist naar complexiteit:

  • Werken met het netwerk en html-parsing met iteratie en zoeken op ID.
  • Documenten met een heterogene structuur.
  • Er zijn veel plaatsen waar de code gemakkelijk kan vallen.
  • Het is noodzakelijk om || te schrijven code.
  • De benodigde documentatie, codevoorbeelden en/of community ontbreken.

De geschatte tijd voor deze taak zal 3-5 keer hoger zijn dan voor het verzamelen van gegevens van Reddit.

Vergelijking van Odnoklassniki-groepen

Laten we verder gaan met het technisch meest interessante beschreven geval. Voor mij was het juist interessant omdat het er op het eerste gezicht nogal triviaal uitziet, maar dat blijkt helemaal niet zo te zijn - zodra je er met een stok tegenaan steekt.

Laten we beginnen met onze moeilijkheidschecklist en merk op dat veel ervan veel moeilijker zullen blijken te zijn dan ze op het eerste gezicht lijken:

  • Er is een API, maar deze mist vrijwel volledig de noodzakelijke functies.
  • Voor bepaalde functies moet u per mail toegang aanvragen, dat wil zeggen dat het verlenen van toegang niet onmiddellijk plaatsvindt.
  • Het is vreselijk gedocumenteerd (om te beginnen zijn Russische en Engelse termen overal door elkaar gehaald, en volkomen inconsistent - soms moet je gewoon raden wat ze ergens van je willen) en bovendien is het ontwerp niet geschikt om bijvoorbeeld gegevens te verkrijgen , de functie die we nodig hebben.
  • Vereist een sessie in de documentatie, maar maakt er eigenlijk geen gebruik van - en er is geen manier om alle fijne kneepjes van de API-modi te begrijpen, behalve rondneuzen en hopen dat iets zal werken.
  • Er zijn geen voorbeelden en geen gemeenschap; het enige steunpunt bij het verzamelen van informatie is een klein wikkel in Python (zonder veel gebruiksvoorbeelden).
  • Selenium lijkt de meest werkbare optie, omdat veel van de noodzakelijke gegevens achter slot en grendel zitten.
    1) Dat wil zeggen dat autorisatie plaatsvindt via een fictieve gebruiker (en handmatige registratie).

    2) Bij Selenium zijn er echter geen garanties voor correct en herhaalbaar werk (tenminste zeker in het geval van ok.ru).

    3) De Ok.ru-website bevat JavaScript-fouten en gedraagt ​​zich soms vreemd en inconsistent.

    4) U moet paginering uitvoeren, elementen laden, enz...

    5) API-fouten die de wrapper geeft, moeten bijvoorbeeld op deze manier worden afgehandeld (een stukje experimentele 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
    

    Mijn favoriete fout was:

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

    6) Uiteindelijk lijkt Selenium + API de meest rationele optie.

  • Het is noodzakelijk om de status op te slaan en het systeem opnieuw op te starten, veel fouten op te lossen, inclusief inconsistent gedrag van de site - en deze fouten zijn vrij moeilijk voor te stellen (tenzij je natuurlijk parsers professioneel schrijft).

De voorwaardelijke tijdschatting voor deze taak zal 3-5 keer hoger zijn dan voor het verzamelen van gegevens uit Habr. Ondanks dat we in het geval van Habr een frontale benadering hanteren met HTML-parsing, en in het geval van OK op kritische plekken met de API kunnen werken.

Bevindingen

Hoe vaak u ook de deadlines “ter plekke” (we plannen het vandaag!) van een omvangrijke pijplijnmodule voor gegevensverwerking moet inschatten, de uitvoeringstijd is bijna nooit mogelijk om zelfs maar kwalitatief in te schatten zonder de taakparameters te analyseren.

Op een iets meer filosofische toon werken agile schattingsstrategieën goed voor technische taken, maar problemen die meer experimenteel en in zekere zin ‘creatief’ en verkennend zijn, d.w.z. minder voorspelbaar, hebben moeilijkheden, zoals in de voorbeelden van soortgelijke onderwerpen. die we hier hebben besproken.

Natuurlijk is het verzamelen van gegevens slechts een goed voorbeeld; het is meestal een ongelooflijk eenvoudige en technisch ongecompliceerde taak, en de duivel zit vaak in de details. En juist met deze taak kunnen we het hele scala aan mogelijke opties laten zien van wat er mis kan gaan en hoe lang het werk precies kan duren.

Als je zonder aanvullende experimenten naar de kenmerken van de taak kijkt, zien Reddit en OK er hetzelfde uit: er is een API, een Python-wrapper, maar in wezen is het verschil enorm. Afgaande op deze parameters lijkt de pars van Habr ingewikkelder dan oké - maar in de praktijk is het precies het tegenovergestelde, en dit is precies wat kan worden ontdekt door eenvoudige experimenten uit te voeren om de parameters van het probleem te analyseren.

In mijn ervaring is de meest effectieve aanpak het grofweg inschatten van de tijd die je nodig hebt voor de voorlopige analyse zelf en voor eenvoudige eerste experimenten, waarbij je de documentatie leest - hiermee kun je een nauwkeurige schatting maken van het hele werk. In termen van de populaire agile-methodologie vraag ik je om een ​​ticket aan te maken voor het ‘schatten van taakparameters’, op basis waarvan ik een inschatting kan geven van wat er binnen de ‘sprint’ kan worden bereikt en voor elke taak een nauwkeurigere schatting kan geven. taak.

Daarom lijkt het meest effectieve argument er een te zijn die een ‘niet-technische’ specialist laat zien hoeveel tijd en middelen zullen variëren afhankelijk van parameters die nog moeten worden beoordeeld.

Wat kan er misgaan bij Data Science? Gegevensverzameling

Bron: www.habr.com

Voeg een reactie