มีอะไรผิดพลาดกับ Data Science บ้าง? การเก็บรวบรวมข้อมูล

มีอะไรผิดพลาดกับ Data Science บ้าง? การเก็บรวบรวมข้อมูล
ปัจจุบันมีหลักสูตร Data Science กว่า 100500 หลักสูตร และเป็นที่รู้กันมานานแล้วว่ารายได้ส่วนใหญ่ใน Data Science สามารถหาได้จากหลักสูตร Data Science (จะขุดทำไมในเมื่อคุณสามารถขายพลั่วได้) ข้อเสียเปรียบหลักของหลักสูตรเหล่านี้คือไม่เกี่ยวข้องกับงานจริง: ไม่มีใครให้ข้อมูลที่สะอาดและประมวลผลแก่คุณในรูปแบบที่ต้องการ และเมื่อคุณออกจากหลักสูตรและเริ่มแก้ไขปัญหาจริง ความแตกต่างหลายอย่างก็เกิดขึ้น

ดังนั้นเราจึงเริ่มบันทึกชุด "วิทยาศาสตร์ข้อมูลสามารถทำอะไรผิดพลาดได้" โดยอิงจากเหตุการณ์จริงที่เกิดขึ้นกับฉัน สหาย และเพื่อนร่วมงาน เราจะวิเคราะห์งาน Data Science ทั่วไปโดยใช้ตัวอย่างจริง: สิ่งนี้เกิดขึ้นได้อย่างไร มาเริ่มกันตั้งแต่วันนี้กับงานรวบรวมข้อมูล

และสิ่งแรกที่ผู้คนสะดุดเมื่อเริ่มทำงานกับข้อมูลจริงคือการรวบรวมข้อมูลที่เกี่ยวข้องกับเรามากที่สุด ข้อความสำคัญของบทความนี้:

เราประเมินเวลา ทรัพยากร และความพยายามที่จำเป็นในการรวบรวม ทำความสะอาด และจัดเตรียมข้อมูลต่ำเกินไปอย่างเป็นระบบ

และที่สำคัญที่สุดเราจะหารือกันว่าต้องทำอย่างไรเพื่อป้องกันสิ่งนี้

ตามการประมาณการต่างๆ การทำความสะอาด การแปลง การประมวลผลข้อมูล วิศวกรรมคุณลักษณะ ฯลฯ ใช้เวลา 80-90% และการวิเคราะห์ 10-20% ในขณะที่สื่อการเรียนรู้เกือบทั้งหมดมุ่งเน้นไปที่การวิเคราะห์โดยเฉพาะ

ลองดูปัญหาเชิงวิเคราะห์ง่ายๆ ในสามเวอร์ชันเป็นตัวอย่างทั่วไป และดูว่า "สถานการณ์ที่เลวร้าย" คืออะไร

และขอยกตัวอย่างอีกครั้ง เราจะพิจารณางานรวบรวมข้อมูลและเปรียบเทียบชุมชนในรูปแบบต่างๆ ที่คล้ายกันสำหรับ:

  1. Reddit subreddits สองอัน
  2. สองส่วนของ Habr
  3. Odnoklassniki สองกลุ่ม

แนวทางแบบมีเงื่อนไขในทางทฤษฎี

เปิดไซต์และอ่านตัวอย่าง หากชัดเจน ให้เผื่อเวลาไว้สองสามชั่วโมงในการอ่าน สองสามชั่วโมงสำหรับโค้ดโดยใช้ตัวอย่างและการแก้ไขจุดบกพร่อง เพิ่มสองสามชั่วโมงสำหรับการรวบรวม สำรองไว้สักสองสามชั่วโมง (คูณสองและเพิ่ม N ชั่วโมง)

ประเด็นสำคัญ: การประมาณเวลาขึ้นอยู่กับสมมติฐานและการคาดเดาว่าจะใช้เวลานานแค่ไหน

