راهنمای مفاهیم

قصهٔ جست‌وجویی که هنوز اتفاق نیفتاده

هر اصطلاحی که در گزارش فنی و ارائه به کار رفته، اینجا از پایه و با زبان ساده توضیح داده شده است. یک‌بار از اول تا آخر بخوانید؛ بعد از آن به‌عنوان واژه‌نامه استفاده‌اش کنید.

شب سی‌ام آبان است. در آپارتمانی در تهران، چهار نفر دور میز نشسته‌اند و دربارهٔ یلدا حرف می‌زنند. هنوز هیچ‌کس گوشی‌اش را برنداشته. هیچ جست‌وجویی ثبت نشده. برای پایگاه دادهٔ ما، این خانواده امشب وجود ندارد.

هجده روز بعد، ساعت یازده‌ونیم شب، یکی از همان چهار نفر در رختخواب گوشی را برمی‌دارد و می‌نویسد: «ویلا چالوس». چند دقیقه بعد خواهرش هم همین کار را می‌کند. دو جست‌وجو ثبت می‌شود، هر دو برای شب بیست‌وهشتم آذر.

مسئلهٔ ما این است: همین امشب، سی‌ام آبان، باید بگوییم برای شب بیست‌وهشتم آذر در چالوس چند جست‌وجو انجام خواهد شد. درحالی‌که آن دو جست‌وجو هنوز به ذهن کسی هم خطور نکرده.

و این تمام ماجراست: ما یک عدد را پیش‌بینی نمی‌کنیم که بعداً معلوم شود. عددی را پیش‌بینی می‌کنیم که در حال ساخته‌شدن است — و بخشی از آن، همین حالا، در دست ماست.

۱دو تاریخ در هر جست‌وجو

قبل از هر مدلی، باید یک چیز را دید: هر ردیف داده دو تاریخ دارد، نه یکی.

تشبیه

بلیت قطار را در نظر بگیرید. یک تاریخ روی بلیت هست — روزی که سوار می‌شوید. و یک تاریخ دیگر هم هست که روی بلیت چاپ نمی‌شود ولی وجود دارد: روزی که بلیت را خریدید. این دو با هم فرق دارند، و فاصله‌شان معنا دارد.

در داده‌های ما هر جست‌وجو دقیقاً همین دو تاریخ را دارد:

ستونیعنی چهمثال ما
log_dateروزی که کاربر جست‌وجو کرد۱۸ آذر
checkinشبی که می‌خواهد اقامت کند۲۸ آذر
leadفاصلهٔ این دو، به روز۱۰ روز

ستون سوم را ما ساختیم، ولی مهم‌ترین ستون کل پروژه است. به آن lead time یا «فاصلهٔ تا اقامت» می‌گوییم.

تعریف

تقاضا در این مسئله یعنی: برای یک زوج مشخصِ (شهر، شب اقامت)، مجموع همهٔ جست‌وجوهایی که در تمام روزها برای آن انجام شده. یعنی تقاضای شب ۲۸ آذر تا خودِ ۲۸ آذر همچنان در حال زیاد شدن است.

این تعریف جاییست که بیشتر تیم‌ها اشتباه می‌کنند. اگر داده را «چند جست‌وجو در هر روز» ببینید، دارید چیز دیگری را مدل می‌کنید. تقاضا یک جمع است روی یک پنجرهٔ باز، نه یک شمارش در یک روز.

یک کشف ساختاری

وقتی توزیع lead را در دو سال داده حساب کردیم، معلوم شد هیچ‌کس بیشتر از ۵۹ روز قبل جست‌وجو نمی‌کند. هیچ ماهی، هیچ شهری، هیچ استثنایی. این یعنی پنجرهٔ جست‌وجو دقیقاً ۶۰ روز است و بسته است — و همین است که کل کار را ممکن می‌کند.

۲مثلث تأخیر

وقتی دو محور زمانی دارید، داده شکل مثلث پیدا می‌کند. و مثلث یعنی: بخشی را می‌بینید، بخشی را نه.

