از «ویژگی» چه می دانید؟ (قسمت دوم)

مروری بر مهندسی ویژگی و اهمیت آن + یک تجربه

و اما یک تجربه...

چند ماه پیش با دو نفر از دوستان دیگر یک مسابقه داده‌کاوی شرکت کردیم. مساله مسابقه این بود که شما یک میلیون هفت‌صد هزار رکورد از ثبت سفارش های یک آژانس هوایی را در سال۱۳۹۵ و ۱۳۹۶ داشتیم و با استفاده از آن حجم سفارش های سال ۹۷ را پیش‌بینی می کردیم.

فیلدهای دیتا ها به صورت زیر بود:
مبدا/ مقصد/ تاریخ ثبت سفارش/ تاریخ پرواز/ کد خط هوایی (ایرلاین)/ زمان پرواز/ قیمت بلیت
و خروجی باید به صورت زیر می بود:
تاریخ سفارش و مبدا و مقصد داده می شد و تعداد درخواست باید پیش بینی می شد.

گرچه نتیجه این مسابقه خیلی دلنشین نبود (چون تجربه عملیاتی اول کل تیم‌مون بود) ولیکن تجربه‌های خیلی خوبی برای همه‌مون به دست اومد.

چالش ها

مساله این مسابقه چالش‌های زیادی داشت مثل اینکه باید داده ها نویز گیری می شدند(denoise)، باید داده تمیز می شدند (clean) باید مدل مناسب طراحی می‌شد و یکی از مهم‌ترین چالش‌هایی که ما تا مدت مدیدی به عنوان چالش به آن نگاه نمی کردیم همین مهندسی ویژگی و استخراج ویژگی ها به صورت مناسب و کارا بود؛ باید سعی می کردیم سیستمی که قرار است به مدل تصمیم‌گیرنده یا پیش‌بینی کننده ارایه می دادیم دقیق تر و با پارامترهای بیشتری می شد. برای همین شروع کردیم یک سری تغییرات به داده هایمان دادیم و یک سری داده های دیگر نیز اضافه کردیم.
قبل از ادامه باید بگم مدل تصمیم‌گیرنده ما یک شبکه عصبی ساده بود که همین هم آخرهای کار فهمیدیم اشتباه هستش ولی چون زمان کم بود خیلی فرصت نشد کاری بکنیم؛ و ورودی های مدل نیز به صورت یک بردار (vector) از اعداد به آن داده می‌شد.

و اما تغییراتی در ویژگی‌ها اعمال کردیم:

ویژگی ‌های دسته اول: تاریخ

برای تاریخ چند کار کردیم.

  • یک؛ اینکه اول فرمت تاریخ ها را که با صورت مثلا ۱۳۹۶/۱۲/۲ بود و آن را به صورت رشته(string) در نظر می گرفتیم را تفکیک کرده و به صورت ماه و سال و روز به صورت عدد تبدیل کردیم.
  • دو؛ از روی ماه های سال فصل ها را مشخص کردیم و به عنوان یک ورودی جدید اضافه کردیم.
  • سه؛ به عنوان دانش پیشین، تعطیلات سال ۹۶ را از سایت های ایرانی پیدا کردیم و یک ورودی باینری جدید که تعطیل بودن یا نبودن روز تعطیل را مشخص می کرد اضافه کردیم.
  • چهار؛ فاصله روز پرواز تا نزدیک ترین تعطیلات را به صورت یک عدد بیت منفی ۳ تا ۳ محاسبه کردیم.
  • پنج؛ ۳ روز های ابتدا و انتهای ماه را با یک متغیر باینری دیگر مشخص کردیم.
  • شش؛ محاسبه کردیم که هر تاریخ چه روز هفته بوده است و آخر و اول هفته بودن را با یک متغیر باینری مشخص کردیم.
  • هفت؛ ما هم تاریخ سفارش را داشتیم و هم تاریخ پرواز، برای همین از روی این دو فاصله زمانی خرید لیت تا پرواز را محاسبه کردیم به عنوان یک ورودی جدید.

هشت؛ با نمودارها و آمار های کلی که گرفته بودیم و با توجه به رفتارهای کلی داده‌ها، مسافرت های هوایی را با توجه به ویژگی‌هایشان به دو دسته خانوادگی-تفریحی و کاری تقسیم کردیم. برای دسته اول ویژگی‌های زیر را در نظر گرفتیم: ۱- از مدتی قبل برنامه‌ریزی شده‌اند (فاصله رزرو و پرواز زیاد است) ۲- به جاهای پر تردد سفر خواهند کرد ۳- پروازشان به تعطیلات رسمی و یا آخر هفته نزدیک تر است ۴- در تابستان بیشتر سفر می کنند و… و برای دسته دوم برعکس موارد بالا؛ یعنی هم فاصله رزرو و پرواز کم‌تر است هم لزوما جایی که می روند پرتردد نیست هم ضمن هفته پرواز دارند و وابسته به تاریخ خاصی نیست
البته این مورد به خاطر خام بودن ایده و نیز پیچیده‌تر کردن مدل در ادامه کنار گذاشته‌شد.

