¿Qué puede salir mal con la ciencia de datos? Recopilación de datos

¿Qué puede salir mal con la ciencia de datos? Recopilación de datos
Hoy en día hay 100500 cursos de ciencia de datos y se sabe desde hace tiempo que la mayor cantidad de dinero en ciencia de datos se puede ganar a través de cursos de ciencia de datos (¿por qué cavar cuando puedes vender palas?). La principal desventaja de estos cursos es que no tienen nada que ver con el trabajo real: nadie le proporcionará datos limpios y procesados ​​en el formato requerido. Y cuando dejas el curso y empiezas a resolver un problema real, surgen muchos matices.

Por eso, iniciamos una serie de notas “Qué puede salir mal con la Ciencia de Datos”, basadas en hechos reales que nos sucedieron a mí, a mis compañeros y colegas. Analizaremos tareas típicas de ciencia de datos utilizando ejemplos reales: cómo sucede esto realmente. Comencemos hoy con la tarea de recopilación de datos.

Y lo primero con lo que la gente se topa cuando empieza a trabajar con datos reales es con la recopilación de los datos que son más relevantes para nosotros. El mensaje clave de este artículo:

Subestimamos sistemáticamente el tiempo, los recursos y el esfuerzo necesarios para recopilar, limpiar y preparar datos.

Y lo más importante, discutiremos qué hacer para evitarlo.

Según diversas estimaciones, la limpieza, la transformación, el procesamiento de datos, la ingeniería de funciones, etc. toman entre el 80 y el 90% del tiempo, y el análisis entre el 10 y el 20%, mientras que casi todo el material educativo se centra exclusivamente en el análisis.

Consideremos un problema analítico simple en tres versiones como ejemplo típico y veamos qué son las "circunstancias agravantes".

Y como ejemplo, nuevamente, consideraremos variaciones similares de la tarea de recopilar datos y comparar comunidades para:

  1. Dos subreddits de Reddit
  2. Dos secciones de Habr
  3. Dos grupos de Odnoklassniki

Enfoque condicional en teoría.

Abra el sitio y lea los ejemplos, si está claro, reserve unas horas para leer, unas horas para el código usando los ejemplos y depurando. Agregue algunas horas para la recolección. Echa unas horas de reserva (multiplica por dos y suma N horas).

Punto clave: Las estimaciones de tiempo se basan en suposiciones y conjeturas sobre cuánto tiempo llevará.

Es necesario comenzar el análisis de tiempo estimando los siguientes parámetros para el problema condicional descrito anteriormente:

  • ¿Cuál es el tamaño de los datos y cuántos de ellos deben recopilarse físicamente (*ver más abajo*)?
  • ¿Cuál es el tiempo de recolección de un registro y cuánto tiempo hay que esperar antes de poder recolectar el segundo?
  • Considere escribir código que guarde el estado e inicie un reinicio cuando (no si) todo falla.
  • Averigüe si necesitamos autorización y establezca el tiempo para obtener acceso a través de la API.
  • Establezca la cantidad de errores en función de la complejidad de los datos: evalúe para una tarea específica: estructura, cuántas transformaciones, qué y cómo extraer.
  • Solucione errores de red y problemas con comportamientos de proyectos no estándar.
  • Evalúe si las funciones requeridas están en la documentación y, en caso contrario, cómo y cuánto se necesita para una solución alternativa.

Lo más importante es que para estimar el tiempo (en realidad es necesario dedicar tiempo y esfuerzo al "reconocimiento en vigor"), sólo entonces su planificación será adecuada. Por lo tanto, no importa cuánto lo presionen para decir "cuánto tiempo lleva recopilar datos", gane algo de tiempo para un análisis preliminar y argumente cuánto variará el tiempo dependiendo de los parámetros reales del problema.

Y ahora mostraremos ejemplos específicos donde dichos parámetros cambiarán.

Punto clave: La estimación se basa en un análisis de factores clave que influyen en el alcance y la complejidad del trabajo.

La estimación basada en conjeturas es un buen enfoque cuando los elementos funcionales son lo suficientemente pequeños y no hay muchos factores que puedan influir significativamente en el diseño del problema. Pero en el caso de una serie de problemas de ciencia de datos, dichos factores se vuelven extremadamente numerosos y ese enfoque resulta inadecuado.

Comparación de comunidades de Reddit