بیایید برای یک شب مشخص — مثلاً ۲۸ آذر — همهٔ جست‌وجوهایش را روی یک خط بچینیم، از دورترین (۵۹ روز قبل) تا نزدیک‌ترین (خودِ همان روز). حالا ما در ۳۰ آبان ایستاده‌ایم، یعنی ۲۸ روز مانده به آن شب.

جست‌وجوهایی که leadشان بیشتر از ۲۸ است، قبلاً اتفاق افتاده‌اند و در فایل ما هستند. جست‌وجوهایی که lead کمتری دارند، هنوز نیامده‌اند. برای هر شبِ آذر همین اتفاق می‌افتد، ولی با برش متفاوت — و وقتی همهٔ شب‌ها را کنار هم بگذارید، یک مثلث می‌بینید.

تشبیه

شرکت بیمه را تصور کنید. تصادف امروز اتفاق افتاده، ولی پرونده‌اش شاید سه ماه دیگر به دست شرکت برسد. شرکت باید همین امروز بگوید امسال چقدر خسارت خواهد داد — درحالی‌که بخشی از پرونده‌ها هنوز نرسیده‌اند. اسم این مسئله در بیمه IBNR است: خسارتِ رخ‌داده ولی گزارش‌نشده. مسئلهٔ ما دقیقاً همان است، فقط به‌جای خسارت، جست‌وجو.

تقاضای نهایی  =  P  +  RP: آنچه تا امروز ثبت شده  ·  R: آنچه هنوز نیامده
تعریف

P (partial) یعنی بخش محقق‌شده. این عدد را دقیقاً می‌دانیم؛ همان چیزی است که در فایل evaluation.csv به ما داده‌اند. هیچ مدلی نمی‌تواند بهترش کند و نباید هم تلاش کند.

R (remainder) یعنی باقی‌مانده. تنها چیزی که واقعاً مجهول است، و تنها چیزی که ما مدل می‌کنیم.

وقتی همین ساختار را روی آذر پارسال آزمودیم، عدد درآمد: در روز پیش‌بینی، ۲۹٫۸٪ تقاضا از قبل معلوم بود و ۷۰٫۲٪ هنوز نیامده بود. یعنی صرفاً با همین تقسیم‌بندی، یک‌سوم مسئله قبل از هر محاسبه‌ای حل می‌شود.

یک نتیجهٔ جانبی مهم: چون P یک واقعیت ثبت‌شده است، پیش‌بینی ما هرگز نباید از P کمتر باشد. این یک کف سخت است که در کد اعمال می‌شود.

۳منحنی تکمیل

اگر بدانیم «معمولاً چند درصد تقاضا تا این فاصله آمده»، می‌توانیم از بخش دیده‌شده کل را حدس بزنیم.

تشبیه

لیوانی را زیر شیر آب گذاشته‌اید. اگر بدانید معمولاً بعد از ده ثانیه لیوان یک‌سوم پر می‌شود، و الان یک‌سوم پر است، می‌توانید حدس بزنید لیوان در نهایت چقدر پر خواهد شد. منحنی تکمیل همان «معمولاً بعد از ده ثانیه یک‌سوم» است.

تعریف

منحنی تکمیل (completion curve) برای هر شهر و هر فاصله می‌گوید: به‌طور معمول چند درصد تقاضای آن شب، وقتی این‌قدر روز مانده، از قبل ثبت شده است. اگر این عدد را f بنامیم، ساده‌ترین برآورد این است: تقاضای نهایی ≈ P ÷ f

چرا برای هر شهر جدا؟

چون سرعت تصمیم‌گیری مردم برای شهرهای مختلف فرق دارد. و این تفاوت تصادفی نیست — به انگیزهٔ سفر برمی‌گردد:

شهر۳۰ روز مانده، چند درصد تقاضا آمده؟چرا
کیش۴۳٪بلیت هواپیما، سفر بلند، برنامه‌ریزی زودهنگام
قشم۳۹٪همین‌طور
مشهد۳۶٪سفر زیارتی، معمولاً برنامه‌ریزی‌شده
چالوس۲۲٪دو ساعت راه، تصمیم چهارشنبه‌شب
کردان۲۲٪ویلای دم‌دستی، لحظهٔ آخر

