Scikit-learn: Panda masuk, Panda keluar?

Dibuat pada 22 Okt 2015  ·  59Komentar  ·  Sumber: scikit-learn/scikit-learn

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?

Komentar yang paling membantu

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.

Semua 59 komentar

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:

  • semua metode dapat menyalin indeks dari input
  • transformer harus menampilkan kolom dengan nama yang tepat
  • multiclass predict_proba dapat melabeli kolom dengan nama kelas

Ya, dari atas kepalaku:

  • indeks dapat sangat berguna, misalnya untuk membuat variabel tertinggal waktunya (misalnya kelambatan 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 kategorikal dengan LabelBinarizer, inverse_transform kembali).
  • sklearn-pandas sudah menyediakan antarmuka yang bagus yang memungkinkan Anda melewatkan kerangka data, dan hanya menggunakan subset data, dan mengubah kolom individual secara sewenang-wenang.

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 ...)

http://pandas-ml.readthedocs.org/en/latest/sklearn.html

• 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.

5172

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 X

Saya 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 X

Saya 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 GitHub

https://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:

6425 (direferensikan Oktober 2016 di atas di utas ini)

9012 (jelas tumpang tindih dengan sklearn-panda, tetapi dijelaskan sebagai eksperimental?)

3886 (digantikan oleh #9012?)

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).

9012 akan terjadi dan akan menjadi stabil, PR adalah iterasi pertama (atau iterasi ke-10, jika Anda menghitung yang tidak digabungkan;)

6425 kemungkinan besar akan terjadi, meskipun tidak sepenuhnya terkait dengan panda.

3886 memang digantikan oleh #9012

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 menggunakan values 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:

  1. https://github.com/pandas-dev/pandas/issues/27211
  2. Panda itu tidak menangani array ND.

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

Apakah halaman ini membantu?
0 / 5 - 0 peringkat