در کدگذاری One-hot، برای هر دسته شناختهشده یک ستون میسازیم و حضور آن دسته را با ۱ نشان میدهیم. هدف، تبدیل نام دسته به نمایش عددی است، بدون اینکه با کدهای ۱، ۲ و ۳ فاصله یا ترتیب ساختگی به نامها نسبت بدهیم. پرسش مهم بعدی این است: اگر ورودی تازه، دستهای داشته باشد که در آموزش ندیدهایم، چه اتفاقی بیفتد؟
ابتدا معنی ستونها را ثابت کنیم
مثال آموزشی، کانال درخواست را دارد: chat و phone. ترتیب ستونها را صریحاً chat، سپس phone تعریف میکنیم. پس chat به [1,0] و phone به [0,1] تبدیل میشود. اگر در فایل بعد ترتیب را جابهجا کنیم، شکل داده همچنان دو ستون دارد ولی معنای ورودی مدل برعکس میشود.
| ورودی | ستون chat | ستون phone |
|---|---|---|
| chat | ۱ | ۰ |
| phone | ۰ | ۱ |
| email، دسته تازه | تابع سیاست ناشناخته است؛ نباید خودسرانه ستون تازه بسازیم |
این مثال یک ویژگی تکمقداری دارد. اگر هر درخواست بتواند همزمان چند برچسب داشته باشد، قرارداد مسئله متفاوت است. همچنین نام دستهها نماینده کانال ساختگیاند و داده مشتری واقعی در تمرین استفاده نشده است.
دو سیاست ساده برای دسته نادیده
روش اول توقف با خطای مشخص است. این انتخاب وقتی مفید است که دسته تازه نشانه قرارداد ناسازگار باشد و مسیر بازبینی تعریف شده باشد. توقف نباید به حذف خاموش ردیف یا فرض نتیجه منفی تبدیل شود؛ مصرفکننده باید بداند تبدیل انجام نشده است.
روش دوم، نمایش همهصفر روی ستونهای همان ویژگی است. در مستندات OneHotEncoder، گزینه ignore چنین رفتاری دارد. این نمایش بهتنهایی به معنی تشخیص معنای email نیست؛ فقط میگوید هیچکدام از دستههای شناختهشده فعال نشده است. کد زیر برای آموزش همین دو رفتار، بدون نصب کتابخانه نوشته شده و پیادهسازی کامل ابزار نیست.
کد را روی دسته معلوم و تازه اجرا کنیم
CATEGORIES = ('chat', 'phone')
def encode(value, unknown='error'):
if unknown not in ('error', 'ignore'):
raise ValueError('unknown policy must be error or ignore')
if value not in CATEGORIES and unknown == 'error':
raise ValueError('unseen category')
return [int(value == category) for category in CATEGORIES]
print('columns', CATEGORIES)
print('chat', encode('chat'))
print('phone', encode('phone'))
print('email ignored', encode('email', unknown='ignore'))
try:
encode('email')
except ValueError as error:
print('email rejected:', error)
assert encode('chat') == [1, 0]
assert encode('phone') == [0, 1]
assert encode('email', 'ignore') == [0, 0]
assert encode('chat')[1:] == encode('email', 'ignore')[1:] == [0]
یک دسته تازه، تعداد یا ترتیب ستونهای تابع را تغییر نمیدهد. نامها در این کد دقیق مقایسه میشوند؛ Phone با phone یکسان نیست. اگر قرار است بزرگی حروف، فاصله یا نام جایگزین یکسان شوند، آن تبدیل باید پیشاپیش تعریف، نسخهدار و با مثال آزموده شود. نرمالسازی حدسی ممکن است دو دسته واقعاً متفاوت را ادغام کند.
حذف ستون اول چه ابهامی میسازد؟
اگر ستون chat را حذف کنیم، در این مثال فقط ستون phone باقی میماند: chat با صفر و phone با یک نمایش داده میشود. حالا ناشناخته همهصفر نیز به صفر میرسد و از دسته مبنا قابل تشخیص نیست. این ابهام را باید آگاهانه بپذیریم یا با قرارداد دیگری، مانند ستون صریحِ «سایر» و قاعده مشخص نگاشت، حل کنیم.
ستون «سایر» را نمیتوان پس از آموزش، بیاطلاع به انتهای ورودی مدل چسباند. مدل باید همان ساختار را بشناسد. همچنین تبدیل مقدار خالی به «سایر»، تصمیم دیگری است: نبود داده لزوماً دسته تازه نیست. نرخ ناشناختهها و منشأ آنها را جدا از کیفیت پیشبینی ثبت کنید.
با Target encoding چه فرقی دارد؟
One-hot در این تعریف، نام دسته را به ستون حضور تبدیل میکند و از پاسخ هدف برای ساخت مقدار استفاده نمیکند. در Target encoding آماری از پاسخ وارد ویژگی میشود؛ بنابراین کنترل نشت و روش ساخت ویژگی آموزش متفاوت است. انتخاب یکی، مجوز استفاده بیقید از اطلاعات آزمون در دیگری نیست.
پیش از استقرار، واژهنامه دستهها، ترتیب ستونها، رفتار ناشناخته و مقدار خالی را در قرارداد ویژگی بنویسید. اگر مسئله اصلی تیم شما دریافت و ارجاع درخواست مشتری است، نمونههای مجاز و موارد مبهم را برای بررسی مسیر مناسب با اپرا آماده کنید؛ این نوشته معماری داخلی محصولات اپرا را بیان نمیکند.
فایل تمرین و منبع
دریافت کد مستقل این تمرین. ورودیها آموزشیاند؛ این فایل اتصال شبکه ندارد و ابزار پردازش عملیاتی داده مشتری نیست.
تاریخ خواندن منبع: ۳ نوامبر ۲۰۲۶. کد و داده مثال برای همین راهنما طراحی شدهاند.