ปัจจุบันมีหลักสูตร Data Science กว่า 100500 หลักสูตร และเป็นที่รู้กันมานานแล้วว่ารายได้ส่วนใหญ่ใน Data Science สามารถหาได้จากหลักสูตร Data Science (จะขุดทำไมในเมื่อคุณสามารถขายพลั่วได้) ข้อเสียเปรียบหลักของหลักสูตรเหล่านี้คือไม่เกี่ยวข้องกับงานจริง: ไม่มีใครให้ข้อมูลที่สะอาดและประมวลผลแก่คุณในรูปแบบที่ต้องการ และเมื่อคุณออกจากหลักสูตรและเริ่มแก้ไขปัญหาจริง ความแตกต่างหลายอย่างก็เกิดขึ้น
ดังนั้นเราจึงเริ่มบันทึกชุด "วิทยาศาสตร์ข้อมูลสามารถทำอะไรผิดพลาดได้" โดยอิงจากเหตุการณ์จริงที่เกิดขึ้นกับฉัน สหาย และเพื่อนร่วมงาน เราจะวิเคราะห์งาน Data Science ทั่วไปโดยใช้ตัวอย่างจริง: สิ่งนี้เกิดขึ้นได้อย่างไร มาเริ่มกันตั้งแต่วันนี้กับงานรวบรวมข้อมูล
และสิ่งแรกที่ผู้คนสะดุดเมื่อเริ่มทำงานกับข้อมูลจริงคือการรวบรวมข้อมูลที่เกี่ยวข้องกับเรามากที่สุด ข้อความสำคัญของบทความนี้:
เราประเมินเวลา ทรัพยากร และความพยายามที่จำเป็นในการรวบรวม ทำความสะอาด และจัดเตรียมข้อมูลต่ำเกินไปอย่างเป็นระบบ
และที่สำคัญที่สุดเราจะหารือกันว่าต้องทำอย่างไรเพื่อป้องกันสิ่งนี้
ตามการประมาณการต่างๆ การทำความสะอาด การแปลง การประมวลผลข้อมูล วิศวกรรมคุณลักษณะ ฯลฯ ใช้เวลา 80-90% และการวิเคราะห์ 10-20% ในขณะที่สื่อการเรียนรู้เกือบทั้งหมดมุ่งเน้นไปที่การวิเคราะห์โดยเฉพาะ
ลองดูปัญหาเชิงวิเคราะห์ง่ายๆ ในสามเวอร์ชันเป็นตัวอย่างทั่วไป และดูว่า "สถานการณ์ที่เลวร้าย" คืออะไร
และขอยกตัวอย่างอีกครั้ง เราจะพิจารณางานรวบรวมข้อมูลและเปรียบเทียบชุมชนในรูปแบบต่างๆ ที่คล้ายกันสำหรับ:
- Reddit subreddits สองอัน
- สองส่วนของ Habr
- 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 ที่มีอยู่ทั้งหมด
เอามาจากนี้ บทความ - ข้อมูลดิบที่ห่อหุ้มด้วย 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 แบบเธรดเดียวที่ใช้งานได้อยู่แล้วเท่านั้น ซึ่งจะเข้าสู่โหมดสลีปและไม่ตกอยู่ภายใต้การแบนใด ๆ ) ใน
นี้ บทความ ซึ่งนำไปสู่โครงการที่คล้ายกัน:
รายการตรวจสอบทั้งหมดตามความซับซ้อน:
- การทำงานกับเครือข่ายและการแยกวิเคราะห์ 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 ที่ได้รับความนิยม ฉันขอให้คุณสร้างตั๋วสำหรับ "การประมาณค่าพารามิเตอร์ของงาน" โดยฉันสามารถประเมินสิ่งที่สามารถทำได้สำเร็จภายใน "การวิ่ง" และให้การประมาณค่าที่แม่นยำยิ่งขึ้นสำหรับแต่ละรายการ งาน.
ดังนั้น ข้อโต้แย้งที่มีประสิทธิผลมากที่สุดน่าจะเป็นข้อโต้แย้งที่จะแสดงให้ผู้เชี่ยวชาญที่ "ไม่ใช่ด้านเทคนิค" เห็นว่าเวลาและทรัพยากรจะแตกต่างกันไปขึ้นอยู่กับพารามิเตอร์ที่ยังไม่ได้ประเมิน
ที่มา: will.com