ویژگی ‌های دسته دوم: نوسانات دلار

سال ۹۷ دقیقا سالی بود که نوسانات دلار بسیار زیاد بود و این آشفته‌بازار دلار قیمت پرواز های هوایی را هم گریبانگیر کرده بود. برای همین ما به این فکر افتادیم که نرخ دلار را مستقیم و یا غیر مستقیم وارد این مدل بکنیم.
اول خواستیم که نرخ روزانه دلار را وارد کنیم، دیدیم که برای به دست آوردن ۲ سال نرخ روزانه خیلی باید انرژی صرف شود چون به صورت ساختار یافته در جایی پیدا نکردیم و باید دستی جمع‌آوری می‌کردیم. در ادامه به این نتیجه رسیدیم که این کار را ماهانه انجام بدهیم و بعدتر قیمت هر پرواز با با نرخ دلار نرمال کنیم که مرحله آخر محقق نشد.

ویژگی ‌های دسته سوم: آب و هوا

ویژگی آب و هوا
ویژگی آب و هوا

یکی از پارامتر های اصلی موثر بر روی مسافرت های هوایی، بی‌شک آب‌و‌هوا می باشد. اگر هوا طوفانی باشد پرواز ها لغو می شوند برای همین تقاضای پرواز بالا می رود و قیمت ها بالا می رود و خیلی از اثرات دیگر ولیکن وارد کردن این پارامتر را به مدل‌مان به سه دلیل لغو کردیم: ۱- به دست آوردن داده های ساختارمند آب و هوای ایران برای استفاده در دسترس نبود ۲- مدلسازی آب و هوا و استخراج الگو (چون یک سیستم آشوبناک است) بسیار سخت بود ۳- وضعیت کلی آب و هوا در فصل ها مشخص بود و فصل را در نظر گرفته بودیم، مثلا احتمال بارش باران در تابستان خیلی کمتر از بهار است و ..

آخر کار...

تمام موارد بالا فقط مرحله اول مدل سازی بود و مطمینا باز هم جای کار کردن بیشتر و دقیق‌تر داشت و مرحله بعدی آن نیز طراحی یک مدل پیش‌بینی کننده کارا بود که در ابتدا با یک شبکه عصبه عادی شروع کردیم ولی در پایان به این نتیجه رسیدیم که شاید معماری های جدید تر شبکه های عصبی کارا تر بودند مثل شبکه های عصبی بازگشتی (RNN) چون داده های ما توالی داشتند و شبکه های معمولی نمی توانستند این توالی را یاد بگیرند و این نسل از شبکه ها این توانایی را با استفاده از سری های زمانی داشتند.
بحث ها و گفتگو ها و ایده های زیادی در این فرآیند مطرح شد و در پایان این مسابقه گرچه رتبه یا مقام خاصی دست‌گیرمان نشد (البته گروه های خیلی قوی بعضا غیر دانشجو هم در این مسابقه شرکت‌کرده‌بودند:)) ولی تجربیات عملیاتی و تیوری بسیار زیادی نصیب‌مان شد وا فهمیدیم که همه چیز یک مدل پیش‌بینی کننده یک شبکه ساده نیست که صرفا یاد بگیرند بلکه «مهندسی ویژگی» در این میان بسیار مهم و تاثیر گذار هستند، بلکه باید بخش زیادی از انرژی را در پروژه‌های مختلف صرف این موضوع کرد.

آخر کار هم توصیه می کنم که اگر مسابقه ای برگزار شد و هیچ امیدی برای کسب رتبه در آن را هم نداشتید، حتما شرکت کنید چون هم جرات رقابت را تجربه می کنید و هم تجربه های خوبی را در چالش های آن کسب می کنید. با آرزوی موفقیت :)

در پایان از اساتید محترم دکتر خردپیشه ( استاد علوم کامپیوتر دانشگاه شهیدبهشتی) و دکتر آزمین(پژوهشکده بیماری‌های غیرواگیر) باید تشکر کنیم که از مشورت ها و راهنمایی هایشان استفاده کردیم.
مسیر چالش برانگیز این مسابقه نیز با همراهی آقایان علیرضا آزادبخت و علیرضا جواهری طی شد و تجربه های خوب و ماندگاری به جا ماند.