Satu pembuat enkode panas kami membuat fitur untuk setiap tingkat fitur kategoris asli:
from evalml.pipelines import OneHotEncoder
import pandas as pd
df = pd.DataFrame({"category": ["a", "b"], "number": [4,5 ]})
OneHotEncoder().fit_transform(df).to_dataframe()
Kolom category_a
dan category_b
benar-benar collinear, yang membuat satu kolom menjadi redundan. Ini bisa memiliki efek buruk pada pemasangan estimator. Saya pikir kita harus menjatuhkan satu secara default.
FYI @rpeck
% kita harus membuang kolom kasus negatif.
Jika kita melakukan OHE sendiri dulu, maka sklearn semoga tidak mengembangkannya. Seperti yang dikatakan Freddy, Anda dapat menganggap ini sebagai menghasilkan dua kolom yang memiliki kolinearitas sempurna.
Ada dua masalah yang saya lihat dengan memperluas biner menjadi dua kolom daripada satu:
@freddyaboulton T: Kerangka data di atas untuk kolom OHE menunjukkannya sebagai pelampung. Apakah ini benar?
@rpeck Ya!
@freddyaboulton Ada apa? Itu aneh. Saya belum pernah melihat apa pun selain boolean sejati, atau bilangan bulat 0/1. Saya bertanya-tanya bagaimana model pohon benar-benar menangani ini. Ini memiliki bau yang tidak enak bagi saya.
Hukum Kode Ketiga: Jangan Membuat == Perbandingan Dengan Floats
(ok, kecuali dengan Math.NaN
)
Hmm, saya pikir kami melakukan ini!
Saya setuju kita harus. Saya pikir itu hanya bendera yang harus kami atur di impl.
@dsherry @freddyaboulton Sepertinya kami memiliki dukungan untuk itu melalui parameter drop
tetapi hanya mempertimbangkan input pengguna dan tidak digunakan oleh impl kami sehingga masalah ini hanya melacak pengaturan default untuk drop
untuk sesuatu selain Tidak Ada?
https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.OneHotEncoder.html
Kita bisa menggunakan first
atau if_binary
, tidak yakin apa panggilan yang tepat.
@ angela97lin Anda benar bahwa mengubah nilai default sudah cukup! Saya pikir first
adalah cara untuk pergi karena kita harus menghindari fitur collinear sempurna bahkan ketika jumlah kategori > 2. Bagaimana menurut Anda @rpeck ?
Sedang membaca ini sedikit dan menemukan tautan ini: https://inmachineswetrust.com/posts/drop-first-columns/
Takeaways utama:
Komentar pertama RE @rpeck : "Seperti bentuk kolinearitas fitur lainnya, ini mengacaukan banyak hal dalam interpretasi, karena efek dari satu kolom sumber asli dibagi di antara dua kolom OHE. Rollup SHAP baru Freddy mengatasi hal ini, jelas, tetapi hal-hal seperti Kepentingan Fitur dan plot Ketergantungan Sebagian masih akan bermasalah."
Ini masuk akal untuk kasus biner, tetapi dalam kasus di mana kami memiliki beberapa kategori, menjatuhkan satu col akan tetap memiliki masalah ini.
Mungkin kita seharusnya tidak melakukan ini secara default, tetapi harus memperbarui make_pipeline
untuk membuat OHE dengan first
sebagai parameter jika penaksirnya adalah regresi linier?
Sayangnya, saya tidak memiliki pemahaman yang kuat tentang matematika yang mendasari untuk membuat penilaian, jadi saya ingin mendengar pendapat Anda, @freddyaboulton @rpeck @dsherry
Pasca-diskusi dengan @freddyaboulton @rpeck @dsherry @chukarsten @jeremyliweishih
@ angela97lin terdengar baik perilaku default RE. Hal lain yang bagus untuk dimiliki: kemampuan untuk mengganti perilaku default itu melalui params komponen
@dsherry Jika saya mengerti dengan benar, karena kami memperbarui nilai default drop
(parameter), pengguna akan memiliki kemampuan untuk menimpa ini dengan mengatur parameter komponen secara manual?
Gali sekitar untuk melihat apa yang diperlukan untuk mengimplementasikan ini. Secara khusus, saya ingin tahu betapa sulitnya untuk selalu menghapus kelas minoritas dalam kasus biner.
Hasil dari penggalian tersebut adalah:
drop
(https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.OneHotEncoder.html). Namun, setelah mencobanya, diperlukan nilai indeks yang ditentukan untuk setiap kolom. Oleh karena itu, berikut ini, yang mencoba menghapus kategori yang ditentukan pada indeks 0 untuk kolom 0 dan tidak ada nilai lain untuk kesalahan kolom 1 dan 2:import pandas as pd
import numpy as np
from sklearn.preprocessing import OneHotEncoder
X = pd.DataFrame({'col_1': ["a", "b", "b", "a", "b"],
'col_2': ["a", "b", "a", "c", "b"],
'col_3': ["a", "a", "a", "a", "a"]})
indices_to_drop = np.array([0, None, None])
ohe = OneHotEncoder(drop=indices_to_drop)
ohe.fit(X)
ValueError Traceback (most recent call last)
<ipython-input-4-a099fa2fc4a7> in <module>
----> 1 ohe.fit(X)
~/Desktop/venv/lib/python3.7/site-packages/sklearn/preprocessing/_encoders.py in fit(self, X, y)
417 self._fit(X, handle_unknown=self.handle_unknown,
418 force_all_finite='allow-nan')
--> 419 self.drop_idx_ = self._compute_drop_idx()
420 return self
421
~/Desktop/venv/lib/python3.7/site-packages/sklearn/preprocessing/_encoders.py in _compute_drop_idx(self)
394 ["Category: {}, Feature: {}".format(c, v)
395 for c, v in missing_drops])))
--> 396 raise ValueError(msg)
397 return np.array(drop_indices, dtype=object)
398
ValueError: The following categories were supposed to be dropped, but were not found in the training data.
Category: 0, Feature: 0
Category: 1, Feature: None
Category: 2, Feature: None
Saya percaya ini juga setengah dari apa yang ditunjukkan oleh masalah ini: https://github.com/scikit-learn/scikit-learn/issues/16511
Alternatif yang dapat kita lakukan untuk mendukung ini adalah secara manual melacak kolom mana dan nilai apa yang ingin kita jatuhkan selama pemasangan. Berikan data ke scikit-learn. Kemudian, pangkas kolom yang kami simpan dan tentukan yang ingin kami jatuhkan. Namun, ini memerlukan beberapa penanganan logika untuk menentukan yang asli (fitur, nilai) dari nama kolom yang diubah. (Kami memiliki logika ini di get_feature_names
tetapi itu membantu kami menghubungkan nama kolom dengan asumsi tidak ada yang harus dijatuhkan ...)
Semua ini untuk mengatakan, mungkin hanya menggunakan default scikit-learn if_binary
sudah cukup untuk saat ini, dan kita dapat mengajukan masalah terpisah untuk selalu menggunakan kelas minoritas. Jujur juga mendukung pindah dari implementasi OHE scikit-learn mengingat betapa kami harus mengatasinya.
Sumber daya yang berguna:
Dokumen OHE: https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.OneHotEncoder.html
Kode dalam scikit-learn menyebabkan ketidakfleksibelan: https://github.com/scikit-learn/scikit-learn/blob/95119c13af77c76e150b753485c662b7c52a41a2/sklearn/preprocessing/_encoders.py#L338
Masalah terkait: https://github.com/scikit-learn/scikit-learn/issues/16511
Untuk menggunakan if_binary
: scikit-learn mensyaratkan bahwa handle_unknown
adalah error
. Ini tidak cocok dengan parameter top_n
, yang menghapus semuanya kecuali kategori N teratas karena data yang akan diubah tidak akan tahu apa yang harus dilakukan dengan kategori baru. Seperti yang dicatat Becca di https://github.com/alteryx/evalml/pull/830 , kita harus menyetel top_n
ke None agar parameter ini berfungsi.
Dengan pemikiran ini, mungkin yang terbaik adalah menggulung impl kita sendiri
Komentar yang paling membantu
Hukum Kode Ketiga: Jangan Membuat == Perbandingan Dengan Floats