O que pode dar errado com a ciência de dados? Coleção de dados

O que pode dar errado com a ciência de dados? Coleção de dados
Hoje existem 100500 cursos de Ciência de Dados e há muito se sabe que a maior parte do dinheiro em Ciência de Dados pode ser ganho por meio de cursos de Ciência de Dados (por que cavar quando você pode vender pás?). A principal desvantagem desses cursos é que eles não têm nada a ver com o trabalho real: ninguém fornecerá dados limpos e processados ​​no formato exigido. E quando você sai do curso e começa a resolver um problema real, surgem muitas nuances.

Portanto, estamos iniciando uma série de notas “O que pode dar errado com a Ciência de Dados”, baseadas em acontecimentos reais que aconteceram comigo, com meus camaradas e colegas. Analisaremos tarefas típicas de Data Science usando exemplos reais: como isso realmente acontece. Vamos começar hoje com a tarefa de coleta de dados.

E a primeira coisa que as pessoas tropeçam quando começam a trabalhar com dados reais é na verdade coletar esses dados que são mais relevantes para nós. A mensagem principal deste artigo:

Subestimamos sistematicamente o tempo, os recursos e o esforço necessários para coletar, limpar e preparar dados.

E o mais importante, discutiremos o que fazer para evitar isso.

De acordo com várias estimativas, limpeza, transformação, processamento de dados, engenharia de recursos, etc. levam de 80 a 90% do tempo e a análise de 10 a 20%, enquanto quase todo o material educacional se concentra exclusivamente na análise.

Vejamos um problema analítico simples em três versões como um exemplo típico e vejamos o que são “circunstâncias agravantes”.

E como exemplo, consideraremos novamente variações semelhantes da tarefa de coletar dados e comparar comunidades para:

  1. Dois subreddits do Reddit
  2. Duas seções de Habr
  3. Dois grupos de Odnoklassniki

Abordagem condicional em teoria

Abra o site e leia os exemplos, se estiver claro reserve algumas horas para leitura, algumas horas para o código utilizando os exemplos e depuração. Adicione algumas horas para coleta. Adicione algumas horas de reserva (multiplique por dois e adicione N horas).

Ponto-chave: As estimativas de tempo são baseadas em suposições e suposições sobre quanto tempo levará.

É necessário iniciar a análise temporal estimando os seguintes parâmetros para o problema condicional descrito acima:

  • Qual é o tamanho dos dados e quanto deles precisa ser coletado fisicamente (*veja abaixo*).
  • Qual é o tempo de coleta de um registro e quanto tempo você terá que esperar antes de coletar o segundo?
  • Considere escrever um código que salve o estado e inicie uma reinicialização quando (não se) tudo falhar.
  • Descubra se precisamos de autorização e defina o tempo para obter acesso via API.
  • Defina o número de erros em função da complexidade dos dados - avalie para uma tarefa específica: estrutura, quantas transformações, o que e como extrair.
  • Corrija erros de rede e problemas com comportamento de projeto fora do padrão.
  • Avalie se as funções necessárias estão na documentação e, caso contrário, como e quanto é necessário para uma solução alternativa.

O mais importante é que para estimar o tempo - na verdade é preciso despender tempo e esforço no "reconhecimento em vigor" - só assim o seu planejamento estará adequado. Portanto, não importa o quanto você seja pressionado a dizer “quanto tempo leva para coletar dados” - ganhe algum tempo para uma análise preliminar e argumente quanto o tempo irá variar dependendo dos parâmetros reais do problema.

E agora demonstraremos exemplos específicos onde tais parâmetros serão alterados.

Ponto-chave: A estimativa é baseada em uma análise dos principais fatores que influenciam o escopo e a complexidade do trabalho.

A estimativa baseada em suposições é uma boa abordagem quando os elementos funcionais são pequenos o suficiente e não há muitos fatores que possam influenciar significativamente o design do problema. Mas no caso de uma série de problemas de Ciência de Dados, tais fatores tornam-se extremamente numerosos e tal abordagem torna-se inadequada.

Comparação de comunidades Reddit

Vamos começar com o caso mais simples (como veremos mais tarde). Em geral, para ser totalmente honesto, temos um caso quase ideal, vamos verificar nossa lista de verificação de complexidade:

  • Existe uma API organizada, clara e documentada.
  • É extremamente simples e, o mais importante, um token é obtido automaticamente.
  • Tem invólucro python - com muitos exemplos.
  • Uma comunidade que analisa e coleta dados no reddit (até mesmo vídeos do YouTube explicando como usar o wrapper python) aqui é um exemplo.
  • Os métodos que precisamos provavelmente existem na API. Além disso, o código parece compacto e limpo. Abaixo está um exemplo de função que coleta comentários em uma postagem.

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