คุณต้องเริ่มการวิเคราะห์เวลาโดยการประมาณค่าพารามิเตอร์ต่อไปนี้สำหรับปัญหาตามเงื่อนไขที่อธิบายไว้ข้างต้น:

  • ข้อมูลมีขนาดเท่าใดและจำเป็นต้องรวบรวมทางกายภาพเป็นจำนวนเท่าใด (*ดูด้านล่าง*)
  • เวลาในการรวบรวมสำหรับหนึ่งบันทึกคือเท่าใด และคุณต้องรอนานเท่าใดจึงจะสามารถรวบรวมบันทึกที่สองได้
  • ลองเขียนโค้ดที่บันทึกสถานะและเริ่มการรีสตาร์ทเมื่อ (ไม่ใช่ถ้า) ทุกอย่างล้มเหลว
  • พิจารณาว่าเราจำเป็นต้องได้รับอนุญาตหรือไม่ และกำหนดเวลาในการเข้าถึงผ่าน API
  • ตั้งค่าจำนวนข้อผิดพลาดตามฟังก์ชันความซับซ้อนของข้อมูล - ประเมินสำหรับงานเฉพาะ เช่น โครงสร้าง จำนวนการแปลง อะไรและจะแยกออกมาอย่างไร
  • แก้ไขข้อผิดพลาดของเครือข่ายและปัญหาเกี่ยวกับพฤติกรรมของโปรเจ็กต์ที่ไม่ได้มาตรฐาน
  • ประเมินว่าฟังก์ชันที่จำเป็นอยู่ในเอกสารประกอบหรือไม่ และถ้าไม่มี จะต้องทำอย่างไรและมากน้อยเพียงใดในการแก้ไขปัญหาเบื้องต้น

สิ่งที่สำคัญที่สุดคือในการประมาณเวลา - คุณต้องใช้เวลาและความพยายามใน "กำลังลาดตระเวน" - เมื่อนั้นการวางแผนของคุณจึงจะเพียงพอ ดังนั้นไม่ว่าคุณจะถูกกดดันให้พูดว่า "ใช้เวลานานเท่าใดในการรวบรวมข้อมูล" - ซื้อเวลาให้ตัวเองเพื่อการวิเคราะห์เบื้องต้นและโต้แย้งว่าเวลาจะแตกต่างกันมากน้อยเพียงใดขึ้นอยู่กับพารามิเตอร์ที่แท้จริงของปัญหา

และตอนนี้เราจะสาธิตตัวอย่างเฉพาะที่พารามิเตอร์ดังกล่าวจะเปลี่ยนไป

ประเด็นสำคัญ: การประมาณการขึ้นอยู่กับการวิเคราะห์ปัจจัยสำคัญที่มีอิทธิพลต่อขอบเขตและความซับซ้อนของงาน

การประมาณค่าโดยใช้การคาดเดาเป็นแนวทางที่ดีเมื่อองค์ประกอบการทำงานมีขนาดเล็กเพียงพอ และมีปัจจัยไม่มากนักที่จะส่งผลต่อการออกแบบปัญหาได้อย่างมีนัยสำคัญ แต่ในกรณีที่เกิดปัญหา Data Science หลายประการ ปัจจัยดังกล่าวมีมากมายมหาศาลและวิธีการดังกล่าวไม่เพียงพอ

การเปรียบเทียบชุมชน Reddit

เริ่มจากกรณีที่ง่ายที่สุดกันก่อน (ตามที่ปรากฎในภายหลัง) โดยทั่วไป พูดตามตรง เรามีกรณีที่เกือบจะสมบูรณ์แบบ มาตรวจสอบรายการตรวจสอบความซับซ้อนของเรากัน:

  • มี API ที่ชัดเจน เข้าใจได้ และมีเอกสารประกอบ
  • มันง่ายมากและที่สำคัญที่สุดคือได้รับโทเค็นโดยอัตโนมัติ
  • มี เสื้อคลุมหลาม - พร้อมตัวอย่างมากมาย
  • ชุมชนที่วิเคราะห์และรวบรวมข้อมูลบน Reddit (แม้แต่วิดีโอ YouTube ที่อธิบายวิธีใช้ Python Wrapper) ตัวอย่างเช่น.
  • วิธีการที่เราต้องการมากที่สุดนั้นมีอยู่ใน API นอกจากนี้โค้ดยังดูกะทัดรัดและสะอาดตา ด้านล่างนี้เป็นตัวอย่างของฟังก์ชันที่รวบรวมความคิดเห็นในโพสต์

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