یعنی وقتی برای کیش پیش‌بینی می‌کنیم، تقریباً نصف جواب در دستمان است. برای چالوس فقط یک‌پنجم. به همین دلیل هم دقت مدل روی کیش و قشم بهتر از چالوس است — و این یک ضعف مدل نیست، ویژگی خودِ مسئله است.

تعریف

chain-ladder نام همین روش در بیمه است: از بخش دیده‌شده و یک ضریب تاریخی، کل را برآورد می‌کنند. ما همان را با ضریب مخصوص هر شهر به کار برده‌ایم.

تعریف

shrinkage (جمع‌کردن به سمت میانگین) یعنی: برای شهر کوچکی که داده‌اش کم و پر نوسان است، به‌جای منحنی خودش، ترکیبی از منحنی خودش و منحنی گروهش را به کار می‌بریم. هرچه داده بیشتر، وزن منحنی خودش بیشتر. این جلوی نویز را می‌گیرد.

۴معیار WAPE

معیاری که با آن نمره می‌گیریم، شکل مدل را تعیین می‌کند — نه برعکس.

WAPE = مجموع |خطا| ÷ مجموع تقاضای واقعیهرچه کمتر، بهتر

یعنی همهٔ خطاها را بدون علامت جمع می‌کنیم و بر کل تقاضا تقسیم می‌کنیم. عدد ۰٫۱۸ یعنی «مجموع خطاهای ما ۱۸٪ کل تقاضاست».

یک نکته که همه‌چیز را عوض می‌کند

چون مخرج ثابت است، کم‌کردن WAPE یعنی کم‌کردن مجموع قدرمطلق خطا. و این با کم‌کردن مجموع مربع خطا فرق دارد.

تشبیه

ده نفر در اتاق‌اند: نُه نفر ۱۰ تومان دارند و یک نفر ۱۰۰۰ تومان. میانگین پولشان ۱۰۹ تومان است — عددی که هیچ‌کس ندارد. میانهشان ۱۰ تومان است. حالا اگر بخواهید یک عدد بگویید که مجموع فاصله‌اش از همه کمترین باشد، جواب میانه است، نه میانگین.

تعریف

بهینهٔ WAPE میانهٔ شرطی است، نه میانگین. توزیع تقاضا هم شدیداً چوله‌به‌راست است (چند شهر خیلی بزرگ، خیلی شهر کوچک). پس میانه پایین‌تر از میانگین می‌افتد و مدلِ درست، طبیعتاً کمی «کم‌بین» است.

این توضیح می‌دهد چرا مدل ما در همهٔ فولدهای ۱۴۰۴ کمی کم می‌زند و چرا تصحیحش را — بعد از آزمایش — انجام ندادیم. جزئیاتش در فصل ۷.

نتیجهٔ عملی دوم

چون مخرج یکی است، سهم هر شهر در نمره به اندازهٔ حجمش است. بیست شهر اول ۷۹٪ کل جست‌وجوها را دارند و ۱۲۱ شهر آخر روی‌هم کمتر از ۰٫۰۳٪. پس خطای مطلق روی تهران هزار برابر مهم‌تر از خطای نسبی روی یک روستاست.

۵بک‌تست و نشت اطلاعات

چطور بفهمیم مدل واقعاً کار می‌کند، وقتی جواب واقعی هنوز وجود ندارد؟

فایل evaluation.csv وسوسه‌انگیز است: به نظر می‌رسد «جواب» است. ولی نیست. آن فایل فقط همان ۳۰٪ محقق‌شده است، نه تقاضای نهایی. اگر مدل را با آن بسنجیم، مدلی برنده می‌شود که ۳۰٪ واقعیت را خوب بزند.

تشبیه

برای امتحان درس می‌خوانید. اگر خودتان را با سؤال‌هایی محک بزنید که جوابشان را از قبل دیده‌اید، نمرهٔ تمرینتان عالی می‌شود و نمرهٔ امتحان افتضاح. باید با سؤال‌هایی تمرین کنید که ندیده‌اید.

راه‌حل: بازپخش تاریخ

ما دو سال داده داریم و برای گذشته می‌دانیم تقاضای نهایی چه شد. پس می‌رویم عقب، در یک تاریخ گذشته می‌ایستیم، وانمود می‌کنیم فقط همان‌قدر داده داریم، ۳۰ روز بعد را پیش‌بینی می‌کنیم، و با حقیقتِ معلوم مقایسه می‌کنیم.