Comencemos con el caso más simple (como veremos más adelante). En general, para ser completamente honesto, tenemos un caso casi ideal, revisemos nuestra lista de verificación de complejidad:

  • Existe una API ordenada, clara y documentada.
  • Es extremadamente simple y lo más importante es que un token se obtiene automáticamente.
  • Hay envoltorio de pitón - con muchos ejemplos.
  • Una comunidad que analiza y recopila datos en reddit (incluso videos de YouTube que explican cómo usar Python Wrapper) aquí hay un ejemplo.
  • Lo más probable es que los métodos que necesitamos existan en la API. Además, el código parece compacto y limpio; a continuación se muestra un ejemplo de una función que recopila comentarios en una publicación.

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

Tomado de este una selección de prácticas utilidades para envolver.

A pesar de que este es el mejor de los casos, vale la pena tener en cuenta una serie de factores importantes de la vida real:

  • Límites de API: nos vemos obligados a tomar datos en lotes (dormir entre solicitudes, etc.).
  • Tiempo de recopilación: para un análisis y una comparación completos, deberá reservar un tiempo considerable solo para que la araña camine por el subreddit.
  • El bot debe ejecutarse en un servidor; no puede simplemente ejecutarlo en su computadora portátil, guardarlo en su mochila y seguir con sus asuntos. Entonces ejecuté todo en un VPS. Usando el código promocional habrahabr10 puedes ahorrar otro 10% del costo.
  • La inaccesibilidad física de algunos datos (son visibles para los administradores o son demasiado difíciles de recopilar): esto debe tenerse en cuenta; en principio, no todos los datos pueden recopilarse en el tiempo adecuado.
  • Errores de red: la creación de redes es una molestia.
  • Estos son datos reales y vivos, nunca son puros.

Por supuesto, es necesario incluir estos matices en el desarrollo. Las horas/días específicos dependen de la experiencia de desarrollo o de la experiencia trabajando en tareas similares; sin embargo, vemos que aquí la tarea es puramente de ingeniería y no requiere movimientos corporales adicionales para resolverse: todo se puede evaluar, programar y realizar muy bien.

Comparación de secciones de Habr.

Pasemos a un caso más interesante y no trivial de comparar hilos y/o secciones de Habr.

Revisemos nuestra lista de verificación de complejidad: aquí, para comprender cada punto, tendrá que profundizar un poco en la tarea en sí y experimentar.

  • Al principio crees que existe una API, pero no la hay. Sí, sí, Habr tiene una API, pero simplemente no es accesible para los usuarios (o tal vez no funciona en absoluto).
  • Luego comienza a analizar html: "solicitudes de importación", ¿qué podría salir mal?
  • ¿Cómo analizar de todos modos? El enfoque más simple y utilizado con mayor frecuencia es iterar sobre los ID; tenga en cuenta que no es el más eficiente y tendrá que manejar diferentes casos; aquí se muestra un ejemplo de la densidad de ID reales entre todos los existentes.

    ¿Qué puede salir mal con la ciencia de datos? Recopilación de datos
    Tomado de este artículos

  • Los datos sin procesar envueltos en HTML en la parte superior de la web son una molestia. Por ejemplo, desea recopilar y guardar la calificación de un artículo: arrancó la calificación del html y decidió guardarla como un número para su posterior procesamiento: 

    1) int(score) arroja un error: como en Habré hay un signo menos, como, por ejemplo, en la línea “–5”, este es un guión final, no un signo menos (inesperadamente, ¿verdad?), entonces en En algún momento tuve que hacer que el analizador cobrara vida con una solución tan terrible.

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

    Es posible que no haya fecha, ventajas y desventajas (como vemos arriba en la función check_date, esto sucedió).

    2) Caracteres especiales sin escape: vendrán, debes estar preparado.

    3) La estructura cambia según el tipo de puesto.

    4) Las publicaciones antiguas pueden tener una **estructura extraña**.

  • Esencialmente, habrá que manejar el manejo de errores y lo que puede suceder o no, y no se puede predecir con certeza qué saldrá mal y de qué otra manera puede ser la estructura y qué se caerá y dónde; solo tendrá que intentarlo y tenerlo en cuenta. los errores que arroja el analizador.
  • Luego se da cuenta de que necesita analizar varios subprocesos; de lo contrario, analizar uno tomará más de 30 horas (este es simplemente el tiempo de ejecución de un analizador de un solo subproceso que ya funciona, que está inactivo y no está bajo ninguna prohibición). EN este artículo, esto llevó en algún momento a un esquema similar:

¿Qué puede salir mal con la ciencia de datos? Recopilación de datos

Lista de verificación total por complejidad:

  • Trabajo con la red y análisis html con iteración y búsqueda por ID.
  • Documentos de estructura heterogénea.
  • Hay muchos lugares donde el código puede caer fácilmente.
  • Es necesario escribir || código.
  • Falta la documentación, los ejemplos de código y/o la comunidad necesarios.

El tiempo estimado para esta tarea será de 3 a 5 veces mayor que el de recopilar datos de Reddit.