เอามาจาก นี้ ยูทิลิตี้ให้เลือกมากมายสำหรับการห่อ

แม้ว่านี่จะเป็นกรณีที่ดีที่สุด แต่ก็ยังคุ้มค่าที่จะคำนึงถึงปัจจัยสำคัญหลายประการจากชีวิตจริง:

  • ขีดจำกัด API - เราถูกบังคับให้รับข้อมูลเป็นชุด (สลีประหว่างคำขอ ฯลฯ)
  • เวลาในการรวบรวม - เพื่อการวิเคราะห์และการเปรียบเทียบที่สมบูรณ์ คุณจะต้องจัดสรรเวลาที่สำคัญเพื่อให้แมงมุมเดินผ่าน subreddit
  • บอทจะต้องทำงานบนเซิร์ฟเวอร์ คุณไม่สามารถรันมันบนแล็ปท็อปของคุณ ใส่มันไว้ในกระเป๋าเป้สะพายหลัง และดำเนินธุรกิจของคุณได้ ดังนั้นฉันจึงรันทุกอย่างบน VPS การใช้รหัสส่งเสริมการขาย habrahabr10 คุณสามารถประหยัดได้อีก 10% ของค่าใช้จ่าย
  • ความไม่สามารถเข้าถึงได้ทางกายภาพของข้อมูลบางอย่าง (ผู้ดูแลระบบมองเห็นได้หรือยากเกินไปที่จะรวบรวม) - ต้องคำนึงถึงสิ่งนี้ โดยหลักการแล้ว ไม่สามารถรวบรวมข้อมูลทั้งหมดได้ในเวลาที่เหมาะสม
  • ข้อผิดพลาดของเครือข่าย: เครือข่ายเป็นเรื่องที่เจ็บปวด
  • นี่คือข้อมูลจริงที่มีชีวิต - มันไม่เคยบริสุทธิ์เลย

แน่นอนว่าจำเป็นต้องรวมความแตกต่างเหล่านี้ไว้ในการพัฒนา ชั่วโมง/วันที่เจาะจงขึ้นอยู่กับประสบการณ์การพัฒนาหรือประสบการณ์ในการทำงานที่คล้ายคลึงกัน อย่างไรก็ตาม เราเห็นว่างานนี้เป็นงานทางวิศวกรรมล้วนๆ และไม่ต้องใช้การเคลื่อนไหวร่างกายเพิ่มเติมเพื่อแก้ไข ทุกอย่างสามารถประเมิน กำหนดเวลา และดำเนินการได้อย่างดี

การเปรียบเทียบส่วน Habr

เรามาดูกรณีที่น่าสนใจและไม่สำคัญในการเปรียบเทียบเธรดและ/หรือส่วนของ Habr กันดีกว่า