اصطلاحمعنی ساده
fold — فولدیک «تمرین» کامل: یک تاریخ مبدأ، ۳۰ روز افق، و جواب معلوم. ما ۱۰۰ فولد ساختیم.
as-of date — تاریخ مبدأروزی که وانمود می‌کنیم امروز است. بعد از آن هیچ داده‌ای نمی‌بینیم.
held-out — کنارگذاشته‌شدهفولدی که مدل هرگز روی آن آموزش ندیده و فقط برای نمره‌دادن استفاده می‌شود.
rolling origin — مبدأ متحرکهمین کار را در چند تاریخ مختلف تکرار کنیم تا نمره به یک ماه خاص وابسته نباشد.
تعریف

نشت اطلاعات (leakage) یعنی به مدل، آگاهانه یا ناآگاهانه، اطلاعاتی برسد که در زمان واقعی در دسترس نبوده. نتیجه‌اش نمرهٔ تمرینِ عالی و عملکرد واقعیِ بد است.

قانون ما ساده و بی‌استثناست: یک فولد فقط وقتی می‌تواند برای آموزش استفاده شود که کل پنجرهٔ ۳۰ روزه‌اش قبل از تاریخ مبدأِ فولدِ در حال نمره‌دهی بسته شده باشد. همین یک قانون است که باعث می‌شود اعداد گزارش معنا داشته باشند.

۶ویژگی و مدل

مدل چه چیزهایی می‌بیند، و چطور از آن‌ها به عدد می‌رسد.

تعریف

ویژگی (feature) هر عددی است که به مدل می‌دهیم تا از رویش تصمیم بگیرد. مثل «چند روز مانده»، «پارسال همین شب چقدر بود»، «فردا تعطیل است یا نه».

مدل ما حدود ۶۰ ویژگی می‌بیند، در پنج خانواده:

خانوادهنمونهچه چیزی را می‌گوید
بخش محقق‌شدهP، جست‌وجوهای ۷ روز اخیر همین زوجاین شب الان چقدر داغ است
فعالیت شهرکل جست‌وجوهای شهر در ۲۸ روز اخیرخودِ شهر الان در چه سطحی است
پارسالتقاضای همان شب پارسال، نسبت تکمیل پارسالشکل فصلی معمول
تقویمروز هفته، تعطیلی، فاصله تا تعطیلی، شب یلدااین شب چقدر جذاب است
شهرانگیزهٔ سفر، فاصله تا تهران، پروفایل فصلیاین شهر چه‌جور جایی است

گرادیان بوستینگ به زبان ساده

تشبیه

یک پزشک تازه‌کار را تصور کنید که با پرسیدن سؤال‌های پشت سر هم تشخیص می‌دهد: «تب دارد؟ بله. سرفه دارد؟ خیر…». این یک درخت تصمیم است. حالا هزار پزشک بگذارید که هر کدام فقط روی اشتباه‌های پزشک قبلی تمرکز می‌کند. مجموعشان می‌شود گرادیان بوستینگ.

تعریف

LightGBM یک پیاده‌سازی سریع از همین ایده است. برای داده‌های جدولی با تعداد زیاد سری زمانی، هنوز یکی از قوی‌ترین گزینه‌هاست — در مسابقهٔ جهانی M5 هم روش‌های مبتنی بر آن بالای جدول بودند.

یک ترفند که فقط اینجا مجاز است

دامنهٔ تقاضا از صفر تا صدها هزار است. برای رام‌کردنش روی log1p آموزش می‌دهیم. معمولاً این کار سوگیری ایجاد می‌کند و باید تصحیح شود — ولی چون معیار ما میانه‌محور است و میانه زیر تبدیل‌های یکنوا تغییر نمی‌کند، اینجا برگرداندن بدون هیچ تصحیحی دقیق است.

۷کالیبراسیون و عدم قطعیت

تفاوت «خطا» با «سوگیری»، و اینکه عدد تنها کافی نیست.

خطا (error)

چقدر از واقعیت دوریم — چه بالا، چه پایین. همیشه بد است.

