لطفاً کد جواب سوالات را در قالب فایل `zip` که شامل ۵ فولدر به ازای هر سوال است در این قسمت آپلود کنید. آپلود نکردن جواب سوالات به منزلهی انصراف از مسابقه میباشد.
**توجه:** محدودیت سایز فایل زیپ *۲۰ مگابایت* میباشد.
بارگذاری کد جواب سوالات - الزامی
# صورت مسئله
فرض کنید شما قرار است قیمتگذار کالاهای دیجیکالا باشید. با کمک گرفتن از دادههای محصولات مشابه و قیمتهای آنها، قیمت باقی محصولات را با توجه به نوع و ویژگیهای محصول محاسبه کنید.
# ورودی
فایل ورودی به نام `train.csv`، دارای سه ستون است:
1. `id`: شامل یک شماره یکتا به ازای هر سطر است.
2. `product_description`: به فرمت یک `dictionary` میباشد و شامل دستهبندی، برند و سایر مشخصات محصول میباشد.
3. `price`: شامل قیمت محصول است.
همچنین یک فایل به نام `test.csv` به شما داده شده است که شامل دو ستون اول ذکر شده در بالا میباشد. از شما خواسته شده است مدلی طراحی کنید که قیمت این محصولات را تخمین بزند.
برای دریافت دادههای آموزش و آزمون روی [این لینک](https://quera.org/contest/assignments/39253/download_problem_initial_project/132527/?noconvert=true) کلیک کنید.
# خروجی
فایل خروجی باید دارای نام `output.csv` باشد. این فایل باید دارای دو ستون `id` و `price` باشد. `id` باید همان شماره یکتای محصولات فایل `test` با همان ترتیب باشد و `price` قیمت محاسبه شده توسط مدل شما برای آن محصول است.
توجه کنید که مغایرت نام فایل، نام ستونها، ترتیب محصولات، و یا آوردن دو قیمت برای یک محصول باعث میشود به طور کامل امتیاز این بخش را از دست بدهید.
# ارزیابی
برای ارزیابی خروجیهای شما از معیار ارزیابی **Mean Absolute Percentage Error (MAPE)** استفاده میشود، که این عدد هر چه به صفر نزدیکتر باشد عملکرد شما بهتر بوده است.
![{\displaystyle {\mbox{MAPE}}={\frac {100\%}{n}}\sum _{t=1}^{n}\left|{\frac {A_{t}-F_{t}}{A_{t}}}\right|}](https://wikimedia.org/api/rest_v1/media/math/render/svg/5ada3996551e35503a1605edd4e35a26f1215d36)
نمره این سوال بر اساس فرمول زیر محاسبه میشود که هر چه به صد در صد نزدیکتر باشد، یعنی شما بهتر عمل کردهاید و به همان نسبت امتیاز این سوال را کسب میکنید.
$$ SCORE = 100 - MAPE $$
قیمتگذاری کالاهای دیجیکالا
# مسئله
در پنل فروشندگان دیجیکالا هنگامیکه فروشندگان محصولات خود را برای فروش به وبسایت اضافه میکنند باید برای هر محصول، تعدادی از تصاویر آن محصول را نیز ارسال کنند؛ اما هر تصویر ممکن است مناسب نباشد زیرا تصاویر باید یک شرایط از قبل تعیینشدهای را رعایت کنند. یکی از این شرایط نبود هیچگونه واترمارک بر روی تصویر است. در این مسئله از شما میخواهیم با استفاده از دادههایی که در اختیار شما قرار داده شده است مدلی آموزش دهید که توانایی تشخیص وجود واترمارک را داشته باشد.
مجموعهدادهای که در اختیار شما قرار داده شده دارای دو بخش آموزش و آزمون میباشد که در بخش آموزش، مجموعهای از تصاویر که دارای واترمارک هستند در پوشهی `positive` و مجموعهای از تصاویر که در آنها واترمارک دیده نمیشود در پوشهی `negative` قرار گرفتهاند. شما باید با استفاده از این تصاویر، الگوریتم یادگیری ماشین خود را آموزش داده و سپس پیشبینی کنید که هرکدام از تصاویر موجود در پوشهی آزمون دارای واترمارک هستند یا خیر.
[**دریافت دیتاست**](https://static.quera.org/dl/dk-dataset.zip)
# فرمت خروجی
خروجیهای تولید شده برای تصاویر پوشهی آزمون را در قالب فایل `output.csv` با فرمت نمونه زیر تولید کنید و سپس فایل `output.csv` خود را با فرمت `zip` فشرده کرده و آپلود کنید. دقت داشته باشید که در ستون `predicted` مقدار 1 بیانگر وجود واترمارک بوده و مقدار 0 بیانگر عدم وجود واترمارک است.
````
name,predicted
2d9cc95f-36ef-42e6-ade8-951bb61c75ea.jpg,1
4c0bb25f-6f66-4e88-99b1-02064884a7c9.jpg,1
cc760241-baba-4182-b4d5-596ea5855129.jpg,0
f098a6fa-f7f1-44a5-abfe-1a53956c1fb8.jpg,1
d6aed00a-7d2e-4fc6-b6d7-518ab210a416.jpg,0
da70fe84-dff7-4a4e-a174-474f6cebdb74.jpg,1
6dc921a0-3caf-4df0-bf67-6bff8a8b013e.jpg,0
101b432e-87d0-4d1a-8bff-2641a078b757.jpg,1
cf882d66-d8ae-4838-903f-519b880dd512.jpg,0
83f4edd9-2917-4342-9731-9cec492a07d9.jpg,1
.
.
.
````
تشخیص واترمارک در تصاویر محصولات دیجیکالا
احتمالاً شما هم از آن دست کاربرانی باشید که یک سری محصول خاص را بصورت دورهای مصرف میکنید و زمانی که آن محصول مصرف شد، نوبت خرید دوباره فرا میرسد. هدف ما در این مسأله تشخیص همین عادتهای خرید (Purchase Habits) و پیشنهاد خرید بعدی به کاربران است. با این کار کاربران زمان کمتری را صرف پیدا کردن محصولات موردنظرشان میکنند.
# صورت مسئله
همانطور که گفته شد، هدف ما این است که دریابیم هر کاربر در دیجیکالا چه محصولاتی را بصورت دورهای خریداری میکند. بصورت دقیقتر، میخواهیم بفهمیم که کاربر `U` کالای `P` را **هر چند روز یک بار** خریداری میکند و وقتی که موعد خرید بعدیاش رسید، به وی پیشنهاد خرید کالا را بدهیم. طبیعتاً برای این کار به تاریخچهی خرید کاربرها نیاز داریم که در بخش بعدی در مورد آن صحبت خواهیم کرد.
شما ابتدا باید **هر جفت «کاربر-محصول»** را جدا کرده و سپس سعی کنید با تست کردن الگوریتمهای مختلف پیشبینی کنید که تاریخ خرید بعدی این کاربر از همین محصول چه زمانیست. روند مسأله ساده بوده و کار اصلی شما تلاش برای پیدا کردن دقیق دوره برای هر جفت «کاربر-محصول» و پیشنهاد تاریخ خرید بعدی است.
<details class="yellow">
<summary>توجه</summary>
به عبارت «جفت» دقت کنید. در آخر شما باید به ازای هر جفت، یک تاریخ خروجی بدهید.
</details>
----------
# دادگان
ابتدا فایل تاریخچهی خرید و فرمت جوابی که باید آپلود کنید را از [این لینک](/contest/assignments/39253/download_problem_initial_project/132516/) دریافت کنید. فایل `purchase_history.csv` بخشی از خریدهای کاربران و تاریخشان را شامل میشود (البته آخرین خرید آنها حذف و برای ارزیابی نگهداری شده است). شما میبایست عملیاتتان را روی فایل `purchase_history.csv` انجام داده و خروجی را درون فایل `answer.csv` ذخیره کنید. چند ردیف از فایل `purchase_history.csv` را در جدول زیر مشاهده میکنید:
| user_id | product_id | created_at |
|:---:|:---:|:---:|
| 6823506 | 1015421 | 2019-06-10 |
| 11886162 | 5622949 | 2019-11-27 |
----------
# ارزیابی
در بخش قبلی اشاره شد که آخرین خرید هر جفت «کاربر-محصول» برای ارزیابی برداشته میشود و جواب شما نیز با همان آخرین خرید مقایسه خواهد شد. فرمول ارزیابی ***میانگین وزندار* تفاوت پیشبینی شما از تاریخ خرید بعدی و تاریخ اصلی خرید بعدی هر جفت «کاربر-محصول»** در نظر گرفته شده و طبق روند زیر محاسبه میشود:
$$ error = abs(predicted_i - actual_i) $$
$$ total\_error = \frac{\sum(error * 1.04^{error})}{\sum(1.04^{error})} $$
$$ score = max(100 - total\_error, 0) $$
در فرمول بالا:
+ مقدار $n$ تعداد نمونههای دادگان خروجیست.
+ مقدار $predicted_i$ تاریخ پیشبینیشدهی ردیف $i$ام توسط شماست.
+ مقدار $actual_i$ تاریخیست که مشتری ردیف $i$ کالای ردیف $i$ را خریده است.
+ امتیاز شما در نهایت مقدار `score` است.
<details class="green">
<summary>توضیحات</summary>
+ بهترین جواب (`score=100`) یعنی میانگین اختلاف روزهای پیشبینیشده ۰ بوده و بدترین جواب (`score=0`) یعنی شما به طور میانگین ۱۰۰ روز از حالت واقعی فاصله داشتهاید. طبیعتاً شما باید تلاش کنید که `score` به بیشترین مقدار (۱۰۰) برسد.
+ میانگین تفاوت بیشتر از ۱۰۰ روز در واقع برای ما ارزشی نداشته و به همین دلیل لحاظ نمیشوند و شما به ازای آن جوابها نمرهای دریافت نخواهید کرد.
+ برای اختلافهای بیشتر از ۱۰۰ (x > 100)، همان وزن عدد ۱۰۰ را دریافت خواهید کرد. به بیانی دیگر، ماکسیمم مقدار وزن هر اختلاف (x) برابر با $1.04^{100}$ هست.
+ امتیاز شما برای این سوال دقیقاً همین مقدار `score` خواهد بود. برای مثال اگر فردی تمامی تاریخها را ۵ روز دیرتر پیشبینی کرده باشد، مقدار `score` وی برابر با ۹۵ خواهد بود.
+ منطق این نحوهی وزندهی بدین صورت است که برای اختلاف روزهای بیشتر، `error` شما وزن بیشتری دریافت کند (به اصطلاح بیشتر punish شوید).
</details>
----------
# خروجی
برای ارسال جواب این سوال، شما میبایست تاریخ خرید بعدی هر جفت «کاربر-محصول» را درون جدول `answer.csv` ذخیره کرده (**بدون دو ستون اول**) و این فایل را `zip` کرده و آپلود کنید. به موارد زیر هنگام ساختن فایل خروجی دقت کنید:
+ پاسخ شما باید داخل ستون `next_purchase` نگهداری شود.
+ اسم فایل باید `answer.csv` باشد.
+ حتماً `header` ستون گذاشته شود.
+ از گذاشتن ستونی برای `index` خودداری کنید.
+ نام فایل نهایی `zip` اهمیتی ندارد.
----------
# نمونهی فایل خروجی `answer.csv`
```
next_purchase
2019-09-14
2019-10-28
2019-01-01
```
<details class="red">
<summary>توجه ویژه</summary>
فایل خروجی شما (`answer.csv`) باید دارای یک ستون و ۳۱۸,۰۵۰ ردیف (بدون احتساب `header`) باشد. همچنین ترتیب تاریخهای نوشتهشده باید **مثل همان ترتیب اولیه** در فایل `answer.csv` باشد وگرنه نمرهی شما اشتباه محاسبه خواهد شد.
</details>
تشخیص عادت خرید کاربران دیجیکالا
+ محدودیت زمان: ۱.۵ ثانیه
+ محدودیت حافظه: ۱۰۰ مگابایت
----------
دیجیکالا تعداد زیادی انبار در مکانهای مختلف دارد. در یکی از شبها دزدی وارد یکی از انبارهای دیجیکالا شده و چند جعبه از انبار خارج کرده است. از آنجا که این دزد بسیار باهوش بوده به شکلی این کار را انجام داده است که از راه دوربینهای انبار قابل ردیابی نباشد. در این سوال میخواهیم بدانیم اگر به همین شکل از بقیهی انبارها دزدی شود حداکثر چند جعبه میتواند از هر انبار خارج شود. فرض کنید هر انبار یک مستطیل `n×m` است که میتوان با یک ماتریس تعداد جعبههای هر خانه را نشان داد. همچنین فرض کنید هر شب از هر انبار سه عکس گرفته میشود؛ از جلو، بغل و بالا.
برای مثال برای انبار زیر:
![ماتریس انبار](https://s6.uupload.ir/files/fig1_quera_jxui.png)
این عکسها گرفته میشود:
![عکسهای انبار](https://s6.uupload.ir/files/fig2_quera_z0nu.png)
و یک دزد میتواند از این انبار به شکل زیر حداکثر ۹ جعبه را بردارد و بقیه را طوری ***جابجا کند*** که از دوربینها همان عکسهای بالا گرفته شود.
![بعد از دزدی!](https://s6.uupload.ir/files/screenshot_from_2022-02-05_17-16-44_e1bq.png)
# ورودی
در اول خط اول ۲ عدد صحیح `r` و `c` که به ترتیب طول و عرض انبار هستند داده میشود. در `r` خط بعدی در هر خط `c` عدد داده میشود که هر کدام تعداد جعبهها هستند.
$$1 \le c, r \le 100$$
# خروجی
در خروجی بیشترین جعبهای که میتواند از انبار خارج شود طوری که از عکس دوربینها مشخص نباشد را چاپ کنید.
# مثال
## ورودی نمونه ۱
```
5 5
1 4 0 5 2
2 1 2 0 1
0 2 3 4 4
0 3 0 3 1
1 2 2 1 1
```
## خروجی نمونه ۱
```
9
```
## ورودی نمونه ۲
```
2 3
50 20 3
20 10 3
```
## خروجی نمونه ۲
```
30
```
دزدی از انبار دیجیکالا
معیار *normalized Discounted Cumulative Gain* یا به اختصار **nDCG** یک معیار (metric) رایج جهت ارزیابی خروجی یک موتور جستجوگر یا هر سیستم رنکینگ دیگر است. مقدار این متریک عددی بین صفر و یک است که از جمله ویژگیهای آن، اندازهگیری میزان درستی در مرتبسازی نتایج میباشد.
این معیار نرمالایز شدهی معیار *DCG* میباشد. برای محاسبهی *DCG* از رابطهی زیر استفاده میشود:
![توضیح تصویر](https://s6.uupload.ir/files/dcg_zsr.jpg)
همانطور که مشاهده میکنید این معیار میتواند برای کوئریهای مختلف، اسیکلهای مختلف داشته باشد. به همین دلیل معیار *nDCG* معرفی میشود که برای محاسبهی آن از رابطهی زیر استفاده میکنیم.
![توضیح تصویر](https://s6.uupload.ir/files/ndcg_nzqb.jpg)
در رابطهی بالا *IDCG* برابر است با مقدار *DCG* برای حالت ایدهآل مرتبسازی:
![توضیح تصویر](https://s6.uupload.ir/files/idcg_bmha.jpg)
برای اطلاعات بیشتر دربارهی این متریک میتوانید [**اینجا**](https://en.wikipedia.org/w/index.php?title=Discounted_cumulative_gain&oldid=1013040968) کلیک کنید.
ما در دیجیکالا برای محاسبه این متریک از دادهی کلیک کاربران به روی نتایج موتور جستجوگر استفاده میکنیم.
فرض کنید جدول زیر موجود باشد. در این جدول هر سطر نشانگر تعداد کلیک بروی نتیجهی سرچ یک کوئری در پوزیشنِ مربوطه است.
| query | click_count | position |
| ------ | ----------- | ---------- |
| pocox3 | 89 | 1 |
| pocox3 | 88 | 2 |
| iphone13 | 100 | 1 |
| ... | ... | ... |
در این مسئله شما باید با استفاده از این دادهها و طراحی یک کوئری sql مناسب، این متریک را برای دادگان کلیک کاربران محاسبه کنید. نمونه فایل دادگان و خروجی مورد نظر در ادامه آورده شده است:
[**دریافت نمونه فایل دادگان (demo_testset.zip)**](https://quera.org/contest/assignments/39253/download_problem_initial_project/132644/?noconvert=true)
در این فایل دیتابیس `sqlite` با نام `testset.sqlite` شامل جدولی با نام `dk_table` در اختیار شما قرار گرفته است. همچنین خروجیی که با اجرای درست کوئری تولید میشود نیز در فایلی به نام `testset_gt.csv` به شما داده شده است.
در این مسئله شما باید کوئری خود را در قالب یک فایل با فرمت *sql* (مانند *query.sql*) در سایت بارگذاری کنید.
## ساختار خروجی
خروجی شما باید شرایط زیر را داشته باشد:
1. تنها دو ستون داشته باشد.
2. یکی از ستونها `query` و دیگری `ndcg` نامیده شود.
3. نوع داده برای ستون `query` **رشته** و برای ستون `ndcg` **عدد اعشاری float** باشد.
4. هیچکدام از ستونها مقدار خالی نداشته باشند.
5. ستون `query` داپلیکت نداشته باشد.
6. معیار *nDCG* برای همه `query` ها محاسبه شده باشد.
## نحوهی ارزیابی:
خروجی کد *sql* شما با خروجی کد زیر مقایسه میشود:
de compute_ndcg_for_dataset(dataset):
df = dataset.groupby('query').agg({'click_count':lambda x: x.tolist(),'position':lambda x: x.tolist()})
df['ndcg'] = df.apply(lambda x: compute_ndcg_per_query(x['click_count'],x['position'])[0],axis=1)
return df[['query','ndcg']]
def compute_ndcg_per_query(clicks,position):
if len(clicks)!= len(position):
raise ValueError("clicks and positions len should be equal")
dcg_list = np.array(clicks)/np.log2(np.array(position)+1)
idcg_list = np.array(sorted(clicks,reverse=True))/np.log2(np.array(position)+1)
dcg = np.sum(dcg_list)
idcg = np.sum(idcg_list)
return dcg/idcg
## تابع لگاریتم در sqlite
برای داشتن تابع لگاریتم در *sqlite* میتوانید کانکشن را به صورت زیر بسازید:
def creaet_sqlite_conn(path):
conn = sqlite3.connect(path)
conn.create_function("log2", 1, np.log2)
return conn
**نکته:** در این سوال از ورژن **3.31** دیتابیس *sqlite* استفاده شده است.