มาตรวจสอบรายการตรวจสอบความซับซ้อนของเรากัน - เพื่อทำความเข้าใจแต่ละประเด็น คุณจะต้องเจาะลึกงานและทดลองเล็กน้อยที่นี่

  • ตอนแรกคุณคิดว่ามี API แต่ไม่มี ใช่ ใช่ Habr มี API แต่ผู้ใช้ไม่สามารถเข้าถึงได้ (หรืออาจจะไม่ทำงานเลย)
  • ถ้าอย่างนั้นคุณก็เริ่มแยกวิเคราะห์ html - "คำขอนำเข้า" มีอะไรผิดพลาดไปบ้าง?
  • จะแยกวิเคราะห์อย่างไร? วิธีที่ง่ายที่สุดและใช้บ่อยที่สุดคือการวนซ้ำ ID โปรดทราบว่าวิธีนี้ไม่ได้มีประสิทธิภาพมากที่สุดและจะต้องจัดการกับกรณีต่างๆ ต่อไปนี้คือตัวอย่างความหนาแน่นของ ID จริงจาก ID ที่มีอยู่ทั้งหมด

    มีอะไรผิดพลาดกับ Data Science บ้าง? การเก็บรวบรวมข้อมูล
    เอามาจาก นี้ บทความ

  • ข้อมูลดิบที่ห่อหุ้มด้วย HTML บนเว็บถือเป็นเรื่องยุ่งยาก ตัวอย่างเช่น คุณต้องการรวบรวมและบันทึกการให้คะแนนของบทความ: คุณฉีกคะแนนออกจาก html และตัดสินใจบันทึกเป็นตัวเลขเพื่อการประมวลผลต่อไป: 

    1) int(score) ส่งข้อผิดพลาด: เนื่องจากในHabréมีเครื่องหมายลบเช่นในบรรทัด "–5" - นี่คือเครื่องหมายขีดกลางไม่ใช่เครื่องหมายลบ (โดยไม่คาดคิดใช่ไหม?) ดังนั้นที่ บางจุดฉันต้องทำให้ parser มีชีวิตขึ้นมาด้วยการแก้ไขที่แย่มาก

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

    อาจไม่มีวัน ข้อดีและข้อเสียเลย (ดังที่เราเห็นด้านบนในฟังก์ชัน check_date สิ่งนี้เกิดขึ้น)

    2) อักขระพิเศษที่ไม่ได้ใช้ Escape - พวกมันจะมา คุณต้องเตรียมตัวให้พร้อม

    3) โครงสร้างเปลี่ยนแปลงไปตามประเภทของโพสต์

    4) โพสต์เก่าอาจมี **โครงสร้างแปลกๆ**

  • โดยพื้นฐานแล้ว การจัดการข้อผิดพลาดและสิ่งที่อาจเกิดขึ้นหรือไม่เกิดขึ้นจะต้องได้รับการจัดการ และคุณไม่สามารถคาดเดาได้อย่างแน่นอนว่าอะไรจะผิดพลาด และโครงสร้างจะเป็นอย่างไร และอะไรจะหลุดจากจุดไหน คุณเพียงแค่ต้องพยายามและคำนึงถึง ข้อผิดพลาดที่ parser พ่น
  • จากนั้นคุณจะรู้ว่าคุณต้องแยกวิเคราะห์หลายเธรด ไม่เช่นนั้นการแยกวิเคราะห์ในเธรดเดียวจะใช้เวลามากกว่า 30 ชั่วโมง (นี่เป็นเวลาดำเนินการของ parser แบบเธรดเดียวที่ใช้งานได้อยู่แล้วเท่านั้น ซึ่งจะเข้าสู่โหมดสลีปและไม่ตกอยู่ภายใต้การแบนใด ๆ ) ใน นี้ บทความ ซึ่งนำไปสู่โครงการที่คล้ายกัน:

มีอะไรผิดพลาดกับ Data Science บ้าง? การเก็บรวบรวมข้อมูล

รายการตรวจสอบทั้งหมดตามความซับซ้อน:

  • การทำงานกับเครือข่ายและการแยกวิเคราะห์ html ด้วยการวนซ้ำและค้นหาด้วย ID
  • เอกสารโครงสร้างต่างกัน
  • มีหลายจุดที่โค้ดตกได้ง่าย
  • จำเป็นต้องเขียน || รหัส.
  • เอกสารที่จำเป็น ตัวอย่างโค้ด และ/หรือชุมชนขาดหายไป

เวลาโดยประมาณสำหรับภารกิจนี้จะสูงกว่าการรวบรวมข้อมูลจาก Reddit ถึง 3-5 เท่า

การเปรียบเทียบกลุ่ม Odnoklassniki