Tirado de este uma seleção de utilitários convenientes para embalagem.

Apesar de este ser o melhor caso, ainda vale a pena levar em consideração uma série de fatores importantes da vida real:

  • Limites da API - somos forçados a coletar dados em lotes (suspensão entre solicitações, etc.).
  • Tempo de coleta - para uma análise e comparação completa, você terá que reservar um tempo significativo apenas para o spider percorrer o subreddit.
  • O bot deve ser executado em um servidor – você não pode simplesmente executá-lo em seu laptop, colocá-lo em sua mochila e cuidar de seus negócios. Então executei tudo em um VPS. Usando o código promocional habrahabr10 você pode economizar mais 10% do custo.
  • A inacessibilidade física de alguns dados (são visíveis para os administradores ou são muito difíceis de recolher) - isto deve ser levado em conta; em princípio, nem todos os dados podem ser recolhidos em tempo adequado.
  • Erros de rede: a rede é uma dor.
  • Isto são dados reais e vivos – nunca são puros.

Claro, é necessário incluir essas nuances no desenvolvimento. Horas/dias específicos dependem da experiência de desenvolvimento ou experiência trabalhando em tarefas semelhantes, porém, vemos que aqui a tarefa é puramente de engenharia e não requer movimentos corporais adicionais para ser resolvida - tudo pode ser muito bem avaliado, programado e feito.

Comparação de seções Habr

Vamos passar para um caso mais interessante e não trivial de comparação de tópicos e/ou seções de Habr.

Vamos verificar nossa lista de verificação de complexidade - aqui, para entender cada ponto, você terá que se aprofundar um pouco na tarefa em si e experimentar.

  • A princípio você pensa que existe uma API, mas não existe. Sim, sim, Habr tem uma API, mas ela simplesmente não está acessível aos usuários (ou talvez nem funcione).
  • Então você simplesmente começa a analisar html - “solicitações de importação”, o que pode dar errado?
  • Como analisar, afinal? A abordagem mais simples e utilizada com mais frequência é iterar sobre IDs, observe que não é a mais eficiente e terá que lidar com casos diferentes - aqui está um exemplo da densidade de IDs reais entre todos os existentes.

    O que pode dar errado com a ciência de dados? Coleção de dados
    Tirado de este artigos.

  • Dados brutos agrupados em HTML na web são uma dor de cabeça. Por exemplo, você deseja coletar e salvar a avaliação de um artigo: você arrancou a pontuação do HTML e decidiu salvá-la como um número para processamento posterior: 

    1) int(pontuação) gera um erro: já que em Habré há um sinal de menos, como, por exemplo, na linha “–5” - este é um travessão, não um sinal de menos (inesperadamente, certo?), então em em algum momento, tive que dar vida ao analisador com uma solução tão terrível.

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

    Pode não haver data, prós e contras (como vemos acima na função check_date, isso aconteceu).

    2) Caracteres especiais sem escape - eles virão, você precisa estar preparado.

    3) A estrutura muda dependendo do tipo de cargo.

    4) Postagens antigas podem ter uma **estrutura estranha**.

  • Essencialmente, o tratamento de erros e o que pode ou não acontecer terão que ser tratados e você não pode prever com certeza o que vai dar errado e de que outra forma a estrutura pode ser e o que vai cair onde - você apenas terá que tentar levar em conta os erros que o analisador lança.
  • Então você percebe que precisa analisar em vários threads, caso contrário, a análise em um levará mais de 30 horas (este é puramente o tempo de execução de um analisador de thread único já em funcionamento, que dorme e não é banido). EM este artigo, isso levou em algum momento a um esquema semelhante:

O que pode dar errado com a ciência de dados? Coleção de dados

Lista de verificação total por complexidade:

  • Trabalhando com rede e análise de html com iteração e busca por ID.
  • Documentos de estrutura heterogênea.
  • Existem muitos lugares onde o código pode cair facilmente.
  • É necessário escrever || código.
  • A documentação necessária, exemplos de código e/ou comunidade estão faltando.

O tempo estimado para esta tarefa será de 3 a 5 vezes maior do que para a coleta de dados do Reddit.

Comparação de grupos Odnoklassniki