سوگیری (bias)

آیا به‌طور سیستماتیک بالا می‌زنیم یا پایین. لزوماً بد نیست.

مدل ما در همهٔ فولدهای ۱۴۰۴ بین ۳٪ تا ۱۹٪ کم می‌زند، در سالی که بازار ۲۵ تا ۳۷ درصد رشد کرده. طبیعی است که آدم بخواهد تصحیحش کند. ما آزمودیمش: ضریبی که WAPE را کمینه می‌کند فقط ۱٫۰۴ است — نه ۱٫۱۵ که برای صفرکردن سوگیری لازم است — و دو فولد از چهار فولد را بدتر می‌کند. پس اعمالش نکردیم.

دلیلش همان فصل ۴ است: بهینهٔ WAPE میانه است و در توزیع چوله، میانه زیر میانگین می‌نشیند. پس مقداری سوگیری منفی نه‌تنها عیب نیست، درست است.

چندک و پوشش

تشبیه

پیش‌بینی هواشناسی که می‌گوید «۷۰٪ احتمال باران» ادعای قطعی نمی‌کند؛ یک بازه می‌دهد. و راه سنجیدنش این است: از صد روزی که گفته ۷۰٪، آیا حدوداً هفتاد روز باران آمده؟ به این می‌گویند پوشش.

اصطلاحمعنی
P50پیش‌بینی مرکزی؛ نصف احتمال بالاتر، نصف پایین‌تر
P10 و P90کف و سقفی که انتظار داریم ۸۰٪ مواقع واقعیت بینشان بیفتد
پوشش (coverage)در عمل چند درصد مواقع واقعیت داخل بازه افتاده

وقتی پوشش بازه‌های خام‌مان را اندازه گرفتیم، معلوم شد فقط ۵۳٪ تقاضا را پوشش می‌دهند، نه ۸۰٪. یعنی برای شهرهای بزرگ خیلی باریک بودند. بازه را روی فولدهای کنارگذاشته‌شده پهن کردیم تا به ۸۰٪ برسد.

بازه‌ای که کسی پوششش را اندازه نگرفته، تزئین است نه عدد. ما اندازه گرفتیم، مردود شد، و درستش کردیم.

۸شوک

بعضی هفته‌ها فصلی نیستند و هرگز هم نخواهند بود.

خرداد ۱۴۰۴ نسبت به خرداد ۱۴۰۳ شصت درصد بالاتر بود، درحالی‌که ماه‌های اطرافش ۷ تا ۲۷ درصد رشد داشتند. علتش جنگ خرداد بود — و واکنش بازار جهش بود نه سقوط: مردم از تهران خارج شدند و در شهرهای دیگر دنبال اقامتگاه گشتند.

تعریف

شوک یا regime indicator یعنی پرچمی که به مدل می‌گوید «این هفته عادی نبود». بدون آن، مدل یاد می‌گیرد «اواخر خرداد همیشه ۶۰٪ شلوغ‌تر است» — که غلط است.

ما این پنجره‌ها را به‌جای اینکه مدل «یاد بگیرد»، صراحتاً اعلام می‌کنیم؛ در یک جدول ساده که هر وقت لازم شد می‌شود ویرایشش کرد. هر شوک سه پرچم جدا می‌دهد، چون سه چیز مختلف را می‌تواند آلوده کند: خودِ شب اقامت، مقایسه با پارسال، و منحنی رزرو.

ظریف‌ترین نکتهٔ کل پروژه: شوک فقط وقتی برای مدل قابل‌مشاهده است که شروع شده باشد. اگر برای فولدی که در ۱ خرداد ایستاده پرچم جنگ ۲۳ خرداد را روشن کنیم، نشت اطلاعات از آینده است — آن روز کسی خبر نداشت. برای همین در جدول نتایج می‌بینید که همهٔ مدل‌ها آن پنجره را از دست داده‌اند، و ما آن شکست را پاک نکردیم.

۹سرعت رزرو

همان تجزیه‌ای که پیش‌بینی می‌سازد، یک ابزار عملیاتی روزانه هم می‌دهد.

تشبیه