เรามาดูกรณีที่น่าสนใจทางเทคนิคที่สุดที่อธิบายไว้กันดีกว่า สำหรับฉันมันน่าสนใจมากเพราะเมื่อมองแวบแรกมันดูค่อนข้างไม่สำคัญ แต่มันก็ไม่ได้เป็นอย่างนั้นเลย - ทันทีที่คุณจิ้มมัน

มาเริ่มกันที่รายการตรวจสอบความยากของเราและสังเกตว่าหลายรายการจะกลายเป็นเรื่องยากมากกว่าที่เห็นในตอนแรก:

  • มี API แต่ขาดฟังก์ชันที่จำเป็นเกือบทั้งหมด
  • สำหรับฟังก์ชันบางอย่าง คุณต้องขอการเข้าถึงทางไปรษณีย์ นั่นคือ การให้สิทธิ์การเข้าถึงไม่ได้เกิดขึ้นทันที
  • มีการบันทึกไว้อย่างมาก (เริ่มต้นด้วยคำศัพท์ภาษารัสเซียและภาษาอังกฤษผสมกันทุกที่และไม่สอดคล้องกันโดยสิ้นเชิง - บางครั้งคุณเพียงแค่ต้องเดาสิ่งที่พวกเขาต้องการจากที่ไหนสักแห่ง) และยิ่งกว่านั้นการออกแบบไม่เหมาะสำหรับการรับข้อมูลเช่น , ฟังก์ชั่นที่เราต้องการ.
  • ต้องมีเซสชันในเอกสารประกอบ แต่ไม่ได้ใช้จริง - และไม่มีวิธีใดที่จะเข้าใจความซับซ้อนทั้งหมดของโหมด API นอกเหนือจากการแหย่และหวังว่าบางสิ่งจะได้ผล
  • ไม่มีตัวอย่างและไม่มีชุมชนจุดเดียวที่สนับสนุนในการรวบรวมข้อมูลมีขนาดเล็ก เสื้อคลุม ใน Python (ไม่มีตัวอย่างการใช้งานมากมาย)
  • ซีลีเนียมดูเหมือนจะเป็นตัวเลือกที่ใช้งานได้ดีที่สุด เนื่องจากข้อมูลที่จำเป็นจำนวนมากถูกล็อคไว้
    1) นั่นคือการอนุญาตเกิดขึ้นผ่านผู้ใช้สมมติ (และการลงทะเบียนด้วยมือ)

    2) อย่างไรก็ตาม Selenium ไม่มีการรับประกันสำหรับงานที่ถูกต้องและทำซ้ำได้ (อย่างน้อยก็ในกรณีของ ok.ru แน่นอน)

    3) เว็บไซต์ Ok.ru มีข้อผิดพลาดของ JavaScript และบางครั้งก็มีพฤติกรรมแปลก ๆ และไม่สอดคล้องกัน

    4) คุณต้องแบ่งหน้า โหลดองค์ประกอบ ฯลฯ...

    5) ข้อผิดพลาด API ที่ wrapper ให้จะต้องได้รับการจัดการอย่างเชื่องช้า เช่น นี้ (โค้ดทดลองชิ้นหนึ่ง):

    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
    

    ข้อผิดพลาดที่ฉันชอบคือ:

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

    6) ท้ายที่สุดแล้ว Selenium + API ดูเหมือนตัวเลือกที่สมเหตุสมผลที่สุด

  • จำเป็นต้องบันทึกสถานะและรีสตาร์ทระบบ จัดการกับข้อผิดพลาดมากมาย รวมถึงพฤติกรรมที่ไม่สอดคล้องกันของไซต์ - และข้อผิดพลาดเหล่านี้ค่อนข้างยากที่จะจินตนาการได้ (เว้นแต่คุณจะเขียน parsers อย่างมืออาชีพ)

การประมาณการเวลาแบบมีเงื่อนไขสำหรับภารกิจนี้จะสูงกว่าการรวบรวมข้อมูลจาก Habr ถึง 3-5 เท่า แม้ว่าในกรณีของ Habr เราจะใช้วิธีการส่วนหน้าด้วยการแยกวิเคราะห์ HTML และในกรณีของ OK เราสามารถทำงานกับ API ในจุดวิกฤตได้

