Saat ini, dimungkinkan untuk menggunakan kerangka data pandas sebagai input untuk sebagian besar metode sklearn fit/predict/transform, tetapi Anda mendapatkan array numpy. Akan sangat menyenangkan jika bisa mengeluarkan data dalam format yang sama dengan yang Anda masukkan.
Ini tidak sepenuhnya mudah, karena jika Dataframe Anda berisi kolom yang bukan numerik, maka array numpy perantara akan menyebabkan sklearn gagal, karena mereka akan menjadi dtype=object
, alih-alih dtype=float
. Ini dapat diselesaikan dengan memiliki Transformator Dataframe->ndarray, yang memetakan data non-numerik ke data numerik (misalnya bilangan bulat yang mewakili kelas/kategori). sklearn-pandas sudah melakukan ini, meskipun saat ini tidak memiliki inverse_transform
, tetapi itu seharusnya tidak sulit untuk ditambahkan.
Saya merasa seperti transformasi seperti ini akan _sangat_ berguna untuk dimiliki di sklearn - ini adalah jenis hal yang akan berguna bagi siapa pun yang bekerja dengan kumpulan data dengan banyak tipe data. Apa yang diperlukan untuk memasukkan sesuatu seperti ini ke sklearn?
Scikit-learn dirancang untuk bekerja dengan format input yang sangat umum. Mungkin dunia di sekitar scikit-learn telah banyak berubah sejak membuat integrasi Panda menjadi lebih penting. Sebagian besar masih bisa dipasok oleh pembungkus pihak ketiga.
Tetapi terlepas dari pertanyaan yang lebih luas, saya pikir Anda harus mencoba memberikan contoh bagaimana keluaran ramah Panda dari penaksir standar akan berbeda dan membuat perbedaan pada kegunaan. Contoh yang dapat saya pikirkan:
Ya, dari atas kepalaku:
Jika ini semua dalam transformasi, maka itu tidak terlalu memengaruhi cara kerja sklearn secara default.
Saya tidak berpikir itu dapat diimplementasikan dengan baik sebagai transformator. Itu akan
satu atau lebih metaestimator atau mixin. Saya pikir mereka seharusnya pada awalnya
diimplementasikan secara eksternal dan ditunjukkan sebagai berguna
Pada 22 Oktober 2015 pukul 17:40, naught101 [email protected] menulis:
Ya, dari atas kepalaku:
- indeks bisa sangat berguna, misalnya untuk membuat jeda waktu
variabel (misalnya lag 1 hari, pada data harian dengan beberapa hari yang hilang)- sklearn regressor dapat digunakan secara transparan dengan data kategorikal
(lewati kerangka data campuran, ubah kolom kategoris dengan LabelBinarizer,
inverse_transform kembali).- sklearn-pandas sudah menyediakan antarmuka yang bagus yang memungkinkan Anda untuk
melewati kerangka data, dan hanya menggunakan sebagian data, dan secara sewenang-wenang
mengubah kolom individu.Jika ini semua dalam transformasi, maka itu tidak terlalu mempengaruhi seberapa sklearn
bekerja secara default.—
Balas email ini secara langsung atau lihat di GitHub
https://github.com/scikit-learn/scikit-learn/issues/5523#issuecomment -150123228
.
Membuat "pandas masuk" lebih baik adalah ide di balik trafo kolom PR #3886. Mungkin saya seharusnya melihat lebih dekat apa yang sudah dilakukan sklearn-panda. Saya tidak sepenuhnya yakin apa jalan terbaik ke depan yang ada.
Hal lain yang akan menyenangkan adalah mempertahankan nama kolom dalam transformasi/memilihnya saat melakukan pemilihan fitur. Saya tidak menemukan masalah di mana kita membahas ini sekarang. Mungkin @jnothman ingat. Saya sangat menyukainya, meskipun itu akan membutuhkan operasi besar dengan validasi input untuk mempertahankan nama kolom :-/
Terkait #4196
meskipun itu akan membutuhkan operasi besar dengan validasi input untuk
pertahankan nama kolom :-/
Tidak hanya validasi input: setiap transformasi harus menjelaskan apa itu
lakukan untuk kolom input.
Benar, tapi itu menurut saya akan menyenangkan ;)
Satu pertanyaan mungkin apakah kita menginginkan ini hanya di jalur pipa atau di mana-mana. Jika kita membatasinya pada pipeline, operasi validasi input akan lebih kecil. Tapi saya tidak yakin seberapa berguna itu.
Anda selalu dapat melakukan pipeline hanya dengan satu hal di dalamnya, bukan? Jadi kami _kind of_ menangani semua kasus (meskipun hacky dalam batas 1 objek) dengan membatasi hanya pipa pada awalnya ...
+1. Dimulai dengan pipa terdengar bagus, dan tutupi semua trafo di langkah berikutnya.
Saya juga memiliki impl dengan panda dan integrasi sklearn, yang dapat mengembalikan info kolom melalui inverse_transform
(peretasan kotor meskipun ...)
• indeks dapat benar-benar berguna, misalnya untuk membuat variabel tertinggal waktunya
(misalnya lag 1 hari, pada data harian dengan beberapa hari yang hilang)
Saya agak bodoh, tetapi tidak membicarakan sesuatu dalam sampel
arah sini, bukan arah fitur?
• sklearn regressor dapat digunakan secara transparan dengan data kategorikal (pass
kerangka data campuran, ubah kolom kategoris dengan LabelBinarizer, the
inverse_transform kembali).• sklearn-pandas sudah menyediakan antarmuka yang bagus yang memungkinkan Anda untuk lulus a
kerangka data, dan hanya menggunakan sebagian data, dan mengubah secara sewenang-wenang
kolom individu.
OK, tapi itu saja pada tingkat satu transformator yang mengambil Panda,
dan memberikan matriks data, bukan? Daripada mencoba
modifikasi pada semua objek scikit-learn (yang berisiko
usaha), pertama-tama kita dapat mengimplementasikan transformator ini (saya percaya bahwa
@amueller memikirkan ini).
arah sampel di sini, bukan arah fitur?
Ya.
OK, tapi itu semua pada tingkat satu transformator yang mengambil Panda, dan mengeluarkan matriks data, bukan?
Ya, itulah yang saya pikirkan untuk memulai. Saya akan lebih dari senang dengan pembungkus yang menangani X
dan y
sebagai kerangka data. Saya tidak melihat alasan yang jelas untuk mengacaukan internal sklearn.
OK, but that's all at the level of one transformer that takes Pandas in, and gives a data matrix out, isn't it?
Ya, itulah yang saya pikirkan untuk memulai. Saya akan lebih dari senang dengan
pembungkus yang menangani X dan y sebagai kerangka data. Saya tidak melihat alasan yang jelas
untuk sekrup dengan internal sklearn.
Kemudian kita berada di halaman yang sama. Saya pikir @amueller punya ide tentang
ini, dan kita mungkin melihat beberapa diskusi, dan mungkin kode segera.
Hal lain yang akan menyenangkan adalah mempertahankan nama kolom dalam transformasi/memilihnya saat melakukan pemilihan fitur. Saya tidak menemukan masalah di mana kita membahas ini sekarang.
Catatan: Saya bertanya-tanya apakah seseorang hanya ingin membungkus estimator terluar dalam ansambel untuk menyediakan fungsionalitas ini kepada pengguna. Saya pikir jawabannya adalah: tidak, orang ingin membungkus trafo atom juga, untuk memungkinkan trafo yang sadar kerangka data di dalam pipa (mengapa tidak?). Tanpa menerapkan ini sebagai mixin, saya pikir Anda akan mendapatkan masalah dengan awalan parameter yang tidak perlu atau masalah kloning (seperti pada #5080).
:+1:
Hanya ingin membuang solusi yang saya gunakan:
def check_output(X, ensure_index=None, ensure_columns=None):
"""
Joins X with ensure_index's index or ensure_columns's columns when avaialble
"""
if ensure_index is not None:
if ensure_columns is not None:
if type(ensure_index) is pd.DataFrame and type(ensure_columns) is pd.DataFrame:
X = pd.DataFrame(X, index=ensure_index.index, columns=ensure_columns.columns)
else:
if type(ensure_index) is pd.DataFrame:
X = pd.DataFrame(X, index=ensure_index.index)
return X
Saya kemudian membuat pembungkus di sekitar estimator sklearn yang memanggil fungsi ini pada output transformasi misalnya,
from sklearn.preprocessing import StandardScaler as _StandardScaler
class StandardScaler(_StandardScaler):
def transform(self, X):
Xt = super(StandardScaler, self).transform(X)
return check_output(Xt, ensure_index=X, ensure_columns=X)
Pengklasifikasi yang membutuhkan penggunaan indeks kerangka data input X dapat menggunakan indeksnya saja (berguna untuk deret waktu seperti yang ditunjukkan).
Pendekatan ini memiliki keuntungan karena sepenuhnya kompatibel dengan desain sklearn yang ada sambil juga menjaga kecepatan komputasi (operasi matematika dan pengindeksan pada kerangka data hingga 10x lebih lambat daripada array numpy, http://penandpants.com/2014/09/05 /performance-of-pandas-series-vs-numpy-arrays/). Sayangnya, banyak pekerjaan yang membosankan untuk ditambahkan ke setiap estimator yang dapat menggunakannya.
Mungkin hanya perlu membuat varian Pipeline dengan sihir ini...
Pada 15 Januari 2016 pukul 02:30, Dean Wyatte [email protected] menulis:
Hanya ingin membuang solusi yang saya gunakan:
def check_output(X, sure_index=Tidak ada, sure_columns=Tidak ada):
"""
Bergabung dengan X dengan indeks sure_index atau kolom sure_columns saat tersedia
"""
jika sure_index bukan Tidak Ada:
jika sure_columns bukan None:
jika type(ensure_index) adalah pd.DataFrame dan type(ensure_columns) adalah pd.DataFrame:
X = pd.DataFrame(X, indeks=ensure_index.index, kolom=ensure_columns.columns)
lain:
jika tipe(ensure_index) adalah pd.DataFrame:
X = pd.DataFrame(X, index=ensure_index.index)
kembali XSaya kemudian membuat pembungkus di sekitar penaksir sklearn yang memanggil fungsi ini
pada output transformasi misalnya,dari sklearn.preprocessing impor StandardScaler sebagai _StandardScaler
kelas MinMaxScaler(_MinMaxScaler):
def mengubah (diri, X):
Xt = super(MinMaxScaler, self).transform(X)
kembalikan check_output(Xt, sure_index=X, sure_columns=X)Pengklasifikasi yang membutuhkan penggunaan indeks kerangka data input X hanya dapat
gunakan indeksnya (berguna untuk deret waktu seperti yang ditunjukkan).Pendekatan ini memiliki keuntungan karena sepenuhnya kompatibel dengan
desain sklearn yang ada sambil juga menjaga kecepatan komputasi
(operasi matematika dan pengindeksan pada kerangka data hingga 10x lebih lambat dari numpy
array). Sayangnya, banyak pekerjaan yang membosankan untuk ditambahkan ke setiap penaksir
yang bisa memanfaatkannya.—
Balas email ini secara langsung atau lihat di GitHub
https://github.com/scikit-learn/scikit-learn/issues/5523#issuecomment -171674105
.
Atau hanya sesuatu yang membungkus pipa/estimator, bukan?
Saya tidak begitu mengerti mengapa Anda memanggil fungsi seperti itu "check_*" ketika itu melakukan lebih dari sekadar memeriksa ...
Pada 14 Januari 2016 10:45:44 CST, Joel Nothman [email protected] menulis:
Mungkin hanya perlu membuat varian Pipeline dengan sihir ini...
Pada 15 Januari 2016 pukul 02:30, Dean Wyatte [email protected]
menulis:Hanya ingin membuang solusi yang saya gunakan:
def check_output(X, sure_index=Tidak ada, sure_columns=Tidak ada):
"""
Bergabung dengan X dengan indeks sure_index atau kolom sure_columns
saat tersedia
"""
jika sure_index bukan Tidak Ada:
jika sure_columns bukan None:
jika tipe(ensure_index) adalah pd.DataFrame dan
type(ensure_columns) adalah pd.DataFrame:
X = pd.DataFrame(X, indeks=pastikan_index.index,
kolom=ensure_columns.columns)
lain:
jika tipe(ensure_index) adalah pd.DataFrame:
X = pd.DataFrame(X, index=ensure_index.index)
kembali XSaya kemudian membuat pembungkus di sekitar penaksir sklearn yang menyebut ini
fungsi
pada output transformasi misalnya,dari sklearn.preprocessing impor StandardScaler sebagai _StandardScaler
kelas MinMaxScaler(_MinMaxScaler):
def mengubah (diri, X):
Xt = super(MinMaxScaler, self).transform(X)
kembalikan check_output(Xt, sure_index=X, sure_columns=X)Pengklasifikasi yang membutuhkan penggunaan indeks kerangka data input X dapat
hanya
gunakan indeksnya (berguna untuk deret waktu seperti yang ditunjukkan).Pendekatan ini memiliki keuntungan karena sepenuhnya kompatibel dengan
desain sklearn yang ada sambil juga menjaga kecepatan
komputasi
(operasi matematika dan pengindeksan pada kerangka data hingga 10x lebih lambat dari
numpy
array). Sayangnya, banyak pekerjaan yang membosankan untuk ditambahkan ke masing-masing
penaksir
yang bisa memanfaatkannya.—
Balas email ini secara langsung atau lihat di GitHubhttps://github.com/scikit-learn/scikit-learn/issues/5523#issuecomment -171674105
.Balas email ini secara langsung atau lihat di GitHub:
https://github.com/scikit-learn/scikit-learn/issues/5523#issuecomment -171697542
Dikirim dari perangkat Android saya dengan K-9 Mail. Mohon maafkan singkatnya saya.
Saya tidak yakin apakah Pipeline adalah tempat yang tepat untuk memulai karena semua pewarisan nama kolom adalah khusus penaksir, misalnya, scaler harus mewarisi nama kolom dari kerangka data input sedangkan model seperti PCA, tidak. Penaksir pemilihan fitur harus mewarisi nama kolom tertentu, tetapi itu adalah masalah lain, mungkin lebih terkait dengan #2007.
Apakah selalu n_rows dari semua array dipertahankan selama transformasi? Jika demikian, hanya mewarisi indeks input (jika ada) tampaknya aman, tetapi saya tidak yakin bahwa mendapatkan kerangka data dengan nama kolom default (misalnya, [0, 1, 2, 3, ...]) adalah lebih baik daripada perilaku saat ini dari perspektif pengguna akhir, tetapi jika pembungkus eksplisit/meta-estimator digunakan, maka setidaknya pengguna akan tahu apa yang diharapkan.
Juga, setuju bahwa check_* adalah nama yang buruk -- Saya melakukan sedikit lebih banyak validasi dalam fungsi saya, dan baru saja menghapus logika kerangka data untuk diposting di sini.
Saya pikir pipeline akan menjadi tempat untuk memulai, meskipun kita perlu menambahkan sesuatu ke semua estimator yang memetakan nama kolom dengan tepat.
transformer harus menampilkan kolom dengan nama yang tepat @ naught101
meskipun itu akan membutuhkan operasi besar dengan validasi input untuk mempertahankan nama kolom :-/ @amueller
Tidak hanya validasi input: setiap transformasi harus menjelaskan apa yang dilakukannya pada kolom input. @GaelVaroquaux
Adakah yang pernah memikirkan mekanisme bagaimana menyebarkan nama, dari transformator ke transformator, dan mungkin cara melacak asalnya? Di mana orang akan menyimpan ini?
Seorang teman saya, @cbrummitt , memiliki masalah yang sama, di mana setiap kolom matriks desainnya adalah bentuk fungsional (misalnya x^2, x^3, x_1^3x_2^2, direpresentasikan sebagai ekspresi sympy), dan dia memiliki transformer yang bertindak mirip dengan Fitur Polinomial, yang dapat mengambil bentuk fungsional dan menghasilkan lebih banyak fitur berdasarkan itu. Tapi dia menggunakan sympy untuk mengambil ekspresi lama dan menghasilkan yang baru, dan menyimpan ekspresi sebagai label string tidak memotongnya, dan menjadi rumit saat Anda melapisi transformasi fungsi. Dia bisa melakukan semua ini di luar jalur pipa, tetapi kemudian dia tidak mendapatkan manfaat dari GridSearch, dll.
Saya kira versi yang lebih umum dari pertanyaan kami adalah, bagaimana Anda memiliki beberapa informasi yang akan diteruskan dari transformator ke transformator yang BUKAN data itu sendiri? Saya tidak dapat menemukan cara yang bagus tanpa memiliki status pipa-global atau memiliki setiap transformator / penaksir tahu tentang yang sebelumnya, atau meminta setiap langkah mengembalikan banyak hal, atau sesuatu.
Kami kemudian juga datang dengan ide untuk memodifikasi pipa untuk melacak ini, Anda harus mengubah _fit() dan _transform() dan mungkin beberapa hal lainnya. Itu sepertinya pilihan terbaik kami.
Ini kedengarannya gila tapi bagaimana rasanya kita benar-benar ingin matriks data kita menjadi ekspresi sympy , dan setiap transformasi menghasilkan ekspresi baru? Ini menjijikkan, check_array() menghentikannya agar tidak terjadi, dan itu akan membuat langkah-langkah lain menjadi marah.
lihat #6425 untuk ide saat ini.
Yang Anda inginkan hanyalah pemetaan, untuk setiap transformator (termasuk saluran pipa
transformer), dari nama fitur input hingga nama fitur output (atau beberapa
representasi terstruktur dari transformasi, yang saya duga lebih
rekayasa daripada yang akan kita dapatkan). Itulah yang diberikan #6425.
Pada 8 Oktober 2016 pukul 03:42, Andreas Mueller [email protected]
menulis:
lihat #6425 https://github.com/scikit-learn/scikit-learn/issues/6425 untuk
ide saat ini.—
Anda menerima ini karena Anda disebutkan.
Balas email ini secara langsung, lihat di GitHub
https://github.com/scikit-learn/scikit-learn/issues/5523#issuecomment -252301608,
atau matikan utasnya
https://github.com/notifications/unsubscribe-auth/AAEz65fBsMwqmkDq3DEjMSUC-W-nfn9zks5qxnZxgaJpZM4GThGc
.
Kami akan memeriksanya, terima kasih!
Dapatkah seseorang memberikan pembaruan umum tentang keadaan dunia tentang masalah ini?
Akankah panda DataFrame
support selalu menjadi hal yang YMMV?
Panduan tentang apa yang dianggap/tidak aman untuk digunakan dengan panda DataFrame
alih-alih hanya ndarray
akan sangat membantu. Mungkin sesuatu di sepanjang baris berikut (MADE UP CONTOH TABEL):
module/category|dapat dengan aman menggunakan pandas DataFrame
--|--
sklearn.pipeline|AMAN
sklearn.feature_selection|AMAN
regressor|YMMV
sklearn.feature_extraction|TIDAK AMAN, tidak ada rencana untuk diterapkan
dll|...
Saat ini, saya tidak yakin dengan pendekatan selain "coba saja dan lihat apakah itu mengeluarkan pengecualian".
Kami telah menguji beberapa contoh kode tangan yang tampaknya berfungsi dengan baik menerima pandas DataFrame, tetapi tidak dapat membantu berpikir ini pasti akan berhenti bekerja dengan benar ketika kami memutuskan kami perlu membuat pertukaran komponen pipa yang tampaknya sepele... pada titik mana semuanya jatuh seperti rumah kartu dalam jejak tumpukan samar.
Proses pemikiran awal saya adalah membuat objek pipa pengganti yang dapat menggunakan pandas DataFrame
yang dibuat secara otomatis pembungkus untuk komponen scikit-learn standar untuk mengubah input/output objek DataFrame
menjadi numpy ndarray
sesuai kebutuhan. Dengan begitu saya dapat menulis Selectors/Transformers kustom saya sendiri sehingga saya dapat menggunakan panda DataFrame
primitif, tetapi itu tampaknya agak berat. Apalagi, jika kita berada di puncak dukungan "resmi" untuk mereka.
Saya telah mengikuti beberapa PR yang berbeda, tetapi sulit untuk memahami mana yang ditinggalkan dan/atau yang mencerminkan pemikiran saat ini:
Contoh:
Ini sangat bergantung pada apa yang Anda maksud dengan "Dapat dengan aman mengkonsumsi pandas DataFrame". Jika yang Anda maksud adalah DataFrame yang hanya berisi angka float, kami menjamin bahwa semuanya akan berfungsi. Jika bahkan ada satu string di mana pun, tidak ada yang akan berfungsi.
Saya pikir estimator scikit-learn apa pun yang mengembalikan kerangka data untuk operasi non-sepele (atau mungkin bahkan sepele) adalah sesuatu yang mungkin tidak akan pernah terjadi (meskipun itu ingin).
Fungsi #6425 saat ini diterapkan (untuk beberapa transformator dan
dapat diperluas ke orang lain) melalui singledispatch di
https://codecov.io/gh/TeamHG-Memex/eli5 untuk apa nilainya.
Pada 21 Juni 2017 pukul 13:25, Andreas Mueller [email protected] menulis:
9012 https://github.com/scikit-learn/scikit-learn/pull/9012 akan
terjadi dan akan menjadi stabil, PR adalah iterasi pertama.
6425 https://github.com/scikit-learn/scikit-learn/issues/6425 adalah
mungkin terjadi, meskipun tidak sepenuhnya terkait dengan panda.
3886 https://github.com/scikit-learn/scikit-learn/pull/3886 memang
digantikan oleh #9012
https://github.com/scikit-learn/scikit-learn/pull/9012—
Anda menerima ini karena Anda disebutkan.
Balas email ini secara langsung, lihat di GitHub
https://github.com/scikit-learn/scikit-learn/issues/5523#issuecomment-309952467 ,
atau matikan utasnya
https://github.com/notifications/unsubscribe-auth/AAEz61lgGBW1AoukPm_87elBjF2NGOUwks5sGI0-gaJpZM4GThGc
.
Oh dan ketika saya mengatakan " Jika yang Anda maksud adalah DataFrame yang hanya berisi angka float, kami menjamin bahwa semuanya akan berfungsi." Maksud saya dengan pengindeksan kolom berbasis lokasi. kolom training dan test set diasumsikan sama berdasarkan posisinya.
Ini sangat bergantung pada apa yang Anda maksud dengan "Dapat dengan aman mengkonsumsi pandas DataFrame". Jika yang Anda maksud adalah DataFrame yang hanya berisi angka float, kami menjamin bahwa semuanya akan berfungsi. Jika bahkan ada satu string di mana pun, tidak ada yang akan berfungsi.
Saya pikir itu cukup baik bagi kami.
Kami menggunakan pipa komponen khusus (pembungkus tipis di sekitar perkakas yang ada yang tidak ramah pipa) untuk mengubah tipe campuran (string, pelampung, dan int) menjadi pelampung melalui penyandian/penskalaan sebelum mencapai komponen scikit-learn seperti pemilih atau model.
Semua transformer saya mengembalikan DataFrame
s ketika diberikan DataFrame
s.
Ketika saya memasukkan 300-kolom DataFrame
ke dalam Pipeline
dan menerima 500-kolom ndarray
, saya tidak dapat belajar banyak darinya secara efektif, dengan, misalnya, feature_selection
, karena saya tidak memiliki nama kolom lagi. Jika, katakanlah, mutual_info_classif
memberi tahu saya bahwa hanya kolom 30 dan 75 yang penting, saya tidak tahu bagaimana menyederhanakan Pipeline
untuk produksi.
Jadi, sangat penting bagi kasus penggunaan saya untuk menyimpan data saya dalam DataFrame
.
Terima kasih.
@sam-s Saya setuju sekali. Dalam jangka "pendek", ini akan ditangani oleh https://github.com/scikit-learn/scikit-learn/pull/13307 dan https://github.com/scikit-learn/enhancement_proposals/pull/18
Anda tidak akan mendapatkan kerangka data panda, tetapi Anda akan mendapatkan nama kolom untuk membuatnya.
Bisakah Anda memberikan contoh yang lebih konkrit? Karena jika semua transformer mengembalikan DataFrames, semuanya akan berfungsi (atau dibuat bekerja lebih mudah daripada proposal di atas).
Sedikit pembaruan melalui https://github.com/pandas-dev/pandas/issues/27211
yang meredam harapanku. Sepertinya kami tidak dapat mempercayai adanya perjalanan pulang pergi tanpa salinan, sehingga membungkus dan membuka bungkusan ke dalam panda akan menghasilkan biaya yang besar.
Sedikit pembaruan melalui pandas-dev/pandas#27211 yang meredam harapan saya. Sepertinya kami tidak dapat mempercayai adanya perjalanan pulang pergi tanpa salinan, sehingga membungkus dan membuka bungkusan ke dalam panda akan menghasilkan biaya yang besar.
ya, tapi saya kira begitu kita membahas fitur dan contoh alat peraga (nama baris dan "indeks" menjadi contoh alat peraga), sebagian besar kasus penggunaan terkait yang agak membutuhkan panda sekarang akan dibahas, bukan?
@adrinjalali Saya tidak yakin apa yang Anda maksud dengan "kasus penggunaan yang paling terkait dengan panda yang agak membutuhkan". Saya melihat masalah ini bukan terutama sebagai pendukung panda untuk mengimplementasikan fitur dalam scikit-learn, tetapi agar scikit-learn terintegrasi lebih mudah dalam alur kerja berbasis panda.
Hanya ingin tahu, apakah ada jangka waktu di mana kompatibilitas Panda yang ditingkatkan diharapkan akan mendarat? Saya secara khusus tertarik pada Pandas in -> Pandas out seharga StandardScaler
.
Saya memiliki kasus penggunaan di mana saya membutuhkan kerangka data pandas yang diawetkan melalui setiap langkah dalam Pipeline
. Misalnya pipeline dengan 1) langkah pemilihan fitur menyaring fitur berdasarkan data, 2) langkah transformasi data, 3) langkah pemilihan fitur lainnya untuk memfilter nama kolom fitur tertentu atau indeks asli, 4) standarisasi, 5) klasifikasi.
Langkah 3) Saya yakin saat ini tidak mungkin di sklearn, bahkan dengan input array numpy, karena indeks fitur asli tidak ada artinya ketika data mencapai 3) karena pada 1) ada langkah pemilihan fitur. Jika kerangka data panda dipertahankan dalam pipa, itu akan berfungsi karena saya bisa memfilter berdasarkan nama kolom di 3).
Apakah saya salah dalam berpikir bahwa saat ini tidak ada cara untuk melakukan ini bahkan dengan input array numpy?
Anda benar bahwa itu tidak didukung, dan mendukungnya bukanlah hal yang sepele. Terkait dengan kasus penggunaan Anda, kami sedang berupaya meneruskan nama fitur di sepanjang alur (seperti yang Anda lihat di PR dan proposal tertaut di atas). Mudah-mudahan itu akan membantu kasus Anda setelah selesai. Saya tidak yakin apakah itu membantu, tetapi Anda juga dapat melihat https://github.com/scikit-learn-contrib/sklearn-pandas
Anda benar bahwa itu tidak didukung, dan mendukungnya bukanlah hal yang sepele. Terkait dengan kasus penggunaan Anda, kami sedang berupaya meneruskan nama fitur di sepanjang alur (seperti yang Anda lihat di PR dan proposal tertaut di atas). Mudah-mudahan itu akan membantu kasus Anda setelah selesai.
Terima kasih atas konfirmasinya, ya, dapat menyebarkan nama fitur (atau properti fitur lainnya) agar sesuai dengan metode dan memotongnya dengan benar selama setiap langkah pemilihan fitur akan baik-baik saja untuk kasus penggunaan ini.
Saya tidak yakin apakah itu membantu, tetapi Anda juga dapat melihat https://github.com/scikit-learn-contrib/sklearn-pandas
Sebelumnya saya membaca dokumen mereka dan mungkin saya tidak melihatnya tetapi sebagian besar (atau semua) fitur mereka sudah usang sekarang di scikit-learn 0.21 dengan sklearn.compose.ColumnTransformer
? Juga sepertinya mereka tidak mendukung panda, sepertinya array numpy setelah transformasi.
(Saya ingin tahu apakah mendukung Panda dalam pemilihan fitur akan rusak
banyak...)
Hanya memeriksa kode secara singkat, ada berbagai jenis pemeriksaan yang terjadi secara sewenang-wenang di banyak tempat, misalnya menggunakan https://github.com/scikit-learn/scikit-learn/blob/939fa3cccefe708db7a81c5248db32a1d600bf8d/sklearn/utils/validation.py# L619
Ditambah banyak operasi menggunakan pengindeksan dengan cara numpy yang tidak akan diterima oleh kerangka data panda.
Menjaga panda masuk/keluar akan menjadi suatu keharusan untuk IMO ilmu data sehari-hari, tetapi scikit-learn tampaknya dirancang dengan cara yang akan membuatnya sulit untuk diimplementasikan.
Menjaga panda masuk/keluar akan menjadi keharusan bagi IMO ilmu data sehari-hari, tapi
scikit-learn tampaknya dirancang sedemikian rupa sehingga sulit untuk menjadi
dilaksanakan.
Numerik yang baik sulit diterapkan pada kerangka data panda. Mereka hanya
tidak dimaksudkan untuk itu, khususnya untuk operasi multivariat (numerik
operasi melintasi kolom).
Pembelajaran mesin sebagian besar adalah numerik mutlivariat.
Numerik yang baik sulit diterapkan pada kerangka data panda. Mereka tidak dimaksudkan untuk itu, khususnya untuk operasi multivarian (operasi numerik di seluruh kolom). Pembelajaran mesin sebagian besar adalah numerik mutlivariat.
Keputusan itu harus diserahkan kepada pengguna? Dalam pengalaman saya menggunakan scikit-learn secara ekstensif selama dua tahun terakhir, saya pikir dua fungsi inti dan penting yang hilang dan harus dimiliki untuk banyak kasus penggunaan ML adalah dukungan untuk meneruskan sampel dan metadata fitur. Dukungan kerangka data panda penuh adalah cara alami dan elegan untuk menangani beberapa hal ini.
Fungsionalitas inti semacam ini sangat penting untuk menjaga basis pengguna dan mendatangkan pengguna baru. Kalau tidak, saya melihat perpustakaan seperti misalnya mlr3 akhirnya matang dan menarik pengguna menjauh dari sklearn karena saya tahu mereka (atau akan) sepenuhnya mendukung bingkai data dan metadata.
Keputusan itu harus diserahkan kepada pengguna?
Nah, pengguna tidak mengimplementasikan algoritma.
Kalau tidak, saya melihat perpustakaan seperti misalnya mlr3 akhirnya jatuh tempo dan
menarik pengguna menjauh dari sklearn karena saya tahu mereka melakukannya (atau akan)
sepenuhnya mendukung bingkai data dan metadata.
mlr3 ada di R, kerangka datanya sangat berbeda dari kerangka data pandas.
Mungkin ini membuatnya lebih mudah untuk diterapkan.
Saya setuju bahwa dukungan yang lebih baik untuk nama fitur dan data heterogen
jenis adalah penting. Kami sedang berupaya menemukan solusi teknis yang baik
yang tidak menyebabkan hilangnya kinerja dan kode yang terlalu rumit.
Keputusan itu harus diserahkan kepada pengguna?
Nah, pengguna tidak mengimplementasikan algoritma.
Kalau tidak, saya melihat perpustakaan seperti misalnya mlr3 akhirnya matang dan menarik pengguna menjauh dari sklearn karena saya tahu mereka (atau akan) sepenuhnya mendukung bingkai data dan metadata.
mlr3 ada di R, kerangka datanya sangat berbeda dari kerangka data pandas. Mungkin ini membuatnya lebih mudah untuk diterapkan. Saya setuju bahwa dukungan yang lebih baik untuk nama fitur dan tipe data heterogen adalah penting. Kami sedang berupaya menemukan solusi teknis yang baik yang tidak menyebabkan hilangnya kinerja dan kode yang terlalu rumit.
Saya pikir pendekatan Anda untuk tetap menggunakan array numpy dan setidaknya mendukung nama fitur yang lewat atau bahkan beberapa metadata fitur yang lebih baik akan berfungsi untuk banyak kasus penggunaan. Untuk melewatkan metadata sampel pelatihan, Anda sudah mendukungnya di **fit_params
dan saya tahu ada upaya untuk meningkatkan desain. Tetapi saya menyebutkan di https://github.com/scikit-learn/enhancement_proposals/pull/16 bahwa ada kasus penggunaan di mana Anda juga memerlukan metadata sampel uji yang diteruskan ke metode transform
dan ini saat ini tidak didukung .
mlr3 ada di R, kerangka datanya sangat berbeda dari kerangka data pandas.
Ilmuwan komputasi dalam penelitian ilmu kehidupan biasanya sangat nyaman dengan python dan R dan menggunakan keduanya bersama-sama (termasuk saya sendiri). Saya cukup yakin persentase yang signifikan dari basis pengguna scikit-learn adalah peneliti ilmu kehidupan.
Saat ini perpustakaan ML matang yang tersedia di R IMHO bahkan tidak mendekati scikit-learn dalam hal menyediakan API yang dirancang dengan baik dan membuat bagian utilitarian ML sangat mudah (pipa, pencarian hyperparameter, penilaian, dll) sedangkan di R dengan perpustakaan ini Anda harus mengkodekannya sendiri. Tapi mlr3 saya lihat sebagai kompetisi besar masa depan untuk scikit-belajar karena mereka mendesainnya dari bawah ke atas dengan cara yang benar.
Numerik yang baik sulit diterapkan pada kerangka data panda. Mereka hanya
tidak dimaksudkan untuk itu, khususnya untuk operasi multivariat (numerik
operasi melintasi kolom).
Mungkin saya kehilangan sesuatu, tetapi apakah mungkin untuk membuka DataFrame (menggunakan df.values
), melakukan perhitungan dan kemudian membungkus kembali ke DataFrame baru?
Pada dasarnya itulah yang saya lakukan secara manual di antara langkah-langkah, dan satu-satunya hal yang mencegah penggunaan Pipeline
.
Mungkin saya melewatkan sesuatu, tetapi tidakkah mungkin untuk membuka bungkusnya?
DataFrame (menggunakan df.values), lakukan perhitungan dan kemudian bungkus kembali ke yang baru
bingkai data?
Secara umum tidak: itu mungkin tidak berfungsi (kolom heterogen), dan itu akan
menyebabkan banyak salinan memori.
Secara umum tidak: mungkin tidak berfungsi (kolom heterogen)
Saya pikir Transformer Kolom dan semacamnya dapat menanganinya secara individual.
itu akan menyebabkan banyak salinan memori.
Saya mengerti bahwa ada pilihan desain & implementasi yang sulit untuk dibuat, dan itu adalah argumen yang masuk akal.
Namun, saya tidak mengerti mengapa Anda berpendapat bahwa itu bukan ide yang baik untuk meningkatkan cara sklearn mendukung data meta kolom.
Mengizinkan misalnya untuk mencerna df dengan fitur, menambahkan kolom berkat prediktor, melakukan lebih banyak manipulasi data, melakukan prediksi lain, semua itu dalam Pipeline, adalah sesuatu yang akan berguna karena akan (misalnya) memungkinkan pengoptimalan parameter hiper dengan cara yang jauh lebih terintegrasi dan elegan.
Melakukannya dengan atau tanpa panda hanyalah saran karena ini adalah cara paling umum, mudah dan populer untuk memanipulasi data, dan saya tidak melihat manfaat apa pun untuk menulis ulang lebih dari apa yang mereka lakukan.
Terserah pengguna untuk memutuskan untuk tidak menggunakan alur kerja ini saat mengoptimalkan kinerja.
Menyerahkan semuanya kepada pengguna untuk memutuskan membutuhkan penjelasan yang jelas tentang
pilihan kepada pengguna. Sebagian besar pengguna tidak membaca dokumentasi yang akan
menjelaskan pilihan seperti itu. Banyak yang akan mencoba apa yang menurut mereka berhasil, dan kemudian
menyerah ketika mereka merasa lambat, tidak menyadari bahwa itu adalah pilihan mereka
daraframe yang membuatnya begitu.
Jadi kita perlu melangkah dengan hati-hati di sini. Tapi kita harus terus memecahkannya
ini sebagai prioritas tinggi.
Saya pikir solusi terbaik adalah mendukung pandas dataframe masuk dan keluar untuk sampel dan properti fitur dan meneruskan dan mengirisnya dengan benar ke dalam train dan test fit/transform. Itu akan menyelesaikan sebagian besar kasus penggunaan sambil menjaga kecepatan matriks data X sebagai array numpy.
Satu poin penting yang hilang dari argumen ini adalah bahwa panda bergerak menuju representasi kolom dari data, dengan cara np.array(pd.DataFrame(numpy_data))
akan memiliki dua salinan memori _dijamin_. Itu sebabnya tidak semudah hanya menyimpan dataframe dan menggunakan values
kapan pun kita membutuhkan kecepatan.
Satu poin penting yang hilang dari argumen ini adalah bahwa panda bergerak menuju representasi kolom dari data, dengan cara
np.array(pd.DataFrame(numpy_data))
akan memiliki dua salinan memori _dijamin_. Itu sebabnya tidak semudah hanya menyimpan dataframe dan menggunakanvalues
kapan pun kita membutuhkan kecepatan.
Saya harap saya jelas di posting saya sebelumnya. Saya percaya scikit-learn saat ini tidak perlu mendukung kerangka data panda untuk data X, simpan sebagai array numpy yang cepat. Tetapi apa yang akan memecahkan banyak kasus penggunaan adalah dukungan penuh melalui kerangka kerja untuk kerangka data pandas untuk metadata, yaitu properti sampel dan properti fitur. Ini seharusnya tidak menjadi beban kinerja bahkan untuk salinan memori karena kedua struktur data ini akan lebih kecil dibandingkan dengan X dan benar-benar hanya subsetting yang akan dilakukan pada ini.
Ya, perubahan itu memang membantu dalam banyak kasus penggunaan, dan kami sedang mengerjakannya. Tetapi masalah ini lebih dari itu: https://github.com/scikit-learn/scikit-learn/issues/5523#issuecomment -508807755
@hermidalc apakah Anda menyarankan agar kami membiarkan X
menjadi array numpy, dan menetapkan data meta di objek kerangka data lain?
@hermidalc apakah Anda menyarankan agar kami membiarkan
X
menjadi array numpy, dan menetapkan data meta di objek kerangka data lain?
Ya, dukungan penuh untuk properti sampel dan properti fitur sebagai kerangka data panda. Diskusi sudah terjadi pada contoh properti dan nama fitur di PR dan masalah lain, misalnya di sini #9566 dan #14315
Saya telah membaca tentang masalah ini dan sepertinya ada dua pemblokir utama di sini:
Sudahkah Anda mempertimbangkan untuk menambahkan dukungan untuk xarrays? Mereka tidak memiliki keterbatasan panda.
X = np.arange(10).reshape(5, 2)
assert np.asarray(xr.DataArray(X)) is X
assert np.asarray(xr.Dataset({"data": (("samples", "features"), X)}).data).base is X.base
Ada paket bernama sklearn-xarray
: https://phausamann.github.io/sklearn-xarray/content/wrappers.html yang membungkus estimator scikit untuk menangani xarrays sebagai input dan output tetapi tampaknya tidak terawat bertahun-tahun. Namun, saya bertanya-tanya apakah pembungkus adalah cara untuk pergi ke sini.
xarray secara aktif sedang dipertimbangkan. Itu sedang diprototipe dan dikerjakan di sini: https://github.com/scikit-learn/scikit-learn/pull/16772 Ada buku catatan penggunaan tentang seperti apa tampilan API di PR.
(Saya akan kembali ke sana setelah kita selesai dengan rilis 0.23)
Saya juga sangat tertarik dengan fitur ini.
Itu akan memecahkan masalah yang tak terbatas. Saat ini adalah solusi yang saya gunakan.
Saya menulis pembungkus di sekitar modul sklearn.preprocessing
, yang saya sebut sklearn_wrapper
Jadi alih-alih mengimpor dari sklearn.preprocessing
saya mengimpor dari sklearn_wrapper
.
Sebagai contoh:
# this
from sklearn.preprocessing import StandardScaler
# becomes
from sklearn_wrapper import StandardScaler
Di bawah implementasi modul ini. Cobalah dan beri tahu saya pendapat kalian
from functools import wraps
from itertools import chain
import pandas as pd
from sklearn import preprocessing, compose, feature_selection, decomposition
from sklearn.compose._column_transformer import _get_transformer_list
modules = (preprocessing, feature_selection, decomposition)
def base_wrapper(Parent):
class Wrapper(Parent):
def transform(self, X, **kwargs):
result = super().transform(X, **kwargs)
check = self.check_out(X, result)
return check if check is not None else result
def fit_transform(self, X, y=None, **kwargs):
result = super().fit_transform(X, y, **kwargs)
check = self.check_out(X, result)
return check if check is not None else result
def check_out(self, X, result):
if isinstance(X, pd.DataFrame):
result = pd.DataFrame(result, index=X.index, columns=X.columns)
result = result.astype(X.dtypes.to_dict())
return result
def __repr__(self):
name = Parent.__name__
tmp = super().__repr__().split('(')[1]
return f'{name}({tmp}'
Wrapper.__name__ = Parent.__name__
Wrapper.__qualname__ = Parent.__name__
return Wrapper
def base_pca_wrapper(Parent):
Parent = base_wrapper(Parent)
class Wrapper(Parent):
@wraps(Parent)
def __init__(self, *args, **kwargs):
self._prefix_ = kwargs.pop('prefix', 'PCA')
super().__init__(*args, **kwargs)
def check_out(self, X, result):
if isinstance(X, pd.DataFrame):
columns = [f'{self._prefix_}_{i}' for i in range(1, (self.n_components or X.shape[1]) + 1)]
result = pd.DataFrame(result, index=X.index, columns=columns)
return result
return Wrapper
class ColumnTransformer(base_wrapper(compose.ColumnTransformer)):
def check_out(self, X, result):
if isinstance(X, pd.DataFrame):
return pd.DataFrame(result, index=X.index, columns=self._columns[0]) if self._remainder[1] == 'drop' \
else pd.DataFrame(result, index=X.index, columns=X.columns). \
astype(self.dtypes.iloc[self._remainder[-1]].to_dict())
class SelectKBest(base_wrapper(feature_selection.SelectKBest)):
def check_out(self, X, result):
if isinstance(X, pd.DataFrame):
return pd.DataFrame(result, index=X.index, columns=X.columns[self.get_support()]). \
astype(X.dtypes[self.get_support()].to_dict())
def make_column_transformer(*transformers, **kwargs):
n_jobs = kwargs.pop('n_jobs', None)
remainder = kwargs.pop('remainder', 'drop')
sparse_threshold = kwargs.pop('sparse_threshold', 0.3)
verbose = kwargs.pop('verbose', False)
if kwargs:
raise TypeError('Unknown keyword arguments: "{}"'
.format(list(kwargs.keys())[0]))
transformer_list = _get_transformer_list(transformers)
return ColumnTransformer(transformer_list, n_jobs=n_jobs,
remainder=remainder,
sparse_threshold=sparse_threshold,
verbose=verbose)
def __getattr__(name):
if name not in __all__:
return
for module in modules:
Parent = getattr(module, name, None)
if Parent is not None:
break
if Parent is None:
return
if module is decomposition:
Wrapper = base_pca_wrapper(Parent)
else:
Wrapper = base_wrapper(Parent)
return Wrapper
__all__ = [*[c for c in preprocessing.__all__ if c[0].istitle()],
*[c for c in decomposition.__all__ if c[0].istitle()],
'SelectKBest']
def __dir__():
tmp = dir()
tmp.extend(__all__)
return tmp
https://github.com/koaning/scikit-lego/issues/304 memberikan solusi lain dengan Hot-fixing di sklearn.pipeline.FeatureUnion
Komentar yang paling membantu
Semua transformer saya mengembalikan
DataFrame
s ketika diberikanDataFrame
s.Ketika saya memasukkan 300-kolom
DataFrame
ke dalamPipeline
dan menerima 500-kolomndarray
, saya tidak dapat belajar banyak darinya secara efektif, dengan, misalnya,feature_selection
, karena saya tidak memiliki nama kolom lagi. Jika, katakanlah,mutual_info_classif
memberi tahu saya bahwa hanya kolom 30 dan 75 yang penting, saya tidak tahu bagaimana menyederhanakanPipeline
untuk produksi.Jadi, sangat penting bagi kasus penggunaan saya untuk menyimpan data saya dalam
DataFrame
.Terima kasih.