دوندهٔ ماراتن در کیلومتر ۲۱ است. عدد مهم فقط «چقدر دویده» نیست؛ «نسبت به زمان هدفش جلوتر است یا عقب‌تر» است. برای همین در ورزش به آن split می‌گویند.

اصطلاحمعنینمونه از آذر ۱۴۰۴
شاخص سرعت (pace index)آنچه تا حالا ثبت شده ÷ آنچه پارسال در همین فاصله ثبت شده بود، بعد از حذف رشد خودِ شهرقشم ۱٫۲۲ (جلوتر) · کردان ۰٫۸۳ (عقب‌تر)
تقاضای باقی‌ماندهپیش‌بینی منهای بخش محقق‌شده — یعنی چقدرش هنوز قابل تأثیرگذاری استکردان ۷۹٪ هنوز نیامده
میانهٔ فاصلهٔ رزرو (lead p50)چند روز مانده به اقامت، نصف تقاضا آمدهکیش ۱۰ روز · چالوس ۳ روز

ستون سوم نکتهٔ عملیاتی است: برای کیش باید ده روز قبل تبلیغ کرد، برای چالوس سه روز قبل. همان بودجه، با تقویم متفاوت، اثر متفاوت.

شاخص سرعت کل بازار در آذر ۱۴۰۴ برابر ۰٫۹۸ است — یعنی بازار روی روند است. پراکندگیِ بین شهرهاست که سیگنال می‌دهد، نه عدد کل.

۱۰واژه‌نامه

همهٔ اصطلاحات، یک‌جا. برای وقتی که وسط ارائه سؤالی پرسیده می‌شود.

اصطلاحانگلیسیتوضیح یک‌خطی
فاصلهٔ تا اقامتlead timeچند روز بین جست‌وجو و شب اقامت
تاریخ مبدأas-of dateروزی که در آن ایستاده‌ایم و بعدش را نمی‌بینیم
افقhorizonچند روز جلوتر را پیش‌بینی می‌کنیم — اینجا ۳۰
مثلث تأخیرdelay triangleشکل داده وقتی دو محور زمانی دارد
بخش محقق‌شدهpartial / Pجست‌وجوهایی که تا امروز ثبت شده‌اند
باقی‌ماندهremainder / Rجست‌وجوهایی که هنوز نیامده‌اند
منحنی تکمیلcompletion curveچند درصد تقاضا در هر فاصله معمولاً آمده
نردبان زنجیره‌ایchain ladderبرآورد کل از روی بخش دیده‌شده
جمع‌شدن به میانگینshrinkageترکیب برآورد شهر با برآورد گروهش
فولدfoldیک تمرین کامل با جواب معلوم
کنارگذاشته‌شدهheld-outداده‌ای که مدل ندیده و فقط نمره می‌دهد
مبدأ متحرکrolling originتکرار تمرین در چند تاریخ مختلف
نشت اطلاعاتleakageرسیدن اطلاعات آینده به مدل
ویژگیfeatureهر ورودی عددی که مدل می‌بیند
گرادیان بوستینگgradient boostingهزار درخت تصمیم که خطای هم را جبران می‌کنند
خط پایهbaselineساده‌ترین راه‌حل ممکن، برای مقایسه
ابلیشنablationجدولی که نشان می‌دهد هر ایده چقدر ارزش داشت
سوگیریbiasآیا سیستماتیک بالا می‌زنیم یا پایین
کالیبراسیونcalibrationتنظیم سطح یا بازه با شواهد
چندکquantileعددی که فلان درصد احتمال زیرش است
پوششcoverageدر عمل چند درصد مواقع واقعیت در بازه افتاد
شوکshock / regimeدوره‌ای که فصلی نیست و باید اعلام شود
شاخص سرعتpace indexجلوتر یا عقب‌تر از برنامهٔ معمول
خوشهclusterگروهی از شهرها با رفتار مشابه
تجمیعaggregationپیش‌بینی برای گروه به‌جای تک‌تک شهرها
این راهنما همراه گزارش فنی و ارائهٔ پروژهٔ پیش‌بینی تقاضا برای آذر ۱۴۰۴ تهیه شده است. همهٔ اعداد از خروجی کد همین مخزن می‌آیند.