ผลการวิจัย

ไม่ว่าคุณจะต้องประมาณกำหนดเวลา "ตรงจุด" มากเพียงใด (เรากำลังวางแผนในวันนี้!) ของโมดูลไปป์ไลน์การประมวลผลข้อมูลขนาดใหญ่ เวลาในการดำเนินการแทบจะเป็นไปไม่ได้เลยที่จะประมาณในเชิงคุณภาพ โดยไม่ต้องวิเคราะห์พารามิเตอร์งาน

ในบันทึกเชิงปรัชญาที่มากกว่าเล็กน้อย กลยุทธ์การประมาณค่าแบบคล่องตัวทำงานได้ดีสำหรับงานวิศวกรรม แต่ปัญหาที่เป็นการทดลองมากกว่าและในแง่หนึ่ง "สร้างสรรค์" และเชิงสำรวจ เช่น คาดเดาได้น้อยกว่า จะมีปัญหาดังเช่นในตัวอย่างของหัวข้อที่คล้ายกัน , ซึ่งเราได้พูดคุยกันที่นี่

แน่นอนว่าการรวบรวมข้อมูลเป็นเพียงตัวอย่างเท่านั้น งานมักจะดูเรียบง่ายอย่างไม่น่าเชื่อและไม่ซับซ้อนในทางเทคนิค และปีศาจมักจะอยู่ในรายละเอียด และในงานนี้เองที่เราสามารถแสดงตัวเลือกที่เป็นไปได้ทั้งหมดสำหรับสิ่งที่อาจผิดพลาดและระยะเวลาที่งานอาจใช้เวลานาน

หากคุณดูลักษณะของงานโดยไม่มีการทดลองเพิ่มเติม Reddit และ OK ก็ดูคล้ายกัน: มี API ที่เป็น Python Wrapper แต่โดยพื้นฐานแล้วความแตกต่างนั้นใหญ่มาก เมื่อพิจารณาจากพารามิเตอร์เหล่านี้ พาร์ของ Habr ดูซับซ้อนกว่าตกลง - แต่ในทางปฏิบัติมันค่อนข้างตรงกันข้ามและนี่คือสิ่งที่สามารถพบได้โดยทำการทดลองง่าย ๆ เพื่อวิเคราะห์พารามิเตอร์ของปัญหา

จากประสบการณ์ของผม วิธีการที่มีประสิทธิภาพมากที่สุดคือการประมาณเวลาโดยประมาณที่คุณต้องการสำหรับการวิเคราะห์เบื้องต้นและการทดลองเบื้องต้นแบบง่ายๆ โดยการอ่านเอกสารประกอบ ซึ่งจะช่วยให้คุณประมาณค่างานทั้งหมดได้อย่างแม่นยำ ในแง่ของวิธีการแบบ Agile ที่ได้รับความนิยม ฉันขอให้คุณสร้างตั๋วสำหรับ "การประมาณค่าพารามิเตอร์ของงาน" โดยฉันสามารถประเมินสิ่งที่สามารถทำได้สำเร็จภายใน "การวิ่ง" และให้การประมาณค่าที่แม่นยำยิ่งขึ้นสำหรับแต่ละรายการ งาน.

ดังนั้น ข้อโต้แย้งที่มีประสิทธิผลมากที่สุดน่าจะเป็นข้อโต้แย้งที่จะแสดงให้ผู้เชี่ยวชาญที่ "ไม่ใช่ด้านเทคนิค" เห็นว่าเวลาและทรัพยากรจะแตกต่างกันไปขึ้นอยู่กับพารามิเตอร์ที่ยังไม่ได้ประเมิน

มีอะไรผิดพลาดกับ Data Science บ้าง? การเก็บรวบรวมข้อมูล

ที่มา: will.com

เพิ่มความคิดเห็น