Passemos ao caso tecnicamente mais interessante descrito. Para mim, foi interessante justamente porque à primeira vista parece bastante trivial, mas não é assim - assim que você cutuca isso.

Vamos começar com nossa lista de verificação de dificuldades e observar que muitas delas serão muito mais difíceis do que parecem à primeira vista:

  • Existe uma API, mas falta quase completamente as funções necessárias.
  • Para determinadas funções é necessário solicitar acesso por correio, ou seja, a concessão de acesso não é instantânea.
  • Está terrivelmente documentado (para começar, os termos em russo e inglês estão misturados em todos os lugares e de forma completamente inconsistente - às vezes você só precisa adivinhar o que eles querem de você em algum lugar) e, além disso, o design não é adequado para obter dados, por exemplo , a função que precisamos.
  • Requer uma sessão na documentação, mas na verdade não a utiliza - e não há outra maneira de entender todas as complexidades dos modos de API a não ser dar uma olhada e esperar que algo funcione.
  • Não há exemplos nem comunidade; o único ponto de apoio na recolha de informação é um pequeno invólucro em Python (sem muitos exemplos de uso).
  • O Selenium parece ser a opção mais viável, já que muitos dos dados necessários estão bloqueados.
    1) Ou seja, a autorização ocorre por meio de usuário fictício (e cadastro manual).

    2) Porém, com Selenium não há garantias de trabalho correto e repetível (pelo menos no caso de ok.ru com certeza).

    3) O site Ok.ru contém erros de JavaScript e às vezes se comporta de maneira estranha e inconsistente.

    4) Você precisa fazer paginação, carregar elementos, etc...

    5) Os erros de API que o wrapper fornece terão que ser tratados de maneira estranha, por exemplo, assim (um pedaço de código experimental):

    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
    

    Meu erro favorito foi:

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

    6) Em última análise, Selenium + API parece a opção mais racional.

  • É necessário salvar o estado e reiniciar o sistema, lidar com muitos erros, incluindo comportamento inconsistente do site - e esses erros são bastante difíceis de imaginar (a menos que você escreva analisadores profissionalmente, é claro).

A estimativa de tempo condicional para esta tarefa será de 3 a 5 vezes maior do que para a coleta de dados do Habr. Apesar de no caso do Habr utilizarmos uma abordagem frontal com análise de HTML, e no caso do OK podemos trabalhar com a API em locais críticos.

Descobertas

Não importa o quanto você precise estimar os prazos “na hora” (estamos planejando hoje!) de um volumoso módulo de pipeline de processamento de dados, quase nunca é possível estimar o tempo de execução, mesmo qualitativamente, sem analisar os parâmetros da tarefa.

Numa nota um pouco mais filosófica, estratégias de estimativa ágil funcionam bem para tarefas de engenharia, mas problemas que são mais experimentais e, de certa forma, “criativos” e exploratórios, ou seja, menos previsíveis, apresentam dificuldades, como nos exemplos de tópicos semelhantes. que discutimos aqui.

É claro que a coleta de dados é apenas um excelente exemplo – geralmente é uma tarefa incrivelmente simples e tecnicamente descomplicada, e o diabo geralmente está nos detalhes. E é justamente nesta tarefa que podemos mostrar todo o leque de opções possíveis sobre o que pode dar errado e exatamente quanto tempo o trabalho pode levar.

Se você observar as características da tarefa sem experimentos adicionais, o Reddit e o OK serão semelhantes: existe uma API, um wrapper python, mas, em essência, a diferença é enorme. A julgar por esses parâmetros, a pars de Habr parece mais complicada do que OK - mas na prática é exatamente o oposto, e é exatamente isso que pode ser descoberto realizando experimentos simples para analisar os parâmetros do problema.

Na minha experiência, a abordagem mais eficaz é estimar aproximadamente o tempo necessário para a análise preliminar e os primeiros experimentos simples, lendo a documentação - isso permitirá que você forneça uma estimativa precisa para todo o trabalho. Em termos da popular metodologia ágil, peço que criem um ticket para “estimar parâmetros de tarefas”, com base no qual posso avaliar o que pode ser realizado dentro do “sprint” e fornecer uma estimativa mais precisa para cada tarefa.

Portanto, o argumento mais eficaz parece ser aquele que mostraria a um especialista “não técnico” quanto tempo e recursos irão variar dependendo de parâmetros que ainda não foram avaliados.

O que pode dar errado com a ciência de dados? Coleção de dados

Fonte: habr.com

Adicionar um comentário