Comparación de grupos Odnoklassniki

Pasemos al caso técnicamente más interesante descrito. Para mí fue interesante precisamente porque a primera vista parece bastante trivial, pero no lo es en absoluto, tan pronto como lo tocas con un palo.

Comencemos con nuestra lista de dificultad y tengamos en cuenta que muchas de ellas resultarán mucho más difíciles de lo que parecen al principio:

  • Existe una API, pero carece casi por completo de las funciones necesarias.
  • Para determinadas funciones es necesario solicitar acceso por correo, es decir, la concesión del acceso no es instantánea.
  • Está terriblemente documentado (para empezar, los términos ruso e inglés se mezclan en todas partes y de manera completamente inconsistente; a veces solo necesitas adivinar lo que quieren de ti en alguna parte) y, además, el diseño no es adecuado para obtener datos, por ejemplo. , la función que necesitamos.
  • Requiere una sesión en la documentación, pero en realidad no la usa, y no hay forma de comprender todas las complejidades de los modos API más que husmear y esperar que algo funcione.
  • No hay ejemplos ni comunidad; el único punto de apoyo en la recolección de información es un pequeño envoltura en Python (sin muchos ejemplos de uso).
  • Selenium parece ser la opción más viable, ya que muchos de los datos necesarios están bloqueados.
    1) Es decir, la autorización se realiza a través de un usuario ficticio (y registro manual).

    2) Sin embargo, con Selenium no hay garantías de un trabajo correcto y repetible (al menos en el caso de ok.ru, seguro).

    3) El sitio web Ok.ru contiene errores de JavaScript y, a veces, se comporta de forma extraña e inconsistente.

    4) Necesitas hacer paginación, cargar elementos, etc...

    5) Los errores de API que proporciona el contenedor deberán manejarse de manera incómoda, por ejemplo, así (un fragmento 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
    

    Mi error favorito fue:

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

    6) En última instancia, Selenium + API parece la opción más racional.

  • Es necesario guardar el estado y reiniciar el sistema, manejar muchos errores, incluido el comportamiento inconsistente del sitio, y estos errores son bastante difíciles de imaginar (a menos que escriba analizadores de manera profesional, por supuesto).

El tiempo estimado condicional para esta tarea será de 3 a 5 veces mayor que el de la recopilación de datos de Habr. A pesar de que en el caso de Habr utilizamos un enfoque frontal con análisis HTML, y en el caso de OK podemos trabajar con la API en lugares críticos.

Hallazgos

No importa cuánto se requiera estimar los plazos "en el lugar" (¡lo estamos planificando hoy!) de un módulo de procesamiento de datos voluminoso, casi nunca es posible estimar el tiempo de ejecución, ni siquiera cualitativamente, sin analizar los parámetros de la tarea.

En una nota un poco más filosófica, las estrategias de estimación ágiles funcionan bien para tareas de ingeniería, pero los problemas que son más experimentales y, en cierto sentido, "creativos" y exploratorios, es decir, menos predecibles, tienen dificultades, como en los ejemplos de temas similares. que hemos comentado aquí.

Por supuesto, la recopilación de datos es sólo un buen ejemplo: suele ser una tarea increíblemente sencilla y técnicamente sencilla, y el diablo suele estar en los detalles. Y es precisamente en esta tarea que podemos mostrar toda la gama de opciones posibles sobre lo que puede salir mal y exactamente cuánto tiempo puede llevar el trabajo.

Si observa las características de la tarea sin experimentos adicionales, entonces Reddit y OK se ven similares: hay una API, un contenedor de Python, pero en esencia, la diferencia es enorme. A juzgar por estos parámetros, los pares de Habr parecen más complicados que correctos, pero en la práctica es todo lo contrario, y esto es exactamente lo que se puede descubrir realizando experimentos sencillos para analizar los parámetros del problema.

En mi experiencia, el enfoque más efectivo es estimar aproximadamente el tiempo que necesitará para el análisis preliminar en sí y los primeros experimentos simples, leyendo la documentación; esto le permitirá dar una estimación precisa de todo el trabajo. En términos de la popular metodología ágil, les pido que creen un ticket para "estimar los parámetros de la tarea", en base al cual puedo dar una evaluación de lo que se puede lograr dentro del "sprint" y dar una estimación más precisa para cada uno. tarea.

Por lo tanto, el argumento más eficaz parece ser aquel que mostraría a un especialista “no técnico” cuánto tiempo y recursos variarán dependiendo de parámetros que aún no han sido evaluados.

¿Qué puede salir mal con la ciencia de datos? Recopilación de datos

Fuente: habr.com

Añadir un comentario